/** * Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org> * * This file is part of org.appwork.utils.swing * * This software is licensed under the Artistic License 2.0, * see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php * for details */ package org.appwork.utils.swing; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; import javax.swing.JTree; import javax.swing.tree.TreePath; import org.appwork.utils.logging.Log; /** * This class is used to save the selection states and expanded states of each * tree node before rebuilding the tree. After rebuilding, the model is able to * restore these states. * * @author $Author: unknown$ * */ public class TreeModelStateSaver { protected JTree tree; /** * Stores for each node the expanded state */ private final HashMap<Object, Boolean> expandCache; /** * treePath for internal use */ private TreePath treePath; /** * Stores all selected Pathes */ protected TreePath[] selectedPathes; /** * @param tree */ public TreeModelStateSaver(final JTree tree) { this.tree = tree; this.expandCache = new HashMap<Object, Boolean>(); } /** * @return the expandCache */ public HashMap<Object, Boolean> getExpandCache() { return this.expandCache; } /** * @return the {@link TreeModelStateSaver#selectedPathes} * @see TreeModelStateSaver#selectedPathes */ public TreePath[] getSelectedPathes() { return this.selectedPathes; } /** * Restore the saved tree state */ public void restore() { new EDTHelper<Object>() { @Override public Object edtRun() { try { if (TreeModelStateSaver.this.tree.getModel() != null) { TreeModelStateSaver.this.restoreState(TreeModelStateSaver.this.tree.getModel().getRoot(), new ArrayList<Object>()); } final TreePath[] selectedPathes = TreeModelStateSaver.this.getSelectedPathes(); if (selectedPathes != null && selectedPathes.length > 0) { TreeModelStateSaver.this.tree.getSelectionModel().clearSelection(); TreeModelStateSaver.this.tree.getSelectionModel().setSelectionPaths(selectedPathes); } } catch (Throwable e) { Log.exception(Level.WARNING, e); } return null; } }.start(); } protected void restoreState(final Object node, final ArrayList<Object> path) { new EDTHelper<Object>() { @Override public Object edtRun() { if (node == null) { return null; } path.add(node); TreeModelStateSaver.this.treePath = new TreePath(path.toArray(new Object[] {})); final Boolean bo = TreeModelStateSaver.this.expandCache.get(node); try { if (bo != null && bo.booleanValue()) { TreeModelStateSaver.this.tree.expandPath(TreeModelStateSaver.this.treePath); } } catch (final Throwable e) { Log.exception(Level.WARNING, e); } for (int i = 0; i < TreeModelStateSaver.this.tree.getModel().getChildCount(node); i++) { try { TreeModelStateSaver.this.restoreState(TreeModelStateSaver.this.tree.getModel().getChild(node, i), new ArrayList<Object>(path)); } catch (final Throwable e) { Log.exception(Level.WARNING, e); } } return null; } }.start(); } /** * Save the current state of the tree */ public void save() { if (this.tree.getModel() != null) { this.saveState(this.tree.getModel().getRoot(), new ArrayList<Object>()); } this.selectedPathes = this.tree.getSelectionPaths(); } /** * Saves the expaned states of each node to cacheMap runs rekursive * * @param root */ private void saveState(final Object node, final ArrayList<Object> path) { path.add(node); try { this.treePath = new TreePath(path.toArray(new Object[] {})); this.expandCache.put(node, this.tree.isExpanded(this.treePath)); } catch (final Exception e) { Log.exception(e); } final int max = this.tree.getModel().getChildCount(node); for (int i = 0; i < max; i++) { try { this.saveState(this.tree.getModel().getChild(node, i), new ArrayList<Object>(path)); } catch (final Exception e) { Log.exception(e); } this.tree.getModel().getChildCount(node); } } /** * @param selectedPathes * the selectedPathes to set */ public void setSelectedPathes(final TreePath[] selectedPathes) { this.selectedPathes = selectedPathes; } }