lunes, 29 de septiembre de 2008

Grandes Páginas de Flex


En estos últimos tres meses que me he adentrado en el mundo de flex, he visto que hay mucha mas documentación de la que pensaba, y no solo es simple documentacion, sino documentacion Open Source. Lamentablemente, al principio no conocia muchas de las mejores páginas lo que me llevo a desarrollar infinidad de componentes o aplicaciones que necesitaba, pero que en realidad ya otro las habia desarrollado (no saben lo frustrante que es saber que llevas 3 semanas haciendo algo que ya estaba hecho).

Por eso, he decidido recopilar lo que para mi, son páginas obligatorias a ojear antes de empezar a desarrollar algun componente o aplicación, probablemente lo que quieras hacer ya exista, y no solo existe, sino que ademas te la puedes bajar gratis y con una guia de como usarla!! que perfecto no?

Bueno aqui les dejo una lista de las mejores páginas que según mi humilde opinón les van a servir de mucho:

  • http://blog.flexexamples.com/ Una INCREIBE cantidad de ejemplos, probablemente tienen un ejemplo para todo lo que tu quieras hacer. Es la página que yo mas utilizo.
  • http://code.google.com/p/flexlib/ Una libreria de componentes para flex Open Source, tiene muchos componentes que pueden ser muy utiles y ha sido construida con la colaboracion de toda la comunidad desarrolladora de flex.
  • http://dougmccune.com/blog/ Uno de los gurus mas importantes de flex, publica ejemplos mas avanzados, pero no dejan de ser muy interesantes y uno nunca sabe cuando pueden ser utiles.
Espero que les sirvan estas páginas que para mi han sido de muchisima importancia.


Continuar leyendo...

Video Tutorial Eventos Flex


En este tutorial vamos a profundizar un poco mas en la utilización de los eventos con flex, la utilización de eventos en este framework es primordial para interactuar entre componentes o controles, por ejemplo, si queremos que un botón borre un campo de un formulario, debemos utilizar eventos (en este caso especifico el evento click).

Cada control en flex posee sus propios eventos definidos (los eventos que puede lanzar o disparar) y para saber cuales son solo debemos ir a la documentacion de su clase respectiva y ver de que eventos dispone.

En este tutorial vamos a estar trabajando especificamente con el control Button ya que es muy utilizado en las aplicaciones y me parecio apropiado, se va a utilizar especificamente 4 eventos, Mouse Over, Mouse Out, Creation Complete y Click (cabe destacar que practicamente todos los controles de flex poseen estos 4 eventos).
  1. Mouse Over: Ocurre cuando colocamos el mouse sobre el botón.
  2. Mouse Out: Ocurre cuando retiramos el mouse del botón.
  3. Click: cuando hacemos click en el botón.
  4. Creation Complete: cuando el botón termina de cargarse en la aplicación.
Estos eventos pueden ejecutar cualquier bloque de código (funcion) que nosotros definamos (esta función que se ejecuta es llamada Handler) dentro y fuera de la misma clase. Cabe destacar que la clase botón dispone de muchos otros eventos, y cada uno de ellos aporta una funcionalidad y oportunidad para realizar nuevas interaciones con el usuario.

Bueno les dejo un rar con el codigo fuente del ejemplo ademas del video y el ejemplo en funcionamiento en este post:



Código
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function limpiar() : void
{
LabelClick.text = "";
LabelMouseOver.text = "";
LabelMouseOut.text = "";
LabelCreationComplete.text = "";
}

public function clickHandler() : void
{
LabelClick.text = "Click";
}

public function mouseOverHandler() : void
{
LabelMouseOver.text = "Mouse Over";
}

public function mouseOutHandler() : void
{
LabelMouseOut.text = "Mouse Out";
}

public function creationCompleteHandler() : void
{
LabelCreationComplete.text = "Creation Complete";
}
]]>
</mx:Script>
<mx:Button x="190" y="103" label="Boton de prueba" click="clickHandler()" mouseOver="mouseOverHandler()" mouseOut="mouseOutHandler()" creationComplete="creationCompleteHandler()"/>
<mx:Label id="LabelClick" x="44" y="57" text="Label"/>
<mx:Label id="LabelMouseOver" x="125" y="57" text="Label"/>
<mx:Label id="LabelMouseOut" x="212" y="57" text="Label" />
<mx:Label id="LabelCreationComplete" x="299" y="57" text="Label" />
<mx:Button x="92" y="103" label="Limpiar" click="limpiar()"/>

