Author: sletellier Date: 2010-03-19 18:53:26 +0100 (Fri, 19 Mar 2010) New Revision: 1797 Log: Creation of adapter to sort navigation tree Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationSortedTreeAdapter.java Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java 2010-03-19 17:32:29 UTC (rev 1796) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java 2010-03-19 17:53:26 UTC (rev 1797) @@ -22,6 +22,7 @@ import jaxx.runtime.JAXXContext; +import javax.swing.tree.TreeModel; import javax.swing.tree.TreeNode; import java.util.regex.Pattern; @@ -33,7 +34,7 @@ * @author sletellier * @since 2.0.0 */ -public interface NavigationModel { +public interface NavigationModel extends TreeModel { Object getRoot(); Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationSortedTreeAdapter.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationSortedTreeAdapter.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationSortedTreeAdapter.java 2010-03-19 17:53:26 UTC (rev 1797) @@ -0,0 +1,245 @@ +/* + * *##% + * JAXX Runtime + * Copyright (C) 2008 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.decorator.Decorator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import java.util.*; + +/** + * Adapter to sort NavigationModel + * FIXME : Dont work with TreeTable + * + * @author sletellier + * @since 2.0.1 + */ +public class NavigationSortedTreeAdapter implements TreeModelListener { + + /** + * Logger + */ + static private final Log log = LogFactory.getLog(NavigationSortedTreeAdapter.class); + + protected NavigationModel model; + protected List<Comparator> comparators; + + + /** + * Used to sort NavigationTreeModel by decorator + * + * @param model of navigation tree + */ + public NavigationSortedTreeAdapter(NavigationModel model){ + this.model = model; + model.addTreeModelListener(this); + } + + /** + * Used to sort NavigationTreeModel by comparator + * + * @param model of navigation tree + * @param comparator used to sort tree + */ + public NavigationSortedTreeAdapter(NavigationModel model, Comparator comparator){ + this.model = model; + comparators = new ArrayList<Comparator>(); + comparators.add(comparator); + model.addTreeModelListener(this); + } + + /** + * Used to sort NavigationTreeModel by comparators + * + * @param model of navigation tree + * @param comparators used to sort tree + */ + public NavigationSortedTreeAdapter(NavigationModel model, List<Comparator> comparators){ + this.model = model; + this.comparators = comparators; + model.addTreeModelListener(this); + } + + /** + * Used to sort NavigationTreeModel by comparators + * + * @param model of navigation tree + * @param comparators used to sort tree + */ + public NavigationSortedTreeAdapter(NavigationModel model, Comparator ... comparators){ + this.model = model; + this.comparators = Arrays.asList(comparators); + model.addTreeModelListener(this); + } + + // TODO : find how optimize this (structure not change every times) + @Override + public void treeNodesChanged(TreeModelEvent e) { + sort(getCurrentNode(e), true); + } + + @Override + public void treeNodesInserted(TreeModelEvent e) { + sort(getCurrentNode(e), true); + } + + @Override + public void treeNodesRemoved(TreeModelEvent e) { + } + + @Override + public void treeStructureChanged(TreeModelEvent e) { + sort(getCurrentNode(e), true); + } + + protected NavigationTreeNode getCurrentNode(TreeModelEvent e){ + return (NavigationTreeNode) e.getTreePath().getLastPathComponent(); + } + + // Sort + protected void sort() { + NavigationTreeNode rootNode = (NavigationTreeNode) model.getRoot(); + if (rootNode != null && log.isDebugEnabled()){ + log.debug("Sort from root node : " + rootNode.getBean()); + } + sort(rootNode, true); + } + protected void sort(NavigationTreeNode parent, boolean structureChanged) { + + if (parent == null){ + return; + } + + List<NavigationTreeNode> children = Collections.list(parent.children()); + + if (comparators == null || comparators.isEmpty()){ + Collections.sort(children, RENDERER_COMPARATOR); + } else { + children = sortWithComparators(children); + } + + if (children == null || children.isEmpty()){ + return; + } + + Iterator<NavigationTreeNode> childrenIterator = children.iterator(); + if (childrenIterator != null){ + + model.removeTreeModelListener(this); + + parent.removeAllChildren(); + while (childrenIterator.hasNext()) { + NavigationTreeNode childNode = childrenIterator.next(); + if (log.isDebugEnabled()){ + log.debug("Adding child " + childNode.getBean() + " to parent " + parent.getBean()); + } + parent.add(childNode); + } + + if (structureChanged){ + model.nodeStructureChanged(parent); + } else { + model.nodeChanged(parent, true); + } + model.addTreeModelListener(this); + } + } + + protected List<NavigationTreeNode> sortWithComparators(List<NavigationTreeNode> children) { + for (Comparator<?> comparator : comparators){ + List<NavigationTreeNode> result = sortWithComparator(children, comparator); + if (result != null){ + return result; + } + } + return null; + } + + protected <T> List<NavigationTreeNode> sortWithComparator(List<NavigationTreeNode> children, + Comparator<T> comparator) { + Map<T, NavigationTreeNode> toSort = new HashMap<T, NavigationTreeNode>(); + + List<T> beans = new ArrayList<T>(); + + // Extract beans + for (NavigationTreeNode child : children){ + Object o = child.getBean(); + if (o != null){ + try{ + T casted = (T) o; + beans.add(casted); + toSort.put(casted, child); + } catch (ClassCastException eee){ + return null; + } + } + } + + if (beans.isEmpty()){ + return null; + } + + // Sort beans + if (log.isDebugEnabled()){ + log.debug("Sorting : " + + beans.get(0).getClass().getName() + + " With comparator : " + comparator.getClass().getName()); + } + + try{ + Collections.sort(beans, comparator); + } catch (Exception eee){ + if (log.isWarnEnabled()){ + log.warn("Cant appply comparator : " + comparator.getClass().getName() + + " with entity of type : " + + (beans.isEmpty() ? " vide " : beans.get(0).getClass().getName())); + } + return null; + } + + // Retrieve sorted nodes + children.clear(); + int cnt = 0; + for (T bean : beans){ + if (log.isDebugEnabled()){ + log.debug("Retrieve sorted bean : " + ++cnt + " - " + bean); + } + children.add(toSort.get(bean)); + } + return children; + } + + static final Comparator RENDERER_COMPARATOR = new Comparator() { + @Override + public int compare(Object o1, Object o2) { + try { + String label1 = ((NavigationTreeNode)o1).getRenderer().toString(); + String label2 = ((NavigationTreeNode)o2).getRenderer().toString(); + return label1.compareTo(label2); + } catch (Exception eee) { + return 0; + } + } + }; +}
participants (1)
-
sletellier@users.nuiton.org