Material‎ > ‎Software‎ > ‎Arena‎ > ‎

Tips Arena en XTend

Introducción

En esta página van a ver cómo utilizar ciertos features de Xtend para crear aplicaciones Arena de forma más concisa y fácil de leer / mantener.

Atajos a properties

El compilador de xtend es muy piola (?). Cuando una clase define una property (getter + setter), entonces como esta es una convención muy común en Java, nos permite al querer usar estas propiedades (obtener el valor, o setear un nuevo valor), usar una sintaxis más concisa:

 TradicionalmenteEn xtend se puede escribir 
  persona.getEdad()    persona.edad 
    persona.setEdad(23)       persona.edad = 23

Ojo, no significa que estamos accediendo a la variable de instancia directamente (lo que sería una mala práctica). Es simplemente un chiche sintáctico que igualmente usa los getters y setters)

Esto nos viene muy bien para definir propiedades de nuestros componentes en Arena:

val button = new Button(mainPanel)
button.caption = "Comprar"
button.height = 40
button.width = 100
button.onClick = [| modelObject.comprar ]

Operador => (with)

El operador "=>", llamado "with" en xtend nos viene muy bien en Arena para construir los componentes de la vista.
Este operador se aplica sobre una expresión y recibe un bloque. Lo que hace es enviar todos los mensajes que se envíen dentro del bloque al objeto al cual se evalúa la expresión.

algo => [
     mensaje1()
     mensaje2()
]

Además todo esto retorna el objeto referenciado por "algo", con lo cual se puede asignar o retornar como cuerpo de un método.

def crearLabel(Panel contenedor, String texto) {
    new Label(contenedor) => [
          text = texto
          width = 100
          height = 20
    ]
}

Esto nos viene muy bien cuando tenemos que crear paneles y dentro de ellos más paneles u objetos.
Ejemplo complejo:

new Panel(mainPanel) => [
    new Label(it) => [
        text = "Pedidos" fontSize = 18
    ]
    new List(it) => [
        bindItemsToProperty("pedidos")
        width = 300
        height = 220
    ]
    new Panel(it) => [
        layout = new HorizontalLayout
        new Label(it).text = "Cliente"
        new Label(it) => [
            bindValueToProperty("clienteSeleccionado")
            width = 200
        ]
    ]
]

Bindings

Arena provee un proyecto adicional, opcional, para trabajar con bindings desde xtend.

<dependency>
      <groupId>org.uqbar-project</groupId>
      <artifactId>arena-xtend</artifactId>
      <version>3.6.3</version>
</dependency>

Si estás utilizando arena-xtend-parent como parent pom de tu proyecto, no es necesario que agregues esta dependencia.

Luego desde una clase Window debemos hacer un import especial que nos va a agregar nuevos métodos para trabajar con bindings

import static extension org.uqbar.arena.xtend.ArenaXtendExtensions.*


Ahora sí, podemos usar un operador especial "<=>" (o también llamado "spaceship") para definir los bindings.

 Antes hacíamos Con arena-xtend
 new TextBox(panel) => [
      bindValueToProperty("millas")
 ]
 new TextBox(panel) => [
      value <=> "millas"
 ]
 new Selector(panel) => [
    bindItemsToProperty("empleados")
    bindValueToProperty("empleadoSeleccionado")
 ]

 new Selector(panel) => [
     items <=> "empleados"
     value <=> "empleadoSeleccionado"
 ]

 bindXXXXToProperty("P")   XXXX <=> "P" 

Un par de puntos a observar acá:
  • <=>
    • es un operador.
    • En xtend los operadores se pueden redefinir (sobrecarga de operadores)
    • Si se fijan con F3 sobre el operador, el eclipse los va a llevar hasta un método que se llama operator_spaceship.
    • Con lo cual, <=> es simplemente una sintaxis especial para un método.
  • Los componentes de arena proveen métodos que
    • representa una característica "bindeable"
    • Ej: items, value, background, visible, enabled
    • Éstas métodos no retorna el valor, sino un objeto especial que es observable
    • Detalles de implementación, simplemente sepan que no pueden obtener los valores directamente. Sólo sirven para bindear

Bindings sin Strings (type safe)

Existe una forma de evitar usar strings a la hora de bindear una característica de la vista a una propiedad del modelo.
Hasta ahora siempre usábamos la forma de Strings. Ej:  "millas".
Luego si le cambiábamos el nombre en el dominio, el compilador no se daba cuenta y esto generaba errores al ejecutar la aplicación.
O bien, a veces, cometíamos un error de tipeo, y pasaba lo mismo.

Existe otra sobrecarga del operador "<=>" que permite expresar la información del binding con código, en lugar de un String.
Específicamente con un bloque de código.

 Antes hacíamos Con arena-xtend (strings) Con arena-xtend (no Strings . Bloques)
 new TextBox(panel) => [
    bindValueToProperty("millas")
 ]
 new TextBox(panel) => [
      value <=> "millas"
 ]
 new TextBox(panel) => [
      value <=> [Conversor c| c.millas]
 ]

Detalles:
  • El bloque recibe un sólo parámetro: el modelo
  • Debe acceder a una property de ése modelo que recibe por parámetro (¡¡¡y sólo de ése!!! ¡¡¡no escriban código que hace otra cosa porque puede tener efectos inesperados!!!!)
  • Puede ser una property anidada: Ej.  [Persona p | p.direccion.calle.numero ]
  • Por un problema de los Generics de Java, es necesario volver a especificar el tipo del modelo (Conversor) en el bloque.

Comments