Tuesday, March 17, 2009

Resizable Containers (Flex 3)

Please go here for Flex 4 Spark Resizable Controls.

I previous posted a blog on a Resizable Movable Panel control which was an extension of the TitleWindow class which let the user drag the panel titlebar to move it around the screen, and drag a small resize handle in the bottom right corner to resize the panel.

I've made some updates to this class, and further extended it to support not just Panel/TitleWindow containers, but also Box (VBox/HBox), Canvas, and TextArea (similar to what Google Chrome does).

The main class that does all the work is called ResizeManager. It adds a small resize component in the bottom right corner of the container that when dragged resizes the container.

Here is an example (right click to view source). Let me know what you think!


Important: the resize containers do not resize properly if you set the resizeEffect property.

For a similar project that is devoted to movable windows, check out the MDI project which is now part of the FlexLib project.

November 30th 2009 Update: I've updated the MoveManager adding two new fields. Setting the MoveManager.constrainToParentBounds to true will cause the component's movement to be restricted to the parent's bounds. You can also set your own custom bound's constraint by setting the constrainToBounds property to a Rectangle. The way this works is by passing that bounding Rectangle into the move component's startDrag(false, bounds) function.

December 23rd 2009 Update: I've updated the MoveManager and ResizeWindow classes to fix a problem that occurred when movable="true" and resizable="true" and no dragComponent was set. Now the move and resize should work properly.

January 5th 2010 Update: I've updated the MoveManagerand ResizeManagerclasses to use custom cursors for moving and resizing. You can also set the MoveManager.moveIcon and ResizeManager.resizeIcon properties to use your own custom icons, or just edit those classes directly and change the [Embed(source="...")] metadata tags.
The move cursor is only shown when the mouse is down. The resize cursor is shown when the mouse is over the resize handle and when the resize is happening. There might be some problems with the resize cursor getting stuck always on, but hopefully it's a good starting point.

March 4th 2010 Update: I've separated the move/drag and resize handles into separate stand-alone components: DragHandle and ResizeHandle. The colors of the handles can be customized using styles. You can also control how many rows and columns of dots are shown in the handles. Alternatively you can explicitly set a width and height for the drag/resize handles and the number of dots will be calculated automatically to fill the space. The size of the dots is configurable too.

I also added a new properties to the resize components - bringToFrontOnResize, and bringToFrontOnMove (ResizableWindow only). These properties determine whether the components should be brought to the front to be on top of the other siblings. By default these properties are false. It only makes sense to set these values to true if the parent container is using an absolute layout.

I've put up a blog post about the DragHandle and ResizeHandle if you're interested.

September 15th 2010 Update: I added a new component - ResizableButton. There were a few things that had to be changed to make it resizable and movable since it is not a Container. The main difference is that the Button class by default has the mouseChildren property set to false, which prevents the move and resize handles from getting mouse events.

112 comments:

Miroslav said...

it is great !

but when i use it in canvas, viewStack(this is important for me), vbox or hbox,...

it seems like i can't move it as good as in application tag.

is it a bug ? could you help me please

Chris Callendar said...

Hey Miroslav, try now (clear your cache if it doesn't work).

I changed how the moving/dragging works. Now it works much better (it doesn't do the drag and drop anymore).

Miroslav said...

now it works perfekt :) thanks a lot :)

i already find a solution for the last release maybe to someone it could help.
it a little hack :)

all you have to do is to put this component where you want to use a drag and drop

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" backgroundColor="#CCCCCC" backgroundAlpha="0" />

Miroslav said...

i find a bug, it seems like binding is not running.

for example i have a bindable variable
[Bindable]
private var myWidth:int = 200;

and then i have a component

<resize:ResizableWindow width={myWidth} resizable="true" moveable="true">

<mx:Text text="{myWidth.toString()}" />

</resize:ResizableWindow>

when i run this, and resize window, the binding variable is not changing

i'm having the same issue with height and x, y position

is there an easy way to fix it ?

thanks a lot :)

Chris Callendar said...

Hey Miroslav,
So first off I'm not an expert at binding. But I think the binding you did above is a one way binding. When the value of the myWidth variable changes it causes the ResizeWindow.width property as well as the Text.text property to change. But when the ResizeWindow.width property changes it doesn't bind it back to your variable.

