miércoles, 3 de junio de 2009

Extendiendo de el SuperTitleWindow para que todas tus ventanas tengan "Cerrar" y "Aceptar" de forma nativa


Desde que empece mi aprendizaje en el desarrollo de aplicaciones con flex, he tenido la necesidad de crear ventanas emergentes con un formato especifico, todas ellas debian tener un botón de "Aceptar" y "Cancelar" para cerrar la ventana en el momento que el usuario lo creyera conveniente. En este ejemplo vamos a ver como se puede estantadrizar el comportamiento de todas las ventanas emergentes de una aplicacion apartir de la clase SuperTitleWindow.cs que tiene inmerso el siguiente comportamiento:

  1. Metodo "Aceptar" cuando se presiona el botón "Enter" del teclado.
  2. Metodo "Cancelar" cuando se presiona el boton "ESC" del teclado.
  3. Metodo "Limpiar Pantalla" cuando se presionan las teclas "shift" + "Delete".
  4. Botón cerrar en la parte superior derecha de la ventana (al estilo windows).
  5. Obliga a definir el foco inicial del mouse dentro que se utilizara al desplegarse la ventana.
  6. Permite modificar la logica a realizar una vez despachado el evento "Cerrar" o "Aceptar".


Para que se entienda un poco mejor vamos a ver un ejemplo de ventana emergente que herede del SuperTitleWindow.

Si observamos el codigo de esta ventana vamos a notar unas pequeñas particularidades con respecto a las ventanas tradicionales:

Código LoginWindow.mxml

<?xml version="1.0" encoding="utf-8"?>
<SuperTitleWindow xmlns="popupClasses.*" xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="174" title="Inicio de sesión">
<mx:Script>
<![CDATA[
import popupClasses.SuperTitleWindowEvent;
import mx.managers.PopUpManager;

private function aceptarClick() : void
{
//Lanzo el evento SuperTitleWindowEvent.OK_WINDOW para que se llame el metodo okPressed
var ev : SuperTitleWindowEvent = new SuperTitleWindowEvent(SuperTitleWindowEvent.OK_WINDOW);
this.dispatchEvent(ev);
}

private function cancelarClick() : void
{
//Lanzo el evento SuperTitleWindowEvent.CANCEL_WINDOW para que se llame el metodo cancelPressed
var ev : SuperTitleWindowEvent = new SuperTitleWindowEvent(SuperTitleWindowEvent.CANCEL_WINDOW);
this.dispatchEvent(ev);
}

override protected function setWindowFocus():void
{
//Seteo el foco al text input llamado "usuario"
//si no implemento esta funcion entonces se disparará una excepcion
//de esta manera obligo a que siempre se defina el foco inicial de una ventana emergante
usuario.setFocus();
}

override protected function okPressed(event:SuperTitleWindowEvent):void
{
//aqui inserto mi logica de aceptar, por ejemplo una validacion.


PopUpManager.removePopUp(this);
}

override protected function cancelPressed(event:SuperTitleWindowEvent):void
{
super.cancelPressed(event);//Debo remover esto si deseo sobreescribir el comportamiento original al momento de presionar cacelar
}

override protected function clearPressed(event:SuperTitleWindowEvent):void
{
//aqui va la logica para limpiar la ventana, se despacha con las teclas "shift" + "delete"
super.clearPressed(event);
}
]]>
</mx:Script>
<mx:Label text="Ingrese el nombre de usuario y contraseña"/>
<mx:HBox width="100%">
<mx:Label text="Nombre de usuario:"/>
<mx:TextInput id="usuario"/>
</mx:HBox>
<mx:HBox width="100%">
<mx:Label text="Contraseña:"/>
<mx:TextInput/>
</mx:HBox>
<mx:ControlBar horizontalAlign="right">
<mx:Button label="Cancelar" click="cancelarClick()"/>
<mx:Button label="Aceptar" click="aceptarClick()"/>
</mx:ControlBar>
</SuperTitleWindow>

Lo primero que notamos es que la ventanta hereda de la clase SuperTitleWindow, luego notamos que existen 6 funciones principales que las podemos utilizar dependiendo de nuestros requerimientos:
  1. okPressed() : Esta funcion se dispará automaticamente cada vez que la ventana esta a punto de cerrarse, en esta funcion debo agregar la logica a realizar justo antes de cerrar.
  2. cancelPressed() : Ocurre igual que en la funcion okPressed pero en este caso cuando la ventana esta apunto de cerrarse.
  3. clearPressed() : Esta funcion se ejecuta automaticamente cada vez que la ventana debe limpiarse, se debe introducir aqui la logica de limpiado, por ejemplo en este caso la logica de limpiado es:
    usuario.text = "";
    clave.text = "";
  4. setWindowFocus(): esta funcion es oblicatoria de sobreescribir, esto se debe a que debemos colocar el foco del mouse sobre el primer campo del formulario que se encuentra en la ventana, de esta manera la aplicacion fluye sin la necesidad de la intervencion del mouse. Si no se sobreescribe esta funcion, entonces ocurre una excepción.
  5. cancelarClick() : Esta funcion la debemos crear en caso de que queramos colocar un botón de cancelar dentro de la ventana, esta funcion debe despachar al evento SuperTitleWindowEvent de tipo SCANCEL_WINDOW para que sea escuchado por el SuperTitleWindow y volvamos a caer en el metodo cancelPressed().
  6. aceptarClick() : Esta funcion la debemos crear en caso de que queramos colocar un botón de cancelar dentro de la ventana, esta funcion debe despachar al evento SuperTitleWindowEvent de tipo OK_WINDOW para que sea escuchado por el SuperTitleWindow y volvamos a caer en el metodo okPressed().
Por otro lado tenemos 3 propiedades configurables para la confirmacion de las tres acciones tipicas en la ventana Aceptar, Cancelar, Limpiar:
  1. askClear: Defino si debo o no debo confirmar la limpieza de la pantalla, por defecto es verdadera para obligar al prigramador a deshabilitarla en caso que lo crea pertienente.
  2. askOk: Defino si debo o no debo confirmar el cerrado de la pantalla, por defecto es verdadera para obligar al prigramador a deshabilitarla en caso que lo crea pertienente.
  3. askCancel: Defino si debo o no debo confirmar el cerrado de la pantalla, por defecto es verdadera para obligar al programador a deshabilitarla en caso que lo crea pertienente.
Al heredar de esta clase estamos teniendo varias ventajas, la primera de ellas es que estamos estandarizando la implementacion de las ventanas, de esta manera el usuario se acostumbrará a presionar el boton "Enter" para aceptar las ventanas emergentes y "ESC" para cancelarlas. Por otro lado se organiza y estructura el código, se fomenta la reutilizacion del codigo y si se necesita variar algun comportamiento se puede manipular a la SuperTitleWindow.cs en lugar de realizar modificaciones a todas las ventanas por separado.

Para descargar este ejemplo pueden hacer click en el siguiente vinculo, cualquier duda no duden en preguntarlo como comentario de este post, espero que les sea de tanta utilidad como a mi.


2 comentarios:

  1. Que tal la verdad me parece excelente . . . .
    Una pregunta tendra alguna direccion en donde pueda escribirle para que me pueda ayudar a disipar algunas dudas . . .??
    Saludos y de antemano muchas gracias

    ResponderEliminar
  2. Hola, es muy interesante tu Blog, estare en contacto siempre, ya que estoy iniciando a desarrollar con Flex.

    Saludos, que tengas buen día.

    ResponderEliminar