Making Swing Fun Again
Agenda
A Brief History of Desktop Java Groovy’s Improvements for Swing Grails + Swing -> Griffon Griffon’s Unique Values Q&A / Live Demo
History of Desktop Java
Java 1.0 January 1996 AWT
Native Peers Subclass to Add Behavior
History of Desktop Java
Java 1.1 February 1997 Inner and Anonymous Classes JavaBeans
Events Listener Interfaces and Event Objects
Properties getters/setters and BeanInfos
AWT reworked with JavaBeans Lightweight Peers Swing as an External Library
History of Desktop Java
History of Desktop Java
Java 1.3 May 2000 HotSpot JIT JavaSound Java WebStart as External Download
History of Desktop Java
Java 1.4 February 2002 Java WebStart Reworked Focus and Drag and Drop JSpinner and JFormattedTextField
Java 1.4.2 September 2003 Windows XP Look and Feel GTK+ Look and Feel
History of Desktop Java
Java 5.0 September 2004 Synth Look and Feel Ocean Theme for Metal Pack 200 Generics AutoBoxing Annotations Enumerations Varargs
History of Desktop Java
Java 6.0 December 2006 SwingWorker API Scripting Language support (JSR-223) Improved Java2D Rendering Pipeline
No More Grey Rectangles System Tray and Notifications Support
History of Desktop Java
Java 6u10 October 2008 Kernel Installer Nimbus Look and Feel Improved Java Plug-In
JNLP Integration New Process Model
Patch in Place Updating
History of Desktop Java
JavaFX Desktop 1.0 December 2008 New Node Based Graphics Engine
Interop APIs for Swing New Programming Language
Java Interop on par with JRuby / Jython / Rhino
Should You Forget Most of the Last 8 Slides?
Groovy’s Improvements
Groovy Addresses Developer Pain Points JavaBeans Events JavaBeans Properties Declarative Structure
Groovy Language Features Closures Concise Syntax Meta Object Protocol
Groovy’s Improvements
Java Beans Event Listener Java
JButton myButton = new JButton("Hello World");myButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.out.println("Hello World"); }});
Groovy
JButton myButton = new JButton("Hello World")myButton.actionPerformed = { println "Hello World" }
Groovy’s Improvements
Properties Java
String field;
public String getField() { return field;}
public void setField(String field) { this.field = field;}
Groovy
String field
Groovy’s Improvements
Declarative Structure
def swing = new SwingBuilder()swing.frame(size:[400, 300], show:true) { borderLayout() scrollPane(constraints:CENTER) { textArea(text: bind { model.script }) } hbox(constraints:SOUTH) { hglue() button("OK", actionPerformed: controller.&okPressed) button("Cancel", actionPerformed: controller.&canceled) }}
Groovy’s Improvements
Closures Can be cast to Interfaces Directly Usable for Single Method Interfaces (Runnable
et. al.)
Concise Syntax Boilerplate Code is Removed Lots of Closure Sensitive Methods Added to Core Classes
Meta Object Protocol – i.e. Dynamic Language Allows Any Method to be Called on Any Object Allows Methods to be Intercepted Allows Missing Methods to be Handled Allows Magic to Happen
Grails + Swing -> Griffon Grails
Inspired by Rails Groovy as the Language Web as the Domain Java as the Platform
Spring Custom Value Added by Framework
GORM GSPs
Grails + Swing -> Griffon Griffon
Deeply Inspired by Grails Groovy as the Language Desktop/Rich Client as the Domain Java as the Platform
Swing Custom Value Added by Framework
MVC Groups Packaging
Grails + Swing -> GriffonDifferences
Fairly Strict Runtime/CLI Separation No Spring at Runtime No J2EE
Servlets , EJB, JSP, JMS
Grails + Swing -> Griffon Similarities
View Scripts – JSP Pages EDT Event Loop – HTTP Request Loop Source Tree is Partitioned by Role
Griffon’s Unique Values
Builders MVC Groups Application Lifecycle Pattern Build Time Packaging
Builders
MyBuilder builder = new MyBuilder()builder.parent { child(attr:value, attr2:value, id:'a') favoriteChild(arg) { spoiledGrandchild(inheritance:a) }}bequethKingdom(builder.a)
Builders are Groovy Code Nesting Contexts are Closures Nodes are Method Calls Attributes and Arguments are Method
Arguments
Builders
SwingBuilder One of the Original Builder Samples Re-factored as a FactoryBuilderSupport
Builder SwingXBuilder
First Builder for a Non-Core Widget Set JideBuilder GraphicsBuilder
Builders
UberBuilder Composites Other Builders Intercepts Calls and Dispatches to Approptiate
Builder Can Prefix Nodesgriffon-app/conf/Builder.groovy –
root { 'groovy.swing.SwingBuilder' { controller = ['Threading', 'SupportNodes', 'Binding'] } 'griffon.app.ApplicationBuilder' { view = "*" }}jx { 'groovy.swing.SwingXBuilder' { }}
MVC Groups
The MVC Pattern is Great… But Swing Provides a Low Effort to
Reward Ratio
Lower the Effort Language Level Support for Data Binding Framework Level Support for MVC Triads
Increase the Reward Reusability of Triads
MVC Groups – Binding
JavaBeans Bound Propertiesprotected PropertyChangeSupport pcs = new PropertyChangeSupport(this)private String myProperty;public String getMyProperty() { return myProperty;}public void setMyProperty(String myProperty) { pcs.firePropertyChange(“myProperty”, this.myProperty, this.myProperty = myProperty);}
Groovy Bound Properties@Bindable String myProperty
MVC Groups – View Scripts Views are Groovy Scripts
No Class Declarations Looks Like Free-Form Code Compiles to .class
Method Contexts are Implied No Required Swing Imports Method Meanings are Provided by the
Builder
MVC Groups – Data Injection Methods and Fields are Injected
Global Imports createMVCGroup() Method model, view, controller, builder
Fields/Properties
On a per-builder basis SwingBuilder provides edt, doLater, doOutside
Other Builders Can Provide Their Own Methods
Injection Controlled by Builder.groovy
Application Lifecycle
Follows the JSR-296 Lifecycle stages
griffon-app/lifecycle/Initialize.groovy Before Any GUI Work Good Place for Look and Feel Setup
griffon-app/lifecycle/Startup.groovy After Startup MVC Groups are Initialized
griffon-app/lifecycle/Ready.groovy After the EDT Calms Down
griffon-app/lifecycle/Shutdown.groovy After a Shutdown is Successfully Initiated
Packaging
How do you… Keep an Applet From Thrashing the
Server for BeanInfos? Create a Self-Signed Certificate? Use Pack200
On a Signed Jar? Over 1 MB?
Create a Draggable Applet? Write a JNLP file? Switch Between the Applet and Object
Tags? When do you Use Applet or Object?
Packaging
Griffon Handles Standard Packaging Issues Pack 200 quirks Useful Applet Parameters JNLP Generation Uses Sun Java Deployment Toolkit
JavaScripts
Room to Grow
Plug-ins(Deeply Inspired by Grails 1.1 plug-ins)
Existing Plug-ins swingx-builder – SwingX Components jide-builder – Jide-oss Components fest – Swing GUI Testing easyb – Behavior Driven Testing installer – Packages (deb, dmg, rpm) and
IzPack
More Information
Web links http://griffon.codehaus.org/ [email protected]
Creators' blogs Danno Ferrin http://shemnon.com/speling Andres Almiray http://jroller.com/aalmiray James Williams http://jameswilliams.be/blog