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:

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 09:37 AM 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 01: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 06:40 AM 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 02: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 12:18 PM PDT #

How about tooltips/highlighters that JXTreeTable provides?

Posted by Montechristos on June 15, 2008 at 09:47 PM 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 12: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 guest on June 16, 2008 at 12: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 11:27 AM 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 03: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 03: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 04: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 28, 2008 at 09:51 PM 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 01: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 18, 2008 at 11:27 PM 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 29, 2008 at 10:46 PM PDT #

under which license is the outline.jar released? Can we use this binary in our commercial application without problems to our license terms (e.g. like we have with GPL and/or lgpl licenses)

Thanks for your help

Froed

Posted by Froed on November 18, 2008 at 06:47 AM PST #

Is there a JavaDoc anywherethat describes Outline, RowModel etc.?

Posted by thorsten on November 20, 2008 at 12:42 AM PST #

how to implement the expansion and collapse of the object JTree using the outline?

Posted by Francisco Martins on August 18, 2009 at 05:43 AM PDT #

In Fedora, Outline doesn't paint expand/collapse icons for the tree elements as well as doesn't put any gap for the descendants
Does anybody have any idea why and maybe some workaround?
Thanks in advance.

Posted by Anatoliy on August 28, 2009 at 01:06 AM PDT #

Where can I get the sources for the 'org-netbeans-swing-outline.jar' that comes bundled with NetBeans 6.5 installation? I need it as it would help me while debugging my application which uses Outline component. Can somebody point me to the sources archive?
Thanks in advance.

Posted by Samyak on September 09, 2009 at 08:08 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 hootoo on December 07, 2009 at 02:01 PM PST #

Hi Geertjan,

Love your tutorial and writeups all over the netbeans.org site and internet. Can you show how to build a Tree with each tree node having an image of its own?

Thanks,

Posted by NetBeans Newbie on March 03, 2010 at 07:44 AM PST #

Thanks for the great work. But looks like I have some problem when I set asksAllowsChildren to false. What I am doing is

- Build the tree table
- add some nodes under an empty node, then fireTreeNodesInserted event. The node collapse icon is not updated.
- add some nodes under an empty node, then fireTreeNodesInserted event and fireTreeNodesChanged event. The node collapse icon is updated. But when I click the collapse icon, it does not expend.

Is there some way to fix the problem? Thanks.

Posted by Xue li Shen on May 20, 2010 at 06:39 AM PDT #

Thanks for that comments, is very usefull.

Posted by aquiles on March 01, 2011 at 11:38 AM PST #

I understand that when you call the setValueFor method that you change the value for a single cell of the table. In a chase where you have that value modify other cells of the table (summations for example) how would you force the entire table to update after such a change? In a normal table you can force a data update by calling fireTableDataChanged() but here I don't see where you have that capibility.

Posted by Jaime on October 04, 2011 at 02:47 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
24
25
26
27
28
29
30
   
       
Today