<?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>Hans Muller&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/" />
<modified>2008-01-19T00:03:19Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/hansmuller/45</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, hansmuller</copyright>
<entry>
<title>Introducing the SceneGraph Project</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2008/01/introducing_the.html" />
<modified>2008-01-19T00:03:19Z</modified>
<issued>2008-01-09T02:50:28Z</issued>
<id>tag:weblogs.java.net,2008:/blog/hansmuller/45.8952</id>
<created>2008-01-09T02:50:28Z</created>
<summary type="text/plain">An introduction to the new java.net SceneGraph project.  </summary>
<author>
<name>hansmuller</name>


</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[    <h1>Introducing SceneGraph</h1>
    <p>
      I haven't written a blog entry since January when I advertised the fledgling 
      <a
        href="http://weblogs.java.net/blog/hansmuller/archive/2007/01/application_fra.html">
        Swing Application Framework (JSR-296)
      </a>
      project with an uncharacteristically brief item.  Work on that
      kept me busy until summer, when the Java FX juggernaut got
      underway here at Sun.  Since then I've devoted much of my time
      to leading a project we've called "Scenario" that provides the
      graphical runtime for Java FX Script.  We're now a public
      project on java.net called 
      <a href="https://scenegraph.dev.java.net/"> 
        scenegraph.dev.java.net
      </a>. 
      You'll find downloads of the the 0.4.1 version of the Scenario
      source and binaries and (very) sketchy javadoc on the site.  The
      0.x version number is intended to convey the fact that the API
      hasn't stabilized yet.  It's sufficient for experimentation and
      the implementation was robust enough to support a port of the
      Java FX Script interpreter, which we've showcased with a
      Scenario version of the
      <a href="http://download.java.net/javadesktop/scenario/demos/demo-12-10-07/fxpad-0.41/fxpad.jnlp">
        FXPad Demo
      </a>.
      Obviously, we don't recommend putting anything based on Scenario
      into production.  Not yet.
    </p>
      
    <p>
      The code is being made available under the GPLv2 license.
      Passion about open source licenses is not something I possess so
      I'll leave the shouting about the implications of this choice to
      others.  Suffice it to say that, per my limited understanding of
      these matters, you're free to share the code, and in the process of
      developing it further.  We're moving our discussions of the API
      to the newly minted
      <a href="http://forums.java.net/jive/forum.jspa?forumID=129">
        Scene Graph java.net forum 
      </a>.  
      If you're interested in the project's evolution, that would be a
      good place to start looking.
    </p>

    <p>
      There are quite a few engineers working on Scenario, most of
      whom have made bigger contributions to the new software than I
      have, and you'll be hearing from them in their own blogs before
      too long.  For now, what I'd like to do is to provide an
      introduction to the new Java APIs and just one demo.  The team
      has written a whole raft of demos and we'll be opening up a
      subproject before too long, that contains the entire
      demo catalog.
    </p>

    <h2>Demo</h2>
    <p>
      All of the examples that follow are part of a demo, each one
      occupies a tab.   If you press "control-T" after clicking on a
      demo, you'll get a nice interactive tree view of the scene
      graph's structure, thanks to 
      <a href="http://weblogs.java.net/blog/aim/">
        Amy Fowler
      </a> for that!  So press the orange button to launch the demo.
    </p>

    <p align="center">
      <a href="http://download.java.net/javadesktop/scenario/demos/intro-Intro.jnlp">
        <img alt="Launch Button" 
          src="http://weblogs.java.net/blog/hansmuller/archive/jws-launch-button.png" 
          width="88" 
          height="23"
          style="border-style:none"/>
      </a>
    </p>
      
    <p>
      Note also: the demo scales the selected example scene to fit.
      This is done with a small extension to <code>JSGPanel</code>,
      take a look at the 
      <a href="http://weblogs.java.net/blog/hansmuller/archive/Intro.java">
        code
      </a> 
      if you're interested.
      

    <h2>Basics, Hello World</h2>

    <p>
      <img alt="Intro Screenshot1" 
        src="http://weblogs.java.net/blog/hansmuller/archive/intro-screenshot1.PNG"
        width="290" 
        height="195" />
    </p>


    <p>
      A scene graph, really a tree for now, is a data structure you
      create from <i>leaf</i> nodes that represent visual elements
      like 2D graphics and Swing components, <i>filter</i> nodes that
      represent visual state, like 2D transforms and composition, and
      <i>group</i> nodes that manage a list of children.  All nodes
      are subclasses of <code>SGNode</code> and have a parent node,
      rectangular bounds, visibility, and support for event
      dispatching.  Leaf nodes extend <code>SGLeaf</code> and have
      <code>paint/repaint</code> methods similar to
      AWT/Swing. <code>SGFilter</code> nodes have one child, and
      <code>SGGroups</code> have a list of them.  To display a scene
      graph you set the <code>scene</code> property of a
      <code>JSGPanel</code>, and add the panel to a Swing application
      in the usual way.  Here's a simple example:
    </p>

    <pre>
SGText text = new SGText();
text.setText("Hello World");
JSGPanel panel = new JSGPanel();
panel.setScene(text);
panel.setPreferredSize(new Dimension(640, 480));
// create a JFrame, add the panel to it, etc..
    </pre>
    
    <p>
      One unusual line from the previous example, from a Swing
      programmer's perspective, is that we've explicitly set the
      preferred size of the <code>JSGPanel</code>.  Although the
      JSGPanel will compute (and recompute...) a preferred size based
      on bounds of its scene, it's usually a good idea to define a
      reasonable fixed preferred size instead.  To make the scene
      slightly more interesting to look at, we can set the
      <code>SGText</code> node's font and color, turn on antialiasing,
      and configure the panel's background color:
    </p>

    <pre>
SGText text = new SGText();
text.setText("Hello World");
text.setFont(new Font("SansSerif", Font.PLAIN, 36));
text.setAntialiasingHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
text.setFillPaint(Color.WHITE);
JSGPanel panel = new JSGPanel();
panel.setBackground(Color.BLACK);
panel.setScene(text);
panel.setPreferredSize(new Dimension(640, 480));
    </pre>

    <h2>More Hello World: Groups and Shapes</h2>

    <p>
      <img alt="Intro Screenshot2" 
        src="http://weblogs.java.net/blog/hansmuller/archive/intro-screenshot2.PNG"
        width="290" 
        height="195" />
    </p>

    <p>
      Most of the Scenario classes are simple Java Beans.  They
      provide null (no parameters) constructors and mutable
      properties.  The API is intended to be "minimal" in the sense
      that it exposes the capabilities of the underlying Java 2D and
      Swing classes but does attempt to substantially simplify or
      abstract them.  Scenario is intended to serve as the basis for
      higher level abstractions that require a scene graph, notably
      Java FX Script.  For that reason, you may find programming
      against the Scenario API directly to be a bit tedious.  Creating
      your own abstractions that simplify creating scene graphs is
      definitely the order of the day.
    </p>

    <p>
      To add a border to the simple Hello World scene, we'll write a
      method that takes any scene graph node and puts a garish rounded
      rectangle border behind it.  This example demonstrates using the
      <code>SGShape</code> leaf node which can render any Java 2D 
      <a
        href="http://java.sun.com/javase/6/docs/api/java/awt/Shape.html">
        Shape
      </a>, 
      like lines, arcs, bezier curves, and of course rounded
      rectangles.  Just to highlight the support for both
      <i>filling</i> and <i>stroking</i> (drawing the outline of)
      shapes, we'll do both here.  The <code>createBorder</code>
      method creates a red and yellow rounded rectangle that's a
      little bigger than the node it's given.  It returns an
      <code>SGGroup</code> scene graph node that contains both the
      original node and the "border".   
    </p>
      
    <pre>
SGNode createBorder(SGNode node) {
    Rectangle2D nodeR = node.getBounds();
    double borderWidth = 10;
    double x = nodeR.getX() - borderWidth;
    double y = nodeR.getY() - borderWidth;
    double w = nodeR.getWidth() + (2 * borderWidth);
    double h = nodeR.getHeight() + (2 * borderWidth);
    double a = 1.5 * borderWidth;
    SGShape border = new SGShape();
    border.setShape(new RoundRectangle2D.Double(x, y, w, h, a, a));
    border.setFillPaint(new Color(0x660000));
    border.setDrawPaint(new Color(0xFFFF33));
    border.setDrawStroke(new BasicStroke(borderWidth / 2.0));
    border.setMode(SGShape.Mode.STROKE_FILL);
    border.setAntialiasingHint(RenderingHints.VALUE_ANTIALIAS_ON);
    SGGroup borderedNode = new SGGroup();
    borderedNode.add(border);
    borderedNode.add(node);
    return borderedNode;
}
    </pre>

    <p>
      Adding a the border doesn't change the code that creates the
      scene graph very much:
    </p>

    <pre>
SGText text = new SGText();
text.setText("Hello World");
// same as before ...
panel.setScene(createBorder(text));
    </pre>

    <h2>Rotating Hello World: Transforms</h2>

    <p>
      <img alt="Intro Screenshot3" 
        src="http://weblogs.java.net/blog/hansmuller/archive/intro-screenshot3.PNG"
        width="290" 
        height="195" />
    </p>

    <p>
      As you can see in the previous example, the
      <code>SGNode#getBounds()</code> method returns a bounding box
      for the its node, in the way same way
      <code>Component#getBounds()</code> does for AWT and Swing
      components.  In AWT and Swing, a component's parent node
      recursively defines its origin in terms of a translation, which
      is the value of <code>getParent().getLocation()</code>.  Scene
      graphs are much more flexible than that.  The relationship
      between a child and its parent node can be defined with any 2D
      affine transformation.
    </p>

    <p>
      To rotate a scene graph node around a point, you have to
      assemble a chain of three transforms that: translate the node so
      that the rotation point is at the origin, rotate the desired
      amount, translate the node back to its original location.
      Transforms are created with <code>SGTransform</code> nodes,
      which are <code>SGFilter</code> subclasses because they have
      just one child, which is the node the transform is to be
      applied to.  Here's a method that creates such a chain and uses
      the node's bounds' center as the rotation point:
    </p>

    <pre>
SGTransform createRotation(SGNode node) {
    Rectangle2D nodeR = node.getBounds();
    double cx = nodeR.getCenterX();
    double cy = nodeR.getCenterY();
    SGTransform toOriginT = SGTransform.createTranslation(-cx, -cy, node);
    SGTransform.Rotate rotateT = SGTransform.createRotation(0.0, toOriginT);
    return SGTransform.createTranslation(cx, cy, rotateT);
}
    </pre>

    <p>
      To use the <code>createRotation</code> method we apply it to the
      node that's going to spin around its center, and then add the returned
      value to the scene instead of the node itself.   The return
      value is the chain of three transform nodes followed by the
      original node.  To specify a rotation you have to refer to the
      second <code>SGTransform.Rotate</code> from the chain and change
      its rotation property:
    </p>
    
    <pre>
SGTransform scene = createRotation(node);
SGTransform.Rotate rotateT = (SGTransform.Rotate)scene.getChild();
rotateT.setRotation(...);
    </pre>


    <h2>Images and More Layout</h2>

    <p>
      <img alt="Intro Screenshot4" 
        src="http://weblogs.java.net/blog/hansmuller/archive/intro-screenshot4.PNG"
        width="290" 
        height="195" />
    </p>


    <p>
      Images can be incorporated in a scene graph with the
      <code>SGImage</code> node type.  To add one to our scene so that
      it appears to the right of the "Hello World" text, we'll have to
      create an <code>SGGroup</code> node that contains the text and
      the image, and then use <code>SGTransform</code> nodes to
      arrange the group's children along a row.  Here's a method that
      creates such a group:
    </p>

    <pre>
SGNode createRow(SGNode... nodes) {
    double rowHeight = 0.0;
    for(SGNode node : nodes) {
        rowHeight = Math.max(rowHeight, node.getBounds().getHeight());
    }
    SGGroup row = new SGGroup();
    double x = 0.0;
    double gap = 8.0;
    for(SGNode node : nodes) {        
        Rectangle2D nodeR = node.getBounds();
        double y = (rowHeight - nodeR.getHeight()) / 2.0;
        double dx = x - nodeR.getX();
        double dy = y - nodeR.getY();
        SGTransform xlate = SGTransform.createTranslation(dx, dy, node);
        row.add(xlate);
        x += nodeR.getWidth() + gap;
    }
    return row;
}
    </pre>

    <p>
      The code to create the SGImage node and the overall scene looks
      like this:
    </p>

    <pre>
SGNode createEarth() {
    BufferedImage image = null; 
    // ... code to load the image file
    SGImage sgImage = new SGImage();
    sgImage.setImage(image);
    return sgImage;
}
// ...
SGNode row = createRow(createHelloWorldText(), createEarth());
SGNode scene = createBorder(row);
JSGPanel panel = new JSGPanel();
panel.setScene(scene);
    </pre>

    <h2>Handling Input</h2>

    <p>
      <img alt="Intro Screenshot5" 
        src="http://weblogs.java.net/blog/hansmuller/archive/intro-screenshot5.PNG"
        width="290" 
        height="195" />
    </p>

    <p>
      All nodes can handle mouse and keyboard events and the support for
      doing so is very similar to what AWT/Swing provides.  For
      example to make a node handle mouse events you add an
      <code>SGMouseListener</code>.  <code>SGMouseListener</code>
      combines the methods from AWT's <code>MouseListener</code> and
      <code>MouseMotionListener</code> and it adds an
      <code>SGNode</code> argument to each one.   <code>SGKeyListener</code>
      and <code>SGFocusListener</code> are similar.  The source of a scene
      graph mouse or keyboard event is always a JSGPanel and the
      additional node argument indicates the node the event was
      actually dispatched to.
    <p>

    <p>
      In this example, we've added a mouse listener to the
      earth node in the scene from the previous example and restored
      the support for rotating the scene.  Dragging the earth with the
      mouse rotates the scene.  Here's the code that sets up the scene
      and its <code>SGMouseListener</code>:
    </p>

    <pre>
SGNode earth = createEarth();
SGNode row = createRow(createHelloWorldText(), earth);
SGTransform scene = createRotation(createBorder(row));
final SGTransform.Rotate rotateT = (SGTransform.Rotate)scene.getChild();
SGMouseListener changeRotation = new SGMouseAdapter() {
    @Override public void mouseDragged(MouseEvent e, SGNode node) {
        Rectangle2D r = e.getComponent().getBounds();
        double x = e.getX() - r.getCenterX();
        double y = e.getY() - r.getCenterY();
        rotateT.setRotation(Math.atan2(y, x));
    }
};
earth.addMouseListener(changeRotation);
JSGPanel panel = new JSGPanel();
panel.setScene(scene);
    </pre>

    <p>
      Although there's a great deal more to say by way of introducing
      Scenario, this blog entry has grown long enough that I'd better
      just take the same tack 
      <a
        href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html"> 
        that Chet did
      </a>,
      and declare this "Part 1".  
    </p>

    <p>
      The code for the examples can be found here:
      <a href="http://weblogs.java.net/blog/hansmuller/archive/Intro.java">
        http://weblogs.java.net/blog/hansmuller/archive/Intro.java
      </a> 
      A easy to build version will appear along with the other
      Scenario demos, later this month. 
    </p>
]]>

