http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/styles/StyleProtoChain.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/styles/StyleProtoChain.as index 342e7ca,0000000..ba6ea3f mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/styles/StyleProtoChain.as +++ b/frameworks/projects/MX/src/main/flex/mx/styles/StyleProtoChain.as @@@ -1,1078 -1,0 +1,1078 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.styles +{ + - COMPILE::AS3 ++COMPILE::SWF +{ + import flash.display.DisplayObject; + import flash.display.DisplayObjectContainer; +} +COMPILE::JS +{ + import flex.display.DisplayObject; + import flex.display.DisplayObjectContainer; +} +import flex.system.DefinitionManager; +import org.apache.flex.reflection.getQualifiedClassName; +import org.apache.flex.reflection.getQualifiedSuperclassName; + +import mx.core.FlexGlobals; +import mx.core.IFlexDisplayObject; +import mx.core.IFlexModule; +COMPILE::LATER +{ + import mx.core.IFlexModuleFactory; + import mx.effects.EffectManager; + import mx.managers.SystemManager; + import mx.modules.IModule; + import mx.modules.ModuleManager; +} +import mx.core.IFontContextComponent; +import mx.core.IInvalidating; +import mx.core.IUITextField; +import mx.core.IVisualElement; +import mx.core.IUIComponent; +import mx.core.UIComponent; +import mx.core.mx_internal; +import mx.utils.NameUtil; +import mx.utils.OrderedObject; +import mx.utils.object_proxy; + +use namespace mx_internal; +use namespace object_proxy; + +[ExcludeClass] + +/** + * @private + * This is an all-static class with methods for building the protochains + * that Flex uses to look up CSS style properties. + * @flexjsignoreimport mx.core.UIComponent + */ +public class StyleProtoChain +{ + include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Class constants + // + //-------------------------------------------------------------------------- + + /** + * @private + * The inheritingStyles and nonInheritingStyles properties + * are initialized to this empty Object. + * This allows the getStyle() and getStyle() + * methods to simply access inheritingStyles[] and nonInheritingStyles[] + * without needing to first check whether those objects exist. + * If they were simply initialized to {}, we couldn't determine + * whether the style chain has already been built or not. + */ + public static var STYLE_UNINITIALIZED:Object = {}; + + //-------------------------------------------------------------------------- + // + // Class methods + // + //-------------------------------------------------------------------------- + + /** + * @private + * Implements the getClassStyleDeclarations() logic + * for UIComponent and TextBase. + * The 'object' parameter will be one or the other. + */ + public static function getClassStyleDeclarations(object:IStyleClient):Array + { + var styleManager:IStyleManager2 = getStyleManager(object); + var qualified:Boolean = styleManager.qualifiedTypeSelectors; + var className:String = qualified ? getQualifiedClassName(object) : object.className; + var advancedObject:IAdvancedStyleClient = object as IAdvancedStyleClient; + + var typeHierarchy:OrderedObject = getTypeHierarchy(object, styleManager, qualified); + var types:Array = typeHierarchy.propertyList; + var typeCount:int = types.length; + var classDecls:Array = null; + + if (!styleManager.hasAdvancedSelectors()) + { + classDecls = styleManager.typeSelectorCache[className]; + if (classDecls) + return classDecls; + } + + classDecls = []; + + // Loop over the type hierarhcy starting at the base type and work + // down the chain of subclasses. + for (var i:int = typeCount - 1; i >= 0; i--) + { + var type:String = types[i].toString(); + if (styleManager.hasAdvancedSelectors() && advancedObject != null) + { + var decls:Object = styleManager.getStyleDeclarations(type); + if (decls) + { + var matchingDecls:Array = matchStyleDeclarations(decls, advancedObject); + classDecls = classDecls.concat(matchingDecls); + } + } + else + { + var decl:CSSStyleDeclaration = styleManager.getMergedStyleDeclaration(type); + if (decl) + classDecls.push(decl); + } + } + + if (styleManager.hasAdvancedSelectors() && advancedObject != null) + { + // Advanced selectors may result in more than one match per type so + // we sort based on specificity, but we preserve the declaration + // order for equal selectors. + classDecls = sortOnSpecificity(classDecls); + } + else + { + // Cache the simple type declarations for this class + styleManager.typeSelectorCache[className] = classDecls; + } + + return classDecls; + } + + /** + * @private + * Implements the initProtoChain() logic for UIComponent and TextBase. + * The 'object' parameter will be one or the other. + * @flexjsignorecoercion mx.core.UIComponent + */ + public static function initProtoChain(object:IStyleClient, inheritPopUpStylesFromOwner:Boolean=true):void + { + var styleManager:IStyleManager2 = getStyleManager(object); + var n:int; + var i:int; + + var uicObject:UIComponent = object as UIComponent; + var advancedObject:IAdvancedStyleClient = object as IAdvancedStyleClient; + var styleDeclaration:CSSStyleDeclaration = null; + + var universalSelectors:Array = []; + var hasStyleName:Boolean = false; + var styleName:Object = object.styleName; + if (styleName) + { + if (styleName is CSSStyleDeclaration) + { + // Get the styles referenced by the styleName property. + universalSelectors.push(CSSStyleDeclaration(styleName)); + } + else if (styleName is IFlexDisplayObject || styleName is IStyleClient) + { + // If the styleName property is a UIComponent, then there's a + // special search path for that case. + StyleProtoChain.initProtoChainForUIComponentStyleName(object); + return; + } + else if (styleName is String) + { + hasStyleName = true; + } + } + + // To build the proto chain, we start at the end and work forward. + // Referring to the list at the top of this function, we'll start + // by getting the tail of the proto chain, which is: + // - for non-inheriting styles, the global style sheet + // - for inheriting styles, my parent's style object + var nonInheritChain:Object = styleManager.stylesRoot; + + if (nonInheritChain && nonInheritChain.effects) + object.registerEffects(nonInheritChain.effects); + + var p:IStyleClient = null; + if (object is IVisualElement) + p = IVisualElement(object).parent as IStyleClient; + else if (object is IAdvancedStyleClient) + p = IAdvancedStyleClient(object).styleParent as IStyleClient; + + if (p) + { + var inheritChain:Object = p.inheritingStyles; + if (inheritChain == StyleProtoChain.STYLE_UNINITIALIZED) + inheritChain = nonInheritChain; + + COMPILE::LATER + { + // If this object is a module then add its global styles to the + // inheritChain. If we don't have global styles in this style manager + // then the user didn't declare a global style in the module and the + // compiler didn't add a duplicate default style. In that case don't + // add global styles to the chain because the parent style manager's + // global styles are already on the chain. + if (object is IModule) + { + styleDeclaration = styleManager.getStyleDeclaration("global"); + if (styleDeclaration) + inheritChain = styleDeclaration.addStyleToProtoChain(inheritChain, DisplayObject(object)); + } + } + } + else + { + // Pop ups inheriting chain starts at Application instead of global. + // This allows popups to grab styles like themeColor that are + // set on Application. + if (uicObject && uicObject.isPopUp) + { + var owner:DisplayObjectContainer = uicObject._owner; + if (inheritPopUpStylesFromOwner && owner && (owner is IStyleClient)) + { + inheritChain = IStyleClient(owner).inheritingStyles; + } + else + { + inheritChain = FlexGlobals.topLevelApplication.inheritingStyles; + } + } + else + { + inheritChain = styleManager.stylesRoot; + } + } + + var styleDeclarations:Array = null; + + // If we have an advanced style client, we handle this separately + // because of the considerably more complex selector matches... + if (styleManager.hasAdvancedSelectors() && advancedObject != null) + { + styleDeclarations = getMatchingStyleDeclarations(advancedObject, universalSelectors); + + n = styleDeclarations != null ? styleDeclarations.length : 0; + for (i = 0; i < n; i++) + { + styleDeclaration = styleDeclarations[i]; + inheritChain = styleDeclaration.addStyleToProtoChain(inheritChain, uicObject); + nonInheritChain = styleDeclaration.addStyleToProtoChain(nonInheritChain, uicObject); + + if (styleDeclaration.effects) + advancedObject.registerEffects(styleDeclaration.effects); + } + } + // Otherwise we use the legacy Flex 3 logic for simple selectors. + else + { + // Get the styles referenced by the styleName property + if (hasStyleName) + { + var styleNames:Array = styleName.split(/\s+/); + n = styleNames.length; + for (i = 0; i < n; i++) + { + if (styleNames[i].length) + { + styleDeclaration = styleManager.getMergedStyleDeclaration("." + styleNames[i]); + if (styleDeclaration) + universalSelectors.push(styleDeclaration); + } + } + } + + // Working backwards up the list, the next element in the + // search path is the type selector + styleDeclarations = object.getClassStyleDeclarations(); + n = styleDeclarations != null ? styleDeclarations.length : 0; + for (i = 0; i < n; i++) + { + styleDeclaration = styleDeclarations[i]; + inheritChain = styleDeclaration.addStyleToProtoChain(inheritChain, uicObject); + nonInheritChain = styleDeclaration.addStyleToProtoChain(nonInheritChain, uicObject); + + if (styleDeclaration.effects) + object.registerEffects(styleDeclaration.effects); + } + + // Next are the class selectors + n = universalSelectors.length; + for (i = 0; i < n; i++) + { + styleDeclaration = universalSelectors[i]; + if (styleDeclaration) + { + inheritChain = + styleDeclaration.addStyleToProtoChain(inheritChain, uicObject); + + nonInheritChain = + styleDeclaration.addStyleToProtoChain(nonInheritChain, uicObject); + + if (styleDeclaration.effects) + object.registerEffects(styleDeclaration.effects); + } + } + } + + // Finally, we'll add the in-line styles + // to the head of the proto chain. + + styleDeclaration = object.styleDeclaration; + + object.inheritingStyles = + styleDeclaration ? + styleDeclaration.addStyleToProtoChain(inheritChain, uicObject) : + inheritChain; + + object.nonInheritingStyles = + styleDeclaration ? + styleDeclaration.addStyleToProtoChain(nonInheritChain, uicObject) : + nonInheritChain; + } + + /** + * @private + * If the styleName property points to a UIComponent, then we search + * for stylable properties in the following order: + * + * 1) Look for inline styles on this object + * 2) Look for inline styles on the styleName object + * 3) Look for class selectors on the styleName object + * 4) Look for type selectors on the styleName object + * 5) Look for type selectors on this object + * 6) Follow the usual search path for the styleName object + * + * If this object doesn't have any type selectors, then the + * search path can be simplified to two steps: + * + * 1) Look for inline styles on this object + * 2) Follow the usual search path for the styleName object + */ + public static function initProtoChainForUIComponentStyleName( + obj:IStyleClient):void + { + var styleManager:IStyleManager2 = getStyleManager(obj); + var styleName:IStyleClient = IStyleClient(obj.styleName); + var target:DisplayObject = obj as DisplayObject; + + // Push items onto the proto chain in reverse order, beginning with + // 6) Follow the usual search path for the styleName object + var nonInheritChain:Object = styleName.nonInheritingStyles; + if (!nonInheritChain || + nonInheritChain == StyleProtoChain.STYLE_UNINITIALIZED) + { + nonInheritChain = styleManager.stylesRoot; + + if (nonInheritChain.effects) + obj.registerEffects(nonInheritChain.effects); + } + + var inheritChain:Object = styleName.inheritingStyles; + if (!inheritChain || + inheritChain == StyleProtoChain.STYLE_UNINITIALIZED) + { + inheritChain = styleManager.stylesRoot; + } + + // If there's no type selector on this object, then we can collapse + // 6 steps to 2 (see above) + var typeSelectors:Array = obj.getClassStyleDeclarations(); + var n:int = typeSelectors.length; + + // If we are a StyleProxy and we aren't building the protochain from + // our type selectors, then we need to build the protochain from + // the styleName since styleName.nonInheritingStyles is always null. + if (styleName is StyleProxy) + { + if (n == 0) + { + // 4) Look for type selectors on the styleName object + // 3) Look for class selectors on the styleName object + // 2) Look for inline styles on the styleName object + nonInheritChain = addProperties(nonInheritChain, styleName, false); + } + target = StyleProxy(styleName).source as DisplayObject; + } + + for (var i:int = 0; i < n; i++) + { + var typeSelector:CSSStyleDeclaration = typeSelectors[i]; + + // If there's no *inheriting* type selector on this object, then we + // can still collapse 6 steps to 2 for the inheriting properties. + + // 5) Look for type selectors on this object + inheritChain = typeSelector.addStyleToProtoChain(inheritChain, target); + + // 4) Look for type selectors on the styleName object + // 3) Look for class selectors on the styleName object + // 2) Look for inline styles on the styleName object + inheritChain = addProperties(inheritChain, styleName, true); + + // 5) Look for type selectors on this object + nonInheritChain = typeSelector.addStyleToProtoChain(nonInheritChain, target); + + // 4) Look for type selectors on the styleName object + // 3) Look for class selectors on the styleName object + // 2) Look for inline styles on the styleName object + nonInheritChain = addProperties(nonInheritChain, styleName, false); + + if (typeSelector.effects) + obj.registerEffects(typeSelector.effects); + } + + // 1) Look for inline styles on this object + + obj.inheritingStyles = + obj.styleDeclaration ? + obj.styleDeclaration.addStyleToProtoChain(inheritChain, target) : + inheritChain; + + obj.nonInheritingStyles = + obj.styleDeclaration ? + obj.styleDeclaration.addStyleToProtoChain(nonInheritChain, target) : + nonInheritChain; + } + + /** + * See the comment for the initProtoChainForUIComponentStyleName + * function. The comment for that function includes a six-step + * sequence. This sub-function implements the following pieces + * of that sequence: + * + * 2) Look for inline styles on the styleName object + * 3) Look for class selectors on the styleName object + * 4) Look for type selectors on the styleName object + * + * This piece is broken out as a separate function so that it + * can be called recursively when the styleName object has a + * styleName property is itself another UIComponent. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + private static function addProperties(chain:Object, obj:IStyleClient, + bInheriting:Boolean):Object + { + // Only use a filter map if styleName is a StyleProxy and we are building the nonInheritingStyles chain + var filterMap:Object = obj is StyleProxy && !bInheriting ? StyleProxy(obj).filterMap : null; + + // StyleProxy's usually have sources that are DisplayObject's, but a StyleProxy can also have + // another StyleProxy as it's source (Example: CalendarLayout's source is a StyleProxy for DateChooser, + // whose style is a StyleProxy for DateField) + + // The way we use target is a bit hacky, but we always assume that styles (if pointed to DisplayObjects) + // are the parent (or atleast an ancestor), and we rely on this down the line (such as in + // DataGridColumn.addStyleToProtoChain) + var curObj:IStyleClient = obj; + while (curObj is StyleProxy) + { + curObj = StyleProxy(curObj).source; + } + var target:DisplayObject = curObj as DisplayObject; + + var advancedObject:IAdvancedStyleClient = obj as IAdvancedStyleClient; + var styleName:Object = obj.styleName; + var styleDeclarations:Array; + var decl:CSSStyleDeclaration; + var styleManager:IStyleManager2 = getStyleManager(target); + + // If we have an advanced style client, we handle this separately + // because of the considerably more complex selector matches... + if (advancedObject != null && styleManager.hasAdvancedSelectors()) + { + // Handle special case of styleName as a CSSStyleDeclaration + if (styleName is CSSStyleDeclaration) + { + styleDeclarations = [CSSStyleDeclaration(styleName)]; + } + + // Find matching style declarations, sorted by specificity + styleDeclarations = getMatchingStyleDeclarations(advancedObject, styleDeclarations); + + // Then apply matching selectors to the proto chain + for (i = 0; i < styleDeclarations.length; i++) + { + decl = styleDeclarations[i]; + if (decl) + { + chain = decl.addStyleToProtoChain(chain, target, filterMap); + if (decl.effects) + obj.registerEffects(decl.effects); + } + } + + // Finally, handle special case of styleName as an IStyleClient + // which overrides any of the selectors above + if (styleName is IStyleClient) + { + // If the styleName property is another UIComponent, then + // recursively add type selectors, class selectors, and + // inline styles for that UIComponent + chain = addProperties(chain, IStyleClient(styleName), + bInheriting); + } + } + else + { + // 4) Add type selectors + styleDeclarations = obj.getClassStyleDeclarations(); + var n:int = styleDeclarations.length; + for (var i:int = 0; i < n; i++) + { + decl = styleDeclarations[i]; + chain = decl.addStyleToProtoChain(chain, target, filterMap); + + if (decl.effects) + obj.registerEffects(decl.effects); + } + + // 3) Add class selectors + if (styleName) + { + styleDeclarations = []; + if (typeof(styleName) == "object") + { + if (styleName is CSSStyleDeclaration) + { + // Get the style sheet referenced by the styleName property. + styleDeclarations.push(CSSStyleDeclaration(styleName)); + } + else + { + // If the styleName property is another UIComponent, then + // recursively add type selectors, class selectors, and + // inline styles for that UIComponent + chain = addProperties(chain, IStyleClient(styleName), + bInheriting); + } + } + else + { + // Get the style sheets referenced by the styleName property + var styleNames:Array = styleName.split(/\s+/); + for (var c:int=0; c < styleNames.length; c++) + { + if (styleNames[c].length) + { + styleDeclarations.push(styleManager.getMergedStyleDeclaration("." + styleNames[c])); + } + } + } + + for (i = 0; i < styleDeclarations.length; i++) + { + decl = styleDeclarations[i]; + if (decl) + { + chain = decl.addStyleToProtoChain(chain, target, filterMap); + if (decl.effects) + obj.registerEffects(decl.effects); + } + } + } + } + + // 2) Add inline styles + if (obj.styleDeclaration) + chain = obj.styleDeclaration.addStyleToProtoChain(chain, target, filterMap); + + return chain; + } + + /** + * @private + */ + public static function initTextField(obj:IUITextField):void + { + // TextFields never have any inline styles or type selector, so + // this is an optimized version of the initObject function (above) + var styleManager:IStyleManager2 = StyleManager.getStyleManager(obj.moduleFactory); + var styleName:Object = obj.styleName; + var classSelectors:Array = []; + + if (styleName) + { + if (typeof(styleName) == "object") + { + if (styleName is CSSStyleDeclaration) + { + // Get the style sheet referenced by the styleName property. + classSelectors.push(CSSStyleDeclaration(styleName)); + } + else if (styleName is StyleProxy) + { + obj.inheritingStyles = + IStyleClient(styleName).inheritingStyles; + + obj.nonInheritingStyles = addProperties(styleManager.stylesRoot, IStyleClient(styleName), false); + + return; + } + else + { + // styleName points to a UIComponent, so just set + // this TextField's proto chains to be the same + // as that UIComponent's proto chains. + obj.inheritingStyles = + IStyleClient(styleName).inheritingStyles; + obj.nonInheritingStyles = + IStyleClient(styleName).nonInheritingStyles; + return; + } + } + else + { + // Get the style sheets referenced by the styleName property + var styleNames:Array = styleName.split(/\s+/); + for (var c:int=0; c < styleNames.length; c++) + { + if (styleNames[c].length) { + classSelectors.push(styleManager.getMergedStyleDeclaration("." + + styleNames[c])); + } + } + } + } + + // To build the proto chain, we start at the end and work forward. + // We'll start by getting the tail of the proto chain, which is: + // - for non-inheriting styles, the global style sheet + // - for inheriting styles, my parent's style object + var inheritChain:Object = IStyleClient(obj.parent).inheritingStyles; + var nonInheritChain:Object = styleManager.stylesRoot; + if (!inheritChain) + inheritChain = styleManager.stylesRoot; + + // Next are the class selectors + for (var i:int = 0; i < classSelectors.length; i++) + { + var classSelector:CSSStyleDeclaration = classSelectors[i]; + if (classSelector) + { + inheritChain = + classSelector.addStyleToProtoChain(inheritChain, DisplayObject(obj)); + + nonInheritChain = + classSelector.addStyleToProtoChain(nonInheritChain, DisplayObject(obj)); + } + } + + obj.inheritingStyles = inheritChain; + obj.nonInheritingStyles = nonInheritChain; + } + + /** + * @private + * Implements the setStyle() logic for UIComponent and TextBase. + * The 'object' parameter will be one or the other. + */ + public static function setStyle(object:IStyleClient, styleProp:String, + newValue:*):void + { + var styleManager:IStyleManager2 = getStyleManager(object); + + if (styleProp == "styleName") + { + // Let the setter handle this one, see UIComponent. + object.styleName = newValue; + + // Short circuit, because styleName isn't really a style. + return; + } + + COMPILE::LATER + { + if (EffectManager.getEventForEffectTrigger(styleProp) != "") + EffectManager.setStyle(styleProp, object); + } + + // If this object didn't previously have any inline styles, + // then regenerate its proto chain + // (and the proto chains of its descendants). + var isInheritingStyle:Boolean = + styleManager.isInheritingStyle(styleProp); + var isProtoChainInitialized:Boolean = + object.inheritingStyles != StyleProtoChain.STYLE_UNINITIALIZED; + var valueChanged:Boolean = object.getStyle(styleProp) != newValue; + + if (!object.styleDeclaration) + { + object.styleDeclaration = new CSSStyleDeclaration(null, styleManager); + + object.styleDeclaration.setLocalStyle(styleProp, newValue); + + // If inheritingStyles is undefined, then this object is being + // initialized and we haven't yet generated the proto chain. To + // avoid redundant work, don't bother to create the proto chain here. + if (isProtoChainInitialized) + object.regenerateStyleCache(isInheritingStyle); + } + else + { + object.styleDeclaration.setLocalStyle(styleProp, newValue); + } + + if (isProtoChainInitialized && valueChanged) + { + object.styleChanged(styleProp); + object.notifyStyleChangeInChildren(styleProp, isInheritingStyle); + } + } + + /** + * @private + * Implements the styleChanged() logic for UIComponent and TextBase. + * The 'object' parameter will be one or the other. + */ + public static function styleChanged(object:IInvalidating, styleProp:String):void + { + var styleManager:IStyleManager2 = getStyleManager(object); + + // If font changed, then invalidateProperties so + // we can re-create the text field in commitProperties + // TODO (gosmith): Should hasFontContextChanged() be added to IFontContextComponent? + if (object is IFontContextComponent && + "hasFontContextChanged" in object && + object["hasFontContextChanged"]()) + { + object.invalidateProperties(); + } + + if (!styleProp || + styleProp == "styleName" || + styleProp == "layoutDirection") + { + object.invalidateProperties(); + } + + // Check to see if this is one of the style properties + // that is known to affect layout. + if (!styleProp || + styleProp == "styleName" || + styleManager.isSizeInvalidatingStyle(styleProp)) + { + // This style property change may affect the layout of this + // object. Signal the LayoutManager to re-measure the object. + object.invalidateSize(); + } + + // TODO (gosmith): Should initThemeColor() be in some interface? + if (!styleProp || + styleProp == "styleName" || + styleProp == "themeColor") + { + if (object is IUIComponent) + object["initThemeColor"](); + } + + object.invalidateDisplayList(); + + var parent:IInvalidating; + if (object is IVisualElement) + parent = IVisualElement(object).parent as IInvalidating; + + if (parent) + { + if (styleProp == "styleName" || styleManager.isParentSizeInvalidatingStyle(styleProp)) + parent.invalidateSize(); + + if (styleProp == "styleName" || styleManager.isParentDisplayListInvalidatingStyle(styleProp)) + parent.invalidateDisplayList(); + } + } + + /** + * @private + */ + public static function matchesCSSType(object:IAdvancedStyleClient, cssType:String):Boolean + { + var styleManager:IStyleManager2 = getStyleManager(object); + var qualified:Boolean = styleManager.qualifiedTypeSelectors; + var typeHierarchy:OrderedObject = getTypeHierarchy(object, styleManager, qualified); + return typeHierarchy.object_proxy::getObjectProperty(cssType) != null; + } + + /** + * @private + * Find all matching style declarations for an IAdvancedStyleClient + * component. The result is sorted in terms of specificity, but the + * declaration order is preserved. + * + * @param object - an IAdvancedStyleClient instance of the component to + * match. + * @param styleDeclarations - an optional Array of additional + * CSSStyleDeclarations to be included in the sorted matches. + * + * @return An Array of matching style declarations sorted by specificity. + */ + public static function getMatchingStyleDeclarations(object:IAdvancedStyleClient, + styleDeclarations:Array=null):Array // of CSSStyleDeclaration + { + var styleManager:IStyleManager2 = getStyleManager(object); + + if (styleDeclarations == null) + styleDeclarations = []; + + // First, look for universal selectors + var universalDecls:Object = styleManager.getStyleDeclarations("*"); + styleDeclarations = matchStyleDeclarations(universalDecls, object).concat(styleDeclarations); + + // Next, look for type selectors (includes ActionScript supertype matches) + // If we also had universal selectors, concatenate them with our type + // selectors and then resort by specificity... + if (styleDeclarations.length > 0) + { + styleDeclarations = object.getClassStyleDeclarations().concat(styleDeclarations); + styleDeclarations = sortOnSpecificity(styleDeclarations); + } + else + { + // Otherwise, we only have type selectors (which are already sorted) + styleDeclarations = object.getClassStyleDeclarations(); + } + return styleDeclarations; + } + + /** + * @private + * @param object - the IStyleClient to be introspected + * @param qualified - whether qualified type names should be used + * @return an ordered map of class names, starting with the object's class + * name and then each super class name until we hit a stop class, such as + * mx.core::UIComponent. + */ + private static function getTypeHierarchy(object:IStyleClient, styleManager:IStyleManager2, qualified:Boolean=true):OrderedObject + { + var className:String = getQualifiedClassName(object); + var hierarchy:OrderedObject = styleManager.typeHierarchyCache[className] as OrderedObject; + if (hierarchy == null) + { + hierarchy = new OrderedObject(); + + var myApplicationDomain:DefinitionManager = new DefinitionManager(); + COMPILE::LATER + { + var myApplicationDomain:DefinitionManager; + var factory:IFlexModuleFactory = ModuleManager.getAssociatedFactory(object); + if (factory != null) + { + myApplicationDomain = new DefinitionManager(factory.info()["currentDomain"]); + } + else + { + var myRoot:DisplayObject = SystemManager.getSWFRoot(object); + if (!myRoot) + return hierarchy; + myApplicationDomain = new DefinitionManager(myRoot.loaderInfo.applicationDomain); + } + } + + styleManager.typeHierarchyCache[className] = hierarchy; + while (!isStopClass(className)) + { + try + { + var type:String; + if (qualified) + type = className.replace("::", "."); + else + type = NameUtil.getUnqualifiedClassName(className); + + hierarchy.object_proxy::setObjectProperty(type, true); + className = getQualifiedSuperclassName( + myApplicationDomain.getDefinition(className)); + } + catch(e:ReferenceError) + { + className = null; + } + } + } + return hierarchy; + } + + /** + * @private + * Our style type hierarhcy stops at UIComponent, UITextField or + * GraphicElement, not Object. + */ + private static function isStopClass(value:String):Boolean + { + return value == null || + value == "mx.core::UIComponent" || + value == "mx.core::UITextField" || + value == "mx.graphics.baseClasses::GraphicElement"; + } + + /** + * @private + * Find all matching style declarations for an IAdvancedStyleClient + * component. The result is unsorted in terms of specificity, but the + * declaration order is preserved. + * + * @param declarations - a map of declarations to be searched for matches. + * @param object - an instance of the component to match. + * + * @return An unsorted Array of matching style declarations for the given + * subject. + */ + private static function matchStyleDeclarations(declarations:Object, + object:IAdvancedStyleClient):Array // of CSSStyleDeclaration + { + var matchingDecls:Array = []; + var pseudos:Array = declarations["pseudo"]; + var classes:Array = declarations["class"]; + var ids:Array = declarations["id"]; + var unconditionals:Array = declarations["unconditional"]; + + var decl:CSSStyleDeclaration; + + // Find the subset of declarations that match this component + for each (decl in unconditionals) + { + if (decl.matchesStyleClient(object)) + matchingDecls.push(decl); + } + + if (object.styleName is String) + { + // Find the subset of declarations that match this component + for each (decl in classes) + { + if (decl.matchesStyleClient(object)) + matchingDecls.push(decl); + } + } + + if (object.hasCSSState()) + { + // Find the subset of declarations that match this component + for each (decl in pseudos) + { + if (decl.matchesStyleClient(object)) + matchingDecls.push(decl); + } + } + + if (object.id) + { + // Find the subset of declarations that match this component + for each (decl in ids) + { + if (decl.matchesStyleClient(object)) + matchingDecls.push(decl); + } + } + + if (matchingDecls.length > 1) + matchingDecls.sortOn("selectorIndex", Array.NUMERIC); + + // if there are declarations from the parent StyleManager, match them in their own + // order, then prepend them. Parent styles go on the chain before child styles. + if (declarations.parent) + matchingDecls = matchStyleDeclarations(declarations.parent, object).concat(matchingDecls); + + return matchingDecls; + } + + /** + * @private + * Sort algorithm to order style declarations by specificity. Note that + * Array.sort() is not used as it does not employ a stable algorithm and + * CSS requires the order of equal style declaration to be preserved. + */ + private static function sortOnSpecificity(decls:Array):Array // of CSSStyleDeclaration + { + // TODO (pfarland): Copied algorithm from Group.sortOnLayer as the + // number of declarations to be sorted is usually small. We may consider + // replacing this insertion sort with an efficient but stable merge sort + // or the like if many style declarations need to sorted. + var len:Number = decls.length; + var tmp:CSSStyleDeclaration; + + if (len <= 1) + return decls; + + for (var i:int = 1; i < len; i++) + { + for (var j:int = i; j > 0; j--) + { + if (decls[j].specificity < decls[j-1].specificity) + { + tmp = decls[j]; + decls[j] = decls[j-1]; + decls[j-1] = tmp; + } + else + { + break; + } + } + } + + return decls; + } + + /** + * @private + * Get the style manager of any object. If the object does not implement IFlexModule or + * is not of type StyleProxy, then the top-level style manager will be returned. + * + * @param object - Typed as Object because various interfaces are passed here. + * @return a style manager, will not be null. + */ + private static function getStyleManager(object:Object):IStyleManager2 + { + if (object is IFlexModule) + return StyleManager.getStyleManager(IFlexModule(object).moduleFactory); + else if (object is StyleProxy) + return getStyleManagerFromStyleProxy(StyleProxy(object)); + else + return StyleManager.getStyleManager(null); + } + + /** + * @private + * Get the style manager for a given StyleProxy object. + * + * @return a style manager, will not be null. + */ + private static function getStyleManagerFromStyleProxy(obj:StyleProxy):IStyleManager2 + { + // StyleProxy's usually have sources that are DisplayObject's, but a StyleProxy can also have + // another StyleProxy as it's source (Example: CalendarLayout's source is a StyleProxy for DateChooser, + // whose style is a StyleProxy for DateField) + var curObj:IStyleClient = obj; + while (curObj is StyleProxy) + { + curObj = StyleProxy(curObj).source; + } + + if (curObj is IFlexModule) + return StyleManager.getStyleManager(IFlexModule(curObj).moduleFactory); + + return StyleManager.getStyleManager(null); + } +} + +}
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/styles/metadata/ContainerBackgroundStyles.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/styles/metadata/ContainerBackgroundStyles.as index 7da71d7,0000000..adbe785 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/styles/metadata/ContainerBackgroundStyles.as +++ b/frameworks/projects/MX/src/main/flex/mx/styles/metadata/ContainerBackgroundStyles.as @@@ -1,65 -1,0 +1,65 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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. +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * Alpha level of the color defined by the <code>backgroundColor</code> + * property, of the image or SWF file defined by the <code>backgroundImage</code> + * style. + * Valid values range from 0.0 to 1.0. For most controls, the default value is 1.0, + * but for ToolTip controls, the default value is 0.95 and for Alert controls, the default value is 0.9. + * + * @default 1.0 + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +[Style(name="backgroundAlpha", type="Number", inherit="no", theme="halo, spark, mobile")] + +/** + * Background color of a component. + * You can have both a <code>backgroundColor</code> and a + * <code>backgroundImage</code> set. + * Some components do not have a background. + * The DataGrid control ignores this style. + * The default value is <code>undefined</code>, which means it is not set. + * If both this style and the <code>backgroundImage</code> style + * are <code>undefined</code>, the component has a transparent background. + * + * <p>For the Application container, this style specifies the background color + * while the application loads, and a background gradient while it is running. + * Flex calculates the gradient pattern between a color slightly darker than + * the specified color, and a color slightly lighter than the specified color.</p> + * + * <p>The default skins of most Flex controls are partially transparent. As a result, the background color of + * a container partially "bleeds through" to controls that are in that container. You can avoid this by setting the + * alpha values of the control's <code>fillAlphas</code> property to 1, as the following example shows: + * <pre> + * <mx:<i>Container</i> backgroundColor="0x66CC66"/> + * <mx:<i>ControlName</i> ... fillAlphas="[1,1]"/> + * </mx:<i>Container</i>></pre> + * </p> + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ - [Style(name="backgroundColor", type="uint", format="Color", inherit="no", theme="halo, spark, mobile")] ++[Style(name="backgroundColor", type="uint", format="Color", inherit="no", theme="halo, spark, mobile")] http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/utils/DensityUtil.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/utils/DensityUtil.as index e80bad5,0000000..7fb27e0 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/utils/DensityUtil.as +++ b/frameworks/projects/MX/src/main/flex/mx/utils/DensityUtil.as @@@ -1,98 -1,0 +1,98 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.utils +{ +import mx.core.DPIClassification; +import mx.core.RuntimeDPIProvider; +import mx.core.Singleton; + +[ExcludeClass] + +/** + * The <code>DensityUtil</code> class is an all-static class with methods for working with + * density within Flex. + * + * Flex uses this class to calculate the scaling factor when automatic density + * scaling is enabled for the <code>Application</code>. + * + * @see mx.core.DPIClassification + * @see spark.components.Application#applicationDPI + */ +public class DensityUtil +{ + /** + * Cached runtimeDPI value, which is computed from the runtimeDPIProvider class. + */ + private static var runtimeDPI:Number; + + /** + * Returns the current runtimeDPI value which is calculated by + * an instance of the runtimeDPIProvider class. + * If a runtimeDPIProvider class is not provided to the Application, + * Flex uses the default class, RuntimeDPIProvider. + * + * @see #getDPIScale + * @see mx.core.RuntimeDPIProvider + */ + public static function getRuntimeDPI():Number + { + if (!isNaN(runtimeDPI)) + return runtimeDPI; + + var runtimeDPIProviderClass:Class = Singleton.getClass("mx.core::RuntimeDPIProvider"); + + // Default to RuntimeDPIProvider + if (!runtimeDPIProviderClass) + runtimeDPIProviderClass = RuntimeDPIProvider; + + var instance:RuntimeDPIProvider = RuntimeDPIProvider(new runtimeDPIProviderClass()); + runtimeDPI = instance.runtimeDPI; + + return runtimeDPI; + } + + /** + * Calculates a scale factor to be used when element authored for + * <code>sourceDPI</code> is rendered at <code>targetDPI</code>. + * + * @param sourceDPI The <code>DPIClassification</code> dpi value for which + * a resource is optimized. + * + * @param targetDPI The <code>DPIClassification</code> dpi value at + * which a resource is rendered. + * + * @return The scale factor to be applied to the resource at render time. + * + * @see #getRuntimeDPI + * @see mx.core.DPIClassification + */ + public static function getDPIScale(sourceDPI:Number, targetDPI:Number):Number + { + // Unknown dpi returns NaN + if ((sourceDPI != DPIClassification.DPI_120 && sourceDPI != DPIClassification.DPI_160 && sourceDPI != DPIClassification.DPI_240 && sourceDPI != DPIClassification.DPI_320 && sourceDPI != DPIClassification.DPI_480 && sourceDPI != DPIClassification.DPI_640) || + (targetDPI != DPIClassification.DPI_120 && targetDPI != DPIClassification.DPI_160 && targetDPI != DPIClassification.DPI_240 && targetDPI != DPIClassification.DPI_320 && targetDPI != DPIClassification.DPI_480 && targetDPI != DPIClassification.DPI_640)) + { + return NaN; + } + + return targetDPI / sourceDPI; + } +} - } ++} http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/utils/DescribeTypeCacheRecord.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/utils/DescribeTypeCacheRecord.as index 5572500,0000000..26ad70b mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/utils/DescribeTypeCacheRecord.as +++ b/frameworks/projects/MX/src/main/flex/mx/utils/DescribeTypeCacheRecord.as @@@ -1,164 -1,0 +1,164 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.utils +{ + +import org.apache.flex.utils.Proxy; +import org.apache.flex.reflection.TypeDefinition; - COMPILE::AS3 ++COMPILE::SWF +{ +import flash.utils.flash_proxy; +use namespace flash_proxy; +} + +[ExcludeClass] + +/** + * @private + * This class represents a single cache entry, this gets created + * as part of the <code>describeType</code> method call on the + * <code>DescribeTypeCache</code> class. + * @flexjsignoreimport mx.utils.DescribeTypeCache + */ + +public dynamic class DescribeTypeCacheRecord extends Proxy +{ + //-------------------------------------------------------------------------- + // + // Class variables + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + private var cache:Object = {}; + + //-------------------------------------------------------------------------- + // + // Class properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // typeDescription + //---------------------------------- + + /** + * @private + */ + public var typeDescription:TypeDefinition; + + //---------------------------------- + // typeName + //---------------------------------- + + /** + * @private + */ + public var typeName:String; + + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + public function DescribeTypeCacheRecord() + { + super(); + } + + //-------------------------------------------------------------------------- + // + // Overridden methods + // + //-------------------------------------------------------------------------- + + /** + * @private + */ - COMPILE::AS3 ++ COMPILE::SWF + override flash_proxy function getProperty(name:*):* + { + var result:* = cache[name]; + + if (result === undefined) + { + result = DescribeTypeCache.extractValue(name, this); + cache[name] = result; + } + + return result; + } + COMPILE::JS + override public function getProperty(name:String):* + { + var result:* = cache[name]; + + if (result === undefined) + { + result = DescribeTypeCache.extractValue(name, this); + cache[name] = result; + } + + return result; + } + + + /** + * @private + */ - COMPILE::AS3 ++ COMPILE::SWF + override flash_proxy function hasProperty(name:*):Boolean + { + if (name in cache) + return true; + + var value:* = DescribeTypeCache.extractValue(name, this); + + if (value === undefined) + return false; + + cache[name] = value; + + return true; + } + COMPILE::JS + override public function hasProperty(name:String):Boolean + { + if (name in cache) + return true; + + var value:* = DescribeTypeCache.extractValue(name, this); + + if (value === undefined) + return false; + + cache[name] = value; + + return true; + } +} + +} http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/utils/GraphicsUtil.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/utils/GraphicsUtil.as index c366553,0000000..e1be742 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/utils/GraphicsUtil.as +++ b/frameworks/projects/MX/src/main/flex/mx/utils/GraphicsUtil.as @@@ -1,305 -1,0 +1,305 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.utils +{ + - COMPILE::AS3 ++COMPILE::SWF +{ + import flash.display.Graphics; +} +COMPILE::JS +{ + import flex.display.Graphics; +} + +/** + * The Graphics class is an all-static class with utility methods + * related to the Graphics class. + * You do not create instances of GraphicsUtil; + * instead you simply call methods such as the + * <code>GraphicsUtil.drawRoundRectComplex()</code> method. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +public class GraphicsUtil +{ + include "../core/Version.as"; + + //-------------------------------------------------------------------------- + // + // Class methods + // + //-------------------------------------------------------------------------- + + /** + * Draws a rounded rectangle using the size of a radius to draw the rounded corners. + * You must set the line style, fill, or both + * on the Graphics object before + * you call the <code>drawRoundRectComplex()</code> method + * by calling the <code>linestyle()</code>, + * <code>lineGradientStyle()</code>, <code>beginFill()</code>, + * <code>beginGradientFill()</code>, or + * <code>beginBitmapFill()</code> method. + * + * @param graphics The Graphics object that draws the rounded rectangle. + * + * @param x The horizontal position relative to the + * registration point of the parent display object, in pixels. + * + * @param y The vertical position relative to the + * registration point of the parent display object, in pixels. + * + * @param width The width of the round rectangle, in pixels. + * + * @param height The height of the round rectangle, in pixels. + * + * @param topLeftRadius The radius of the upper-left corner, in pixels. + * + * @param topRightRadius The radius of the upper-right corner, in pixels. + * + * @param bottomLeftRadius The radius of the bottom-left corner, in pixels. + * + * @param bottomRightRadius The radius of the bottom-right corner, in pixels. + * + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public static function drawRoundRectComplex(graphics:Graphics, x:Number, y:Number, + width:Number, height:Number, + topLeftRadius:Number, topRightRadius:Number, + bottomLeftRadius:Number, bottomRightRadius:Number):void + { + var xw:Number = x + width; + var yh:Number = y + height; + + // Make sure none of the radius values are greater than w/h. + // These are all inlined to avoid function calling overhead + var minSize:Number = width < height ? width * 2 : height * 2; + topLeftRadius = topLeftRadius < minSize ? topLeftRadius : minSize; + topRightRadius = topRightRadius < minSize ? topRightRadius : minSize; + bottomLeftRadius = bottomLeftRadius < minSize ? bottomLeftRadius : minSize; + bottomRightRadius = bottomRightRadius < minSize ? bottomRightRadius : minSize; + + // Math.sin and Math,tan values for optimal performance. + // Math.rad = Math.PI / 180 = 0.0174532925199433 + // r * Math.sin(45 * Math.rad) = (r * 0.707106781186547); + // r * Math.tan(22.5 * Math.rad) = (r * 0.414213562373095); + // + // We can save further cycles by precalculating + // 1.0 - 0.707106781186547 = 0.292893218813453 and + // 1.0 - 0.414213562373095 = 0.585786437626905 + + // bottom-right corner + var a:Number = bottomRightRadius * 0.292893218813453; // radius - anchor pt; + var s:Number = bottomRightRadius * 0.585786437626905; // radius - control pt; + graphics.moveTo(xw, yh - bottomRightRadius); + graphics.curveTo(xw, yh - s, xw - a, yh - a); + graphics.curveTo(xw - s, yh, xw - bottomRightRadius, yh); + + // bottom-left corner + a = bottomLeftRadius * 0.292893218813453; + s = bottomLeftRadius * 0.585786437626905; + graphics.lineTo(x + bottomLeftRadius, yh); + graphics.curveTo(x + s, yh, x + a, yh - a); + graphics.curveTo(x, yh - s, x, yh - bottomLeftRadius); + + // top-left corner + a = topLeftRadius * 0.292893218813453; + s = topLeftRadius * 0.585786437626905; + graphics.lineTo(x, y + topLeftRadius); + graphics.curveTo(x, y + s, x + a, y + a); + graphics.curveTo(x + s, y, x + topLeftRadius, y); + + // top-right corner + a = topRightRadius * 0.292893218813453; + s = topRightRadius * 0.585786437626905; + graphics.lineTo(xw - topRightRadius, y); + graphics.curveTo(xw - s, y, xw - a, y + a); + graphics.curveTo(xw, y + s, xw, y + topRightRadius); + graphics.lineTo(xw, yh - bottomRightRadius); + } + + /** + * Draws a rounded rectangle using the size of individual x and y radii to + * draw the rounded corners. + * You must set the line style, fill, or both + * on the Graphics object before + * you call the <code>drawRoundRectComplex2()</code> method + * by calling the <code>linestyle()</code>, + * <code>lineGradientStyle()</code>, <code>beginFill()</code>, + * <code>beginGradientFill()</code>, or + * <code>beginBitmapFill()</code> method. + * + * @param graphics The Graphics object that draws the rounded rectangle. + * + * @param x The horizontal position relative to the + * registration point of the parent display object, in pixels. + * + * @param y The vertical position relative to the + * registration point of the parent display object, in pixels. + * + * @param width The width of the round rectangle, in pixels. + * + * @param height The height of the round rectangle, in pixels. + * + * @param radiusX The default radiusX to use, if corner-specific values are not specified. + * This value must be specified. + * + * @param radiusY The default radiusY to use, if corner-specific values are not specified. + * If 0, the value of radiusX is used. + * + * @param topLeftRadiusX The x radius of the upper-left corner, in pixels. If NaN, + * the value of radiusX is used. + * + * @param topLeftRadiusY The y radius of the upper-left corner, in pixels. If NaN, + * the value of topLeftRadiusX is used. + * + * @param topRightRadiusX The x radius of the upper-right corner, in pixels. If NaN, + * the value of radiusX is used. + * + * @param topRightRadiusY The y radius of the upper-right corner, in pixels. If NaN, + * the value of topRightRadiusX is used. + * + * @param bottomLeftRadiusX The x radius of the bottom-left corner, in pixels. If NaN, + * the value of radiusX is used. + * + * @param bottomLeftRadiusY The y radius of the bottom-left corner, in pixels. If NaN, + * the value of bottomLeftRadiusX is used. + * + * @param bottomRightRadiusX The x radius of the bottom-right corner, in pixels. If NaN, + * the value of radiusX is used. + * + * @param bottomRightRadiusY The y radius of the bottom-right corner, in pixels. If NaN, + * the value of bottomRightRadiusX is used. + * + * + * @langversion 3.0 + * @playerversion Flash 10 + * @playerversion AIR 1.5 + * @productversion Flex 4 + */ + public static function drawRoundRectComplex2(graphics:Graphics, x:Number, y:Number, + width:Number, height:Number, + radiusX:Number, radiusY:Number, + topLeftRadiusX:Number, topLeftRadiusY:Number, + topRightRadiusX:Number, topRightRadiusY:Number, + bottomLeftRadiusX:Number, bottomLeftRadiusY:Number, + bottomRightRadiusX:Number, bottomRightRadiusY:Number):void + { + var xw:Number = x + width; + var yh:Number = y + height; + var maxXRadius:Number = width / 2; + var maxYRadius:Number = height / 2; + + // Rules for determining radius for each corner: + // - If explicit nnnRadiusX value is set, use it. Otherwise use radiusX. + // - If explicit nnnRadiusY value is set, use it. Otherwise use corresponding nnnRadiusX. + if (radiusY == 0) + radiusY = radiusX; + if (isNaN(topLeftRadiusX)) + topLeftRadiusX = radiusX; + if (isNaN(topLeftRadiusY)) + topLeftRadiusY = topLeftRadiusX; + if (isNaN(topRightRadiusX)) + topRightRadiusX = radiusX; + if (isNaN(topRightRadiusY)) + topRightRadiusY = topRightRadiusX; + if (isNaN(bottomLeftRadiusX)) + bottomLeftRadiusX = radiusX; + if (isNaN(bottomLeftRadiusY)) + bottomLeftRadiusY = bottomLeftRadiusX; + if (isNaN(bottomRightRadiusX)) + bottomRightRadiusX = radiusX; + if (isNaN(bottomRightRadiusY)) + bottomRightRadiusY = bottomRightRadiusX; + + // Pin radius values to half of the width/height + if (topLeftRadiusX > maxXRadius) + topLeftRadiusX = maxXRadius; + if (topLeftRadiusY > maxYRadius) + topLeftRadiusY = maxYRadius; + if (topRightRadiusX > maxXRadius) + topRightRadiusX = maxXRadius; + if (topRightRadiusY > maxYRadius) + topRightRadiusY = maxYRadius; + if (bottomLeftRadiusX > maxXRadius) + bottomLeftRadiusX = maxXRadius; + if (bottomLeftRadiusY > maxYRadius) + bottomLeftRadiusY = maxYRadius; + if (bottomRightRadiusX > maxXRadius) + bottomRightRadiusX = maxXRadius; + if (bottomRightRadiusY > maxYRadius) + bottomRightRadiusY = maxYRadius; + + // Math.sin and Math,tan values for optimal performance. + // Math.rad = Math.PI / 180 = 0.0174532925199433 + // r * Math.sin(45 * Math.rad) = (r * 0.707106781186547); + // r * Math.tan(22.5 * Math.rad) = (r * 0.414213562373095); + // + // We can save further cycles by precalculating + // 1.0 - 0.707106781186547 = 0.292893218813453 and + // 1.0 - 0.414213562373095 = 0.585786437626905 + + // bottom-right corner + var aX:Number = bottomRightRadiusX * 0.292893218813453; // radius - anchor pt; + var aY:Number = bottomRightRadiusY * 0.292893218813453; // radius - anchor pt; + var sX:Number = bottomRightRadiusX * 0.585786437626905; // radius - control pt; + var sY:Number = bottomRightRadiusY * 0.585786437626905; // radius - control pt; + graphics.moveTo(xw, yh - bottomRightRadiusY); + graphics.curveTo(xw, yh - sY, xw - aX, yh - aY); + graphics.curveTo(xw - sX, yh, xw - bottomRightRadiusX, yh); + + // bottom-left corner + aX = bottomLeftRadiusX * 0.292893218813453; + aY = bottomLeftRadiusY * 0.292893218813453; + sX = bottomLeftRadiusX * 0.585786437626905; + sY = bottomLeftRadiusY * 0.585786437626905; + graphics.lineTo(x + bottomLeftRadiusX, yh); + graphics.curveTo(x + sX, yh, x + aX, yh - aY); + graphics.curveTo(x, yh - sY, x, yh - bottomLeftRadiusY); + + // top-left corner + aX = topLeftRadiusX * 0.292893218813453; + aY = topLeftRadiusY * 0.292893218813453; + sX = topLeftRadiusX * 0.585786437626905; + sY = topLeftRadiusY * 0.585786437626905; + graphics.lineTo(x, y + topLeftRadiusY); + graphics.curveTo(x, y + sY, x + aX, y + aY); + graphics.curveTo(x + sX, y, x + topLeftRadiusX, y); + + // top-right corner + aX = topRightRadiusX * 0.292893218813453; + aY = topRightRadiusY * 0.292893218813453; + sX = topRightRadiusX * 0.585786437626905; + sY = topRightRadiusY * 0.585786437626905; + graphics.lineTo(xw - topRightRadiusX, y); + graphics.curveTo(xw - sX, y, xw - aX, y + aY); + graphics.curveTo(xw, y + sY, xw, y + topRightRadiusY); + graphics.lineTo(xw, yh - bottomRightRadiusY); + } +} + +} http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/77148f4a/frameworks/projects/MX/src/main/flex/mx/utils/IXMLNotifiable.as ---------------------------------------------------------------------- diff --cc frameworks/projects/MX/src/main/flex/mx/utils/IXMLNotifiable.as index 0ca48bc,0000000..8826dd0 mode 100644,000000..100644 --- a/frameworks/projects/MX/src/main/flex/mx/utils/IXMLNotifiable.as +++ b/frameworks/projects/MX/src/main/flex/mx/utils/IXMLNotifiable.as @@@ -1,43 -1,0 +1,43 @@@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.utils +{ + +/** + * The IXMLNotifiable interface. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ +public interface IXMLNotifiable +{ + /** + * @private + */ + function xmlNotification(currentTarget:Object, + type:String, + target:Object, + value:Object, + detail:Object):void; +} + - } ++}
