Wednesday, August 27, 2014

Back to the Future!

After a five year hiatus I'm committed to getting back to blogging. Expect to see Java, Arduino, design patterns and more in the future.

Tuesday, December 9, 2008

CJUG Meeting on Tuesday, December 16th 2008

Topic: The Seductions of Scala Scala is a new, statically-typed language for the JVM. Its advantages over Java include a succinct syntax, an improved object model and full support for functional programming (FP). In this code-heavy talk, I’ll show why Scala is so seductive, how it can improve your productivity, and why it might replace Java as the de facto language for the JVM.

Who: Dean Wampler

When: December 16th, 2008 6:00 PM - 8:00 PM (Networking from 6:00 PM - 6:30 PM) (Presentation from 6:30 PM - 8:00 PM)

Where: Lewis Towers Ballroom, Beane Hall Loyola University of Chicago 820 N Michigan Ave (enter on Pearson 111 E. Pearson) Chicago, IL 60611

Cost: FREE to current CJUG members and first time guests Join Now!

For full details and to RSVP go to http://www.cjug.org/Wiki.jsp?page=2008.12.16.downtown

Hope to see you there.

Monday, November 10, 2008

Layout Prototyping Part 1: XML

GUI Layout is hard, but is it harder then it should be in Java? Can we do something to better the situation? My next few blogs will be about prototyping different approaches in an attempt to find something better. For my first article I'm going to attempt to apply XML to the GUI layout. The goal is to approximate some of the features of MXML from Flex.

In a previous article I compared layout logic in Flex/Flex Builder to Java. I found only one layout manager that had no Java equivalent. I wrote CoordinateLayout to mimic absolute layout from Flex. Here is a very basic example of it's usage.


public class CoordinateLayoutDemo extends JPanel {

public CoordinateLayoutDemo() {
setLayout(new CoordinateLayout());

add(new JLabel("Last Name:"), "x=10, y=10");
add(new JTextField(), "x=87, y=8, width=223");

add(new JLabel("First Name:"), "x=318, y=10");
add(new JTextField(), "x=395, y=10, width=207");

add(new JLabel("Phone:"), "x=10, y=36");
add(new JTextField(), "x=87, y=34, width=223");

add(new JLabel("Email:"), "x=318, y=36");
add(new JTextField(), "x=395, y=34, width=207");

add(new JLabel("Address:"), "x=10, y=62");
add(new JTextField(), "x=87, y=60, width=515");

add(new JLabel("City:"), "x=10, y=88");
add(new JTextField(), "x=87, y=86, width=223");

add(new JLabel("State"), "x=318, y=88");
add(new JTextField(), "x=395, y=86, width=207");
}
}



This lets one layout a screen pixel by pixel. It also has an "anchor mode" that allows one to determine how a component will resize by specifying the location of an anchor on one the four sides.


public class CoordinateLayoutDemo2 extends JPanel {
/**
*
*/
private static final long serialVersionUID = 5744676397576694341L;

public CoordinateLayoutDemo2() {
setLayout(new CoordinateLayout());

add(new JScrollPane(new JTextArea()),
"left=35, top=40, right=10, bottom=10");
add(new JSlider(SwingConstants.VERTICAL), "bottom=10, left=10, top=40");
add(new JComboBox(), "right=287, left=35, top=10");
add(new JButton("Button"), "right=10, top=10");
}
}


This code results in the following screen.



The only other thing I need is XML bindings and I have functionality similar to absolute layout.

XMLBeans to the Rescue.

Without going into too much detail, XMLbeans takes an XSD (XML Schema Definition) and creates java classes that can parse XML that conforms to that schema.

Here is a tiny schema that represents CoordinateLayout.


