A utilização de janelas no Flex 4 pode ser um pouco confusa para quem está habituado com outros sistemas. No Flex para mostrar uma janela, ao contrário de outros frameworks que a classe windown tem um método show(), usamos os métodos estáticos da classe PopUpManager:
- PopUpManager.addPopUp(window:TitleWindow, parent:DisplayObject, modal);
- PopUpManager.removePopUp(window:TitleWindow);
- PopUpManager.createPopUp(parent:DisplayObject, WindowClass:Class, modal:Boolean):IFlexDisplayObject;
Existe uma documentação sobre como utilizar o PopUpManager mas nesse artigo irei apresentar uma nova abordagem em que as Janelas herdaram o comportamento de fechar e mostrar, e também implementaremos uma janela que possua apenas uma instancia criada ao mesmo tempo, usando o padrão singleton. Com o padrao singleton não importa quantas vezes o usuario clicar no botao para abrir a janela, apenas uma janela será criada.
Primeiro vamos estudar a estrutura proposta nesse diagrama:
A interface IWindow define os metodos que toda janela deverá ter, no caso show() e close() a classe AbstractWindow é quem implementa a interface e define mais um método protegido: handleCloseEvent() esse método não é publico e pode ser sobre-escrito para customizar o a lógica de fechar a janela. Por fim a janela LoginWindow define um método estático getInstance() que retorna uma instância de LoginWindow verificando se ela já não existe.
Vamos aos códigos:
package components.windows
{
/**
* Interface para as classes que representam janelas na aplicacao
*/
import flash.display.DisplayObject;
import flash.events.Event;
import mx.core.UIComponent;
public interface IWindow
{
/**
* Monstra a janela na tela em popup por padrão gera uma janela sem modal
* @param modal Verdadeiro se a janela criada deve ser modal, default para false
* @param parent O component em que a janela ficará por cima, se nenhum parametro for passado a janela vai para o topo da aplicação
*/
function show(modal:Boolean = false, parent:DisplayObject=null):void;
/**
* Fecha a janela. Dispara o evento CloseEvent
*/
function close():void;
}
}
AbstractWindow
package components.windows
{
import flash.display.DisplayObject;
import flash.events.Event;
import mx.core.UIComponent;
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
import spark.components.TitleWindow;
/**
* Implementa metodos comuns as janelas, essa classe não deve ser instanciada diretamente
*/
public class AbstractWindow extends TitleWindow implements IWindow
{
public function AbstractWindow()
{
super();
this.addEventListener(CloseEvent.CLOSE, handleCloseEvent);
}
/**
* Manipula o evento de fechar a janela removendo-a da tela.
* Pode ser sobrescrito para conter comportamentos especificos
*/
protected function handleCloseEvent(event:Event):void{
PopUpManager.removePopUp(this);
}
public function close():void{
this.dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
}
public function show(parent:DisplayObject):void{
PopUpManager.addPopUp(this, parent, false);
PopUpManager.centerPopUp(this);
}
}
}
LoginWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<windows:AbstractWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:windows="components.windows.*" width="400" height="300"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private static var instance:CadastrarCliente;
import flash.events.Event;
public static function getInstance():CadastrarCliente{
if(instance == null){
instance = new CadastrarCliente();
}
return instance;
}
protected override function handleCloseEvent(event:Event):void{
Alert.show("Janela está sendo fechada");
super.handleCloseEvent(event);
}
]]>
</fx:Script>
<windows:layout>
<s:VerticalLayout />
</windows:layout>
<s:Form>
<s:FormItem label="Nome">
<s:TextInput id="username" width="100%"/>
</s:FormItem>
<s:FormItem label="CPF">
<s:TextInput id="password"
displayAsPassword="true"
width="100%"/>
</s:FormItem>
</s:Form>
<s:HGroup>
<s:Button label="OK"
/>
<s:Button label="Cancel"
click="close()"/>
</s:HGroup>
</windows:AbstractWindow>
Na aplicação Utilizamos da seguinte forma
private function showLoginWindow():void{
window = LoginWindow.getInstance();
window.show(this);
}
protected function fechar_clickHandler(event:MouseEvent):void
{
if(window)
window.close();
}
Bem com isso nos temos um gerência de janelas flexiva e mais automática. Basta extender a classe de janelas abstrata para ter uma janela.
Lembrando que em mxml não podemos definir construtores portando não há como não permitir que a classe seja instanciada diretamente sem usar o getInstance. O jeito é manter documentado.
No caso das janelas elas na maioria das vezes serão apresentadas em cima da aplicação inteira não precisando passar o parâmetro de parent, a implementação ficou parecido com o Alert.show() de mx.controls.