</mx:Application>
Ejemplo



Continuar leyendo...

Video Tutorial Hola Mundo Flex


Este tutorial es para todas las sabias personas que han decidido empezar en el mundo de flex, es un video tutorial donde explico como crear la primera aplicacion en flex, con el típico "Hola Mundo".

Para empezar esta aplicacion debemos saber que flex es un lenguaje orientado a eventos, todos los controles (textBox, label, textArea, Botones, etc.) interactuan entre ellos disparando y escuchando eventos, por ejemplo:

Si queremos que cuando el usuario presione un botón se llene un label con un texto, entonces debemos decirle al botón que dispare un evento "click" y que cuando eso ocurra una funcion (tecnicamente llama "Handler") se encargue de realizar la accion de llenar el label con el texto deseado.



Un evento puede ser disparado por cualquier clase que implemente la interfaz IEventDispacher, todos los controles o componentes de flex la implementan, asi que pueden disparar eventos, la "Aplicacion principal" tambien puede disparar eventos, siendo uno de los mas populares y utilizados, el evento "creationComplete".

Un "Handler" puede llamarse por multiples eventos, como se muestra en este tutorial, el handler "init" se ejecuta en el evento "creationComplete" y en el evento "click", asi estos eventos sean disparados por controles diferentes.

Ya hablaremos un poco más de esto en los próximos tutoriales de eventos, asi que no debemos preocuparnos, es mucho mas fácil de lo que parece al principio, y ya van a ver que hasta le agarrarán el gusto a este estilo de programación.

Por ahora aqui les dejo el video tutorial y les coloco el descargable del código fuente de la aplicación, asi como el ejemplo funcionando:



Codigo
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function init() : void
{
label1.text = "Hola Mundo";
TextInput1.text = "Hola Mundo";
}

public function limpiar() : void
{
label1.text = "";
TextInput1.text = "";
}
]]>
</mx:Script>

<mx:Label id="label1" x="68" y="35" text="Label"/>
<mx:TextInput id="TextInput1" x="132" y="33"/>
<mx:Button id="Button1" x="215" y="63" label="Imprimir" click="init()"/>
<mx:Button id="Button0" x="130" y="63" label="Limpiar" click="limpiar()"/>

</mx:Application>
Ejemplo


Continuar leyendo...

domingo, 28 de septiembre de 2008

Video Tutorial Instalación Adobe Flex


Para los que han tomado la sabia decisión de iniciarse en este prometedor y apasionante mundo de Flex aqui les dejo un tutorial con video para aprender a instalarlo, es muy fácil y solo requiere de dos simples descargas fundamentalmente, espero que les guste ya que es mi primer tutorial, y empezaré a hacer muchos más con ejemplos de como llenar un datagrid, data Binding (enlace de datos), el típico primer "Hola Mundo", como crear un componente, etc.

Todos los ejemplos que agregue de ahora en adelante voy a procurar de publicarlos con un video acompañado que explico con mas detalle lo que se hace en el ejemplo, y se aceptan sugerencias de posibles ejemplos, estaré esperandolos y feliz de ayudarlos con mis humildes conocimientos. Sin mas que decir, les dejo el tutorial:







Lo primero que debemos hacer para empezar a desarrollar en flex es realizar las primeras dos descargas de la lista a continuación:
  1. Eclipse Classic 3.4.1
  2. El plugin para eclipse llamado Adobe Flex Builder
  3. El Adobe Flash player and debugger para Firefox o Internet Explorer segun nuestra preerencia.
El primero de la lista es el IDE para desarrollar, es el mismo que se utiliza con frecuencia para desarrollar aplicaciones con J2EE, C/C++, Java Standard Edition, etc.

El segundo de la lista le dice a eclipse como debe compilar y entender los codigos escritos en ActionScrip 3.0 (Que es el lenguaje para desarrollar en el framework Flex).

El tercero de la lista es opcional, y es el que nos permite realizar una prueba paso a paso de los codigos programados, aunque en el caso de flex, por ser un lenguaje asincrono y orientado a eventos, realizar estas pruebas paso a paso es un poco complejo cuando se involucran los eventos, yo me inclino por la utilización de la consola con la función "trace" en estos casos, pero ya hablaremos de estos temas mas adelante, espero que les guste y cualquier opinion o sugerencia por favor son bienvenidas, miren que es mi primer tutorial y no se que tan bien lo he hecho.


