001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032: package com.vividsolutions.jump.workbench.ui;
033:
034: import com.vividsolutions.jts.util.Assert;
035:
036: import com.vividsolutions.jump.util.Block;
037: import com.vividsolutions.jump.util.StringUtil;
038:
039: import java.awt.Color;
040: import java.awt.Component;
041: import java.awt.Font;
042:
043: import java.util.ArrayList;
044: import java.util.Arrays;
045: import java.util.Collection;
046: import java.util.List;
047: import java.util.Stack;
048:
049: import javax.swing.ImageIcon;
050: import javax.swing.JTree;
051: import javax.swing.event.TreeModelEvent;
052: import javax.swing.tree.DefaultTreeCellRenderer;
053: import javax.swing.tree.TreeCellRenderer;
054: import javax.swing.tree.TreeModel;
055: import javax.swing.tree.TreePath;
056:
057: public class TreeUtil {
058: public static TreeCellRenderer createSimpleTreeCellRenderer(
059: ImageIcon icon) {
060: return createSimpleTreeCellRenderer(null, icon, new JTree()
061: .getFont());
062: }
063:
064: /**
065: * @param text null to get the text by calling #toString on the value
066: */
067: public static TreeCellRenderer createSimpleTreeCellRenderer(
068: final String text, final ImageIcon icon, final Font font) {
069: return new DefaultTreeCellRenderer() {
070:
071: {
072: setOpenIcon(icon);
073: setClosedIcon(icon);
074: setLeafIcon(icon);
075:
076: //Transparent. [Jon Aquino]
077: setBackgroundNonSelectionColor(new Color(0, 0, 0, 0));
078: }
079:
080: public Component getTreeCellRendererComponent(JTree tree,
081: Object value, boolean sel, boolean expanded,
082: boolean leaf, int row, boolean hasFocus) {
083: Component component = super
084: .getTreeCellRendererComponent(tree,
085: (text == null) ? value : text, sel,
086: expanded, leaf, row, hasFocus);
087: component.setFont(font);
088:
089: return component;
090: }
091: };
092: }
093:
094: public static void visit(TreeModel model, Visitor visitor) {
095: Stack path = new Stack();
096: path.push(model.getRoot());
097: visit(model, path, visitor);
098: }
099:
100: /**
101: * Visit the path and all subpaths.
102: */
103: public static void visit(TreeModel model, TreePath path,
104: Visitor visitor) {
105: Stack stack = new Stack();
106: stack.addAll(Arrays.asList(path.getPath()));
107: visit(model, stack, visitor);
108: }
109:
110: private static void visit(TreeModel model, Stack path,
111: Visitor visitor) {
112: visitor.visit(path);
113:
114: for (int i = 0; i < model.getChildCount(path.peek()); i++) {
115: path.push(model.getChild(path.peek(), i));
116: visit(model, path, visitor);
117: path.pop();
118: }
119: }
120:
121: public static TreeModelEvent createTreeModelEvent(
122: final Object source, final Object node,
123: final TreeModel model) {
124: TreePath path = findTreePath(node, model);
125: Assert.isTrue(path != null, "Cannot find node in TreeModel: "
126: + node + "\n" + dump(model));
127:
128: TreePath parentPath = path.getParentPath();
129:
130: return new TreeModelEvent(source, parentPath, new int[] { model
131: .getIndexOfChild(parentPath.getLastPathComponent(),
132: node) }, new Object[] { node });
133: }
134:
135: public static String dump(TreeModel model) {
136: final StringBuffer result = new StringBuffer();
137: visit(model, new Visitor() {
138: public void visit(Stack path) {
139: result.append((StringUtil.repeat(' ', path.size() * 2)
140: + path.lastElement() + "\n"));
141: }
142: });
143:
144: return result.toString();
145: }
146:
147: /**
148: * @return null if the node is not in the tree model
149: */
150: public static TreePath findTreePath(final Object node,
151: final TreeModel model) {
152: final TreePath[] treePath = new TreePath[] { null };
153: visit(model, new Visitor() {
154: public void visit(Stack path) {
155: if (path.peek() != node) {
156: return;
157: }
158:
159: treePath[0] = new TreePath(path.toArray());
160: }
161: });
162:
163: return treePath[0];
164: }
165:
166: public static boolean contains(TreeModel model, final Object node) {
167: final boolean[] result = new boolean[] { false };
168: visit(model, new Visitor() {
169: public void visit(Stack path) {
170: if (path.peek() == node) {
171: result[0] = true;
172: }
173: }
174: });
175:
176: return result[0];
177: }
178:
179: public static List lastPathComponents(TreePath[] paths) {
180: ArrayList lastPathComponents = new ArrayList();
181:
182: for (int i = 0; i < paths.length; i++) {
183: lastPathComponents.add(paths[i].getLastPathComponent());
184: }
185:
186: return lastPathComponents;
187: }
188:
189: public static void expandAll(final JTree tree, TreePath path) {
190: expand(tree, path, new Block() {
191: public Object yield(Object node) {
192: return Boolean.TRUE;
193: }
194: });
195: }
196:
197: public static void expand(final JTree tree, TreePath path,
198: final Block expandNodeCondition) {
199: visit(tree.getModel(), path, new Visitor() {
200: public void visit(Stack path) {
201: if (!((Boolean) expandNodeCondition.yield(path.peek()))
202: .booleanValue()) {
203: return;
204: }
205: tree.expandPath(findTreePath(path.peek(), tree
206: .getModel()));
207: }
208: });
209: }
210:
211: public static Collection nodes(TreePath path, TreeModel model) {
212: final ArrayList nodes = new ArrayList();
213: visit(model, path, new Visitor() {
214: public void visit(Stack path) {
215: nodes.add(path.peek());
216: }
217: });
218:
219: return nodes;
220: }
221:
222: public static interface Visitor {
223: public void visit(Stack path);
224: }
225: }
|