<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="CoordinateLayout">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="item">
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="x" type="xs:int" />
<xs:attribute name="y" type="xs:int" />
<xs:attribute name="width" type="xs:string" />
<xs:attribute name="height" type="xs:string" />
<xs:attribute name="top" type="xs:int" />
<xs:attribute name="left" type="xs:int" />
<xs:attribute name="bottom" type="xs:int" />
<xs:attribute name="right" type="xs:int" />
<xs:attribute name="vcenter" type="xs:int" />
<xs:attribute name="hcenter" type="xs:int" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

If I run this XSD through the XMLBeans schema compiler (scomp) I get a jar with classes that parse this schema. Now with a little drudgery to move the values from the schema generated objects to my layout I am able to represent my UI as an XML file.

Here is an XML file that conforms the XSD and arranges the components the same way as the first example.

<?xml version="1.0" encoding="UTF-8"?>
<CoordinateLayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <item name="lastNameLabel" x="10" y="10" />
    <item name="lastName" x="87" y="8" width="223" />

    <item name="firstNameLabel" x="318" y="10" />
    <item name="firstName" x="395" y="10" width="207" />

    <item name="phoneLabel" x="10" y="36" />
    <item name="phone" x="87" y="34" width="223" />

    <item name="emailLabel" x="318" y="36" />
    <item name="email" x="395" y="34" width="207" />

    <item name="addressLabel" x="10" y="62" />
    <item name="address" x="87" y="60" width="515"/>

    <item name="cityLabel" x="10" y="88" />
    <item name="city" x="87" y="86" width="223"/>

    <item name="stateLabel" x="318" y="88"/>
    <item name="state" x="395" y="86" width="207"/>
</CoordinateLayout>


After all that I took a long hard look at my XML systems and asked myself two questions.

1. Is this roughly equivalent to absolute layout from Flex?
2. Does this make layout any easier?

The answer to number one is, yes. I consider it close enough to the the layout functionality of absolute layout.

Number two, well no. XML doesn't help. No matter which way you slice it specifying pixel locations is not the simplest way of laying out components.

Not wanting to abandon this XML idea I figured I'd apply it to other layout managers.

The first one I tried was TableLayout. I applied the same steps.

1. Create an XML schema that represents the TableLayout finctionality.
2. Use XMLBeans to generate a jar file with the parsing code.
3. Glue the XMLBeans generated object to TableLayout.

This allowed me to create the following XML file.


<?xml version="1.0" encoding="utf-8"?>
<tablelayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    vgap="1" hgap="1">

    <columnsizes>
        <size>10</size><size>FILL</size><size>10</size><size>PREFERRED</size>
        <size>10</size><size>PREFERRED</size><size>10</size>
    </columnsizes>

    <rowsizes>
        <size>10</size><size>PREFERRED</size>
        <size>5</size><size>PREFERRED</size><size>10</size>
        <size>PREFERRED</size><size>5</size>
        <size>PREFERRED</size><size>10</size>
        <size>PREFERRED</size><size>5</size>
        <size>PREFERRED</size><size>10</size>
        <size>PREFERRED</size><size>10</size>
    </rowsizes>

    <item name="nameLabel" col1="1" row1="1" col2="5" row2="1" />
    <item name="name" col1="1" row1="3" col2="5" row2="3" />

    <item name="addLabel" col1="1" row1="5" col2="5" row2="5" />
    <item name="address" col1="1" row1="7" col2="5" row2="7" />

    <item name="cityLabel" col1="1" row1="9" />
    <item name="city" col1="1" row1="11" />

    <item name="stateLabel" col1="3" row1="9" />
    <item name="state" col1="3" row1="11" />

    <item name="zipLabel" col1="5" row1="9" />
    <item name="zip" col1="5" row1="11" />

    <item name="button" col1="1" row1="13" col2="5" row2="13" />
</tablelayout>


Which results in this:



I did the same thing with GridBagLayout.

