Download NetBeans!

20080603 Tuesday June 03, 2008

Swing Outline Component

Announcing the new Swing Tree Table today, Tim writes:

Usage is incredibly easy - you just provide a standard Swing TreeModel of whatever sort you like, and an additional RowModel that can be queried for the other columns contents, editability and so forth.

I found an example from sometime ago, by Tim, and have been playing with it to get used to this new development. The result is as follows:

To get started, I simply download the latest NetBeans IDE development build from netbeans.org and then attached the platform8/org-netbeans-swing-outline.jar to my Java SE project. Then I created a JFrame.

To work with this Swing tree table, you need to provide the new "org.netbeans.swing.outline.Outline" class with the new "org.netbeans.swing.outline.OutlineModel" which, in turn, is built from a plain old javax.swing.tree.TreeModel, together with the new "org.netbeans.swing.outline.RowModel". Optionally, to change the default rendering, you can use the new "org.netbeans.swing.outline.RenderDataProvider".

Let's first create a TreeModel for accessing files on disk. We will receive the root of the file system as a starting point:

private static class FileTreeModel implements TreeModel {

    private File root;

    public FileTreeModel(File root) {
        this.root = root;
    }

    @Override
    public void addTreeModelListener(javax.swing.event.TreeModelListener l) {
        //do nothing
    }

    @Override
    public Object getChild(Object parent, int index) {
        File f = (File) parent;
        return f.listFiles()[index];
    }

    @Override
    public int getChildCount(Object parent) {
        File f = (File) parent;
        if (!f.isDirectory()) {
            return 0;
        } else {
            return f.list().length;
        }
    }

    @Override
    public int getIndexOfChild(Object parent, Object child) {
        File par = (File) parent;
        File ch = (File) child;
        return Arrays.asList(par.listFiles()).indexOf(ch);
    }

    @Override
    public Object getRoot() {
        return root;
    }

    @Override
    public boolean isLeaf(Object node) {
        File f = (File) node;
        return !f.isDirectory();
    }

    @Override
    public void removeTreeModelListener(javax.swing.event.TreeModelListener l) {
        //do nothing
    }

    @Override
    public void valueForPathChanged(javax.swing.tree.TreePath path, Object newValue) {
        //do nothing
    }

}

Next, let's introduce the RowModel class:

private class FileRowModel implements RowModel {

    @Override
    public Class getColumnClass(int column) {
        switch (column) {
            case 0:
                return Date.class;
            case 1:
                return Long.class;
            default:
                assert false;
        }
        return null;
    }

    @Override
    public int getColumnCount() {
        return 2;
    }

    @Override
    public String getColumnName(int column) {
        return column == 0 ? "Date" : "Size";
    }

    @Override
    public Object getValueFor(Object node, int column) {
        File f = (File) node;
        switch (column) {
            case 0:
                return new Date(f.lastModified());
            case 1:
                return new Long(f.length());
            default:
                assert false;
        }
        return null;
    }

    @Override
    public boolean isCellEditable(Object node, int column) {
        return false;
    }

    @Override
    public void setValueFor(Object node, int column, Object value) {
        //do nothing for now
    }
    
}

Now, after dragging-and-dropping an Outline object onto your JFrame (which is possible after adding the beans from the JAR to the Palette Manager) which, in turn, automatically creates a JScrollPane as well, this is how you could code the JFrame's constructor:

public NewJFrame() {

    //Initialize the ui generated by the Matisse GUI Builder, which,
    //for example, adds the JScrollPane to the JFrame ContentPane:
    initComponents();

    //Here I am assuming we are not on Windows,
    //otherwise use Utilities.isWindows() ? 1 : 0
    //from the NetBeans Utilities API:
    TreeModel treeMdl = new FileTreeModel(File.listRoots()[0]);

    //Create the Outline's model, consisting of the TreeModel and the RowModel,
    //together with two optional values: a boolen for something or other,
    //and the display name for the first column:
    OutlineModel mdl = DefaultOutlineModel.createOutlineModel(
            treeMdl, new FileRowModel(), true, "File System");

    //Initialize the Outline object:
    outline1 = new Outline();

    //By default, the root is shown, while here that isn't necessary:
    outline1.setRootVisible(false);

    //Assign the model to the Outline object:
    outline1.setModel(mdl);

    //Add the Outline object to the JScrollPane:
    jScrollPane1.setViewportView(outline1);    

}

At this point, you can run the JFrame, with this result:

So, we see a lot of superfluous info that doesn't look very nice. Let's implement "org.netbeans.swing.outline.RenderDataProvider", as follows:

private class RenderData implements RenderDataProvider {

    @Override
    public java.awt.Color getBackground(Object o) {
        return null;
    }

    @Override
    public String getDisplayName(Object o) {
        return ((File) o).getName();
    }

    @Override
    public java.awt.Color getForeground(Object o) {
        File f = (File) o;
        if (!f.isDirectory() && !f.canWrite()) {
            return UIManager.getColor("controlShadow");
        }
        return null;
    }