There are two ways to solve the problem:
1) In ActionScript add an event listener function on the ResizeWindow for the "widthChanged" property, and in that function manually change the value of your myWidth variable.
2) Use the BindingUtils class to bind the ResizeWindow.width value to your variable. First make myWidth public, then add an id to your ResizeWindow tag and do something like this in ActionScript:
BindingUtils.bindProperty(this, "myWidth", resizeWindow, "width");Let me know if this doesn't work or doesn't make sense.
Chris

Miroslav said...

hey Chris :)

yeah it makes sense :)
i'm now just working on my first flex project so definitely i'm really not an expert in flex :)

i will read some documentations to solve this problem properly.

thanks :)

Anil said...

Its nice.
Can i use it in my project?

Chris Callendar said...

Hi Anil,
Yes, it is freely available for anyone to use. To download right click on the example above and choose "View Source". That will open a new window showing you the source code. If you want to download all the source code click on the "Download" link in the bottom left corner of that page.
Chris

Mark Brindle said...

I have just started a new Flex project at work and this component will be used everywhere.

Great work!!!

Thanks

Chris Callendar said...

Glad it helps! Let me know if you find any problems with it. I've also been thinking of making it resizable from anywhere around the border instead of just in the bottom right corner... maybe later.

Alejandro Alvarez said...
This comment has been removed by the author.
Anonymous said...

Hi, is there any way to move the movable component just from the white panel besides the title bar.?

Chris Callendar said...

Hi there,

I've made a new example here which shows how you can do what you asked:
http://keg.cs.uvic.ca/flexdevtips/resizecontainers/ResizeExample.html

I had to make some small changes to the ResizableWindow class to add a dragComponent property (which defaults to the titleBar). This is the component that listens for mouse drag events.

Chris

Anonymous said...

Hi Chris, thanks for the speed, they are just the functionalities I'm looking to use. Excelent.!!!
When do you think can publish the new sources to get the changes, they will help me a lot.
Best

Anonymous said...

Hi, I found the changes on the Main example. Thanks. :)

Chris Callendar said...

Sorry, I had forgotten to include the View Source option on the new example. Glad you found it anyway.

Anonymous said...

Ive been looking for something like this for a while now. You just made my day, thank you.

yonghan said...

Thanks a lot for the codes...

capuccino video chat said...

Is there a way to constraint the resize ?

Chris Callendar said...

To constrain the size of the panel just set the minWidth/maxWidth, minHeight/maxHeight properties.

pavel said...

Nice work! Will you mavenize your component library ? If you want to, I can help you... another way is to merge with flexlib project, isn't it ?

One more time, thank you.

Phil said...

I really like your components, especially the movable and sizable window.

However I have run into a slight problem. If I set both sizable and movable to "true" then the window moves and resizes at the same time and the mouse does not release. It does not matter if I create the component with actionscript or use "mx". What I also found out is if I create the component with Actionscript with movable "false" and resizable "true" when I create the component and then set movable to "true" after the component is added to the window then everything works fine. Resize and moving the windows works normally.
By the I am using Flex 3.4 on Windows 7.

Any help you can provide will be greatly appreciated.

phil

Chris Callendar said...

Hi Phil,
Can you give me some more information on what exactly you're doing?
When you say "the window moves and resizes at the same time" - are you dragging the titlebar? Or the resize handle?
And what do you mean by the mouse does not release? When you release the mouse then resize or move still continues?
Chris

Daniel said...

Hey Chris,

I really love this class, Flex builder was definitely lacking components like these!

I've had the same issue as Phil. I am creating an AIR application and when I drag the resize handle, the window moves with the mouse as well. As a matter of fact the window moves whenever I drag from the left and right edges too, not just the titlebar. The, when I release the mouse button (from the resize handle), the window is still moving with the mouse.
I'll let you know if I find something when looking through the source!

Thanks,
Daniel

Daniel said...
This comment has been removed by the author.
Daniel said...

just to let you know that I solved the problem by adding:

if (event.target is UIComponent) {
return;
}

in "MoveManager" under "dragComponentMouseDown"

Chris Callendar said...

Hi Daniel,
Thanks for the posts. I hadn't tested this component in AIR, but I see exactly what you and Phil are talking about. For some reason the MoveManager also handles the mouse down and move events even though they aren't inside the titlebar!