Continuar leyendo...

lunes, 1 de septiembre de 2008

DataGrid Expandilble - Componente Flex


Continuando con el desarrollo de los componentes de flex, les presento mi ultima creación. Lo hice puramente con fines esteticos, y porque hay veces que los formularios mostrados estan saturados de informacion y es mejor no mostrarla toda a menos que el usuario lo desee, para eso cree el Datagrid Expandible, que no es mas que un componente Datagrid que tiene dos propiedades nuevas: rowNumber que dice el numero de filas que se desean visualizar cuando el datagrid esta contraido (esto no quiere decir que no se puedan pasar las filas con el scrollBar, que es la diferencia con la propiedad rowCount que ya viene incluida dentro del datagrid del Framework de flex).

Otra cosa que le agregue fue la opcion de colocar un efecto visual a la hora de expandir y contraer, para volverlo mucho mas estetico y agradable para el usuario.

Bueno para no quitarles mas tiempo aqui les coloco el codigo fuente del componente:

Codigo

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[

/**
* Componente DataGrid que permite especificar el numero de filas mostrar,
* colocando un scrollbara las demas filas para irlas pasando,
* tambien permite colocar un efecto de expansion y reduccion de las filas
* @version 1.0, 01/9/2008
* @author Alejandro Sánchez
*/

import mx.effects.Resize;
import mx.effects.Move;

import mx.collections.ArrayCollection;
import mx.collections.IList;
// Define the default property.
[DefaultProperty("columns")]

[Bindable]
public var _rowNumber : int = 0;

[Bindable]
private var _dataProvider : Object;

[Bindable]
private var _expanded : Boolean;

[Bindable]
private var _columns : Array;

[Bindable]
public var _effecto : Boolean = false;

private var _slow : Boolean = false;

private var timer : Timer;

/**
* Inicializa las variables por debecto y visializa el componenete
* por primera vez
*/

private function init() : void
{
if(_expanded) expand();
else collapse();
}

/**
* Permite setear la variable booleana que dice si el datagrid esta
* espandido o no
*/

public function set expanded(value : Boolean) : void
{
if(value!=_expanded)
{
_expanded = value;

invalidateSize();
invalidateProperties();
invalidateDisplayList();
}
}

public function get expanded() : Boolean
{
return _expanded;
}

/**
* La Default Property que recibe el datagrid para que se comporte como un
* datagrid comun y corriente
*/

public function set columns(value : Array) : void
{
if(value!=_columns)
_columns = value;


}

public function get columns() : Array
{
return _columns;
}

/**
* El datagrid debe cargarse de cualquier dataprovider que herede
* de la clase List
*/

public function set dataProvider(value : Object) : void
{
if(this._dataProvider!=value)
{
_dataProvider = value;

invalidateSize();
invalidateProperties();
invalidateDisplayList();
}
}

/**
* Determina el numero de filas a mostrar inicialmente
*/

public function set rowNumber(value : int) : void
{
if(_rowNumber!=value)
{
_rowNumber = value;

invalidateSize();
invalidateProperties();
invalidateDisplayList();
}
}

public function get rowNumber() : int
{
return _rowNumber;
}

public function get dataProvider() : Object
{
return _dataProvider;
}

/**
* Funcion que permite expandir el DataGrid
*/

public function expand() : void
{
_slow = true;
botonCollapse.visible = true;
boton.visible = false;

var cont : int = 0;
for each(var num : Object in _dataProvider)
cont++;

_rowNumber = cont;

invalidateSize();
invalidateProperties();
invalidateDisplayList();
}

/**
* Funcion que permite reducir el datagrid
*/

public function collapse() : void
{
_slow = true;
botonCollapse.visible = false;
boton.visible = true;

_rowNumber = 1;

invalidateSize();
invalidateProperties();
invalidateDisplayList();

}

/**
* Para realizar el binding con las principales propiedades
*/

override protected function commitProperties():void
{
super.commitProperties();

var cont : int = 0;
for each(var num : Object in _dataProvider)
cont++;

this.setChildIndex(boton, this.numChildren-1);
this.setChildIndex(botonCollapse, this.numChildren-1);

if(cont > 1)
{
boton.visible = true;
}
else
{
boton.visible = false;
}

}

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);

