blob: 8d1903bf70f7c9c8aa6c387bf98ff14c6b7790a5 [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.elements.ListElement;
import flashx.textLayout.tlf_internal;
use namespace tlf_internal;
[ExcludeClass]
public class CounterContentHandler extends PropertyHandler
{
// check to see if this handler has a custom exporter that must be used when owningHandlerCheck is true
public override function get customXMLStringHandler():Boolean
{ return true; }
public override function toXMLString(val:Object):String
{
if (val.hasOwnProperty("counter"))
return val.ordered == null ? "counter(ordered)" : "counter(ordered," + val.ordered + ")";
if (val.hasOwnProperty("counters"))
{
var rslt:String = "counters(ordered";
if (val.suffix != null)
{
rslt += ",\"" + val.suffix + "\"";
if (val.ordered)
rslt += "," + val.ordered;
}
rslt += ")"
return rslt;
}
return val.toString();
}
/** matches counter(ordered) */
static private const _counterContentPattern1:RegExp = /^\s*counter\s*\(\s*ordered\s*\)\s*$/;
/** matches counter(ordered,ListStyleType) */
static private const _counterContentPattern2:RegExp = /^\s*counter\s*\(\s*ordered\s*,\s*\S+\s*\)\s*$/;
/** matches counters(ordered) */
static private const _countersContentPattern1:RegExp = /^\s*counters\s*\(\s*ordered\s*\)\s*$/;
/** matches counters(ordered,"suffix") */
static private const _countersContentPattern2:RegExp = /^\s*counters\s*\(\s*ordered\s*,\s*".*"\s*\)\s*$/;
/** matches counters(ordered,"suffix",ListStyleType) */
static private const _countersContentPattern3:RegExp = /^\s*counters\s*\(\s*ordered\s*,\s*".*"\s*,\s*\S+\s*\)\s*$/;
// return a value if this handler "owns" this property - otherwise return undefined
public override function owningHandlerCheck(newVal:*):*
{
var listStyleType:String;
// check for the more efficient parsed representation
if (!(newVal is String))
return newVal.hasOwnProperty("counter") || newVal.hasOwnProperty("counters") ? newVal : undefined;
if (_counterContentPattern1.test(newVal))
return newVal;
if (_counterContentPattern2.test(newVal))
{
// need to validate the specified listStyleType
listStyleType = extractListStyleTypeFromCounter(newVal);
return ListElement.listSuffixes[listStyleType] !== undefined ? newVal : undefined;
}
if (_countersContentPattern1.test(newVal))
return newVal;
if (_countersContentPattern2.test(newVal))
return newVal;
if (_countersContentPattern3.test(newVal))
{
listStyleType = extractListStyleTypeFromCounters(newVal);
return ListElement.listSuffixes[listStyleType] !== undefined ? newVal : undefined;
}
return undefined;
}
static private const _counterBeginPattern:RegExp = /^\s*counter\s*\(\s*ordered\s*,\s*/g;
static private const _trailingStuff:RegExp = /\s*\)\s*/g
/** @private - from _counterContentPattern2 counters(ordered,"suffix") */
static tlf_internal function extractListStyleTypeFromCounter(s:String):String
{
CONFIG::debug { assert(_counterContentPattern2.test(s),"Bad Parameter to extractListStyleTypeFromCounter"); }
_counterBeginPattern.lastIndex = 0;
_counterBeginPattern.test(s);
s = s.substr(_counterBeginPattern.lastIndex);
_trailingStuff.lastIndex = 0;
_trailingStuff.test(s);
s = s.substr(0,_trailingStuff.lastIndex-1);
return s;
}
static private const _countersTillSuffixPattern:RegExp = /^\s*counters\s*\(\s*ordered\s*,\s*"/g;
static private const _afterSuffixPattern2:RegExp = /^"\s*\)\s*$/
/** @private - from _countersContentPattern2 */
static tlf_internal function extractSuffixFromCounters2(s:String):String
{
CONFIG::debug { assert(_countersContentPattern2.test(s),"Bad Parameter to extractListStyleTypeFromCounter2"); }
_countersTillSuffixPattern.lastIndex = 0;
_countersTillSuffixPattern.test(s);
s = s.substr(_countersTillSuffixPattern.lastIndex);
var rslt:String = "";
while (!_afterSuffixPattern2.test(s))
{
rslt += s.substr(0,1);
s = s.substr(1);
}
return rslt;
}
static private const _afterSuffixPattern3:RegExp = /^"\s*,\s*\S+\s*\)\s*$/
static tlf_internal function extractSuffixFromCounters3(s:String):String
{
CONFIG::debug { assert(_countersContentPattern3.test(s),"Bad Parameter to extractListStyleTypeFromCounter2"); }
_countersTillSuffixPattern.lastIndex = 0;
_countersTillSuffixPattern.test(s);
s = s.substr(_countersTillSuffixPattern.lastIndex);
var rslt:String = "";
while (!_afterSuffixPattern3.test(s))
{
rslt += s.substr(0,1);
s = s.substr(1);
}
return rslt;
}
static private const _countersTillListStyleTypePattern:RegExp = /^\s*counters\s*\(\s*ordered\s*,\s*".*"\s*,\s*/g;
/** @private - from _countersContentPattern2 */
static tlf_internal function extractListStyleTypeFromCounters(s:String):String
{
CONFIG::debug { assert(_countersContentPattern3.test(s),"Bad Parameter to extractListStyleTypeFromCounter"); }
_countersTillListStyleTypePattern.lastIndex = 0;
_countersTillListStyleTypePattern.test(s);
s = s.substr(_countersTillListStyleTypePattern.lastIndex);
_trailingStuff.lastIndex = 0;
_trailingStuff.test(s);
s = s.substr(0,_trailingStuff.lastIndex-1);
return s;
}
/** parse the input string and create a valid input value */
public override function setHelper(newVal:*):*
{
var s:String = newVal as String;
var listStyleType:String;
var suffix:String;
if (s == null)
return newVal; // assume its an object that's been parsed already
if (_counterContentPattern1.test(newVal))
return { counter:"ordered" };
if (_counterContentPattern2.test(newVal))
{
listStyleType = extractListStyleTypeFromCounter(newVal);
return { counter:"ordered", ordered:listStyleType };
}
if (_countersContentPattern1.test(newVal))
return { counters:"ordered" };
if (_countersContentPattern2.test(newVal))
{
suffix = extractSuffixFromCounters2(newVal);
return { counters:"ordered", suffix:suffix };
}
if (_countersContentPattern3.test(newVal))
{
listStyleType = extractListStyleTypeFromCounters(newVal);
suffix = extractSuffixFromCounters3(newVal);
return { counters:"ordered", suffix:suffix, ordered:listStyleType };
}
return undefined;
}
}
}