jueves, 31 de diciembre de 2009

UI Binding Con GWT 2.0

Una de las características nuevas de GWT es la posibilidad de crear interfaces de usuario definidas en un archivo XML, y luego vincular dicha definición con una clase, la cual incluirá el comportamiento de dicha interfaz, todo esto se realiza gracias al nuevo UiBinder.
En el siguiente ejemplo muestro como hacer una simple calculadora de enteros, definiendo la interfaz de usuario en un archivo xml y el comportamiento en una clase. Luego de todo eso podremos utilizar nuestra pantalla como si fuera un simple Widget de GWT.

El ejemplo funcionando se encuentra disponible bajo el enlace "Calculadora" del appspot de este blog.

Para empezar mostraré la pantalla definida en el xml. El archivo es "WebCalc.ui.xml"

<?xml version="1.0" encoding="UTF-8"?>
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:DockPanel>
<g:Dock direction="SOUTH">
<g:HorizontalPanel>
<g:Button text="Suma" ui:field="botonSumar" />
<g:Button text="Resta" ui:field="botonRestar" />
<g:Button text="Multuplicación" ui:field="botonMultiplicar" />
<g:Button text="División" ui:field="botonDividir" />
</g:HorizontalPanel>
</g:Dock>
<g:Dock direction="CENTER">
<g:HTMLPanel>
<p>Operador 1: <input type="text" ui:field="operador1" /></p>
<p>Operador 2: <input type="text" ui:field="operador2" /></p>
<p>Resultado: <span ui:field="resultado"/></p>
</g:HTMLPanel>
</g:Dock>
</g:DockPanel>
</ui:UiBinder>

Podemos ver que es bastante sencillo, primero definimos declarativamente un DockPanel, para la botonoera utilizamos un HorizontalPanel, el cual contiene 4 botones, vinculados por el atributo "ui:field" con ciertos métodos de la clase controladora que veremos más adelante.
Para la entrada, y en el centro del dock panel, utilizamos un panel html con tags html estándar (lo cual resalta el poder del UiBinder). Dandole el formato que a nosotros nos plazca y aún así pudiendo vincular elementos en la clase, de la misma forma que lo hicimos con los botones.

En este ejemplo no se muestra pero es posible también incluir estilos personalizados que se aplican sólo para el xml que estamos definiendo; otra muestra del gran poder de esta herramienta.

A continuación mostramos la clase que define el comportamiento de nuestra calculadora, el archivo "WebCalc.java".

public class WebCalc extends Composite {

interface Pantalla extends UiBinder<Widget, WebCalc> { }
private static Pantalla pantalla = GWT.create(Pantalla.class);

@UiField
InputElement operador1;
@UiField
InputElement operador2;
@UiField
SpanElement resultado;

public WebCalc() {
initWidget(pantalla.createAndBindUi(this));
}

@UiHandler("botonSumar")
public void sumar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 + op2));
}

@UiHandler("botonRestar")
public void restar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 - op2));
}

@UiHandler("botonMultiplicar")
public void multiplicar(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 * op2));
}

@UiHandler("botonDividir")
public void dividir(ClickEvent evt) {
int op1 = leerOperador(operador1);
int op2 = leerOperador(operador2);
resultado.setInnerText("" + (op1 / op2));
}

private int leerOperador(InputElement tb) {

if (tb == null) {
Window.alert("No es posible leer un valor");
return 0;
}
try {
return Integer.parseInt(tb.getValue());

} catch (NumberFormatException ex) {
Window.alert("No es posible convertir a entero: " + tb.getValue());
}
return 0;
}
}

Como podemos ver es bastante simple:
Para realizar el vínculo con el archivo declaramos la interfaz interna, a la cual podemos ponerle el nombre que mas nos convenga, utilizando como sus parámetros de generics el tipo de componente resultante que deseamos y el tipo de componente que tiene el "dueño" de la interfaz generada.
Posteriormente creamos el componente utilizando el mecanismo de "Deferred Binding" que nos provee GWT.

En el constructor de nuestro manejador le indicamos a nuestro componente recien creado que se vincule con la instancia actual de la clase mediante el llamado al método "createAndBindUi".

Finalmente utilizamos los annotations @UiField y @UiHandler para vincular componentes y las acciones de los botones.
Los botones pueden vincularse con cualquier método que devuelva void, y reciba un ClickEvent.

Bueno, espero haber podido ilustrar un poco el uso de esta gran herramienta que nos provee GWT. Si se desea ampliar la lectura, recomiendo leer el siguiente tutorial.

Saludos!

3 comentarios:

  1. Hola Juan,

    gracias a tu entrada me he dado cuenta de que la sentencia:

    contentDockPanel.add(scrollPanelGrid, DockPanel.CENTER);

    utilizando UiBinder, en el XML queda:





    Me podrías indicar dónde puedo encontrar las demás equivalencias. Es decir, un lugar donde muestren cómo puedo pasar las cosas que solo se hacían con archivos .java utilizando UiBinder.

    Te agradezco.

    ResponderBorrar
  2. utilizando UiBinder, en el XML queda: (Sin etiquetas a ver si sale...)

    g:DockPanel
    g:Dock direction="CENTER" g:ScrollPanel /g:ScrollPanel
    /g:Dock
    /g:DockPanel

    ResponderBorrar
  3. My brother suggested I might like this blog. He was totally right.

    This post actually made my day. You cann't imagine simply how much time I had spent for this information! Thanks!

    Here is my web site - gto120dlaocm402mfos02.com

    ResponderBorrar