if((_slow)&&(unscaledHeight!=dataGrid.height + boton.height))
{
var eff : Resize = new Resize(this);
eff.widthTo = dataGrid.width;
eff.heightTo = dataGrid.height + boton.height;
eff.duration = 400;

var eff2 : Move = new Move(boton);
eff2.yTo = dataGrid.height;
eff2.duration = 400;

var eff3 : Move = new Move(botonCollapse);
eff3.yTo = dataGrid.height;
eff3.duration = 400;

eff2.play();
eff3.play();
eff.play();

}
else
{
dataGrid.width = unscaledWidth;
this.height = dataGrid.height + boton.height;

boton.x = dataGrid.width - boton.width;
boton.y = dataGrid.height;
botonCollapse.x = dataGrid.width - boton.width;
botonCollapse.y = dataGrid.height;
}

}

]]>
</mx:Script>
<mx:Button id="boton" cornerRadius="0" width="18" height="18" click="expand()">
<mx:icon>@Embed(source='../../../assets/button_expand.PNG')</mx:icon>
</mx:Button>
<mx:Button id="botonCollapse" cornerRadius="0" width="18" height="18" click="collapse()">
<mx:icon>@Embed(source='../../../assets/button_collapse.PNG')</mx:icon>
</mx:Button>
<mx:DataGrid id="dataGrid" dataProvider="{_dataProvider}" rowCount="{_rowNumber}" columns="{_columns}">
</mx:DataGrid>
</mx:Canvas>
Ejemplo


Continuar leyendo...

Selector de Hora - Componente Flex


En los últimos dias he empezado a desarrollar mis primeros componentes, aprendiendo las fantásticas funciones como commitProperties, updateDisplayList, merge, etc. Que te permiten realizar un Binding de manera mas acoplada al framework de Flex y mejorar el rendimiento de los componentes.

Como primer componente (y en vista de mis necesidades para futuros componentes) he decidido desarrollar un componente que por extrañas razones no viene incluido en el framework de desarrollo de flex: Selector de Horas (Time Picker).

Trate de hacer el componente lo mas parametrizable posible, permite cambiar los saltos de minutos de 5minutos, 10minutos, 15 minutos, etc. Permite cambiar el color de fondo y texto del componente, puede trabajar tanto en hora militar como meridiano, etc.

Para descargar el codigo del componente en formato RAR debes hacer click aqui, y cualquier duda que tengan pueden preguntame a mi mail aalejo@gmail.com, espero que les guste y ¡ que le saquen dinero!

Sin mas, el codigo y ejemplo del componente, los parametros estan hechos para cargar desde el inicio, no para modificarlos en tiempo de ejecucion, asi que perdonen los errores si los cambian, prometo dar una version mejorada en los proximos dias que acepte cambios en tiempo de ejecucion sin errores:

Codigo

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initApp()" horizontalGap="0">
<mx:Metadata>
[Event(name="onChange", type="flash.events.Event")]
</mx:Metadata>

