blob: 1b560f5988ad9545ac111ab8d003797e54edf288 [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
{
import flash.utils.Dictionary;
import flashx.textLayout.elements.FlowElement;
import flashx.textLayout.elements.FlowGroupElement;
import flashx.textLayout.elements.IFormatResolver;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.formats.ITextLayoutFormat;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.property.Property;
import flashx.textLayout.tlf_internal;
use namespace tlf_internal;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
import mx.styles.IStyleManager2;
/** This version hands back a style on demand from the dictinoary.
* Another way to do it would be to "redo" the cascade top down.
*/
public class FlexStyleResolver implements IFormatResolver
{
private var _formatCache:Dictionary;
private var _styleManager:IStyleManager2;
static public var classToNameDictionary:Object = { "SpanElement":"flashx.textLayout.elements.span", "ParagraphElement":"flashx.textLayout.elements.p", "TextFlow":"flashx.textLayout.elements.TextFlow", "DivElement":"flashx.textLayout.elements.div" }
/** Create a flex style resolver.
* @param ignoreGlobal - don't use global settings.
*/
public function FlexStyleResolver(styleManager:IStyleManager2):void
{
// cache results
_formatCache = new Dictionary(true);
_styleManager = styleManager;
}
private function addStyleAttributes(attr:TextLayoutFormat, styleSelector:String):TextLayoutFormat
{
var foundStyle:CSSStyleDeclaration = _styleManager.getStyleDeclaration(styleSelector);
if (foundStyle)
{
for each (var prop:Property in TextLayoutFormat.description)
{
var propStyle:Object = foundStyle.getStyle(prop.name);
if (propStyle)
{
if (attr == null)
attr = new TextLayoutFormat();
attr[prop.name] = propStyle;
}
}
}
return attr;
}
public function resolveFormat(elem:Object):ITextLayoutFormat
{
// trace("flowStyleResolver");
// lookup in the cache
var attr:TextLayoutFormat = _formatCache[elem];
if (attr !== null)
return attr;
// global on TextFlow only
if (elem is FlowElement)
{
// maps ParagraphElement to p, SpanElement to span etc.
var elemClassName:String = flash.utils.getQualifiedClassName(elem);
elemClassName = elemClassName.substr(elemClassName.lastIndexOf(":")+1)
var dictionaryName:String = FlexStyleResolver.classToNameDictionary[elemClassName] ;
attr = addStyleAttributes(attr, dictionaryName ? dictionaryName : elemClassName);
if (elem.styleName != null)
attr = addStyleAttributes(attr, "." + elem.styleName);
if (elem.id != null)
attr = addStyleAttributes(attr, "#" + elem.id);
_formatCache[elem] = attr;
}
// else if elem is ContainerController inherit via the container?
return attr;
}
public function resolveUserFormat(elem:Object,userStyle:String):*
{
var flowElem:FlowElement = elem as FlowElement;
var cssStyle:CSSStyleDeclaration;
var propStyle:*;
// support non-tlf styles
if (flowElem)
{
if (flowElem.id)
{
cssStyle = _styleManager.getStyleDeclaration("#"+flowElem.id);
if (cssStyle)
{
propStyle = cssStyle.getStyle(userStyle);
if (propStyle !== undefined)
return propStyle;
}
}
if (flowElem.styleName)
{
cssStyle = _styleManager.getStyleDeclaration("."+flowElem.styleName);
if (cssStyle)
{
propStyle = cssStyle.getStyle(userStyle);
if (propStyle !== undefined)
return propStyle;
}
}
var elemClassName:String = flash.utils.getQualifiedClassName(flowElem);
elemClassName = elemClassName.substr(elemClassName.lastIndexOf(":")+1)
var dictionaryName:String = classToNameDictionary[elemClassName];
cssStyle = _styleManager.getStyleDeclaration(dictionaryName == null ? elemClassName : dictionaryName);
if (cssStyle)
{
propStyle = cssStyle.getStyle(userStyle);
if (propStyle !== undefined)
return propStyle;
}
}
return undefined;
}
public function invalidateAll(tf:TextFlow):void
{
_formatCache = new Dictionary(true); // clears the cache
}
// id and styleName don't need to descend now do they - this could conditionally descend on the change type.
public function invalidate(target:Object):void
{
delete _formatCache[target];
var blockElem:FlowGroupElement = target as FlowGroupElement;
if (blockElem)
{
for (var idx:int = 0; idx < blockElem.numChildren; idx++)
invalidate(blockElem.getChildAt(idx));
}
}
// these are sharable between TextFlows
public function getResolverForNewFlow(oldFlow:TextFlow,newFlow:TextFlow):IFormatResolver
{ return this; }
}
}