flexmdi: Starting out simple with MDICanvas
The quickest, dirtiest, most basic way to use flexmdi is with the MDICanvas class. MDICanvas essentially wraps the manager (MDIManager) and container (Canvas) into one class, allowing you to define a basic MDI interface purely in MXML. Let's look at some code.
-
<flexmdi:MDICanvas id="mdic" width="500" height="500">
-
<flexmdi:MDIWindow id="win1" title="Window One" x="10" y="10">
-
<samples:SampleContent />
-
</flexmdi:MDIWindow>
-
<flexmdi:MDIWindow id="win2" title="Window Two" x="250" y="250">
-
<samples:SampleContent />
-
</flexmdi:MDIWindow>
-
<flexmdi:MDIWindow id="win3" title="Window Three" x="100" y="100">
-
<samples:SampleContent />
-
</flexmdi:MDIWindow>
-
</flexmdi:MDICanvas>
As you can probably guess, this will create a 500 x 500 Canvas with three windows in it. The windows are created at the coordinates specified in the MXML, and since no size is specified they are created at the default size of 200 x 200.
As it turns out, thats pretty much all there is to it. You could also use this approach for doing a quick layout in MXML but still use AS to gain a little more control and customize things. You can obviously address any of the windows by their id, but you can also address the MDIManager that is created for you with code like this: mdic.windowManager. I will discuss some of the more advanced topics in subsequent articles but feel free to leave questions or comments.