I've added two fixes which should ensure that it works properly. The first simple fix was to add event.stopImmediatePropagation() inside the ResizeManager.resizeHandler(event:MouseEvent) function. This stops the MouseEvent from propagating to the MoveManager.

The second fix is inside the MoveManager.dragComponentMouseDown(event:MouseEvent) function (as you said!). I've added a new function called inHierarchy(dragComponent, event.target) which determines if the target component (that had a mouse down event) is either the same as the drag component (titlebar), or is contained inside the drag component. This way the dragging only works when you drag the titlebar now, not the edges.

I've also update the example above, although your browser might cache the old version.

Thanks again,
Chris

Anonymous said...

Chris-

Great stuff! Thanks!

One question: Is there any way I can constrain the move dragging to stay within my parent container? I've been able to do that with resizing by setting maxWidth and maxHeight when dragging starts, but I don't know how to constrain the move.

Thanks again,

Patrick Jamieson

Chris Callendar said...

Hi Patrick,

Thanks for the comment. That is a good question, and something that could be very useful I think.

I've updated the example above to now include the option of constraining the movement to the parent's bounds.

All the code that I changed is in the MoveManager - see the constrainToParentBounds property (true/false). I also added a constrainToBounds property in case someone wanted to have a custom rectangle to constrain the movement.

This works very well when the parent is a Canvas. But when the parent is a Panel (or TitleWindow) the constraining doesn't work perfectly due to the size of the borders. I tried adding in the parent's borderMetrics, but it is still off by a few pixels.

Cheers,
Chris
Nov 30th, 2009

Anonymous said...

Thanks, Chris. I like it!

I was listening for the move event, then popping the component back within the parents bounds, if it had moved outside them. Your constraint solution is much better.

If you'd like to see how I'm using your move and resize managers, check it out at easycoolnow.com. (I'm expecting to officially launch the site later this month.)

I hope your holiday season is as happy as you've made mine.

Patrick

Chris Callendar said...

Hey Patrick,

That is a pretty awesome website! Makes me hungry :) The tree control with images is pretty slick.

A few comments if you want them. It would be useful to have a "send to back" button to help with ordering the layers of images, text and background colors (the famfamfam icon set is great if you ever need more icons).

Also, you might consider making a custom preloader for your site (check out my blog post on Custom Preloaders)? I think it makes it look more professional, and there are lots of possibilities for your site. Such as starting with a blank label template and slowly adding content (images, text, etc) as the swf loads until it reaches 100% and you show the finished label. :)

Anyways, awesome site, and happy holidays to you as well.
Chris

Peter Weinstein said...

Thank you so much for these classes, which will save me the need to invent them myself.

My initial experience with them required some fiddling:

* Explicitly setting layout="absolute" although the parent layout is absolute

* Required a drag component for resizing to work properly, with the corner underneath the mouse

* With a drag component, does not drag from the title bar (what I really want is dragging from the title bar only, as in the example)

Thanks again -

Chris Callendar said...

Hi Peter,

Thanks for the comments.

You always have to set the layout="absolute|vertical|horizontal" property, it is not something that gets inherited from it's parent.

Resizing the ResizableWindow component should work properly without a drag component. If you don't specify a drag component, or if you set it to null then the window title bar is used as the drag component.

I'm not sure I understand your third point. If you set the drag component to something other than the titlebar, then of course you won't be able to drag from the titlebar. If you want to drag from the titlebar, then don't set the drag component, it defaults to the titlebar.

If you are still having problems let me know, or post an example and I'll try to help out some more.
Chris

Peter said...

Chris,

I appreciate the support, thanks yet again.

Without a drag component, I get undesired behavior including dragging from the entire window not just the title bar, resizing gets very out of sync with the mouse location, and the window moves when it should just resize. I'm guessing I'm using ResizableWindow in an untested way. These are the options I'm using (below). I used the source code from the zip file. I renamed the package but made no other changes.

You have saved me a lot of effort. I don't expect you to solve every little problem for me, but I do appreciate your help. My email is peterw@umich.edu if you'd rather go offline.



Thanks,
Peter

Peter said...

Oops, let me try posting the options without the angle brackets:

