| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.skins.halo |
| { |
| |
| import flash.display.GradientType; |
| import flash.display.Graphics; |
| import mx.core.IContainer; |
| import mx.core.EdgeMetrics; |
| import mx.core.IUIComponent; |
| import mx.core.mx_internal; |
| import mx.graphics.RectangularDropShadow; |
| import mx.skins.RectangularBorder; |
| import mx.styles.IStyleClient; |
| import mx.styles.StyleManager; |
| import mx.utils.ColorUtil; |
| import mx.graphics.GradientEntry; |
| |
| use namespace mx_internal; |
| |
| /** |
| * Defines the appearance of the default border for the Halo theme. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class HaloBorder extends RectangularBorder |
| { |
| include "../../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * A look up table for the offsets. |
| */ |
| private static var BORDER_WIDTHS:Object = |
| { |
| none: 0, |
| solid: 1, |
| inset: 2, |
| outset: 2, |
| alert: 3, |
| dropdown: 2, |
| menuBorder: 1, |
| comboNonEdit: 2 |
| }; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function HaloBorder() |
| { |
| super(); |
| |
| // 'default' is a keyword; setting it this way avoids a compiler error |
| BORDER_WIDTHS["default"] = 3; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Fields |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * A reference to the object used to cast a drop shadow. |
| * See the drawDropShadow() method for details. |
| */ |
| private var dropShadow:RectangularDropShadow; |
| |
| mx_internal var backgroundColor:Object; |
| mx_internal var backgroundAlphaName:String; |
| mx_internal var backgroundHole:Object; |
| mx_internal var bRoundedCorners:Boolean; |
| mx_internal var radius:Number; |
| mx_internal var radiusObj:Object; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // borderMetrics |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Internal object that contains the thickness of each edge |
| * of the border |
| */ |
| protected var _borderMetrics:EdgeMetrics; |
| |
| /** |
| * @private |
| * Return the thickness of the border edges. |
| * |
| * @return Object top, bottom, left, right thickness in pixels |
| */ |
| override public function get borderMetrics():EdgeMetrics |
| { |
| if (_borderMetrics) |
| return _borderMetrics; |
| |
| var borderThickness:Number; |
| |
| // Add support for "custom" style type here when we support it. |
| var borderStyle:String = getStyle("borderStyle"); |
| |
| if (borderStyle == "default" || |
| borderStyle == "alert") |
| { |
| return EdgeMetrics.EMPTY; |
| } |
| |
| else if (borderStyle == "controlBar" || |
| borderStyle == "applicationControlBar") |
| { |
| _borderMetrics = new EdgeMetrics(1, 1, 1, 1); |
| } |
| |
| else if (borderStyle == "solid") |
| { |
| borderThickness = getStyle("borderThickness"); |
| if (isNaN(borderThickness)) |
| borderThickness = 0; |
| |
| _borderMetrics = new EdgeMetrics(borderThickness, |
| borderThickness, |
| borderThickness, |
| borderThickness); |
| |
| var borderSides:String = getStyle("borderSides"); |
| if (borderSides != "left top right bottom") |
| { |
| // Adjust metrics based on which sides we have |
| if (borderSides.indexOf("left") == -1) |
| _borderMetrics.left = 0; |
| |
| if (borderSides.indexOf("top") == -1) |
| _borderMetrics.top = 0; |
| |
| if (borderSides.indexOf("right") == -1) |
| _borderMetrics.right = 0; |
| |
| if (borderSides.indexOf("bottom") == -1) |
| _borderMetrics.bottom = 0; |
| } |
| } |
| |
| else |
| { |
| borderThickness = BORDER_WIDTHS[borderStyle]; |
| if (isNaN(borderThickness)) |
| borderThickness = 0; |
| |
| _borderMetrics = new EdgeMetrics(borderThickness, |
| borderThickness, |
| borderThickness, |
| borderThickness); |
| } |
| |
| return _borderMetrics; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * If borderStyle may have changed, clear the cached border metrics. |
| */ |
| override public function styleChanged(styleProp:String):void |
| { |
| super.styleChanged(styleProp); |
| |
| if (styleProp == null || |
| styleProp == "styleName" || |
| styleProp == "borderStyle" || |
| styleProp == "borderThickness" || |
| styleProp == "borderSides") |
| { |
| _borderMetrics = null; |
| } |
| } |
| |
| /** |
| * @private |
| * Draw the border, either 3D or 2D or nothing at all. |
| */ |
| override protected function updateDisplayList(w:Number, h:Number):void |
| { |
| if (isNaN(w) || isNaN(h)) |
| return; |
| |
| super.updateDisplayList(w, h); |
| |
| // Store background color in an object, |
| // so that null is distinct from black. |
| backgroundColor = getBackgroundColor(); |
| bRoundedCorners = false; |
| backgroundAlphaName = "backgroundAlpha"; |
| backgroundHole = null; |
| radius = 0; |
| radiusObj = null; |
| |
| drawBorder(w,h); |
| drawBackground(w,h); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| mx_internal function drawBorder(w:Number, h:Number):void |
| { |
| var borderStyle:String = getStyle("borderStyle"); |
| |
| // Other styles that we may fetch. |
| var highlightAlphas:Array = getStyle("highlightAlphas"); |
| |
| var backgroundAlpha:Number; |
| |
| var borderCapColor:uint; |
| var borderColor:uint; |
| var borderSides:String; |
| var borderThickness:Number; |
| var buttonColor:uint; |
| var docked:Boolean; |
| var dropdownBorderColor:uint; |
| var fillColors:Array; |
| var footerColors:Array; |
| var highlightColor:uint; |
| var shadowCapColor:uint; |
| var shadowColor:uint; |
| var themeColor:uint; |
| var translucent:Boolean; |
| |
| var hole:Object; |
| var drawTopHighlight:Boolean = false; |
| |
| var borderColorDrk1:Number |
| var borderColorDrk2:Number |
| var borderColorLt1:Number |
| |
| var borderInnerColor:Object; |
| |
| var g:Graphics = graphics; |
| g.clear(); |
| |
| if (borderStyle) |
| { |
| switch (borderStyle) |
| { |
| case "none": |
| { |
| break; |
| } |
| |
| case "inset": // used for text input & numeric stepper |
| { |
| borderColor = getStyle("borderColor"); |
| borderColorDrk1 = |
| ColorUtil.adjustBrightness2(borderColor, -40); |
| borderColorDrk2 = |
| ColorUtil.adjustBrightness2(borderColor, +25); |
| borderColorLt1 = |
| ColorUtil.adjustBrightness2(borderColor, +40); |
| |
| borderInnerColor = backgroundColor; |
| if (borderInnerColor === null || |
| borderInnerColor === "") |
| { |
| borderInnerColor = borderColor; |
| } |
| |
| draw3dBorder(borderColorDrk2, borderColorDrk1, borderColorLt1, |
| Number(borderInnerColor), |
| Number(borderInnerColor), |
| Number(borderInnerColor)); |
| break; |
| } |
| |
| case "outset": |
| { |
| borderColor = getStyle("borderColor"); |
| borderColorDrk1 = |
| ColorUtil.adjustBrightness2(borderColor, -40); |
| borderColorDrk2 = |
| ColorUtil.adjustBrightness2(borderColor, -25); |
| borderColorLt1 = |
| ColorUtil.adjustBrightness2(borderColor, +40); |
| |
| borderInnerColor = backgroundColor; |
| if (borderInnerColor === null || |
| borderInnerColor === "") |
| { |
| borderInnerColor = borderColor; |
| } |
| |
| draw3dBorder(borderColorDrk2, borderColorLt1, borderColorDrk1, |
| Number(borderInnerColor), |
| Number(borderInnerColor), |
| Number(borderInnerColor)); |
| break; |
| } |
| |
| case "alert": |
| case "default": |
| { |
| break; |
| } |
| |
| case "dropdown": // never used |
| { |
| // The dropdownBorderColor is currently only used |
| // when displaying an error state. |
| dropdownBorderColor = getStyle("dropdownBorderColor"); |
| |
| drawDropShadow(0, 0, w, h, 4, 0, 0, 4); |
| |
| // frame |
| drawRoundRect( |
| 0, 0, w, h, |
| { tl: 4, tr: 0, br: 0, bl: 4 }, |
| 0x4D555E, 1); |
| |
| // gradient |
| drawRoundRect( |
| 0, 0, w, h, |
| { tl: 4, tr: 0, br: 0, bl: 4}, |
| [ 0xFFFFFF, 0xFFFFFF ], [ 0.7, 0 ], |
| verticalGradientMatrix(0, 0, w, h)); |
| |
| // button top higlight edge |
| drawRoundRect( |
| 1, 1, w - 1, h - 2, |
| { tl: 3, tr: 0, br: 0, bl: 3 }, |
| 0xFFFFFF, 1); |
| |
| // button face |
| drawRoundRect( |
| 1, 2, w - 1, h - 3, |
| { tl: 3, tr: 0, br: 0, bl: 3 }, |
| [ 0xEEEEEE, 0xFFFFFF ], 1, |
| verticalGradientMatrix(0, 0, w - 1, h - 3)); |
| |
| if (!isNaN(dropdownBorderColor)) |
| { |
| // combo background in error state |
| drawRoundRect( |
| 0, 0, w + 1, h, |
| { tl: 4, tr: 0, br: 0, bl: 4 }, |
| dropdownBorderColor, 0.5); |
| |
| // button top higlight edge |
| drawRoundRect( |
| 1, 1, w - 1, h - 2, |
| { tl: 3, tr: 0, br: 0, bl: 3 }, |
| 0xFFFFFF, 1); |
| |
| //button face |
| drawRoundRect( |
| 1, 2, w - 1, h - 3, |
| { tl: 3, tr: 0, br: 0, bl: 3 }, |
| [ 0xEEEEEE, 0xFFFFFF ], 1, |
| verticalGradientMatrix(0, 0, w - 1, h - 3)); |
| } |
| |
| // Make sure the border isn't filled in down below. |
| backgroundColor = null; |
| |
| break; |
| } |
| |
| case "menuBorder": |
| { |
| borderColor = getStyle("borderColor"); |
| drawRoundRect( |
| 0, 0, w, h, 0, |
| borderColor, 1); |
| drawDropShadow(1, 1, w - 2, h - 2, 0, 0, 0, 0); |
| break; |
| } |
| |
| case "comboNonEdit": |
| { |
| break; |
| } |
| |
| case "controlBar": |
| { |
| if (w == 0 || h == 0) |
| { |
| // If the width or height is 0, don't draw anything. |
| backgroundColor = null; |
| break; |
| } |
| |
| footerColors = getStyle("footerColors"); |
| var showChrome:Boolean = footerColors != null; |
| var borderAlpha:Number = getStyle("borderAlpha"); |
| |
| if (showChrome) |
| { |
| g.lineStyle(0, footerColors.length > 0 ? |
| footerColors[1] : footerColors[0], borderAlpha); |
| g.moveTo(0, 0); |
| g.lineTo(w, 0); |
| g.lineStyle(0, 0, 0); |
| |
| // cornerRadius is defined on our parent container. Reach up |
| // and grab it. Yes, this is cheating... |
| if (parent && parent.parent && parent.parent is IStyleClient) |
| { |
| radius = |
| IStyleClient(parent.parent).getStyle("cornerRadius"); |
| borderAlpha = |
| IStyleClient(parent.parent).getStyle("borderAlpha"); |
| } |
| |
| if (isNaN(radius)) |
| radius = 0; |
| |
| // If our parent has square bottom corners, |
| // use square corners. |
| if (IStyleClient(parent.parent). |
| getStyle("roundedBottomCorners").toString().toLowerCase() != "true") |
| { |
| radius = 0; |
| } |
| |
| drawRoundRect( |
| 0, 1, w, h - 1, |
| { tl: 0, tr: 0, bl:radius, br: radius }, |
| footerColors, borderAlpha, |
| verticalGradientMatrix(0, 0, w, h)); |
| |
| if (footerColors.length > 1 && |
| footerColors[0] != footerColors[1]) |
| { |
| drawRoundRect( |
| 0, 1, w, h - 1, |
| { tl: 0, tr: 0, bl: radius, br: radius }, |
| [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, |
| verticalGradientMatrix(0, 0, w, h)); |
| |
| drawRoundRect( |
| 1, 2, w - 2, h - 3, |
| { tl: 0, tr: 0, bl: radius - 1, br: radius - 1 }, |
| footerColors, borderAlpha, |
| verticalGradientMatrix(0, 0, w, h)); |
| } |
| } |
| |
| // Don't draw the background color below. |
| // We've already handled it here. |
| backgroundColor = null; |
| break; |
| } |
| |
| case "applicationControlBar": |
| { |
| fillColors = getStyle("fillColors"); |
| backgroundAlpha = getStyle("backgroundAlpha"); |
| highlightAlphas = getStyle("highlightAlphas"); |
| var fillAlphas:Array = getStyle("fillAlphas"); |
| docked = getStyle("docked"); |
| |
| // background color of the bar |
| var backgroundColorNum:uint = uint(backgroundColor); |
| |
| radius = getStyle("cornerRadius"); |
| if (!radius) |
| radius = 0; |
| |
| drawDropShadow(0, 1, w, h - 1, |
| radius, radius, radius, radius); |
| |
| if (backgroundColor !== null && |
| styleManager.isValidStyleValue(backgroundColor)) |
| { |
| drawRoundRect( |
| 0, 1, w, h - 1, radius, |
| backgroundColorNum, backgroundAlpha, |
| verticalGradientMatrix(0, 0, w, h)); |
| } |
| |
| // surface |
| drawRoundRect( |
| 0, 1, w, h - 1, radius, |
| fillColors, fillAlphas, |
| verticalGradientMatrix(0, 0, w, h)); |
| |
| // highlight |
| drawRoundRect( |
| 0, 1, w, (h / 2) - 1, |
| { tl: radius, tr: radius, bl: 0, br: 0 }, |
| [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, |
| verticalGradientMatrix(0, 0, w, h / 2 - 1)); |
| |
| // edge |
| drawRoundRect( |
| 0, 1, w, h - 1, |
| { tl: radius, tr: radius, bl: 0, br: 0 }, |
| 0xFFFFFF, 0.3, null, |
| GradientType.LINEAR, null, |
| { x: 0, y: 2, w: w, h: h - 2, |
| r: { tl: radius, tr: radius, bl: 0, br: 0 } }); |
| |
| // Don't draw the background color below. |
| // We've already handled it here. |
| backgroundColor = null; |
| |
| break; |
| } |
| |
| default: // ((borderStyle == "solid") || (borderStyle == null)) |
| { |
| borderColor = getStyle("borderColor"); |
| borderThickness = getStyle("borderThickness"); |
| borderSides = getStyle("borderSides"); |
| var bHasAllSides:Boolean = true; |
| radius = getStyle("cornerRadius"); |
| |
| bRoundedCorners = |
| getStyle("roundedBottomCorners").toString().toLowerCase() == "true"; |
| |
| var holeRadius:Number = |
| Math.max(radius - borderThickness, 0); |
| |
| hole = { x: borderThickness, |
| y: borderThickness, |
| w: w - borderThickness * 2, |
| h: h - borderThickness * 2, |
| r: holeRadius }; |
| |
| if (!bRoundedCorners) |
| { |
| radiusObj = {tl:radius, tr:radius, bl:0, br:0}; |
| hole.r = {tl:holeRadius, tr:holeRadius, bl:0, br:0}; |
| } |
| |
| if (borderSides != "left top right bottom") |
| { |
| // Convert the radius values from a scalar to an object |
| // because we need to adjust individual radius values |
| // if we are missing any sides. |
| hole.r = { tl: holeRadius, |
| tr: holeRadius, |
| bl: bRoundedCorners ? holeRadius : 0, |
| br: bRoundedCorners ? holeRadius : 0 }; |
| |
| radiusObj = { tl: radius, |
| tr: radius, |
| bl: bRoundedCorners ? radius : 0, |
| br: bRoundedCorners ? radius : 0}; |
| |
| borderSides = borderSides.toLowerCase(); |
| |
| if (borderSides.indexOf("left") == -1) |
| { |
| hole.x = 0; |
| hole.w += borderThickness; |
| hole.r.tl = 0; |
| hole.r.bl = 0; |
| radiusObj.tl = 0; |
| radiusObj.bl = 0; |
| bHasAllSides = false; |
| } |
| |
| if (borderSides.indexOf("top") == -1) |
| { |
| hole.y = 0; |
| hole.h += borderThickness; |
| hole.r.tl = 0; |
| hole.r.tr = 0; |
| radiusObj.tl = 0; |
| radiusObj.tr = 0; |
| bHasAllSides = false; |
| } |
| |
| if (borderSides.indexOf("right") == -1) |
| { |
| hole.w += borderThickness; |
| hole.r.tr = 0; |
| hole.r.br = 0; |
| radiusObj.tr = 0; |
| radiusObj.br = 0; |
| bHasAllSides = false; |
| } |
| |
| if (borderSides.indexOf("bottom") == -1) |
| { |
| hole.h += borderThickness; |
| hole.r.bl = 0; |
| hole.r.br = 0; |
| radiusObj.bl = 0; |
| radiusObj.br = 0; |
| bHasAllSides = false; |
| } |
| } |
| |
| if (radius == 0 && bHasAllSides) |
| { |
| drawDropShadow(0, 0, w, h, 0, 0, 0, 0); |
| |
| g.beginFill(borderColor); |
| g.drawRect(0, 0, w, h); |
| g.drawRect(borderThickness, borderThickness, |
| w - 2 * borderThickness, |
| h - 2 * borderThickness); |
| g.endFill(); |
| } |
| else if (radiusObj) |
| { |
| drawDropShadow(0, 0, w, h, |
| radiusObj.tl, radiusObj.tr, |
| radiusObj.br, radiusObj.bl); |
| |
| drawRoundRect( |
| 0, 0, w, h, radiusObj, |
| borderColor, 1, |
| null, null, null, hole); |
| |
| // Reset radius here so background drawing |
| // below is correct. |
| radiusObj.tl = Math.max(radius - borderThickness, 0); |
| radiusObj.tr = Math.max(radius - borderThickness, 0); |
| radiusObj.bl = bRoundedCorners ? Math.max(radius - borderThickness, 0) : 0; |
| radiusObj.br = bRoundedCorners ? Math.max(radius - borderThickness, 0) : 0; |
| } |
| else |
| { |
| drawDropShadow(0, 0, w, h, |
| radius, radius, radius, radius); |
| |
| drawRoundRect( |
| 0, 0, w, h, radius, |
| borderColor, 1, |
| null, null, null, hole); |
| |
| // Reset radius here so background drawing |
| // below is correct. |
| radius = Math.max(getStyle("cornerRadius") - |
| borderThickness, 0); |
| } |
| } |
| } // switch |
| } |
| } |
| |
| |
| /** |
| * @private |
| * Draw a 3D border. |
| */ |
| mx_internal function draw3dBorder(c1:Number, c2:Number, c3:Number, |
| c4:Number, c5:Number, c6:Number):void |
| { |
| var w:Number = width; |
| var h:Number = height; |
| |
| /* |
| // temp color override to verify layout of lines |
| var c1:Number = 0x919999; |
| var c2:Number = 0x6F7777; |
| var c3:Number = 0xD5DDDD; |
| var c4:Number = 0xC4CCCC; |
| var c5:Number = 0xEEEEEE; |
| var c6:Number = 0xD5DDDD; |
| */ |
| |
| drawDropShadow(0, 0, width, height, 0, 0, 0, 0); |
| |
| var g:Graphics = graphics; |
| |
| // outside sides |
| g.beginFill(c1); |
| g.drawRect(0, 0, w, h); |
| g.drawRect(1, 0, w - 2, h); |
| g.endFill(); |
| |
| // outside top |
| g.beginFill(c2); |
| g.drawRect(1, 0, w - 2, 1); |
| g.endFill(); |
| |
| // outside bottom |
| g.beginFill(c3); |
| g.drawRect(1, h - 1, w - 2, 1); |
| g.endFill(); |
| |
| // inside top |
| g.beginFill(c4); |
| g.drawRect(1, 1, w - 2, 1); |
| g.endFill(); |
| |
| // inside bottom |
| g.beginFill(c5); |
| g.drawRect(1, h - 2, w - 2, 1); |
| g.endFill(); |
| |
| // inside sides |
| g.beginFill(c6); |
| g.drawRect(1, 2, w - 2, h - 4); |
| g.drawRect(2, 2, w - 4, h - 4); |
| g.endFill(); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function drawBackground(w:Number, h:Number):void |
| { |
| // The behavior used to be that we always create a background |
| // regardless of whether we have a background color or not. |
| // Now we only create a background if we have a color |
| // or if the mouseShield or mouseShieldChildren styles are true. |
| // Look at Container.addEventListener and Container.isBorderNeeded |
| // for the mouseShield logic. JCS 6/24/05 |
| if ((backgroundColor !== null && |
| backgroundColor !== "") || |
| getStyle("mouseShield") || |
| getStyle("mouseShieldChildren")) |
| { |
| var nd:Number = Number(backgroundColor); |
| var alpha:Number = 1.0; |
| var bm:EdgeMetrics = getBackgroundColorMetrics(); |
| var g:Graphics = graphics; |
| |
| if (isNaN(nd) || |
| backgroundColor === "" || |
| backgroundColor === null) |
| { |
| alpha = 0; |
| nd = 0xFFFFFF; |
| } |
| else |
| { |
| alpha = getStyle(backgroundAlphaName); |
| } |
| |
| // If we have a non-zero radius, use drawRoundRect() |
| // to fill in the background. |
| if (radius != 0 || backgroundHole) |
| { |
| var bottom:Number = bm.bottom; |
| |
| if (radiusObj) |
| { |
| var topRadius:Number = |
| Math.max(radius - Math.max(bm.top, bm.left, bm.right), 0); |
| var bottomRadius:Number = bRoundedCorners ? |
| Math.max(radius - Math.max(bm.bottom, bm.left, bm.right), 0) : 0; |
| |
| radiusObj = { tl: topRadius, |
| tr: topRadius, |
| bl: bottomRadius, |
| br: bottomRadius }; |
| |
| drawRoundRect( |
| bm.left, bm.top, |
| width - (bm.left + bm.right), |
| height - (bm.top + bottom), |
| radiusObj, |
| nd, alpha, null, |
| GradientType.LINEAR, null, |
| backgroundHole); |
| } |
| else |
| { |
| drawRoundRect( |
| bm.left, bm.top, |
| width - (bm.left + bm.right), |
| height - (bm.top + bottom), |
| radius, |
| nd, alpha, null, |
| GradientType.LINEAR, null, |
| backgroundHole); |
| } |
| } |
| else |
| { |
| g.beginFill(nd, alpha); |
| g.drawRect(bm.left, bm.top, |
| w - bm.right - bm.left, h - bm.bottom - bm.top); |
| g.endFill(); |
| } |
| } |
| } |
| |
| /** |
| * @private |
| * Apply a drop shadow using a bitmap filter. |
| * |
| * Bitmap filters are slow, and their slowness is proportional |
| * to the number of pixels being filtered. |
| * For a large HaloBorder, it's wasteful to create a big shadow. |
| * Instead, we'll create the shadow offscreen |
| * and stretch it to fit the HaloBorder. |
| */ |
| mx_internal function drawDropShadow(x:Number, y:Number, |
| width:Number, height:Number, |
| tlRadius:Number, trRadius:Number, |
| brRadius:Number, blRadius:Number):void |
| { |
| // Do I need a drop shadow in the first place? If not, return |
| // immediately. |
| if (getStyle("dropShadowEnabled") == false || |
| getStyle("dropShadowEnabled") == "false" || |
| width == 0 || |
| height == 0) |
| { |
| return; |
| } |
| |
| // Calculate the angle and distance for the shadow |
| var distance:Number = getStyle("shadowDistance"); |
| var direction:String = getStyle("shadowDirection"); |
| var angle:Number; |
| if (getStyle("borderStyle") == "applicationControlBar") |
| { |
| var docked:Boolean = getStyle("docked"); |
| angle = docked ? 90 : getDropShadowAngle(distance, direction); |
| distance = Math.abs(distance); |
| } |
| else |
| { |
| angle = getDropShadowAngle(distance, direction); |
| distance = Math.abs(distance) + 2; |
| } |
| |
| // Create a RectangularDropShadow object, set its properties, |
| // and draw the shadow |
| if (!dropShadow) |
| dropShadow = new RectangularDropShadow(); |
| |
| dropShadow.distance = distance; |
| dropShadow.angle = angle; |
| dropShadow.color = getStyle("dropShadowColor"); |
| dropShadow.alpha = 0.4; |
| |
| dropShadow.tlRadius = tlRadius; |
| dropShadow.trRadius = trRadius; |
| dropShadow.blRadius = blRadius; |
| dropShadow.brRadius = brRadius; |
| |
| dropShadow.drawShadow(graphics, x, y, width, height); |
| } |
| |
| /** |
| * @private |
| * Convert the value of the shadowDirection property |
| * into a shadow angle. |
| */ |
| mx_internal function getDropShadowAngle(distance:Number, |
| direction:String):Number |
| { |
| if (direction == "left") |
| return distance >= 0 ? 135 : 225; |
| |
| else if (direction == "right") |
| return distance >= 0 ? 45 : 315; |
| |
| else // direction == "center" |
| return distance >= 0 ? 90 : 270; |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getBackgroundColor():Object |
| { |
| var p:IUIComponent = parent as IUIComponent; |
| if (p && !p.enabled) |
| { |
| var color:Object = getStyle("backgroundDisabledColor"); |
| if (color !== null && styleManager.isValidStyleValue(color)) |
| return color; |
| } |
| |
| return getStyle("backgroundColor"); |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getBackgroundColorMetrics():EdgeMetrics |
| { |
| return borderMetrics; |
| } |
| } |
| |
| } |