<mx:Script>
<![CDATA[

/**
* Componenete que permite seleccionar una hora del dia, representada
* en formato militar o meridiano, el componente tambien permite ajustar
* el salto en minutos que debe dar al aumentar o disminuir la hora,
* si se quiere saltar de dos horas en dos horas se debe colocar 120 minutos
* @version 1.0, 01/9/2008
* @author Alejandro Sánchez
*/

import mx.containers.VBox;
import mx.binding.utils.BindingUtils;


[Bindable]
public var textColor : uint = 0x000000;

[Bindable]
public var backGroundColor : uint = 0xffffff;

[Bindable]
public var _twelveHour : Boolean = true;

[Bindable]
private var _hour : Number = 1;

[Bindable]
private var _minutes : Number=0;

[Bindable]
private var _meridian : String = "AM";

[Bindable]
private var _minutesJump : Number = 1;

[Bindable]
private var _hoursJump : Number = 1;

[Bindable]
[Inspectable(type="Boolean")]
public var editable : Boolean = true;


private var focused : TextInput = null;

/**
* Inicializa las variables por debecto y visializa el componenete
* por primera vez
*/

private function initApp():void {
focused=tHour;
if(!_twelveHour) {
tMeridian.width=0;
}
tHour.text = _hour.toString();
tMinute.text = _minutes.toString();
tMeridian.text = _meridian.toString();

BindingUtils.bindSetter(changeHourType,this,"twelveHour");
BindingUtils.bindSetter(resetMinutes,this,"minutesJump");

validateHour();
validateMinutes();
}

/**
* Cambia la visualizacion del comoponente de militar a meridian
* o visceversa
* @param value Falso si se quiere pasar a hora militar
*/

public function changeHourType(value : Boolean) : void
{
if(!value)
{
tMeridian.width=0;
hBox.width = tHour.width + tMinute.width + TextDosPuntos.width + 5;
vBox.x = hBox.width;
}
else
{
tMeridian.width=20;
hBox.width = tHour.width + tMinute.width + TextDosPuntos.width + tMeridian.width + 5;
vBox.x = hBox.width;
}
}

[Inspectable(type="Boolean")]
public function set twelveHour(twHour:Boolean):void {
this._twelveHour = twHour;
}

/**
* Vuelve a empezar el conteo de minutos para evitar errores
*/

public function resetMinutes(value : int) : void
{
_minutes = 0;
}

/**
*
* @return true o false
*/

public function get twelveHour() : Boolean
{
return this._twelveHour;
}

public function set hour(hr:Number):void {
this._hour = hr;
this.tHour.text = hr > 9 ? ""+hr : "0"+hr;
}

public function set minutes(mn:Number):void {
this._minutes = mn;
this.tMinute.text = mn > 9 ? ""+mn : "0"+mn;
}

/**
*
* @return Los minutos actuales que marca el componente
*/

public function get minutes():Number {
return this._minutes;
}

/**
*
* @return La hora actual que marca el componente
*/

public function get hour():Number {
return this._hour;
}

/**
* El salto en minutos que se espera que haga
* @return El salto en minutos que se espera que haga.
*/

public function get minutesJump() : int {
return this._minutesJump;
}

/**
* Calcula el salto en horas y en minutos que se debe saltar
* @param value el salto en minutos que se quiere saltar (Ej. 120min)
*/
[Inspectable(defaultValue=5, enumeration="1,5,10,15,30,60,120,180,240,300,360,420,480,540,600", type="int")]
public function set minutesJump(value : int):void
{
if(value>=60)
{
_minutesJump= 0;
_hoursJump = Math.floor(value/60);
}
else
{
this._minutesJump = value;
}
}

/**
*
* @return AM o FM
*/

public function get meridian():String {
return this._meridian;
}

public function set meridian(ampm:String):void {
this._meridian = ampm;
}

/**
* Si el usuario presiona el boton para subir la hora (o minuto)
*/

private function arrowUp():void {
if(editable)
{
if(focused == tHour && _twelveHour) {
adjustHour12(true);
} else if (focused == tHour && !_twelveHour) {
adjustHour24(true);
} else if (focused == tMinute) {
if(_minutesJump>0) adjustMinute(true);
} else if (focused == tMeridian) {
switchAm();
} else {
return;
}
dispatchEvent(new Event("onChange",true));
}
}

/**
* Si el usuario presiona el boton para bajar la hora (o minuto)
*/

private function arrowDown():void {
if(editable)
{
if(focused == tHour && _twelveHour) {
adjustHour12(false);
} else if (focused == tHour && !_twelveHour) {
adjustHour24(false);
} else if (focused == tMinute) {
if(_minutesJump>0) adjustMinute(false);
} else if (focused == tMeridian) {
switchAm();
} else {
return;
}
dispatchEvent(new Event("onChange",true));
}
}

/**
* Si se esta trabajando en Meridian y se quiere subir o bajar una hora
* @param up Un booleano "verdadero" si se esta subiendo en la hora
*/

private function adjustHour12(up:Boolean):void {
var n:Number = new Number(tHour.text);
if ((n<=12) && ((n+_hoursJump) > 12) && up) {
n = (n+_hoursJump)%12;
} else if ((n>=1) && ((n-_hoursJump) < 1) && !up) {
n = 12 + (n-_hoursJump);
} else if (up) {
n+=_hoursJump;
} else if (!up) {
n-=_hoursJump;
}
_hour = n;
if (n<10) {
tHour.text = "0"+n.toString();
} else {
tHour.text = n.toString();
}
}

/**
* Actualiza los valores en minutos del componenete
* @param up Un booleano "verdadero" si se esta subiendo en la hora
*/

public function adjustMinute(up:Boolean):void {
var n:Number = new Number(tMinute.text);
if (n == (60-minutesJump) && up)
{
if(_twelveHour) adjustHour12(up);
else adjustHour24(up);
n = 0;
} else if (n == 0 && !up) {
if(_twelveHour) adjustHour12(up);
else adjustHour24(up);
n = 60 - minutesJump;
} else if (up) {
n+=minutesJump;
} else if (!up) {
n-=minutesJump;
}
if (n<10) {
tMinute.text = "0"+n.toString();
} else {
tMinute.text = n.toString();
}
_minutes = n;
}

/**
* Actualiza los valores en horas militares del componenete
* @param up Un booleano "verdadero" si se esta subiendo en la hora
*/

private function adjustHour24(up:Boolean):void {
var n:Number = new Number(tHour.text);
if ((n+_hoursJump) > 23 && up) {
n = (n+_hoursJump)%24;
} else if ((n-_hoursJump) <= 0 && !up) {
n = 24 + (n -_hoursJump);
} else if (up) {
n+=_hoursJump;
} else if (!up) {
n-=_hoursJump;
}
if (n<10) {
tHour.text = "0"+n.toString();
} else {
tHour.text = n.toString();
}
_hour = n;

}

/**
* Cambia de AM a FM o visceversa
*/

public function switchAm():void {
if (tMeridian.text == "AM") {
tMeridian.text = "PM";
} else {
tMeridian.text = "AM";
}
_meridian = tMeridian.text;
dispatchEvent(new Event("onChange",true));

}

/**
* Valida que los valores del campo para AM y PM sean coherentes (o AM o FM)
*/

public function validateAm():void {
if (tMeridian.text.toUpperCase() != "AM" && tMeridian.text.toUpperCase() != "PM") {
if (tMeridian.text.length > 0 && tMeridian.text.toUpperCase().charAt(0) == 'P') {
tMeridian.text="PM";
} else {
tMeridian.text="AM";
}
}
tMeridian.text = tMeridian.text.toUpperCase();
_meridian = tMeridian.text;
dispatchEvent(new Event("onChange",true));
}

/**
* Se encarga de llamar a las funciones que actualizan las horas segun
* el tipo de visualizacion
* @param up Un booleano "verdadero" si se esta subiendo en la hora
*/

public function validateHour():void {
if (_twelveHour) {
validateHour12();
} else {
validateHour24();
}
dispatchEvent(new Event("onChange",true));
}

public function validateHour12():void {
var n:Number = new Number(tHour.text);
if (n >12) {
n= n % 12;
} else if (n < 1) {
n = 12 + n;
}
if (n < 10) {
tHour.text = "0"+n.toString();
} else {
tHour.text = n.toString();
}
_hour = n;
}

public function validateHour24():void {
var n:Number = new Number(tHour.text);
if (n >23) {
n= n % 24;
} else if (n < 0) {
n = 24 + n;
}
if (n < 10) {
tHour.text = "0"+n.toString();
} else {
tHour.text = n.toString();
}
_hour = n;
}

public function validateMinutes():void {
var n:Number = new Number(tMinute.text);
if (n >59) {
n=0;
} else if (n < 0) {
n = 60 - _minutesJump;
}
if (n < 10) {
tMinute.text = "0"+n.toString();
} else {
tMinute.text = n.toString();
}
_minutes = n;
dispatchEvent(new Event("onChange",true));
}

public function changeFocus(focusBox : TextInput):void {
focused=focusBox;
}

]]>
</mx:Script>

