Saturday, May 30, 2009

Making a draggable titlewindow without PopupManager

I wanted to make a application with a Windows-like interface with multiple draggable windows. TitleWindow was the obvious choice for the windows but they are only draggable only when created as a popup by the PopupManager.

I didn't want to use TitleWindow+PopupManager because I wanted to reserve PopupManager to display real popups that will always be on top of other components. Basically I wanted the windows to not be children of the systemManager but of a particular Canvas. This also means that I could have multiple "desktops" in the future.

To do this, first I created an extension of TitleWindow to make it draggable without being a popup.

DragWindow.as
package
{
import flash.events.MouseEvent;
import mx.containers.TitleWindow;

public class DragWindow extends TitleWindow
{
public function DragWindow()
{
super();
}

override protected function createChildren():void
{
super.createChildren();
this.titleBar.addEventListener( MouseEvent.MOUSE_DOWN, startDragging );
}
}
}

Then I created a WindowManager that replicates the behaviour of the PopupManager.

WindowManager.as

package
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;

import mx.containers.Panel;
import mx.containers.TitleWindow;
import mx.core.IFlexDisplayObject;
import mx.events.CloseEvent;

public class WindowManager
{
// array of all windows in any container
public static var windowList:Array = [];

private static var instance:WindowManager;

public function WindowManager():void
{

}

public static function getInstance():WindowManager
{
if(instance == null)
{
WindowManager.instance = new WindowManager;
}
return WindowManager.instance;
}

public static function addWindow(window:IFlexDisplayObject, parent:DisplayObjectContainer):void
{
if(window is TitleWindow)
{
TitleWindow(window).showCloseButton = true;
window.addEventListener(CloseEvent.CLOSE, WindowManager.closeWindow);
}
window.addEventListener(MouseEvent.MOUSE_DOWN, WindowManager.focusWindow);
parent.addChild(DisplayObject(window));
windowList.push(window);
}

// Brings the window to the top of displaylist of the parent
public static function bringToFront(window:DisplayObject):void
{
var parent:DisplayObjectContainer = DisplayObjectContainer(window.parent);
parent.setChildIndex( window, parent.numChildren - 1);
}

public static function createWindow(parent:DisplayObjectContainer, className:Class):IFlexDisplayObject
{
var window:IFlexDisplayObject = new className();
WindowManager.addWindow(window, parent);

return window;
}

public static function removeWindow(window:IFlexDisplayObject):void
{
var parent:DisplayObjectContainer = DisplayObjectContainer(window.parent);
// Remove from display list
parent.removeChild(DisplayObject(window));
// Remove from window list
windowList.splice(windowList.indexOf(window),1);
}

// Brings the window to the top of displaylist of the parent
private static function focusWindow(event:MouseEvent):void
{
var window:DisplayObjectContainer = DisplayObjectContainer(event.currentTarget);
WindowManager.bringToFront(window);
}

// Removes the window from the displaylist
private static function closeWindow(event:CloseEvent):void
{
var window:IFlexDisplayObject = IFlexDisplayObject(event.currentTarget);
WindowManager.removeWindow(window);
}
}
}

asdasd

2 comments:

  1. Hi,thanks for the share.I want to ask,how to use both of them?Thanks a lot...

    ReplyDelete