resizable:ResizableWindow id="listWindow" x="2" y="400" width="800" height="305" backgroundColor="0xE1F0F0"
dragComponent="{listWindowDrag}"
movable="true" resizable="true" layout="absolute" moveHandleColor="0xFF0000"
title=" Model video contents" status="" showCloseButton="false"
verticalScrollPolicy="off" horizontalScrollPolicy="off"

Thanks -

Chris Callendar said...

Hi Peter,

Thanks for posting the MXML, using it I found the problem right away. The mouse down listener gets added to the window instead of the titlebar (when you don't specify a dragComponent) because the titlebar hasn't been created yet (when movable="true").

I've updated the examples above with the fixed code. I think this should solve the problems you mentioned above.

Chris

Peter said...

Chris,

Super, thanks so much for the support!

I have another question. I need to add some buttons to the titleWindow title bar. The titleBar class does not support this, so I added them to the window's parent, with x and y bound to the window's location.

Two problems with this approach are:

-- When dragging the window, the buttons are left behind until the drag is complete.

-- More seriously, after a move the buttons are behind the window and not clickable.

It seems to me the easiest solution would be to add functions triggered by the start and end of the move, which would, respectively:

-- Make the buttons not visible during the move

-- Set the buttons' child indices to be on top afterwards.

My initial guess would be that the dragStart and dragEnd events would serve perfectly. However, when I add hooks for these events to the mxml for the resizable window, I do not get a response.

Does my question make sense to you?

Thanks again -- I hope you are enjoying the holidays.

Peter

Chris Callendar said...

Hi Peter,

Whenever I want to add custom buttons to the titlebar I always subclass the TitleWindow (or ResizableWindow) component, and add in my new buttons in the createChildren() function like this:

override protected function createChildren():void {
super.createChildren();
// titleBar should be created now
titleBar.addChild(yourButton);
}

Then you override the layoutChrome() function to position the button. See the ResizableWindow for more details since it does this with the move handle.

override protected function layoutChrome(w:Number, h:Number):void {
super.layoutChrome(w, h);
// e.g. position your button on the left of the close button
yourButton.x = closeButton.x - 22;
}

I would imagine you could do it your way, but it sounds difficult.
Hope this helps,
Chris

ps I wrote the code above from memory, so there might be syntax errors.

Dominik Hurnaus said...

Great post! I really like your way of adding resize-capabilites to windows using this ResizeManager. Is there a way to also change the mouse cursor when the mouse is over the resize area?
Dominik

Chris Callendar said...

Hi Dominik,

I've made an update to the example above to add move and resize cursors.

The code is all in the MoveManager and ResizeManager classes.

See my January 5th 2010 update above for more information.

Chris

Anonymous said...

Hi, thanks this is great - A question though: What event can I listen for to know

A. When does the resize start?
B. When is a resize finished?

Thanks again.
SG

Chris Callendar said...

Hi SG,
I've changed the example above to now dispatch the events resizeStart and resizeEnd events. There are constants for those two strings in the ResizeManager class, as well as in the resizable components too.
Thanks for the suggestion!
Chris

Anonymous said...

hi !!

thanks for the component

silly question : what are the conditions to use this code ? Is is public domain ? Is it part of some lib somewher ?

Thanks

Chris Callendar said...

It's freely available.
Chris

anup kumar said...

how to resize proportionately.

Chris Callendar said...

Hi Anup,

I've updated the example above to show you how to fix the width/height aspect ratio when resizing. Simply set window.keepAspectRatio = true and it should work. It is false by default.

Thanks for the idea,
Chris

Jacob Samuel said...

Hi,

This is an incredible library! Respect Due! I noticed the source doesn't use Spark components. Is there any chance you'll be porting to Flex 4 in the near/distant future?

Thanks,
Jacob

Anonymous said...

Thanks a lot chris
Its a very useful component.

anup kumar said...

Thanks a lot chris
its a very useful component

Chris Callendar said...

Hi Jacob,

I have only just started using FB4, so I don't have any immediate plans to port these components to use Spark. But as soon as I do I'll post them here.

Chris

anup kumar said...

hi chris
i need to develop a vertically auto scrolling list control
smoothly
i have tried verticalscrollposition++ on timer function
in creation complete of list control for auto scroll
but smooth scrolling is not achieved

Chris Callendar said...

Hi Anup,

Lists can only be scrolled one item at a time, so you won't be able to get very smooth scrolling even if you only increase the verticalScrollPosition by 1.

Another option would be to use a container like a VBox and add Label items in, then you can control the scrolling by 1 pixel at a time.

To show you what I mean, I've put up an example:
http://keg.cs.uvic.ca/flexdevtips/smoothscrollinglist/SmoothScrollingList.html

It uses a custom class that I often find useful called ButtonBox which acts like a CheckBox list - each item is selected and de-selected using a single left click unlike the usual List selection mode. Try playing with the scrolling speed and see what you think. If you want the ButtonBox class to work exactly like the List selection does then you'll have to do some work to make it act the same :)

In that example I set the itemRenderer="flex.utils.ui.SelectableLabel" to make it look like a List. If you remove that then you'll see a CheckBox list.

Chris

anup kumar said...

Hi Chris
excellent work
Thats what i was looking for
only thing remains is ,can we set the continous scrolling that is when it reaches at end it should scroll from bottom

and also can we set the row count property like list
to it

ts very useful component in my project
Thanks a lot again

Chris Callendar said...

Hi Anup,

I've updated the same example as above (link) to show you how to make the scrolling reverse at the bottom and go on for ever until you stop it.

And good suggestion about the rowCount property, I've added it and the rowHeight property.

Chris

anup kumar said...

Hi chris
Great work Chris
done with all the issues for this component with the help of ur great work and support

Thanks a lot

anup kumar said...

Hi chris

my requirement slightly changed,is to continous scroll the buttonbox in up direction
so i tried
else if (nextPosition > this.maxVerticalScrollPosition)
{
nextPosition = 0;

}
the problem is its blinking when it coming back from lastposition to first position i need smooth and continoos scrolling so that user should not be able to detect.

is it possible by setting the rowcount and then duplicating the dataprovider with rowcount at bottom

anup kumar said...

Hi chris
iam just stuck here

In ButtonBox when iam scrolling upward direction,
the problem is its blinking when it coming back from lastposition to first position i need smooth and continoos scrolling ,as its is coming From bottom
so that user should not be able to detect.

iam trying to duplicate the dataprovider
Thanks

Chris Callendar said...

Hi Anup,

I don't think I understand your problem.

Did you look at my updated example here? When you click start it shows the list scrolling down first, then when it reaches the bottom it comes back up. The scrolling is very smooth in both directions.

Maybe I'm missing something...
Chris

anup kumar said...

Hi Chris
sorry for being unclear
My requirement is,
I need to continous scroll the items in Button Box only in one direction i.e Up direction
So i tried here
else if (nextPosition > this.maxVerticalScrollPosition)
{
nextPosition = 0;
//reverse = true;
//nextPosition = this.maxVerticalScrollPosition - (nextPosition - this.maxVerticalScrollPosition);

}
the problemis, when its scrolling and reaching the last item and moving back to First item Its giving a blink.
it should look like its coming from botom of button box(in second,third... round trip).

Thanks

anup kumar said...

Hi Chris
I have prepared the Rss Feed reader
The problrm is
For some Feed Urls its saying
Error,
A term is undefined and has no properties.

how to resolve this issue.

Thanks

Chris Callendar said...

Hi Anup,

Ah, I understand you know. You basically want a list that scrolls continuously, so when it reaches the bottom the items at the top show up again. That makes sense.
Do you even need the scrollbar to show up? Because if you are scrolling programmatically, then maybe it is not needed. You could maybe determine when an item goes off the top, and add it to the bottom.

As for your other question about the RSS Feed URL getting an error saying A term is undefined and has no properties, this is a null pointer error. Run the application in debug mode, and it will tell you the line number where it is happening, and then you can figure out why the object is null.

Chris

anup kumar said...

Hi Chris
In button Box,
i need scroll bar is set from outside,it can be on or off.

In RSS FEED READER

Actually,the problem is
Some Feed urls are fetching the updates in my list based itemrenderer.
some Feed urls are not working,
i tried to debug for this urls
its retrieving the view source of the page in the result property.
working urls its successfullyretrieving an xml and the format is event.result.rss.channel.item

Thanks a lot

Chris Callendar said...

Hi Anup,
In order for the continuous scrolling to work in the ButtonBox (by setting the verticalScrollPosition), the verticalScrollPolicy property must be set to "auto" (default) or "on". If you want the scrollbar hidden, then you'll have to modify the ButtonBox class and manually hide the verticalScrollBar.

For example:
override protected function updateDisplayList(w:Number, h:Number):void {
    super.updateDisplayList(w, h);
    // show or hide the scrollbar?
    if (verticalScrollBar && verticalScrollBar.visible)) {
        verticalScrollBar.visible = false;
    }
}

