Griffon @ Svwjug
-
Upload
andres-almiray -
Category
Technology
-
view
107 -
download
0
description
Transcript of Griffon @ Svwjug
Welcome to the Desktop Revolution
What is Griffon ?
+ +
+ Sugar, Spice and everything Nice =
HelloWorld.java
public class HelloWorld { String name;
public void setName(String name) { this.name = name; } public String getName(){ return name; }
public String greet() { return "Hello "+ name; }
public static void main(String args[]){ HelloWorld helloWorld = new HelloWorld(); helloWorld.setName("Groovy"); System.err.println( helloWorld.greet() ); }}
HelloWorld.groovy
public class HelloWorld { String name;
public void setName(String name) { this.name = name; } public String getName(){ return name; }
public String greet() { return "Hello "+ name; }
public static void main(String args[]){ HelloWorld helloWorld = new HelloWorld(); helloWorld.setName("Groovy"); System.err.println( helloWorld.greet() ); }}
GroovierHelloWorld.groovy
class HelloWorld { String name def greet() { "Hello $name" }}
def helloWorld = new HelloWorld(name:"Groovy")println helloWorld.greet()
Swing
import java.awt.GridLayout;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import javax.swing.JFrame;import javax.swing.JTextField;import javax.swing.JButton;import javax.swing.SwingUtilities;
public class JavaFrame { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable(){ public void run() { JFrame frame = buildUI(); frame.setVisible(true); } }); } // next page ...
// continued ... private static JFrame buildUI() { JFrame frame = new JFrame("JavaFrame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout( new GridLayout(3,1) ); final JTextField input = new JTextField(20); final JTextField output = new JTextField(20); output.setEditable(false); JButton button = new JButton("Click me!"); button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event) { output.setText(input.getText()); } }); frame.getContentPane().add(input); frame.getContentPane().add(button); frame.getContentPane().add(output); frame.pack(); return frame; }}
●The light at the end of the tunnel...
import groovy.swing.SwingBuilderimport static javax.swing.JFrame.EXIT_ON_CLOSE
new SwingBuilder().edt { frame(title: "GroovyFrame", pack: true, visible: true, defaultCloseOperation: EXIT_ON_CLOSE) { gridLayout(cols: 1, rows: 3) textField(id: "input", columns: 20) button("Click me!", actionPerformed: { output.text = input.text }) textField(id: "output", columns: 20, editable: false) }}
What is going on?
Each node is syntactically a method call
All of these method calls are dynamically dispatched
Most don’t actually exist in bytecode
Child closures create hierarchical relations
Child widgets are added to parent containers
SwingBuilder node names are derived from Swing classes
Remove the leading ‘J’ from a Swing class when present
SwingBuilder also supports some AWT classes like layouts
●Threads
Threading and the EDT
All painting and UI operations must be done in the EDT
Anything else should be outside the EDT
Swing has SwingUtilities using Runnable
Java 6 technology adds SwingWorker
However, closures are Groovy
For code inside EDT
edt { … }doLater { … }
For code outside EDT
doOutside { … }Build UI on the EDT
SwingBuilder.build { … }
Threading Example
action( id: 'countdown', name: 'Start Countdown', closure: { evt -> int count = lengthSlider.value status.text = count while ( --count >= 0 ) { sleep( 1000 ) status.text = count } status.background = Color.RED })
Threading Example
action( id: 'countdown', name: 'Start Countdown', closure: { evt -> int count = lengthSlider.value status.text = count doOutside { while ( --count >= 0 ) { sleep( 1000 ) edt { status.text = count } } doLater { status.background = Color.RED } }})
Binding
Binding Example
import groovy.swing.SwingBuilder
new SwingBuilder().edt { frame( title: "Binding Test", size: [200, 120], visible: true ) { gridLayout( cols: 1, rows: 2 ) textField( id: "t1" ) textField( id: "t2", editable: false ) } bind(source: t1, sourceProperty: "text", target: t2, targetProperty: "text")}
Binding Example
import groovy.swing.SwingBuilder
new SwingBuilder().edt { frame( title: "Binding Test", size: [200, 120], visible: true ) { gridLayout( cols: 1, rows: 2 ) textField( id: "t1" ) textField( id: "t2", editable: false, text: bind(source: t1, sourceProperty: "text") ) }}
Binding Example
import groovy.swing.SwingBuilder
new SwingBuilder().edt { frame( title: "Binding Test", size: [200, 120], visible: true ) { gridLayout( cols: 1, rows: 2 ) textField( id: "t1" ) textField( id: "t2", editable: false, text: bind{ t1.text } ) }}
Convention over Configuration
Don't repeat yourself (DRY)
MVC Pattern
Testing supported “out of the box”
Automate repetitive tasks
Convention over Configuration
Java Desktop Application Conventions are MIA
Very few official examples
No Blueprints (Like Java EE Blueprints)
We have to create our own
Following Grails Patterns
Source Files Segregated by Role
Standardize App Lifecycle (like JSR-296)
Automated Packaging (App, WebStart, Applet)
Lyfecycle Scripts
Lifecycle Scripts are in griffon-app/lifecycle
Lifecycle Events modeled after JSR-296
Initialize
Startup
Ready
Shutdown
Don't Repeat Yourself
How? Use a Dynamic Language!
With Closures/Blocks
With terse property syntaxmyJTextArea.text = "Fires Property Change"
With terse eventing syntaxbutton.actionPerformed = {println 'hi'}
With Rich Annotation Support@Bindable String aBoundProperty
Most of this impacts the View Layer
See JavaOne 2008 TS-5098 - Building Rich Applications with Groovy's SwingBuilder
Built-in Testing
Griffon has built in support for testing
create-mvc script creates a test file in test/integration
Uses GroovyTestCase
See JavaOne 2008 TS-5101 – Boosting your Testing Productivity with Groovy
Griffon doesn’t write the test for you
test-app script executes the tests for youBootstraps the application for you
Everything up to instantiating MVC Groups
Testing Plugins
Sometimes apps need more involved testing
fest Fluent interface for functional swing testing
easybBehavioral Driven Development
code-coverage – CoberturaLine Coverage Metrics
jdependCode quality metrics
codenarcStatic code analysis
Automate Tasks
command line interface
Scripts and events
plugins
builders: SwingX, JIDE, Flamingo, Trident , CSS, JavaFX and more
miscellaneous: installer (IzPack, RPM, OSX app bundles), Splash, Wizard, Scala
●Griffon's Roadmap
Resources
http://griffon.codehaus.org
http://griffon.codehaus.org/Builders
http://griffon.codehaus.org/Plugins
http://groovy.dzone.com
twitter: @theaviary
Griffon in Action (2010)
● http://manning.com/almiray
● http://groovymag.com
Groovy, Grails, Griffon and more!
Questions
●Thank you!
Image Credits
http://www.flickr.com/photos/fadderuri/841064754/
http://www.flickr.com/photos/colorloose/3539708679/
http://www.flickr.com/photos/icultist/2842153495/
http://www.flickr.com/photos/bishi/2313888267/
http://www.flickr.com/photos/kirimobile/2581287574/
http://www.flickr.com/photos/chelseaaaaaa/3564365301/
http://www.flickr.com/photos/psd/2086641/