| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 flashx.textLayout.property |
| { |
| import flashx.textLayout.debug.assert; |
| import flashx.textLayout.elements.GlobalSettings; |
| import flashx.textLayout.formats.FormatValue; |
| import flashx.textLayout.tlf_internal; |
| |
| [ExcludeClass] |
| /** Base class of property metadata. Each property in the various TextLayout attributes structures has a metadata singletion Property class instance. The instance |
| * can be used to process the property to and from xml, find out range information and help with the attribute cascade. The Property class also contains static functions |
| * for processing all the properties collected in a TextLayout Format object. @private */ |
| public class Property |
| { |
| public static var errorHandler:Function = defaultErrorHandler; |
| public static function defaultErrorHandler(p:Property,value:Object):void |
| { |
| throw(new RangeError(createErrorString(p,value))); |
| } |
| public static function createErrorString(p:Property,value:Object):String |
| { |
| return GlobalSettings.resourceStringFunction("badPropertyValue",[ p.name, value.toString() ]) |
| } |
| |
| /** not yet enabled. @private */ |
| public const NO_LIMITS:String ="noLimits"; |
| /** not yet enabled. @private */ |
| public const LOWER_LIMIT:String ="lowerLimit"; |
| /** not yet enabled. @private */ |
| public const UPPER_LIMIT:String = "upperLimit"; |
| /** not yet enabled. @private */ |
| public const ALL_LIMITS:String = "allLimits"; |
| |
| // storing name here is redundant but is more efficient |
| private var _name:String; |
| private var _default:Object; |
| private var _inherited:Boolean; |
| private var _limits:String; |
| private var _category:String; |
| |
| /** @private */ |
| tlf_internal static const inheritHashValue:uint = 314159; |
| |
| /** Initializer. Each property has a name and a default. */ |
| public function Property(nameValue:String,defaultValue:Object,inherited:Boolean,category:String) |
| { |
| _name = nameValue; |
| _default = defaultValue; |
| _limits = ALL_LIMITS; |
| _inherited = inherited; |
| _category = category; |
| } |
| |
| /** not yet enabled. @private */ |
| protected function checkLowerLimit():Boolean |
| { return _limits == ALL_LIMITS || _limits == LOWER_LIMIT; } |
| |
| /** not yet enabled. @private */ |
| protected function checkUpperLimit():Boolean |
| { return _limits == ALL_LIMITS || _limits == LOWER_LIMIT; } |
| |
| /** The name of the property */ |
| public function get name():String |
| { return _name; } |
| |
| /** The default value of this property */ |
| public function get defaultValue():Object |
| { return _default; } |
| |
| /** Is this property inherited */ |
| public function get inherited():Object |
| { return _inherited; } |
| |
| /** Category of this property. */ |
| public function get category():String |
| { return _category; } |
| |
| /** Helper function when setting the property */ |
| public function setHelper(currVal:*,newVal:*):* |
| { |
| if (newVal === null) |
| newVal = undefined; |
| |
| return newVal; |
| } |
| |
| /** Helper function when merging the property to compute actual attributes */ |
| public function concatInheritOnlyHelper(currVal:*,concatVal:*):* |
| { |
| return (_inherited && currVal === undefined) || currVal == FormatValue.INHERIT ? concatVal : currVal; |
| } |
| /** Helper function when merging the property to compute actual attributes */ |
| public function concatHelper(currVal:*,concatVal:*):* |
| { |
| if (_inherited) |
| return currVal === undefined || currVal == FormatValue.INHERIT ? concatVal : currVal; |
| if (currVal === undefined) |
| return defaultValue; |
| return currVal == FormatValue.INHERIT ? concatVal : currVal; |
| } |
| |
| /** Helper function when comparing the property */ |
| public function equalHelper(v1:*,v2:*):Boolean |
| { return v1 == v2; } |
| |
| /** Convert the value of this property to a string appropriate for XML export */ |
| public function toXMLString(val:Object):String |
| { |
| return val.toString(); |
| } |
| |
| /** Get the hash of the property value |
| * @param val the property value |
| * @param seed seed value for the hash algorithm |
| * @return the hash of the property value |
| */ |
| public function hash(val:Object, seed:uint):uint |
| { |
| return 0; |
| } |
| |
| // ///////////////////////////////////////////// |
| // Following static functions are used by Format classes to |
| // perform functions that iterate over all the attributes. |
| // They are driven by the attributes metadata object that contains |
| // definitions for all the properties. |
| // ///////////////////////////////////////////// |
| |
| /** Helper function to initialize all property values from defaults. */ |
| static public function defaultsAllHelper(description:Object,current:Object):void |
| { |
| for each (var prop:Property in description) |
| current[prop.name] = prop.defaultValue; |
| } |
| |
| /** Helper function to compare two sets of properties. */ |
| static public function equalAllHelper(description:Object,p1:Object,p2:Object):Boolean |
| { |
| if (p1 == p2) |
| return true; |
| // these could be "equal" if all attributes of p1 or p2 are null |
| if (p1 == null || p2 == null) |
| return false; |
| for each (var prop:Property in description) |
| { |
| var name:String = prop.name; |
| if (!(prop.equalHelper(p1[name],p2[name]))) |
| return false; |
| } |
| return true; |
| } |
| |
| static public function extractInCategory(formatClass:Class,description:Object,props:Object,category:String):Object |
| { |
| var rslt:Object = null; |
| for each (var prop:Property in description) |
| { |
| if (prop.category == category && props[prop.name] != null) |
| { |
| if (rslt == null) |
| rslt = new formatClass(); |
| rslt[prop.name] = props[prop.name]; |
| } |
| } |
| return rslt; |
| } |
| /** @private */ |
| static public function shallowCopy(src:Object):Object |
| { |
| // make a shallow copy |
| var rslt:Object = new Object() |
| for (var val:Object in src) |
| rslt[val] = src[val]; |
| return rslt; |
| } |
| |
| static private const nullStyleObject:Object = new Object(); |
| /** @private */ |
| static public function equalStyleObjects(o1:Object,o2:Object):Boolean |
| { |
| if (o1 == null) |
| o1 = nullStyleObject; |
| if (o2 == null) |
| o2 = nullStyleObject; |
| var o1len:int = 0; |
| // compare property values and count o1len |
| for (var val:Object in o1) |
| { |
| CONFIG::debug { assert(!(o1[val] is Array) && !(o2[val] is Array),"Arrays as user styles not supported"); } |
| if (o1[val] != o2[val]) |
| return false; // different |
| o1len++; |
| } |
| var o2len:int = 0; |
| for (val in o2) |
| o2len++; |
| // matching keys from o1 to o2. return equal if they both have the same length |
| return o1len == o2len; |
| } |
| |
| /** @private */ |
| static public function equalCoreStyles(o1:Object,o2:Object,description:Object):Boolean |
| { |
| if (o1 == null) |
| o1 = nullStyleObject; |
| if (o2 == null) |
| o2 = nullStyleObject; |
| var o1len:int = 0; |
| // compare property values and count o1len |
| for (var val:String in o1) |
| { |
| var o1val:Object = o1[val]; |
| var o2val:Object = o2[val]; |
| if (o1val != o2val) |
| { |
| if (!(o1val is Array) || !(o2val is Array) || o1val.length != o2val.length) |
| return false; // different |
| var valClass:Class = description[val].memberType; |
| if (!Property.equalAllHelper(valClass.tlf_internal::description,o1val,o2val)) |
| return false; |
| } |
| o1len++; |
| } |
| var o2len:int = 0; |
| for (val in o2) |
| o2len++; |
| // matching keys from o1 to o2. return equal if they both have the same length |
| return o1len == o2len; |
| } |
| } |
| } |