I don't have any idea what is wrong with some of the urls in the RSS Feed Reader.

Chris

anup kumar said...

Thanks Chris

anup kumar said...

Hi Chris
any idea on light weight cover flow component in flex.
i mean without using swc files.
I need it.
Thanks

Chris Callendar said...

Hi Anup,

No, I don't know of any cover flow components. Have you played with Flex 4 at all? They have some new layouts and examples that might be useful.

Chris

Mr. B said...

Have you ever put a grid inside of a resizable window? I played around with it a little but and I'm wondering how I would get the grid to grow/shrink to the new size of the parent window.

Chris Callendar said...

Hi Mr. B,

If you set the grid to have a width and height of 100% then the grid will automatically resize with the window.

Chris

anup kumar said...

Hi chris
need help in butttonBox
iam nnot getting it.
continous scroll the items in Button Box only in one direction i.e Up direction
So i tried here
else if (nextPosition > this.maxVerticalScrollPosition)
{
arraycollection.source.concat(arraycollection);
arraycollecetion.referesh();
//reverse = true;
//nextPosition = this.maxVerticalScrollPosition - (nextPosition - this.maxVerticalScrollPosition);

}

thanks

Chris Callendar said...

Hi Anup,

What I did was something slightly different. I added 12 sample items (only 7 of which are visible at one time), then I use a timer to start scrolling up, and once the first item moves off the top of the view, I remove it and put it last.