<?xml version="1.0" encoding="utf-8"?>
<gridbag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <defaults anchor="EAST" top="5" left="5" right="5" />
    <item name="lastNameLabel" />
    <item name="lastNameTF" fill="HORIZONTAL" weightx="1" />
    <item name="firstNameLabel" />
    <item name="firstNameTF" fill="HORIZONTAL" weightx="1" gridwidth="REMAINDER" />
    <item name="phone" />
    <item name="phoneTF" fill="HORIZONTAL" weightx="1" />
    <item name="email"/>
    <item name="emailTF" fill="HORIZONTAL" weightx="1" gridwidth="REMAINDER" />
    <item name="address" />
    <item name="addressTF" fill="HORIZONTAL" weightx="1" gridwidth="REMAINDER" />
    <item name="city" bottom="5"/>
    <item name="cityTF" fill="HORIZONTAL" weightx="1" bottom="5"/>
    <item name="state" bottom="5"/>
    <item name="stateTF" fill="HORIZONTAL" weightx="1" bottom="5"/>
</gridbag>


Which actually looks like less code then writing this in Java. That's not hard though. Gridbag is rather cumbersome to use.

I decided to go through this process once more. This time with MigLayout. In the end I was disappointed. Not because it didn't work. Not because of any failure in MigLayout. Just because it was too simple. Now I could have built an XSD around the type-safe constraint objects available in MigLayout. Unfortunately that was going to make for some very verbose XML. Instead I just packaged up the string version of the constraints in some XML and called it a day.

<?xml version="1.0" encoding="utf-8"?>
<miglayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    layout="ins 20" column="[para]0[][100lp, fill][60lp][95lp, fill]" row="">
   
    <item name="man" params="skip" />
    <item name="manSep" params="span 3, growx, wrap" />
   
    <item name="compLbl" params="skip" />
    <item name="company" params="span, growx" />
    <item name="contactLabel" params="skip" />
    <item name="contact" params="span, growx" />
    <item name="orderLabel" params="skip" />
    <item name="order" params="wrap para" />

    <item name="ins" params="skip" />
    <item name="insSep" params="span 3, growx, wrap" />
   
    <item name="namelabel" params="skip" />
    <item name="name" params="span, growx" />
    <item name="refNoLabel" params="skip" />
    <item name="refNo" params="wrap" />
    <item name="statLabel" params="skip" />
    <item name="stat" params="wrap para" />
   
    <item name="ship" params="skip" />
    <item name="shipSep" params="span 4, growx, wrap" />
   
    <item name="yardLabel" params="skip" />
    <item name="yard" params="span, growx" />
    <item name="regLabel" params="skip" />
    <item name="reg" params=""/>
    <item name="hullLabel" params="right" />
    <item name="hull" params="wrap" />
    <item name="typeLabel" params="skip" />
    <item name="type" params=""/>
</miglayout>


About five minuets after I finished I realized I created an XSD for what could be more simply represented as a properties file.

Here is a properties file version of the same layout.
layout = ins 20 
column = [para]0[][100lp, fill][60lp][95lp, fill]
row =
man = skip
manSep = span 3, growx, wrap

compLbl = skip
company = span, growx
contactLabel = skip
contact = span, growx
orderLabel = skip
order = wrap para

ins = skip
insSep = span 3, growx, wrap

namelabel = skip
name = span, growx
refNoLabel = skip
refNo = wrap
statLabel = skip
stat = wrap para

ship = skip
shipSep = span 4, growx, wrap

yardLabel = skip
yard = span, growx
regLabel = skip
reg =
hullLabel = right
hull = wrap
typeLabel = skip
type=


So what did I accomplish? Well I can say I successfully built a system that decouples layout parameters from components. Certainly decoupling can be a good design pattern. Gridbag showed that there was some benefit to the XML way of doing things. Yet MigLayout showed that in the end it's all about the capability of the layout manager itself and not the markup. I don't think just applying XML is going to make GUI layout easier all by itself.

I have a web start app demonstrating my prototype.



The source is also available.

xmllayoutdemo-src.zip

Wednesday, July 2, 2008

