31 julio 2009

Binding And Triggers

Hoy hablaremos de una de las características más poderosas de JavaFX la cual consiste en el binding entre datos, esto nos brinda la posibilidad de vincular dos variables entre si ya sea por el cambio de valor de una, o por la evaluación de una expresión. Además tenemos la posibilidad de asignar triggers que son bloques de códigos los cuales se ejecutan al cambiar el valor de una variable.

Contenidos

  • Binding Overview
  • Binding and Objects
  • Binding and Functions
  • Binding with Sequences
  • Replace Triggers


Binding Overview
Empezaremos diciendo que para poder realizar el binding entre variables debemos usar la keyword bind, también existe una expresión bound que ahora veremos la cual crea una relación más amplia.

Binding and Objects
Veamos un ejemplo donde creamos un binding entre dos variables.
var x = 0;
def y = bind x;
x = 1;
println(y); // y ahora vale 1
x = 50;
println(y); // y ahora vale 50
Aquí se nota como nosotros solo modificamos los valores de la variable x esto automáticamente se ve reflejado en la variable y.
Ahora veremos un binding parecido pero cuando queremos hacer binding entre objetos.
var myStreet = "1 Main Street";
var myCity = "Santa Clara";
var myState = "CA";
var myZip = "95050";

class Address{
var street;
var city;
var state;
var zip;
}

def address = bind Address {
street: myStreet;
city: myCity;
state: myState;
zip: myZip;
};

println("address.street == {address.street}");
myStreet = "100 Maple Street";
println("address.street == {address.street}");
Aquí definimos la clase Address y luego definimos, 4 variables para iniciar este objeto, al crear nuestro objeto lo hacemos con la palabra bind, esto quiere decir que nuestra variable address siempre tendrá sus atributos actualizado en base a los valores de las variables con cuales fue iniciado.
Si ejecutamos el ejemplo veremos que el resultado es
address.street == 1 Main Street
address.street == 100 Maple Street
Un dato importante que debemos considerar es que con este tipo de binding por cada modificación, se genera un nuevo objeto Address y se asigna nuevamente a la variable.
Otra forma de realizar este binding sin generar un nuevo objeto es de la siguiente manera

var myStreet = "1 Main Street";
var myCity = "Santa Clara";
var myState = "CA";
var myZip = "95050";

class Address{
var street;
var city;
var state;
var zip;
}

def address = Address {
street: bind myStreet;
city: bind myCity;
state: bind myState;
zip: bind myZip;
};

println("address.street == {address.street}");
myStreet = "100 Maple Street";
println("address.street == {address.street}");
La única diferencia es que acá no se hace el bind sobre el objeto sino sobre cada atributo.

Binding and Functions
Aquí es donde entra en juego la keyword bound, no debemos confundir esto con el bind son dos cosas distintas que en combinación nos ofrecen alguna funcionalidad especifica.
Veamos un ejemplo de bind y bound para entender cómo funciona y como usarlo
// Paso 1
var scale = 1.0;

// Paso 2
class Point {
var x : Number;
var y : Number;
}

// Paso 3
bound function makePoint(xPos : Number, yPos : Number) : Point {
Point {
x: xPos * scale
y: yPos * scale
}
}

// Paso 4
var myX = 3.0;
var myY = 3.0;
def pt = bind makePoint(myX, myY);
println(pt.x);

// Paso 5
myX = 10.0;
println(pt.x);

// Paso 6
scale = 2.0;
println(pt.x);
Entendamos este ejemplo paso por paso.
Paso 1:
Aquí definimos una variable del tipo Number y la inicializamos en 1.0

Paso 2:
Definimos la clase Point

Paso 3:
Creamos una función la cual la marcamos con el atributo bound, aquí debemos saber que hay dos tipos de funciones las bound y las not-bound que se comportan de manera distinta si tan con binding sobre una variable.
Las funciones not-bound solo se ejecutan si sus parámetro cambian, en caso contrario las funciones bound siempre se ejecutan

Paso 4:
Creamos las variables las inicializamos y hacemos un bind entre la función y una variable del tipo Point.

Paso 5:
Cambiamos el valor de myX como esta variable fue usada como parámetro de la función con bind se dispara la función y cambia los valores del Point

Paso 6:
Cambiamos el valor de la scale y como esta es una función bound también se vuelve a ejecutar la función y nos cambia los valores de Point
Si ejecutamos el ejemplo el resultado será:
3.0
10.0
20.0
Si sacáramos el bound de la función el resultado sería:
3.0
10.0
10.0

Binding with Sequences
Aquí usaremos un bind entre secuencias pero además usando la expresión for. Tranquilamente podríamos hacer un bind común entre dos secuencias como si fueran variables, pero para ver el poder de esto usaremos una expresión for de la siguiente manera
// Definimos la secuencia 1
var seq1 = [1..10];

// Definimos la secuencia 2, pero con la diferencia que cada ítem será multiplicado por dos
def seq2 = bind for (ítem in seq1) ítem*2;
printSeqs();

function printSeqs() {
println("First Sequence:");
for (i in seq1){println(i);}
println("Second Sequence:");
for (i in seq2){println(i);}
}

Si ejecutamos el ejemplo el resultado será el siguiente:
First Sequence:
1
2
3
4
5
6
7
8
9
10
Second Sequence:
2
4
6
8
10
12
14
16
18
20

Se nota claramente como la secuencia 2 está relacionada con la secuencia 1,pero además aplica una multiplicación sobre cada ítem, para confirmar el bind vamos a insertar un elemento en la secuencia 1 y este debería estar presente en la secuencia 2
// Definimos la secuencia 1
var seq1 = [1..10];

// Definimos la secuencia 2, pero con la diferencia que cada ítem será multiplicado por dos
def seq2 = bind for (ítem in seq1) ítem*2;
insert 11 into seq1;
printSeqs();

function printSeqs() {
println("First Sequence:");
for (i in seq1){println(i);}
println("Second Sequence:");
for (i in seq2){println(i);}
}
Si volvemos a correr el ejemplo veremos que ahora la secuencia 1 tiene el ítem 1 y la secuencia 2 tiene el ítem 22.

Replace Triggers
Se le llama Replace Triggers a bloques de códigos que podemos asignar a las variables para que se ejecuten cuando sus valores cambien. Aquí debemos usar la sentencia on replace para poder definir el bloque de código que queremos ejecutar
var password = "foo" on replace oldValue {
println("\nALERT! Password has changed!");
println("Old Value: {oldValue}");
println("New Value: {password}");
};
password = "bar";
Primero creas la variables password donde la inicializamos con el valor "foo"(Supuestamente -Ahora explicare porque pongo esto-) y usamos la sentencia on replace seguido de un nombre a elección del valor anterior y luego definimos el código a ejecutar. al correr el ejemplo veremos lo siguiente

ALERT! Password has changed!
Old Value:
New Value: foo

ALERT! Password has changed!
Old Value: foo
New Value: bar

Vemos que se ejecuta dos veces ya que la variable en un comienzo esta inicializa en Null por eso nuestra inicialización en "foo" es supuesta.

Bueno con esto daremos por finalizada la introducción a las características de JavaFX en lo que sería la parte de scripting, ahora nos dedicaremos a la parte más visual donde empezaremos a usar todos estos conocimientos.

Saludos

No hay comentarios:

Publicar un comentario