Here is an example (with view-source):
http://keg.cs.uvic.ca/flexdevtips/smoothscrollinglist/continuousscrollinglist/ContinuouslyScrollList.html

It will only work if the scrollbar would normally by visible (more items than can be shown). But I hide the scrollbar by default because otherwise it jumps around and is distracting.

Chris

Mike said...

Hello!
Great work, it's really nice and smooth.

I have a question about the events: why are you not removing the handlers in resizeMouseMoveHandler?
As I understand it, the handlers will be re-added upon the next mouse move. Doesn't that create some memory leakage?

Best regards, Mike.

Chris Callendar said...

Hi Mike,

In the ResizeManager class, in the startResize() function I add two listeners - MOUSE_MOVE and MOUSE_UP.

Both of those listeners are removed in the resizeMouseUpHandler() function.

So I don't remove any handlers in the resizeMouseMoveHandler() function because I still need them until the user has finished moving (with the mouse down) and released the mouse button.

I agree that having extra listeners hanging around is a bad idea, but it turns out that if you repeatedly add the same listener, it actually only gets added once.

E.g.
btn.addEventListener(MouseEvent.CLICK, someFunction);
btn.addEventListener(MouseEvent.CLICK, someFunction);
btn.addEventListener(MouseEvent.CLICK, someFunction);

someFunction() will only get called once when the button is clicked, not 3 times as you might expect.

Chris

Anonymous said...

Hi chris,

Great App ( resizable window ). However I am having a problem with a phantom window popping up. It only happens once with the initial addChild function.

I am using it as a popup window so I have to add it to the stage.
Background of parent document is black so when I addChild(), I see a small clear window in the upper left corner with the parent background completely grey. It last for about 1 sec then my window opens up fine. I don't have the problem after the first resizable window is added to the stage.

Any idea on what can or should I do to get rid of the phantom window?

Chris Callendar said...

Hi there,

I don't have any ideas off hand.

How are you adding it as a Popup window? Are you using the PopUpManager? Or adding it to the stage yourself?

If you can help me reproduce this, then I might be able to find a solution.
Chris

Erwann said...
This comment has been removed by the author.
Anonymous said...

I am doing a simple " this.addChild(resizableModule); " to the application

inside the resizableModule module is ... .

I also use the PopUpManager as well.

I am adding to the stage myself..

Anonymous said...

inside the resizableModule module is ... .

< ResizableWindow >
< mx:Canvas > ... < mx:Canvas />

Anonymous said...

