SlideShare a Scribd company logo
Welcome to the Desktop Revolution
What is Griffon ?
Griffon @ Svwjug
+                 +

+ Sugar, Spice and everything Nice =
Griffon @ Svwjug
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()
Griffon @ Svwjug
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.SwingBuilder
import 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 } )
  }
}
Griffon @ Svwjug
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)
Griffon @ Svwjug
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 syntax
  myJTextArea.text = "Fires Property Change"
  With terse eventing syntax
  button.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 you
     Bootstraps 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
  easyb
     Behavioral Driven Development
  code-coverage – Cobertura
     Line Coverage Metrics
  jdepend
     Code quality metrics
  codenarc
     Static 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/

More Related Content

Griffon @ Svwjug

  • 1. Welcome to the Desktop Revolution
  • 4. + + + Sugar, Spice and everything Nice =
  • 6. 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() ); } }
  • 7. 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() ); } }
  • 8. GroovierHelloWorld.groovy class HelloWorld { String name def greet() { "Hello $name" } } def helloWorld = new HelloWorld(name:"Groovy") println helloWorld.greet()
  • 10. Swing
  • 11. 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 ...
  • 12. // 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; } }
  • 13. The light at the end of the tunnel...
  • 14. import groovy.swing.SwingBuilder import 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) } }
  • 15. 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
  • 17. 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 { … }
  • 18. 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 })
  • 19. 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 } } })
  • 21. 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") }
  • 22. 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") ) } }
  • 23. 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 } ) } }
  • 25. Convention over Configuration Don't repeat yourself (DRY) MVC Pattern Testing supported “out of the box” Automate repetitive tasks
  • 26. 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)
  • 28. Lyfecycle Scripts Lifecycle Scripts are in griffon-app/lifecycle Lifecycle Events modeled after JSR-296 Initialize Startup Ready Shutdown
  • 29. Don't Repeat Yourself How? Use a Dynamic Language! With Closures/Blocks With terse property syntax myJTextArea.text = "Fires Property Change" With terse eventing syntax button.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
  • 30. 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 you Bootstraps the application for you Everything up to instantiating MVC Groups
  • 31. Testing Plugins Sometimes apps need more involved testing fest Fluent interface for functional swing testing easyb Behavioral Driven Development code-coverage – Cobertura Line Coverage Metrics jdepend Code quality metrics codenarc Static code analysis
  • 32. 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
  • 35. Griffon in Action (2010) ● http://manning.com/almiray
  • 36. http://groovymag.com Groovy, Grails, Griffon and more!