001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2006-2009 Pentaho 008// Copyright (C) 2006-2007 Cincom Systems, Inc. 009// Copyright (C) 2006-2007 JasperSoft 010// All Rights Reserved. 011*/ 012package mondrian.gui; 013 014import java.util.HashSet; 015import java.util.Set; 016import javax.swing.*; 017import javax.swing.event.*; 018import javax.swing.tree.DefaultTreeModel; 019import javax.swing.tree.TreePath; 020 021/** 022 * Helper to enable update the tree and keep expanded nodes expanded after 023 * reloading the tree. 024 * 025 * @author erik 026 */ 027public class JTreeUpdater 028 implements TreeExpansionListener, TreeSelectionListener 029{ 030 private JTree tree = null; 031 private Set<TreePath> expandedTreePaths = new HashSet<TreePath>(); 032 private TreePath[] selectedTreePaths = new TreePath[0]; 033 034 /** 035 * Constructor 036 * 037 * @param tree The tree to track 038 */ 039 public JTreeUpdater(JTree tree) { 040 this.tree = tree; 041 this.tree.addTreeExpansionListener(this); 042 this.tree.addTreeSelectionListener(this); 043 } 044 045 /** 046 * Call this method whenever you update the tree and needs it reloaded 047 */ 048 public synchronized void update() { 049 synchronized (this.tree) { 050 this.tree.removeTreeExpansionListener(this); 051 this.tree.removeTreeSelectionListener(this); 052 053 ((DefaultTreeModel) this.tree.getModel()).reload(); 054 for (TreePath treePath : expandedTreePaths) { 055 this.tree.expandPath(treePath); 056 } 057 this.tree.getSelectionModel().setSelectionPaths(selectedTreePaths); 058 this.tree.addTreeExpansionListener(this); 059 this.tree.addTreeSelectionListener(this); 060 } 061 } 062 063 public void treeExpanded(TreeExpansionEvent treeExpansionEvent) { 064 TreePath expandedPath = treeExpansionEvent.getPath(); 065 066 // remove all ancestors of eventpath from expandedpaths set. 067 Object[] paths = expandedTreePaths.toArray(); 068 for (int i = 0; i < paths.length; i++) { 069 TreePath path = (TreePath) paths[i]; 070 071 // Path is a descendant of event path if path contains all 072 // components that make eventpath. For example, if eventpath = [a,b] 073 // path=[a,b,c] then path is descendant of eventpath. 074 if (path.isDescendant(expandedPath)) { 075 expandedTreePaths.remove(path); 076 } 077 } 078 expandedTreePaths.add(expandedPath); 079 } 080 081 public void treeCollapsed(TreeExpansionEvent treeExpansionEvent) { 082 TreePath collapsedPath = treeExpansionEvent.getPath(); 083 expandedTreePaths.remove(collapsedPath); 084 085 // remove all descendants from expandedpaths set. 086 Object[] paths = expandedTreePaths.toArray(); 087 for (int i = 0; i < paths.length; i++) { 088 TreePath path = (TreePath) paths[i]; 089 090 // Path is a descendant of event path if path contains all 091 // components that make eventpath. For example, if eventpath = [a,b] 092 // path=[a,b,c] then path is descendant of eventpath. 093 if (collapsedPath.isDescendant(path)) { 094 expandedTreePaths.remove(path); 095 } 096 } 097 } 098 099 public void valueChanged(TreeSelectionEvent treeSelectionEvent) { 100 if (this.tree.getSelectionPaths() != null 101 && this.tree.getSelectionPaths().length > 0) 102 { 103 selectedTreePaths = 104 this.tree.getSelectionModel().getSelectionPaths(); 105 } 106 } 107} 108 109// End JTreeUpdater.java