<mx:HBox id="hBox" horizontalGap="0" borderStyle="inset" verticalAlign="middle" height="22" horizontalScrollPolicy="off" backgroundColor="{backGroundColor}">
<mx:TextInput color="{textColor}" maxChars="2" restrict="0-9" borderStyle="none" textAlign="right" id="tHour" width="17" focusIn="changeFocus(tHour)" focusOut="validateHour()" backgroundAlpha="0.0"/>
<mx:TextInput color="{textColor}" id="TextDosPuntos" borderStyle="none" textAlign="right" editable="false" text=":" width="7" focusEnabled="false" backgroundAlpha="0.0"/>
<mx:TextInput color="{textColor}" maxChars="2" restrict="0-9" borderStyle="none" textAlign="right" id="tMinute" width="17" focusIn="changeFocus(tMinute)" focusOut="validateMinutes()" backgroundAlpha="0.0"/>
<mx:TextInput color="{textColor}" visible="{_twelveHour}" maxChars="2" restrict="APM" borderStyle="none" textAlign="right" id="tMeridian" click="switchAm()" width="20" focusIn="changeFocus(tMeridian)" focusOut="validateAm()" backgroundAlpha="0.0"/>
</mx:HBox>

<mx:VBox id="vBox" verticalAlign="bottom" verticalGap="0" horizontalGap="0">
<mx:Button verticalGap="0" cornerRadius="0" icon="@Embed(source='assets//uparrow.png')" click="arrowUp()" width="16" height="10"/>
<mx:Button verticalGap="0" cornerRadius="0" icon="@Embed(source='assets//downarrow.png')" click="arrowDown()" width="16" height="11"/>
</mx:VBox>