</content>
</entry>
<entry>
<title>Application Framework Prototype Bows</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2007/01/application_fra.html" />
<modified>2007-01-30T16:36:47Z</modified>
<issued>2007-01-30T16:03:01Z</issued>
<id>tag:weblogs.java.net,2007:/blog/hansmuller/45.6437</id>
<created>2007-01-30T16:03:01Z</created>
<summary type="text/plain">A prototype implementation of the fledgling Swing Application
Framework (JSR-296) API is now available.</summary>
<author>
<name>hansmuller</name>


</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
  I've made a prototype of the fledgling JSR-296 API available,
  it's <a
    href="https://appframework.dev.java.net/">
    https://appframework.dev.java.net/</a>.  
  There's a quick overview doc and downloads of the source code,
  the javadoc, and the AppFramework.jar file.  If you're
  interested in this API, please take a look at the overview, and
  download the code and then take a look at some of the examples
  and the javadoc.  You can post feedback here or, if you want to
  participate in the long-term discussion, subscribe to the 
  appframework.dev.java.net "users" mailing list:
  <a href="https://appframework.dev.java.net/servlets/ProjectMailingListList">
    https://appframework.dev.java.net/servlets/ProjectMailingListList
  </a>.  
  The users alias is the last one listed.
</p>

<p>
  That's all I really wanted to say.  I don't want to make too
  much of a commotion about this version of the design because
  there's still quite a bit that remains to be done.  I was hoping
  that this would be a sort-of <i>stealth</i> release: not
  terribly noticeable, unless you know where to look.  On the
  other hand, I know there are Swing developers who aren't members
  of the JSR-296 expert group, who'd like to take stock of where
  this project is going.  And I know there are experienced Swing
  developers out there, some of whom have built their own
  application frameworks, that would like see how this one
  measures up.  I'd welcome feedback from anyone who's interested
  and I'll promise to respond promptly, unless you bring up a
  really difficult issue or a really large number of them.  That
  might take longer.
</p>

<p>
  Note also: the JCP defines a milestone called "Early Draft
  Review" that means the expert group thinks the spec is complete
  enough to begin fine tuning.  We have not reached that milestone
  yet.
</p>

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1271158-1";
urchinTracker();
</script>]]>

</content>
</entry>
<entry>
<title>Property Syntax for Java? A Constructive Alternative</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2007/01/property_syntax.html" />
<modified>2007-01-10T14:16:30Z</modified>
<issued>2007-01-10T13:57:04Z</issued>
<id>tag:weblogs.java.net,2007:/blog/hansmuller/45.6294</id>
<created>2007-01-10T13:57:04Z</created>
<summary type="text/plain">I don&apos;t think the current proposal for a Java language property
keyword serves Java Bean developers very well, since it doesn&apos;t
support defining bound properties.  I think the use-case that
motivated the proposal would be better served by a new class level
keyword, one whose origins are buried deep in Java&apos;s DNA.
</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[    <p>
      Having written, by conservative estimates, about a jillion Java
      Beans classes over the years, I have to say that I'm amazed that
      we'd seriously consider changing the Java language to trivialize

      this kind of Java Bean property.  It certainly is a property per
      the spec, a read/write property at that, but - as a Swing
      developer - it's the kind of property I almost never write.  And
      if repetitive boilerplate is what we're hunting with this
      language change, then we're shooting at rabbits while a herd of
      buffalo thunders by.  The mighty buffalo of the Java Beans
      boilerplate animal kingdom are bound properties.  They're the
      kind of properties we write so that our beans can be
      automatically and dynamically synchronized with a GUI or with
      each other.  As a desktop developer, I almost always write bound
      properties.
    </p>

    <p>
      To write a bound property properly you've got to ensure that
      your class defines or inherits support for a
      PropertyChangeListener.  That's about 20 lines of code just to
      get started: 
    <pre>
class FooBean {
    private final java.beans.PropertyChangeSupport pcs;
    public FooBean () {
	pcs = new PropertyChangeSupport(this);
    }
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(listener);
    }
    public PropertyChangeListener[] getPropertyChangeListeners() {
        return pcs.getPropertyChangeListeners();
    }
    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        pcs.firePropertyChange(propertyName, oldValue, newValue);
    }
}
    </pre>
    </p>

    <p>
      And then there's the definition of each read/write property
      which should: check the validity of new values in its
      <tt>set</tt> method as well as calling firePropertyChange to notify
      PropertyChangeListeners, and defensively copy the return value
      (if necessary) in its <tt>get</tt> method.  I suppose one could
      concoct syntax that would simplify all of this, at least a
      little, as well as allowing for read-only/write-only variants.
      But that's not the proposal I wanted to make here.
    </p>

    <p>
      If you consider the property keyword proposal in light of Java's
      origins in the C language, then it's pretty clear what the
      proposal's proponents are really after: structs.  It's not
      about defining properties, it's about simplifying defining a
      Java class that's comparable to a struct in the C language.  So
      perhaps the proposal should really focus on allowing one to 
      write classes, not properties.  Where this:
    <pre>
struct FooBean { Foo foo; }
    </pre>
    Would by equivalant to this (as before):
    <pre>
class FooBean {
    private Foo foo; 
    public Foo getFoo() { return foo; }
    public void setFoo(Foo foo) { this.foo = foo; }
}
    </pre>
    </p>

    <p>
      If you admit that the focus of the property proposal is really
      adding support for defining structs in Java, then using "->" to
      refer to struct properties feels like coming home again.
    </p>

    <pre>
struct Point { int x, y; }
Point p = new Point(); 
p->x = p->y = 0; // oh joy
    </pre>

    <p>
      I'm not a language design expert however I would think that I
      would be among the target developers for Java language feature
      designed to support properties.  In my humble (ha) opinion, the
      current proposal serves the needs of Java Beans developers
      poorly by targeting a special case that doesn't warrant language
      support.  Although I would welcome a proposal that also simplified
      defining bound properties, I would guess that it would be hard
      to invent syntax that would handle the general case without
      being obscure.  If there is a consituency for the current
      proposal, I say: give them structs instead.
    </p>
]]>

