r2010 - in trunk: jaxx-demo/src/main/java/jaxx/demo jaxx-demo/src/main/java/jaxx/demo/component/jaxx jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable jaxx-demo/src/main/java/jaxx/demo/tree jaxx-runtime/src/main/java/jaxx/runtime/swing/nav jaxx-runtim
Author: sletellier Date: 2010-06-30 00:50:39 +0200 (Wed, 30 Jun 2010) New Revision: 2010 Url: http://nuiton.org/repositories/revision/jaxx/2010 Log: - Refactor tree package to nav pakage - Rename classes with nav in name - Fix javadocs (first pass) Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemo.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoDataProvider.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoHelper.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/AbstractContentUI.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorContentUI.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorsContentUI.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MovieContentUI.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MoviesContentUI.jaxx trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/ActorsNodeLoadors.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/MoviesNodeLoadors.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoCellRenderer.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoNode.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoModel.java trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoNode.java trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNavHelper.java Removed: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/tree/ trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeHelper.java Modified: trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxDelegateTreeModel.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNode.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNodeChildLoador.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNode.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNodeChildLoador.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableModel.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNode.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNodeChildLoador.java Modified: trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -25,7 +25,7 @@ package jaxx.demo; -import jaxx.demo.component.jaxx.tree.JaxxTreeDemo; +import jaxx.demo.component.jaxx.nav.JaxxNavDemo; import jaxx.runtime.JAXXUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -228,7 +228,7 @@ DEMO_PATH( "ui.demo.path", _("jaxxdemo.config.ui.demo.path"), - "jaxxdemo.tree/jaxxdemo.tree.component.jaxx/jaxxdemo.tree.component.jaxx.tree/" + JaxxTreeDemo.class.getSimpleName(), + "jaxxdemo.tree/jaxxdemo.tree.component.jaxx/jaxxdemo.tree.component.jaxx.tree/" + JaxxNavDemo.class.getSimpleName(), String.class, false, true); Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemo.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemo.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemo.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,254 @@ +<!-- + #%L + JAXX :: Demo + $Id: FullNavigationTreeDemo.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.decorator.DecoratorProvider + jaxx.demo.component.jaxx.nav.content.ActorContentUI + jaxx.demo.component.jaxx.nav.content.ActorsContentUI + jaxx.demo.component.jaxx.nav.content.MovieContentUI + jaxx.demo.component.jaxx.nav.content.MoviesContentUI + jaxx.demo.component.jaxx.nav.tree.JaxxTreeDemoCellRenderer + jaxx.demo.component.jaxx.nav.tree.JaxxTreeDemoNode + jaxx.demo.component.jaxx.nav.treetable.JaxxTreeTableDemoNode + jaxx.demo.entities.Movie + jaxx.demo.entities.People + javax.swing.tree.TreePath + java.lang.reflect.Constructor + jaxx.demo.component.jaxx.nav.content.AbstractContentUI + org.jdesktop.swingx.JXTreeTable + jaxx.runtime.swing.nav.JaxxNode + </import> + + <CardLayout2 id='contentLayout'/> + + <script><![CDATA[ +private JaxxNavDemoDataProvider dataProvider = new JaxxNavDemoDataProvider(); +private JaxxNavDemoHelper<JaxxTreeDemoNode> treeHelper = new JaxxNavDemoHelper<JaxxTreeDemoNode>(dataProvider); +private JaxxNavDemoHelper<JaxxTreeTableDemoNode> treeTableHelper = new JaxxNavDemoHelper<JaxxTreeTableDemoNode>(dataProvider); + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), + "JaxxNavDemoHelper.java", + "tree/JaxxTreeDemoNode.java", + "tree/JaxxTreeDemoCellRenderer.java", + "treetable/JaxxTreeTableDemoModel.java", + "treetable/JaxxTreeTableDemoNode.java", + "loadors/ActorsNodeLoadors.java", + "loadors/MoviesNodeLoadors.java"}; +} + +private void $afterCompleteSetup() { + setContextValue(treeHelper, "treeHelper"); + setContextValue(treeTableHelper, "treeTableHelper"); + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + JaxxTreeDemoNode demoNode = (JaxxTreeDemoNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeTableSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + JaxxTreeTableDemoNode demoNode = (JaxxTreeTableDemoNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + // Register decorator + DecoratorProvider decoratorProvider = getContextValue(DecoratorProvider.class); + + // Attach renderer + navigationTree.setCellRenderer(new JaxxTreeDemoCellRenderer(decoratorProvider, dataProvider)); + + // Register tree + treeHelper.setTree(navigationTree, true, treeSelectionListener); + + // Register tree table + treeTableHelper.setTreeTable(navigationTreeTable, true, treeTableSelectionListener); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + navigationTree.setSelectionInterval(0, 0); + splitPane.resetToPreferredSizes(); + } + }); + + // expand the tree + SwingUtil.expandTree(navigationTree); + SwingUtil.expandTreeTable(navigationTreeTable); + + // auto-expand demoNode when selected + SwingUtil.addExpandOnClickListener(navigationTree); + SwingUtil.addExpandOnClickListener(navigationTreeTable); +} + +protected void openUI(JaxxNode demoNode) { + + // Get demoNode type + Class<?> editType = demoNode.getInternalClass(); + String id = demoNode.getId(); + + // If it's category demoNode + if (editType.equals(String.class)) { + + // Actors categorie demoNode + if (JaxxNavDemoHelper.ACTORS_CATEGORY_NODE.equals(id)) { + + java.util.List<People> peoples = dataProvider.getPeoples(); + showUI(peoples, ActorsContentUI.class); + + // Movies categorie demoNode + } else if (JaxxNavDemoHelper.MOVIES_CATEGORY_NODE.equals(id)) { + + java.util.List<Movie> movies = dataProvider.getMovies(); + showUI(movies, MoviesContentUI.class); + } + + // People demoNode + } else if (editType.equals(People.class)) { + People people = dataProvider.getPeople(id); + showUI(people, ActorContentUI.class); + + // Movie demoNode + } else if (editType.equals(Movie.class)) { + Movie movie = dataProvider.getMovie(id); + showUI(movie, MovieContentUI.class); + } +} + +// Create by introspection content ui +protected <B> void showUI(B bean, Class<? extends AbstractContentUI> uiClass) { + + // Verify if instance is existing + AbstractContentUI ui = getContentIfExist(uiClass); + + // Get layout identifier + String contentName = uiClass.getName(); + + if (ui == null) { + try { + // Get constructor + Constructor<? extends AbstractContentUI> constructor = + uiClass.getConstructor(JAXXContext.class); + + // Invoke instance creation + ui = constructor.newInstance(this); + } catch (Exception eee) { + log.error(eee); + ErrorDialogUI.showError(eee); + } + + // Add to content panel + content.add(ui, contentName); + } + + // Attach bean + ui.setData(bean); + + // show ui + contentLayout.show(content, contentName); +} + +// Get content if exist in content, else return null +protected <E extends Component> E getContentIfExist(Class<E> uiClass) { + String contentName = uiClass.getName(); + if (log.isDebugEnabled()) { + log.debug("Get content if exist " + contentName); + } + if (!contentLayout.contains(contentName)) { + return null; + } + return (E) contentLayout.getComponent(content, contentName); +} + ]]> + </script> + + <JSplitPane id='splitPane' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JTabbedPane> + <tab title='jaxxdemo.tree.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JTree id="navigationTree" + font-size='11' + rootVisible='false' + showsRootHandles='false' + model='{treeHelper.createTreeModel()}'/> + + </JScrollPane> + </tab> + <tab title='jaxxdemo.treeTable.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JXTreeTable id="navigationTreeTable" + font-size='11' + rootVisible='false' + showsRootHandles='false' + treeTableModel='{treeTableHelper.createTreeTableModel()}'/> + + </JScrollPane> + </tab> + </JTabbedPane> + + <JPanel id="content" layout="{contentLayout}"/> + + </JSplitPane> + +</jaxx.demo.DemoPanel> Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoDataProvider.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoDataProvider.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoDataProvider.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,112 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav; + +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.DataProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxNavDemoDataProvider implements DataProvider { + + /** Logger */ + static private final Log log = LogFactory.getLog(JaxxNavDemoDataProvider.class); + + protected Map<String, Movie> movies; + + protected Map<String, People> peoples; + + public JaxxNavDemoDataProvider() { + + movies = new HashMap<String, Movie>(); + peoples = new HashMap<String, People>(); + + log.info("for " + this); + People a = new People("0", "Jack", "Black", 0, "/jaxx/demo/images/jack.jpg"); + People a2 = new People("1", "Héctor", "Jiménez", 0, "/jaxx/demo/images/hector.jpg"); + People a3 = new People("2", "Ana", "de la Reguera", 0, "/jaxx/demo/images/ana.jpg"); + + Movie m = new Movie("0", "Nacho libre", 1996, "/jaxx/demo/images/nacho.jpg"); + m.addActor(a); + m.addActor(a2); + m.addActor(a3); + + Movie m2 = new Movie("1", "Nacho 2", 2009, "/jaxx/demo/images/nacho2.png"); + m2.addActor(a); + m2.addActor(a2); + + movies.put(m.getId(), m); + movies.put(m2.getId(), m2); + + peoples.put(a.getId(), a); + peoples.put(a2.getId(), a2); + peoples.put(a3.getId(), a3); + } + + @Override + public boolean isEnabled() { + return true; + } + + public Movie getMovie(String id) { + return movies.get(id); + } + + public People getPeople(String id) { + return peoples.get(id); + } + + public List<Movie> getMovies() { + return new ArrayList<Movie>(movies.values()); + } + + public List<People> getPeoples() { + return new ArrayList<People>(peoples.values()); + } + + public List<People> getPeoples(Movie m) { + return m.getActors(); + } + + public List<People> getPeoples(String moviesId) { + + if (log.isDebugEnabled()) { + log.debug("Get people for movie " + moviesId); + } + + return movies.get(moviesId).getActors(); + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoHelper.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoHelper.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/JaxxNavDemoHelper.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,141 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav; + +import jaxx.demo.component.jaxx.nav.tree.JaxxTreeDemoNode; +import jaxx.demo.component.jaxx.nav.treetable.JaxxTreeTableDemoModel; +import jaxx.demo.component.jaxx.nav.treetable.JaxxTreeTableDemoNode; +import jaxx.demo.component.jaxx.nav.loadors.ActorsNodeLoadors; +import jaxx.demo.component.jaxx.nav.loadors.MoviesNodeLoadors; +import jaxx.runtime.swing.nav.JaxxNavHelper; +import jaxx.runtime.swing.nav.JaxxNode; +import jaxx.runtime.swing.nav.treetable.JaxxTreeTableModel; +import jaxx.runtime.swing.nav.JaxxDelegateTreeModel; + +import javax.swing.tree.DefaultTreeModel; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxNavDemoHelper<N extends JaxxNode<N>> extends JaxxNavHelper<N> { + + public static String MOVIES_CATEGORY_NODE = "movies"; + + public static String ACTORS_CATEGORY_NODE = "actors"; + + public JaxxNavDemoHelper(JaxxNavDemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public JaxxNavDemoDataProvider getDataProvider() { + return (JaxxNavDemoDataProvider)dataProvider; + } + + @SuppressWarnings({"unchecked"}) + public DefaultTreeModel createTreeModel() { + + // Create root static node + JaxxNode root = new JaxxTreeDemoNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + JaxxNode moviesCategoryNode = new JaxxTreeDemoNode( + String.class, + n_(MOVIES_CATEGORY_NODE), + null, + new MoviesNodeLoadors<JaxxTreeDemoNode>() + ); + + // Create peoples category node + JaxxNode peoplesCategoryNode = new JaxxTreeDemoNode( + String.class, + n_(ACTORS_CATEGORY_NODE), + null, + new ActorsNodeLoadors<JaxxTreeDemoNode>() + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + JaxxDelegateTreeModel<N> model = createTreeModel((N) root); + + // Populate childs nodes + root.populateChilds(model, getDataProvider()); + + return getTreeModel(); + } + + @SuppressWarnings({"unchecked"}) + public JaxxTreeTableModel createTreeTableModel() { + + // Create root static node + JaxxNode root = new JaxxTreeTableDemoNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + JaxxNode moviesCategoryNode = new JaxxTreeTableDemoNode( + String.class, + n_(MOVIES_CATEGORY_NODE), + null, + new MoviesNodeLoadors<JaxxTreeTableDemoNode>(true) + ); + + // Create peoples category node + JaxxNode peoplesCategoryNode = new JaxxTreeTableDemoNode( + String.class, + n_(ACTORS_CATEGORY_NODE), + null, + new ActorsNodeLoadors<JaxxTreeTableDemoNode>(true) + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + JaxxTreeTableDemoModel delegate = new JaxxTreeTableDemoModel(getDataProvider()); + JaxxDelegateTreeModel model = createTreeTableModel(delegate, (N) root); + + // Populate childs nodes + root.populateChilds(model, getDataProvider()); + + return getTreeTableModel(); + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/AbstractContentUI.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/AbstractContentUI.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/AbstractContentUI.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,45 @@ +<!-- + #%L + JAXX :: Demo + $Id: AbstractContentUI.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<JPanel abstract='true' + layout='{new BorderLayout()}' + genericType='B extends Object'> + + <script><![CDATA[ +import jaxx.demo.component.jaxx.nav.JaxxNavDemoHelper; + +// Get helper in context +JaxxNavDemoHelper getTreeHelper() { + return getContextValue(JaxxNavDemoHelper.class, "treeHelper"); +} +JaxxNavDemoHelper getTreeTableHelper() { + return getContextValue(JaxxNavDemoHelper.class, "treeTableHelper"); +} + +public abstract B getData(); + +public abstract void setData(B data); + ]]> + </script> +</JPanel> Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorContentUI.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorContentUI.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorContentUI.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,78 @@ +<!-- + #%L + JAXX :: Demo + $Id: ActorContentUI.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<AbstractContentUI superGenericType='People'> + + <import> + jaxx.demo.entities.* + </import> + <script><![CDATA[ +import jaxx.demo.entities.*; + +String getContent(People data) { + if (data == null) { + return "no content"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append(data); + return buffer.toString(); +} + +ImageIcon getImage(People data) { + return data == null? null :SwingUtil.createIcon(data.getImage()); +} + +]]></script> + + <JSplitPane id='splitPane' + orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <People id='data' javaBean='null'/> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane + border='{new TitledBorder(_("jaxxdemo.navigation.actor.title"))}' + editable='false' + font-size='11' + text='{getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> \ No newline at end of file Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorsContentUI.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorsContentUI.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/ActorsContentUI.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,88 @@ +<!-- + #%L + JAXX :: Demo + $Id: ActorsContentUI.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<AbstractContentUI superGenericType='java.util.List<People>'> + + <script><![CDATA[ +import jaxx.demo.entities.*; +import jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer; +import jaxx.runtime.binding.SimpleJAXXObjectBinding; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +private void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_DATA, new PropertyChangeListener(){ + @Override + public void propertyChange(PropertyChangeEvent evt) { + java.util.List<People> ps = getData(); + + if (ps != null) { + DefaultListModel model = (DefaultListModel) list.getModel(); + for (People p : ps) { + model.addElement(p); + } + } else { + // clean list model + DefaultListModel model = (DefaultListModel) list.getModel(); + model.removeAllElements(); + } + } + }); +} + +protected void selectChild() { + People selected = (People)list.getSelectedValue(); + getTreeHelper().selectNode(selected.getId()); + getTreeTableHelper().selectNode(selected.getId()); +} + ]]></script> + + <java.util.List id='data' genericType='People' javaBean='null'/> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(_("jaxxdemo.navigation.actors.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + <JList id='list' model='{new DefaultListModel()}' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + </JScrollPane> + <JToolBar id='toolbar' constraints='BorderLayout.SOUTH' + floatable='false'> + <JPanel layout='{new GridLayout(1,0)}'> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='selectChild()'/> + <JButton text='jaxxdemo.action.add'/> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + </JToolBar> + + </JPanel> +</AbstractContentUI> \ No newline at end of file Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MovieContentUI.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MovieContentUI.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MovieContentUI.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,74 @@ +<!-- + #%L + JAXX :: Demo + $Id: MovieContentUI.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<AbstractContentUI superGenericType='Movie'> + + <script><![CDATA[ +import jaxx.demo.entities.*; + +String getContent(Movie data) { + if (data == null) { + return "no content"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append(data); + return buffer.toString(); +} + +ImageIcon getImage(Movie data) { + return data == null? null :SwingUtil.createIcon(data.getImage()); +} +]]></script> + + <JSplitPane id='splitPane' + orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <Movie id='data' javaBean='null'/> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane + border='{new TitledBorder(_("jaxxdemo.navigation.movie.title"))}' + editable='false' + font-size='11' + text='{getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> \ No newline at end of file Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MoviesContentUI.jaxx =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MoviesContentUI.jaxx (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/content/MoviesContentUI.jaxx 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,95 @@ +<!-- + #%L + JAXX :: Demo + $Id: MoviesContentUI.jaxx 1861 2010-04-29 14:16:39Z tchemit $ + $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/compo... $ + %% + Copyright (C) 2008 - 2010 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>. + #L% + --> + +<AbstractContentUI + superGenericType='java.util.List<Movie>'> + + <import> + jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + jaxx.demo.entities.* + jaxx.runtime.binding.SimpleJAXXObjectBinding + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + </import> + <script><![CDATA[ + +private void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_DATA, new PropertyChangeListener(){ + @Override + public void propertyChange(PropertyChangeEvent evt) { + java.util.List<Movie> ms = getData(); + + if (ms != null) { + DefaultListModel model = (DefaultListModel) list.getModel(); + for (Movie m : ms) { + model.addElement(m); + } + } else { + // clean list model + DefaultListModel model = (DefaultListModel) list.getModel(); + model.removeAllElements(); + } + } + }); +} + +protected void selectChild() { + Movie selected = (Movie)list.getSelectedValue(); + getTreeHelper().selectNode(selected.getId()); + getTreeTableHelper().selectNode(selected.getId()); +} + ]]></script> + + <java.util.List id='data' genericType='Movie' javaBean='null'/> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(_("jaxxdemo.navigation.movies.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JList id='list' model='{new DefaultListModel()}' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + + </JScrollPane> + + <JToolBar id='toolbar' opaque='false' constraints='BorderLayout.SOUTH' + floatable='false'> + + <JPanel layout='{new GridLayout(1,0)}'> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='selectChild()'/> + <JButton text='jaxxdemo.action.add'/> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + </JToolBar> + + </JPanel> +</AbstractContentUI> \ No newline at end of file Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/ActorsNodeLoadors.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/ActorsNodeLoadors.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/ActorsNodeLoadors.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav.loadors; + +import jaxx.demo.component.jaxx.nav.JaxxNavDemoDataProvider; +import jaxx.demo.component.jaxx.nav.treetable.JaxxTreeTableDemoNode; +import jaxx.demo.component.jaxx.nav.tree.JaxxTreeDemoNode; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.DataProvider; +import jaxx.runtime.swing.nav.JaxxNode; +import jaxx.runtime.swing.nav.JaxxNodeChildLoador; + +import java.util.List; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class ActorsNodeLoadors<N extends JaxxNode<N>> extends JaxxNodeChildLoador<People,People, N> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public ActorsNodeLoadors() { + this(false); + } + + public ActorsNodeLoadors(boolean isTreeTable) { + super(People.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<People> getData(Class<?> parentClass, + String moviesId, + DataProvider dataProvider) throws Exception { + + // Get people for parentId + JaxxNavDemoDataProvider provider = (JaxxNavDemoDataProvider) dataProvider; + + // If its not root + if (moviesId != null) { + + // Return peoples for movies id + return provider.getPeoples(moviesId); + } + + // Return all peoples + return provider.getPeoples(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N createNode(People data, DataProvider dataProvider) { + + JaxxNode actorNode; + + // Create actor static nodes + if (!isTreeTable) { + actorNode = new JaxxTreeDemoNode( + getBeanType(), + data.getId(), + null, + null + ); + } else { + actorNode = new JaxxTreeTableDemoNode( + getBeanType(), + data.getId(), + null, + null + ); + } + + return (N) actorNode; + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/MoviesNodeLoadors.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/MoviesNodeLoadors.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/loadors/MoviesNodeLoadors.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav.loadors; + +import jaxx.demo.component.jaxx.nav.JaxxNavDemoDataProvider; +import jaxx.demo.component.jaxx.nav.JaxxNavDemoHelper; +import jaxx.demo.component.jaxx.nav.tree.JaxxTreeDemoNode; +import jaxx.demo.component.jaxx.nav.treetable.JaxxTreeTableDemoNode; +import jaxx.demo.entities.Movie; +import jaxx.runtime.swing.nav.JaxxNode; +import jaxx.runtime.swing.nav.JaxxNodeChildLoador; +import jaxx.runtime.swing.nav.DataProvider; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class MoviesNodeLoadors<N extends JaxxNode<N>> extends JaxxNodeChildLoador<Movie, Movie, N> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public MoviesNodeLoadors() { + this(false); + } + + public MoviesNodeLoadors(boolean isTreeTable) { + super(Movie.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<Movie> getData(Class<?> parentClass, + String parentId, + DataProvider dataProvider) throws Exception { + + JaxxNavDemoDataProvider provider = (JaxxNavDemoDataProvider) dataProvider; + + // Return all movies + return provider.getMovies(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N createNode(Movie data, DataProvider dataProvider) { + + JaxxNode moviesNode; + JaxxNode actorsCategoryNode; + + if (!isTreeTable) { + // Create movies static nodes + moviesNode = new JaxxTreeDemoNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new JaxxTreeDemoNode( + String.class, + n_(JaxxNavDemoHelper.ACTORS_CATEGORY_NODE), + null, + new ActorsNodeLoadors<JaxxTreeDemoNode>(false) + ); + } else { + // Create movies static nodes + moviesNode = new JaxxTreeTableDemoNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new JaxxTreeTableDemoNode( + String.class, + n_(JaxxNavDemoHelper.ACTORS_CATEGORY_NODE), + null, + new ActorsNodeLoadors<JaxxTreeDemoNode>(true) + ); + } + + // Add actors nodes to movies node + moviesNode.add(actorsCategoryNode); + + return (N) moviesNode; + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoCellRenderer.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoCellRenderer.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoCellRenderer.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,114 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav.tree; + +import jaxx.demo.component.jaxx.nav.JaxxNavDemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.decorator.Decorator; +import jaxx.runtime.decorator.DecoratorProvider; +import jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTree; +import java.awt.Component; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxTreeDemoCellRenderer extends AbstractJaxxTreeCellRenderer<JaxxTreeDemoNode> { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(JaxxTreeDemoCellRenderer.class); + + protected DecoratorProvider decoratorProvider; + + public JaxxTreeDemoCellRenderer(DecoratorProvider decoratorProvider, JaxxNavDemoDataProvider provider) { + super.setDataProvider(provider); + this.decoratorProvider = decoratorProvider; + } + + @Override + public JaxxNavDemoDataProvider getDataProvider() { + return (JaxxNavDemoDataProvider) super.getDataProvider(); + } + + @Override + protected String computeNodeText(JaxxTreeDemoNode node) { + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // get decorator + Decorator<?> decorator = decoratorProvider.getDecorator(editType); + + Object toDecorate = null; + + // People node + if (editType.equals(People.class)) { + toDecorate = getDataProvider().getPeople(id); + + // Movie node + } else if (editType.equals(Movie.class)) { + toDecorate = getDataProvider().getMovie(id); + } + + // Get decorated value + String decorated = decorator.toString(toDecorate); + + if (log.isDebugEnabled()) { + log.debug("Compute text for node " + + node + " return " + + decorated); + } + + return decorated; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + // get node + JaxxTreeDemoNode node = (JaxxTreeDemoNode) value; + + // get text for node + String text = getNodeText(node); + + // Render node + return super.getTreeCellRendererComponent(tree, text, sel, + expanded, leaf, + row, hasFocus); + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoNode.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoNode.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/tree/JaxxTreeDemoNode.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,49 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.component.jaxx.nav.tree; + +import jaxx.runtime.swing.nav.JaxxNodeChildLoador; +import jaxx.runtime.swing.nav.tree.JaxxTreeNode; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxTreeDemoNode extends JaxxTreeNode<JaxxTreeDemoNode> { + + private static final long serialVersionUID = 1L; + + public JaxxTreeDemoNode(String id) { + super(id); + } + + public JaxxTreeDemoNode(Class<?> internalClass, + String id, + String context, + JaxxNodeChildLoador<?, ?, JaxxTreeDemoNode> loador) { + super(internalClass, id, context, loador); + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoModel.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoModel.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoModel.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,119 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ +package jaxx.demo.component.jaxx.nav.treetable; + +import jaxx.demo.component.jaxx.nav.JaxxNavDemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.treetable.JaxxTreeTableModel; +import jaxx.runtime.swing.nav.JaxxNode; + +import static org.nuiton.i18n.I18n._; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxTreeTableDemoModel extends JaxxTreeTableModel.MyDefaultTreeTableModel { + + protected JaxxNavDemoDataProvider dataProvider; + + public JaxxTreeTableDemoModel(JaxxNavDemoDataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + @Override + public Object getValueAt(Object o, int i) { + JaxxNode node = (JaxxNode)o; + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // If it's category node + if (node.isStringNode()) { + if (i == 0) { + return _(id); + } + return ""; + + // People node + } else if (editType.equals(People.class)) { + People people = dataProvider.getPeople(id); + return getPeopleColumn(people, i); + + // Movie node + } else if (editType.equals(Movie.class)) { + Movie movie = dataProvider.getMovie(id); + return getMovieColumn(movie, i); + } + + // This never append + return "not found"; + } + + private String getMovieColumn(Movie movie, int i) { + String result = ""; + + switch (i) { + case 0: + result = movie.getTitle(); + break; + case 2: + result = String.valueOf(movie.getYear()); + break; + } + return result; + } + + protected String getPeopleColumn(People people, int i) { + String result = ""; + + switch (i) { + case 0: + result = people.getFirstName(); + break; + case 1: + result = people.getLastName(); + break; + case 2: + result = String.valueOf(people.getAge()); + break; + } + return result; + } + + @Override + public String[] getColumnsNames() { + return new String[]{_("jaxxdemo.tree.firstName"), + _("jaxxdemo.tree.lastName"), + _("jaxxdemo.tree.age")}; + } + + @Override + public boolean isCellEditable(Object node, int column) { + return false; + } +} Added: trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoNode.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoNode.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/nav/treetable/JaxxTreeTableDemoNode.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ +package jaxx.demo.component.jaxx.nav.treetable; + +import jaxx.runtime.swing.nav.JaxxNodeChildLoador; +import jaxx.runtime.swing.nav.treetable.JaxxTreeTableNode; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class JaxxTreeTableDemoNode extends JaxxTreeTableNode<JaxxTreeTableDemoNode> { + + protected JaxxTreeTableDemoNode(String id) { + super(id); + } + + public JaxxTreeTableDemoNode(Class<?> internalClass, String id, String context, JaxxNodeChildLoador childLoador) { + super(internalClass, id, context, childLoador); + } +} Modified: trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -25,7 +25,7 @@ package jaxx.demo.tree; -import jaxx.demo.component.jaxx.tree.JaxxTreeDemoDataProvider; +import jaxx.demo.component.jaxx.nav.JaxxNavDemoDataProvider; import jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,8 +51,8 @@ } @Override - public JaxxTreeDemoDataProvider getDataProvider() { - return (JaxxTreeDemoDataProvider) super.getDataProvider(); + public JaxxNavDemoDataProvider getDataProvider() { + return (JaxxNavDemoDataProvider) super.getDataProvider(); } @Override Modified: trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -30,7 +30,7 @@ import jaxx.demo.component.jaxx.editor.ComboEditorDemo; import jaxx.demo.component.jaxx.editor.I18nEditorDemo; import jaxx.demo.component.jaxx.editor.NumberEditorDemo; -import jaxx.demo.component.jaxx.tree.JaxxTreeDemo; +import jaxx.demo.component.jaxx.nav.JaxxNavDemo; import jaxx.demo.component.swing.HidorButtonDemo; import jaxx.demo.component.swing.JButtonDemo; import jaxx.demo.component.swing.JCheckBoxDemo; @@ -152,7 +152,7 @@ I18nEditorDemo.class ); addMapping(n_("jaxxdemo.tree.component.jaxx.tree"), - JaxxTreeDemo.class + JaxxNavDemo.class ); addMapping(n_("jaxxdemo.tree.feature"), Deleted: trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2008 - 2010 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>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.runtime.swing.nav.JaxxDelegateTreeModel; -import jaxx.runtime.swing.nav.tree.JaxxTreeHelper; - -import javax.swing.tree.TreeModel; - -/** - * @author sletellier <letellier@codelutin.com> - * @since 2.1 - */ -public class DemoTreeHelper extends JaxxTreeHelper<DemoNode> { - - public DemoTreeHelper(DemoDataProvider provider) { - setDataProvider(provider); - } - - @Override - public DemoDataProvider getDataProvider() { - return (DemoDataProvider) super.getDataProvider(); - } - - public TreeModel createTreeModel() { - - // Create root static node - DemoNode root = new DemoNode("jaxxdemo.tree"); - - // Create model - JaxxDelegateTreeModel<DemoNode> model = createTreeModel(root); - - // load all nodes of model - loadAllNodes(model, root, getDataProvider()); - - return getTreeModel(); - } -} \ No newline at end of file Added: trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java =================================================================== --- trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java (rev 0) +++ trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id: DemoTreeHelper.java 2009 2010-06-29 16:09:09Z sletellier $ + * $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/... $ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ + +package jaxx.demo.tree; + +import jaxx.runtime.swing.nav.JaxxDelegateTreeModel; +import jaxx.runtime.swing.nav.JaxxNavHelper; + +import javax.swing.tree.TreeModel; + +/** + * @author tchemit <tchemit@codelutin.com> + * @since 2.1 + */ +public class DemoTreeHelper extends JaxxNavHelper<DemoNode> { + + public DemoTreeHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + public TreeModel createTreeModel() { + + // Create root static node + DemoNode root = new DemoNode("jaxxdemo.tree"); + + // Create model + JaxxDelegateTreeModel<DemoNode> model = createTreeModel(root); + + // load all nodes of model + loadAllNodes(model, root, getDataProvider()); + + return getTreeModel(); + } +} \ No newline at end of file Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxDelegateTreeModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxDelegateTreeModel.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxDelegateTreeModel.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -41,21 +41,40 @@ import java.util.EventListener; import java.util.List; +/** + * Delegate model used to switch between tree model and tree table model api + * + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + **/ public class JaxxDelegateTreeModel<N extends JaxxNode<N>> { /** Logger */ static private final Log log = LogFactory.getLog(JaxxDelegateTreeModel.class); + // Delegate tree model protected DefaultTreeModel treeModel; + + // Delegate jaxx tree table model protected JaxxTreeTableModel treeTableModel; protected boolean isTreeTable; + /** + * Use this constructor to use tree api + * + * @param treeModel {@link DefaultTreeModel} to use + */ public JaxxDelegateTreeModel(DefaultTreeModel treeModel) { this.treeModel = treeModel; isTreeTable = false; } + /** + * Use this constructor to use tree table api + * + * @param treeTableModel {@link JaxxTreeTableModel} to use + */ public JaxxDelegateTreeModel(JaxxTreeTableModel treeTableModel) { this.treeTableModel = treeTableModel; isTreeTable = true; Copied: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNavHelper.java (from rev 2009, trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeHelper.java) =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNavHelper.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNavHelper.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -0,0 +1,986 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 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>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer; +import jaxx.runtime.swing.nav.treetable.JaxxTreeTableModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; + +import javax.swing.JTree; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Tree helper to deal with the build of trees and other usefull operations. + * <p/> + * A helper acts as an handler for a {@code tree}. It owns the {@link #model} of + * the {@link #tree}. + * <p/> + * <b>Note:</b> A helper can NOT be used to manage multi-trees. + * <h2>Internal states</h2 + * <h3>Internal model</h3> + * To create the model, use method {@link #createModel(jaxx.runtime.swing.nav.JaxxNode)} given a + * root node. + * <p/> + * To obtain the model, use method {@link #getModel()}. + * <p/> + * <b>Note:</b> The helper internal model can be different from the tree model, + * but must be the <b>lowest</b> model, other models must listen nicely this + * model to obtain model modification and selection notifications. + * <h3>Internal tree</h3> + * As said before, a helper matches exactly one tree. + * <p/> + * To register the tree, use method {@link #setTree(JTree, boolean, TreeSelectionListener)}. + * <p/> + * To obtain the tree, use method {@link #getTree()}. + * <h3>Internal data provider</h3> + * To populate childs nodes and render nodes, we use a {@link jaxx.runtime.swing.nav.DataProvider}. + * <p/> + * To register the data provider, use method {@link #setDataProvider(jaxx.runtime.swing.nav.DataProvider)}. + * <p/> + * To obtain the data provider, use method {@link #getDataProvider()}. + * <h2>Internal listeners</h2> + * Several listeners are used to manage the auto-loading of nodes in model : + * <h3>{@link #expandListener}</h3> + * This listener will load node's childs before node expands if the node is not loaded. + * <p/> + * See the {@link jaxx.runtime.swing.nav.JaxxNode#isLoaded()} method. + * <h3>{@link #treeModelListener}</h3> + * To listen modification of the model, it will mainly repopulate nodes when + * required. + * <p/> + * See the method {@link #populateNode(jaxx.runtime.swing.nav.JaxxNode , Object[], boolean)}. + * <h3>{@link #selectionListener}</h3> + * To listen modification of the selection, it will mainly expand paths if required. + * <p/> + * This is a requirement, since childs of a node should NOT be loaded, so when + * selects a node, always check the path from root to selected node are all fully + * loaded. + * <h2>Model methods</h2> + * The helper offers some methods to modify and query the internal tree model. + * <h3>Model modification</h3> + * <ul> + * <li>{@link #createModel(jaxx.runtime.swing.nav.JaxxNode)}</li> + * <li>{@link #insertNode(jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.JaxxNode)}</li> + * <li>{@link #removeNode(jaxx.runtime.swing.nav.JaxxNode)}</li> + * <li>{@link #moveNode(jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.JaxxNode , int)}</li> + * <li>{@link #refreshNode(jaxx.runtime.swing.nav.JaxxNode , boolean)}</li> + * <li>{@link #loadAllNodes(jaxx.runtime.swing.nav.JaxxDelegateTreeModel , jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.DataProvider)}</li> + * <p/> + * </ul> + * <h3>Model selection modification</h3> + * <ul> + * <li>{@link #selectNode(jaxx.runtime.swing.nav.JaxxNode)}</li> + * <li>{@link #selectNode(String...)}</li> + * <li>{@link #selectParentNode()}</li> + * </ul> + * <h3>Model query</h3> + * <ul> + * <li>{@link #findNode(jaxx.runtime.swing.nav.JaxxNode , String...)}</li> + * </ul> + * <h3>Child loadors factory</h3> + * The class offers a factory of {@link jaxx.runtime.swing.nav.JaxxNodeChildLoador}, use the method + * {@link #getChildLoador(Class)} to obtain the correct child loador given his type. + * + * @author tchemit <chemit@codelutin.com> + * @see jaxx.runtime.swing.nav.JaxxNode + * @see jaxx.runtime.swing.nav.JaxxNodeChildLoador + * @see jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer + * @since 2.1 + */ +public class JaxxNavHelper<N extends JaxxNode<N>> { + + /** Logger */ + static private final Log log = LogFactory.getLog(JaxxNavHelper.class); + + /** + * The shared instance of tree model. + * <p/> + * A helper deals with only ONE model (this one), becuase we add some + * listeners on it, we prefer always to keep ONE instance (any way this is + * a good thing). + * <p/> + * If you want to create a new model, just creates the good root node and + * push it in this model. + * <p/> + * <b>Note:</b> The model of the registred {@link #tree} can be different + * from this one. + * <p/> + * For example, if you wrap the shared model with a filter model... Anyway, all + * listeners of this helper apply always of THIs model. + */ + protected JaxxDelegateTreeModel<N> model; + + /** + * The shared instance of tree. + * <p/> + * A helper deleas with only ONE tree (this one), becuase we add some listeners + * on it, we prefer always to kepp ONE safe instance. + * <p/> + * If you need to work with more than one helper, please instanciat a new + * helper for each tree. + */ + protected JTree tree; + + /** + * The shared instance of treeTable. + * <p/> + * A helper deleas with only ONE tree (this one), becuase we add some listeners + * on it, we prefer always to kepp ONE safe instance. + * <p/> + * If you need to work with more than one helper, please instanciat a new + * helper for each tree. + */ + protected JXTreeTable treeTable; + + /** The shared data provider used to obtain datas to populate nodes and render them. */ + protected DataProvider dataProvider; + + /** + * A {@link TreeWillExpandListener} used to listen when tree should expand. + * <p/> + * If so, the listener will load selected node childs if required + * (says when the {@link jaxx.runtime.swing.nav.JaxxNode#isLoaded()} is sets to {@code false}). + */ + protected TreeWillExpandListener expandListener; + + /** + * pour ouvrir les fils d'un noeud que l'on vient de sélectionner pour + * éviter d'avoir à faire des doubles clics. + */ + protected TreeSelectionListener selectionListener; + + /** + * pour recharger le rendu des noeuds (et charger les fils si nécessaires) + * lors d'une modification dans le modèle de l'arbre. + */ + protected TreeModelListener treeModelListener; + + /** Cache of child loadors. */ + protected static Set<? super JaxxNodeChildLoador<?, ?, ?>> childLoadors; + + protected static Set<? super JaxxNodeChildLoador<?, ?, ?>> getChildLoadors() { + if (childLoadors == null) { + childLoadors = new HashSet<JaxxNodeChildLoador<?, ?, ?>>(); + } + return childLoadors; + } + + /** + * Obtains the {@link JaxxNodeChildLoador} of the given {@code type} from + * internal cache. + * <p/> + * <b>Note:</b> The loador will be instanciated if not found, and push in cache. + * + * @param type the type of loador to get + * @param <L> the type of loador to get + * @return the loador from cache + */ + @SuppressWarnings({"unchecked"}) + public static <L extends JaxxNodeChildLoador<?, ?, ?>> L getChildLoador(Class<L> type) { + Set<? super JaxxNodeChildLoador<?, ?, ?>> cache = getChildLoadors(); + JaxxNodeChildLoador<?, ?, ?> result = null; + for (Object loador : cache) { + if (type.equals(loador.getClass())) { + result = (JaxxNodeChildLoador<?, ?, ?>) loador; + break; + } + } + if (result == null) { + // add it in cache + try { + result = type.newInstance(); + cache.add(result); + if (log.isDebugEnabled()) { + log.debug("Add " + result + " in loadors cache (new size:" + cache.size() + ")."); + } + } catch (Exception e) { + throw new IllegalArgumentException("Could not instanciate loador [" + type.getName() + "]", e); + } + } + return (L) result; + } + + public JaxxNavHelper() { + + selectionListener = new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent e) { + if (!checkModel()) { + return; + } + + // Hack, because event.getSource for TreeTable doesnt return selectionModel + TreeSelectionModel source = getSelectionModel(); + + if (source.isSelectionEmpty()) { + + // empty selection + if (log.isDebugEnabled()) { + log.debug("Selection is empty."); + } + return; + } + + boolean debugEnabled = log.isDebugEnabled(); + boolean traceEnabled = log.isTraceEnabled(); + for (TreePath path : e.getPaths()) { + + N node = getNode(path); + if (node == null) { + + // pas de noeud selectionne + if (debugEnabled) { + log.debug("Skip for null node."); + } + continue; + } + + boolean isAdded = e.isAddedPath(path); + + TreePath pathToExpand = new TreePath(model.getPathToRoot(node)); + boolean pathExpanded = isExpanded(pathToExpand); + + if (traceEnabled || isAdded && debugEnabled) { + log.debug("==== Node selection ===================================="); + log.debug("node ? " + node); + log.debug("is added ? " + isAdded); + log.debug("is path expanded ? " + pathExpanded); + log.debug("is node static ? " + node.isStaticNode()); + log.debug("is node loaded ? " + node.isLoaded()); + log.debug("is node leaf ? " + node.isLeaf()); + log.debug("node nb childs ? " + node.getChildCount()); + } + + if (isAdded && !pathExpanded) { + + // ask to expand path + log.info("expand node [" + pathToExpand + "]"); + expandPath(pathToExpand); + } + } + } + }; + expandListener = new TreeWillExpandListener() { + @Override + public void treeWillExpand(TreeExpansionEvent event) { + + if (!checkModel()) { + // no model + return; + } + + N source = getNode(event.getPath()); + + if (source.isLoaded()) { + + // node is already loaded, nothing to do + return; + } + + if (log.isDebugEnabled()) { + log.debug("will load childs of node [" + source + "]"); + } + // populate childs of node + source.populateChilds(model, getDataProvider()); + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) { + } + }; + + + treeModelListener = new TreeModelListener() { + @Override + public void treeNodesInserted(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("inserted ", source, children)); + } + + // ask to populate children nodes + populateNode(null, children, false); + } + + @SuppressWarnings({"unchecked"}) + @Override + public void treeNodesRemoved(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("removed ", source, children)); + } + + // Invalidates nodes in renderer cache (if any) + AbstractJaxxTreeCellRenderer<N> renderer = getTreeCellRenderer(); + if (children != null && renderer != null) { + for (Object child : children) { + renderer.invalidateCache((N) child); + } + } + } + + @Override + public void treeNodesChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("changed ", source, children)); + } + + // ask to populate modified child nodes + populateNode(null, children, false); + } + + @Override + public void treeStructureChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("structure changed", source, children)); + } + + // ask to populate structure modified node and nodes recursively + populateNode(source, children, true); + } + + protected String getMessage(String action, N source, Object[] children) { + StringBuilder sb = new StringBuilder(); + sb.append("==== Nodes "); + sb.append(action); + sb.append(" ================="); + sb.append("\nsource : ").append(source); + sb.append("\nnb nodes : "); + sb.append(children == null ? 0 : children.length); + if (children != null) { + int i = 0; + for (Object child : children) { + sb.append("\n ["); + sb.append(i++); + sb.append("] - "); + sb.append(child); + } + } + return sb.toString(); + } + }; + } + + /** + * Obtains the attached data provider used to populate and render nodes. + * + * @return the attached data provider + */ + protected DataProvider getDataProvider() { + return dataProvider; + } + + /** + * Obtains the registred tree. + * + * @return the registred tree for this helper or {@code null} if none was registred + */ + public JTree getTree() { + return tree; + } + + /** + * Obtains the registred tree table. + * + * @return the registred tree table for this helper or {@code null} if none was registred + */ + public JXTreeTable getTreeTable() { + return treeTable; + } + + /** + * Obtains the jaxx delegate tree model + * + * @return the internal tree model or {@code null} if none was created. + */ + public JaxxDelegateTreeModel<N> getModel() { + return model; + } + + /** + * Obtains the internal tree table model. + * + * @return the internal tree table model or {@code null} if none was created. + */ + public DefaultTreeModel getTreeModel() { + return model.getTreeDelegateModel(); + } + + /** + * Obtains the internal tree table model. + * + * @return the internal tree table model or {@code null} if none was created. + */ + public JaxxTreeTableModel getTreeTableModel() { + return model.getTreeTableDelegateModel(); + } + + public N getRootNode() { + if (!checkModel()) { + return null; + } + return model.getRoot(); + } + + /** + * Obtains the {@link AbstractJaxxTreeCellRenderer} renderer of the + * registred tree. + * + * @return the renderer of the registred tree or null if no tree was + * registred nor the renderer is a {@link AbstractJaxxTreeCellRenderer}. + */ + @SuppressWarnings({"unchecked"}) + public AbstractJaxxTreeCellRenderer<N> getTreeCellRenderer() { + JTree t = getTree(); + if (t == null) { + return null; + } + TreeCellRenderer r = t.getCellRenderer(); + if (r instanceof AbstractJaxxTreeCellRenderer<?>) { + return (AbstractJaxxTreeCellRenderer<N>) r; + } + return null; + } + + /** + * Obtains the selected node of the registred tree. + * + * @return the selected tree or {@code null} if no registred tree nor + * selection empty. + */ + public N getSelectedNode() { + JTree tree = getTree(); + if (tree == null) { + return null; + } + TreePath path = tree.getSelectionPath(); + N node = null; + if (path != null) { + node = getNode(path); + } + return node; + } + + /** + * Obtains the path of ids fro the root node to the selected node on the + * registred tree. + * + * @return the array of ids from root node to selected node. + */ + public String[] getSelectedIds() { + List<String> result = new ArrayList<String>(); + N selectedNode = getSelectedNode(); + while (selectedNode != null && !selectedNode.isRoot()) { + + result.add(selectedNode.getId()); + selectedNode = selectedNode.getParent(); + } + Collections.reverse(result); + return result.toArray(new String[result.size()]); + } + + /** + * Registers the {@code dataProvider} for the helper. + * <p/> + * <b>Node:</b> As a side-effect, the provider will be propagate to the + * renderer of the registred tree (if any). + * + * @param dataProvider the data provider to use + */ + public void setDataProvider(DataProvider dataProvider) { + this.dataProvider = dataProvider; + AbstractJaxxTreeCellRenderer<N> renderer = getTreeCellRenderer(); + if (renderer != null) { + + // dispatch provider to renderer + renderer.setDataProvider(dataProvider); + } + } + + /** + * Registers the given {@code tree} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param listener the optional selection listener to add + */ + public void setTree(JTree tree, + boolean addExpandTreeListener, + TreeSelectionListener listener) { + this.tree = tree; + if (addExpandTreeListener) { + this.tree.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + this.tree.getSelectionModel().addTreeSelectionListener(listener); + } + this.tree.getSelectionModel().addTreeSelectionListener(selectionListener); + } + + /** + * Registers the given {@code treeTable} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param treeTable the tree table to register + * @param addExpandTreeListener a flag to add expand listener + * @param listener the optional selection listener to add + */ + public void setTreeTable(JXTreeTable treeTable, + boolean addExpandTreeListener, + TreeSelectionListener listener) { + this.treeTable = treeTable; + if (addExpandTreeListener) { + this.treeTable.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + this.treeTable.addTreeSelectionListener(listener); + } + this.treeTable.addTreeSelectionListener(selectionListener); + } + + /** + * Inserts the given node to the given {@code parentNode}. + * <p/> + * The node will be added to his parent, then creation listeners will be + * fired. + * + * @param parentNode the parent node where to insert the new node * + * @param newNode the node to insert + */ + public void insertNode(N parentNode, N newNode) { + parentNode.add(newNode); + if (!model.isTreeTable()) { + model.notifyNodeInserted(newNode); + } else { + model.nodeStructureChanged(parentNode); + } + } + + /** + * Removes the given {@code node} from the registred tree model and returns + * his parent. + * + * @param node the node to remove + * @return the parent node of the removed node. + */ + public N removeNode(N node) { + N parentNode = node.getParent(); + model.removeNodeFromParent(node); + return parentNode; + } + + /** + * Moves the given {@code node} to the new {@code position}. + * + * @param parentNode the parent node + * @param node the node to move + * @param position the new position of the node + */ + public void moveNode(N parentNode, N node, int position) { + parentNode.remove(node); + parentNode.insert(node, position); + model.nodeStructureChanged(parentNode); + } + + /** + * Refreshs the given {@code node}. + * <p/> + * If flag {@code deep} is set to {@code true}, then it will refresh + * recursively children nodes. + * <p/> + * <b>Note:</b>As a side-effect, evvery node involved will become + * {@code dirty}. + * + * @param node the node to refresh + * @param deep un flag pour activer la repainte de la descendance du + * noeud + * @see jaxx.runtime.swing.nav.JaxxNode#isDirty() + */ + @SuppressWarnings({"unchecked"}) + public void refreshNode(N node, boolean deep) { + if (log.isDebugEnabled()) { + log.debug("Will refresh (deep ? " + deep + ") node " + node); + } + model.nodeChanged(node); + if (deep) { + // repaint childs nodes + Enumeration<N> e = node.children(); + while (e.hasMoreElements()) { + N child = e.nextElement(); + refreshNode(child, true); + } + } + } + + /** + * To load all nodes of a model. + * + * @param model the tree model owner of nodes + * @param node the root node to load + * @param dataProvider the data provider used to populate nodes + */ + @SuppressWarnings({"unchecked"}) + public void loadAllNodes(JaxxDelegateTreeModel<N> model, + N node, + DataProvider dataProvider) { + if (!checkModel()) { + return; + } + if (!node.isLoaded()) { + node.populateChilds(model, dataProvider); + Enumeration<? extends JaxxNode<?>> enumeration = node.children(); + while (enumeration.hasMoreElements()) { + N jaxxNode = (N) enumeration.nextElement(); + loadAllNodes(model, jaxxNode, dataProvider); + } + } + } + + /** + * Selects the parent of the currently selected node. + * <p/> + * <b>Note:</> If selection is empty, then throws a NPE. + * + * @throws NullPointerException if selection is empty + */ + public void selectParentNode() throws NullPointerException { + + N node = getSelectedNode(); + + if (node == null) { + // pas de noeud selectionne + throw new NullPointerException("no selected node in context"); + } + node = node.getParent(); + + selectNode(node); + } + + /** + * Selects the given {@code node} in the registred tree. + * + * @param node the node to select + */ + public void selectNode(N node) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node [" + node + "]"); + } + TreePath path = new TreePath(model.getPathToRoot(node)); + + setSelectionPath(path); + scrollPathToVisible(path); + } + + /** + * Selects the node described by his given {@code path} of ids. + * + * @param path the absolute path of ids from root node to node to select. + */ + public void selectNode(String... path) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node from ids " + Arrays.toString(path)); + } + N root = model.getRoot(); + N node = findNode(root, path); + if (log.isDebugEnabled()) { + log.debug("selected node [" + node + "]"); + } + if (node != null) { + selectNode(node); + } + } + + /** + * Finds a node from the given root {@code node}, applying the path given + * by {@code ids}. + * + * @param node the starting node + * @param ids the path of ids to apply on the node. + * @return the find node or {@code null} if no node matchs. + */ + public N findNode(N node, String... ids) { + if (!checkModel()) { + + // no model + return null; + } + N result = null; + for (String id : ids) { + + result = node.findNodeById(id, model, getDataProvider()); + + if (result == null) { + + // un des noeud n'a pas ete trouve, on sort + break; + } + node = result; + } + return result; + } + + /** + * Register a new root node. + * <p/> + * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, + * otherwise just set the new root on the existing model. + * <p/> + * <p/> + * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} + * and the {@link #treeModelListener} will be registred on this model. + * + * @param node the root node of the new model + * @return the new model + * @deprecated use registerTreeModel + */ + @Deprecated + protected JaxxDelegateTreeModel createModel(N node) { + return createTreeModel(node); + } + + /** + * Register a new root node for tree. + * + * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, + * otherwise just set the new root on the existing model. + * <p/> + * + * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} + * and the {@link #treeModelListener} will be registred on this model. + * + * @param node the root node of the new model + * @return the new model + */ + protected JaxxDelegateTreeModel<N> createTreeModel(N node) { + DefaultTreeModel delegate = new DefaultTreeModel(node); + if (model == null) { + model = new JaxxDelegateTreeModel<N>(delegate); + model.addTreeModelListener(treeModelListener); + } else { + model.setRoot(node); + } + + // notify structure has changed + model.nodeStructureChanged(getRootNode()); + return model; + } + + /** + * Register a new root node for tree table. + * + * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, + * otherwise just set the new root on the existing model. + * <p/> + * + * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} + * and the {@link #treeModelListener} will be registred on this model. + * + * @param delegate model for tree table + * @param node the root node of the new model + * @return the tree model model + */ + protected JaxxDelegateTreeModel<N> createTreeTableModel(JaxxTreeTableModel.MyDefaultTreeTableModel delegate, N node) { + JaxxTreeTableModel tableModel = new JaxxTreeTableModel(delegate); + if (model == null) { + model = new JaxxDelegateTreeModel<N>(tableModel); + model.addTreeModelListener(treeModelListener); + } + model.setRoot(node); + + // notify structure has changed + model.nodeStructureChanged(getRootNode()); + return model; + } + + /** + * Checks if internal model was created. + * + * @return {@code true} if model was created + * (should be done via {@link #createModel(JaxxNode)} method), + * {@code false} otherwise. + */ + protected boolean checkModel() { + if (model == null) { + + // no model set, + log.warn("No model set in " + this); + return false; + } + // model is set + return true; + } + + /** + * Populates nodes. + * <p/> + * If {@code node} is not {@code null}, then populate it. + * <p/> + * If {@code children} is not {@code null}, then populate them, moreover + * if {@code recurse} is set to {@code true} then do a recurse refresh on + * children. + * + * @param node the parent node to populate (optional) + * @param children the child nodes to populate (optional) + * @param recurse flag sets to {@code true} if should do recurse refresh on + * given {@code children} nodes. + */ + @SuppressWarnings({"unchecked"}) + protected void populateNode(N node, + Object[] children, + boolean recurse) { + DataProvider dataProvider = getDataProvider(); + if (node != null) { + if (log.isDebugEnabled()) { + log.debug("Will populate node : " + node); + } + node.populateNode(model, dataProvider, false); + } + if (children != null) { + for (Object o : children) { + N child = (N) o; + if (log.isDebugEnabled()) { + log.debug("Will populate child node : " + child); + } + child.populateNode(model, dataProvider, recurse); + } + } + } + + /** + * Convinient method to objet the casted node of a {@link TreePath}. + * + * @param path the path contaning the node. + * @return the casted node from the path. + */ + @SuppressWarnings({"unchecked"}) + protected N getNode(TreePath path) { + N result = (N) path.getLastPathComponent(); + return result; + } + + //-------------------------------------------------------------------------- + //-- Methode to switch between tree and tree table + //-------------------------------------------------------------------------- + + public void scrollPathToVisible(TreePath path) { + JTree tree = getTree(); + if (tree != null) { + tree.scrollPathToVisible(path); + return; + } + getTreeTable().scrollPathToVisible(path); + } + + public void setSelectionPath(TreePath path) { + JTree tree = getTree(); + if (tree != null) { + tree.setSelectionPath(path); + return; + } + getTreeTable().getTreeSelectionModel().setSelectionPath(path); + } + + public TreeSelectionModel getSelectionModel() { + JTree tree = getTree(); + if (tree != null) { + return tree.getSelectionModel(); + } + return getTreeTable().getTreeSelectionModel(); + } + + public boolean isExpanded(TreePath pathToExpand) { + JTree tree = getTree(); + if (tree != null) { + return tree.isExpanded(pathToExpand); + } + return getTreeTable().isExpanded(pathToExpand); + } + + public void expandPath(TreePath pathToExpand) { + JTree tree = getTree(); + if (tree != null) { + tree.expandPath(pathToExpand); + return; + } + getTreeTable().expandPath(pathToExpand); + } +} Property changes on: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNavHelper.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNode.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNode.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNode.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -24,19 +24,18 @@ */ package jaxx.runtime.swing.nav; -import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import java.io.Serializable; /** - * Definition of a node with a optional {@link #childLoador} to build childs of + * Definition of a node with a optional {@code childLoador} to build childs of * node. * <p/> - * A node is identified by an {@link #id} of an associated data of type - * {@link #internalClass}. + * A node is identified by an {@link #getId} of an associated data of type + * {@link #getInternalClass}. * <p/> * <b>Note:</b> - * <p><i> While using a {@link #childLoador}, we can not know before node + * <p><i> While using a {@code childLoador}, we can not know before node * was loaded the exact count of his childs. As a matter of facts, real leaf * nodes appears at the beginning in ui as a not leaf (there is a root handler). * When node was loaded, a leaf node will be then displayed as required. @@ -72,7 +71,7 @@ * Some nodes do not need auto-loading, we call them {@code static nodes}. * The method {@link #isStaticNode()} gives this state. * <p/> - * <b>Note:</b> A static node has no {@link #childLoador}. + * <b>Note:</b> A static node has no {@code childLoador}. * <h2>Node loading</h2> * Initialy node has no data child nodes, ({@link #isLoaded()} equals * {@code false}). @@ -80,10 +79,10 @@ * {@link #populateNode(JaxxDelegateTreeModel , DataProvider, boolean)} * and {@link #populateChilds(JaxxDelegateTreeModel , DataProvider)} methods. * <h2>Node rendering</h2 - * the {@link jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer} looks the {@link #dirty} state to + * the {@link jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer} looks the {@link #isDirty} state to * know when render should be (re-)compute and set back the state to {@code false}. * <p/> - * Each time, a node is modified, the {@link #dirty} should be set to {@code true}. + * Each time, a node is modified, the {@link #isDirty} should be set to {@code true}. * * @author tchemit <chemit@codelutin.com> * @since 2.1 @@ -110,10 +109,10 @@ /** * To know if the node is static. * <p/> - * A {@code static} node has no {@link #childLoador}. + * A {@code static} node has no {@code childLoador}. * * @return {@code true} when the node is static : says, the node has - * no {@link #childLoador}. + * no {@code childLoador}. */ boolean isStaticNode(); @@ -129,7 +128,7 @@ * Given an {@code id}, obtain the child with matching id. * <p/> * If node is NOT {@code loaded}, then first loads it (method - * {@link #populateChilds(DefaultTreeModel, DataProvider)}) then do search + * {@link #populateChilds(JaxxDelegateTreeModel, DataProvider)}) then do search * on direct childs of the node. * * @param id the id of the researched node @@ -142,7 +141,7 @@ DataProvider provider); /** - * Changes the {@link #dirty} state. + * Changes the {@link #isDirty} state. * <p/> * As a side effect, when a renderer will use this node, it will force to * reload the render from the {@link DataProvider}. Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNodeChildLoador.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNodeChildLoador.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/JaxxNodeChildLoador.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -37,7 +37,7 @@ * {@link #loadChilds(JaxxDelegateTreeModel , JaxxNode, DataProvider)} to obtain datas * then build childs nodes. * <p/> - * A factory of such objects can be found in {@link jaxx.runtime.swing.nav.tree.JaxxTreeHelper} to make + * A factory of such objects can be found in {@link JaxxNavHelper} to make * them reusable in other places than inside a {@link JaxxNode} to auto-load * childs. * <p/> @@ -48,7 +48,7 @@ * @param <T> type of data used to create nodes (can be just a String type to use only ids) * @param <O> type of data associated with nodes * @param <N> type of node to used (to make possible full co-variance and no cast in fal implementations). - * @see jaxx.runtime.swing.nav.tree.JaxxTreeHelper + * @see JaxxNavHelper * @see JaxxNode * @since 2.1 */ Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html 2010-06-29 22:50:39 UTC (rev 2010) @@ -2,7 +2,7 @@ <body> <h1>JAXX - tree utilities</h1> -This package contains all the classes of the new tree framework. +This package contains all the classes of the new tree and treeTable framework. <p> Replace the previous framework from package @@ -28,23 +28,56 @@ were loaded, if not, load them then give by hand to system. </p> +<p> + This api allow to switch easily between tree implementation and tree table + api. +</p> + + <h1>Api</h1> + <h2>DataProvider</h2> Contract of objet responsible of acquiring data to populate nodes and render them. <h2>JaxxNode</h2> -An override of DefaultMutableTreeNode customized for our purpose (loaded, dirty -states,...) +Jaxx node contract customized for our purpose (loaded, dirty +states,...). <h2>JaxxNodeChildLoador</h2> -Object to load childs of a node using DataProvider. +Contract to load childs of a JaxxNode using DataProvider. -<h2>JaxxTreeHelper</h2> -Helper to manage a tree using auto-loading nodes. +<h2>JaxxNavHelper</h2> +Helper to manage a tree or a tree table using auto-loading nodes. +<h2>JaxxDelegateTreeModel</h2> +Model to switch between tree model and tree table model. + + +<h1>Tree api</h1> + + +<h2>JaxxTreeNode</h2> +An override of DefaultMutableTreeNode implement JaxxNode. + +<h2>JaxxTreeNodeChildLoador</h2> +Object to load childs of a tree node using DataProvider. + <h2>AbstractJaxxTreeCellRenderer</h2> Abstract renderer using DataProvider to acquire node render. + +<h1>Tree table api</h1> + + +<h2>JaxxTreeTableNode</h2> +An override of DefaultMutableTreeTableNode implement JaxxNode + +<h2>JaxxTreeTableNodeChildLoador</h2> +Object to load childs of a tree table node using DataProvider. + +<h2>JaxxTreeTableModel</h2> +Implementation of TreeTableModel used by JaxxDelegateTreeModel + </body> </html> Deleted: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeHelper.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeHelper.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeHelper.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -1,989 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2008 - 2010 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>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.JaxxDelegateTreeModel; -import jaxx.runtime.swing.nav.treetable.JaxxTreeTableModel; -import jaxx.runtime.swing.nav.DataProvider; -import jaxx.runtime.swing.nav.JaxxNode; -import jaxx.runtime.swing.nav.JaxxNodeChildLoador; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTreeTable; - -import javax.swing.JTree; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeCellRenderer; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Tree helper to deal with the build of trees and other usefull operations. - * <p/> - * A helper acts as an handler for a {@code tree}. It owns the {@link #model} of - * the {@link #tree}. - * <p/> - * <b>Note:</b> A helper can NOT be used to manage multi-trees. - * <h2>Internal states</h2 - * <h3>Internal model</h3> - * To create the model, use method {@link #createModel(jaxx.runtime.swing.nav.JaxxNode)} given a - * root node. - * <p/> - * To obtain the model, use method {@link #getModel()}. - * <p/> - * <b>Note:</b> The helper internal model can be different from the tree model, - * but must be the <b>lowest</b> model, other models must listen nicely this - * model to obtain model modification and selection notifications. - * <h3>Internal tree</h3> - * As said before, a helper matches exactly one tree. - * <p/> - * To register the tree, use method {@link #setTree(JTree, boolean, TreeSelectionListener)}. - * <p/> - * To obtain the tree, use method {@link #getTree()}. - * <h3>Internal data provider</h3> - * To populate childs nodes and render nodes, we use a {@link jaxx.runtime.swing.nav.DataProvider}. - * <p/> - * To register the data provider, use method {@link #setDataProvider(jaxx.runtime.swing.nav.DataProvider)}. - * <p/> - * To obtain the data provider, use method {@link #getDataProvider()}. - * <h2>Internal listeners</h2> - * Several listeners are used to manage the auto-loading of nodes in model : - * <h3>{@link #expandListener}</h3> - * This listener will load node's childs before node expands if the node is not loaded. - * <p/> - * See the {@link jaxx.runtime.swing.nav.JaxxNode#isLoaded()} method. - * <h3>{@link #treeModelListener}</h3> - * To listen modification of the model, it will mainly repopulate nodes when - * required. - * <p/> - * See the method {@link #populateNode(jaxx.runtime.swing.nav.JaxxNode , Object[], boolean)}. - * <h3>{@link #selectionListener}</h3> - * To listen modification of the selection, it will mainly expand paths if required. - * <p/> - * This is a requirement, since childs of a node should NOT be loaded, so when - * selects a node, always check the path from root to selected node are all fully - * loaded. - * <h2>Model methods</h2> - * The helper offers some methods to modify and query the internal tree model. - * <h3>Model modification</h3> - * <ul> - * <li>{@link #createModel(jaxx.runtime.swing.nav.JaxxNode)}</li> - * <li>{@link #insertNode(jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.JaxxNode)}</li> - * <li>{@link #removeNode(jaxx.runtime.swing.nav.JaxxNode)}</li> - * <li>{@link #moveNode(jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.JaxxNode , int)}</li> - * <li>{@link #refreshNode(jaxx.runtime.swing.nav.JaxxNode , boolean)}</li> - * <li>{@link #loadAllNodes(jaxx.runtime.swing.nav.JaxxDelegateTreeModel , jaxx.runtime.swing.nav.JaxxNode , jaxx.runtime.swing.nav.DataProvider)}</li> - * <p/> - * </ul> - * <h3>Model selection modification</h3> - * <ul> - * <li>{@link #selectNode(jaxx.runtime.swing.nav.JaxxNode)}</li> - * <li>{@link #selectNode(String...)}</li> - * <li>{@link #selectParentNode()}</li> - * </ul> - * <h3>Model query</h3> - * <ul> - * <li>{@link #findNode(jaxx.runtime.swing.nav.JaxxNode , String...)}</li> - * </ul> - * <h3>Child loadors factory</h3> - * The class offers a factory of {@link jaxx.runtime.swing.nav.JaxxNodeChildLoador}, use the method - * {@link #getChildLoador(Class)} to obtain the correct child loador given his type. - * - * @author tchemit <chemit@codelutin.com> - * @see jaxx.runtime.swing.nav.JaxxNode - * @see jaxx.runtime.swing.nav.JaxxNodeChildLoador - * @see AbstractJaxxTreeCellRenderer - * @since 2.1 - */ -public class JaxxTreeHelper<N extends JaxxNode<N>> { - - /** Logger */ - static private final Log log = LogFactory.getLog(JaxxTreeHelper.class); - - /** - * The shared instance of tree model. - * <p/> - * A helper deals with only ONE model (this one), becuase we add some - * listeners on it, we prefer always to keep ONE instance (any way this is - * a good thing). - * <p/> - * If you want to create a new model, just creates the good root node and - * push it in this model. - * <p/> - * <b>Note:</b> The model of the registred {@link #tree} can be different - * from this one. - * <p/> - * For example, if you wrap the shared model with a filter model... Anyway, all - * listeners of this helper apply always of THIs model. - */ - protected JaxxDelegateTreeModel<N> model; - - /** - * The shared instance of tree. - * <p/> - * A helper deleas with only ONE tree (this one), becuase we add some listeners - * on it, we prefer always to kepp ONE safe instance. - * <p/> - * If you need to work with more than one helper, please instanciat a new - * helper for each tree. - */ - protected JTree tree; - - /** - * The shared instance of treeTable. - * <p/> - * A helper deleas with only ONE tree (this one), becuase we add some listeners - * on it, we prefer always to kepp ONE safe instance. - * <p/> - * If you need to work with more than one helper, please instanciat a new - * helper for each tree. - */ - protected JXTreeTable treeTable; - - /** The shared data provider used to obtain datas to populate nodes and render them. */ - protected DataProvider dataProvider; - - /** - * A {@link TreeWillExpandListener} used to listen when tree should expand. - * <p/> - * If so, the listener will load selected node childs if required - * (says when the {@link jaxx.runtime.swing.nav.JaxxNode#isLoaded()} is sets to {@code false}). - */ - protected TreeWillExpandListener expandListener; - - /** - * pour ouvrir les fils d'un noeud que l'on vient de sélectionner pour - * éviter d'avoir à faire des doubles clics. - */ - protected TreeSelectionListener selectionListener; - - /** - * pour recharger le rendu des noeuds (et charger les fils si nécessaires) - * lors d'une modification dans le modèle de l'arbre. - */ - protected TreeModelListener treeModelListener; - - /** Cache of child loadors. */ - protected static Set<? super JaxxNodeChildLoador<?, ?, ?>> childLoadors; - - protected static Set<? super JaxxNodeChildLoador<?, ?, ?>> getChildLoadors() { - if (childLoadors == null) { - childLoadors = new HashSet<JaxxNodeChildLoador<?, ?, ?>>(); - } - return childLoadors; - } - - /** - * Obtains the {@link JaxxNodeChildLoador} of the given {@code type} from - * internal cache. - * <p/> - * <b>Note:</b> The loador will be instanciated if not found, and push in cache. - * - * @param type the type of loador to get - * @param <L> the type of loador to get - * @return the loador from cache - */ - @SuppressWarnings({"unchecked"}) - public static <L extends JaxxNodeChildLoador<?, ?, ?>> L getChildLoador(Class<L> type) { - Set<? super JaxxNodeChildLoador<?, ?, ?>> cache = getChildLoadors(); - JaxxNodeChildLoador<?, ?, ?> result = null; - for (Object loador : cache) { - if (type.equals(loador.getClass())) { - result = (JaxxNodeChildLoador<?, ?, ?>) loador; - break; - } - } - if (result == null) { - // add it in cache - try { - result = type.newInstance(); - cache.add(result); - if (log.isDebugEnabled()) { - log.debug("Add " + result + " in loadors cache (new size:" + cache.size() + ")."); - } - } catch (Exception e) { - throw new IllegalArgumentException("Could not instanciate loador [" + type.getName() + "]", e); - } - } - return (L) result; - } - - public JaxxTreeHelper() { - - selectionListener = new TreeSelectionListener() { - - @Override - public void valueChanged(TreeSelectionEvent e) { - if (!checkModel()) { - return; - } - - // Hack, because event.getSource for TreeTable doesnt return selectionModel - TreeSelectionModel source = getSelectionModel(); - - if (source.isSelectionEmpty()) { - - // empty selection - if (log.isDebugEnabled()) { - log.debug("Selection is empty."); - } - return; - } - - boolean debugEnabled = log.isDebugEnabled(); - boolean traceEnabled = log.isTraceEnabled(); - for (TreePath path : e.getPaths()) { - - N node = getNode(path); - if (node == null) { - - // pas de noeud selectionne - if (debugEnabled) { - log.debug("Skip for null node."); - } - continue; - } - - boolean isAdded = e.isAddedPath(path); - - TreePath pathToExpand = new TreePath(model.getPathToRoot(node)); - boolean pathExpanded = isExpanded(pathToExpand); - - if (traceEnabled || isAdded && debugEnabled) { - log.debug("==== Node selection ===================================="); - log.debug("node ? " + node); - log.debug("is added ? " + isAdded); - log.debug("is path expanded ? " + pathExpanded); - log.debug("is node static ? " + node.isStaticNode()); - log.debug("is node loaded ? " + node.isLoaded()); - log.debug("is node leaf ? " + node.isLeaf()); - log.debug("node nb childs ? " + node.getChildCount()); - } - - if (isAdded && !pathExpanded) { - - // ask to expand path - log.info("expand node [" + pathToExpand + "]"); - expandPath(pathToExpand); - } - } - } - }; - expandListener = new TreeWillExpandListener() { - @Override - public void treeWillExpand(TreeExpansionEvent event) { - - if (!checkModel()) { - // no model - return; - } - - N source = getNode(event.getPath()); - - if (source.isLoaded()) { - - // node is already loaded, nothing to do - return; - } - - if (log.isDebugEnabled()) { - log.debug("will load childs of node [" + source + "]"); - } - // populate childs of node - source.populateChilds(model, getDataProvider()); - } - - @Override - public void treeWillCollapse(TreeExpansionEvent event) { - } - }; - - - treeModelListener = new TreeModelListener() { - @Override - public void treeNodesInserted(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("inserted ", source, children)); - } - - // ask to populate children nodes - populateNode(null, children, false); - } - - @SuppressWarnings({"unchecked"}) - @Override - public void treeNodesRemoved(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("removed ", source, children)); - } - - // Invalidates nodes in renderer cache (if any) - AbstractJaxxTreeCellRenderer<N> renderer = getTreeCellRenderer(); - if (children != null && renderer != null) { - for (Object child : children) { - renderer.invalidateCache((N) child); - } - } - } - - @Override - public void treeNodesChanged(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("changed ", source, children)); - } - - // ask to populate modified child nodes - populateNode(null, children, false); - } - - @Override - public void treeStructureChanged(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("structure changed", source, children)); - } - - // ask to populate structure modified node and nodes recursively - populateNode(source, children, true); - } - - protected String getMessage(String action, N source, Object[] children) { - StringBuilder sb = new StringBuilder(); - sb.append("==== Nodes "); - sb.append(action); - sb.append(" ================="); - sb.append("\nsource : ").append(source); - sb.append("\nnb nodes : "); - sb.append(children == null ? 0 : children.length); - if (children != null) { - int i = 0; - for (Object child : children) { - sb.append("\n ["); - sb.append(i++); - sb.append("] - "); - sb.append(child); - } - } - return sb.toString(); - } - }; - } - - /** - * Obtains the attached data provider used to populate and render nodes. - * - * @return the attached data provider - */ - protected DataProvider getDataProvider() { - return dataProvider; - } - - /** - * Obtains the registred tree. - * - * @return the registred tree for this helper or {@code null} if none was registred - */ - public JTree getTree() { - return tree; - } - - /** - * Obtains the registred tree table. - * - * @return the registred tree table for this helper or {@code null} if none was registred - */ - public JXTreeTable getTreeTable() { - return treeTable; - } - - /** - * Obtains the jaxx delegate tree model - * - * @return the internal tree model or {@code null} if none was created. - */ - public JaxxDelegateTreeModel<N> getModel() { - return model; - } - - /** - * Obtains the internal tree table model. - * - * @return the internal tree table model or {@code null} if none was created. - */ - public DefaultTreeModel getTreeModel() { - return model.getTreeDelegateModel(); - } - - /** - * Obtains the internal tree table model. - * - * @return the internal tree table model or {@code null} if none was created. - */ - public JaxxTreeTableModel getTreeTableModel() { - return model.getTreeTableDelegateModel(); - } - - public N getRootNode() { - if (!checkModel()) { - return null; - } - return model.getRoot(); - } - - /** - * Obtains the {@link AbstractJaxxTreeCellRenderer} renderer of the - * registred tree. - * - * @return the renderer of the registred tree or null if no tree was - * registred nor the renderer is a {@link AbstractJaxxTreeCellRenderer}. - */ - @SuppressWarnings({"unchecked"}) - public AbstractJaxxTreeCellRenderer<N> getTreeCellRenderer() { - JTree t = getTree(); - if (t == null) { - return null; - } - TreeCellRenderer r = t.getCellRenderer(); - if (r instanceof AbstractJaxxTreeCellRenderer<?>) { - return (AbstractJaxxTreeCellRenderer<N>) r; - } - return null; - } - - /** - * Obtains the selected node of the registred tree. - * - * @return the selected tree or {@code null} if no registred tree nor - * selection empty. - */ - public N getSelectedNode() { - JTree tree = getTree(); - if (tree == null) { - return null; - } - TreePath path = tree.getSelectionPath(); - N node = null; - if (path != null) { - node = getNode(path); - } - return node; - } - - /** - * Obtains the path of ids fro the root node to the selected node on the - * registred tree. - * - * @return the array of ids from root node to selected node. - */ - public String[] getSelectedIds() { - List<String> result = new ArrayList<String>(); - N selectedNode = getSelectedNode(); - while (selectedNode != null && !selectedNode.isRoot()) { - - result.add(selectedNode.getId()); - selectedNode = selectedNode.getParent(); - } - Collections.reverse(result); - return result.toArray(new String[result.size()]); - } - - /** - * Registers the {@code dataProvider} for the helper. - * <p/> - * <b>Node:</b> As a side-effect, the provider will be propagate to the - * renderer of the registred tree (if any). - * - * @param dataProvider the data provider to use - */ - public void setDataProvider(DataProvider dataProvider) { - this.dataProvider = dataProvider; - AbstractJaxxTreeCellRenderer<N> renderer = getTreeCellRenderer(); - if (renderer != null) { - - // dispatch provider to renderer - renderer.setDataProvider(dataProvider); - } - } - - /** - * Registers the given {@code tree} for this helper. - * <p/> - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and the {@link #selectionListener}. - * - * @param tree the tree to register - * @param addExpandTreeListener a flag to add expand listener - * @param listener the optional selection listener to add - */ - public void setTree(JTree tree, - boolean addExpandTreeListener, - TreeSelectionListener listener) { - this.tree = tree; - if (addExpandTreeListener) { - this.tree.addTreeWillExpandListener(expandListener); - } - if (listener != null) { - this.tree.getSelectionModel().addTreeSelectionListener(listener); - } - this.tree.getSelectionModel().addTreeSelectionListener(selectionListener); - } - - /** - * Registers the given {@code treeTable} for this helper. - * <p/> - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and the {@link #selectionListener}. - * - * @param treeTable the tree table to register - * @param addExpandTreeListener a flag to add expand listener - * @param listener the optional selection listener to add - */ - public void setTreeTable(JXTreeTable treeTable, - boolean addExpandTreeListener, - TreeSelectionListener listener) { - this.treeTable = treeTable; - if (addExpandTreeListener) { - this.treeTable.addTreeWillExpandListener(expandListener); - } - if (listener != null) { - this.treeTable.addTreeSelectionListener(listener); - } - this.treeTable.addTreeSelectionListener(selectionListener); - } - - /** - * Inserts the given node to the given {@code parentNode}. - * <p/> - * The node will be added to his parent, then creation listeners will be - * fired. - * - * @param parentNode the parent node where to insert the new node * - * @param newNode the node to insert - */ - public void insertNode(N parentNode, N newNode) { - parentNode.add(newNode); - if (!model.isTreeTable()) { - model.notifyNodeInserted(newNode); - } else { - model.nodeStructureChanged(parentNode); - } - } - - /** - * Removes the given {@code node} from the registred tree model and returns - * his parent. - * - * @param node the node to remove - * @return the parent node of the removed node. - */ - public N removeNode(N node) { - N parentNode = node.getParent(); - model.removeNodeFromParent(node); - return parentNode; - } - - /** - * Moves the given {@code node} to the new {@code position}. - * - * @param parentNode the parent node - * @param node the node to move - * @param position the new position of the node - */ - public void moveNode(N parentNode, N node, int position) { - parentNode.remove(node); - parentNode.insert(node, position); - model.nodeStructureChanged(parentNode); - } - - /** - * Refreshs the given {@code node}. - * <p/> - * If flag {@code deep} is set to {@code true}, then it will refresh - * recursively children nodes. - * <p/> - * <b>Note:</b>As a side-effect, evvery node involved will become - * {@code dirty}. - * - * @param node the node to refresh - * @param deep un flag pour activer la repainte de la descendance du - * noeud - * @see jaxx.runtime.swing.nav.JaxxNode#isDirty() - */ - @SuppressWarnings({"unchecked"}) - public void refreshNode(N node, boolean deep) { - if (log.isDebugEnabled()) { - log.debug("Will refresh (deep ? " + deep + ") node " + node); - } - model.nodeChanged(node); - if (deep) { - // repaint childs nodes - Enumeration<N> e = node.children(); - while (e.hasMoreElements()) { - N child = e.nextElement(); - refreshNode(child, true); - } - } - } - - /** - * To load all nodes of a model. - * - * @param model the tree model owner of nodes - * @param node the root node to load - * @param dataProvider the data provider used to populate nodes - */ - @SuppressWarnings({"unchecked"}) - public void loadAllNodes(JaxxDelegateTreeModel<N> model, - N node, - DataProvider dataProvider) { - if (!checkModel()) { - return; - } - if (!node.isLoaded()) { - node.populateChilds(model, dataProvider); - Enumeration<? extends JaxxNode<?>> enumeration = node.children(); - while (enumeration.hasMoreElements()) { - N jaxxNode = (N) enumeration.nextElement(); - loadAllNodes(model, jaxxNode, dataProvider); - } - } - } - - /** - * Selects the parent of the currently selected node. - * <p/> - * <b>Note:</> If selection is empty, then throws a NPE. - * - * @throws NullPointerException if selection is empty - */ - public void selectParentNode() throws NullPointerException { - - N node = getSelectedNode(); - - if (node == null) { - // pas de noeud selectionne - throw new NullPointerException("no selected node in context"); - } - node = node.getParent(); - - selectNode(node); - } - - /** - * Selects the given {@code node} in the registred tree. - * - * @param node the node to select - */ - public void selectNode(N node) { - if (!checkModel()) { - - // no model - return; - } - if (log.isDebugEnabled()) { - log.debug("try to select node [" + node + "]"); - } - TreePath path = new TreePath(model.getPathToRoot(node)); - - setSelectionPath(path); - scrollPathToVisible(path); - } - - /** - * Selects the node described by his given {@code path} of ids. - * - * @param path the absolute path of ids from root node to node to select. - */ - public void selectNode(String... path) { - if (!checkModel()) { - - // no model - return; - } - if (log.isDebugEnabled()) { - log.debug("try to select node from ids " + Arrays.toString(path)); - } - N root = model.getRoot(); - N node = findNode(root, path); - if (log.isDebugEnabled()) { - log.debug("selected node [" + node + "]"); - } - if (node != null) { - selectNode(node); - } - } - - /** - * Finds a node from the given root {@code node}, applying the path given - * by {@code ids}. - * - * @param node the starting node - * @param ids the path of ids to apply on the node. - * @return the find node or {@code null} if no node matchs. - */ - public N findNode(N node, String... ids) { - if (!checkModel()) { - - // no model - return null; - } - N result = null; - for (String id : ids) { - - result = node.findNodeById(id, model, getDataProvider()); - - if (result == null) { - - // un des noeud n'a pas ete trouve, on sort - break; - } - node = result; - } - return result; - } - - /** - * Register a new root node. - * <p/> - * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, - * otherwise just set the new root on the existing model. - * <p/> - * <p/> - * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} - * and the {@link #treeModelListener} will be registred on this model. - * - * @param node the root node of the new model - * @return the new model - * @deprecated use registerTreeModel - */ - @Deprecated - protected JaxxDelegateTreeModel createModel(N node) { - return createTreeModel(node); - } - - /** - * Register a new root node for tree. - * - * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, - * otherwise just set the new root on the existing model. - * <p/> - * - * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} - * and the {@link #treeModelListener} will be registred on this model. - * - * @param node the root node of the new model - * @return the new model - */ - protected JaxxDelegateTreeModel<N> createTreeModel(N node) { - DefaultTreeModel delegate = new DefaultTreeModel(node); - if (model == null) { - model = new JaxxDelegateTreeModel<N>(delegate); - model.addTreeModelListener(treeModelListener); - } else { - model.setRoot(node); - } - - // notify structure has changed - model.nodeStructureChanged(getRootNode()); - return model; - } - - /** - * Register a new root node for tree table. - * - * If internal {@link #model} does not exists, creates a new one from his given root {@code node}, - * otherwise just set the new root on the existing model. - * <p/> - * - * <b>Note:</b> As a side-effect, the model will be keep in field {@link #model} - * and the {@link #treeModelListener} will be registred on this model. - * - * @param delegate model for tree table - * @param node the root node of the new model - * @return the tree model model - */ - protected JaxxDelegateTreeModel<N> createTreeTableModel(JaxxTreeTableModel.MyDefaultTreeTableModel delegate, N node) { - JaxxTreeTableModel tableModel = new JaxxTreeTableModel(delegate); - if (model == null) { - model = new JaxxDelegateTreeModel<N>(tableModel); - model.addTreeModelListener(treeModelListener); - } - model.setRoot(node); - - // notify structure has changed - model.nodeStructureChanged(getRootNode()); - return model; - } - - /** - * Checks if internal model was created. - * - * @return {@code true} if model was created - * (should be done via {@link #createModel(JaxxNode)} method), - * {@code false} otherwise. - */ - protected boolean checkModel() { - if (model == null) { - - // no model set, - log.warn("No model set in " + this); - return false; - } - // model is set - return true; - } - - /** - * Populates nodes. - * <p/> - * If {@code node} is not {@code null}, then populate it. - * <p/> - * If {@code children} is not {@code null}, then populate them, moreover - * if {@code recurse} is set to {@code true} then do a recurse refresh on - * children. - * - * @param node the parent node to populate (optional) - * @param children the child nodes to populate (optional) - * @param recurse flag sets to {@code true} if should do recurse refresh on - * given {@code children} nodes. - */ - @SuppressWarnings({"unchecked"}) - protected void populateNode(N node, - Object[] children, - boolean recurse) { - DataProvider dataProvider = getDataProvider(); - if (node != null) { - if (log.isDebugEnabled()) { - log.debug("Will populate node : " + node); - } - node.populateNode(model, dataProvider, false); - } - if (children != null) { - for (Object o : children) { - N child = (N) o; - if (log.isDebugEnabled()) { - log.debug("Will populate child node : " + child); - } - child.populateNode(model, dataProvider, recurse); - } - } - } - - /** - * Convinient method to objet the casted node of a {@link TreePath}. - * - * @param path the path contaning the node. - * @return the casted node from the path. - */ - @SuppressWarnings({"unchecked"}) - protected N getNode(TreePath path) { - N result = (N) path.getLastPathComponent(); - return result; - } - - //-------------------------------------------------------------------------- - //-- Methode to switch between tree and tree table - //-------------------------------------------------------------------------- - - public void scrollPathToVisible(TreePath path) { - JTree tree = getTree(); - if (tree != null) { - tree.scrollPathToVisible(path); - return; - } - getTreeTable().scrollPathToVisible(path); - } - - public void setSelectionPath(TreePath path) { - JTree tree = getTree(); - if (tree != null) { - tree.setSelectionPath(path); - return; - } - getTreeTable().getTreeSelectionModel().setSelectionPath(path); - } - - public TreeSelectionModel getSelectionModel() { - JTree tree = getTree(); - if (tree != null) { - return tree.getSelectionModel(); - } - return getTreeTable().getTreeSelectionModel(); - } - - public boolean isExpanded(TreePath pathToExpand) { - JTree tree = getTree(); - if (tree != null) { - return tree.isExpanded(pathToExpand); - } - return getTreeTable().isExpanded(pathToExpand); - } - - public void expandPath(TreePath pathToExpand) { - JTree tree = getTree(); - if (tree != null) { - tree.expandPath(pathToExpand); - return; - } - getTreeTable().expandPath(pathToExpand); - } -} Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNode.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNode.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNode.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -36,64 +36,11 @@ import java.util.Enumeration; /** - * Definition of a node with a optional {@link #childLoador} to build childs of - * node. - * <p/> - * A node is identified by an {@link #id} of an associated data of type - * {@link #internalClass}. - * <p/> - * <b>Note:</b> - * <p><i> While using a {@link #childLoador}, we can not know before node - * was loaded the exact count of his childs. As a matter of facts, real leaf - * nodes appears at the beginning in ui as a not leaf (there is a root handler). - * When node was loaded, a leaf node will be then displayed as required. - * </i></p> - * <p/> - * <h2>Why JaxxNode is generic ?</h2> - * In a project, you should implements your own Node extending with one like this : - * <pre> - * class MyNode extends JaxxNode<MyNode> { ... } - * </pre> - * While in this class, you overrides every method with a node return type, - * co-variance you'll be able to use this code : - * <pre> - * MyNode parentNode = new MyNode(); - * MyNode node = parentNode.getFirstNode(); - * </pre> - * So for final application this generic type avoid any cast for your own node - * type, this is quite convinient. - * <p/> - * Even if in your project, you wants to have a heriarchy of nodes, this will - * still works (if you use a genercic type on your abstract nodes). - * <h2>Internal states</h2> - * <ul> - * <li><b>internalClass</b> : the type of data associated with the node</li> - * <li><b>context</b> : an optinal context to distinguish different types of - * node with same {@code internalclass}</li> - * <li><b>id</b> : id of the data associated with the node</li> - * <li><b>dirty</b> : flag sets to {@code true} when node render MUST be recomputed</li> - * <li><b>loaded</b> : flag sets to {@code true} when node was loaded</li> - * <li><b>childLoador</b> : optional loador of childs</li> - * </ul> - * <h2>Static nodes</h2> - * Some nodes do not need auto-loading, we call them {@code static nodes}. - * The method {@link #isStaticNode()} gives this state. - * <p/> - * <b>Note:</b> A static node has no {@link #childLoador}. - * <h2>Node loading</h2> - * Initialy node has no data child nodes, ({@link #isLoaded()} equals - * {@code false}). - * when model requires node's childs, it can load them via method - * {@link #populateNode(javax.swing.tree.DefaultTreeModel , jaxx.runtime.swing.nav.DataProvider , boolean)} - * and {@link #populateChilds(javax.swing.tree.DefaultTreeModel , jaxx.runtime.swing.nav.DataProvider)} methods. - * <h2>Node rendering</h2 - * the {@link AbstractJaxxTreeCellRenderer} looks the {@link #dirty} state to - * know when render should be (re-)compute and set back the state to {@code false}. - * <p/> - * Each time, a node is modified, the {@link #dirty} should be set to {@code true}. + * Implementation of {@link JaxxNode} used to create in tree table + * This node extends {@link DefaultMutableTreeNode} * * @author tchemit <chemit@codelutin.com> - * @since 2.1 + * @since 2.2 */ public class JaxxTreeNode<N extends JaxxTreeNode<N>> extends DefaultMutableTreeNode implements JaxxNode<N> { @@ -145,53 +92,42 @@ } } + @Override public String getId() { return id; } + @Override public String getContext() { return context; } + @Override public Class<?> getInternalClass() { return internalClass; } + @Override public boolean isLoaded() { return loaded; } + @Override public boolean isDirty() { return dirty; } - /** - * Convinient method to known if the node is a {@code String} typed. - * - * @return {@code true} if the type of node if - */ + @Override public boolean isStringNode() { return String.class.equals(internalClass); } - /** - * To know if the node is static. - * <p/> - * A {@code static} node has no {@link #childLoador}. - * - * @return {@code true} when the node is static : says, the node has - * no {@link #childLoador}. - */ + @Override public boolean isStaticNode() { return childLoador == null; } - /** - * Gets the first node form this one to the root which has a none - * {@code String} type. - * - * @return the first concrete node type - */ + @Override @SuppressWarnings({"unchecked"}) public N getContainerNode() { if (isRoot()) { @@ -209,18 +145,7 @@ return (N) this; } - /** - * Given an {@code id}, obtain the child with matching id. - * <p/> - * If node is NOT {@code loaded}, then first loads it (method - * {@link #populateChilds(jaxx.runtime.swing.nav.JaxxDelegateTreeModel , jaxx.runtime.swing.nav.DataProvider)}) then do search - * on direct childs of the node. - * - * @param id the id of the researched node - * @param model model owner of nodes - * @param provider data provider - * @return the found node or {@code null} if not found - */ + @Override @SuppressWarnings({"unchecked"}) public N findNodeById(String id, JaxxDelegateTreeModel<N> model, @@ -262,14 +187,7 @@ return null; } - /** - * Changes the {@link #dirty} state. - * <p/> - * As a side effect, when a renderer will use this node, it will force to - * reload the render from the {@link DataProvider}. - * - * @param dirty the new dirty value - */ + @Override public void setDirty(boolean dirty) { this.dirty = dirty; } @@ -299,17 +217,7 @@ //-- Populate methods //-------------------------------------------------------------------------- - /** - * To populate the node. A side-effect of this method is to set {@code dirty} - * the node (renderer will recompute the render of the node). - * <p/> - * If {@code populateChilds} is set to {@code true}, then also populate - * childs of the node using the given {@code dataProvider}. - * - * @param model le modèles content le noeud - * @param provider le provider de données - * @param populateChilds un drapeau pour charger aussi les fils du noeud courant - */ + @Override public void populateNode(JaxxDelegateTreeModel<N> model, DataProvider provider, boolean populateChilds) { @@ -324,15 +232,7 @@ } } - /** - * To populate childs of the node (only when a none static node). - * A side-effect of this method is to set {@code loaded} of the node. - * <p/> - * For a static node, do nothing. - * - * @param model model owner of the node - * @param provider data provider - */ + @Override @SuppressWarnings({"unchecked"}) public void populateChilds(JaxxDelegateTreeModel<N> model, DataProvider provider) { if (isStaticNode()) { Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNodeChildLoador.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNodeChildLoador.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/JaxxTreeNodeChildLoador.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -26,6 +26,12 @@ import jaxx.runtime.swing.nav.JaxxNodeChildLoador; +/** + * Implementation for tree of {@link JaxxNodeChildLoador} + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ public abstract class JaxxTreeNodeChildLoador<T, O, N extends JaxxTreeNode<N>> extends JaxxNodeChildLoador<T, O, N> { protected JaxxTreeNodeChildLoador(Class<O> beanType) { Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableModel.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableModel.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -38,7 +38,7 @@ /** * Model of the tree table used for a jaxx tree table api. * - * @author sletellier + * @author sletellier <letellier@codelutin.com> * @since 2.2 */ public class JaxxTreeTableModel implements TreeTableModel { @@ -46,10 +46,8 @@ /** * Logger */ - static private final Log log = - LogFactory.getLog(JaxxTreeTableModel.class); + static private final Log log = LogFactory.getLog(JaxxTreeTableModel.class); - /** * Hack to acces to the modelSupport * @@ -139,6 +137,10 @@ delegate.setRoot(root); } + //-------------------------------------------------------------------------- + //-- Overrides delegate methode + //-------------------------------------------------------------------------- + @Override public TreeTableNode getRoot() { return delegate.getRoot(); Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNode.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNode.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNode.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -34,64 +34,12 @@ import java.util.Enumeration; /** - * Definition of a node with a optional {@link #childLoador} to build childs of - * node. - * <p/> - * A node is identified by an {@link #id} of an associated data of type - * {@link #internalClass}. - * <p/> - * <b>Note:</b> - * <p><i> While using a {@link #childLoador}, we can not know before node - * was loaded the exact count of his childs. As a matter of facts, real leaf - * nodes appears at the beginning in ui as a not leaf (there is a root handler). - * When node was loaded, a leaf node will be then displayed as required. - * </i></p> - * <p/> - * <h2>Why JaxxNode is generic ?</h2> - * In a project, you should implements your own Node extending with one like this : - * <pre> - * class MyNode extends JaxxNode<MyNode> { ... } - * </pre> - * While in this class, you overrides every method with a node return type, - * co-variance you'll be able to use this code : - * <pre> - * MyNode parentNode = new MyNode(); - * MyNode node = parentNode.getFirstNode(); - * </pre> - * So for final application this generic type avoid any cast for your own node - * type, this is quite convinient. - * <p/> - * Even if in your project, you wants to have a heriarchy of nodes, this will - * still works (if you use a genercic type on your abstract nodes). - * <h2>Internal states</h2> - * <ul> - * <li><b>internalClass</b> : the type of data associated with the node</li> - * <li><b>context</b> : an optinal context to distinguish different types of - * node with same {@code internalclass}</li> - * <li><b>id</b> : id of the data associated with the node</li> - * <li><b>dirty</b> : flag sets to {@code true} when node render MUST be recomputed</li> - * <li><b>loaded</b> : flag sets to {@code true} when node was loaded</li> - * <li><b>childLoador</b> : optional loador of childs</li> - * </ul> - * <h2>Static nodes</h2> - * Some nodes do not need auto-loading, we call them {@code static nodes}. - * The method {@link #isStaticNode()} gives this state. - * <p/> - * <b>Note:</b> A static node has no {@link #childLoador}. - * <h2>Node loading</h2> - * Initialy node has no data child nodes, ({@link #isLoaded()} equals - * {@code false}). - * when model requires node's childs, it can load them via method - * {@link #populateNode(javax.swing.tree.DefaultTreeModel , DataProvider, boolean)} - * and {@link #populateChilds(javax.swing.tree.DefaultTreeModel , DataProvider)} methods. - * <h2>Node rendering</h2 - * the {@link jaxx.runtime.swing.nav.tree.AbstractJaxxTreeCellRenderer} looks the {@link #dirty} state to - * know when render should be (re-)compute and set back the state to {@code false}. - * <p/> - * Each time, a node is modified, the {@link #dirty} should be set to {@code true}. + * Implementation of {@link JaxxNode} used to create in tree table + * This node extends {@link DefaultMutableTreeTableNode} used by + * {@link org.jdesktop.swingx.JXTreeTable} * - * @author tchemit <chemit@codelutin.com> - * @since 2.1 + * @author sletellier <letellier@codelutin.com> + * @since 2.2 */ public class JaxxTreeTableNode<N extends JaxxTreeTableNode<N>> extends DefaultMutableTreeTableNode implements JaxxNode<N> { @@ -143,53 +91,42 @@ } } + @Override public String getId() { return id; } + @Override public String getContext() { return context; } + @Override public Class<?> getInternalClass() { return internalClass; } + @Override public boolean isLoaded() { return loaded; } + @Override public boolean isDirty() { return dirty; } - /** - * Convinient method to known if the node is a {@code String} typed. - * - * @return {@code true} if the type of node if - */ + @Override public boolean isStringNode() { return String.class.equals(internalClass); } - /** - * To know if the node is static. - * <p/> - * A {@code static} node has no {@link #childLoador}. - * - * @return {@code true} when the node is static : says, the node has - * no {@link #childLoador}. - */ + @Override public boolean isStaticNode() { return childLoador == null; } - /** - * Gets the first node form this one to the root which has a none - * {@code String} type. - * - * @return the first concrete node type - */ + @Override @SuppressWarnings({"unchecked"}) public N getContainerNode() { if (isRoot()) { @@ -211,18 +148,7 @@ return getParent() == null; } - /** - * Given an {@code id}, obtain the child with matching id. - * <p/> - * If node is NOT {@code loaded}, then first loads it (method - * {@link #populateChilds(jaxx.runtime.swing.nav.JaxxDelegateTreeModel , DataProvider)}) then do search - * on direct childs of the node. - * - * @param id the id of the researched node - * @param model model owner of nodes - * @param provider data provider - * @return the found node or {@code null} if not found - */ + @Override @SuppressWarnings({"unchecked"}) public N findNodeById(String id, JaxxDelegateTreeModel<N> model, @@ -264,14 +190,7 @@ return null; } - /** - * Changes the {@link #dirty} state. - * <p/> - * As a side effect, when a renderer will use this node, it will force to - * reload the render from the {@link DataProvider}. - * - * @param dirty the new dirty value - */ + @Override public void setDirty(boolean dirty) { this.dirty = dirty; } @@ -301,17 +220,7 @@ //-- Populate methods //-------------------------------------------------------------------------- - /** - * To populate the node. A side-effect of this method is to set {@code dirty} - * the node (renderer will recompute the render of the node). - * <p/> - * If {@code populateChilds} is set to {@code true}, then also populate - * childs of the node using the given {@code dataProvider}. - * - * @param model le modèles content le noeud - * @param provider le provider de données - * @param populateChilds un drapeau pour charger aussi les fils du noeud courant - */ + @Override public void populateNode(JaxxDelegateTreeModel<N> model, DataProvider provider, boolean populateChilds) { @@ -326,15 +235,7 @@ } } - /** - * To populate childs of the node (only when a none static node). - * A side-effect of this method is to set {@code loaded} of the node. - * <p/> - * For a static node, do nothing. - * - * @param model model owner of the node - * @param provider data provider - */ + @Override @SuppressWarnings({"unchecked"}) public void populateChilds(JaxxDelegateTreeModel<N> model, DataProvider provider) { if (isStaticNode()) { Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNodeChildLoador.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNodeChildLoador.java 2010-06-29 16:09:09 UTC (rev 2009) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/JaxxTreeTableNodeChildLoador.java 2010-06-29 22:50:39 UTC (rev 2010) @@ -26,6 +26,12 @@ import jaxx.runtime.swing.nav.JaxxNodeChildLoador; +/** + * Implementation for tree table of {@link JaxxNodeChildLoador} + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ public abstract class JaxxTreeTableNodeChildLoador<T, O, N extends JaxxTreeTableNode<N>> extends JaxxNodeChildLoador<T, O, N> { protected JaxxTreeTableNodeChildLoador(Class<O> beanType) {
participants (1)
-
sletellier@users.nuiton.org