StyleManager in Flex 4

In my previous post stylish modules and sub applications, I mentioned that StyleManager is not going to be a singleton class in Flex 4. There are some more StyleManager related api changes that you should be aware of.

StyleManager now implements IStyleManager2. If you recompile your Flex 3 app using Flex 4 SDK, you will get deprecation warnings because all static methods of StyleManager class except for getStyleManager() have been deprecated. In order to get rid of the deprecation warnings, you will need to use the StyleManager instance. You can either get the StyleManager instance using the getStyleManager() method or change StyleManager to styleManager (notice the lower case ‘s’). mx.core.UIComponent now has a new public property called styleManager which is a reference to your current StyleManager.

Also StyleManager now has a new method called getMergedStyleDeclaration() which can be used to get the merged style declarations (both declared in the current style manager and those inherited from the parent style managers). One thing to be aware of with this method is that CSSStyleDeclaration obtained via this method can not be used to modify style values. In order to modify style values, you will have to obtain CSSStyleDeclaration using the getStyleDeclaration() method.

Lets look at an example:
Here is the code for an application that defines Style for a spark List (specifically it defines the borderColor and fontSize).

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="1024" minHeight="768" creationComplete="application1_creationCompleteHandler(event)">
	<fx:Style>
		@namespace s "library://ns.adobe.com/flex/spark";
		@namespace mx "library://ns.adobe.com/flex/mx";
 
		s|List
		{
			borderColor: #0000FF;
			fontSize: 16;
		}
	</fx:Style>
 
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayList;
			import mx.events.FlexEvent;
			import spark.components.TextInput;
                        // The following two lines (import and var declaration for PopUpManager) are to make sure that PopUpManager gets sucked into the app. Since PopUpManager
                        //  is a singleton, its definition should be available in the main app
                        // Otherwise module will throw an RTE when ColorPicker is used.
			import mx.managers.PopUpManager;			
			private var ph:PopUpManager;
 
			private var arr:Array =
			[
				{ label:'Apple', data:10.00},
				{ label:'Banana', data:15.00 },
				{ label:'Melon', data:3.50 },
				{ label:'Kiwi', data:7.65},
				{ label:'Strawberry',data:12.35 },
				{ label:'Other', data:00.00}
			];
 
			private var listArr :ArrayList = new ArrayList(arr);
 
			protected function application1_creationCompleteHandler(event:FlexEvent):void
			{
				appList.dataProvider = listArr;
			}
 
			public function iniit():void
			{
				mod_loader.url = "ModifyCSSDeclarationModule.swf";
			}
 
			public function unload():void
			{
				mod_loader.unloadModule();
				mod_loader.url = "";
			}
		]]>
	</fx:Script>
	<s:layout>
		<s:VerticalLayout paddingTop="5" paddingLeft="5" paddingRight="5" paddingBottom="5"/>
	</s:layout>
	<s:HGroup id="hgroupContainer" paddingLeft="5">
			<s:List id="appList"  />
			<mx:ModuleLoader id="mod_loader" />
	</s:HGroup>
	<s:Button label="Load Module" click="iniit()" />
	<s:Button label="UnLoad Module" click="unload()" />
</s:Application>

Below is the code for the module (ModifyCSSDeclarationModule.mxml) loaded by the app:

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:fx="http://ns.adobe.com/mxml/2009" 
		   xmlns:s="library://ns.adobe.com/flex/spark" 
		   xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="module1_creationCompleteHandler(event)">
	<fx:Style>
		@namespace s "library://ns.adobe.com/flex/spark";
		@namespace mx "library://ns.adobe.com/flex/mx";
 
		s|List
		{
			fontStyle: italic;
			color: #FF0000;
		}
	</fx:Style>
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayList;
			import mx.events.FlexEvent;
 
			private var arr:Array =
				[
					{ label:'Apple', data:10.00},
					{ label:'Banana', data:15.00 },
					{ label:'Melon', data:3.50 },
					{ label:'Kiwi', data:7.65},
					{ label:'Strawberry',data:12.35 },
					{ label:'Other', data:00.00}
				];
 
			private var listArr :ArrayList = new ArrayList(arr);
			private var myStyleManager: IStyleManager2;
 
			protected function module1_creationCompleteHandler(event:FlexEvent):void
			{
				moduleList.dataProvider = listArr;
				myStyleManager = StyleManager.getStyleManager(this.moduleFactory);	
			}
 
			public function modifyStyleValue(  ):void
			{
				var cssDecl:CSSStyleDeclaration = myStyleManager.getStyleDeclaration("spark.components.List");
				cssDecl.setStyle("color", colorPicker.value);
				cssDecl.setStyle("borderColor", colorPicker.value);
			}
 
			public function modifyMergedStyleValue( ):void
			{
				var cssDecl:CSSStyleDeclaration = myStyleManager.getMergedStyleDeclaration("spark.components.List");
				cssDecl.setStyle("borderColor", colorPicker.value);
				cssDecl.setStyle("color", colorPicker.value);
			}
		]]>
	</fx:Script>
	<s:List id="moduleList"  />
	<s:Label text="Choose Color" />	
	<mx:ColorPicker id="colorPicker" />
 
	<s:Button id="localButton" label="Modify Styles" click="modifyStyleValue( )" />
	<s:Button id="mergedButton"  label="Modify Merged Styles" click="modifyMergedStyleValue( )" />
</mx:Module>

The module code above tries to modify the styles (color, and borderColor) for the spark List. You can use the color picker to pick in the new color. If you press the “Modify Styles” button, the style values will get updated because modifyStyleValue() method obtains CSSStyleDeclaration via the getStyleDeclaration() method.
But if you press the “Modify Merged Styles” button, the setStyle() calls will fail silentely because CSSStyleDeclaration (in modifyMergedStyleValue) is obtained via getMergedStyleDeclaration().

Here is the running swf:




Also notice that when you press the “Modify Styles” button, only the styles of the spark list in the module will get updated. Why? It’s because the module is using the instance of StyleManager (myStyleManager) obtained using getStyleManager() (by passing the current module factory – this.moduleFactory). So this instance is different that the top level style manager which the main app is using.

5 comments to StyleManager in Flex 4

  • zeroin

    Hi,

    Thank you for this article. I have one question: I have my Flex 3 components written in pure AS3, and made them work with FB4 by changing

    StyleManager.getStyleDeclaration(“MyComp”) to StyleManager.getStyleDeclaration(“com.xxx.MyComp”)

    and

    StyleManager.setStyleDeclaration(“MyComp”, styleDeclaration, false) to StyleManager.setStyleDeclaration(“com.xxx.MyComp”, styleDeclaration, false)

    All works fine, but, of course, I get the error like you described.

    My styles are inited by calling static method, initStyles, like it was used in FB3 components. This means I can’t address to this.moduleFactory in this method. Does this mean I should make this method not static and call it, well, in Constructor?

    Thanks a lot!

  • Gaurav

    initStyles() doesn’t have to be a static method. You can override the set moduleFactory() method and call initStyles from that method.

    HTH,
    Gaurav

  • This example is not working anymore in FB 4.0

  • Gaurav

    What error are you getting? I just tried it and it worked for me using FB 4.

  • [...] implementation has changed so that every loaded module has its own instance of StyleManager. This post by Gaurav Jain explains how you can use it so that the loaded modules have their own separate style [...]

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">