scaffold.libs_as.feathers.skins.StyleProviderRegistry.as Maven / Gradle / Ivy
/*
Feathers
Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved.
This program is free software. You can redistribute and/or modify it in
accordance with the terms of the accompanying license agreement.
*/
package feathers.skins
{
import flash.utils.Dictionary;
/**
* Used by themes to create and manage style providers for component classes.
*/
public class StyleProviderRegistry
{
/**
* @private
*/
protected static const GLOBAL_STYLE_PROVIDER_PROPERTY_NAME:String = "globalStyleProvider";
/**
* @private
*/
protected static function defaultStyleProviderFactory():IStyleProvider
{
return new StyleNameFunctionStyleProvider();
}
/**
* Constructor.
*
* If style providers are to be registered globally, they will be
* passed to the static globalStyleProvider
property of the
* specified class. If the class does not define a
* globalStyleProvider
property, an error will be thrown.
*
* The style provider factory function is expected to have the following
* signature:
* function():IStyleProvider
*
* @param registerGlobally Determines if the registry sets the static globalStyleProvider
property.
* @param styleProviderFactory An optional function that creates a new style provider. If null
, a StyleNameFunctionStyleProvider
will be created.
*/
public function StyleProviderRegistry(registerGlobally:Boolean = true, styleProviderFactory:Function = null)
{
this._registerGlobally = registerGlobally;
if(styleProviderFactory === null)
{
this._styleProviderFactory = defaultStyleProviderFactory;
}
else
{
this._styleProviderFactory = styleProviderFactory;
}
}
/**
* @private
*/
protected var _registerGlobally:Boolean;
/**
* @private
*/
protected var _styleProviderFactory:Function;
/**
* @private
*/
protected var _classToStyleProvider:Dictionary = new Dictionary(true);
/**
* Disposes the theme.
*/
public function dispose():void
{
//clear the global style providers, but only if they still match the
//ones that the theme created. a developer could replace the global
//style providers with different ones.
for(var untypedType:Object in this._classToStyleProvider)
{
var type:Class = Class(untypedType);
this.clearStyleProvider(type);
}
this._classToStyleProvider = null;
}
/**
* Creates an IStyleProvider
for the specified component
* class, or if it was already created, returns the existing registered
* style provider. If the registry is global, a newly created style
* provider will be passed to the static globalStyleProvider
* property of the specified class.
*
* @param forClass The style provider is registered for this class.
* @param styleProviderFactory A factory used to create the style provider.
*/
public function getStyleProvider(forClass:Class):IStyleProvider
{
this.validateComponentClass(forClass);
var styleProvider:IStyleProvider = IStyleProvider(this._classToStyleProvider[forClass]);
if(!styleProvider)
{
styleProvider = this._styleProviderFactory();
this._classToStyleProvider[forClass] = styleProvider;
if(this._registerGlobally)
{
forClass[GLOBAL_STYLE_PROVIDER_PROPERTY_NAME] = styleProvider;
}
}
return styleProvider;
}
/**
* Removes the style provider for the specified component class. If the
* registry is global, and the static globalStyleProvider
* property contains the same value, it will be set to null
.
* If it contains a different value, then it will be left unchanged to
* avoid conflicts with other registries or code.
*
* @param forClass The style provider is registered for this class.
*/
public function clearStyleProvider(forClass:Class):void
{
this.validateComponentClass(forClass);
if(forClass in this._classToStyleProvider)
{
var styleProvider:IStyleProvider = IStyleProvider(this._classToStyleProvider[forClass]);
delete this._classToStyleProvider[forClass];
if(this._registerGlobally &&
forClass[GLOBAL_STYLE_PROVIDER_PROPERTY_NAME] === styleProvider)
{
//something else may have changed the global style provider
//after this registry set it, so we check if it's equal
//before setting to null.
forClass[GLOBAL_STYLE_PROVIDER_PROPERTY_NAME] = null;
}
}
}
/**
* @private
*/
protected function validateComponentClass(type:Class):void
{
if(!this._registerGlobally || Object(type).hasOwnProperty(GLOBAL_STYLE_PROVIDER_PROPERTY_NAME))
{
return;
}
throw ArgumentError("Class " + type + " must have a " + GLOBAL_STYLE_PROVIDER_PROPERTY_NAME + " static property to support themes.");
}
}
}