| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 flash.utils.getQualifiedClassName; |
| import flash.utils.describeType; |
| import mx.core.IContainer; |
| import mx.core.EdgeMetrics; |
| import mx.core.IUIComponent; |
| import mx.core.mx_internal; |
| |
| use namespace mx_internal; |
| |
| /** |
| * The PanelSkin class defines the skin for the Panel, TitleWindow, and Alert components. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class PanelSkin extends HaloBorder |
| { |
| include "../../core/Version.as"; |
| |
| /** |
| * Constructor |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function PanelSkin() |
| { |
| super(); |
| } |
| |
| /** |
| * @private |
| */ |
| private var oldHeaderHeight:Number; |
| |
| /** |
| * @private |
| */ |
| private var oldControlBarHeight:Number; |
| |
| /** |
| * @private |
| * Internal object that contains the thickness of each edge |
| * of the border |
| */ |
| protected var _panelBorderMetrics:EdgeMetrics; |
| |
| /** |
| * @private |
| * Return the thickness of the border edges. |
| * |
| * @return Object top, bottom, left, right thickness in pixels |
| */ |
| override public function get borderMetrics():EdgeMetrics |
| { |
| var hasPanelParent:Boolean = isPanel(parent); |
| var controlBar:IUIComponent = hasPanelParent ? Object(parent)._controlBar : null; |
| var hHeight:Number = hasPanelParent ? Object(parent).getHeaderHeightProxy() : NaN; |
| |
| var newControlBarHeight:Number; |
| |
| if (controlBar && controlBar.includeInLayout) |
| newControlBarHeight = controlBar.getExplicitOrMeasuredHeight(); |
| |
| if (newControlBarHeight != oldControlBarHeight && |
| !(isNaN(oldControlBarHeight) && isNaN(newControlBarHeight))) |
| _panelBorderMetrics = null; |
| |
| if ((hHeight != oldHeaderHeight) && |
| !(isNaN(hHeight) && isNaN(oldHeaderHeight))) |
| _panelBorderMetrics = null; |
| |
| if (_panelBorderMetrics) |
| return _panelBorderMetrics; |
| |
| var o:EdgeMetrics = super.borderMetrics; |
| var vm:EdgeMetrics = new EdgeMetrics(0, 0, 0, 0); |
| |
| var bt:Number = getStyle("borderThickness"); |
| var btl:Number = getStyle("borderThicknessLeft"); |
| var btt:Number = getStyle("borderThicknessTop"); |
| var btr:Number = getStyle("borderThicknessRight"); |
| var btb:Number = getStyle("borderThicknessBottom"); |
| |
| // Add extra space to edges (was margins). |
| vm.left = o.left + (isNaN(btl) ? bt : btl); |
| vm.top = o.top + (isNaN(btt) ? bt : btt); |
| vm.right = o.bottom + (isNaN(btr) ? bt : btr); |
| |
| // Bottom is a special case. If borderThicknessBottom is NaN, |
| // use btl if we don't have a control bar or btt if we do. |
| vm.bottom = o.bottom + (isNaN(btb) ? |
| (controlBar && !isNaN(btt) ? btt : isNaN(btl) ? bt : btl) : |
| btb); |
| |
| // Since the header covers the solid portion of the border, |
| // we need to use the larger of borderThickness or headerHeight |
| |
| oldHeaderHeight = hHeight; |
| if (!isNaN(hHeight)) |
| vm.top += hHeight; |
| |
| oldControlBarHeight = newControlBarHeight |
| if (!isNaN(newControlBarHeight)) |
| vm.bottom += newControlBarHeight; |
| |
| _panelBorderMetrics = vm; |
| |
| return _panelBorderMetrics; |
| } |
| |
| /** |
| * @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 == "borderThicknessTop" || |
| styleProp == "borderThicknessBottom" || |
| styleProp == "borderThicknessLeft" || |
| styleProp == "borderThicknessRight" || |
| styleProp == "borderSides" ) |
| { |
| _panelBorderMetrics = null; |
| } |
| |
| invalidateDisplayList(); |
| } |
| |
| /** |
| * @private |
| */ |
| override mx_internal function drawBorder(w:Number, h:Number):void |
| { |
| super.drawBorder(w,h); |
| |
| var borderStyle:String = getStyle("borderStyle"); |
| |
| if (borderStyle == "default") |
| { |
| // For Panel/Alert, "borderAlpha" is the alpha for the |
| // title/control/gutter area and "backgroundAlpha" |
| // is the alpha for the content area. |
| // We flip-flop the variables here so the "borderAlpha" |
| // is applied by the background drawing code at the bottom. |
| var contentAlpha:Number = getStyle("backgroundAlpha"); |
| var backgroundAlpha:Number = getStyle("borderAlpha"); |
| backgroundAlphaName = "borderAlpha"; |
| |
| radiusObj = null; |
| radius = getStyle("cornerRadius"); |
| bRoundedCorners = |
| getStyle("roundedBottomCorners").toString().toLowerCase() == "true"; |
| var br:Number = bRoundedCorners ? radius : 0; |
| |
| var g:Graphics = graphics; |
| |
| drawDropShadow(0, 0, w, h, radius, radius, br, br); |
| |
| // If we don't have rounded corners we need to initialize |
| // the complex radius object so the background fill code |
| // below works correctly. |
| if (!bRoundedCorners) |
| radiusObj = {}; |
| |
| var parentContainer:IContainer = parent as IContainer; |
| |
| if (parentContainer) |
| { |
| var vm:EdgeMetrics = parentContainer.viewMetrics; |
| |
| // The backgroundHole is the content area |
| backgroundHole = {x:vm.left, y:vm.top, |
| w: Math.max(0, w - vm.left - vm.right), |
| h: Math.max(0, h - vm.top - vm.bottom), |
| r:0}; |
| |
| if (backgroundHole.w > 0 && backgroundHole.h > 0) |
| { |
| // Draw a shadow around the content |
| // if the content and panel alpha are different. |
| // This could be a style property if needed |
| if (contentAlpha != backgroundAlpha) |
| { |
| drawDropShadow(backgroundHole.x, backgroundHole.y, |
| backgroundHole.w, backgroundHole.h, |
| 0, 0, 0, 0); |
| } |
| |
| // Fill in the content area |
| g.beginFill(Number(backgroundColor), contentAlpha); |
| g.drawRect(backgroundHole.x, backgroundHole.y, |
| backgroundHole.w, backgroundHole.h); |
| g.endFill(); |
| } |
| } |
| |
| // When the content and panel alpha are different, the border |
| // of the panel is drawn using borderColor. We've already |
| // drawn the content background so we set backgroundColor to |
| // borderColor here so the drawing code below is done with the |
| // border color. |
| backgroundColor = getStyle("borderColor"); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override mx_internal function drawBackground(w:Number, h:Number):void |
| { |
| super.drawBackground(w,h); |
| |
| if (getStyle("headerColors") == null && getStyle("borderStyle") == "default") |
| { |
| var highlightAlphas:Array = getStyle("highlightAlphas"); |
| var highlightAlpha:Number = highlightAlphas ? highlightAlphas[0] : 0.3; |
| // edge |
| drawRoundRect( |
| 0, 0, w, h, |
| { tl: radius, tr: radius, bl: 0, br: 0 }, |
| 0xFFFFFF, highlightAlpha, null, |
| GradientType.LINEAR, null, |
| { x: 0, y: 1, w: w, h: h - 1, |
| r: { tl: radius, tr: radius, bl: 0, br: 0 } }); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override mx_internal function getBackgroundColorMetrics():EdgeMetrics |
| { |
| if (getStyle("borderStyle") == "default") |
| return EdgeMetrics.EMPTY; |
| else |
| { |
| return super.borderMetrics; |
| } |
| } |
| |
| /** |
| * We don't use 'is' to prevent dependency issues |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private static var panels:Object = {}; |
| |
| private static function isPanel(parent:Object):Boolean |
| { |
| var s:String = getQualifiedClassName(parent); |
| if (panels[s] == 1) |
| return true; |
| |
| if (panels[s] == 0) |
| return false; |
| |
| if (s == "mx.containers::Panel") |
| { |
| panels[s] == 1; |
| return true; |
| } |
| |
| var x:XML = describeType(parent); |
| var xmllist:XMLList = x.extendsClass.(@type == "mx.containers::Panel"); |
| if (xmllist.length() == 0) |
| { |
| panels[s] = 0; |
| return false; |
| } |
| |
| panels[s] = 1; |
| return true; |
| } |
| |
| } |
| } |