Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.gui > #3146

Re: Sortable Java Tree Ta

From "Rogan Dawes" <rogan.dawes@THRWHITE.remove-dii-this>
Subject Re: Sortable Java Tree Ta
Message-ID <Y-KdnbSp1ugtvC7anZ2dneKdnZydnZ2d@saix.net> (permalink)
Newsgroups comp.lang.java.gui
References <4in3r31llscj3ri5toa64avef8m52d6c6n@4ax.com>
Date 2011-04-27 15:43 +0000
Organization TDS.net

Show all headers | View raw


  To: comp.lang.java.gui
Roedy Green wrote:
> On Tue, 12 Feb 2008 14:40:57 +0200, Rogan Dawes <discard@dawes.za.net>
> wrote, quoted or indirectly quoted someone who said :
> 
>> The big thing that I was trying to point out in this thread, and which 
>> Roedy seems to be missing repeatedly, is that sorting a *TREE* is very 
>> different from sorting a *TABLE*.
> 
> Sorry, I always muddle those two.  Sorting a tree is not a common
> operation.  I just read it as sort a table.
> 
> I presume you mean just sort the children of each node. It looks as
> though you must sort, and if the order has changed, remove all elts
> past the point of change, and re-add them in the new order.

Well, I guess you could write a SortedTreeModel adapter class that 
contains a similar node pattern to the underlying TreeModel, along with 
int[] arrays mapping viewToModel and modelToView

e.g.

public class SortedTreeModel extends AbstractTreeModel {

private Map<Object, int[]> viewToModel;
private Comparator comparator;

public SortedTreeModel(TreeModel delegate) {
     viewToModel = new HashMap<Object, int[]>();
     this.delegate = delegate;
}

public Object getChild(Object parent, int index) {
     int[] viewToModel = getViewToModel(parent);
     if (viewToModel == null)
         return delegate.getChild(parent, index);
     return delegate.getChild(parent, viewToModel[index]);
}

public int getChildCount(Object parent) {
     return delegate.getChildCound(parent);
}

public int getIndexOfChild(Object parent, Object child) {
     int index = delegate.getIndexOfChild(parent, child);
     int[] viewToModel = getViewToModel(parent);
     if (viewToModel == null)
         return index;
     for (int i=0; i<viewToModel.length; i++)
         if (viewToModel[i] == index)
             return i;
     throw new RuntimeException("This should never happen");
}

public Object getRoot() {
     return delegate.getRoot();
}

public boolean isLeaf(Object node) {
     return delegate.isLeaf(node);
}

public void valueForPathChanged(TreePath path, Object newValue) {
     delegate.valueForPathChanged(path, newValue);
}

protected int[] getViewToModel(Object parent) {
     return viewToModel.get(parent);
}

public void setComparator(Comparator comparator) {
     this.comparator = comparator;
     sort(new TreePath(getRoot()), true);
}

protected void sort(TreePath path, boolean recursive) {
     Object parent = path.lastPathComponent();
     int childCount = delegate.getChildCount(parent);
     if (childCount == 0)
         return;
     Object[] children = new Object[childCount];
     int[] viewToModel = new int[childCount];
     for (int i=0; i<childCount; i++) {
         children[i] = delegate.getChild(parent, i);
         if (recursive)
             sort(path.pathByAddingChild(children[i]), recursive);
     }
     Arrays.sort(children, comparator);
     for (int i=0; i<childCount; i++)
         viewToModel[i] = delegate.getIndexOfChild(parent, children[i]);
     this.viewToModel.put(parent, viewToModel);
     fireChildrenChanged(path, childrenArray[children.length], children);
}

private int[] childrenArray(int size) {
     int[] a = new int[size];
     for (int i=0; i<size; i++)
         a[i] = i;
     return a;
}

}

This *should* work, but since I wrote it in my news reader, I make no 
guarantees it will even compile.

Now, all you need to do is implement a Comparator for your nodes. And if 
it is a dynamic TreeModel, then you need to add the necessary listener 
to the delegate and call sort(node) (or sort(node, true) ) whenever the 
node changes.

Use it like so:

TreeModel delegate = . . . ; // your underlying TreeModel
TreeModel sorted = new SortedTreeModel(delegate);
JTree tree = new JTree(sorted);
Comparator comp = new MyComparator();
sorted.setComparator(comp);

Obviously, you can extend the identical technique to TreeTableModel.

NOTE: You can try to be more fine grained in your event firing, of course.

Rogan

---
 * Synchronet * The Whitehouse BBS --- whitehouse.hulds.com --- check it out free usenet!
--- Synchronet 3.15a-Win32 NewsLink 1.92
Time Warp of the Future BBS - telnet://time.synchro.net:24

Back to comp.lang.java.gui | Previous | NextPrevious in thread | Find similar | Unroll thread


Thread

Re: Sortable Java Tree Ta arvim85@gmail.com.remove-dii-this - 2011-04-27 15:43 +0000
  Re: Sortable Java Tree Ta "Roedy Green" <roedy.green@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000
  Re: Sortable Java Tree Ta "Rogan Dawes" <rogan.dawes@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000
    Re: Sortable Java Tree Ta "Roedy Green" <roedy.green@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000
      Re: Sortable Java Tree Ta "Roedy Green" <roedy.green@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000
        Re: Sortable Java Tree Ta "Rogan Dawes" <rogan.dawes@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000
      Re: Sortable Java Tree Ta "Rogan Dawes" <rogan.dawes@THRWHITE.remove-dii-this> - 2011-04-27 15:43 +0000

csiph-web