</content>
</entry>
<entry>
<title>Javapolis Session Interrupted by Marriage Proposal</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/12/javapolis_sessi.html" />
<modified>2006-12-24T20:58:24Z</modified>
<issued>2006-12-18T00:34:10Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.6187</id>
<created>2006-12-18T00:34:10Z</created>
<summary type="text/plain">This year I gave a session at Javapolis about the Swing
Application Framework. Before it was all over, there was a surprise
announcement.
</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Javapolis Session Interrupted by Marriage Proposal</title>
  </head>

  <body>
    <h1>Javapolis 2006</h1>

    <p>
      <a href="http://javapolis.com/confluence/download/attachments/27963/HansMuller.jpg">
	I 
      </a>
      spent most of last week at the Javapolis conference in Antwerp
      Belgium.  With nearly 3000 attendees, it's the second biggest
      Java conference after JavaOne, and it's held in a movie cineplex
      complex called "Metropolis".  The venue delivers large halls,
      comfortable seats (with beverage caddies!), and dramatic
      lighting.  Half of each enormous movie screen is devoted to a
      live image of the presenter and the camerawork is quite good,
      pausing for a dramatic closeup now and then.  My laptop wasn't
      working correctly so I had to turn around periodically, to
      visually sync up with my slides.  That meant that the audience
      was treated to six linear feet of my balding hemisphere glowing
      in the klieg lights.  I was thankful that everyone put up with
      that, and also with my raspy voice.  I'd managed to pick up a
      cold the day before leaving, and only hours before I was
      scheduled to speak, I could do little more than croak and
      wheeze.  Things were somewhat better by the showtime, however
      from the sound of my voice you might think I'd spent the day
      smoking heavily and shrieking.

    <p> 
      My presentation topic was JSR-296 "Swing Application Framework".
      If you're interested, there's a copy 
      <a href="http://weblogs.java.net/blog/hansmuller/archive/jsr296-presentation.pdf">here</a>.
      Within a few months you'll find a nicely edited slides-and-video
      version of the presentation on <a
      href="http://www.parleys.com">parleys.com</a>, thanks to 
      Stephan Janssen, the tireless Javapolis organizer.  And when it
      appears, do not miss the finale.  As Richard Bair and I finished
      up a demo of a prototype of the Application Framework 
      in NetBeans, Stephan appeared and asked to
      interrupt the proceedings for a special announcment.  He picked
      up the microphone and asked a woman who's name I didn't catch to
      come forward.  Sure enough, a tall young blonde woman came to
      the front, looking nonplussed.  After a brief pause, a young man
      wearing a suit came loping down the aisle and in a moment he was
      facing the woman and making a declaration of some kind in Dutch.
      She looked pretty nervous and, not knowing where this was all
      going, we started feeling a bit anxious too.  Until he dropped
      to one knee and assumed the international marriage proposal
      position.  Then we really started to worry, because
      here was a situation that could only end really well, or really
      badly.  The woman was crying (uh oh) and smiling (whew!), and
      then nodding her head, and to everyone's relief, we had a happy
      betrothal.  The couple bounded up the steps to a nice round of
      applause, and Richard and I tried to remember what it was we'd
      been talking about.
    </p>

    <p>
      The Javapolis conference was memorable as always.  One evening
      the organizers arranged for enough french fries and mayonaise to
      serve 3000 (that's a lot), they showed the new James Bond movie,
      Mark Fleury performed his keynote dressed up like Flavor Flav,
      Sun raffled away a Nintendo Wii, the technical sessions were
      solid, and, mine was interrupted by a proposal of marriage.
      With a happy ending.
    </p>

    <p>
      <b>Merry Christmas!</b>
    </p>

    <p>
      Update: Stephan Janssen has published the video, you'll find it here:<br>
      <a href="http://www.javapolis.com/confluence/display/JP06/2006/12/22/JavaPolis+2006+Marriage+Proposal">
        http://www.javapolis.com/confluence/display/JP06/2006/12/22/JavaPolis+2006+Marriage+Proposal
      </a>
    </p>

  </body>
</html>
]]>

</content>
</entry>
<entry>
<title>Dialog Diatribe</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/10/dialog_diatribe.html" />
<modified>2006-10-28T02:00:17Z</modified>
<issued>2006-10-28T01:48:10Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.5814</id>
<created>2006-10-28T01:48:10Z</created>
<summary type="text/plain">A menu item whose action creates and shows a new dialog which is
centered over (and owned by) the menu item&apos;s frame, should be a
no-brainer.  I found the some quirks in the process, they made me
cranky, and so I wrote about it.</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
  I've been writing the occasional small application recently and
  now and then I blunder into a problem with Java SE that's,
  uh..., well, annoying.  I realize that I'm not the only one
  who's had this experience and I'm probably not the only one who
  seeks relief by writing a lengthy diatribe and then sending it
  to whomever might be guilty of creating the situation.  Of
  course, in my case that's often me, and since relief usually
  doesn't come from berating oneself, I'm guilty of sending the
  occasional long crabby missive to the people who are currently
  responsible for maintaining things that I'm probably responsible
  for bollocksing up in the first place.  It's not a particularly
  endearing habit.
</p>

<p>
  I sent the following to Swing's technical lead, 
  <a href="http://weblogs.java.net/blog/shan_man/">Shannon
    Hickey</a>, and he confirmed that the details, though twisted
  with bile, are essentially correct.  So in the interest of
  furthering my own therapy, and also to ensure that some record of
  this will be stored away in Google's indices till the end
  of time, I thought I'd share.
</p>

<p>
  I would think that a fairly common idiom in a Swing application
  would be to popup a dialog in response to selecting a menu item.
  Given <a href="http://form.netbeans.org/">Matisse</a>, we'll
  assume that the JDialog has been created with the IDE, rather
  than some JOptionPane convenience method, and given rudimentary
  aesthetics, assume the dialog should be centered over the menu
  item's frame.  Accomplishing this seems to be much too
  difficult:
</p>

<pre>
public void showMyDialog(ActionEvent e) {
    // How to find the Dialog's Frame owner?
    Window dialogOwner = null;
    JDialog dialog = new MyDialog(dialogOwner, true); // true => modal Dialog
    dialog.pack();
    // How to center the Dialog?
    dailog.setVisible(true);
}
</pre>

<p>
  The first problem to deal with is mapping from the menu item's
  ActionEvent to the frame that contains the menu item.  The
  frame will be the dialog's owner as well as the component we're
  going to center the dialog relative to.  
</p>

<p>
  There seems to be an overabundance of SwingUtilities methods that
  address this trivial problem:
<ul>
  <li><code>Window getWindowAncestor(Component c)</code></li>
  <li><code>Window windowForComponent(Component c)</code></li>
  <li><code>Component getRoot(Component c)</code></li>
</ul>
  Sadly, none of them "work" for a JMenuItem.  They all simply
  traipse up the parent chain and in our case they find a
  JPopupMenu and then null.
</p>

<p>
  To find the Frame that owns a JMenuItem, we have to follow the JPopupMenu's 
  <a href="http://download.java.net/jdk6/docs/api/javax/swing/JPopupMenu.html#getInvoker()">
    "invoker"</a> property, which gets us back into the component
  hierarchy.  So to find the frame that corresponds to an ActionEvent
  one must write (!):
</p>

<pre>
Frame frameForActionEvent(ActionEvent e) {
    if (e.getSource() instanceof Component) {
        Component c = (Component)e.getSource();
        while(c != null) {
            if (c instanceof Frame) {
	        return (Frame)c;
            }
            c = (c instanceof JPopupMenu) ? ((JPopupMenu)c).getInvoker() : c.getParent();
        }
    }
    return null;
}
</pre>

<p>
  It would more useful to have written
  <code><i>window</i>ForActionEvent</code> but sadly support for
  creating Dialogs whose owner is a Window (the parent class for
  Frames and Dialogs) only appeared in Java SE 6, and I needed
  code that worked for Java SE 5.  It's also worth noting that
  this works for Applets too, although you'd be forgiven for not
  guessing that this is true.  Applets do have a Frame parent
  that's created by the Java plugin and whose bounds are the same
  as the Applet (Panel) itself.
</p>

<p>
  But we're still not done, because we must also center the dialog
  over the frame.  Naturally there are other useful positions for
  the dialog.  Centering a dialog over its frame happens to be what
  started me on this quest.
</p>

<p>
  I have it on good authority that
  <a
    href="http://download.java.net/jdk6/docs/api/java/awt/Window.html#setLocationRelativeTo(java.awt.Component)">
    Windows.setLocationRelativeTo()</a> is the handy method for
    this job.  The javadoc for this method isn't promising:
</p>

<blockquote>
  <code>
    Sets the location of the window relative to the specified
    component.
  </code>
</blockquote>

<p>
  OK so far.  Except it sounds like I'm going to have to compute the
  relative origin of my dialog and deal with edge (of the screen)
  conditions.  Yech.
</p>

<blockquote>
  <code>
    If the component is not currently showing, or c is null, the
    window is placed at the center of the screen. The center point
    can be determined with GraphicsEnvironment.getCenterPoint
    [sic]
  </code>
</blockquote>

<p>
  Huh?  What does "the component" refer to in this sentence?  I
  assume they're not referring to <i>this Window</i> and I have to
  wonder what "showing" means in this context.  Is is the same
  thing as <code>getVisible()</code> being true?  If not, do I
  have to hope that my menu item is still "showing" when this
  method is called?  And what's this advice about
  <code>getCenterPoint</code> (and where's the period)?  In my
  case the Window and its menu item are visible, so I'm hoping
  none of this stuff applies.  Because I don't really understand
  it.
</p>

<blockquote>
  <code>
    If the bottom of the component is offscreen, the window is
    placed to the side of the Component that is closest to the
    center of the screen. So if the Component is on the right part
    of the screen, the Window is placed to its left, and visa
    versa.
  </code>
</blockquote>

<p>
  This, no doubt, means that the method will endeavor to find a
  location for my dialog that respects the relative location I've
  specified, without making part of the dialog appear off-screen.
  Good, I think.
</p>

<p>
  So I still appear to be stuck with computing an origin for my
  dialog that centers it relative to its owner.  Before I code
  that, I try leaving the origin of the new dialog at 0,0, which 
  is the default:
</p>

<pre>
public void showMyDialog(ActionEvent e) {
    Window dialogOwner = frameForActionEvent(e);
    JDialog dialog = new MyDialog(dialogOwner, true);
    dialog.pack();
    aboutBox.setLocationRelativeTo(dialogOwner);
    dialog.setVisible(true);
}
</pre>

<p>
  Miraculously, this works.  The dialog appears centered over the
  dialogOwner unless that would cause the dialog to appear
  off-screen. I have no idea why it works, since according to the
  "spec" (and the name of the method) I should have had to compute
  an appropriate relative origin for the dialog.  But I guess I
  don't.
</p>

<p>
  Frankly, I think this whole mess is a mini-travesty.  If I'm
  going to show a dialog, I should be able to do so without
  writing code that digs around the component hierarchy and
  without experimentally determining what something as simple (and
  not terribly useful) as Window.setLocationRelativeTo() does.
</p>

<p>
  There, that feels a little better.
</p>

<p>
  A <a
  href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4231737">
  seven year old bug</a> that covers the menu item to frame lookup
  problem is still open.  Given the fact that it's accumulated
  exactly 0 votes in that time, perhaps no one has ever cared about
  the problem quite as much as I do at this moment.  I would think
  that a cleaner way to handle this case would be some static
  methods that handled the entire idiom, for example:
</p>

<pre>
public void showMyDialog(AWTEvent event) {
    Window dialogOwner = Window.eventToWindow(event);
    JDialog dialog = new MyDialog(dialogOwner, true);
    Window.showModalDialog(dialog); // Center dialog relative to its owner
}
</pre>

<p>
  And Shannon suggested that the method name might be rationalized
  as implying that the Window is be moved to a location that makes
  its <i>relationship</i> to the component parameter obvious.
  Typically that means centering the Window <i>relative to</i> the
  component.  In return for that tortured explanation, I had to
  agree to file an RFE about the
  <code>Window.setLocationRelativeTo()</code> javadoc.  I haven't
  done so yet.  But I will.
</p>

 <p>
   Thanks for listening.
 </p>]]>