</mx:HBox>
Ejemplo


Continuar leyendo...

domingo, 24 de agosto de 2008

Penetracion Adobe Flash Player

Adobe Flash PLayer
Para nadie es un secreto que una de las principales variables en contra que tendrán las tecnologías Flex y Flash para continuar expandiendose será la necesidad de instalar una máquina virtual en el ordenador para poder visualizarlas.

Segun un estudio publicado por la Página oficial de Adobe, al parecer esto ya dejo de ser un problema, ya que el Adobe Flash Player se encuentra instalado en un 99% (Si, 99, leiste bien) de las máquinas que están preparadas para internet.


El senso realizado por Millward Brown fue, y esta siendo, realizado desde Septiembre del 2007 y hasta el dia de hoy ha arrojado los siguientes resultados para Septiembre 2007:

Penetracion Adobe Flash Player
Para el mes de junio del 2008 arrojó los siguientes resultados:

Penetracion Adobe Flash Player
Como pueden ver el 99% de las máquinas tienen algún Flash Player instalado y para los amantes de Flex saben que un 97% de las máquinas tienen instalado el Flash Player 9 necesario para correr aplicaciones Flex 2 y Flex 3.

Viendo estos resultados yo creo que ahora podemos decirle a los que se encargan de criticar estas excelentes tecnologías que van a tener que buscarse otra razón para decir que no les gustan.



Continuar leyendo...

domingo, 17 de agosto de 2008

LLenar y Obtener informacion de un Datagrid (Binding)


Como mi primero ejemplo quiero mostrar lo fácil que puede resultar realizar acciones muy vistosas y utiles en aplicaciones hechas en flex. En este ejemplo se muestra como llenar y obtener información de un DataGrid (que no es mas que una Lista de campos mostrados consecutivamente con ciertas funcionalidades), caber destacar que en este ejemplo se usan muy pocas de las grandiosas funcionalidades que puede ofrecer un DataGrid, pero las iremos publicando en el futuro.


Para llenar un Datagrid debemos asignar en la propiedad DataProvider objetos basados en la clase List de Actionscrip 3.0, tales como XMLList, Array,Colecciones, etc. Por supuesto tambien podemos usar la clase Object (ya que un objeto object puede comportarse como cualquier instancia de cualquier clase) .

Luego de asignar un DataProvider debemos decirle al DataGrid cuales van a ser sus columnas de información DataGridColumn, asignando un dataField con el nombre de la variable a mostrar y un headerText con el nombre de la columna.

Como la variable asignada como DataProvider la colocamos entre llaves le estamos diciendo a flex que es una variable de ActionScript, y hasta si declararamos bindable la variable pudieramos sincronizar la data contenida dentro del XMLList en tiempo real con el datagrid (Excelente, ¿no?), pero de esto hablaremos mas adelante. Cabe destacar que es imposible referirse a variables del codigo actual sin expresarlas entre llaves (ya sea codigo MXML o ActionScript).

Por ultimo le asiganos un identificador (id) al Datagrid para referirnos a el en cualquier parte del codigo, en este caso, para llenar el texto de las labels con la informacion seleccionada en el Datagrid.

Este codigo fue sacado de la página del Flash Component Explorer, para otros códigos de este mismo nivel pueden visitar la página.

Codigo

