Sunday, August 14, 2011

Ant InputHandler GUI Using Groovy

Intro

With Apache Ant you can get input from the user using the "input" task. When you run Ant in a console window, the DefaultInputHandler is used. This handler just uses the console's error and input streams. When you run Ant in a graphical IDE, a Graphical User Interface based input handler may be used. This handler will use the graphics toolkit (on Eclipse that would SWT) to pop up dialog boxes.

GUI in console? Can you use GUI input dialogs when running in a command shell? Yes, and it is very easy. First you create an InputHandler subclass that will be used with the Ant command option "-inputhandler <class>".

GUI InputHandler subclass

Below in listing 1, there is example Groovy source: AntGuiInputHandler.groovy

Much harder is actually getting Ant to use this handler.

Build file

First lets create an Ant build file that will get some input:

<project name="AntGui" default="all" basedir=".">
<target name="all">

    <input message="What is your name?"       addproperty="got.response"/>  
    <echo>${got.response}</echo>  
</target>

</project>
Compiling
Now, compile the Groovy source as follows: 
groovyc AntGuiInputHandler.groovy
Running There are many ways to actually run the Ant build. The simplest but not the best way is to set up your CLASSPATH and then run Ant as usual, for example:

C:\temp\AntGui>set classpath=.;\java\groovy\embeddable\groovy-all-1.8.1.jar

C:\temp\AntGui>ant -inputhandler AntGuiInputHandler Buildfile: C:\temp\AntGui\build.xml

all: [input] prompt=What is your name? [input] Josef [echo] Josef from Groovy InputHandler

BUILD SUCCESSFUL Total time: 11 seconds

C:\temp\AntGui>ant -inputhandler AntGuiInputHandler Buildfile: C:\temp\AntGui\build.xml

all: [input] prompt=What is your name? [input] Josef [echo] Josef from Groovy InputHandler

BUILD SUCCESSFUL Total time: 5 minutes 35 seconds

The resulting input dialog is: image
import java.awt.event.WindowEvent
import javax.swing.ActionPropertyChangeListener;

import groovy.swing.SwingBuilder;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.input.InputHandler;
import org.apache.tools.ant.input.InputRequest;
import org.apache.tools.ant.input.MultipleChoiceInputRequest;

import javax.swing.*


/**
* @author jbetancourt
*
*/
class AntGuiInputHandler implements InputHandler {

   /* (non-Javadoc)
    * @see org.apache.tools.ant.input.InputHandler#handleInput(org.apache.tools.ant.input.InputRequest)
    */
   @Override
   public void handleInput(InputRequest request) throws BuildException {
       def response = ''
       println "prompt=${request.getPrompt()}"
     
       if(request instanceof org.apache.tools.ant.input.MultipleChoiceInputRequest){
           response =     getMultipleChoiceInput(request)
       }else{
           response = getTextInput(request)
       }
     
       println response
       request.setInput("${response} from Groovy InputHandler");
   }
 
   String getTextInput(InputRequest request){
       def swingBuilder = new SwingBuilder()
       def response = ''
       def prompt = request.getPrompt()
       response = JOptionPane.showInputDialog(null, 'Dialog',prompt, 
          JOptionPane.OK_OPTION)

       return response  
     
   }
 
 
   String getMultipleChoiceInput(InputRequest request){
       def swingBuilder = new SwingBuilder()
       def req = (MultipleChoiceInputRequest)request;
     
       def choices = req.getChoices()
       def defaultValue = req.getDefaultValue()      
       def prompt = request.getPrompt()
     
       def pane = swingBuilder.optionPane(message:prompt, 
           selectionValues:choices as Object[], 
           optionType:JOptionPane.CLOSED_OPTION)
       def dialog = pane.createDialog(null, 'dialog')
       dialog.show()
     
       def response = pane.getInputValue()
     
       println "input: ${response}"      
     
       return response
   }

   static main(args) {
       def swing = new SwingBuilder()
       def frame = swing.frame(title:'Dialog'){
           panel {
               textField(id:'message',columns:25)
               button(text:'ok',actionPerformed:{ println swing.message.text })
           }
       }
       frame.pack()
       frame.setVisible(true)
   }
}

Pretty groovy use of Groovy!

No comments: