Author: sletellier Date: 2010-02-12 19:49:48 +0100 (Fri, 12 Feb 2010) New Revision: 1739 Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationHandler.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModelBuilder.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableHandler.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModel.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModelBuilder.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableNode.java Modified: trunk/jaxx-runtime/pom.xml trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeContextHelper.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHandler.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHelper.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java trunk/pom.xml Log: - Add SwingX dependency - Add implementation to use JXTreeTable with helper using JXPath - TODO : Fix hack to get selected value (in NavigationTreeTableHandler) Modified: trunk/jaxx-runtime/pom.xml =================================================================== --- trunk/jaxx-runtime/pom.xml 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/pom.xml 2010-02-12 18:49:48 UTC (rev 1739) @@ -1,3 +1,4 @@ + <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> @@ -56,6 +57,13 @@ <artifactId>junit</artifactId> </dependency> + <!-- pour utiliser JTreeTable --> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>swingx</artifactId> + </dependency> + </dependencies> <!-- ************************************************************* --> Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationHandler.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationHandler.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationHandler.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,77 @@ +/* + * *##% + * 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.JAXXContext; + +/** + * Interface to create an handler of a navigation tree. + * + * @author sletellier + * @since 2.0.0 + */ +public interface NavigationHandler { + + /** + * Strategy of instanciation of ui. + * <p/> + * For a given {@code node}, the method {@link #getId(NavigationTreeNode)} + * returns the id of ui to use. + */ + public enum Strategy { + + /** + * instanciate a ui for a node + */ + PER_NODE { + + @Override + public String getId(NavigationTreeNode node) { + return node.getFullPath(); + } + }, + /** + * instanciate only one a ui for a type,nodes will share the instanciation + */ + PER_UI_TYPE { + + @Override + public String getId(NavigationTreeNode node) { + return node.getUIClass().getName(); + } + }; + + public abstract String getId(NavigationTreeNode node); + } + + /** + * To get the context will be used by handler + * @return {@link JAXXContext} to use + */ + public JAXXContext getContext(); + + /** + * To get helper will be used by handler + * @return {@link NavigationTreeContextHelper} to use + */ + public NavigationTreeContextHelper getContextHelper(); + +} Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModel.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,151 @@ +/* + * *##% + * 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.JAXXContext; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import java.util.regex.Pattern; + +/** + * Interface to create model of the tree used for a navigation tree. + * <p/> + * Il est composé de {@link NavigationTreeNode} + * + * @author sletellier + * @since 2.0.0 + */ +public interface NavigationModel { + + public Object getRoot(); + + public TreeNode[] getPathToRoot(TreeNode aNode); + + /** + * Search from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#path} valued separated by dot. + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @return the node matching the fully context from the root node, or <code>null</code> if not find. + */ + public NavigationTreeNode findNode(String path); + + /** + * Apply first the regex pattern to obtain the searched node fi the given <code>regex</code> is not null. + * <p/> + * Search then from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. + * <p/> + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @param regex a optional regex to apply to path before searching + * @return the node matching the fully context from the root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(String path, String regex); + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @param regex a optional regex to apply to path before searching + * @return the node matching the fully context from the root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(String path, Pattern regex); + + /** + * Search from a given root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path); + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from a given root node a node named by his fully path (concatenation of nodes) + * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @param regex a previous regex to apply to path : must have a matches + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, String regex); + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from a given root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @param regex a previous regex to apply to path : must have a matches + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, Pattern regex); + + public JAXXContext getContext(); + + /** + * Obtain the associated bean value from context corresponding to node from given navigation path. + * + * @param navigationPath the current context path of the node + * @return the value associated in context with the given navigation path + */ + public Object getBean(String navigationPath); + + /** + * Obtain the associated bean value from context corresponding to node + * + * @param node the current node + * @return the value associated in context with the given node. + */ + public Object getBean(NavigationTreeNode node); + + public void nodeChanged(TreeNode node); + + public void nodeStructureChanged(TreeNode node); + + public void nodeChanged(TreeNode node, boolean deep); + + public String getPathSeparator(); +} Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModelBuilder.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModelBuilder.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationModelBuilder.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,95 @@ +/* + * *##% + * 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.JAXXAction; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.context.JAXXContextEntryDef; +import jaxx.runtime.decorator.Decorator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Enumeration; + +/** + * Interface to create a builder, this object is design to build a {@link NavigationModel}. + * + * @author sletellier + * @since 2.0.0 + */ +public interface NavigationModelBuilder { + + public NavigationModel getModel(); + + public NavigationTreeNode buildEmptyRoot(JAXXContextEntryDef<?> entryDef, String contextName); + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef<?> entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef<?> entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef<?> entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef<?> entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass); + + public NavigationTreeNode removeChildNode(NavigationTreeNode node); + + public void addI18nNodeRenderer(NavigationTreeNode node, String libelle); + + public void addDecoratorNodeRenderer(NavigationTreeNode node, Decorator<?> decorator); + + public void addNodeJaxxClasses( + NavigationTreeNode node, + Class<? extends JAXXObject> uIClass, + Class<? extends JAXXAction> uIHandlerClass); + + public void printModel(NavigationTreeNode node); +} Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeContextHelper.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeContextHelper.java 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeContextHelper.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -25,6 +25,7 @@ import jaxx.runtime.JAXXContext; import jaxx.runtime.JAXXUtil; import jaxx.runtime.context.JAXXContextEntryDef; +import org.jdesktop.swingx.JXTreeTable; /** * To help getting and setting navigation tree objects from a {@link JAXXContext}. @@ -64,16 +65,18 @@ protected JAXXContextEntryDef<String> selectedPathContextEntry; protected JAXXContextEntryDef<Object> selectedBeanContextEntry; protected JAXXContextEntryDef<NavigationTreeNode> selectedNodeContextEntry; - protected JAXXContextEntryDef<NavigationTreeModel> treeModelContextEntry; - protected JAXXContextEntryDef<NavigationTreeHandler> treeHandlerContextEntry; + protected JAXXContextEntryDef<NavigationModel> modelContextEntry; + protected JAXXContextEntryDef<NavigationHandler> handlerContextEntry; protected JAXXContextEntryDef<JTree> treeContextEntry; + protected JAXXContextEntryDef<JXTreeTable> treeTableContextEntry; // protected JAXXContextEntryDef<Component> selectedUIContextEntry; public NavigationTreeContextHelper(String prefix) { this.prefix = prefix; treeContextEntry = JAXXUtil.newContextEntryDef(prefix + "-tree", JTree.class); - treeModelContextEntry = JAXXUtil.newContextEntryDef(prefix + "-tree-model", NavigationTreeModel.class); - treeHandlerContextEntry = JAXXUtil.newContextEntryDef(prefix + "-tree-handler", NavigationTreeHandler.class); + treeTableContextEntry = JAXXUtil.newContextEntryDef(prefix + "-tree-table", JXTreeTable.class); + modelContextEntry = JAXXUtil.newContextEntryDef(prefix + "-model", NavigationModel.class); + handlerContextEntry = JAXXUtil.newContextEntryDef(prefix + "-handler", NavigationHandler.class); selectedBeanContextEntry = JAXXUtil.newContextEntryDef(prefix + "-selected-bean", Object.class); selectedNodeContextEntry = JAXXUtil.newContextEntryDef(prefix + "-selected-node", NavigationTreeNode.class); selectedPathContextEntry = JAXXUtil.newContextEntryDef(prefix + "-selected-path", String.class); @@ -89,16 +92,36 @@ return r; } - public NavigationTreeModel getTreeModel(JAXXContext context) { - NavigationTreeModel r = getTreeModelContextEntry().getContextValue(context); + public JXTreeTable getTreeTable(JAXXContext context) { + JXTreeTable r = getTreeTableContextEntry().getContextValue(context); return r; } - public NavigationTreeHandler getTreeHandler(JAXXContext context) { - NavigationTreeHandler r = getTreeHandlerContextEntry().getContextValue(context); + public NavigationModel getModel(JAXXContext context) { + NavigationModel r = getModelContextEntry().getContextValue(context); return r; } + @Deprecated + public NavigationTreeModel getTreeModel(JAXXContext context) { + NavigationModel r = getModelContextEntry().getContextValue(context); + if (r instanceof NavigationTreeModel){ + return (NavigationTreeModel)r; + } + return null; + } + + /** + * @deprecated please use {@link #getHandler(JAXXContext)}, will be remove soon + * @param context + * @return handler + */ + @Deprecated + public NavigationHandler getTreeHandler(JAXXContext context) { + NavigationHandler r = getTreeHandlerContextEntry().getContextValue(context); + return r; + } + public String getSelectedPath(JAXXContext context) { String r = getSelectedPathContextEntry().getContextValue(context); return r; @@ -119,18 +142,42 @@ // return r; // } - public void setTreeModel(JAXXContext context, NavigationTreeModel model) { - getTreeModelContextEntry().setContextValue(context, model); + /** + * @deprecated please use {@link #setModel(JAXXContext, NavigationModel)}, will be remove soon + * @param context + * @param model + */ + @Deprecated + public void setTreeModel(JAXXContext context, NavigationModel model) { + getModelContextEntry().setContextValue(context, model); } + public void setModel(JAXXContext context, NavigationModel model) { + getModelContextEntry().setContextValue(context, model); + } + public void setTree(JAXXContext context, JTree tree) { getTreeContextEntry().setContextValue(context, tree); } - public void setTreeHandler(JAXXContext context, NavigationTreeHandler handler) { + public void setTreeTable(JAXXContext context, JXTreeTable treeTable) { + getTreeTableContextEntry().setContextValue(context, treeTable); + } + + /** + * @deprecated please use {@link #setHandler(JAXXContext, NavigationHandler)}, will be remove soon + * @param context + * @param handler + */ + @Deprecated + public void setTreeHandler(JAXXContext context, NavigationHandler handler) { getTreeHandlerContextEntry().setContextValue(context, handler); } + public void setHandler(JAXXContext context, NavigationHandler handler) { + getHandlerContextEntry().setContextValue(context, handler); + } + public void setSelectedPath(JAXXContext context, String path) { if (path == null) { getSelectedPathContextEntry().removeContextValue(context); @@ -163,14 +210,19 @@ // } // } - protected JAXXContextEntryDef<NavigationTreeModel> getTreeModelContextEntry() { - return treeModelContextEntry; + protected JAXXContextEntryDef<NavigationModel> getModelContextEntry() { + return modelContextEntry; } - protected JAXXContextEntryDef<NavigationTreeHandler> getTreeHandlerContextEntry() { - return treeHandlerContextEntry; + @Deprecated + protected JAXXContextEntryDef<NavigationHandler> getTreeHandlerContextEntry() { + return handlerContextEntry; } + public JAXXContextEntryDef<NavigationHandler> getHandlerContextEntry() { + return handlerContextEntry; + } + protected JAXXContextEntryDef<Object> getSelectedBeanContextEntry() { return selectedBeanContextEntry; } @@ -187,7 +239,13 @@ return treeContextEntry; } + protected JAXXContextEntryDef<JXTreeTable> getTreeTableContextEntry() { + return treeTableContextEntry; + } + // public JAXXContextEntryDef<Component> getSelectedUIContextEntry() { + // return selectedUIContextEntry; + // } } Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHandler.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHandler.java 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHandler.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -42,7 +42,7 @@ * @author tony * @since 1.7.2 */ -public abstract class NavigationTreeHandler extends DefaultTreeSelectionModel { +public abstract class NavigationTreeHandler extends DefaultTreeSelectionModel implements NavigationHandler{ private static final long serialVersionUID = 1L; /** @@ -50,37 +50,6 @@ */ static private final Log log = LogFactory.getLog(NavigationTreeHandler.class); - /** - * Strategy of instanciation of ui. - * <p/> - * For a given {@code node}, the method {@link #getId(NavigationTreeNode)} - * returns the id of ui to use. - */ - public enum Strategy { - - /** - * instanciate a ui for a node - */ - PER_NODE { - - @Override - public String getId(NavigationTreeNode node) { - return node.getFullPath(); - } - }, - /** - * instanciate only one a ui for a type,nodes will share the instanciation - */ - PER_UI_TYPE { - - @Override - public String getId(NavigationTreeNode node) { - return node.getUIClass().getName(); - } - }; - - public abstract String getId(NavigationTreeNode node); - } /** * UI which contains navigation tree */ @@ -117,10 +86,10 @@ /** * @return le modèle de navigation associé */ - protected abstract NavigationTreeModel getNavigationTreeModel(); + protected abstract NavigationModel getNavigationTreeModel(); /** - * @return le composent actuellement visible associé au noeud courant ou + * @return le composent actuellement visible associé au noeud courant ou * au noeud précédent lors d'un changement de noeud. */ protected abstract Component getCurrentUI(); @@ -163,10 +132,16 @@ */ protected abstract void treateError(Exception e); + /** + * {@see NavigationHandler#getContext() + **/ public JAXXContext getContext() { return context; } + /** + * {@see NavigationHandler#getContextHelper() + **/ public NavigationTreeContextHelper getContextHelper() { return contextHelper; } Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHelper.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHelper.java 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeHelper.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -24,11 +24,13 @@ import java.util.Enumeration; import java.util.regex.Pattern; import javax.swing.JTree; +import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import jaxx.runtime.JAXXContext; import jaxx.runtime.JAXXObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; /** * Helper object associated to a given navigation tree system. @@ -47,12 +49,12 @@ static private final Log log = LogFactory.getLog(NavigationTreeHelper.class); /** - * Create the tree model. + * Create the model. * * @param context the context to associate with fresh model * @return the new model build with data from the given context */ - public abstract NavigationTreeModel createTreeModel(JAXXContext context); + public abstract NavigationModel createTreeModel(JAXXContext context); /** * Create the tree handler. @@ -60,36 +62,36 @@ * @param context the context to associate with fresh handler * @return the new handler */ - public abstract NavigationTreeHandler createTreeHandler(JAXXObject context); + public abstract NavigationHandler createTreeHandler(JAXXObject context); public NavigationTreeHelper(String contextPrefix) { super(contextPrefix); } public Object getContextValue(JAXXContext context, String path) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); return treeModel.getBean(path); } public NavigationTreeNode findNode(JAXXContext context, String path) { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); return treeModel.findNode(path); } public NavigationTreeNode findNode(JAXXContext context, String path, String regex) { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); return treeModel.findNode(path, regex); } public NavigationTreeNode findNode(JAXXContext context, String path, Pattern regex) { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); return treeModel.findNode(path, regex); } public NavigationTreeNode findNode(JAXXContext context, String path, String regex, String suffix) { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); NavigationTreeNode navigationTreeNode = treeModel.findNode(path, regex); if (navigationTreeNode != null && suffix != null) { @@ -100,7 +102,7 @@ public NavigationTreeNode findNode(JAXXContext context, String path, Pattern regex, String suffix) { - NavigationTreeModel treeModel = getSafeTreeModel(context); + NavigationModel treeModel = getSafeModel(context); NavigationTreeNode navigationTreeNode = treeModel.findNode(path, regex); if (navigationTreeNode != null && suffix != null) { @@ -134,7 +136,7 @@ public void selectNode(JAXXContext context, NavigationTreeNode node) { - NavigationTreeModel navigationModel = getSafeTreeModel(context); + NavigationModel navigationModel = getSafeModel(context); if (log.isDebugEnabled()) { log.debug(node); } @@ -224,7 +226,7 @@ * @param deep un flag pour activer la repainte de la descendance du noeud */ public void repaintNode(JAXXContext context, NavigationTreeNode node, boolean deep) { - NavigationTreeModel navigationModel = getSafeTreeModel(context); + NavigationModel navigationModel = getSafeModel(context); if (log.isDebugEnabled()) { log.debug(node); } @@ -240,14 +242,26 @@ } } + @Deprecated public NavigationTreeModel getSafeTreeModel(JAXXContext context) throws NullPointerException { - NavigationTreeModel treeModel = getTreeModel(context); - if (treeModel == null) { - throw new NullPointerException("could not find tree model with key " + getTreeModelContextEntry() + " in context " + context); + NavigationModel model = getModel(context); + if (model == null) { + throw new NullPointerException("could not find tree model with key " + getModelContextEntry() + " in context " + context); } - return treeModel; + if (model instanceof NavigationTreeModel){ + return (NavigationTreeModel) model; + } + return null; } + public NavigationModel getSafeModel(JAXXContext context) throws NullPointerException { + NavigationModel model = getModel(context); + if (model == null) { + throw new NullPointerException("could not find tree model with key " + getModelContextEntry() + " in context " + context); + } + return model; + } + public JTree getSafeTree(JAXXContext context) throws NullPointerException { JTree tree = getTree(context); if (tree == null) { @@ -255,4 +269,12 @@ } return tree; } + + public JXTreeTable getSafeTreeTable(JAXXContext context) throws NullPointerException { + JXTreeTable treeTable = getTreeTable(context); + if (treeTable == null) { + throw new NullPointerException("could not find tree with key " + getTreeTableContextEntry() + " in context " + context); + } + return treeTable; + } } Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -39,7 +39,7 @@ * @author chemit * @since 1.7.2 */ -public class NavigationTreeModel extends DefaultTreeModel { +public class NavigationTreeModel extends DefaultTreeModel implements NavigationModel{ static private final long serialVersionUID = 1L; /** @@ -64,100 +64,51 @@ this.context = context; } + /** + * @see {NavigationModel#getRoot()} + */ @Override public NavigationTreeNode getRoot() { return (NavigationTreeNode) super.getRoot(); } /** - * Search from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#path} valued separated by dot. - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @return the node matching the fully context from the root node, or <code>null</code> if not find. + * @see {NavigationModel#findNode(String)} */ public NavigationTreeNode findNode(String path) { return findNode(getRoot(), path, (Pattern) null); } /** - * Apply first the regex pattern to obtain the searched node fi the given <code>regex</code> is not null. - * <p/> - * Search then from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. - * <p/> - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @param regex a optional regex to apply to path before searching - * @return the node matching the fully context from the root node, or <code>null</code> if not found. + * @see {NavigationModel#findNode(String, String)} */ public NavigationTreeNode findNode(String path, String regex) { return findNode(getRoot(), path, regex); } /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @param regex a optional regex to apply to path before searching - * @return the node matching the fully context from the root node, or <code>null</code> if not found. + * @see {NavigationModel#findNode(String, Pattern)} */ public NavigationTreeNode findNode(String path, Pattern regex) { return findNode(getRoot(), path, regex); } /** - * Search from a given root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + * @see {NavigationModel#findNode(NavigationTreeNode, String)} */ public NavigationTreeNode findNode(NavigationTreeNode root, String path) { return findNode(root, path, (Pattern) null); } /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from a given root node a node named by his fully path (concatenation of nodes) - * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @param regex a previous regex to apply to path : must have a matches - * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + * @see {NavigationModel#findNode(NavigationTreeNode, String, String)} */ public NavigationTreeNode findNode(NavigationTreeNode root, String path, String regex) { return findNode(root, path, regex == null ? null : Pattern.compile(regex)); } /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from a given root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#path} valued separated by {@link #pathSeparator}. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @param regex a previous regex to apply to path : must have a matches - * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + * @see {NavigationModel#findNode(NavigationTreeNode, String, Pattern)} */ public NavigationTreeNode findNode(NavigationTreeNode root, String path, Pattern regex) { if (regex != null) { @@ -186,15 +137,15 @@ return result; } + /** + * @see {NavigationModel#getContext()} + */ public JAXXContext getContext() { return context; } /** - * Obtain the associated bean value from context corresponding to node from given navigation path. - * - * @param navigationPath the current context path of the node - * @return the value associated in context with the given navigation path + * @see {NavigationModel#getBean(String)} */ public Object getBean(String navigationPath) { Object result; @@ -204,10 +155,7 @@ } /** - * Obtain the associated bean value from context corresponding to node - * - * @param node the current node - * @return the value associated in context with the given node. + * @see {NavigationModel#getBean(NavigationTreeNode)} */ public Object getBean(NavigationTreeNode node) { if (node == null) { @@ -218,6 +166,9 @@ return node.getBean(getContext()); } + /** + * @see {NavigationModel#nodeChanged(TreeNode)} + */ @Override public void nodeChanged(TreeNode node) { nodeChanged(node, false); @@ -226,6 +177,9 @@ } } + /** + * @see {NavigationModel#nodeStructureChanged(TreeNode)} + */ @Override public void nodeStructureChanged(TreeNode node) { NavigationTreeNode n = (NavigationTreeNode) node; @@ -237,6 +191,9 @@ } } + /** + * @see {NavigationModel#nodeChanged(TreeNode, boolean)} + */ public void nodeChanged(TreeNode node, boolean deep) { NavigationTreeNode n = (NavigationTreeNode) node; @@ -264,6 +221,9 @@ } } + /** + * @see {NavigationModel#getPathSeparator()} + */ public String getPathSeparator() { return pathSeparator; } Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -31,11 +31,13 @@ /** * This object is design to build a {@link NavigationTreeModel}. + * + * @see NavigationModelBuilder * * @author chemit * @since 17.2 */ -public class NavigationTreeModelBuilder { +public class NavigationTreeModelBuilder implements NavigationModelBuilder{ /** * Logger @@ -95,6 +97,7 @@ Class<? extends JAXXObject> uiClass, Class<? extends JAXXAction> actionClass) { NavigationTreeNode node = new NavigationTreeNode(model.pathSeparator, contextName, entryDef); + // TODO : Must be : NavigationTreeNode node = new NavigationTreeNode(model.pathSeparator, contextName, null, entryDef); ??? addI18nNodeRenderer(node, libelle); addNodeJaxxClasses(node, uiClass, actionClass); return addChildNode(parentNode, node); Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableHandler.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableHandler.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableHandler.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,253 @@ +/* + * *##% + * 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.JAXXAction; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.context.JAXXInitialContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; + +/** + * The handler of a navigation tree table. + * + * This is also the selection model to use, since we must check before moving + * from a node we can not just listen selection model changed, we must control + * it. + * + * TODO : Chercher une solution pour limiter le copier/coller.... @see {NavigationTreeHandler} + * + * @author sletellier + * @since 2.0.0 + */ +public abstract class NavigationTreeTableHandler extends DefaultListSelectionModel implements NavigationHandler { + + private static final long serialVersionUID = 1L; + /** + * Logger + */ + static private final Log log = LogFactory.getLog(NavigationTreeTableHandler.class); + + /** + * UI which contains navigation tree + */ + protected JAXXContext context; + /** + * UI Instanciation strategy + */ + protected Strategy strategy; + /** + * JAXXContext access helper. + * + * @since 1.7.2 + */ + protected NavigationTreeContextHelper contextHelper; + + protected NavigationTreeTableHandler(String contextPrefix, final JAXXObject context, Strategy strategy, TreeSelectionModel selectModel) { + this.contextHelper = new NavigationTreeContextHelper(contextPrefix); + this.context = context; + this.strategy = strategy; + addListSelectionListener(new ListSelectionListener(){ + @Override + public void valueChanged(ListSelectionEvent event) { + log.info("Value changed old : " + event.getFirstIndex() + " last " + event.getLastIndex() + " source " + event.getSource()); + if (event.getSource() == null || !event.getValueIsAdjusting()) { + // do not treate this if no path changed + return; + } + + // FIXME : event.getSource devrais retourner le navigationTreeNode.... + NavigationTreeNode node = (NavigationTreeNode) contextHelper.getTreeTable(context).getModel().getValueAt(event.getLastIndex(), 0); + selectNodeUI(node); + } + }); + } + + /** + * @return le modèle de navigation associé + */ + protected abstract NavigationModel getNavigationTreeModel(); + + /** + * @return le composent actuellement visible associé au noeud courant ou + * au noeud précédent lors d'un changement de noeud. + */ + protected abstract Component getCurrentUI(); + + /** + * @param node le noeud associé à l'ui à retrouver + * @return l'ui associé au novueau noeud sélectionné + */ + protected abstract Component getUI(NavigationTreeNode node); + + /** + * @param component le composent actuellement visible + * @return <code>true</code> si le composent a bien été fermé, <code>false</code> sinon + * @throws Exception if any + */ + protected abstract boolean closeUI(Component component) throws Exception; + + /** + * Instancie une nouvelle ui associé à un noeud de l'arbre de navigation + * + * @param node le noeud associé à l'ui à créer + * @return la nouvelle ui associée au noeud + * @throws Exception if any + */ + protected abstract Component createUI(NavigationTreeNode node) throws Exception; + + /** + * Ouvre l'ui associée au noeud sélectionné dans l'arbre de navigation. + * + * @param newUI l'ui associé au noeud sélectionné à ouvrir + * @param node le node de l'ui a ouvrir + * @throws Exception if any + */ + protected abstract void openUI(Component newUI, NavigationTreeNode node) throws Exception; + + /** + * Traitement des exceptions. + * + * @param e l'erreur recontrée (ou null si pas d"erreur) + */ + protected abstract void treateError(Exception e); + + /** + * @see NavigationHandler#getContext() + */ + public JAXXContext getContext() { + return context; + } + + /** + * @see NavigationHandler#getContextHelper() + */ + public NavigationTreeContextHelper getContextHelper() { + return contextHelper; + } + + protected void selectNodeUI(NavigationTreeNode node) { + + try { + + String path = node.getFullPath(); + + if (log.isTraceEnabled()) { + log.trace(path); + } + + Component newUI = getUI(node); + + // now, we are free to open the ui associated with the selected node in navigation + + // get the bean associated with the node + Object data = getNavigationTreeModel().getBean(path); + + // save it in context (must be done before init ui) + addSelectedBeanInContext(node, data); + + if (newUI == null) { + + // a new ui instance is required + newUI = createUI(node); + } + + JAXXContext ctxt = getContext(); + NavigationTreeContextHelper helper = getContextHelper(); + + // save in context current node context path + helper.setSelectedPath(ctxt, node.getFullPath()); + + // save in context current node + helper.setSelectedNode(ctxt, node); + + // save in context current ui +// helper.setSelectedUI(ctxt, newUI); + + // really open the ui associated with the selected node + // init ui before to be visible + if (newUI instanceof NavigationContentUI) { + ((NavigationContentUI) newUI).openUI(node); + } + + // set ui in content + openUI(newUI, node); + + } catch (Exception e) { + // remove data from context + + // if any error, go back to previvous node + treateError(e); + } + } + + /** + * Prepare le context a utiliser pour initialiser une nouvelle ui. + * + * @param node le noeud associé à l'ui à créer + * @return le context à utiliser pour instancier l'ui + * @throws Exception if any + */ + protected JAXXContext createUIContext(NavigationTreeNode node) throws Exception { + + if (node.getUIHandlerClass() == null) { + if (log.isWarnEnabled()) { + log.warn("no action associated with ui " + node.getUIClass()); + } + // no action associated, just + return getContext(); + } + + JAXXAction action = node.getUIHandlerClass().newInstance(); + + // init context with + JAXXInitialContext uiContext = action.init(getContext()); + return uiContext; + } + + protected void addSelectedBeanInContext(NavigationTreeNode node, Object data) { + + if (log.isDebugEnabled()) { + log.debug("find data for contextPath <" + node.getFullPath() + "> : " + (data == null ? null : data.getClass())); + } + JAXXContext ctxt = getContext(); + NavigationTreeContextHelper helper = getContextHelper(); + + // remove previous selected bean + //TODO-TC-20091004 should have an automatic clean context method while + helper.setSelectedBean(ctxt, null); + + if (data != null) { + + helper.setSelectedBean(ctxt, data); + } + } +} Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModel.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModel.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,314 @@ +/* + * *##% + * 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.JAXXContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.tree.TreeModelSupport; +import org.jdesktop.swingx.treetable.DefaultTreeTableModel; +import org.jdesktop.swingx.treetable.MutableTreeTableNode; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.table.TableModel; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.Enumeration; +import java.util.List; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Model of the tree used for a navigation tree table. + * <p/> + * Il est composé de {@link NavigationTreeNode} + * + * @author sletellier + * @since 2.0.0 + */ +public class NavigationTreeTableModel extends DefaultTreeTableModel implements NavigationModel { + + static private final long serialVersionUID = 1L; + + /** + * Logger + */ + static private final Log log = LogFactory.getLog(NavigationTreeTableModel.class); + + /** + * The path separator used to build the {@link NavigationTreeNode#fullPath}. + * + * @see NavigationTreeNode#getNodePath() + * @see NavigationTreeNode#getFullPath() + */ + protected final String pathSeparator; + + /** + * Context to retrieve beans + */ + private JAXXContext context; + + protected List<String> columnsName; + + public NavigationTreeTableModel(String pathSeparator, JAXXContext context, List<String> columnsName) { + super(null); + this.pathSeparator = pathSeparator; + this.context = context; + this.columnsName = columnsName; + } + + /** + * @see NavigationModel#getRoot() + */ + public NavigationTreeTableNode getRoot() { + return (NavigationTreeTableNode) super.root; + } + + public TreeNode[] getPathToRoot(TreeNode aNode) { + if (aNode == null){ + return null; + } + return super.getPathToRoot((TreeTableNode)aNode); + + } + + public void setRoot(NavigationTreeTableNode root) { + this.root = root; + getModelSupport().fireNewRoot(); + } + + /** + * Message this to remove node from its parent. This will message + * nodesWereRemoved to create the appropriate event. This is the preferred + * way to remove a node as it handles the event creation for you. + */ + public void removeNodeFromParent(MutableTreeNode node) { + MutableTreeTableNode parent = (MutableTreeTableNode) node.getParent(); + + if (parent == null) { + throw new IllegalArgumentException("node does not have a parent."); + } + + int index = parent.getIndex(node); + node.removeFromParent(); + + modelSupport.fireChildRemoved(new TreePath(getPathToRoot(parent)), + index, node); + } + + /** + * @see NavigationModel#findNode(String) + */ + public NavigationTreeNode findNode(String path) { + return findNode(getRoot(), path, (Pattern) null); + } + + /** + * @see NavigationModel#findNode(String, String) + */ + public NavigationTreeNode findNode(String path, String regex) { + return findNode(getRoot(), path, regex); + } + + /** + * @see NavigationModel#findNode(String, Pattern) + */ + public NavigationTreeNode findNode(String path, Pattern regex) { + return findNode(getRoot(), path, regex); + } + + /** + * @see NavigationModel#findNode(NavigationTreeNode, String) + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path) { + return findNode(root, path, (Pattern) null); + } + + /** + * @see NavigationModel#findNode(NavigationTreeNode, String, String) + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, String regex) { + return findNode(root, path, regex == null ? null : Pattern.compile(regex)); + } + + /** + * @see NavigationModel#findNode(NavigationTreeNode, String, Pattern) + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, Pattern regex) { + if (regex != null) { + Matcher matcher = regex.matcher(path); + if (!matcher.matches() || matcher.groupCount() < 1) { + log.warn("no matching regex " + regex + " to " + path); + return null; + } + path = matcher.group(1); + if (log.isDebugEnabled()) { + log.debug("matching regex " + regex + " : " + path); + } + } + StringTokenizer stk = new StringTokenizer(path, pathSeparator); + NavigationTreeNode result = root; + // pas the first token (matches the root node) + if (root.isRoot() && stk.hasMoreTokens()) { + String rootPath = stk.nextToken(); + if (!rootPath.equals(root.getNodePath())) { + return null; + } + } + while (stk.hasMoreTokens()) { + result = result.getChild(stk.nextToken()); + } + return result; + } + + /** + * @see NavigationModel#getContext() + */ + public JAXXContext getContext() { + return context; + } + + /** + * @see NavigationModel#getBean(String) + */ + public Object getBean(String navigationPath) { + Object result; + NavigationTreeNode node = findNode(navigationPath, (Pattern) null); + result = getBean(node); + return result; + } + + /** + * @see NavigationModel#getBean(NavigationTreeNode) + */ + public Object getBean(NavigationTreeNode node) { + if (node == null) { + return null; + //fixme should throw a NPE exception + //throw new NullPointerException("node can not be null"); + } + return node.getBean(getContext()); + } + + + /** + * Accessor to tree model support. + * + * @return tree model support + */ + protected TreeModelSupport getModelSupport() { + return modelSupport; + } + + /** + * @see NavigationModel#nodeChanged(TreeNode) + */ + public void nodeChanged(TreeNode node) { + if (node != null){ + MutableTreeNode parent = (MutableTreeNode)node.getParent(); + TreeNode[] treeNodes = getPathToRoot(parent); + if (treeNodes != null){ + modelSupport.fireChildChanged(new TreePath(treeNodes), parent.getIndex(node), node); + } else { + log.error("[Node changed] Path to root is null !"); + } + reload((NavigationTreeTableNode)node, true); + } else { + log.error("Node is null !"); + } + } + + /** + * @see NavigationModel#nodeStructureChanged(TreeNode) + */ + public void nodeStructureChanged(TreeNode node) { + if (node != null){ + MutableTreeNode parent = (MutableTreeNode)node.getParent(); + TreeNode[] treeNodes = getPathToRoot(parent); + if (treeNodes != null){ + modelSupport.fireTreeStructureChanged(new TreePath(treeNodes)); + } else { + log.error("[Node structure changed] Path to root is null !"); + } + reload((NavigationTreeTableNode)node, true); + } else { + log.error("Node is null !"); + } + } + + /** + * @see NavigationModel#nodeChanged(TreeNode, boolean) + */ + public void nodeChanged(TreeNode node, boolean deep) { + if (node != null){ + MutableTreeNode parent = (MutableTreeNode)node.getParent(); + TreeNode[] treeNodes = getPathToRoot(parent); + if (treeNodes != null){ + modelSupport.fireChildChanged(new TreePath(treeNodes), parent.getIndex(node), node); + } else { + log.error("[Node changed] Path to root is null !"); + } + reload((NavigationTreeTableNode)node, deep); + } else { + log.error("Node is null !"); + } + } + + protected void reload(NavigationTreeTableNode node) { + reload(node, false); + } + + protected void reload(NavigationTreeTableNode node, boolean deep) { + if (node == null) { + return; + } + node.reload(getContext()); + + if (deep) { + Enumeration<?> childs = node.children(); + while (childs.hasMoreElements()) { + NavigationTreeTableNode o = (NavigationTreeTableNode) childs.nextElement(); + reload(o, true); + } + } + } + + /** + * @see NavigationModel#getPathSeparator() + */ + public String getPathSeparator() { + return pathSeparator; + } + + @Override + public int getColumnCount(){ + return columnsName.size(); + } + + @Override + public String getColumnName(int column){ + return columnsName.get(column); + } + +} Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModelBuilder.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModelBuilder.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableModelBuilder.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,264 @@ +/* + * *##% + * 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.JAXXAction; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.context.JAXXContextEntryDef; +import jaxx.runtime.decorator.Decorator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Enumeration; + +/** + * This object is design to build a {@link NavigationTreeTableModel}. + * + * @see NavigationModelBuilder + * + * @author sletellier + * @since 2.0.0 + */ +public abstract class NavigationTreeTableModelBuilder implements NavigationModelBuilder{ + + /** + * Logger + */ + static private final Log log = LogFactory.getLog(NavigationTreeModelBuilder.class); + /** + * The model dealed by the builder. + * + * <b>Note:</b> It is a good idea to keep only one instance of the model. + * If reset is required, should empty the model but not reinstanciate it. + */ + protected NavigationTreeTableModel model; + /** + * default ui class to use if node does not define an ui class + */ + protected Class<? extends JAXXObject> defaultUIClass; + /** + * [optional] default action class + */ + protected Class<? extends JAXXAction> defaultUIHandlerClass; + + public NavigationTreeTableModelBuilder(Class<? extends JAXXObject> defaultUIClass, Class<? extends JAXXAction> defaultUIHandlerClass, NavigationTreeTableModel model) { + this.defaultUIClass = defaultUIClass; + this.defaultUIHandlerClass = defaultUIHandlerClass; + this.model = model; + } + + public NavigationTreeTableModel getModel() { + return model; + } + + public NavigationTreeNode buildEmptyRoot(JAXXContextEntryDef<?> entryDef, String contextName) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, entryDef, null); + addI18nNodeRenderer(node, ""); + return addChildNode(null, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef<?> entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, entryDef, entryPath); + addI18nNodeRenderer(node, libelle); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef<?> entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, entryDef, null); + addI18nNodeRenderer(node, libelle); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, null, entryPath); + addI18nNodeRenderer(node, libelle); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef<?> entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, entryDef, entryPath); + addDecoratorNodeRenderer(node, decorator); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef<?> entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, entryDef, null); + addDecoratorNodeRenderer(node, decorator); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeTableNode node = createNavigationTreeTableNode(model.pathSeparator, contextName, null, entryPath); + addDecoratorNodeRenderer(node, decorator); + addNodeJaxxClasses(node, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + protected NavigationTreeNode addChildNode(NavigationTreeNode parentNode, NavigationTreeTableNode node) { + + if (node.getUIClass() == null) { + // no ui is associated with this node, use the default one + node.setUIClass(defaultUIClass); + } + + if (node.getUIHandlerClass() == null) { + // no ui handler associated with this node, use the default one + node.setUIHandlerClass(defaultUIHandlerClass); + } + if (parentNode == null) { + model.setRoot(node); + } else { + parentNode.add(node); + } + model.nodeStructureChanged(node); + return node; + } + + public NavigationTreeNode removeChildNode(NavigationTreeNode node) { + NavigationTreeNode parentNode = node.getParent(); + model.removeNodeFromParent(node); + return parentNode; + } + + public void addI18nNodeRenderer(NavigationTreeNode node, String libelle) { + node.setRenderer(new NavigationTreeNodeRendererI18nImpl(libelle)); + } + + public void addDecoratorNodeRenderer(NavigationTreeNode node, Decorator<?> decorator) { + node.setRenderer(new NavigationTreeNodeRendererDecoratorImpl(decorator)); + } + + public void addNodeJaxxClasses( + NavigationTreeNode node, + Class<? extends JAXXObject> uIClass, + Class<? extends JAXXAction> uIHandlerClass) { + node.setUIClass(uIClass); + node.setUIHandlerClass(uIHandlerClass); + } + + public void printModel(NavigationTreeNode node) { + if (node == null) { + return; + } + log.info("node " + node.getFullPath() + ", jxpath: " + node.getJaxxContextEntryPath() + ", entryContextDef: " + node.getJaxxContextEntryDef()); + if (log.isDebugEnabled()) { + log.debug("node userObject" + node.getUserObject()); + log.debug("value from node " + node.getBean(getModel().getContext())); + log.debug("value from model " + getModel().getBean(node)); + } + Enumeration<?> children = node.children(); + while (children.hasMoreElements()) { + printModel((NavigationTreeNode) children.nextElement()); + } + } + + // To create your own instance of NavigationTreeTableNode + public abstract NavigationTreeTableNode createNavigationTreeTableNode(String pathSeparator, String contextName, JAXXContextEntryDef<?> jaxxContextEntryDef, String jaxxContextEntryPath); + + public static abstract class ChildBuilder<O> { + + protected NavigationTreeModelBuilder builder; + + protected ChildBuilder(NavigationTreeModelBuilder builder) { + this.builder = builder; + } + + protected abstract void init(Class<? extends O> klass); + + protected abstract Decorator<? extends O> getDecorator(O child); + + protected abstract String getJXPath(O child); + + protected abstract String getNavigationPath(O child); + + public void build(NavigationTreeNode parent, boolean cacheValues, Class<? extends O> klass, java.util.Collection<? extends O> beans, Class<? extends JAXXObject> ui, Class<? extends JAXXAction> actionClass) { + + if (beans == null || beans.isEmpty()) { + // no bean to treate + return; + } + + init(klass); + + NavigationTreeNode node; + + for (O o : beans) { + node = builder.build(parent, getDecorator(o), getJXPath(o), getNavigationPath(o), ui, actionClass); + if (cacheValues) { + // cache the bean value to improve performance + node.setBean(o); + } + } + } + + public void build(NavigationTreeNode parent, boolean cacheValues, Class<? extends O> klass, O[] beans, Class<? extends JAXXObject> ui, Class<? extends JAXXAction> actionClass) { + + if (beans == null || beans.length == 0) { + // no bean to treate + return; + } + + init(klass); + + NavigationTreeNode node; + + for (O o : beans) { + node = builder.build(parent, getDecorator(o), getJXPath(o), getNavigationPath(o), ui, actionClass); + if (cacheValues) { + // cache the bean value to improve performance + node.setBean(o); + } + } + } + } +} Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableNode.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableNode.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeTableNode.java 2010-02-12 18:49:48 UTC (rev 1739) @@ -0,0 +1,78 @@ +/* + * *##% + * 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.context.JAXXContextEntryDef; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import java.util.Enumeration; + +/** + * Node of the {@link NavigationTreeTableModel}. + * + * @see NavigationTreeNode + * + * @author sletellier + * @since 2.0.0 + */ +public abstract class NavigationTreeTableNode extends NavigationTreeNode implements TreeTableNode{ + + public NavigationTreeTableNode(String pathSeparator, String navigationPath, Object jaxxContextEntryDef) { + super(pathSeparator, navigationPath, jaxxContextEntryDef); + } + + public NavigationTreeTableNode(String pathSeparator, String navigationPath, JAXXContextEntryDef<?> jaxxContextEntryDef, String jaxxContextEntryPath) { + super(pathSeparator, navigationPath, jaxxContextEntryDef, jaxxContextEntryPath); + } + + @Override + public NavigationTreeTableNode getChildAt(int index) { + return (NavigationTreeTableNode) super.getChildAt(index); + } + + @Override + public NavigationTreeTableNode getParent() { + return (NavigationTreeTableNode) super.getParent(); + } + + /** + * @see NavigationTreeNode#getChild(String) + */ + @Override + public NavigationTreeTableNode getChild(String path) { + Enumeration<?> childs = children(); + while (childs.hasMoreElements()) { + NavigationTreeTableNode son = (NavigationTreeTableNode) childs.nextElement(); + if (path.equals(son.getNodePath())) { + return son; + } + } + return null; + } + + public abstract Object getValueAt(int column); + + public abstract int getColumnCount(); + + public abstract boolean isEditable(int column); + + public abstract void setValueAt(Object aValue, int column); +} Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2010-02-08 15:58:19 UTC (rev 1738) +++ trunk/pom.xml 2010-02-12 18:49:48 UTC (rev 1739) @@ -249,6 +249,7 @@ <groupId>org.swinglabs</groupId> <artifactId>swingx</artifactId> <version>1.6</version> + <scope>compile</scope> </dependency> <!--dependency>