blob: 090e892265acb64961d61e890b60234e44072f53 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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.formats.FormatValue;
import flashx.textLayout.tlf_internal;
use namespace tlf_internal;
[ExcludeClass]
/** A property description with an Array value.@private */
public class ArrayProperty extends Property
{
private var _memberType:Class;
public function ArrayProperty(nameValue:String, defaultValue:Array, inherited:Boolean, categories:Vector.<String>, mType:Class)
{
super(nameValue, defaultValue, inherited, categories);
_memberType = mType;
CONFIG::debug { assert(_memberType.description != null,"Array member class must have description"); }
// can defaultValue be INHERIT?
CONFIG::debug { assert(checkArrayTypes(defaultValue),"Array has bad defaultValue"); }
}
/** The type the members of the array are required to be. */
public function get memberType():Class
{ return _memberType; }
protected function checkArrayTypes(val:Object):Boolean
{
if (val == null)
return true;
if (!(val is Array))
return false;
if (_memberType == null)
return true;
for each (var obj:Object in (val as Array))
{
if (!(obj is _memberType))
return false
}
return true;
}
/** @private */
public override function get defaultValue():*
{ return super.defaultValue == null ? null : (super.defaultValue as Array).slice(); }
/** @private */
public override function setHelper(currVal:*,newVal:*):*
{
if (newVal === null)
newVal = undefined;
if (newVal == undefined || newVal == FormatValue.INHERIT)
return newVal;
if (newVal is String)
newVal = this.valueFromString(String(newVal));
if (!checkArrayTypes(newVal))
{
Property.errorHandler(this,newVal);
return currVal;
}
return (newVal as Array).slice();
}
/** @private */
public override function concatInheritOnlyHelper(currVal:*,concatVal:*):*
{
return (inherited && currVal === undefined) || currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
}
/** @private */
public override function concatHelper(currVal:*,concatVal:*):*
{
if (inherited)
return currVal === undefined || currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
if (currVal === undefined)
return defaultValue;
return currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
}
/** @private */
public override function equalHelper(v1:*,v2:*):Boolean
{
if (_memberType != null)
{
var v1Array:Array = v1 as Array;
var v2Array:Array = v2 as Array;
if (v1Array && v2Array)
{
if (v1Array.length == v2Array.length)
{
var desc:Object = _memberType.description;
for (var i:int=0; i < v1Array.length; ++i)
{
if (!Property.equalAllHelper(desc, v1[i], v2[i]))
return false;
}
return true;
}
}
}
return v1 == v2;
}
/** @private */
public override function toXMLString(val:Object):String
{
if (val == FormatValue.INHERIT)
return String(val);
// TODO-7/7/2008-The XML format for array properties (as implemented below)
// is appropriate for what it is currently used, but can be ambiguous.
// For example, what if XML representations of contained elements contain the delimiters used here?
// TODO: Check for description?
var desc:Object = _memberType.description;
var rslt:String = "";
var addSemi:Boolean = false;
for each (var member:Object in val)
{
if (addSemi)
rslt += "; "
// export each element ',' separated
var addComma:Boolean = false;
for each (var prop:Property in desc)
{
var val:Object = member[prop.name];
if (val != null)
{
if (addComma)
rslt += ", ";
rslt += prop.name + ":" + prop.toXMLString(val);
addComma = true;
}
}
addSemi = true;
}
return rslt;
}
/** @private */
private function valueFromString(str:String):*
{
// TODO-7/7/2008-The XML format for array properties can be ambiguous.
// See comment in toXMLString.
if ((str == null) || (str == ""))
return null;
if (str == FormatValue.INHERIT)
return str;
var result:Array = new Array();
var desc:Object = _memberType.description;
var attrsAll:Array = str.split('; ');
for each (var attrs:String in attrsAll)
{
var obj:Object = new _memberType(); // NO PMD
var attrsOne:Array = attrs.split(', ');
for each (var attr:String in attrsOne)
{
var nameValArr:Array = attr.split(':');
var propName:String = nameValArr[0];
var propVal:String = nameValArr[1];
for each (var prop:Property in desc)
{
if (prop.name == propName)
{
obj[propName] = prop.setHelper(propVal,obj[propName]);
break;
}
}
}
result.push(obj);
}
return result;
}
}
}