Recently I ran into a problem that I had to build a Flash movie which should fit the browser window meaning the Flash movie is embedded with 100%x100%.
The problem I had is that even if I resized the browser window to something like 400×400 the stage.width property still showed 662. This caused that the content layout was wrong because it should take a width of 400 but used 662.
I investigated a bit more and it came out that this is caused by my Firefox browser where I tested the content. When I tested with Safari the minimal width my stage could get was 392 pixel. So WTF is happening here?
Then I tried to disable all Firefox toolbars and voilá, it worked like expected. Without any toolbar my flash content resized correctly to the actual size of the browser window.
Conclusion: Firefox with toolbars enabled prevents that the Flashplayer stage gets below a specific width depending on the stuff you have in your toolbar.
If you want to test small width Flash content which is embedded with 100%x100% be sure to disable all Firefox toolbars.
You can easily test it with this code for Flex:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" resize="resizeHandler(event)"> <mx:Script> <![CDATA[ private function resizeHandler(e:Event):void { if(stage != null) { trace("stage width " + stage.width); } } ]]> </mx:Script> </mx:Application>
We just released a new Swiz update:
- Flex 4 support (beta)
- TwoWay autowire
- Mediate priorities
- Pass event to mediating method
Flex 4 support
Today Adobe has released Flex Flash Builder 4 and Flash Catalyst betas on Adobe Labs. One more reason for Swiz to support Flex 4.
We have now posted two SWCs for Flex 2/3 and one for Flex 4. To compile the library on your own you now have to add a new compiler statement because we are using conditional compilation to support Flex 4:
-define=CONFIG::flex4,trueor for Flex 2/3:
-define=CONFIG::flex4,falseso the compiler args for Flex 4 read like:
-keep-as3-metadata +=Autowire,Mediate -namespace http://swiz.swizframework.org manifest.xml -include-namespaces http://swiz.swizframework.org -define=CONFIG::flex4,true
Further to let Swiz work in Flex 4 your beans in a BeanLoader have to be wrappend in a declarations tag:
<?xml version="1.0" encoding="utf-8"?> <swiz:BeanLoader xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/halo" xmlns:swiz="http://swiz.swizframework.org"> <fx:Declarations> <ctrl:TestController id="testController" xmlns:ctrl="example.ctrl.*" /> </fx:Declarations> </swiz:BeanLoader>
If you use the SwizConfig tag in your main application MXML you also have to nest it into a declarations tag. Our first tests with Flex 4 are fine but since this is the first release with it please give use feedback that all works as expected. Also note that Flex 4 is still beta so there might be changes in the future.
Our internal change is that for Flex 4 we are now using FlexGlobals.topLevelApplication to get access to the Application and the SystemManager. We think that should be it and our Flex 4 test projects works fine. If you have any problems with Flex 4 please let us know and post a comment here and/or join the Swiz group on Google code.
TwoWay autowire
Ben has added twoWay autowire which is really cool and already demonstrated it in his awesome Swiz example project. In short you can now do:
[Bindable] [Autowire( bean="appModel", property="activeView", twoWay="true" )] public var activeView:int;
So when you change the activeView variable above also appModel.activeView will be changed.
Mediate priorities
The mediate annotation has a new attribute priority which should be self explaining:
[Mediate(event="FooEvent.FOO", priority="0")] public function secondHandler():void { } [Mediate(event="FooEvent.FOO", priority="1")] public function firstHandler():void { // I am called first because of higher priority }
Pass event to mediating method
Now you have got the possibility to pass over the event to a mediating method instead of properties:
[Mediate(event="FooEvent.FOO")] public function eventHandler(event:FooEvent):void { }
So the rule is when no properties are defined Swiz first tries to call the method without arguments. This is wrapped in a try/catch block so when this fails we call the method again with the event itself as argument. We try to avoid too much “magic” in Swiz but I think in this way it’s pretty handy.
Example
Event:
package { import flash.events.Event; public class FooEvent extends Event { public static const FOO:String = "foo"; public function FooEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=true) { super(type, bubbles, cancelable); } override public function clone():Event { return new FooEvent(type, bubbles, cancelable); } } }
Because dispatchEvent returns false when the event is canceled your view code, in this example opened as popup, could look like this:
// note that the event bubble flag has to be set to true if(dispatchEvent(new FooEvent(FooEvent.FOO)) { // event not canceled // usecase could be to close a popup when an event wasn't canceled like: PopupManager.removePopup(this); } else { // event is canceled, this is what happens in this example with the controller code below }
So let’s have a look at the controller which mediates the FooEvent:
[Mediate(event="FooEvent.FOO", priority="0")] public function secondHandler():void { // I will not be called in this example because event.stopImmediatePropagation() in firstHandler } [Mediate(event="FooEvent.FOO", priority="1")] public function firstHandler(event:FooEvent):void { event.stopImmediatePropagation(); // note that the event cancelable property has to be true to cancel it event.preventDefault(); }
So what happens with the code above:
Because firstHandler has a higher priority than secondHandler it will be called first. In the method we call stopImmediatePropagation so the secondHandler will not be invoked. The event itself gets canceled with preventDefault and the view if statement is false and will not close the popup.
Have fun!
Recently FlexUnit 4 beta 1 was released. To get started I recommend FlexUnit 4 in 360 seconds and the feature overview. If you are using the Swiz framework and want to apply some changes to provide a patch file you could run the unit tests to be sure to break no features.
This is quite easy to do with the following steps:
- Create a new Flex AIR project: SwizTestRunner
- Download latest FlexUnit 4 and copy the SWCs into the SwizTestRunner libs directory
- Add the Swiz test class path: /../Swiz/src/test/flex
- Add your compiled Swiz.swc as a library
- Copy-n-paste the following into the SwizTestRunner.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="applicationCompleteHandler()" width="1200" height="640" xmlns:flexUnitUIRunner="http://www.adobe.com/2009/flexUnitUIRunner"> <mx:Script> <![CDATA[ import org.swizframework.service.ServiceTestSuite; import org.swizframework.autowire.AutowireTestSuite; import org.swizframework.factory.FactoryTestSuite; import org.swizframework.util.ExpressionTestSuite; import org.flexunit.listeners.UIListener; import org.flexunit.runner.FlexUnitCore; private var core:FlexUnitCore; private function applicationCompleteHandler():void { core = new FlexUnitCore(); core.addListener(new UIListener(uiListener)); core.run(AutowireTestSuite, ServiceTestSuite, ExpressionTestSuite, FactoryTestSuite); move(50, 50); } ]]> </mx:Script> <mx:TraceTarget fieldSeparator="->" includeCategory="true" includeTime="true" includeLevel="true" /> <flexUnitUIRunner:TestRunnerBase id="uiListener" width="100%" height="100%" /> </mx:WindowedApplication>
Now you can run the application and you should see the unit tests being executed:
To get started just have a look at the Swiz unit tests we have build so far. FlexUnit 4 is metadata driven so you should feel home when you use Swiz. We are continually extending our unit test suites but if you find a bug and can prove it with a failed test case you have provided this would be pretty awesome!
Swiz got a new feature which allows you to autowire views into any class which has been loaded in a BeanLoader. A target could be a controller class which wants to interact with a view. Normally you would say that the view dispatches events which are then handled by a controller to decouple them but there are scenarios where you wish you had access to the view directly to avoid a large Script tag in the view component.
Disclaimer
Swiz does not require or encourage code behind, just that we decided to support this rare use case for the sake of flexibility.
In this first version Autowire view works only for accessors what should be the common usecase meaning you can autowire a setter with the [Autowire(view=true)] metadata above the setter:
[Autowire(view="true")] public function set myView(view:MyView):void { //... }
The setter is invoked when the view is added to the stage and has dispatched the creationComplete event meaning all elements in the view are created and can be accessed. Since all MXML members are public this gives you quite some power but use it wisely to not introduce unnecessary coupling. Because a view is not a bean you have no bean attribute in the Autowire metadata but you autowire by type.
Example handling NativeDragEvent in an AIR app:
This code to handle drag-n-drop usually ends up in the Script block because you have to add the event listeners for dragEnter and dragDrop on for instance a Canvas. One could of course dispatch this further with custom events to a controller which could do the logic but I think letting a class directly add the event listeners could save this extra code:
package example.ctrl { import example.model.SomeModel; import example.view.DragView; import flash.desktop.ClipboardFormats; import flash.events.NativeDragEvent; import flash.filesystem.File; import mx.core.IUIComponent; import mx.managers.DragManager; public class DragController { [Autowire] public var someModel:SomeModel; [Autowire(view="true")] public function set dragView(view:DragView):void { if(!view.hasEventListener(NativeDragEvent.NATIVE_DRAG_ENTER)) view.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, dragEnterHandler, false, 0, true); if(!view.hasEventListener(NativeDragEvent.NATIVE_DRAG_DROP)) view.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, dragDropHandler, false, 0, true); } public function DragController() { } protected function getFilesFromDragEvent(e:NativeDragEvent):Array { if(e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT)) { var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array; return files; } return null; } protected function dragEnterHandler(e:NativeDragEvent):void { var files:Array = getFilesFromDragEvent(e); if(files != null && files.length == 1) { DragManager.acceptDragDrop(e.currentTarget as IUIComponent); } } protected function dragDropHandler(e:NativeDragEvent):void { var files:Array = getFilesFromDragEvent(e); if(files != null && files.length == 1) { var f:File = files[0] as File; // notify your model that a file is dragged on the view someModel.addFile(f); } } } }
Autowire view can give you more flexibility but for sure more responsibility so take care! So ask yourself twice if you are using the right approach when introducing Autowire view. However, if you have interesting scenarios where you can apply a decent pattern with this approach please share it.
Important
- In some scenarios I have seen that the setter is called twice so you maybe want to add an initView flag. Have to figure out if this is caused by the way Flex works or if this is a Swiz bug.
- Be always sure to add event listeners with a weak reference to enable garbage collection when the view is removed
- When you store a reference of the view be sure to release it when the view is removed to enable garbage collection
- Autowire view is considered to be used for custom components and I have not tried what happens when you autowire a Canvas or a Button or whatever
Chris just released a new version of Swiz with some really great additions and improvements. We now also own the domain swizframework.org which forwards to the Google code homepage.
This release makes Swiz faster, more flexible and even easier to use:
- Support for mediating bubbled event
- Added view attribute in Mediate tag
- Autowire views with view attribute in Autowire tag
- Ignoring view classes with underscore for performance optimization
- Added viewPackages for performance optimization
- Added eventPackages for shorter notation in strict mode
- SwizConfig for Swiz MXML declaration
- Generic fault handler for executeServiceCall
- Autowire bean properties with new property attribute
- Prototype supports class reference and constructor arguments
Swiz got a new member Ben Clinkinbeard who contributed some really cool stuff which makes mediating events more flexible and removed the Swiz dependency from the view because they can now bubble and lot’s of other stuff. Awesome to have Ben on board!
So here a quick overview for each new feature/improvement:
Support for mediating bubbled event
Events don’t have to be dispatched with the central event dispatcher anymore. So when you have a view instead of:
Swiz.dispatchEvent(new FooEvent(FooEvent.CHANGE))
you can do:
dispatchEvent(new FooEvent(FooEvent.CHANGE))
When you want to use this approach you have to
- enable the feature with Swiz.setMediateBubbledEvents(true) or via SwizConfig
- set the bubble flag of the event to “true”
- override clone method of the event
So the view has no Swiz import statement anymore and in fact doesn’t know anything about Swiz except to autowire models.
Added view attribute in Mediate tag
A dynamic mediator can now listen for view specific events. In the following example the dynamic mediator only listens for events dispatches by the view class “MyView”:
[Mediate(event="SomEvent.FOO", view="MyView")]
This is also extremely helpful to code more generic itemRenderers.
Autowire views with view attribute in Autowire tag
You can now autowire views into any bean with:
[Autowire(view="true")] public function set myView(view:MyView):void {...}
The setter is invoked when the view is added to the stage and has fired its creationComplete event so you can access all members of the view which in MXML are all public scope.
For more details and an example read my post here.
Ignoring view classes with underscore for performance optimization
This is an internal performance optimization where you as a developer don’t have to change anything except you have view classes with an underscore in the classname.
In Swiz 0.6 view classes with “_” are ignored for dependency injection because these are internal classes like skin classes, cursors or internal non-custom item renderers. Because these kind of classes won’t contain any metadata we can safely ignore them which improves the runtime performance significantly.
Added viewPackages for performance optimization
For further optimization beyond already ignoring underscore classes you can now define one or multiple view packages. If you set this property only views in these packages will get autowired.
You can set the viewPackage with
Swiz.addViewPackage("com.domain.project.view")
or with the new SwizConfig.
Added eventPackages for shorter notation in strict mode
When you are using Swiz in strict mode you can now define eventPackages to have a shorter notation of the event. I already blogged about this feature here.
SwizConfig for Swiz MXML declaration
Instead of adding an event listener for the Application/WindowedApplication preInitialize event and the calling Swiz.loadBeans besides configuring Swiz you can now use the new SwizConfig class in MXML. The markup for an AIR app then looks like this:
<?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.rpc.events.FaultEvent; import mx.logging.LogEventLevel; private function genericFault(fe:FaultEvent):void { // TODO handle fault } ]]> </mx:Script> <mx:TraceTarget fieldSeparator="->" includeLevel="true" includeCategory="true" includeTime="true" /> <swizframework:SwizConfig xmlns:swizframework="org.swizframework.*" strict="true" mediateBubbledEvents="true" eventPackages="example.event" viewPackages="example.view" beanLoaders="{[Beans]}" serviceCallFaultHandler="{genericFault}" logEventLevel="{LogEventLevel.WARN}" /> <view:SwizConfigTestView xmlns:view="example.view.*" width="100%" height="100%" /> </mx:WindowedApplication>
The SwizConfig itself will listen for the preInitialize event of the application and configure Swiz.
Generic fault handler for executeServiceCall
When you use Swiz.executeServiceCall or subclass AbstractController and call executeService call you can leave out the fault handler. When a fault comes up Swiz currently shows an Alert window with the fault details. You can override this like in the SwizConfig example above.
Autowire bean properties with new property attribute
You can now autowire bean members instead of the bean itself. So instead of:
[Bindable][Autowire] public var someModel:SomeModel; <mx:List dataProvider="{someModel.someList}" />
you can use:
[Bindable][Autowire(bean="someModel", property="someList")] public var someList:ICollectionView; <mx:List dataProvider="{someList}" />
Prototype supports class reference and constructor arguments
Prototype (see old post here) now support constructor arguments and you can declare a class reference instead of the full qualified class name.
Example:
<factory:Prototype xmlns:factory="org.swizframework.factory.*" classReference="{SomeClass}" constructorArguments="{['foo', 'bar']}" />
There will come a lot of new blog posts regarding each new feature soon but I hope this has given an overview about what’s new in 0.6. Besides that we try to add more documentation and example projects.
For Flex skinning I have usually used Flash with the Flex skinning extension. This is called the stateful approach because you can also add transitions between the states. This worked out fine and the workflow was ok and you ended up in Flex to define the skin via CSS like this:
.myButton{ skin: ClassReference("MyButton_skin"); }
You may have followed the discussion in March that this approach is CPU intensive because the Button subclasses mx.flash.UIMovieClip which has an enterFrame event listener which decreases the performance of your application.
Bam! What? So the apps I have written in the past could be faster if I would avoid Flash for Flex skinning? Damn! I first tried to use another base class like explained here. However this did not change much so I decided to switch over to stateless skins because they are obviously the fastest solution.
Ok, the app I wanted to refactor had about 15 different buttons and a bunch of other skinned components and almost all need a scale-9 grid to resize decently. Scale-9 grid is easy to define in Flash because you get kind of rulers which you can drag to the right position. For stateless skins you have to define them by setting the numeric value for scaleGridTop, scaleGridBottom, scaleGridLeft and scaleGridRight so you end up with an Embed directive for a toggle button like this:
.myButton { up-skin: Embed(source='/../assets/default_up.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); over-skin: Embed(source='/../assets/default_over.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); down-skin: Embed(source='/../assets/default_down.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); disabled-skin: Embed(source='/../assets/default_disabled.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); selected-up-skin: Embed(source='/../assets/default_selected_up.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); selected-over-skin: Embed(source='/../assets/default_selected_over.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); selected-down-skin: Embed(source='/../assets/default_selected_down.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); selected-disabled-skin: Embed(source='/../assets/default_selected_disabled.png', scaleGridLeft='15', scaleGridRight='134', scaleGridTop='15', scaleGridBottom='43'); }
Yeah, this look looks like a hell of fun to measure and write! Not!
So long story short, this is where FlairSkin comes into play.
FlairSkin is a little pet project I have been working on in my spare time to create stateless Flex skins in a more decent way. This is the first release so expect new features soon. Besides generating embed directives I also implemented a little font browser which also outputs the CSS needed by Flex.
Thanks to Inara for the logo and design!
Install it here:
Screenshots:



Watch a screen video here:
FlairSkin from Sönke Rohde on Vimeo.
After refactoring my app to stateless skins with FlairSkin the performance improvement was very significant so bye bye Flash for Flex skinning at least for now!
One thing I am missing though is that in Flash I can define the registration point meaning around which point a graphic would rotate. In Flash you can simply move the graphic to the right position and I think there is no way to do this with stateless skins so you need to calculate it programatically which can be a pain. So it would be nice if the Embed metadata would support something like this:
Embed(source="foo.png" centerX="20" centerY="10")
where default would be 0,0
Additional Links