</content>
</entry>
<entry>
<title>JSR 296 Bows - Swing Application Framework</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/06/jsr_296_bows_sw.html" />
<modified>2006-06-02T18:27:41Z</modified>
<issued>2006-06-02T18:18:05Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.4952</id>
<created>2006-06-02T18:18:05Z</created>
<summary type="text/plain">On Tuesday May 15th the JCP Executive Committee approved JSR 296,
&quot;Swing Application Framework&quot;.  I&apos;m the spec lead for JSR 296 and this
is the JCP equivalent of a birth announcement.  A rather long and
meandering birth announcement, with a web started demo at the end.</summary>
<author>
<name>hansmuller</name>


</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[    <p>
      For the past five months or so, I've been working on a fledgling
      project to define an application framework for Swing.  
    </p>

    <p>
      Some people are highly organized.  They set long and short term
      goals according to a stable set of priorities and then focus on
      nothing else but progress.  These people, with their powerful
      work ethic and bulging resumes, are often successful.  They get
      up every morning, attack the day's tasks, take stock of their
      progress, and then dream of how to get the job done just a
      little more efficiently in the morning.  And after exactly 6
      hours sleep, they do it all over again.  These people get things
      done.  
    </p>

    <p>
      I am not these people.  I admire their drive and their
      accomplishments, and sometimes I wave as their phalanx trots by.
      I could try and justify my own meandering progress by pointing
      out all the things that these people miss as they forge forward,
      shields on forearms, eyes straight ahead.  But I will not,
      because the truth is that I'm just not highly organized.  Not
      meant to be at the head of the V formation, with a list of the
      five things that must be done before sundown taped to the inside
      of my protective helmet.  I'll be successful, but in doing so,
      I'll surprise everyone a little.  Even me.
    </p>

    <p>
      Earlier this year I spent some time studying the NetBeans and
      Eclipse IDE subsets that are referred to as "Rich Client
      Platforms".  I was impressed by the scope of both frameworks and
      the evolving support for them in the corresponding tools.  On
      the other hand, I was concerned by their complexity, and by the
      steep learning curve that new desktop application developers
      would face.  Making a substantial investment in learning a rich
      client platform seems warranted when the application you're
      building roughly approximates the size and shape of a general
      purpose IDE.  Similarly, if you're trying to marshall a very
      large loosely coupled engineering team, like the teams that have
      built NetBeans and Eclipse, then you'll find that the structure
      of these platforms help to organize the work.  I don't think
      those situations are typical.
    </p>

    <p>
      We've made a scientific survey of Swing developers and
      discovered that of the 2.5 jillion applications that have been
      written in the past 8 or 9 years, most of them are smaller than
      your average IDE.  Most of them employ smaller teams and most of
      them are built by developers with less time and less experience
      then the authors of our big IDEs.  I think we need to make it
      easier for the average developer to start the average
      application, and to finish it.  To me that implies that a small
      desktop application framework is needed.  Not a framework for
      small applications, but a framework that's small enough for a
      developer to understand after an hour's study.  
    </p>


    <p>
      That said, I don't think
      there's any value in trying to encapsulate or hide the
      underlying Java platform.  That vast API landscape is vital to
      modern applications.  Networking, threading, IO, GUI, graphics,
      XML, and all the rest are in there because they're essential to
      most applications.  Perching an enormous application framework
      on top would only make the overall platform more intimidating.
      We surely don't want that.
    </p>

    <p>
      Having decided that a narrowly focused application framework was
      a good idea, I immediately plotted a course for a prototype, and
      then, clipboard in hand, carpenter's pencil tucked behind my ear,
      I spent about two weeks building a <a 
	href="http://weblogs.java.net/blog/hansmuller/archive/2006/03/multisplitpane.html">
	multi-way split pane</a>.  
      It's not particularly easy to explain why this was the right
      next step to take.  So I will not try.  You can read the article
      and try the web started demos on java.net: <a
      href="http://today.java.net/pub/a/today/2006/03/23/multi-split-pane.html">
      MultiSplitPane: Multi-Way Splitting Without Nesting</a>.  Of
      course, if you do, you're demonstrating the same disorganized
      tendencies that led me to write it in the first place.
    </p>

    <p>
      Thankfully, since then, two processes have kept me (mostly) on
      track.  At JavaOne Scott Violet and I gave a technical session
      about the application framework prototype, and I've filed a JSR
      to cover the development of the API.  The JavaOne session was <a
      href="http://weblogs.java.net/blog/hansmuller/archive/ts-3399-final.pdf">
      A Simple Framework for Desktop Applications</a> (TS-3399).
      Click on the link to download a PDF of the slides.  I've also
      filed <a href="http://jcp.org/en/jsr/detail?id=296">JSR 296</a>,
      and on Tuesday May 15th, it was approved by the JCP executive
      committee.  If you're interested in joining the JSR 296 expert
      group (EG), you can do so from the "I would like to join this
      Expert Group" link on the JSR 296 page.  I'm setting up the EG
      now and hope to begin work in a few weeks.  If all goes well,
      we'll produce reference implementations of the framework for
      Tiger and Mustang Java SE releases, and the framework will be
      incorporated in the next major SE release, code named Dolphin.
    </p>

    <p>
      This blog is my way of publicly introducing the Swing
      Application project and JSR 296.  As the expert group gets
      underway I hope to have a java.net project up an running that
      will contain snapshots of the evolving spec and implementation.
      I'd also like to host a set of smallish applications, built with
      the framework ofcourse, alongside the project.  There's no
      better way to keep a framework project focused on real problems
      than by using it.  So we'll do so, and as things stabilize,
      hopefully other developers will give the framework a test drive.
    </p>

    <p>
      So I wrote all of the above on Monday (four days ago) and then I
      thought: it would be nice to conclude this announcement with a
      little demo app. Something amusing to reward the reader for
      slogging their way through all of this.  So, I decided to create
      a little slide show, using Chet Haase's
      <a href="https://timingframework.dev.java.net/">
	timing framwork
      </a>, 
      that displayed a few pictures in sync with some music.  I
      used the <a href="http://www.javazoom.net/javalayer/javalayer.html">
	JLayer (pure Java!) MP3 player
      </a> library to play the Sunrise movement from Also Sprach
      Zarathustra (that's the opening theme from 2001: A Space Odyssey).
      Jeff Dinkins applied some magic to shorten the
      music to about 51 seconds, because we knew that none of you
      would have enough patience to listen to the complete minute and
      a half, when accompanied by my feeble photo montage.  Finishing
      this project was supposed to have consumed an afternoon.  Sadly,
      life imitates blog, and here it is Friday.  On the upside, I
      managed to uncover a bad interaction (bug) between Mustang and
      the new NetBeans Java Web Start plugin.  On the downside, after
      spending more hours than I'd care to admit trying to find the
      perfect sequence of photos on Flickr and Yahoo and Google, I've
      created the following bit of pretentious codswallop.
    </p>

    <p>
      You'll need to make sure to turn up the VOLUME ON YOUR PC to
      hear the soundtrack.  Dawn starts out dark, and it's not very
      interesting without the catchy music.
    <p>

    <p>
    <table  align="center">
	<tr>
	  <td>
	    <img
	      <img alt="darwin.jpg" src="http://weblogs.java.net/blog/hansmuller/archive/darwin.jpg" width="300" height="400" />
	    <br />
	  </td>
	</tr>
	<tr>
	  <td>
	    <a href="http://www.java.net/download/javadesktop/blogs/hansmuller/jsr296-bows/zarathustra.jnlp">
	      <img alt="Launch Button" 
		src="http://weblogs.java.net/blog/hansmuller/archive/jws-launch-button.png" 
		width="88" 
		height="23"
		style="border-style:none"/>
	    </a>
	  </td>
	</tr>
    </table> 
    </p>

    <p>
      So, in closing, I'd like to thank the JCP executive committee
      for approving JSR 296.  I'm working on getting the expert group
      sorted out right now.  We have many more volunteers than we
      can handle and I appreciate the show of interest and support.
      Updates about JSR 296 progress will appear on javadesktop.org
      and often right here.  So long as I stay focused.
    </p>
]]>

</content>
</entry>
<entry>
<title>Fire Marshall Extinguishes Dukelele Performance</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/05/fire_marshall_e.html" />
<modified>2006-05-20T02:53:20Z</modified>
<issued>2006-05-20T02:52:57Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.4858</id>
<created>2006-05-20T02:52:57Z</created>
<summary type="text/plain">A raucous JavaOne Dukelele performance, led by Looking Glass creator Hideya Kawahara, was cut tragically short by law enforcement.  Fortunately, you can see the entire event on YouTube.com!</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
Tuesday morning this week, I was seated in the vast Moscone
keynote cavern, with 15,000 other Java developers, taking in the
start of another JavaOne conference.  The keynotes and demos
were entertaining and I hope you didn't miss the HUGE Swing <a
href="https://aerith.dev.java.net/">Aerith demo</a> at the
conclusion of the morning.  Sadly I did, although I've seen
quite a lot of it over last few weeks.  I had to dart out early,
because my first-ever JavaOne musical gig started at about 10:30
and I had to get my bass and set up in time for the big Dukelele
show.
</p>

<p>
That's right, Dukelele.  A Ukelele painted like so:
</p>

<p align="center">
<img alt="dukelele.jpg"
      src="http://weblogs.java.net/blog/hansmuller/archive/dukelele.jpg" width="400" height="533" />
