Stylish modules and sub applications.

One of the features that’s coming with Flex 4 is “Per-Module Style Management”. There is a lot that can be written about this feature and it probably can’t be covered in a single post. So for starters here is a small introduction.

The feature for Per-Module Style Management was done to allow modules and sub applications to be able to manage their own styles. With this feature StyleManager will no longer be a singleton and as a result that will allow modules and sub applications to have their own instances of StyleManager.

Modules and sub applications will continue to inherit styles from the parent application/module. But only the style properties not defined by the child modules or sub applications will trickle down (i.e. child module/application will be able to override a style property defined by the parent). There will also be merging of styles properties.

To understand this better, lets take a look at a sample. Following is the code for a parent application:

<?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";
 
		global {
			chromeColor: #DDAA66;	
		}
 
		s|DropDownList
		{
			fontStyle: italic;
		}
 
		s|Button#gumboButton
		{
			fontStyle: italic;
		}
 
		s|Panel s|Label
		{
			fontStyle: italic;
		}
 
		s|Button.myStyle
		{
			fontStyle: italic;
		}
 
		s|HGroup s|RichText
		{
			fontStyle: italic;
		}
 
		.classOfStyle
		{
			fontStyle: italic;
		}
 
	</fx:Style>
 
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import mx.collections.ArrayList;
			import mx.events.ModuleEvent;
			import mx.events.StyleEvent;
			import mx.controls.Alert;
 
			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 load():void
			{
				if(mod_loader.url == null)
				{
					mod_loader.url = "LoadStylesModule.swf";	
				}
				else
				{
					mod_loader.loadModule();
				}
 
			}
 
			public function unload():void
			{
				mod_loader.unloadModule();
			}
 
		]]>
	</fx:Script>
	<s:layout>
		<s:VerticalLayout />
	</s:layout>
	<s:HGroup>
		<s:VGroup id="groupId">
			<s:VGroup >
				<s:CheckBox id="checkBox" label="Check Box" />
				<s:Label text="Label Outside Panel"  />
			</s:VGroup>
			<s:HGroup rotation="10">
				<s:NumericStepper id="numericStepper" stepSize="1" minimum="1" maximum="10" />
				<s:RichText text="This Text is Rich !!" />
			</s:HGroup>
			<s:RichText text="This Text is also Rich !!" />
			<s:Panel title="Gumbo Panel" id="appPanel" rotation="-5">
				<s:layout>
					<s:VerticalLayout />
				</s:layout>
				<s:Button id="gumboButton" label="Gumbo Button"  />
				<s:Button id="gumboButton2" label="Second Gumbo Button" styleName="myStyle"  />
				<s:Label text="Spark Label"  />
				<s:Label text="Spark Label class selector" styleName="classOfStyle"  />
				<s:DropDownList id="appList"  />
			</s:Panel>
		</s:VGroup>	
		<mx:ModuleLoader id="mod_loader"/>
	</s:HGroup>
 
	<s:Button label="Load Module" click="load()" />
	<s:Button label="Unload Module" click="unload()" />
</s:Application>

If you notice, the above code defines a bunch of styles. It sets the chrome color to DDAA66 in the global selector and it sets the fontStyle to italic using various selectors (class, Id, Type, descendant).

Now let’s take a look at the code of the module (LoadStylesModule.mxml):

<?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:Script>
		<![CDATA[
			import mx.collections.ArrayList;
			import mx.controls.Alert;
			import mx.events.FlexEvent;
			import mx.events.StyleEvent;
 
			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 module1_creationCompleteHandler(event:FlexEvent):void
			{
				moduleList.dataProvider = listArr;
				localStyleManager  = StyleManager.getStyleManager(this.moduleFactory);
			}
 
			private var localStyleManager:IStyleManager2 = null;
 
			public var eventDispatcher:IEventDispatcher = null;
			protected function loadStylesButton_clickHandler(event:MouseEvent):void
			{
 
				eventDispatcher = localStyleManager.loadStyleDeclarations("testStyles.swf");
			}
 
			protected function unloadStylesButton_clickHandler(event:MouseEvent):void
			{
				localStyleManager.unloadStyleDeclarations("testStyles.swf");
			}
		]]>
	</fx:Script>
	<s:VGroup>
		<s:CheckBox id="checkBox" label="Check Box Module" />
		<s:Label text="Label Outside Panel"  />
		<s:HGroup rotation="-10">
			<s:NumericStepper id="numericStepper" stepSize="1" minimum="1" maximum="10" />
			<s:RichText text="This Text is Rich Module !!" />
		</s:HGroup>
		<s:RichText text="This Text is also Rich !!" />
		<s:Panel title="Gumbo Module Panel" id="appPanel" rotation="-5">
			<s:layout>
				<s:VerticalLayout />
			</s:layout>
 
			<s:Button id="gumboButton" label="Gumbo Module Button"  />
			<s:Button id="gumboButton2" label="Second Gumbo Module Button" styleName="myStyle"  />
			<s:Label text="Spark Module Label"  />
			<s:Label text="Spark Label Module class selector" styleName="classOfStyle"  />
			<s:ComboBox id="moduleList" height="24" width="147" />
		</s:Panel>
	</s:VGroup>	
	<mx:Button label="Load styles" id="loadStylesButton" click="loadStylesButton_clickHandler(event)" />
	<mx:Button label="Unload styles" id="unloadStylesButton" click="unloadStylesButton_clickHandler(event)" />
</mx:Module>

The code for the module above does not define any styles. So what that means is that it will inherit the styles from the parent app. It will have the chrome color of DDAA66 for all components and also the font styles will be italic. So far that’s all normal and boring stuff. Now you probably also noticed that the module loads a styles declaration swf (which is a css compiled to a swf), and when you load the styles swf you will see the magic of per-module style management. The module will override style definition for some properties (originally defined in the main app) and for other properties styles merging will happen.

Here is the code for the css (testStyles.css):

@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
 
s|DropDownList
{
	borderColor: #FF0000;
	fontSize: 16;
}
 
s|Button#gumboButton
{
	chromeColor: #AAFFAA;
	fontSize: 16;
}
 
s|Panel s|Label
{
	fontSize: 16;
}
 
s|Button.myStyle
{
	chromeColor: #FFFFAA;
	fontSize: 14;
}
 
s|HGroup s|RichText
{
	chromeColor: #BBAAAA;
	fontSize: 14;
}
 
.classOfStyle
{
	color: #0FFFFA;	
	fontSize: 20;
}

Here is the running swf:



Click on the “Load Module” button to load the module. Once the module is loaded, notice the chrome color of most components is the same as in the parent app and the font is italicized for most components – this shows that the module inherits styles from the parent app. Now click on the “Load styles” button in the module, once the styles swf is loaded you can notice that the font size changes for most components but the fonts in the module are still italicized – this shows styles merging because we were only overriding the fontSize in the css and not the fontStyle property. Also notice the new chrome color for components in the module, its now different from the global chrome color (DDAA66). So the module is able to override the styles properties it chooses.

So, hopefully you find this short introduction useful. Stay tuned for more on this.. And if you want me to write about something else, please say so with your comments (which btw are welcome ;-) )

3 comments to Stylish modules and sub applications.

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="">