Lately I've been spending my spare time contributing code samples to the The Java Tutorial Community Portal. My hope is that one or more of these examples will be interesting enough to be included in the official tutorial. My latest addition is an example on how to override tool tip generation for a particular component. This example is a tabbed pane that shows a preview of a tab as a tooltip.

In this picture the mouse was hovering over the "images" tab.

There are techniques for installing custom universal tool tip providers. In this case I only wanted to change the behaviour for one particular component. To accomplish this I overrode the createToolTip() method of JTabbedPane with the following:

/**
* overide createToolTip() to return a JThumbnailToolTip
*/
@Override
public JToolTip createToolTip() {
Point loc = getMousePosition();
int index = indexAtLocation(loc.x, loc.y);

if (index != -1) {
Component comp = getComponentAt(index);

BufferedImage image = ImageFactory.toImage(comp);

JToolTip tip = new JImageToolTip(image, 0.5);

return tip;
} else {
return super.createToolTip();
}
}

This method returns an instance of JImageToolTip which displays an image of the hidden component instead of the tooltip text. The image of the component was generated by the toImage() method of my ImageFactory class.

/**
* Generates a buffered Image of the specified component.
*
* @param componet
* @return image 'snapshot' of the component and it's state at the time this
* method was called.
*/
public static BufferedImage toImage(Component componet) {
BufferedImage image = new BufferedImage(componet.getWidth(), componet
.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
graphics.setColor(componet.getBackground());
graphics.fillRect(0, 0, componet.getWidth(), componet.getHeight());
componet.paint(graphics);
graphics.dispose();

return image;
}

The JImageToolTipThis also class was used to create a label that displays a thumbnail of an image and provides the full size image as a tooltip.

I've made the full source code available. Comments on this or any other code sample are welcomed and encouraged.

Source Code: ThumbnailTooltipDemo-src.zip

Collator - Faster Comparison for identical strings.

Tuesday, June 3, 2008

Java Tutorial Community - Jtree and Borders Code samples

I've been working away on building "code samples" for the Java Tutorial Community Portal. Each one is an example of a piece of code that at one time or another I've found useful. I'm not sure which ones will be interesting or even worthy of a full on tutorial. I'm just posting them and looking for feedback. I have four code samples today.

1. SwitchRootDemo - Demonstrates how to change the root of a default tree model.

2. NodeRolloverDemo - Demonstrates how to highlight a node in a tree when the mouse is over it.

3. FlexibleSearchTreeDemo - Demonstrates how to expand the searching functionality of JTree. Also has RegEx support.

4. CustomBorderDemo - Demonstrates how to use Java2D to create a custom border. 

I have a few other examples in the works for trees. I hope to post that in a few days.



Monday, May 19, 2008

Contributing to The Java Tutorials Community Project

I have been working on contributing to the Java Tutorials Community Project. I've put together some code samples as potential tutorial subjects.
  1. JTable - ColumnsDemo
  2. JTable - ColorEntireRowDemo

  3. JTable - MultiLineRows

  4. JTable - FrozenColumns

  5. JTree - DefaultTreeModelDemo

  6. JTree - CustomEditorDemo

The tutorials project has forums where you can comment on these proposed topics, propose new topics and to request revisions to any of the current Java tutorials. We need your help to create the kind of content that can help reduce the Java learning curve and help create better software.

Thursday, March 20, 2008

The secret life of a DefaultTreeModel

This is a draft of a small tutorial I have been attempting to submit to Sun for inclusion in the official Java tutorial. Unfortunately they are very busy lately and have not had the time to review my work. My intent is to bring to light some of the subtleties of the DefaulTreeModel API that are not covered in the Java tutorial on JTree.

This tutorial will revolve around a demo application designed to show the difference between the right and wrong way to interact with DefaulTreeModel. Right clicking on any node in the tree will bring up a menu with a range of options.



Adding and Removing nodes in a DefaultTreeModel.

A DefaulTreeModel collects DefaultMutableTreeNodes together into a tree structure. At first glance the child modification methods like add() and remove() from DefaultMutableTreeNode look as if they overlap with the insertNodeInto() and removeNodeFromParent() from DefaulTreeModel. When the methods from DefaultTreeModel are used events are fired that update any JTree this model may be associated with. Simply modifying the DefaultMutableTreeNode does not. This can be demonstrated by the following chunk of code.

Example of the wrong way to remove a node.
TreePath currentSelection = tree.getSelectionPath();
if (currentSelection != null) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
    currentSelection.getLastPathComponent();
    node.removeFromParent();
}