</p>

<p>
A group of us played music in front of the JavaOne store at one end of
the corridor that connects the Moscone's North and South subterranean
chambers.  In addition to me, the band was Hideya Kawahara and Yuichi
Sakuraba playing Ukeleles (Dukeleles!) and singing, Mark Anenberg on a
guitar-shaped drum synthesizer, Chet Haase on a laptop powered
keyboard, and Kaoru Nakamura playing a keyboard/harmonica hybrid
called a Pianaca.  And to top if off, Duke danced and hugged people.
</p>

<p>
We started playing as the keynote audience began flooding past and to
our delight, many of them stopped to listen.  Tragically, the Moscone
Fire Marshall did not share our joy.  After about 10 minutes he
swooped in and put a stop to the show.  I guess we were a fire hazard,
or at least Hideya was.  He was really putting his heart into singing
and playing and I suspect that the Fire Marshall was afraid that he
might suddenly burst into flames.
</p>

<p>
Another rock and roll show, shut down by the man.  Not exactly
Altamont Speedway, but definitely a strange and abrupt ending to
our little performance.  Fortunately one of our colleagues
videotaped the whole thing and so now you can check it out on
<a
href="http://www.youtube.com/watch?v=wf5_TN602lc">YouTube.com</a>.  
No animals were harmed in the making of this video.  
</p>

<p>
We played again, in the afternoon, outside on the sidewalk.  It was a
bit breezy and most of the people who drifted by gave us an odd look
and then slipped indoors.  One was exception was <a
href="http://weblogs.java.net/blog/timboudreau/">Tim Boudreau</a>, who
took in the entire set and then threw a quarter in our tip jar.
Except we didn't have a tip jar.  Our friend the Fire Marshall seemed
to be pleased that we finished without spontaneously combusting.
Cautious man that he is, he kept a sharp eye on the proceedings from a
safe distance, clutching his fire extinguisher in one hand, and a
fistful of swag from the Motorola booth in the other.  Next year
we'll bring our own fire protection.
</p>]]>

</content>
</entry>
<entry>
<title>MultiSplitPane: Splitting Without Nesting [Shameless Plug]</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/03/multisplitpane.html" />
<modified>2006-03-23T16:29:01Z</modified>
<issued>2006-03-23T16:23:11Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.4373</id>
<created>2006-03-23T16:23:11Z</created>
<summary type="text/plain">An article I&apos;d written earlier this year about a multiway split
pane, is now available on java.net.  Read the back story in this
gripping new blog.</summary>
<author>
<name>hansmuller</name>


</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p> 
One aspect of many docking GUIs is support for reconfiguring tiled
subwindows by dragging shared subwindow edges.  MultiSplitPane and
MultiSplitLayout support arbitraily complex tiled layouts that can be
reconfigured interactively and programatically.
</p>

<p>
As introductory paragraphs go, the previous one has to set a new
record for "not catchy".  It always seems easier to start these things
with a personal story or recollection.  So how about this:
</p>

<p>
Earlier this year I was arguing with 
<a href="http://weblogs.java.net/blog/timboudreau/">
Tim Boudreau</a> about docking
frameworks and how best to compute an initial layout, when it occurred
to me that a tree structured model would be a nice way to encode the
relative sizes and positions of the tiles.  If nodes in the tree
corresponded to tiles arranged in rows and columns, and if tiles were
allocated space proportionally, it seemed like only a small project to
build a two dimensional analag of JSplitPane.  Tim suggested that my
project estimating skills were suspect and besides, there were more
important things to do.  He was right on both counts, and yet.
Sometimes, when you're orbiting around an idea, headed somewhere else,
you find yourself captured by the idea's gravitational field.  As it
turns out, I was in the software-idea equivalent of a tractor beam.
</p>

<p>
Over the next two days, I implemented the idea.  Since subwindow tiles
were always allocated a fixed percentage of the available space, it
was easy to write a recursive layout algorithm that arranged the rows
and columns.  As I was just finishing up, 
<a href="http://weblogs.java.net/blog/joshy/">
Josh Marinacci</a> dropped by,
and so I proudly demo'd my creation.  The nice way to respond to
someone's new demo, on Friday afternoon, is to smile, deliver a bland
compliment, and suggest that it's time for a cold one.  Josh said:
"that's nice, but I don't think anyone would really want to use it".
After I stopped crying, he pointed out that people expect subwindow
tile boundaries to stay put when the window is resized.  This is true,
and it makes the problem substantially more difficult.  It means
that growing and shrinking the layout aren't symmetrical, and it 
implies that the layout should honor preferred tile sizes, until
the user has indicated otherwise by dragging an edge.  So, with tears
in my eyes, I started over again.
</p>

<p>
Version two of the layout algorithm took considerably longer than the
original version.  The result is the aforementioned MultiSplitPane and
MultiSplitLayout classes, a small set of demos, a smattering of unit
tests, javadoc, a nod to accessibility (more on that later), and an
article that explains how it all works.  The article bows today on
java.net, it's called 
<a href="http://today.java.net/pub/a/today/2006/03/23/multi-split-pane.html">
MultiSplitPane: Multi-Way Splitting Without
Nesting</a>.  I hope you'll find the time to read it.  The classes will
become part of the SwingLabs project now and perhaps be incorporated
into a future Java release.
</p>




]]>

</content>
</entry>
<entry>
<title>A Reusable BuddyList Component</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/02/a_reusable_budd.html" />
<modified>2006-02-27T23:30:53Z</modified>
<issued>2006-02-27T23:30:43Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.4192</id>
<created>2006-02-27T23:30:43Z</created>
<summary type="text/plain">How to build a generic buddy list cell renderer.  File under Advanced
JList Hacking.
</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p> 
Every now and then someone drops by to ask about the slick chat/IM
demo components that were shown in the <a
href="http://developers.sun.com/learning/javaoneonline/2005/desktop/TS-3605.pdf">
Extreme GUI Makeover </a> JavaOne session last year.  The Swing
components created for those demos where hacked together in order to
show what's possible and sadly, they're not available as production
quality components just yet.  I certainly like the idea of
resuable, configurable/extensible, chat client GUI parts.  If I
were building that kind of application I'd be happy to avoid starting
from scratch.  This blog is a brief look at one such part.  You can
try it out by pressing the launch button.
</p>

<p>
<table  align="center">
    <tr>
      <td>
	<a href="http://www.java.net/download/javadesktop/blogs/hansmuller/buddylist/buddylist.jnlp">
	  <img alt="BuddyList demo screenshot" 
	    src="http://weblogs.java.net/blog/hansmuller/archive/jws-launch-button.png" 
	    width="88" 
	    height="23"
	    style="border-style:none; margin-right:44px"/>
	</a>
      </td>
      <td>
	<img src="http://www.java.net/download/javadesktop/blogs/hansmuller/buddylist/screenshot.png"
	  style="border: none; "/>
	<br />
	<font size="-1"><i>BuddyList Demo Screenshot</i></font>
      </td>
    </tr>
</table> 
</p>

<p>
BuddyCellRenderer is an attempt to build a somewhat reusable
JList CellRenderer for Chat/IM buddy lists.  It's job is to 
render an object that represents a Buddy roughly like this:
</p>

<pre>
		  screen name
	[status]  short message   [icon]

</pre>

<p>
Here "status" is one of online, offline, or away.  Away status means
that the user is online but busy.  The "screen name" is the Buddy's
name, "short message" is an optional short message from the Buddy, and
icon is a picture that represents the Buddy.  All of this is quite
conventional.  These elements appear in most chat/IM application
buddy-lists in one form or another.  If a "short message"
isn't provided we change the layout just slightly:
</p>

<pre>
	[status] screen name [icon]
</pre>

<p>
The BuddyListCellRenderer must also provide a Buddy-specific tooltip
that's displayed if the user lingers over one BuddyList element.  
</p>

<p>
JList renders list elements or "cells" by delegating to an
implementation of ListCellRenderer.  ListCellRenderers have only one
method, getListCellRendererComponent(), which returns a Component that
the JList uses to paint a single list element.  The JList really just
uses the cell renderer component's paint() method to draw or "rubber
stamp" a list element.  The getListCellRendererComponent() method is
passed the JList model's "value" for each list element, and its
responsibility is to return a component that's been configured to
display that value.  
</p>

<p>
The default ListCellRenderer is quite simple.  It just uses the same
JLabel for every list element, roughly like this:
</p>

<pre>
JLabel label = new JLabel();
Component getListCellRendererComponent(JList l, Object value, ...) {
    jLabel.setText(value.toString());
    return jLabel;
}
</pre>


<p>
To display the properties of a Buddy in the way we've layed out above
will require more than just a JLabel.  BuddyCellRenderer uses a JPanel
with subcomponents for the various properties and GridBagLayout to
define the layout.
</p>

<p>
A generic ListCellRenderer that configures our JPanel composite to
display a Buddy value is difficult because we don't want to 
dictate the type of the Buddy object but we do need to 
extract its status, screen name, icon, and message.  What's needed
is an adapter that extracts the properties needed by the 
BuddyCellRenderer from the app-specific Buddy object.  The
BuddyListCellRenderer.Adapter class does this.  The way it works
is easiest to explain with an example.  Lets assume that our chat/IM
application has a Buddy class that looks like this:
</p>

<pre>
class MyBuddy {
    boolean isOnline() { ... }
    boolean isAway() { ... }
    String getScreenName() { ... }
    ImageIcon getIcon() { ... }
}
</pre>

<p>
A JList ListModel that encapsulated the list of MyBuddy objects would
have to be created; I will not delve into that here.  The adapter for
MyBuddy objects could be defined and used like this:
</p>
	
<pre>
class MyBuddyAdapter extends BuddyCellRenderer.Adapter {
    private MyBuddy getBuddy() { return (MyBuddy)getValue(); }
    public String getName() { return getBuddy().getScreenName(); }
    public String getMessage() { return getBuddy().getMessage(); }
    public ImageIcon getBuddyIcon() { return getBuddy().getIcon(); }
    public Status getStatus() { 
        if (getBuddy().isAway()) {
            return Status.AWAY;
        }
        else if (getBuddy().isOnline()) {
            return Status.ONLINE;
        }
        else {
            return Status.OFFLINE;
        }
    }
}

BuddyCellRenderer cellRenderer = new BuddyCellRenderer();
cellRenderer.setAdapter(new MyBuddyAdapter());
myBuddyJList.setCellRenderer(cellRenderer);
</pre>

<p>
That's pretty much all there is to it.  The BuddyCellRenderer
scales (and caches) the Icons provided by the Adapter if they're
bigger than <code>BuddyCellRenderer.getBuddyIconSize()</code>.
It also caches the "grayed out" version of the icon that's used
when a Buddy's status is offline.  Alternating rows are
rendered in an off-white color to help with readability and
the whole thing is layed out internally with the old Swing 
layout veteran: GridBagLayout.
</p>