< ResizableWindow xmlns="com.resizables.*" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
styleName="panel" cornerRadius="6" showCloseButton="true" close="close()" width="500" height="400"
creationComplete="init()" xmlns:Resizables="com.resizables.*" name="misc" horizontalScrollPolicy="off" >
< mx:Canvas > ..... < mx:Canvas />
< / ResizableWindow >

anup kumar said...

Hi Chris
This is exactly i need.
Thanks a lot.

Chris Callendar said...

Hi Anonymous,

Sorry I didn't reply sooner.

You could try is setting visible="false" property on the resizableModule or ResizableWindow in the MXML, and then when you actually want to show the resizable window, changing it to visible="true".

Whenever I've used the PopUpManager I usually don't create the component in MXML, instead I do something like this in ActionScript:

var window:ResizableWindow = new ResizableWindow();
PopUpManager.addPopUp(window, parent, true);
PopUpManager.centerPopUp(window);

Chris

Anonymous said...

Hi!, is a great app, but how can i move the canvas?, i just can resize the canvas.

thanks a lot.

Chris Callendar said...

To be able to move the canvas you'd have to use the MoveManager class. I'd suggest downloading the source code from the example above (right click view-source), and look at what is done in the ResizableWindow class. It uses both the ResizeManager and the MoveManager classes to support resizing and moving the window.

Chris

Anonymous said...

Hi again!, Thanks Chris for you answer, i can move the canvas now. But even in the resizableWindow if i change resize="true" and dragComponent="{dragPanel}" when i resized the window it is moved, and don't can put other canvas inside the canvas that i want to moved.

exist other solution?, sorry i am very new in flex,

Thank you

Chris Callendar said...

Hi,

Very good catch, that is a bug.
The fix is very simple, edit the ResizeManager class, and add this one line inside the resizeHandler() function:
event.stopImmediatePropagation();

That way the event won't propagate to the MoveManager, and so the window will only be resized, not moved.

So the full function should look like this:
private function resizeHandler(event:MouseEvent):void {
if (enabled) {
event.stopImmediatePropagation();
startResize(event.stageX, event.stageY);
}
}

Anonymous said...

Hi Chris!
Thank you, is working very well now

Chakravarthy said...

Hi Chris,

Really a great post, you have made my life easier.

Did you try making a Button movable and re-sizable? Why are only containers re-sizable and movable why not flex components, can you explain?

Thanks in Advance.

Chakravarthy said...
This comment has been removed by the author.
Chakravarthy said...
This comment has been removed by the author.
Chris Callendar said...

Hi Chakravarthy,

I've updated the example above to include a ResizableButton class. It turned out to be quite simple after a lot of playing around with it. The main important difference between Containers and Components as I mentioned above is that the mouseChildren property is set to false, meaning that the move and resize handles didn't work. Also, the MoveManager wasn't working properly with Buttons, so I had to make a fix there too.

Cheers,
Chris

Chakravarthy said...

Chris,

How do u find time to work on all these requests? not just mine but all the requests above. Really I have no words to praise your support. You are great!!

I have downloaded and used ResizableButton, its awesome, just what I needed.

You said you made some changes in MoveManager, please update the example viewsource with latest source.

Thanks a lot.

Chris Callendar said...

Hi,
I don't know how :) I get to them when I can, sometimes it takes me a week or two if I'm really busy.

The MoveManager is up to date, there was only a tiny one line change I think.

Chris

Mike said...

Hi Chris,

first of all, thanks for the great code!! Exactly what i was looking for!

I have one problem though. i try to integrate your code (ResizableWindow) into my flex 4 code, which works fine if i just create one instance of the ResizeableWindow. But when i create two instances then i just can resize and/or drag the ResizableWindow i created last. I create the 2 instances within a tabnavigator. Do you have any suggestion what the problem could be?

Thanks again for the excellent code and effort.

Chris Callendar said...

Hi Mike,

Have you tried my new version of the resizable controls for Flex 4/Spark?

http://flexdevtips.blogspot.com/2010/06/flex-4-spark-resizable-controls.html.

Hopefully if you use those instead it will fix your problem. If you still need to use the Flex 3 version I can look into why that is happening.

Chris

lynn said...

HI,

sorry if my question is a stupid one. I'm new with flash/flex/actionscript.

I'm wondering if i could use your mxml code in an xml format. currently i'm working with a program that uses xml and action script. I want to include your resizable panel to my program but I'm not sure what to do. Can I combine both mxml and xml?