Calls to methods like add() or remove() from DefaultMutableTreeNode need to be followed by a call to the DefaultTreeModel to notify the JTree of model changes. In our example a call to nodeStructureChanged() on the parent of the node being removed would have allowed the tree to be updated correctly. For adding or removing a single node from a tree the simplest solution is to call the insertNodeInto and removeNodeFromParent methods on DefaultTreeModel.

Example of the correct way to remove a node.
TreePath currentSelection = tree.getSelectionPath();
if (currentSelection != null) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
        currentSelection.getLastPathComponent();
    DefaultTreeModel model = ((DefaultTreeModel) tree.getModel());
    model.removeNodeFromParent(node);
}


There may be situations where multiple additions or removals happen in large blocks. In these cases the model may not need to be notified of a change until the bulk operation is completed. This is exemplified by the following code which adds multiple children to a node.

...
/**
 *
 * Adds 2 children, "even" and "odd". Even contains all the even numbers from zero to 49.
 * Odd contains all the odd numbers from zero to 49.
 */
TreePath currentSelection = tree.getSelectionPath();
if (currentSelection != null) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
        currentSelection.getLastPathComponent();
    DefaultTreeModel model = ((DefaultTreeModel) tree.getModel());

    DefaultMutableTreeNode odd = new DefaultMutableTreeNode("odd");
    node.add(odd);
    DefaultMutableTreeNode even = new DefaultMutableTreeNode("even");
    node.add(even);
    for (int i = 0; i < 50; i++) {
        if (i % 2 == 0) {
            even.add(new DefaultMutableTreeNode(i));
        } else {
            odd.add(new DefaultMutableTreeNode(i));
        }
    }
    // The above changes may not seem to take effect until nodeStructureChanged is called
    model.nodeStructureChanged(node);
}
...


This example creates 52 new nodes. If they were inserted with insertNodeInto() then 52 TreeNodesInserted events would have been fired. This way only one fireTreeStructureChanged event is fired after all the nodes are modified. Depending upon the particular needs of your application this may save some event processing.

Modifying user objects in a DefaultMutableTreeNodes.

Just as a DefaultTreeModel needs to be notified when children are added or removed for a node, so too does it need to be notified when the user object returned by getUserObject() is modified. Failure to do so could lead to rendering issues in the JTree. This is an example of what a such a situation might look like.



To avoid this make sure to call nodeChanged() on the model after any change that might effect the rendering of that node. Here is an example of code that will update correctly.

...
TreePath currentSelection = tree.getSelectionPath();
if (currentSelection != null) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
    currentSelection.getLastPathComponent();

    node.setUserObject("THIS IS A VERY LOOOOOOOOOOOOOOOOOOOOONG STRING");

    DefaultTreeModel model = ((DefaultTreeModel) tree.getModel());
    model.nodeChanged(node);
}
...


When updated correctly the tree will display the entire string.



Conclusion
As a general rule any time the data associated with your DefaulTreeModel changes it is important to update the model. Proper use of the DefaulTreeModel will limit the number of times you must explicitly do this.

I've made the source code for the example available for download.

As I said this is a draft of a tutorial. I'm looking for feedback on what can be improved and added while staying within the scope of the DefaulTreeModel/DefaultMutableTreeNode.