<p>
If you'd like to try making some changes to BuddyCellRenderer
and the demo, you can download a NetBeans
project with the source code and the jar files here: 
<a href="http://www.java.net/download/javadesktop/blogs/hansmuller/buddylist/buddylist-project.zip">
Download BuddyList NetBeans Project </a>.
</p>
]]>

</content>
</entry>
<entry>
<title>Using Java Web Start to Launch NetBeans</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2006/01/web_started_exa.html" />
<modified>2006-01-10T00:22:06Z</modified>
<issued>2006-01-10T00:21:55Z</issued>
<id>tag:weblogs.java.net,2006:/blog/hansmuller/45.3876</id>
<created>2006-01-10T00:21:55Z</created>
<summary type="text/plain">Wouldn&apos;t it be nice to be able to show a Java source file
in NetBeans by clicking on a JNLP link in the browser?  Now you can.</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
About six months ago I had a dream.  Not the sort of dream that makes
you wake up shrieking or smiling, and not the kind that brings you
down from the mountain top or even gets you off the couch.  Mine was
the kind of dream programmers have.  The kind of sloth inspired idea
that comes to you while staring at the screen, wondering if there's
a way to eliminate all of the mouse clicking and key pressing effort
that makes you weary without actually burning calories.
</p>

<p>
I spend quite a bit of time looking at Java blogs and articles that
incorporate lots of source code.  Usually there's a link for zip file
that contains all of the files the document refers to, and maybe a jar
file with a build.  Sometimes articles include direct links to source files,
however scanning a pile of source code with the web browser isn't
terribly appealing.  The nicest way to look at code and try out APIs,
is to just load everything into a Java IDE like NetBeans.  Once that's
done it's possible to use the editor and debugger and all of the other
IDE features to explore the code.  Like a real programmer should.  And
just like a real programmer, I'm usually too lazy to bother.
</p>

<p>
So the big idea was to write a web started app that would download a
complete NetBeans project, launch NetBeans, and open the key source
files in the editor.  That way, if someone was reading a blog or an
article about some Java project, they could click on a JNLP link - and
with no additional effort! - peruse the code from within the IDE.  To
me, this seems like a civilized way to do business.  Sadly, I wasn't
able to con one of my colleagues into building such a web started app.
Towards the end of last year, as Sun began to slow down in
anticipation of the Christmas break, I took a crack at building a
NetBeans launcher.  You can try it now, by clicking on the handy
launch button below.  It's a signed application, because it creates a
temp file and launches a (NetBeans) process on your machine, so you'll
have to click through a security dialog.
</p>

<p>
To give the example launcher a try, just click the Launch button:
</p>

<p align="center">
<a href="http://www.java.net/download/javadesktop/blogs/hansmuller/launch/launch.jnlp">
<img alt="Web started application launch button" 
     src="http://weblogs.java.net/blog/hansmuller/archive/jws-launch-button.png" 
     width="88" 
     height="23"/>
</a>
</p>

<p>
The <b>launch</b> app depends on the NetBeans OpenFile module to start the
NetBeans IDE, if necessary.  Sadly (at the moment) there isn't 
an "OpenProject" module, so the best I can do is to show a single
Java source file.  If the launch app is unable to locate an installed
copy of NetBeans, it displays a little form that allows choosing
the install directory, or downloading the current NetBeans release.
I haven't tested launch very carefully (works on my machine :-) which
is unwise, since part of the code to find and launch NetBeans is
platform specific.  It should work on Windows XP and it might
work on Linux or the Mac or Solaris.  I'd be happy to
hear from anyone who's tried it.
</p>

<p>
The example file downloaded by the launcher, NetBeans.java, deals
with figuring out if and where NetBeans is installed.  I didn't 
pick this one file out of pride, it's incomplete and contains 
some moderately embarrassing hacks.  On the other hand, it does 
all of the important work.  The class is used like this:
</p>

<pre>
NetBeans nb = new NetBeans();
nb.initialize();
if (!nb.isInstalled()) {
    // give the user the opportunity to choose
    // the install directory or download NetBeans
}
else {
    File file = new File("C:\MyProject\src\pkg\MyFile.java");
    try {
        nb.openFile(file);
    }
    catch (NetBeans.Failure e) {
        // report the problem to the user
    }
}
</pre>

<p>
The initialize method uses some shameful heuristics to try and figure
out where NetBeans was installed.  Check out the source code from 
within the IDE to see what I mean.  It would certainly be much nicer
to be able to look in a well known (per platform) place to find out
what versions of NetBeans were installed and where; maybe in the
future that kind of support will emerge.
</p>

<p>
You can use the launch app on you own web site, just by making a 
copy of the <a href="http://weblogs.java.net/blog/hansmuller/archive/sample.jnlp.txt">JNLP file</a> file
and replace the URL in <i>argument</i> element at the bottom.
The current version links to the example NetBeans.java file:
</p>

<pre>
&lt;argument>http://download.java.net/javadesktop/blogs/hansmuller/launch/NetBeans.java&lt;/argument>
</pre>

<p>
You don't need to copy the launch jar files or anything else.  Just
create a link to your version of launch.jnlp on your site, and make
sure your web server
<a href="http://java.sun.com/docs/books/tutorial/deployment/webstart/deploying.html">
is configured to support the JNLP MIME type</a>.
</p>

<p>
This was originally intended to be a quick project that I'd finish on
on the long flight home from Prague back in December.  It didn't turn 
out that way, in part because building (usable) GUIs is always more
work than you'd think.  It's also because I took the opportunity to 
get introduced to 
<a href="http://www.netbeans.org/kb/articles/matisse.html">Matisse</a>.  
It's been a long time since I've been comfortable writing Swing GUIs
with a tool.  Using Matisse turned out to be pretty inspiring: it
worked well and it greatly simplified the task of evolving a GUI.
Using it was a constant reminder of all of the additional desktop app
building support that should be in NetBeans.  More about that in
another blog.
</p>

<p>
I have a long laundry list of worthy improvements for the NetBeans
launcher.  I'd be interested to hear what other developers think of
it and what you-all think should be changed/improved.  Here are a
few of TODO items from the top of my list:
<ul>
<li>Download a complete project packed into a jar file and expand
that into a temp directory.  Open a set of project relative source
files in NetBeans.</li>
<li>Log errors, and warnings and provide a way to show them.</li>
<li>Show the main window roughly in the middle of the screen. 
And wouldn't it be nice to know which Screen NetBeans was
already running on - if there were multiple screens.</li>
<li>An "OpenProject" NetBeans module.  I've been assured that this
wouldn't be so difficult to write.  Making sure that it was
deployed to the IDE, before the project was launched would be a
bit of a trick.</li>
</ul>
</p>

<p>
If you'd like to look at the complete NetBeans launch project, you'll
find a 
<a href="http://weblogs.java.net/blog/hansmuller/archive/Launch.zip">
zip file of the complete project</a> here.  I realize that it's more
than a little ironic to publish such a link.  Hopefully I'll be able to 
support loading entire projects (not just files) in round two.
</p>]]>

</content>
</entry>
<entry>
<title>JFrame.add() contentPane Pain: The Complete Story</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2005/11/jframeadd_conte.html" />
<modified>2008-01-02T17:42:16Z</modified>
<issued>2005-11-16T19:35:19Z</issued>
<id>tag:weblogs.java.net,2005:/blog/hansmuller/45.3644</id>
<created>2005-11-16T19:35:19Z</created>
<summary type="text/plain">Early on in Swing&apos;s evolution we added a runtime exception that warned
developers not to write JFrame.add(myComponent) and it has been
raising hackles ever since.  And it&apos;s my fault.  Since Graham Hamilton
covered my transgression in his My Favorite (Dead) Java Boilerplate
blog, I thought I&apos;d tell the complete story.</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
It's my fault.  The fact that adding a component to a JFrame required
one to explicitly add it to the JFrame's "contentPane" is my fault.
Early on in Swing's evolution we added a runtime exception that warned
developers not to write JFrame.add(myComponent) and it has been
raising hackles ever since.  Graham Hamilton covered my transgression
in his
<a href="http://weblogs.java.net/blog/kgh/archive/2005/11/my_favorite_dea.html">
My Favorite (Dead) Java Boilerplate
</a> blog and I thought I'd explain the rationale behind it's birth
and eventual demise.
</p>

<p>
It turns out that I did not create this trip-wire to incite violence
or to "educate developers about the choices" within the JFrame container.
JFrame's automatically created rootPane,
layeredPane, and contentPane substructure was designed to enable popup
effects that appear on top of the main GUI.  The original motivation
for JFrame's substructure was we to support lightweight menus and
tooltips and even dialogs that appeared within a top level window.
It's also possible to use the substructure to produce novel GUI
effects,
<a href="http://blogs.sun.com/roller/page/bblfish?entry=roman_guy_s_infinite_progress">
like translucent full-window progress monitors</a>. So why did
JFrame.add() generate an exceptional slap in the face for the
developer who's not schooled in all of this?
</p>

<p>
The 1.0 and 1.1 releases of Swing were delivered on the original Java
1.x platform.  Our audience was AWT developers who typically wrote
small apps by subclassing java.awt.Frame and overriding paint() or
setting its layout manager and adding children.  When we decided to
create JFrame's substructure there was a debate about the wisdom of
automatically mapping JFrame.add() to JFrame.getContentPane().add().
The reason I rejected that approach is that this "convenience" is a
shallow illusion.  To complete the illusion one would have to redirect
get/setLayout(), and addComponentListener(), and getComponent() and
getChildren() and so on.  In addition to making it tough to actually
get inside the JFrame itself, the complete illusion would be
asymmetrical since the source of events or a layout manager's container
wouldn't match what a developer would expect.  So in the interest of
consistency, not education, we did not automatically redirect
JFrame.add() to the content pane.
</p>

<p>
Time has passed and the number of AWT developers who's expectations
might have been violated by making JFrame.add() convenient has become
pretty small.  It's also true that the merits of providing a simple
trouble-free out of the box experience, even if it depends on an
imperfect illusion, are increasingly important.  So, in Tiger,
JFrame's add and setLayout (and addLayout) methods have changed to "do
what you [probably] mean".  The other JFrame methods, like getComponent(),
do not redirect, so if you use them, be careful.  And if you don't use them,
well, ignorance <b>is</b> bliss.
</p>

<p>
Now that we've got that out of the way, anyone have a nomination for
a new Swing boilerplate hall of shame candidate?  As far as I know,
the rest of the API is perfect.
</p>]]>