<?xml version="1.0"?>
<!-- DataGrid control example. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:XMLList id="employees">
<employee>
<name>Christina Coenraets</name>
<phone>555-219-2270</phone>
<email>ccoenraets@fictitious.com</email>
<active>true</active>
</employee>
<employee>
<name>Joanne Wall</name>
<phone>555-219-2012</phone>
<email>jwall@fictitious.com</email>
<active>true</active>
</employee>
<employee>
<name>Maurice Smith</name>
<phone>555-219-2012</phone>
<email>maurice@fictitious.com</email>
<active>false</active>
</employee>
<employee>
<name>Mary Jones</name>
<phone>555-219-2000</phone>
<email>mjones@fictitious.com</email>
<active>true</active>
</employee>
</mx:XMLList>

<mx:Panel title="DataGrid Control Example" height="100%" width="100%"
paddingTop="10" paddingLeft="10" paddingRight="10">

<mx:Label width="100%" color="blue"
text="Select a row in the DataGrid control."/>

<mx:DataGrid id="dg" width="100%" height="100%" rowCount="5" dataProvider="{employees}">
<mx:columns>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="phone" headerText="Phone"/>
<mx:DataGridColumn dataField="email" headerText="Email"/>
</mx:columns>
</mx:DataGrid>

<mx:Form width="100%" height="100%">
<mx:FormItem label="Name">
<mx:Label text="{dg.selectedItem.name}"/>
</mx:FormItem>
<mx:FormItem label="Email">
<mx:Label text="{dg.selectedItem.email}"/>
</mx:FormItem>
<mx:FormItem label="Phone">
<mx:Label text="{dg.selectedItem.phone}"/>
</mx:FormItem>
</mx:Form>

</mx:Panel>
</mx:Application>
Ejemplo


Continuar leyendo...

Utilizando etiqueta <pre> para publicar códigos

A la hora de realizar mi primer post con código ejemplo me encontre un problema que era de esperarse, el navegardor (En mi caso Mozilla Firefox) tomaba el código que yo escribia, como parte de la pagina (lo interpretaba), y no se mostraba en la entrada del blog publicada. Entonces empezo mi busqueda para solucionar el problema.

Luego de horas de investigación logre sacar un formato para la publicación de cogios sin que el navegador los interprete, que fuera fácil de usar, que el texto no perdiera el formato, se mantuviera la identación, etc. Mediante la utilización de HTML Entities a la hora de colocar caractéres especiales propios de HTML, para prevenir la perdida de identación descubi que la etiqueta <pre> de HTML matiene la identacion, y con la utilizacion de estilos CSS le di el formato deseado al texto y al bloque de codigo, con scrollbars, width, height, etc.

Para mostrarles el ejemplo de mi formato ejemplo para publicar codigos nada mejor que mostrarles el propio codigo del formato.



Codigo

<pre style="
background-color: #E8F2FF;
border-bottom: 2px solid #AAA;
border-top: 2px solid #AAA;
font-family: 'Courier New', Courier, Fixed;
overflow-y: scroll;
width: 600px;
height: 200px;">

El codigo ejemplo aqui

</pre>


Continuar leyendo...

Aplicaciones RIA con Flex

Adobe Flex

En los ultimos dias he empezado a trabajar con el increible concepto de aplicaciones RIA (Rich Internet applications) que no son otra cosa que aplicaciones para internet que se asemejan a las aplicaciones de escritorio, pasando la mayor parte de la carga de la aplicacion al lado del cliente, en contraposicion de las tecnologias del lado del servidor como PHP, ASP y otras.

Para desarrollar este tipo de aplicaciones se debe utilizar Adobe Flex con ActionScript 3.0, es un lenguaje bastante completo de programación orientada a objetos que permite multiple herencia, polimorfismo, la utilizacion de interfaces, la utilización de eventos (que para mi es la gran magia y potencial de este lenguaje) y muchas otros conceptos importantes que fomentan la reutilizacion y programacion mas practica.

Para desarrollar en este lenguaje les recomiendo usar el pluglin Flex Builder 3 (que incluso tiene licencia gratis para estudiantes) que corre bajo el IDE de Eclipse, de verdad que con esta nueva propuesta de Adobe he empezado a tomar mas en serio este tipo de tecnologias de la máquina virtual Flash Player 9.0, con el agregado de que hoy en dia ya mas del 90% de las maquinas tienen instalado esta maquina virtual.

En los proximos dias empezare a publicar algunos ejemplos y infomaciones para que vean lo practico y facil que puede llegar a resultar desarrollar en esta herramienta.
Continuar leyendo...