KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > swing > treetable > TreeTableCellEditor


1 /*
2  * $Id: TreeTableCellEditor.java,v 1.3 2004/08/13 21:20:35 rameshgupta Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7
8 package org.jdesktop.swing.treetable;
9
10 import java.util.EventObject JavaDoc;
11
12 import java.awt.Component JavaDoc;
13 import java.awt.Rectangle JavaDoc;
14 import java.awt.event.MouseEvent JavaDoc;
15 import javax.swing.DefaultCellEditor JavaDoc;
16 import javax.swing.Icon JavaDoc;
17 import javax.swing.JTable JavaDoc;
18 import javax.swing.JTextField JavaDoc;
19 import javax.swing.JTree JavaDoc;
20 import javax.swing.tree.DefaultTreeCellRenderer JavaDoc;
21 import javax.swing.tree.TreeCellRenderer JavaDoc;
22
23 import org.jdesktop.swing.JXTreeTable;
24
25 /**
26  * An editor that can be used to edit the tree column. This extends
27  * DefaultCellEditor and uses a JTextField (actually, TreeTableTextField)
28  * to perform the actual editing.
29  * <p>To support editing of the tree column we can not make the tree
30  * editable. The reason this doesn't work is that you can not use
31  * the same component for editing and renderering. The table may have
32  * the need to paint cells, while a cell is being edited. If the same
33  * component were used for the rendering and editing the component would
34  * be moved around, and the contents would change. When editing, this
35  * is undesirable, the contents of the text field must stay the same,
36  * including the caret blinking, and selections persisting. For this
37  * reason the editing is done via a TableCellEditor.
38  * <p>Another interesting thing to be aware of is how tree positions
39  * its render and editor. The render/editor is responsible for drawing the
40  * icon indicating the type of node (leaf, branch...). The tree is
41  * responsible for drawing any other indicators, perhaps an additional
42  * +/- sign, or lines connecting the various nodes. So, the renderer
43  * is positioned based on depth. On the other hand, table always makes
44  * its editor fill the contents of the cell. To get the allusion
45  * that the table cell editor is part of the tree, we don't want the
46  * table cell editor to fill the cell bounds. We want it to be placed
47  * in the same manner as tree places it editor, and have table message
48  * the tree to paint any decorations the tree wants. Then, we would
49  * only have to worry about the editing part. The approach taken
50  * here is to determine where tree would place the editor, and to override
51  * the <code>reshape</code> method in the JTextField component to
52  * nudge the textfield to the location tree would place it. Since
53  * JXTreeTable will paint the tree behind the editor everything should
54  * just work. So, that is what we are doing here. Determining of
55  * the icon position will only work if the TreeCellRenderer is
56  * an instance of DefaultTreeCellRenderer. If you need custom
57  * TreeCellRenderers, that don't descend from DefaultTreeCellRenderer,
58  * and you want to support editing in JXTreeTable, you will have
59  * to do something similiar.
60  *
61  * @author Scott Violet
62  * @author Ramesh Gupta
63  */

64 public class TreeTableCellEditor extends DefaultCellEditor JavaDoc {
65     public TreeTableCellEditor(JXTreeTable treeTable, JTree JavaDoc tree) {
66         super(new TreeTableTextField());
67         if (treeTable == null) {
68             throw new IllegalArgumentException JavaDoc("null treeTable");
69         }
70         if (tree == null) {
71             throw new IllegalArgumentException JavaDoc("null tree");
72         }
73
74         this.treeTable = treeTable; // immutable
75
this.tree = tree; // immutable
76
}
77
78     /**
79      * Overriden to determine an offset that tree would place the
80      * editor at. The offset is determined from the
81      * <code>getRowBounds</code> JTree method, and additionaly
82      * from the icon DefaultTreeCellRenderer will use.
83      * <p>The offset is then set on the TreeTableTextField component
84      * created in the constructor, and returned.
85      */

86     public Component JavaDoc getTableCellEditorComponent(JTable JavaDoc table, Object JavaDoc value,
87                                                  boolean isSelected, int row,
88                                                  int column) {
89         Component JavaDoc component = super.getTableCellEditorComponent(table, value,
90             isSelected, row, column);
91
92         //boolean isRootVisible = tree.isRootVisible();
93
Rectangle JavaDoc bounds = tree.getRowBounds(row);
94         int offset = bounds.x;
95         TreeCellRenderer JavaDoc tcr = tree.getCellRenderer();
96         if (tcr instanceof DefaultTreeCellRenderer JavaDoc) {
97             Object JavaDoc node = tree.getPathForRow(row).getLastPathComponent();
98             Icon JavaDoc icon;
99             if (tree.getModel().isLeaf(node))
100                 icon = ((DefaultTreeCellRenderer JavaDoc) tcr).getLeafIcon();
101             else if (tree.isExpanded(row))
102                 icon = ((DefaultTreeCellRenderer JavaDoc) tcr).getOpenIcon();
103             else
104                 icon = ((DefaultTreeCellRenderer JavaDoc) tcr).getClosedIcon();
105
106             if (icon != null) {
107                 offset += ((DefaultTreeCellRenderer JavaDoc) tcr).getIconTextGap() +
108                     icon.getIconWidth();
109             }
110         }
111         ((TreeTableTextField) getComponent()).offset = offset;
112         //((TreeTableTextField) getComponent()).selectAll();
113
return component;
114     }
115
116     /**
117      * This is overriden to forward the event to the tree. This will
118      * return true if the click count >= clickCountToStart, or the event is null.
119      */

120     public boolean isCellEditable(EventObject JavaDoc e) {
121         if (e == null) {
122             return true;
123         }
124         else if (e instanceof MouseEvent JavaDoc) {
125             // RG: Fix Issue 49 -- Move cell expansion/collapse logic to
126
// JXTreeTable.editCellAt();
127
return (((MouseEvent JavaDoc) e).getClickCount() >= clickCountToStart);
128         }
129
130         // e is some other type of event...
131
return false;
132     }
133
134     /**
135      * Component used by TreeTableCellEditor. The only thing this does
136      * is to override the <code>reshape</code> method, and to ALWAYS
137      * make the x location be <code>offset</code>.
138      */

139     static class TreeTableTextField extends JTextField JavaDoc {
140         int offset; // changed to package private instead of public
141

142         public void reshape(int x, int y, int width, int height) {
143             // Allows precise positioning of text field in the tree cell.
144
//Border border = this.getBorder(); // get this text field's border
145
//Insets insets = border == null ? null : border.getBorderInsets(this);
146
//int newOffset = offset - (insets == null ? 0 : insets.left);
147
int newOffset = offset - getInsets().left;
148             super.reshape(x + newOffset, y, width - newOffset, height);
149         }
150     }
151
152     private final JXTreeTable treeTable; // immutable
153
private final JTree JavaDoc tree; // immutable
154
}
Popular Tags