    @Override
    public javax.swing.Icon getIcon(Object o) {
        return null;

    }

    @Override
    public String getTooltipText(Object o) {
        File f = (File) o;
        return f.getAbsolutePath();
    }

    @Override
    public boolean isHtmlDisplayName(Object o) {
        return false;
    }

}

Now, back in the constructor, add the renderer to the outline:

outline1.setRenderDataProvider(new RenderData());

Run the JFrame again and the result should be the same as in the first screenshot above. Look again at the rendering code and note that, for example, you have tooltips:

Jun 03 2008, 04:22:54 PM PDT Permalink

Trackback URL: http://blogs.sun.com/geertjan/entry/swing_outline_component
Comments:

I wonder why Sun sponsors two distinct yet so similar components as the JXTreeTable from SwingLabs (by Jeannette and Karl) and this NetBeans one (by Tim Bray?).
They appear equally powerful although admittedly I know very little about the NetBeans one, but both appear to revolve around javax.swing.tree.TreeModel.

Posted by Casper Bang on June 03, 2008 at 04:37 PM PDT #

Not Tim Bray, but Tim Boudreau. And, secondly, I'm pretty sure the two tree tables are pretty different, Tim's one is probably more suited to the NetBeans Platform, but that's just a guess.

Posted by Geertjan on June 03, 2008 at 08:36 PM PDT #

Cool, I might be using this for an upcoming project of mine.
This tutorial gave me a nice headstart, thx!

Posted by Jon W on June 04, 2008 at 01:40 PM PDT #

JIDE has one of these too that works really well. So is this going to make its way into javax.swing? Seems that such a component would be a logical fit into the stock Swing family.

Posted by Saeven on June 06, 2008 at 09:18 AM PDT #

I was using jxtreetable in my current project; and by following your example, I was able to hack an alternate version in Outline. Pretty impressive. Haven't played much, but sure to say the two do share certain similarity, which is good thing. No documentation on Outline has been a real pain. Still have no clue as how to make a tree fully expanded in a treetable via code.

Wish the two will merge and become a better one.

Posted by Jay on June 09, 2008 at 07:18 PM PDT #

How about tooltips/highlighters that JXTreeTable provides?

Posted by Montechristos on June 16, 2008 at 04:47 AM PDT #

Just started to evaluate Outline (naturally from my SwingX biased perspective :-) and started a discussion thread over at SwingLabs forum <p>

<a href="http://forums.java.net/jive/thread.jspa?threadID=42470&tstart=0">JXTreeTable vs. Outline</a> <p>

Cheers
Jeanette

Posted by Jeanette Winzenburg on June 16, 2008 at 07:01 AM PDT #

hmm ... no way to edit a post? The link looks busted, trying again:

http://forums.java.net/jive/thread.jspa?threadID=42470&tstart=0

Posted by 145.254.68.134 on June 16, 2008 at 07:03 AM PDT #

[…] former peeps over at Yahoo just released 10 more components, 3 Flash and 5 Flex components. The also fixed some of the bugs […]

Posted by battery on June 26, 2008 at 06:27 PM PDT #

Hi,

Can anybody tell when org-netbeans-swing-outline.jar will be available into final NetBeans 6.1?

Posted by valentin on June 26, 2008 at 10:08 PM PDT #

Can you tell me please how to build org-netbeans-swing-outline.jar from sources?

Posted by valentin on June 26, 2008 at 10:29 PM PDT #

It will be part of 6.5 Milestone 1. You can already get it if you download a development build from netbeans.org. No need to build it from sources, just get the JAR.

Posted by Geertjan on June 26, 2008 at 11:15 PM PDT #

Is it possible to use custom renderer/editor for the cells ? Namely I'de like to use ComboBox to edit values in the table part

Posted by Ivan on July 29, 2008 at 04:51 AM PDT #

I have installed the Netbeans 6.5M1 in a virtual machine and copied the JAR into my 6.1 folders.
Following your examples it has been easy to implement.
Thanks a lot!

Posted by Josep on August 04, 2008 at 08:18 AM PDT #

Hi,
I'm using this amazing component, and I'm having some trouble to enable the DnD support for my data structure.

When I'm using a JTree, I have the getSelectedPaths method to know exactly which objects are selected per node.

Using the OutLine component, How do I do that? Because, the SelectionModel that is accept in this component is a ListSelectionModel and not a TreeSelectionModel.

Thanks..

Posted by José Renato on August 19, 2008 at 06:27 AM PDT #

Having spent two hours trying to get an JXTreeTable working , the demo's too convoluted, Outline up in 15 mins, now modifying for my project.

Cheers Tom

Posted by pfoomer on August 30, 2008 at 05:46 AM PDT #

Post a Comment:

Name:
E-Mail:
URL:

Your Comment:

HTML Syntax: NOT allowed