on September 11th, 2007 at 11:58 am
[...] flexmdi: Starting out simple with MDICanvas [...]
on November 28th, 2007 at 4:46 am
Hi ,
ver y nice framework. I have been using it in a small project: However I have found some strange behaviour which i may need some help with.
Once the close Button is pushed, the MDIWindow is removed and disappears from stage. However it seems the window is still alive, although not visible.
Once i open the window the second time, my initial server call is being called twice, once for the visible window and once for the already closed window.
Further I didnt explicitly call the close method. Can you guys help please ? What am I doing wrong ? Any help is appreciated.
Thanx
Amir
on November 28th, 2007 at 1:19 pm
Hi Amir,
Thanks for the compliment. I think I would need to see some code before I could help diagnose your problem. What kind of listener are you attaching to the window that seems to get called even after closing it? You might want to try a weak listener or manually removing the listener(s) when the window is closed.
As for the window closing without calling close(), the default behavior assigned to the close button's click handler is to close the window. Instructions on how to modify and/or customize that behavior can be found here: http://www.returnundefined.com/2007/09/flexmdi-customizing-default-behaviors/
Let me know if you continue to have trouble.
on December 2nd, 2007 at 4:55 pm
Ben,
I'm using flexmdi in a project to provide windows on one view of a viewstack. This is a very nice framework, BTW. The only problem I have is that the swc file doesn't seem to have the graphics for the buttons (close, maximize, etc.) embedded in it. The only way to get the graphics to show up is to set up styles that embed the graphics and put the styles in my css file for the application. The only way to find out the style names is to either dig through the source code for MDIWindow or copy the styles from one of your examples.
Shouldn't the default graphics for the icons just be embedded in the compiled library? Also, I tried to recompile the library and include the assets, but this didn't help.
One more thing, some examples on how to change the content of the windows using AS would be nice to have. You're examples show how to create the windows with AS, and the canvas example shows how to provide content for the windows via MXML, but there's nothing for AS.
I finally got it to work like this:
private function getViewComplaint(cn:Object):MDIWindow {
var view:ViewComplaint = new ViewComplaint();
view.cn = cn;
view.addEventListener("assignItem", refreshList);
return view;
}
Then in the MXML code:
on December 2nd, 2007 at 6:05 pm
Hi Randy, I'm glad you're enjoying flexmdi! Sorry about your comments getting cut off, it has something to do with the brackets in MXML. I deleted your second comment because the same thing happened to it. I need to look into fixing that but in the meantime if you wrap any code (AS or MXML) in tags like this [as ]// code goes here[ /as] it should get the same highlighting the code in the posts does. ("as" tags with square brackets, I only included spaces to prevent it being applied)
Anyhow, on to your questions. Regarding the CSS and assets you're exactly right. We actually just became aware of defaults.css the other day, which is supposed to embed everything in the SWC. Look for that type of implementation in the next release- there is one coming, I promise. Sorry we got it wrong the first time around.
As for changing content, you can treat MDIWindow just like any Panel (MDIWIndow's superclass) or other container class and use addChild() and removeChild() to modify the window's contents. Hope that helps, let me know if you have additional questions.
on December 3rd, 2007 at 5:32 pm
I'm adapting your great MDI framework for a project I started a while ago using another similar framework. A quick question: how would I execute the tiling while setting all the panels to a particular predetermined size rather than maximizing them? I'm being lazy in asking here before studying the MDIManager code, but I thought you might have a quick easy answer. Thanks!
on December 3rd, 2007 at 7:04 pm
Hi Tom, you want to tile the windows but not use the window sizes that result? If I'm understanding your question correctly there is no way to do that out of the box. Sorry.
on December 4th, 2007 at 10:37 am
What I'd like to do is tile the windows but set their sizes as well. Users would be able to reposition and resize windows, but tiling them would return them all to a particular size (say, 350 X 200 px) and arrange them in a grid starting at the upper left. Is that what you're saying is not possible?
on December 4th, 2007 at 11:29 am
Hi Tom, unfortunately that is not something we anticipated a need for, so we didn't implement that functionality. I don't think it would be too difficult to implement, so if you feel up to it I would encourage you to dive into MDIManager.tile() and see if you can make the necessary changes, or perhaps create a new function called tileWindowsToSize(w:Number, h:Number) or something. If you feel like this is something others would use and/or should be part of the standard library feel free to add an enhancement request on the project site on Google Code.
Thanks!
on December 4th, 2007 at 12:37 pm
OK. I give up. If you'll send me your email address privately, I'll send you the code I used to get this to work, and my suggestions for adding content to the windows.
~randy
on December 4th, 2007 at 5:02 pm
Randy - if that message was meant for me (I hope it was) - how do I send you my email address privately?
Thanks.
on December 7th, 2007 at 8:30 pm
Tom,
Actually, that message was meant for Ben so I could send him the code for how I got content into an MDIWindow via actionscript.
Sorry,
Randy
on January 4th, 2008 at 7:19 pm
[...] Update: If your using FlexMdi and don’t see the correct images for close, minimize etc, then read this, comment in this and this. [...]
on January 11th, 2008 at 2:24 pm
Is there a sample of using the 1.0 version of FlexMDI using PB 3 with the latest SDK to extend the buttons? I've looked at the sample on google for this and using PB 3 causes errors - in attempting to correct the errors the added button appears in the 'main' content area instead of the top bar of the MDI Window. And have been unable to add an additional button successfully.
Thanks
on January 11th, 2008 at 5:05 pm
Hi Mike,
There are significant changes checked in to accommodate customized titleBars but no new release quite yet. I might be able to get a release out next week but if you feel comfortable checking out and examining the code I would encourage you to do so.
Ben
on January 29th, 2008 at 10:06 am
I have a small problem trying to run the demo. When I download the source code and extract it I open the MDIExampleExplorer.mxml file I get these errors :
Type was not found or was not a compile-time constant: MDICanvas line 148
Type was not found or was not a compile-time constant: MDIWindow line 151 and line 154
Any ideas ???
Thanks
Keith Lowry
Atlanta, GA
on January 29th, 2008 at 2:10 pm
Hi Keith,
How do you have your project pointing to the library? I don't think Flex Builder will establish a link for you, you'll need to manually point your project at the SWC or the source.
Hope that helps,
Ben
on January 29th, 2008 at 3:05 pm
I changed it to read xmlns:flexmdi="flexmdi.*" if thats what you mean ?
on January 29th, 2008 at 4:49 pm
No, I mean you need to go into your project's properties -> Build Path -> Add SWC. There is a lot of good info on project configuration in the docs.
HTH,
Ben
on January 29th, 2008 at 5:09 pm
Hmmm.. I dont see a SWC file included ??
on January 29th, 2008 at 5:15 pm
Ahh.. Nevermind.. Success. I got it !!! THANKS !
on January 29th, 2008 at 5:40 pm
One ore thing. I am trying to add code to an event (maximize) but I am getting "mdi.events:MDIWindowEvent is unavailable"
on January 29th, 2008 at 7:55 pm
G'day,
Great framework you've put together, just what I was looking for! I seem to be having some issues with instantiating the components using AS.. Any chance of a quick demo of an all AS implementation... I've been trying:
protected function createMDICanvas():void {
mainMDICanvas = new MDICanvas();
mainMDICanvas.percentHeight = 100;
mainMDICanvas.percentWidth = 100;
mainMDICanvas.horizontalScrollPolicy = "off";
mainMDICanvas.verticalScrollPolicy = "off";
mainMDICanvas.effectsLib = MDIVistaEffects;
addChild(mainMDICanvas);
}
protected function displayMDICanvasItem(template:MDIWindow):void {
mainMDICanvas.windowManager.add(template);
}
protected function removeMDICanvasItem(viewVO:ViewVO):void {
var template:* =mainMDICanvas.getChildByName(viewVO.instanceName);
mainMDICanvas.windowManager.remove(template);
}
These are called from an extended Application object.. Have I missed something important? - getting some undefined parent errors from MDIWindow.as line 623, when I add a window after removing one..
on January 29th, 2008 at 8:13 pm
Hi Andy,
Thanks, we worked hard so we're glad people have found it useful. Your code looks correct at first glance, what is the error you're getting? If you can send me a simple test case I can take a look. ben DOT clinkinbeard at Google's email service :)
on February 4th, 2008 at 2:29 pm
[...] The following is an unedited email thread I have had with a reader over the past week or so. I helped him learn how to add a SWC to a Flex project but apparently that (and FlexMDI) wasn’t good enough. The quotes next to the green bars are mine. Hey Ben, [...]
on February 20th, 2008 at 11:22 am
[...] FlexMDI ????????Flex?????????MDI???????????????????????????????????? ???? ???? flexmdi?????MDICanvas?? MDIManager ?? flexmdi ???? ???? [...]
on March 5th, 2008 at 9:38 am
Hello,
First of all, tnks for such amazing framework!
Well, I'm kind of new into FLEX, so I appologise for my doubts.
I'd like to know how can I have a function just to create a windows with something in it. Like something dynamic, that when I click on a menu, a windows with the parameters I put would open. For instance:
function create_windows("name_of_window", "height", "width", "position x, "position y", "etc",){
mywindow.createmywindow;
mywindow.addsomethingtomywindow;
}
on March 5th, 2008 at 9:46 am
Hi Renan,
MDIWindow extends Panel so you can treat it the same, or like any other Container for that matter. To set properties you would just iterate over the properties sent and assign them like myWindow.height = height.
To add children to it you just use addChild() like for other containers.
Hope that helps.
on March 5th, 2008 at 9:56 am
Hello Ben,
Tnks for answering so quickly!
Would it be something like that?
public function createMDICanvas():void {
var mainMDICanvas:MDICanvas = new MDICanvas();
mainMDICanvas.horizontalScrollPolicy = "off";
mainMDICanvas.verticalScrollPolicy = "off";
mainMDICanvas.effectsLib = MDIVistaEffects;
mainMDICanvas.height = 200;
mainMDICanvas.width = 200;
//How can I put this panel inside the window?
var myPanel:Panel = new Panel();
myPanel.id = "teste";
myPanel.height = 20;
myPanel.width = 30;
//Doing this the window should just appear?
addChild(mainMDICanvas);
}
I understand what you mean with the panel, it is really useful, but I still don't know how to make the window show up.
Tnks again!
on March 5th, 2008 at 10:19 am
Close, but I think you would want to add an MDIWIndow instance to the mainMDICanvas, not a Panel. You would also need to add the mainMDICanvas to the display list.
on March 5th, 2008 at 10:21 am
would you give me a simple example?
on March 5th, 2008 at 10:56 am
Hey m8!
Tnks, I got it... And I'm like UOUUUU...
Seriously... it's very good! Congratulations!
on March 5th, 2008 at 1:04 pm
Why are my minimized windows on top of each others Instead of being side by side when minimized?
on March 5th, 2008 at 1:52 pm
Hey Hello,
Me again...
I was able to do this function, and it is working, although I guess it is creating (obviously) one canvas for each window, and shouldn't be like that, right? I couldnīt do different. Can anyone help me?
//The Function:
public function createMDICanvas(w:Number,h:Number):void{
var mainMDICanvas:MDICanvas = new MDICanvas();
mainMDICanvas.horizontalScrollPolicy = "off";
mainMDICanvas.verticalScrollPolicy = "off";
mainMDICanvas.percentHeight = 90;
mainMDICanvas.percentWidth = 90;
mainMDICanvas.effectsLib = MDIVistaEffects;
var myPanel:Panel = new Panel();
myPanel.id = "teste";
myPanel.height = 300;
myPanel.width = 200;
var myWindow:MDIWindow = new MDIWindow();
myWindow.height = w;
myWindow.width = h;
myWindow.title = "MyWindow" + i++;
addChild(mainMDICanvas);
mainMDICanvas.windowManager.add(myWindow);
myWindow.addChild(myPanel);
}
on March 5th, 2008 at 1:58 pm
Hi John,
I can't really say without seeing your code. I've not seen that happen before.
on March 5th, 2008 at 3:35 pm
Hi Renan, you only need one MDICanvas, so take that out of any functin that gets called more than once. You also don't need a Panel. When creating MDIWindow's you only need to use the manager's add() method. addChild() is then handled for you. Look at the addWindow() function from the explorer for reference.
http://www.returnundefined.com/flexmdi/explorer/srcview/index.html
on March 5th, 2008 at 3:59 pm
Tnks a lot!
One last thing...
Lets say my windows have a certain ID each one.
How do I check if a window is already open?
Tnks again!
on March 5th, 2008 at 4:04 pm
MDIManager has a windowList property you could check.
on May 12th, 2008 at 8:33 am
Hi Ben,
Really great work on this framework that you guys have come up with.
I have a small question, does the children of a MDIWindow automatically resize themselves when the window resizes e.g when it maximizes.
I have something like this
myMDIWindow.addChild(myFlexModule);
N/B i have percentages for the width & height for myFlexModule.
When the window maximizes myFlexModule doesn't seem to resizes to reflect the resizing that has occured.
So i was wondering if I have to do anything special to have that implemented.
Thanks again for the superb work.
on May 12th, 2008 at 8:55 am
Hi Kelvin,
I am a bit surprised they don't stay properly sized when using percentages. I would think the Flex framework would invalidate the size of the children when the window changes size. I unfortunately don't have time to investigate right now but will try to remember to test that next time I deal with the code.
Thanks,
Ben
on May 12th, 2008 at 9:03 am
Hello Ben
We've recently started using FlexMDI and we really like the functionality.
However, we are experiencing performance problems with any windows containing datagrids.
To display a datagrid 10 columns and 15 rows can take 10 seconds.
To switch between windows can take the same length of time (this is the time from clicking on the window and anything happening at all. The window paints instantly when it's ready).
Resizing is also extremely slow. Nothing happens for several seconds then the window repaints far beyond where the cursor was previously seen.
Dragging and dropping a window that's got context works fine.
Do you have any thoughts on what we might be doing wrong?
Thanks in advance
Julian
on May 12th, 2008 at 9:20 am
Hi Julian,
We've been meaning to implement non-live resizing as we know resizing is a performance killer but you shouldn't be seeing problems when the windows are sitting still. MDIWindow is really just a Panel with some added functionality and children. Can you possibly provide a test case?
Thanks,
Ben
on May 12th, 2008 at 9:38 am
Hi Ben
Thanks for replying so quickly!! :-) I can easily send you an example so you can see what I mean...
Where should i mail that?
Julian
on May 13th, 2008 at 5:05 am
Hi Ben,
Thanks for the prompt reply.
When testing the resizing issue, please use a flex module as the child of the the MDIWindow.
Thats what am using and it seems that when the MDIWindow resizes, the flex module doesn't resize as expected.
Thanks again.
on May 26th, 2008 at 4:27 pm
Hi, when I minimize a window, appears a button at botton of mdicanvas. But if a maximize another window, this one cover the first one.
There is a way to always show the windows in task bar like windows taskbar ?
on May 26th, 2008 at 6:55 pm
Hi Paulo,
There is a showMinimizedTiles property, I think on MDIManager. Setting it to true will do what you want.
Ben
on June 4th, 2008 at 7:44 am
Identified a problem in the management of memory. When you add one or multiple windows on the canvas and then remove them, the memory does not reduce. What should be done for this to be corrected, taking into account that this will be used many times in a day's work.
on June 4th, 2008 at 8:53 am
Hi Leonardo,
Flash Player's garbage collection runs unpredictably (its not arbitrary but is impossible to predict) and is triggered by memory allocation requests. Therefore, removing components will never trigger garbage collection. As far as I know FlexMDI takes all necessary steps to ensure garbage collection can clean up as appropriate and does not contain any memory leaks.
Thanks,
Ben
on August 27th, 2008 at 5:03 am
This is great...thanks!
Question: can someone point me to an example of how to populated one of the MDI windows with existing forms that I have in my application? I have several modal pop-up forms that I used to collect or display data in and I'd like to display some of them in different MDI windows.
Thanks!
on August 27th, 2008 at 8:29 am
Hi Chris,
MDIWindow is just a subclass of Panel, so you can add children to it like any other component. If defining in MXML you just put the child tags inside it and if using AS you can use things like addChild(), removeChild(), etc.
Ben
on August 27th, 2008 at 5:52 pm
Ben,
Thanks for the quick and informative response!
I got it working with my forms just fine. Now I'm running into the slow resize/redraw issue previously mentioned by another user. If I open two windows (populated with my controls) it gets slow. Even switching focus between the two windows lags for a couple seconds.
Each window contains several flex components (multiple tabs with datagrids, accordion lists, etc.).
I'm willing to pay/donate to get some additional support on this.
Thanks,
Chris
on October 7th, 2008 at 2:15 pm
hi guys
could anyone help me with this:
I have an application working with MDICanvas but when I need to add a new MDIWindow in an absolute position I can set the x and y position for the MDIWindow but in the MDICanvas the MDIWindow appears in a different x and y position.
thanks
:::::::::::::::::::::::code::::::::::::::::::::::::::
on October 21st, 2008 at 3:00 pm
Create tool, I am using the MDI functionality in an application currently, I do have an issue though, At first launch of application everything is good, then I launch the window, and then minimize, it goes below the screen. But when i resize the browser window and then minimize again the window minimizes to the correct position. i was wondering if you can help me out here, thanks. (Something that I noticed that if I take away my tool-bars its the exact amount of space to the minimized window, don't know if that will help). Thanks again