Update: I have slightly modified the code below to correct a mistake in the original post. Thanks to Brindy for pointing it out.
Every now and then I come across a request of how to use FlexMDI using only ActionScript. Its completely straightforward but I have finally gotten around to getting an example up. The first code snippet shows how to do this while still utilizing MDICanvas for some of the convenience it provides.
import flexmdi.
containers.
MDICanvas;
import flexmdi.
containers.
MDIWindow;
import flexmdi.
effects.
effectsLib.
MDIVistaEffects;
private function init():void
{
var mdic:MDICanvas = new MDICanvas();
mdic.percentWidth = mdic.percentHeight = 100;
mdic.effects = new MDIVistaEffects();
var win1:MDIWindow = new MDIWindow();
win1.title = "First Window";
win1.width = 300;
win1.height = 200;
mdic.windowManager.add( win1 );
var win2:MDIWindow = new MDIWindow();
win2.title = "Second Window";
win2.width = 300;
win2.height = 200;
win2.x = 325;
win2.y = 50;
mdic.windowManager.add( win2 );
var btn:Button = new Button();
btn.label = "Awesome Button";
win2.addChild( btn );
addChild( mdic );
}
This next example shows how to turn a basic Canvas component into the container for an MDI implementation.
import flexmdi.
containers.
MDICanvas;
import flexmdi.
containers.
MDIWindow;
import flexmdi.
effects.
effectsLib.
MDIVistaEffects;
import flexmdi.
managers.
MDIManager;
import mx.containers.Canvas;
private function init():void
{
var canvas:Canvas = new Canvas()
canvas.percentWidth = canvas.percentHeight = 100;
var mgr:MDIManager = new MDIManager( canvas, new MDIVistaEffects() );
var win1:MDIWindow = new MDIWindow();
mgr.add( win1 );
win1.title = "First Window";
win1.width = 300;
win1.height = 200;
win1.x = win1.y = 10;
var win2:MDIWindow = new MDIWindow();
mgr.add( win2 );
win2.title = "Second Window";
win2.width = 300;
win2.height = 200;
win2.x = 350;
win2.y = 100;
var btn:Button = new Button();
btn.label = "Awesome Button";
win2.addChild( btn );
addChild( canvas );
}
Hopefully this clears up some of the uncertainty around how to use FlexMDI without our good friend MXML but feel free to ask questions in the comments.
03.08.08Posted by Ben in FlexComments Off
This announcement got a bit lost in the shuffle at 360|Flex so I wanted to officially get it on the record. flexmdi is now part of the most popular Flex component library around and can be found in the flexlib.mdi package. We considered offering the library to flexlib when we first created it but decided to release independently and gauge feedback first. We thought maybe we'd get an invite to join flexlib and about 3 days after launch that's exactly what happened. Yea, yea, that was about 6 months ago, I know. Well, we finally got around to it and flexlib.mdi is our new home. While flexmdi has done very well on its own and its been downloaded about 8,000 times, joining flexlib will give the library even more exposure and chances to be seen and used. I think all told flexlib has been downloaded about 30,000 60,000 times.
So thats about it, just wanted to make sure those who haven't heard did and know what is going on. All future development will happen in the flexlib repository and any future bug and/or enhan cement requests should be submitted on that site. We will be porting the existing isues list over, eventually.
Binding to read-only properties in Flex takes a bit more work than one might think at first glance. There are two basic types of read-only properties in Flex: "variable backed" and "calculated". Can you guess which one we're going to discuss here?
Lets start by clarifying exactly what we mean by read-only property. The most basic description is when you have a getter but no setter:
public function get someValue():Number {...}
The variable backed version is when the getter is just a gatekeeper for a private variable:
private var _someValue:
Number;
public function get someValue():Number
{
return _someValue;
}
The calculated version is a bit more complex and is generally either a combination of values like first name and last name or a value that requires calculation. The example we'll use here is a totalTime property of a Playlist. The totalTime is calculated by adding together the duration of all songs in the playlist at any given time.
OK, how?
By default you will get a warning telling you that the binding on a read-only property will be ignored (and whatever you've bound to it will indeed not receive any updates). The first part of enabling the bindings involves using metadata. Everybody knows [Bindable], but what we're looking for is [Bindable(event="eventName")]. That will essentially tell the compiler to dispatch a PropertyChangeEvent for the property (which is how binding works) any time an event of type "eventName" is fired. That brings us to the next step of firing the event. In our scenario of a calculated read-only property this needs to happen when one/any of our inputs changes.
Going back to the playlist example, a good time to let everyone know totalTime has changed is when a song is added. For the sake of simplicity that is the only scenario this example covers. I won't bother talking through the code in the example because it is very straightforward.
View the example and view the source and you'll see this is all very simple. I have included the classes generated by the compiler as well in case anyone wants to dig around. The magic seems to be injected from _CalculatedBindableReadOnlyWatcherSetupUtil.as but I won't claim to have a very solid understanding of how that all works.
I hope this will shed some light for somebody out there and maybe even come in handy if you're stuck. Binding to variable backed read-only properties has been covered by numerous other people and I would recommend learning about that as well. Enjoy!
Following Adam's lead, again, I thought I would post the link to the feedback provided by people who attended my session last week in Atlanta. Tom and John rock the transparency vibe pretty hard so I figure its fitting for the speakers to do the same. This was my first time presenting at a conference and overall I was pretty happy with the outcome. I think the feedback stating it focused on FlexMDI a bit too much is probably valid and I apologize for that. My intention was simply to use it as a vehicle to illustrate the concepts I was discussing, I didn't mean to showcase it in any way. I'd also like to repeat that I was/am not the only developer of FlexMDI. It was a joint effort between myself, Brian Holmes and Brendan Meutzner.
View the feedback
Thanks to everyone who attended, even if you didn't provide feedback! Though I really like those of you who did
Recent Comments