Or should I just use the *.as file and incorporate it to my program?

Plese help!

Thanks

lynn

Chris Callendar said...

Hi Lynn,

I'm not totally sure I understand your question. MXML files are xml files. They are used by Flex/Flash Builder as the main application files, and any other custom component files. What program are you using to compile your ActionScript files?

Chris

lynn said...

HI Chris,

I'm using Flashdevelop to compile.

at the moment, I save my file as *.xml. The code that you gace is in *.mxml. I'm not usre how should I incorporate your file (*.mxml) in my file (*.xml)/

Thanks!

Chris Callendar said...

Hi Lynn,

I don't know much about FlashDevelop, but I'd suggest you do some searching to see what other people do.

In a quick search that I did (http://www.flashdevelop.org/wikidocs/index.php?title=AS3) it says that if you are using the Flex SDK then you can compile .mxml files, so I think you should be able to just include the mxml that I provide.

Chris

soufiane said...

please help me I don't anderstand the example, can some one give me o simple example how to create an resizable TextArea with flex 4?

thanks

Anonymous said...

I am looking for a resizable dialog which can be resized from all four sides, not just lower-right corner. Does anyone have an example for Flex 3?

Paul said...

Hi Chris, your resizable panle code works great and was a quick result for what I wanted. Thanks. But as always, I have one small issue.

I am working on Flash Builder (flex 4) and everything appears to work except for the close button. I get...

Cannot resolve attribute 'close' for component type flex.utils.ui.resize.ResizablePanel.
and

Cannot resolve attribute 'showCloseButton' for component type flex.utils.ui.resize.ResizablePanel

Any suggestions would be great.
Thanks in advance
Paul

Chris Callendar said...

Hi Paul,

Have you tried using the newer resizable components that I wrote for Flex 4?

I made another blog post on them here

If you are using the Flex 3 ones for a reason, then I can look into why the close button isn't working in Flex 4.

Chris

Yordan Yanakiev said...

Hello.

From where we could download this greath looking library of components, so we can use then ? :)

// sorry if this is lame question, but i dont really find any link to it :(

Chris Callendar said...

Hi Yordan,

In almost all my example applications you can right click on the app and choose View Source. From there you can either just copy the source code into Flash/Flex Builder, or you can click on the Download source link in the bottom left corner.

Alex said...

Hi Chris,

Great Component, I have a problem with this component when I use ResiseWindow as Popup with bubble chart the size of the bubble reduces. Please let me know if you have any fix for this?

Thanks,
Alex

Chris Callendar said...

Hi Alex,

Sorry, I've not run into this problem.

Have you tried the newer Flex 4 resizable components?

Chris

tharanprabhu said...

Hi Chris,

Very nice component. I am using button component it's parent is canvas. when ever the button is dragging in to outside of the canvas its dragging. so i need to do outside dragging restriction. how to achieve this . Please help me.

Anonymous said...

Hi Chris,

Did you resolved the below one?

making window/widget resizable from anywhere around the border instead of just in the bottom right corner...

Thanks,
Naveen

Chris Callendar said...

Hi Naveen,

No I haven't done that, and don't plan to! I think it would be nice, but just don't have the time.

Chris

Naveen said...

Chris,

thanks for your early reply..

Is there any way that i will get it done? is it duable? if yes do you have any code from different source?

Naveen.

Chris Callendar said...

Hi Naveen,

I think it is do-able yes, but not that easy. I haven't got any code that would help except for the source code in the example above.

If I was doing this in Flex 4, I would make a custom skin for Panel, and I would add four thin Group elements - one for each side that are maybe 5 pixels wide/high that have mouse listeners to handle the resizing.

But beyond that I don't know.

You might google Flex MDI - I know there was a project called that, which had resizable windows and I think they were done the way you are wanting. I did a quick search myself but didn't find anything.

Good luck.

Anonymous said...

Fantastic piece of code that seems to work very well. Thanks very much for making it publicly available. The only changes I needed to make were to fix warnings in the StyleManager which I changed to:

FlexGlobals.topLevelApplication.styleManager.getStyleDeclaration(.)

Anonymous said...

hi chris,

thanks for your component.
But i need to show the resizehandle on every corner of the window as your component shows on bottom right corner of the window.