Adapters

Property Adapter

Selectors (also known as Combo boxes) use an adapter object to show the elements in the list.

// Xtend
new Selector<Job>(form) => [
    value <=> "job"
    val bindingItems = bindItems(new ObservableProperty("jobs"))  // you can also do val bindingItems = items <=> "jobs"
    bindingItems.adaptWith(typeof(Job), "fullDescription") // first option
    //bindingItems.adapter = new PropertyAdapter(typeof(Job), "fullDescription") // second option
]

// Java
Selector<Job> selector = new Selector<Job>(form); 
selector.bindValueToProperty("job");
Binding<Job, Selector<Job>, ListBuilder<Job>> bindingItems = selector.bindItems( //
   new ObservableProperty<Job>("jobs"));
bindingItems.setAdapter( //
   new PropertyAdapter(Job.class, "fullDescription"));

We have a list of possible jobs that a certain employee can perform. Selector has two UI property bindings:

  • value: if model is an employee, value of selector binds to job property of that employee.
  • items: view model class has a method getJobs() that returns a list of jobs (well, it should only delegate to a repository or DAO class).

By default, items are shown using toString() method. But you can override this definition using a PropertyAdapter.

In the class Job we build a getFullDescription() method

def getFullDescription() {
        description + " ($ " + minimumSalary + " )"
}

Selector shows then the following result:

Transformers

Every column in a Table component has a specific binding:

 new Column<Customer>(table) //
     .setTitle("Name")
     .setFixedSize(150)
     .bindContentsToProperty("name")

But in certain cases, we must define an adapter:

 new Column<Customer>(table) //
     .setTitle("Has Debt")
     .setFixedSize(50)
     .bindContentsToTransformer( [ customer | if (customer.debt > 0) "YES" else "NO"])

This adapter transforms an integer property getDebt() into a string YES/NO:

Same example in Java:

Column<Customer> debtColumn = new Column<Customer>(table);
debtColumn.setTitle("Has Debt");
debtColumn.setFixedSize(50);
debtColumn.bindContentsToTransformer(new BooleanToYesNoTransformer());

And here's the implementation of this new transformer (useful if you have to use it several times in your application):

public final class BooleanToYesNoTransformer implements Transformer<Customer, String> {
        @Override
        public String transform(Customer customer) {
                return customer.getDebt() > 0 ? "YES" : "NO";
        }
}

Transformer allows to map a property of type T into a U value:

public interface Transformer<T, U> {
        public U transform(T element);
}

Another example, binding background color of each column. When debt amount is even, column background color will be green, otherwise will be red:

        new Column<Celular>(table) => [
            bindBackground("debt").transformer =
                [ Integer debt | if (debt % 2 == 0) Color.GREEN else Color.RED ]
            ...            
        ]