Desktop Development - The Fun Way

Tutorial - Griffon: Building Desktop Applications with Groovy - Part 3

          The Domain

If you’re a Grails developer you may have noticed we did not start by modelling the domain, which is the usual case when working with Grails applications. There are two reasons for making this choice. First, to show you the basics of the MVC members and how they interact with each other. The second is that Griffon does not support domain classes out of the box, at least not as Grails understands it, that is, there’s no GORM API for Griffon, yet. But we can manage ourselves by writing simple domain classes. Listing 5 for example shows what the Contact domain class may look like.

Listing 5

 

package addressbook
@groovy.transform.EqualsAndHashCode
class Contact {
    long id
    String name
    String lastname
    String address
    String company
    String email
    
    String toString() { "$name $lastname : $email" }
    
    static final List<String> PROPERTIES = ['name', 'lastname', 
         'address', 'company', 'email']

 

This class can be defined in the file src/main/addressbook/Contact.groovy. Next to it we’ll define the companion presentation model, in src/main/addressbook/ContactPresentationModel.groovy with the code seen in Listing 6 in it.

Listing 6

 

package addressbook
import groovy.beans.Bindable
@griffon.transform.PropertyListener(propertyUpdater)
class ContactPresentationModel {
    // attributes
    @Bindable String name
    @Bindable String lastname
    @Bindable String address
    @Bindable String company
    @Bindable String email
    
    // model reference
    @Bindable Contact contact = new Contact()
    
    private propertyUpdater = { e ->
        if(e.propertyName == 'contact') {
            for(property in Contact.PROPERTIES) {
                def bean = e.newValue
                delegate[property] = bean != null ? bean[property] : null
            }
        }
    }

    String toString() { "$name $lastname" }

    void updateContact() {
        if(contact) {
            for(property in Contact.PROPERTIES) {
                contact[property] = this[property]
            }
        }
    }
}

 

As we mentioned before, the domain class is simple in its design; it only needs to be concerned with the data we want to keep. The presentation model on the other hand mirrors the domain class by having the same properties but with a slight modification: each one of them is observable. This means that whenever the value of any of those properties changes, an event will be fired. These events are the ones that enable binding. Griffon makes use of the @Bindable annotation to instruct the Groovy compiler to inject a set of instructions into the byte code that makes this class an observable one. @Bindable belongs to a set of special interfaces found in the Groovy language that open the door for byte code manipulation. This set is known as AST transformations. There’s another AST transformation found in this code, it’s @PropertyListener. This transformation is a fancy way to define and attach a PropertyChangeListener on a particular class and property. In our case, we’re attaching a PropertyChangeListener that reacts on all property changes. The next effect of all the code we have in Listing 6 is that when a Contact instance is attached to an instance of ContactPresentationModels, all of the property values will be copied from the contact to the model. The reverse operation will take effect when the updateContact() method is called.

Good. We’re almost ready to run the application again. But before we do, we must install a group of plug-ins that will make our life easier. We said we’ll make use of GlazedLists. This library is provided by a plug-in, so we’ll install that. In the view we make use of MigLayout, so we’ll install a plug-in for it too. Finally we’ll install another plug-in that makes creating UI actions based on controller methods a breeze. Go to your console prompt and type the following commands

$ griffon install-plugin glazedlists

$ griffon install-plugin miglayout

$ griffon install-plugin actions

After a few lines of output for each plug-in install we have all that’s needed to run the application again.

  

Pages

Andres Almiray
Andres Almiray

What do you think?

JAX Magazine - 2014 - 05 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions