Sunday June 14, 2009
How to Incorporate a Wizard into a Griffon Application (Part 4)
Thanks to an intervention by Andres Almiray, I now have the Griffon wizard/db example working as I'd expect it to. The wizard's first step is filled from a database, when a selection is made in the drop-down two labels below it are updated with additional info about the current selection:
Here's the code, especially the parts in bold:
import net.miginfocom.swing.MigLayout
import ca.odell.glazedlists.*
import javax.swing.event.ListSelectionListener
import java.util.Map
import ca.odell.glazedlists.swing.EventSelectionModel
import ca.odell.glazedlists.swing.EventListModel
class OneWizardPage {
def stepId = "step1" // must be unique per WizardPage
def description = "Customer Details"
def autoListen = true
def selCity = '<empty>'
def selState = '<empty>'
def pageContents = {
EventList namesEventList = new BasicEventList()
namesEventList.addAll( MyDbService.instance.getAllNames() )
EventListModel listModel = new EventListModel(namesEventList)
EventSelectionModel selectionModel = new EventSelectionModel(namesEventList)
def cityLabel = null
def stateLabel = null
selectionModel.addListSelectionListener( [ valueChanged: {e ->
if (e.valueIsAdjusting){
def customer = selectionModel.selected
doOutside {
selCity = MyDbService.instance.getCityForSelectedName(customer)
selState = MyDbService.instance.getStateForSelectedName(customer)
doLater {
cityLabel.text = selCity
stateLabel.text = selState
}
}
}
} ] as ListSelectionListener)
panel(border:lineBorder(1, color: java.awt.Color.black), constraints: "growx", layout: new MigLayout('fill')) {
label( text: "Name:" )
scrollPane(constraints: "growx, wrap"){
list( name: "tf1", model: listModel, selectionModel: selectionModel, visibleRowCount: 1 )
}
label( text: "City:" )
cityLabel = label( name: "tf2",
text: selCity,
constraints: "growx, wrap" )
label( text: "State:" )
stateLabel = label( name: "tf3",
text: selState,
constraints: "growx, wrap" )
}
}
// Either return a String that indicates a problem
// or return a null value indicating no problem
def onValidate = { component, /*PropertyChangeEvent*/ event ->
return null // no problems
}
}
Thanks Andres!
Jun 14 2009, 05:16:53 AM PDT Permalink
I'm sure there is an alternative using @Bindable, but seeing that all MVC members are combined in a single class (OneWizardPage) it might not be worth the effort, specially for a simple wizard page as this one. However for a more complicated page a proper separation between MVC responsibilities would be a good idea, I believe ObservableMap makes a good candidate for implementing the model, the controller responsibilities could be factored out as property closures on the same class.
Cheers,
Andres
Posted by Andres Almiray on June 14, 2009 at 01:29 PM PDT #
Right. I would expect the MVC pattern to be applied to Griffon plugins too. Maybe there should be guidelines for plugin development, such as a 'requirement' that the MVC pattern be integrated.
Posted by Geertjan on June 14, 2009 at 01:32 PM PDT #
It makes you wonder if a wizard pages should share the same M & C or should they have their own, doesn't it? In any case I believe this is a good improvement for the wizard plugin, a feature (I hope) the community helps us bring to shape :-)
Cheers,
Andres
Posted by Andres Almiray on June 14, 2009 at 01:40 PM PDT #
First of all, thank you very much for the article series!!
I'm trying to set up my first wizard into my Griffon application and I can't find any way of passing parameters to the wizard to be available into the pages :(
I'm sure I'm missing something
Many Thanks in advance,
Jorge.
Posted by Jorge Muñiz on December 17, 2009 at 08:18 AM PST #


