001: package net.xoetrope.builder.editor;
002:
003: import javax.swing.JPanel;
004: import javax.swing.JScrollPane;
005: import javax.swing.JTree;
006: import javax.swing.tree.TreeModel;
007: import javax.swing.tree.DefaultTreeModel;
008: import javax.swing.tree.DefaultMutableTreeNode;
009: import java.awt.Container;
010: import java.awt.Component;
011: import net.xoetrope.xui.XTarget;
012: import javax.swing.BorderFactory;
013: import java.awt.Dimension;
014: import java.util.Vector;
015: import java.awt.Rectangle;
016: import javax.swing.tree.TreePath;
017: import net.xoetrope.xui.XPage;
018: import javax.swing.event.TreeSelectionListener;
019: import javax.swing.event.TreeSelectionEvent;
020: import javax.swing.tree.TreeNode;
021: import java.util.Enumeration;
022: import net.xoetrope.swing.XScrollPane;
023: import javax.swing.JViewport;
024: import net.xoetrope.swing.XScrollableMetaContent;
025: import net.xoetrope.swing.XTable;
026: import net.xoetrope.builder.editor.components.swing.XComponentProxy;
027: import net.xoetrope.builder.editor.components.PropertyHelper;
028: import net.xoetrope.builder.editor.components.ComponentHelper;
029:
030: /**
031: * A tree of the complete component hierarchy
032: * <p> Copyright (c) Xoetrope Ltd., 2002-2003</p>
033: * <p> $Revision: 1.11 $</p>
034: * <p> License: see License.txt</p>
035: */
036: public class XComponentTree extends JScrollPane implements
037: TreeSelectionListener {
038: private XPageHolder pageHolder;
039: private JTree tree;
040: private DefaultMutableTreeNode root;
041: private DefaultTreeModel model;
042: private Vector selection;
043: private boolean selectionChanging = false;
044:
045: public XComponentTree() {
046: tree = new JTree();
047: tree.setBorder(BorderFactory.createEmptyBorder());
048: setViewportView(tree);
049:
050: tree.addTreeSelectionListener(this );
051: }
052:
053: /**
054: * Get the preferred size. This controls the size at which the editor
055: * initially appears.
056: * @return the size
057: */
058: public Dimension getPreferredSize() {
059: return new Dimension(100, 200);
060: }
061:
062: /**
063: * Set the page holder or root for the currently edit pages and frameset
064: * @param holder
065: */
066: public void setPageHolder(XPageHolder holder) {
067: pageHolder = holder;
068: refresh();
069: }
070:
071: /**
072: * Highligh the selected components
073: * @param selectedComponents a vector of selected components
074: */
075: public void setSelectedComponents(Vector selectedComponents) {
076: selection = selectedComponents;
077: refresh();
078:
079: if (selection.size() > 0) {
080: XComponentSizer sizer = (XComponentSizer) selection
081: .elementAt(0);
082: DefaultMutableTreeNode node = getPathToRoot(root, sizer
083: .getTarget());
084: if (node != null)
085: tree.setSelectionPath(new TreePath(node.getPath()));
086: }
087: }
088:
089: /**
090: * Refill the tree
091: */
092: public void refresh() {
093: tree.removeAll();
094: root = new DefaultMutableTreeNode("XUI", true);
095:
096: int numChildren = pageHolder.pageContainer.getComponentCount();
097: if (numChildren == 1) {
098: Container cont = (Container) pageHolder.pageContainer
099: .getComponent(0);
100: if (cont instanceof XTarget)
101: addChildren((Container) cont.getComponent(0), root);
102: else
103: addChildren(cont, root);
104: } else {
105: for (int i = 0; i < numChildren; i++) {
106: Component comp = pageHolder.pageContainer
107: .getComponent(i);
108: if (((XTarget) comp).getComponentCount() > 0) {
109: addChildren((Container) ((XTarget) comp)
110: .getComponent(0), root);
111: }
112: }
113: }
114:
115: model = new DefaultTreeModel(root);
116: tree.setModel(model);
117: }
118:
119: /**
120: * The tree selection has changed so highlight the selected component
121: * @param e
122: */
123: public void valueChanged(TreeSelectionEvent e) {
124: if (!selectionChanging) {
125:
126: selectionChanging = true;
127: DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
128: .getLastSelectedPathComponent();
129:
130: if (node == null) {
131: selectionChanging = false;
132: return;
133: }
134:
135: Object nodeInfo = node.getUserObject();
136: ComponentTreeNode treeNode = (ComponentTreeNode) nodeInfo;
137: if (!(treeNode.component instanceof JViewport))
138: pageHolder.selectComponent(treeNode.component, true);
139: selectionChanging = false;
140: }
141: }
142:
143: /**
144: * Add the child nodes for a container
145: * @param cont the container whos children to add
146: * @param node the node to which the children are added
147: */
148: private void addChildren(Container cont, DefaultMutableTreeNode node) {
149: int numChildren = cont.getComponentCount();
150: if (cont instanceof XScrollPane)
151: numChildren = 1;
152: for (int i = 0; i < numChildren; i++) {
153: Component comp = cont.getComponent(i);
154: if (comp != null) {
155: String typeName = comp.getClass().getName();
156: typeName = typeName
157: .substring(typeName.lastIndexOf('.') + 1);
158: String name = comp.getName();
159: if (name == null)
160: name = "?";
161: Rectangle bounds = comp.getBounds();
162: DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
163: new ComponentTreeNode(comp));
164: node.add(newNode);
165: if ((comp instanceof Container)
166: && allowChildren((Container) comp)) {
167: PropertyHelper compHelper = ComponentHelper
168: .getPropertyHelper(comp);
169: if (compHelper.allowsChildren())
170: addChildren((Container) comp, newNode);
171: }
172: }
173: }
174: if (numChildren == 0)
175: node.setAllowsChildren(false);
176: }
177:
178: private boolean allowChildren(Container cont) {
179: int numChildren = cont.getComponentCount();
180: if (numChildren == 0)
181: return false;
182:
183: if (cont instanceof JPanel)
184: return true;
185: else {
186: Component comp = cont.getComponent(0);
187: if (comp instanceof JViewport)
188: return false;
189: }
190: return true;
191: }
192:
193: private DefaultMutableTreeNode getPathToRoot( DefaultMutableTreeNode node, Component comp )
194: {
195: String nodeText = new ComponentTreeNode( comp ).toString();
196: if ( comp instanceof XPage ) {
197: Enumeration enum = node.children();
198: while ( enum.hasMoreElements()) {
199: DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)enum.nextElement();
200: if ( aNode.toString().equals( nodeText ))
201: return aNode;
202: }
203: return null;
204: }
205:
206: DefaultMutableTreeNode parentNode = getPathToRoot( node, comp.getParent());
207: if ( parentNode != null ) {
208: Enumeration enum = parentNode.children();
209: while ( enum.hasMoreElements() ) {
210: DefaultMutableTreeNode aNode = ( DefaultMutableTreeNode ) enum.nextElement();
211: if ( aNode.toString().equals( nodeText ) )
212: return aNode;
213: }
214: }
215:
216: return null;
217: }
218: }
219:
220: class ComponentTreeNode {
221: Component component;
222:
223: public ComponentTreeNode(Component comp) {
224: component = comp;
225: }
226:
227: public String toString() {
228: String typeName = component.getClass().getName();
229: typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
230: String name = component.getName();
231: if (name == null)
232: name = "?";
233: Rectangle bounds = component.getBounds();
234: return name + " <" + typeName + "> [" + bounds.x + ","
235: + bounds.y + "," + bounds.width + "," + bounds.height
236: + "]";
237: }
238: }
|