</content>
</entry>
<entry>
<title>A Brief Report from JavaOne Japan</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2005/11/a_brief_report.html" />
<modified>2008-01-02T17:42:16Z</modified>
<issued>2005-11-09T15:32:01Z</issued>
<id>tag:weblogs.java.net,2005:/blog/hansmuller/45.3594</id>
<created>2005-11-09T15:32:01Z</created>
<summary type="text/plain">This blog is a first for me: it&apos;s brief.  Yesterday Scott Violet, 
Josh Marianacci and I made some presentations at JavaOne Japan,
and we promised to provide a few helpful URLs.  I&apos;ve put together
a couple that cover the Extreme GUI talks with a short tangent
about the perils of translation.</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p align="center">
<img alt="Big JavaOne Tokyo Sign" src="http://weblogs.java.net/blog/hansmuller/archive/tokyo-javaone.jpg" width="640" height="248" />
</p>
<br>

<p>
This year, JavaOne Japan is during the week of November 7th in a jaw
dropping venue called Tokyo International Forum.  On Tuesday
<a href="http://weblogs.java.net/blog/zixle/">
Scott Violet</a>, <a href="http://weblogs.java.net/blog/joshy/"> Josh
Marianacci</a>, and I made two presentations based on Desktop Java
talks from the San Francisco JavaOne: Extreme GUI Makeover, Episode 1:
Lookin' Good, and Extreme GUI Makeover, Episode 2: Runnin' Fast.
</p>

<p>
Sessions at JavaOne Japan are shorter, just 45 minutes, and the
presentations are translated into Japanese in real-time.  Before each
session we met with the translators to go over technical terms and
other jargon.  The translators work in pairs because the job is a bit
of a mental sprint, so they shift the work back and forth.  They always
advise us to follow two simple rules: speak slowly, pausing between
slides to allow them catch up, and don't tell jokes.  Not being funny
just comes naturally, however it's tough to speak slowly when you're
trying to cram 60 minutes of material into a 45 minute session.  We
tended to start out at a sensible pace and then gradually accelerate
to the point where the last slide sounded like it was delivered by
Alvin and the Chipmunks.  After the first talk we met the
translators in the corridor.  The culture here is polite and friendly
and I think they abhor violence.  Still, I was glad that the
translators didn't have a club handy.
</p>

<p>
Here are the important sites and documents we referred to during the
talk.  The San Francisco versions of both talks are available online 
at developers.sun.com:
</p>

<ul>
<li>
<a href="http://developers.sun.com/learning/javaoneonline/2005/desktop/TS-3605.html">
Extreme GUI Makeover, Episode 1: Lookin' Good</a>
</li>
<li>
<a href="http://developers.sun.com/learning/javaoneonline/2005/desktop/TS-3902.html">
Extreme GUI Makeover, Episode 2: Runnin' Fast</a>
</li>
</ul>

<p>
Romain Guy developed some of the special effects shown in the "Lookin' Good"
presentation and he's been writing about them 
<a href="http://www.jroller.com/page/gfx"/a>in his jroller blog</a>
as well as his <a href="http://weblogs.java.net/blog/gfx/">blog on java.net</a>.
The code for some of the special effects is available now
from the <a href="https://swingfx.dev.java.net/">
SwingFX project </a>.
The animation framework used to animate the button and window 
backgrounds was written by Chet Haase and is the basis of an open
source project at <a href="http://timingframework.dev.java.net">
timingframework.dev.java.net</a>
</p>

<p>
The Mustang splash screen API is documented in this
<a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/mustang/splashscreen/">
java.sun.com tutorial
</a>
And you can download an early access build of Mustang 
from <a href="https://mustang.dev.java.net/">
mustang.dev.java.net</a>.
</p>

<p>
Scott Violet's in-depth article about performance tuning 
applications with large JTables is available on java.sun.com:
<a href="http://java.sun.com/products/jfc/tsc/articles/ChristmasTree/">
Christmas Tree Applications</a>
</p>

<p>
The SwingWorker API, for moving work from the event dispatching thread
to a worker thread, has been extensively documented.  The latest
documents and downloads can be found at
<a href="https://swingworker.dev.java.net/">
swingworker.dev.java.net
</a>


<p>
The latest beta release of NetBeans includes support for <a
href="http://www.netbeans.org/kb/articles/nb-profiler-tutor-8.html">performance
tuning</a> and the new <a
href="http://www.netbeans.org/kb/articles/matisse.html">Matisse</a>
Swing GUI designer.  You can download NetBeans from <a
href="http://netbeans.org">netbeans.org</a>.
Information about configuring the GC, for example to reduce
startup time by making the heap big enough, can be
also found on the netbeans site:
<a href="http://performance.netbeans.org/howto/jvmswitches/">
performance.netbeans.org/howto/jvmswitches/
</a>

<p>
Three other bloggers have covered the Extreme GUI talks at JavaOne
Japan: Charles Ditzel: <a
href="http://cld.blog-city.com/live_from_tokyo__extreme_ui_makeover__a_great_talk_on_develo.htm">
Live From Tokyo: Extreme UI Makeover - A Great Talk on Developing
Powerful Desktop Apps</a> and John O'Conner: 
<a href="http://weblogs.java.net/blog/joconner/archive/2005/11/javaone_tokyo_0_11.html">
JavaOne Tokyo '05: Extreme GUI Makeover
</a> and Greg Sporar from the NetBeans team:
<a href="http://weblogs.java.net/blog/gsporar/archive/2005/11/javaone_tokyo_d_1.html">
JavaOne Tokyo, Day One</a>.  Scott, Josh and I appreciate the coverage and the photos (thanks John)!
</p>
]]>

</content>
</entry>
<entry>
<title>Official: Swing is the Dominant GUI Toolkit</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2005/10/official_swing.html" />
<modified>2008-01-02T17:42:16Z</modified>
<issued>2005-10-18T20:31:54Z</issued>
<id>tag:weblogs.java.net,2005:/blog/hansmuller/45.3452</id>
<created>2005-10-18T20:31:54Z</created>
<summary type="text/plain">The most recent Evans Data Corporation developer survey had this to
about Swing: &quot;Java Swing with 47% use, has surpassed WinForms as the
dominant GUI development toolkit&quot;.  We are number one!
</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
I've been trying to think of a way to humbly announce that 
no lesser authority than Evans Data Corporation has reported
that Swing is the dominant GUI Toolkit for Northern American
developers.  It's difficult to present this new statistic with
the grace and humility of good sportsmanship because, after
nearly 8 years of steady growth:
</p>

<blockquote>
"Java Swing with 47% use, has surpassed WinForms as the dominant GUI
development toolkit, an increase of 27% since fall 2004."
</blockquote>

<p>
That's a direct quote from the Spring 2005 report.  You may want to
read it again (I have).  There are more developers building
applications using Swing and Java SE than WinForms and .NET.  Despite
the titanic resources marshalled by Microsoft to assert dominance over
their own desktop platform, the Swing community has grown into an
unstoppable force.  Microsoft has often been referred to as an "eight
hundred pound gorilla".  Thanks to the persistence and enthusiasm of
Swing developers everywhere, we've thrown the gorilla and the cage off
the island.  We're the new alpha male, we're the King Kong of GUI
toolkits.  We are the force to be reckoned with.  <b>We are number one!</b>.
</p>

<p>
I realize that was a little over the top.  I'm supposed to be humble
and quietly confident about our success and not indulge in all of this
vulgar gloating and boasting and jumping up and down on the desk
shouting, we're number one, we're number one, we're number ... 
</p>
<p>
Sorry about that.  
</p>

<p>
I'll just remain calm from here on in.  You'll have to trust me when I
say that I'm reporting the following from a peaceful and serene
perspective.  The use of both Swing and AWT have grown dramatically in
the last year and, quoting from the report, "Java GUI development is
clearly experiencing substantial growth".  So it is.  I would guess
that there are at least two trends at work here.  People are writing
Swing clients to augment or replace browser clients for network
services, and developers really do care about platform portability.
Sometimes portability is just about spanning different versions of
Windows but more often than not, it's about covering the growing
"alternative" desktop market.  Users want applications that provide
entertainment or communication or educational experiences that are
worthy of the fine computer hardware they're seated in front of,
and the zippy internet service they're connected to.  Developers are
choosing Swing to deliver those experiences and here, at camp
Swing headquarters, we couldn't be happier.  
</p>

<p>
It's good to be king and it's hard to be humble.  I feel a T-shirt coming.
</p>

<p align="center">
<img alt="duke1.gif" src="http://weblogs.java.net/blog/hansmuller/archive/duke1.gif" width="218" height="263" />
</p>

<p>
Thanks to Jeff Dinkins for another bit of just-in-time artwork!
</p>
]]>

