<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Dean Iverson&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/diverson/" />
<modified>2008-03-17T22:48:02Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/diverson/342</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2007, diverson</copyright>
<entry>
<title>Beans Binding for Me?  You Shouldn&apos;t Have.</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/diverson/archive/2007/04/beans_binding_f_1.html" />
<modified>2008-03-17T22:48:02Z</modified>
<issued>2007-04-04T01:17:34Z</issued>
<id>tag:weblogs.java.net,2007:/blog/diverson/342.6987</id>
<created>2007-04-04T01:17:34Z</created>
<summary type="text/plain">Like any self-respecting evil genius, a new toy leads me to thoughts of world domination.  What do you want to do tonight?</summary>
<author>
<name>diverson</name>

<email>dean@pleasingsoftware.com</email>
</author>
<dc:subject>Swing</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/diverson/">
<![CDATA[<h2>New Toys!</h2>
<p>
  As it turns out, yesterday was a momentous day.  No, not because of my last post, but thank you for thinking so.  Actually, <a href="http://weblogs.java.net/blog/shan_man/">Shannon Hickey</a> finally managed to navigate through the licensing maze (scariest thing since Minotaurs lived on Crete) and the new <a href="https://beansbinding.dev.java.net/">Beans Binding</a> framework has been released! 
</p>

<p>
  Greedy bastard that I am, I downloaded it as soon as I found out it was available.  I decided to subject it to the Clueless Newbie Test.  Which is, "How long would it take a complete neophyte (that'd be me) to download the library, compile it, and make it do something useful?"  I'm using a loose definition of the word useful here, but the result was: 20 minutes.
</p>

<p>
  I decided to try to see how nicely beans binding plays with the Swing app framework.  You would think that they would integrate nicely, but one never knows.  Sometimes the Sun gods like to torture us just to watch us squirm like little ants under a magnifying glass.  Ok, I've never put an ant under a magnifying glass but I'm sure it's uncomfortable for the little guys and there must be squirming involved.  Which is just how I've felt at times using <a href="http://java.sun.com/j2ee/1.4/index.jsp">certain</a> <a href="http://java.sun.com/webservices/jaxp/">Java</a> <a href="http://java.sun.com/webservices/jaxws/">technologies</a>.
</p>

<p>
  So what brilliant demonstration of the awesome power of beans binding did I come up with?  Well, I was thinking that if <a href="http://weblogs.java.net/blog/diverson/archive/2007/04/swing_applicati_1.html">counting aloud can be rude</a>, then we need some way to determine when counting is allowed.  The really scary part is, that's all the logic I need to pursue my latest plot to take over the world.  This time my instrument of world domination will be...the JCheckBox!  Mwah, hah, hah, hah.
</p>

<h2>Um...What?</h2>
<p>
  So I started with the code from <a href="http://weblogs.java.net/blog/diverson/archive/2007/04/swing_applicati_1.html">Action Game 1</a>, and transformed it into the new and improved Action Game 2 by adding my weapon of mass construction, the check box.
</p>

<pre>
  protected void startup(String[] args)
    {
      ...
      
      JCheckBox check = new JCheckBox();
      check.setName( "allowCountingCheck" );

      JPanel panel = new JPanel();
      panel.setBorder( BorderFactory.createTitledBorder( rMap.getString( "countingDemo" ) ) );
      panel.setLayout( new BorderLayout() );
      panel.add( label, BorderLayout.NORTH );
      panel.add( btn, BorderLayout.CENTER );
      panel.add( check, BorderLayout.SOUTH );
      show( panel );      
    }
</pre>

<p>And I made a small addition to the .properties file as well (now called ActionGame2.properties, naturally).</p>

<pre>
  allowCountingCheck.text=Allow Counting
  allowCountingCheck.font=Arial-BOLD-14
</pre>

<p>The idea is that the check box enables or disables the "Start Counting" button.  Simple right?  One thing I've learned from watching James Bond is that all world domination plans should be kept as simple as possible.  Oh, and don't explain them to the hero until <i>after</i> you <strike>shoot him</strike> put him to sleep with a gentle tranquilizer.  The whole thing now looks like this:</p>

<center>
  <table class="image">
    <caption align="bottom">Dear UN, that will be 1 MILLION dollars...</caption>
    <tr><td>
      <img alt="countingAllowed1.png" 
           src="http://weblogs.java.net/blog/diverson/archive/images/countingAllowed1.png" 
           width="299" height="167" />
    </td></tr>
  </table>
</center>

<h2>Look Mom, No ActionListeners!</h2>

<p>
  All we need now is to somehow tie the state of the checkbox to the button's enabled property.  An ActionListener you say?  Hmm.  Why don't you just step out onto that bridge over the shark tank while I push this big red button here.
</p>

<p>
  With beans binding, there are no action listeners required.  Just a minor modification to our <code>startup</code> method:
</p>

<pre>
protected void startup(String[] args)
{
  ...
  
  JButton btn = new JButton();
  btn.setName( "startCountingBtn" );
  btn.setAction( aMap.get( "startCounting" ) );

  JCheckBox check = new JCheckBox();
  check.setName( "allowCountingCheck" );

  /*** NO ActionListeners ALLOWED!!! ***/
  BindingContext context = new BindingContext();
  context.addBinding( btn, "${enabled}", check, "selected" );
  context.bind();

  JPanel panel = new JPanel();
  panel.setBorder( BorderFactory.createTitledBorder( rMap.getString( "countingDemo" ) ) );
  panel.setLayout( new BorderLayout() );
  panel.add( label, BorderLayout.NORTH );
  panel.add( btn, BorderLayout.CENTER );
  panel.add( check, BorderLayout.SOUTH );
  show( panel );
}
</pre>

<p>
  Those three little lines with the BindingContext in them are all you need to tie the check box to the button.  How's that for slick?
</p>

<h3>But Wait, There's More!</h3>
<p>
  My blogs have never been short and to the point.  So why start now?  There is another cool way to do this.  Say you don't want to tie the checkbox directly to the button.  Say you need the check box's state to be tracked by a property in some Java bean.  Say whatever you want, but I'm going to show this to you anyway.
</p>

<p>
  The first thing we need is a new property in our <code>ActionGame2</code> class:
</p>

<pre>
  private boolean countingAllowed = true;
  
  public boolean isCountingAllowed()
  {
    return countingAllowed;
  }
  
  public void setCountingAllowed(boolean allowed)
  {
    boolean old = isCountingAllowed();
    countingAllowed = allowed;
    firePropertyChange( "countingAllowed", old, countingAllowed );
  }
</pre>

<p>
  Since the app framework's <code>Application</code> class is derived from <code>AbstractBean</code> we inherit all of the property change support we need.  All we have to do to implement proper bean behavior is to call firePropertyChange as I did above.  Next we just alter our binding a little.
</p>

<pre>
  context.addBinding( this, "${countingAllowed}", check, "selected" );
</pre>

<p>
  And <a href="http://en.wikipedia.org/wiki/Viola">viola</a>!  Now we are tracking the check box's state through our bean property!  Oh, we still need to enable the button don't we.  Picky, picky.  Actually this gives us a chance to show off another cool feature of the Swing app framework's <code>@Action</code> annotation.
</p>

<h2>I Can Disable That Button In 35 Characters</h2>
<p>
  All we need to do is add an <code>enabledProperty</code> to our <code>startCounting</code> annotation:
</p>

<pre>
  @Action( block = Block.COMPONENT, enabledProperty = "countingAllowed" )
  public CountingTask startCounting( ActionEvent ev )
  {
    return new CountingTask();
  }
</pre>

<p>And that's all there is to it!  Now the enabled state of the action is tied to the state of our countingAllowed property.  OMG this is, like, so easy!  Are you sure this is Swing?</p>

<p>The complete source code is listed below.</p>

<pre>
  package playground.swing.framework.actions;

  // import lots.of.classes

  public class ActionGame2 extends SingleFrameApplication
  {
    private boolean countingAllowed = true;

    public boolean isCountingAllowed()
    {
      return countingAllowed;
    }

    public void setCountingAllowed(boolean allowed)
    {
      boolean old = isCountingAllowed();
      countingAllowed = allowed;
      firePropertyChange( "countingAllowed", old, countingAllowed );
    }

    @Action( block = Block.COMPONENT, enabledProperty = "countingAllowed" )
    public CountingTask startCounting( ActionEvent ev )
    {
      return new CountingTask();
    }

    protected void startup(String[] args)
    {
      ApplicationActionMap aMap = ApplicationContext.getInstance().getActionMap( getClass(), this );
      ResourceMap rMap = ApplicationContext.getInstance().getResourceMap( getClass() );

      JLabel label = new JLabel();
      label.setName( "titleLabel" );

      JButton btn = new JButton();
      btn.setName( "startCountingBtn" );
      btn.setAction( aMap.get( "startCounting" ) );

      JCheckBox check = new JCheckBox();
      check.setName( "allowCountingCheck" );

      BindingContext context = new BindingContext();
      context.addBinding( this, "${countingAllowed}", check, "selected" );
      context.bind();

      JPanel panel = new JPanel();
      panel.setBorder( BorderFactory.createTitledBorder( rMap.getString( "countingDemo" ) ) );
      panel.setLayout( new BorderLayout() );
      panel.add( label, BorderLayout.NORTH );
      panel.add( btn, BorderLayout.CENTER );
      panel.add( check, BorderLayout.SOUTH );
      show( panel );
    }

    public static void main( String[] args )
    {
      Application.launch( ActionGame2.class, args );
    }
  }  
</pre>

<p>
  And here are a couple of gratuitous screen shots of our masterpiece.
</p>

<center>
  <table class="image">
    <tr>
      <td>
        <img alt="countingIsAllowed.png"      
            src="http://weblogs.java.net/blog/diverson/archive/images/countingIsAllowed.png" 
            width="298" height="167" />
      </td>
      <td>
        <img alt="countingNotAllowed.png" 
             src="http://weblogs.java.net/blog/diverson/archive/images/countingNotAllowed.png" 
             width="300" height="167" />
      </td>
    </tr>
    <tr><td align="center"><b>Counting is allowed.</b></td><td align="center"><b>Counting aloud is rude!</b></td></tr>
  </table>
</center>


<p>I'm definitely going to be playing with this new framework a lot over the next few weeks.  I wonder what I'll do first when I'm Grand Overlord of the Earth...</p>]]>

</content>
</entry>
<entry>
<title>Swing Application Framework Hacks Unleashed For Smarty Pantses</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/diverson/archive/2007/04/swing_applicati_1.html" />
<modified>2008-03-17T22:48:32Z</modified>
<issued>2007-04-02T21:06:14Z</issued>
<id>tag:weblogs.java.net,2007:/blog/diverson/342.6977</id>
<created>2007-04-02T21:06:14Z</created>
<summary type="text/plain">Learn the Swing Application Framework in 21 Days!  Actually, it only takes 1 day.</summary>
<author>
<name>diverson</name>

<email>dean@pleasingsoftware.com</email>
</author>
<dc:subject>Swing</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/diverson/">
<![CDATA[<p><b><i>Join me now as we explore the murky depths of the Swing Application Framework.</i></b></p>

<p>
  Ok, there is nothing murky about the app framework.  <a href="http://weblogs.java.net/blog/hansmuller/">Hans</a> is fond of saying that one of the primary goals of the framework is to be able to explain it to someone in one hour.  It's a noble goal.  In fact, I think Hans' 
<a href="http://weblogs.java.net/blog/hansmuller/archive/ts-3399-final.pdf">presentation</a> does it pretty well.
</p>

<p>
  Even better than the one-hour goal, in my opinion, is the one-day goal.  With the app framework as it stands today, you can sit down and read through the <a href="https://appframework.dev.java.net/">source code</a> for one day and know everything there is to know about it.  How each feature is implemented, the way they work together, where you need to look if something goes wrong.  Transparency is one of my favorite features in a framework and the application framework is a veritable cornucopia of transparency.
</p>

<p>
  This is really important for a framework that you intend to use as the foundation for your entire application.  Maybe the <a href="http://www.jonathancoulton.com/2006/04/14/thing-a-week-29-code-monkey/">code monkeys</a> (and I use that term affectionately) can get away with the one hour explanation.  But if the buck stops at your keyboard, you really need a deeper understanding.  We don't want any surprises down the road.
</p>

<h3>So let's get to it!</h3>
<p>
  One of the coolest things about the app framework is it's support for resource injection.  It can be used to inject resources like text, fonts, and colors into our Swing components and actions.  How does it work?  <a href="http://www.amazon.com/o/ASIN/0545010225/ref=s9_asin_image_3-hf_favarpcbss_2238_g1/002-7339696-3369627?pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-1&pf_rd_r=188H2MYA7CTHYGTBEDJA&pf_rd_t=101&pf_rd_p=278240701&pf_rd_i=507846"/>Magic</a>?  Unfortunately it's not that fantastical.  It turns out that all we need is a good map.
</p>

<center>
  <table class="image">
    <caption align="bottom">Uhm No, Not That Kind Of Map</caption>
    <tr><td><img alt="Wrong Map" 
      src="http://weblogs.java.net/blog/diverson/archive/images/AppFrameworkMap.png" 
      width="361" height="323" />
    </td></tr>
  </table>
</center>

<p>
  No, application frameworks are way more mundane than that.  What we need is a ResourceMap.  So how do we get one?  Well, like most other application frameworks, the Swing app framework features an Application class as its main abstraction.  We will be using one of Application's subclasses, the SingleFrameApplication class since it provides a few extra house keeping services for us.
</p>

<pre>
package playground.swing.framework.actions

// import this.and.that

public class ActionGame1 extends SingleFrameApplication 
{
  protected void startup( String[] args ) 
  {
    System.out.println( "Ahhhh! I've been launched!" );
  }
  
  public static void main( String[] args ) 
  {
    Application.launch( ActionGame1.class, args );
  }
}
</pre>

<p>When we call <code>Application.launch( ActionGame1.class, args )</code>, the framework performs some initialization steps, creates an instance of our application object (based on the class we passed it in the <code>launch</code> method), and calls that new instance's startup method.  The call to the <code>startup</code> method is done on Swing's event dispatch thread (otherwise known as the EDT).  Therefore it is safe to construct Swing components within the friendly confines of our overridden <code>startup</code>.  So all we've done here is write a program that prints a cutesy message on the console and quits. As Romeo might say: Woo who.</p>

<h3>What about the resource map?</h3>

<p>One of those initialization steps that the framework performes before creating an instance of our application class is to build the application ResourceMap.  A ResourceMap is really just a wrapper around a regular old Java ResourceBundle which is itself just a wrapper around a .properties file.  The convention is that the properties file is named ClassName.properties and is located in a "resources" subpackage of its class' package.  The application ResourceMaps are arranged hierarchically (each ResourceMap has a "parent" property and a getParent method) and mirrors the Application class hierarchy.</p>

<p>So for this case we end up with the following structure for our application-level ResourceMap (where I use the ResourceBundle filename to represent the ResourceMap):</p>

<center>
  <table class="image">
    <caption align="bottom">ResourceMap Hierarchy</caption>
    <tr><td>
      <img alt="AppFrameworkResourceHierarchy.png" 
       src="http://weblogs.java.net/blog/diverson/archive/images/AppFrameworkResourceHierarchy.png" width="350" height="354" />
    </td></tr>
  </table>
</center>

<p>Conceptually, our resources are layered on top of the standard Application class resources.  Since resources are searched for from the bottom up, this allows a resource in ActionGame1 to override a resource in Application.  Which, by the way, is how you would localize the names of the default actions defined by the framework's Application class.</p>

<p>Note that technically our Application class hierarchy includes the SingleFrameApplication class.  Since this class does not have a resource bundle associated with it, it does not appear in our ResourceMap hierarchy.</p>

<h3>So much for ResourceMap 101</h3>

<p>Now that we know where to put our resource files, we just need to know what to put in them.  A Java properties file is just a series of key/value pairs.</p>

<pre>
  # The format of a properties file
  someKey=Some Value
</pre>

<p>In order to inject a resource into a Swing component, all we need is some way to tie the value of the resource (identified by its key) to a particular component.  The Swing app framework uses the component's name to make this connection.</p>

<b>com/acme/coyote/order/form/Anvil.java</b>
<pre>
  package com.acme.coyote.order.form;
  ...
  JLabel description = new JLabel();
  description.setName( "anvilDescription" );
  ...
</pre>
<p/>
<b>com/acme/coyote/order/form/resources/Anvil.properties</b>
<pre>
anvilDescription.text=Anvils are heavy, black, and can be dropped on the head of Tastyus Supersonicus.
anvilDescription.font=Arial-BOLD-24
anvilDescritpion.background=255,255,255
</pre>

<p>Now your resources are not only localizable but are injected into your component automatically.  But wait!  How do resources like "Arial-BOLD-24" and "255,255,255" get turned into the component's font and background color?  Is there some magic there (we ask hopefully; clinging to our last shred of child-like wonderment)?</p>

<p>Nope, sorry (we answer ourselves; heartlessly dashing all remaining childish hope and, frankly, worrying ourselves a bit for asking and answering our own questions).  It's actually very simple.  The framework looks at the name of the property we are trying to set (like "text" or "font") and uses reflection to look up the corresponding property of the component (like "setText" or "setFont").  When it finds the property, it looks at what type of object the set method should be called with (like a Color for setBackground).  Once it knows the type of object it needs, it just queries its list of ResourceConverters looking for one that will do the job.</p>

<p>The app framework comes with several standard resource converters and you can easily write your own as well.  Converters exist for all of the basic types, of course: int, float, double, short, byte, boolean.  In the case of the boolean converter, the words "true", "on", and "yes" evaluate to true.  Everything else evaluates to false.</p>

<p>There are also a few more complex converters which are listed below along with the string formats they accept.</p>

<center>
  <table width="80%" frame="void" border="1">
    <tr>
      <th align="left">ResourceConverter</th>
      <th align="left" width="200">Format</th>
      <th align="left" width="200">Example</th>
      <th align="left">Note</th>
    </tr>
    
    <tr><td rowspan="4">ColorStringConverter</td><td>#RRGGBB</td><td>#FF0000</td><td>Red</td></tr>
    <tr><td>#AARRGGBB</td><td>#80FF0000</td><td>Half transparent red</td></tr>
    <tr><td>R, G, B</td><td>0, 255, 0</td><td>Green</td></tr>
    <tr><td>R, G, B, A</td><td>0, 0, 255, 128</td><td>Half transparent blue</td></tr>
    
    <tr>
      <td rowspan="2">FontStringConverter</td>
      <td>fontName-style-size</td>
      <td>Arial-BOLD-12</td>
      <td>This converter is just a wrapper around the <a href=
        "http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Font.html#decode(java.lang.String)">Font#decode method</a>
      </td>
    </tr>
    <tr><td>fontName style size</td><td>times italic 18</td><td>Dashes are optional, case is insensitive</td></tr>

    <tr>
      <td>IconStringConverter</td>
      <td>filename.[png,jpg,gif]</td>
      <td>new_file.png</td>
      <td>Any of the usual image formats Java supports</td></tr>
  </table>
</center>

<p/>

<h3>Injection Junction, what's your function?</h3>

<p>Let's try a simple example.</p>

<b>playground/swing/framework/actions/ActionGame1.java</b>
<pre>
package playground.swing.framework.actions;

// import a.bunch.of.stuff

public class ActionGame1 extends SingleFrameApplication
{
  protected void startup(String[] args)
  {
    JButton btn = new JButton();
    btn.setName( "startCountingBtn" );

    JPanel panel = new JPanel();
    panel.add( btn );
    show( panel );
  }

  public static void main( String[] args )
  {
    Application.launch( ActionGame1.class, args );
  }
}
</pre>
<p/>
<b>playground/swing/framework/actions/resources/ActionGame1.properties</b>
<pre>
Application.title=Action Game 1
Application.id=ActionGame1

startCountingBtn.text=Start Counting
startCountingBtn.font=times italic 18
startCountingBtn.foreground=0,0,255
</pre>

<p>Here we've created a button and added it to a panel.  We then display the panel in a JFrame by calling the <code>show</code> method of SingleFrameApplication.  In addition to constructing and displaying our frame, the show method also causes our resources to be injected by calling the <code>ResourceMap#injectComponents</code> method and passing our new JFrame as the argument.  The results are simply stunning.</p>
  
<center>
  <table class="image">
    <caption align="bottom">Simply Stunning!</caption>
    <tr><td>
      <img alt="buttononly.png" src="http://weblogs.java.net/blog/diverson/archive/images/buttononly.png" 
      width="183" height="69" />
    </td></tr>
  </table>
</center>

<h3>Hey! What about actions?</h3>

<p>So what happens when you press the button?  That's right!  Absolutely nothing.</p>

<p>So let's add an action to our button.  Now, in the bad old days (circa 2 months ago), that meant having to create an action listener and add it to the button.  But these days the sun is shining, the birds are singing, and we have the <code>@Action</code> annotation.</p>

<b>playground/swing/framework/actions/ActionGame1.java</b>
<pre>
package playground.swing.framework.actions;

// import a.bunch.of.stuff

public class ActionGame1 extends SingleFrameApplication
{
  @Action
  public void startCounting( ActionEvent ev )
  {
    System.out.println("Starting to count...1, 2, 3, 4");
  }
  
  protected void startup(String[] args)
  {
    ApplicationActionMap aMap = ApplicationContext.getInstance().getActionMap( getClass(), this );
    
    JButton btn = new JButton();
    btn.setName( "startCountingBtn" );
    btn.setAction( aMap.get( "startCounting" ) );

    JPanel panel = new JPanel();
    panel.add( btn );
    show( panel );
  }

  public static void main( String[] args )
  {
    Application.launch( ActionGame1.class, args );
  }
}
</pre>
<p/>
<b>playground/swing/framework/actions/resources/ActionGame1.properties</b>
<pre>
Application.title=Action Game 1
Application.id=ActionGame1

startCountingBtn.font=times italic 18
startCountingBtn.foreground=0,0,255

startCounting.Action.text = &Start Counting
</pre>

<p>Now when we push the button we see our message printed on the console. All we had to do was add the <code>@Action</code> annotation to a method.  Then we used our <code>ApplicationContext</code> to get the action map for our class.  We used that action map to get the action that calls our <code>startCounting</code> method.  And finally, we gave that action to the button.</p>

<h3>So we saved a few lines of code, big deal.</h3>

<p>Wait for it.</p>

<p>When counting is allowed, counting aloud can be rude.  But counting aloud while blocking the EDT is downright obnoxious.  The problem is that launching a background thread to do a simple task like counting is a <i>huge</i> pain in the neck.  We'll do it anyway.  Put on a brave face, threads can smell fear.</p>

<p>The first thing we'll need is a background task.  The Swing app framework comes with a class made just for this very purpose.  It's called <code>Task</code>, oddly enough.  Creating a new one is fairly easy.</p>

<pre>
public class CountingTask extends Task&lt;Void, Void&gt;
{
  
  /** Creates a new instance of CountingTask */
  public CountingTask()
  {
    super(CountingTask.class);
  }
  
  public Void doInBackground()
  {
    System.out.println("In the background task and counting...");
    
    for( int i=0; i&lt;5; ++i )
    {
      System.out.println( String.valueOf( i ) );
      
      try
      {
        Thread.sleep( 250 );
      } 
      catch (InterruptedException ex)
      {
        System.out.println("I hate being interrupted while counting!  Now where was I?");
      }
    }
    
    return null;
  }
}
</pre>

<p>The really slick part is that launching a background task is completely trivial with the app framework.  We just need to make two changes to our action method.</p>

<pre>
  @Action
  public CountingTask startCounting( ActionEvent ev )
  {
    return new CountingTask();
  }
</pre>

<p>Yep, all we have to do is create and return the task.  That's it.  Finished.  The framework takes care of launching it for us using a thread pool that it creates and manages (actually a ThreadPoolExecutor for you concurrency geeks out there).</p>  

<h3>Putting it all together.</h3>

<p>Since that was too easy, let's dress up the interface just a bit with a label as well.</p>

<b>playground/swing/framework/actions/ActionGame1.java</b>
<pre>
package playground.swing.framework.actions;

// import a.bunch.of.stuff

public class ActionGame1 extends SingleFrameApplication
{
  @Action
  public CountingTask startCounting( ActionEvent ev )
  {
    return new CountingTask();
  }
  
  protected void startup(String[] args)
  {
    ApplicationActionMap aMap = ApplicationContext.getInstance().getActionMap( getClass(), this );
    ResourceMap rMap = ApplicationContext.getInstance().getResourceMap( getClass() );

    JLabel label = new JLabel();
    label.setName( "titleLabel" );
    
    JButton btn = new JButton();
    btn.setName( "startCountingBtn" );
    btn.setAction( aMap.get( "startCounting" ) );

    JPanel panel = new JPanel();
    panel.setBorder( BorderFactory.createTitledBorder( rMap.getString( "countingDemo" ) ) );
    panel.setLayout( new BorderLayout() );
    panel.add( label, BorderLayout.NORTH );
    panel.add( btn, BorderLayout.CENTER );
    show( panel );
  }

  public static void main( String[] args )
  {
    Application.launch( ActionGame1.class, args );
  }
}
</pre>
<p/>
<b>playground/swing/framework/actions/resources/ActionGame1.properties</b>
<pre>
Application.title=Action Game 1
Application.id=ActionGame1

countingDemo=Counting Demonstration
countingIsAllowed=Push the button to start counting.

titleLabel.text=${countingIsAllowed}
titleLabel.font=Arial-BOLD-16

startCountingBtn.font=Arial-BOLD-24
startCountingBtn.foreground=0,0,255

startCounting.Action.text = &Start Counting
startCounting.Action.shortDescription = Start counting in the background
</pre>

<p>Let's go through these changes real quick:
  <ol>
    <li>We included the change to the <code>startCounting</code> action.</li>
    <li>A label has been added whose text is retrieved from the resource bundle.</li>
    <li>The label's text in the .properties file is a gratuitous example of how one property can refer to another.</li>
    <li>A tooltip for the startCounting action was added.</li>
    <li>We created a titled border and used <code>BorderLayout</code> to dress things up a bit.</li>
    <li>The text for the titled border is retrieved from the resource bundle just like a typical piece of localized text would be.</li>
    <li>We've added a mnemonic to the action's text using the '&amp;' character.</li>
    <li>We added some Application resources to the .properties file in order to specify the title of the application and an ID string (which is used when storing user preferences and such)</li>
  </ol>
</p>

<p>This is what our stunning application looks like now.</p>

<center>
  <table class="image">
    <caption align="bottom">Simply Stunning-er!</caption>
    <tr><td>
      <img alt="final.png" 
           src="http://weblogs.java.net/blog/diverson/archive/images/final.png" 
           width="300" height="202" />
    </td></tr>
  </table>
</center>

<p>And this is what we see when the magical button is pushed.</p>

<pre>
  In the background task and counting...
  0
  1
  2
  3
  4  
</pre>

<p>Some of you who have done this a time or two are probably anxious to point out that there is a major piece missing here.  What happens if we quickly push the button twice?</p>

<pre>
  In the background task and counting...
  0
  1
  In the background task and counting...
  0
  2
  1
  3
  2
  4
  3
  4
</pre>

<p>My, what a mess.  When performing background tasks we usually have to be careful to disable the interface while a background task is running.  Then we have to figure out when the task is finished so we can re-enable it.  This can be an error-prone process but the framework gives us an easy way out here too!</p>

<h3>There's just one more thing.</h3>

<p>With one trivial addition to our <code>@Action</code> annotation, this whole problem just disappears.</p>

<pre>
  @Action( block = Block.COMPONENT )
  public CountingTask startCounting( ActionEvent ev )
  {
    return new CountingTask();
  }
</pre>

<p>We simply tell the action to block our component while the task is running.  Now the framework handles all of the details of disabling our button when the task begins and re-enabling it when the task ends.  Personally, I love frameworks that do more work so I can listen to more <a href="http://javaposse.com/">Java Posse</a>...oops, I mean be more productive with other things.</p>

<p>This is what we now see after the button has been pushed.</p>

<center>
  <table class="image">
    <caption align="bottom">Simply Blocked</caption>
    <tr><td>
      <img alt="finalblocked.png" 
           src="http://weblogs.java.net/blog/diverson/archive/images/finalblocked.png" 
           width="301" height="204" />
    </td></tr>
  </table>
</center>

<h3>Hey, boy!  How come that don't look like no Mac program?</h3>

<p>You have probably noticed that I haven't been using the normal Aqua look and feel even though I'm obviously developing this on a Mac.  What you're seeing is the new <a href="https://nimbus.dev.java.net/">Nimbus</a> look and feel.</p>

<p>Like most of the other things I've covered, using this with the Swing app framework is a simple one line addition.  Is that a coincidence or am I just lazy?  You decide.  Regardless, if you would like to use a specific look and feel in your app framework application, all you have to do is....</p>

<p>You know what?  I'm not going to tell you.  Magicians don't divulge all of their secrets!</p>

<h3>That's lame!</h3>

<p>Very true.  But that hasn't stopped me yet in this post!</p>

<p>Oh, alright.  Just download the Nimbus <a href="http://swinglabs.org/hudson/job/Nimbus%20Continuous%20Build/lastSuccessfulBuild/artifact/code/dist/nimbus.jar
">jar file</a> and put it in your class path.  Then add one extra line to the ActionGame1.properties file:</p>

<pre>
  ...
  Application.lookAndFeel=org.jdesktop.swingx.plaf.nimbus.NimbusLookAndFeel
  ...
</pre>

<p>There you have it - no more secrets.</p>]]>

</content>
</entry>
<entry>
<title>A Guide To The Future (Of Swing Applications)</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/diverson/archive/2007/03/a_guide_to_the.html" />
<modified>2007-08-02T14:38:12Z</modified>
<issued>2007-03-19T20:23:21Z</issued>
<id>tag:weblogs.java.net,2007:/blog/diverson/342.6857</id>
<created>2007-03-19T20:23:21Z</created>
<summary type="text/plain">What technologies do you need to learn today to write the Swing applications of tomorrow?</summary>
<author>
<name>diverson</name>

<email>dean@pleasingsoftware.com</email>
</author>
<dc:subject>Swing</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/diverson/">
<![CDATA[I posited in my last blog that Swing application development is about
to change for the better. &nbsp;A few years ago the topic of the Swing
conversation shifted from the components to the applications. People were no longer just trying to wrap their heads around the
toolkit, but instead they started to shift their effort to figuring out
how to really write professional applications with this thing. This is a neccessary step in the maturation of any new
technology. &nbsp;I'm not sure why it took so long for Swing to get
there, but the happy point is that it finally did.<br />
<br />
The result was that some new Swing components were created to fill some
gaps in the toolkit and some best practices started to emerge. Heck,
there even began to be a <a href="http://www.amazon.com/Swing-Hacks-Joshua-Marinacci/dp/0596009070">few</a> <a href="http://www.lulu.com/content/120769">books</a> <a href="http://www.curious-creature.org/2007/03/11/filthy-rich-clients-book-cover/">published</a> that were not just guided tours of the Swing component library. &nbsp;People <span style="font-style: italic;">finally</span>
stopped feeling obligated to try and explain that Swing was based on a
kind of modified MVC. Yes, yes, we get it, already.  The view and
controller are sort of combined...well except that there are these
things called UI delegates that do control how the view is rendered -
unless you override the paintComponent method, of course. &nbsp;<br />
<br />
Oh, and there are defaults for the look and feel that may or may not be
in effect because the programmer can override them by setting
properties and, well, events can be kind of a pain to handle because
you have to implement an ActionListener, or a MouseListener or
WindowListener or ChangeListener or whatever, as an inner class.&nbsp;
Or you can use an anonymous class if it's really just a small event
handler but that makes your code look a little uglier. &nbsp;But there
is an abstraction called Action that can make life a little easier for
you in some&nbsp;situations. &nbsp;And threading? &nbsp;Don't even go
there! &nbsp;Uhm...what was I saying again? &nbsp;<br />
<br />
Oh yeah, as I was saying, I'm not sure why it took so long for the
Swing community to move past that initial figure-out-the-toolkit stage.
&nbsp;One of life's great mysteries, I guess. &nbsp;<br />
<br />
But now we are finally ready to start looking at the bigger picture and
answer the really interesting question: "So just what is the best way
to actually write a Swing application?"<br />
<br />
I claim that the appropriate answer to that question no longer
begins with: "Well, there is this thing called a JFrame, see, and you
need to be careful how you instantiate it - no, you really shouldn't
just subclass it - there's this method called invokeLater and what you
do is..."<br />
<br />
So let's take a look at the things that will go into building
tomorrow's professional Swing application. &nbsp;If I had to come up
with the core technologies to base my next Swing application on, what
would it look like? &nbsp;In one sense, the answer could be as simple
as "just use Netbeans RCP." &nbsp;But what fun is that? &nbsp;So let's
assume that the application's complexity or the developer's skill level
makes the Netbeans RCP inappropriate. &nbsp;After all, there are whole
classes of applications for which an RCP is overkill but they still
have to look good and behave well on user's desktops. &nbsp;Rich
Internet Applications, I'm looking at you.<br /><br/>
<h3>Begin At The Beginning</h3>
Let's start simple. &nbsp;All good applications need a splash screen,
right? &nbsp;A sweet little piece of eye candy to get things started.
&nbsp;Well, thanks to the <a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/splashscreen/">splash screen support</a> in Java 6, this is now trivial for a Java app.<br />
<br />
Alright, next we need some frameworks so that we can avoid the
you-start-with-a-JFrame syndrome mentioned above. &nbsp;Well the Swing
application framework and the new data binding framework (JSRs <a href="http://jcp.org/en/jsr/detail?id=296">296</a> and <a href="http://jcp.org/en/jsr/detail?id=295">295</a>,
respectively) fill this need. &nbsp;The app framework handles your
application's infrastructure: resources, <a href="http://en.wikipedia.org/wiki/Internationalization_and_localization">i18n</a>, and actions. &nbsp;These
two JSRs also make it easy to access data on a background thread and
bind that data to components in your views.<br />
<br />
But how do we create those views? &nbsp;Hand coding, you say?
&nbsp;That is so 12 months ago. &nbsp;These days the tools are good
enough that you don't have to spend all day writing that dialog panel
that should only have taken 30 minutes. &nbsp;Still trying to make
GridBagLayout work? &nbsp;You <a href="http://madbean.com/anim/totallygridbag">poor bastard</a>. &nbsp;Stop! &nbsp;Netbeans has <a href="http://www.netbeans.org/kb/50/quickstart-gui.html">Matisse</a> with it's support for GroupLayout. There is also&nbsp; <a href="http://www.jformdesigner.com/">JFormDesigner</a> or <a href="http://www.jetbrains.com/idea/features/gui_builder.html">Idea</a> with support for <a href="http://www.jgoodies.com/freeware/forms/">JGoodies Forms</a>.
&nbsp;Life is too short to code your UIs by hand. &nbsp;These products
make it almost trival to design complex panels.
&nbsp;Doing the same with gridbag would be about as much fun as
teaching preschool to teething toddlers.<br />
<br />
A lot of real applications also need to interact with the user's
desktop and perhaps launch the native email client or web browser. This can all be done in Java 6 now thanks to another <a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/desktop_api/">recent addition</a>.<br/><br/>
<h3>More Components</h3>
All programs need a way to report errors to users. &nbsp;My experience
is that most programs at some point have to work with dates as well.
&nbsp;Swing doesn't have a nice solution for these, but there is always
SwingX. Here are the date picker and error dialog from SwingX.<br />
<br />
<table style="width: 90%; text-align: left; margin-left: auto; margin-right: auto;" border="0" cellpadding="2" cellspacing="2">
  <tbody>
    <tr>
      <td><img alt="datepicker.png" src="http://weblogs.java.net/blog/diverson/archive/images/datepicker.png" width="359" height="403" /></td>
      <td><img alt="errorpain.png" src="http://weblogs.java.net/blog/diverson/archive/images/errorpain.png" width="473" height="387" /></td>
    </tr>
  </tbody>
</table>
<br />
<br />
There are a lot of other components worth checking out in SwingX.
&nbsp;JXTable and JXList are very nice replacements for Swing's JTable and
JList, for example. &nbsp;My advice for getting started with SwingX is to
skip right over the old out-of-date SwingX milestones and go <a href="http://swinglabs.org/downloads.jsp">download</a> the latest weekly build. &nbsp;It is worth pointing out that SwingX is one of the projects of <a href="http://swinglabs.org/">SwingLabs</a> along with the a lot of other good stuff, some of which I'm going to write about below.<br />
<br />
One big drawback of SwingX is that it is hard to get up to speed.
&nbsp;The situation is improving with the recent changes in the
project's infrastructure and the documentation is also improving.
&nbsp;There are also plenty of good commercial components out there
from vendors like <a href="http://www.jidesoft.com/">JIDE</a> and <a href="http://www.migcalendar.com/index.php">MiG</a>.<br />
<br />
<h3>Adding The Wow Factor</h3>
Adding that extra punch to an application is becoming the norm these days thanks to
users whose expectations have been raised by flashy websites and slick
Mac applications. &nbsp;This is a good thing. &nbsp;After all, putting
in the "wow" is where most of the fun is! &nbsp;To easily add some
sizzle to a Swing app, you will need to look at the <a href="http://weblogs.java.net/blog/joshy/archive/2006/09/introducing_pai.html">Painter</a>
work being done in SwingX. &nbsp;Note that the latest painter work is
just now being merged back into the main development trunk of SwingX.
&nbsp;Isn't it fun to be on the bleeding edge of the future? &nbsp;And,
of course, you will need the <a href="https://timingframework.dev.java.net/">timing framework</a> for all of the cool animation you have to put into your program.<br />
<br />
Since we're talking about the <span style="font-style: italic;">future</span> of Swing development here, there is also a new cross platform look and feel in the works that doesn't suck.  It's called <a href="http://galbraiths.org/blog/2007/03/09/desktop-matters-announcing-nimbus/">Nimbus</a>.<br />
<h3>Coda</h3>
Ok, so here is my list of technologies anyone starting a new Swing applications should check out:<br />
<ul>
  <li><a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/splashscreen/">Splash screen support</a></li>
  <li><a href="http://jcp.org/en/jsr/detail?id=296">Swing application framework</a></li>
  <li><a href="http://jcp.org/en/jsr/detail?id=295">Beans binding</a></li>
  <li><a href="http://www.netbeans.org/kb/50/quickstart-gui.html">Matisse GUI builder</a></li>
  <li><a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/desktop_api/">Desktop integration</a></li>
  <li><a href="http://swinglabs.org/">SwingX components and painters</a></li>
  <li><a href="https://timingframework.dev.java.net/">The timing framework</a></li>
  <li><a href="http://galbraiths.org/blog/2007/03/09/desktop-matters-announcing-nimbus/">Nimbus</a></li>
</ul>
 What did I miss? What technologies do you need to learn today to write the Swing applications of tomorrow?<br />]]>

</content>
</entry>
<entry>
<title>Paradigm Swing</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/diverson/archive/2007/03/paradigm_swing_1.html" />
<modified>2007-08-02T14:38:53Z</modified>
<issued>2007-03-12T22:53:23Z</issued>
<id>tag:weblogs.java.net,2007:/blog/diverson/342.6799</id>
<created>2007-03-12T22:53:23Z</created>
<summary type="text/plain">Swing development is-a changing.  Not only that, but Swing has-a lot of momentum right now.</summary>
<author>
<name>diverson</name>

<email>dean@pleasingsoftware.com</email>
</author>
<dc:subject>Swing</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/diverson/">
<![CDATA[<p>It's a beautiful spring (the season, not the framework) day here in Colorado so I can't help but be in a good mood as I begin to look forward to JavaOne (the first one I will actually be attending) and bid a fond farewell to the first, but hopefully not last, Desktop Matters conference.</p>

<p>At least one thing became clear at the Desktop Matters conference last week.  The way that we write Swing applications is changing for the better.  A few other things that became clear are that <a href="http://weblogs.java.net/blog/chet">Chet</a> has a great sense of humor to go along with a lot of patience for friendly ribbing; <a href="http://weblogs.java.net/blog/hansmuller">Hans</a> really is a nice guy; and <a href="http://www.curious-creature.org/">Romain</a> has a startling talent for video clairvoyance (Chet, that race car demo was very...um, quaint).</p>

<p>Almost gone are the days when every new Swing programmer will be left on their own standing in front of the huge maze of Swing with only the "Abandon hope all ye who enter" sign for company.  Those of us who still remember our first Swing program probably remember something like this:</>

<pre><code>
public class MyFirstReallyCoolSwingApp extends JFrame {

  public static void main( String[] args ) {
    myApp = new MyFirstReallCoolSwingApp();
    ...
  }
}
</pre></code>

<p>EDT?  Isn't that a home pregnancy test or something?</p>

<p>So much for the old paradigm.  A paradigm is only worth about 20 cents, anyway.</p>

<p>Alrighty, moving right along then.</p>

<p>These days there is, and has been for some time now, actually, a new life and energy behind desktop Java.  Personally, I think this resurgance can be traced pretty easily if we look back now.  I think we can thank Eclipse for showing the way.  It came along at just the right time and provided us not only with the great Java development tool but also with the prototypical example of a great Java desktop application.  Of course Eclipse simply could not have been so successful without the improvements made to the Java platform in general.</p>

<p>That brings us to another thing that became clear to me at Desktop Matters: there are a lot of very smart people working at Sun.  Okay, I haven't actually met very many of them, but this is certainly true of the Swing team.  
I am extrapolating from there.</p>

<p>A short while later, Netbeans 5.0 put the lie to the "Swing is slow" line.  It became abundantly clear to anyone who was really paying attention that desktop Java was an increasing priority at Sun.  The release of all those <a href="http://java.sun.com/developer/technicalArticles/javase/6_desktop_features/">desktop-related improvements</a> in Java 6 was yet another data point in the rise of Swing's stock.  And after hearing the Swing team talk about their plans for the future, it looks to me like things are still trending upwards.</p>

<p>It is not clear to me what the business case is for this renewed commitment Sun has for desktop Java.  What return does Sun expect on their investment?  It certainly <i>seems</i> like there has been more corporate support but perhaps what we're seeing is simply the result of the energy and dedication of a small but talented team of Swing engineers?  As just an outsider looking in, I won't pretend to know.  But I'm also not going to look a gift horse in the mouth because, darn it, I really enjoy Swing programming.</p>

<p>I love the flexibility of Swing.  I love the power of Java2D.  And there is some great work going on in <a href="http://swinglabs.org/">SwingLabs</a>.  Now I'm not a Java2D wizard like <a href="http://weblogs.java.net/blog/campbell/">Chris</a>, I can't design ultra cool interfaces like <a href="http://www.curious-creature.org/">Romain</a>, and I certainly can't <a href="https://timingframework.dev.java.net/">time things</a> as well as <a href="http://weblogs.java.net/blog/chet">Chet</a>, but I do know that Swing will be a lot nicer to work with very soon thanks to JSRs <a href="http://jcp.org/en/jsr/detail?id=295">295</a> and <a href="http://jcp.org/en/jsr/detail?id=296">296</a> along with the <a href="http://blogs.sun.com/roumen/entry/swing_application_framework_swing_databinding">support</a> for them that is going into <a href="http://www.netbeans.org">Netbeans</a>.  And this will apply to novice and experienced programmers alike.</p>

<p>This year looks like it will be a continuation of the rise in excitement surrounding desktop Java.  With the release of the <a href="http://weblogs.java.net/blog/chet/archive/2007/01/filthy_rich_cli.html">Filthy Rich Clients</a> book and the <a href=http://www.netbeans.org/books/rcp.html">Netbeans RCP book</a> as well as the upcoming focus on media, 3D, animation, and deployment in JDK 7, I just can't wait to see what we'll be talking about at next year's Desktop Matters conference.</p>

<p>And one last thing.  Since we were on the subject of my interface design impairment, do you suppose there is any chance of Romain putting together a UI design video podcast.  You know, kind of like "Romain's Eye for the Programmer Guy" or something?  Maybe that's not a good title.  The pronunciation of the last word would always be in question.</p>]]>

</content>
</entry>

</feed>