</content>
</entry>
<entry>
<title>Open Source Bluegrass</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2005/10/open_source_blu.html" />
<modified>2008-01-02T17:42:16Z</modified>
<issued>2005-10-05T21:23:28Z</issued>
<id>tag:weblogs.java.net,2005:/blog/hansmuller/45.3387</id>
<created>2005-10-05T21:23:28Z</created>
<summary type="text/plain">Here&apos;s a blog that purports to tie three themes together:
music, the open source movement, and the effect of type parameters
on the java.util classes.  The fact that it achieves none of these
things should not stop you from reading it.</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[
<p>
This past Saturday morning, a friend and I were in San Francisco at
Golden Gate park, walking out of the Speedway Meadow.  It was cool and
overcast and the fog blanketed the tree tops and hung over our heads
and gave the surroundings the blurry hazy look of an old newsreel.  We
were walking down into another hollow, listed on the map as Marx
meadow, and drifting toward us was the sound of Joan Baez singing
"The Night They Drove Old Dixie Down".  The long narrow meadow is
flanked by steep hills and tall trees.  With its foggy ceiling and dim
light it felt like a cathedral.  There were thousands of people there,
listening, shuffling toward the stage for a better view or just
sitting in the grass listening to the story about Virgil Caine and the
tragedy of the American Civil War.  We joined them and listened to
Joan Baez sing more old American songs, songs by Woody Guthrie and Bob
Dylan and folk songs that have been around so long they're just
attributed to "traditional".  I'll never forget being the same place
last year listening to John Prine sing "Angel from Montgomery" or this
year, hearing anti-war and protest songs inspired by conflicts from
the distant past and from right now.  
</p>

<p>
It's tough to write about how great it was spending a day listening to
music.  It was entertaining, it was moving, it was fun, sometimes it
was beautiful.  In the evening it was really cold.  You should have
been there.  If you live in the area, you should have stepped away
from the keyboard and taken your head out of the network for a while,
and plugged it into the music.  At least that's what I did and I
couldn't have been happier.  But that's not why I'm writing this.
</p>

<p>
There were five big stages in Golden Park on Saturday and Sunday,
different bluegrass and folk music performers every hour, from 11AM
till 7PM, and it was all free.  Free as in Free Beer.  A (very)
wealthy man named Warren Hellman has been putting on the "Not Strictly
Bluegrass Festival" show on his own dime for the past five years.  I
can't tell you exactly why he does this, although if I had to guess
I'd say he's motivated by the same spirit that inspires software
engineers to join open source projects and build things just for the
pure joy of it.  That spirit confounds economists looking for a profit
motive and capitalists looking for a profit.  There were about a
bajillion people in Golden Gate Park taking in the music over the
weekend, and they weren't confused at all.
</p>

<p>
So I just wanted to say thank you.  Thank you Warren Hellman for
sharing two days of music with the Bay Area, again.
</p>

<p>
If you've actually read this far and have made a mental note to delete
me and my moon-eyed ravings from your RSS feed, here's a non-sequitur
that I hope you'll find reassuring.  It doesn't have anything to do
with free music, but it's a genuine Java code sample that you might
find useful.
<p>

<p>
Examples from the java.util canon are usually short and tidy.  In
theory, now that we have type parameters, the can be even
<a href="http://java.sun.com/features/2003/05/bloch_qa.html">
shorter and tidier</a>.  For example if you have a TreeMap
that defines the number of occurrences of each word in a document,
you can print them all like this:
</p>

<pre>
Map&lt;String, Integer> countMap = new TreeMap&lt;String, Integer>();
...
for (Map.Entry&lt;String, Integer> e: countMap.entries()) {
    System.out.println(e.getKey() + ":" + e.getValue());
}
</pre>

<p>
All well and good, unless you wanted to see the word/count entries
sorted by word count, not by word.  TreeMap keeps the entries sorted
by key, that's the word String in this case.  To sort the word/count
Map.Entry entries by word count you must convert the entries to a
List, define a Comparator that compares Map.Entry values, and then use
Collections.sort to sort the list.
</p>

<pre>
/* Sort the entries in countMap by count.  This code has
 * me wondering about just going back to AWK.
 */
Comparator&lt;Map.Entry&lt;String, Integer>> compareEntries =
    new Comparator&lt;Map.Entry&lt;String, Integer>>() {
    public int compare(Map.Entry&lt;String, Integer>e1, Map.Entry&lt;String, Integer>e2) {
        return e2.getValue().compareTo(e1.getValue());
    }
};
ArrayList&lt;Map.Entry&lt;String, Integer>> entries =
    new ArrayList&lt;Map.Entry&lt;String, Integer>>(countMap.entrySet());
Collections.sort(entries, compareEntries);
</pre>

<p>
Maybe it's just me, but yech.  Sometimes I'd really rather just
listen to Earl Scruggs play Foggy Mountain Breakdown.
</p>
]]>

</content>
</entry>
<entry>
<title>Using Swing&apos;s JFormattedTextField for integers is not as trivial
as it should be.</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/hansmuller/archive/2005/08/using_swings_jf.html" />
<modified>2008-01-02T17:42:16Z</modified>
<issued>2005-08-25T22:18:48Z</issued>
<id>tag:weblogs.java.net,2005:/blog/hansmuller/45.3152</id>
<created>2005-08-25T22:18:48Z</created>
<summary type="text/plain">Recently, the javadesktop.org JDNC forum has hosted some spirited discussion
about using Swing JFormattedTextFields for decimal input/output.  I&apos;d written
a blog on a similar topic about 8 months ago and forgotten to actually publish it.
So here it is!</summary>
<author>
<name>hansmuller</name>


</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/hansmuller/">
<![CDATA[<p>
Earlier this year I was fiddling around with the new 
J2SE network 
<a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/ProxySelector.html">
ProxySelector 
</a>
APIs as part of a small demo-project.  Sadly, the project just wouldn't
stay small and I didn't have time for something big. So
after a few days it disappeared into one of the many corners of
my laptop's hard disk, where it's been quietly moldering away.
</p>

<p>
One part of the old demo was a small GUI for
collecting network proxy host names and port numbers. I'd used
JFormattedTextFields for the latter.  You might think that doing
so would have been trivial, since port numbers are just integers 
between 0 and 65534 and JFormattedTextField is very, well, flexible.
It turns out to have been <i>not so trivial</i> and at the time I was
inspired to write a blog-sized article about exactly what I'd done.
That article would have remained buried with everything else from 
the project if it
hadn't been for some interesting 
<a href="http://www.javadesktop.org/forums/thread.jspa?messageID=107700">
JFormattedTextField threads 
</a>
on the javadesktop.org JDNC forum that cropped up recently.  The
problem that inspired the JDNC JFormattedTextField thread had to do
with decimals (like 123.45).  Since I'd spent some time in the
trenches with a similar problem, I thought it might be fun to exhume
my old article and toss it on the pyre.  So here it is.
<p>

<h3>ProxyPanel: A Swing Component for Network Proxies</h3>

<p>
<b>Warning:</b> if you're looking for the material about 
JFormattedTextField you can skip the first couple of paragraphs.
I've left the first couple of paragraphs the way they were out
of respect for the dead.  Plus, I'm too lazy to edit them out.
</p> 

<p>
Before writing more than a few lines of code I considered structuring
the ProxyPanel component conventionally: with careful separation of
model and view, and with great flexibility for all dimensions of both.
The model would be a Java Bean that included all of the data required
to completely specify the usual set of networking proxies along with
all of the secondary data like overrides and user names and passwords.
The bean's API would be specified as an interface, so that the
ProxyPanel could operate directly on application data, and an abstract
class would provide a simple backing store for the
data along with all of the change listener machinery required to keep
the GUI view in sync.  The view would be equally overdesigned.  It
would be configurable, to accommodate applications that wanted a
compact or subsetted presentation.  And just before I awoke from my
second system syndrome induced reveries, I imagined providing an XML
schema that could be used to completely configure and (cue the Mormon
Tabernacle choir) even localize the GUI.
</p>

<p>
This was supposed to be a tiny project aimed at highlighting the new
ProxySelector APIs and providing a small coding diversion for yours
truly.  So, after I'd calmed down, I decided to write a simple GUI
that wasn't terribly configurable and that lacked a pluggable model.
That's right: no model/view separation here.  If there are MVC gods,
I'm sure I'll be in for some smiting.  And if the gods can't be bothered,
then I'm confident that my more dogmatic brethren will take up the slack.
Please don't send your self-righteous segregationist rantings about the
merits of MVC to me.  I know, I know.
</p>

<p>
My first cut at structuring the code for the four pairs of proxy
host/port fields that correspond to the bulk of the GUI was to create
a little internal class that defined the GUI for just one proxy, in
terms of four components:
</p>

<pre>
public class ProxyPanel extends JPanel {
    private ProxyUI httpUI;
    private ProxyUI httpsUI;
    // ProxyPanel constructor initializes httpUI etc ...

    private static class ProxyUI {
        private final JLabel hostLabel;
        private final JTextField hostField;
        private final JLabel portLabel;
        private final JFormattedTextField portField; 

        ProxyUI (ProxyPanel panel, String hostTitle, String host, String portTitle, int port) {
           // create labels, fields, and update the GridBagLayout
        }
        String getHostName() {
            return hostField.getText();
        }
        // ...
    }
}
</pre>

<p>
The ProxyPanel created four ProxyUI instances and squirreled them away
in four private ProxyPanel ivars.  The ProxyUI class did
encapsulate the details of how one proxy was presented to the user.
On the down side, had to assume that the ProxyPanel had a
GridBagLayout (no encapsulation there) and it felt gratuitously
complicated.   
</p>

<p>
One lesson I learned as part of building this first revision of
ProxyPanel was how to configure a JFormattedTextField that accepted
either a integer between 0 and 65534 or an empty string.  The latter
indicated that the user hadn't provided a valid value.  It seemed like
it would a little less surprising for users to map no-value or invalid
values to a blank than to insert a valid default value like 0.
</p>

<p>
JFormattedTextFields are eminently configurable and if you'd like to
get acquainted with the API I'd recommend the <a
href="http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.html">
Java Tutorial</a>.
The specific problem I was trying to solve isn't
covered there however with a little help from the local cognoscenti I
was able to work things out.
</p>


<p>
The Swing class that takes care of converting to and from strings as
well as validating same, is called a formatter and the subclass needed
for numbers is called NumberFormatter.  A separate java.text class
called DecimalFormat is delegated the job of doing the actual string
conversions and it provides its own myriad of options for specifying
exactly how our decimal is to be presented.  Fortunately in this case
we don't need to avail ourselves of much of that, in fact we're going
to defeat DecimalFormat's very capable features for rendering numbers
in a locale specific way.  What we need is just a geek friendly 16 bit
unsigned integer.  Or a blank.
</p>

<p>
Here's the code for our JFormattedTextField instance.  We override
NumberFormatter's stringToValue method to map "" (empty string) to
null.  The ProxyPanel.getPort() method that reads this field will map
null to -1, to indicate that the user hasn't provided a valid value.
</p>

<pre>
DecimalFormat df = new DecimalFormat("#####");
NumberFormatter nf = new NumberFormatter(df) {
    public String valueToString(Object iv) throws ParseException {
        if ((iv == null) || (((Integer)iv).intValue() == -1)) {
            return "";
        }
        else {
            return super.valueToString(iv);
        }
    }
    public Object stringToValue(String text) throws ParseException {
        if ("".equals(text)) {
            return null;
        }
        return super.stringToValue(text);
    }
};
nf.setMinimum(0);
nf.setMaximum(65534);
nf.setValueClass(Integer.class);
portField = new JFormattedTextField(nf);
portField.setColumns(5);
</pre>

<p>
It occurred to me that perhaps an IntegerTextField would be
worthwhile.  That way one could write:
</p>

<pre>
IntegerTextField inf = new IntegerTextField();
itf.setMinimum(0);
itf.setMaximum(65534);
itf.setEmptyOK(true);
itf.setEmptyValue(-1);  // new feature, "" => -1
itf.setValue(0);
</pre>

<p>
I don't think that's a vast improvement however developers might have
an easier time sorting out how to create an IntegerTextField than
assembling the right combination of DecimalFormat, NumberFormatter,
and FormattedTextField.  Of course, having gone so far as to create
IntegerTextField we'd want similar classes for currency values, real
numbers, dates, and so on.  Some of this is already covered by
JSpinner although spinners are better suited to cycling through
relatively small sets of values.
</p>


<h4>Eight months later ...</h4>
<p>
It's been a long time since I wrote all of that.  Looking back
I'd have to say that a set of classes, like IntegerTextField,
would certainly make life more straightforward for Swing developers.
Hopefully the 
<a href="https://SwingLabs.dev.java.net">
SwingLabs </a> project will take up the cause and maybe in the future
a collection of battle-hardened special purpose text fields will
find their way into the JDK.  If they do, I'll use them.
</p>]]>

</content>
</entry>

</feed>