KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > tree > SmartTreeCellEditor


1 package com.ca.directory.jxplorer.tree;
2
3 import com.ca.commons.cbutil.*;
4 import com.ca.commons.naming.RDN;
5
6 import javax.naming.NamingException JavaDoc;
7 import javax.swing.*;
8 import javax.swing.border.Border JavaDoc;
9 import javax.swing.tree.*;
10 import java.awt.*;
11 import java.awt.event.ActionEvent JavaDoc;
12 import java.awt.event.ActionListener JavaDoc;
13 import java.util.EventObject JavaDoc;
14
15 /**
16  * This class provides a (potentially) multi-field editor for editing
17  * multi-valued RDNs, and provides a number of sub-classes to allow
18  * it to be integrated into the JTree class.
19  */

20  
21 public class SmartTreeCellEditor extends DefaultTreeCellEditor
22 {
23     Panel display;
24     TextField standard;
25     
26     boolean useIcons = true;
27  
28     Object JavaDoc value = null;
29  
30     /**
31      * Default constructor. All the intelligence is added by overloading
32      * the methods below.
33      * @param tree the tree the editor will be used in.
34      * @param renderer the existing renderer, used to obtain icons from.
35      */

36      
37     public SmartTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
38     {
39         super(tree, renderer);
40         display = new Panel();
41         display.setBackground(Color.green);
42         display.add(standard = new TextField("bloop"));
43     }
44
45
46     /**
47      * overload the standard DefaultTreeCellEditor method that
48      * creates the 'inner' editor used to display data.
49      *
50      * @return a custom tree cell editor, being a 'MyTreeCellEditor'
51      * object (as defined below).
52      */

53      
54     protected TreeCellEditor createTreeCellEditor()
55     {
56         MyTreeCellEditor editor = new MyTreeCellEditor();
57         // One click to edit.
58
editor.setClickCountToStart(1);
59         return editor;
60         
61     }
62
63     /**
64      * Quick hack to disable editing during drag and drop operations.
65      * @param e the event to disable if dragging occuring.
66      */

67      
68     public void actionPerformed(ActionEvent JavaDoc e)
69     {
70         if (((SmartTree)tree).dragging == true)
71             return;
72             
73         super.actionPerformed(e);
74     }
75
76     /**
77      * Hacked to use SmartNode icon, so we don't see the icon
78      * changing during editing.
79      *
80      */

81      
82     protected void determineOffset(JTree tree, Object JavaDoc value,
83                    boolean isSelected, boolean expanded,
84                    boolean leaf, int row)
85     {
86         if(value != null)
87         {
88             editingIcon = ((SmartNode)value).getIcon();
89             
90             if (editingIcon != null)
91                 offset = 4 + editingIcon.getIconWidth();
92             else
93                 offset = 4;
94         }
95         else
96         {
97             editingIcon = null;
98             offset = 0;
99         }
100     }
101     
102     /**
103      * Returns the value of the tree entry currently being edited.
104      * @return
105      */

106      
107     public Object JavaDoc getCellEditorValue()
108     {
109         try
110         {
111             SmartNode node = (SmartNode)value;
112             if (node.isMultiValued())
113             {
114                 return value.toString();
115             }
116         }
117         catch (Exception JavaDoc e) {} // we don't care - even if it's not a SmartNode, just keep going.
118

119         return super.getCellEditorValue();
120     }
121
122     /**
123      * Extend the base method to nobble editing of 'structural' nodes.
124      */

125      
126     public boolean isCellEditable(EventObject JavaDoc event)
127     {
128         if (tree == null) // this should never happen. But if there's no tree,
129
return false; // don't edit it!
130

131         TreePath path = tree.getSelectionPath();
132         
133         if (path == null) // no path == no editing!
134
return false;
135         
136         SmartNode node = (SmartNode)path.getLastPathComponent();
137
138         if (node == null) // if there's no smart node, don't edit that either!
139
return false;
140
141         
142         /*
143          * The point of this method: don't allow structural, dummy or root
144          * nodes to ever be edited.
145          */

146                      
147         if (node != null && node.isDummy() || node.isStructural() || node.isRoot())
148             return false;
149
150         return super.isCellEditable(event);
151     }
152
153
154
155
156
157     /**
158      * This is the actual GUI component shown to the user. (It can be confusing to
159      * work out that this is the object, because of the number of layers of intermediate
160      * components, DefaultCellEditors, EditorDelegates yada yada yada...
161      */

162      
163     class CellEditorGUI extends CBPanel
164     {
165         ActionListener JavaDoc listener; // bit of a hack - we only allow one listener
166

167         boolean multi = false; // whether currently displaying a multi-valued att.
168

169         JTextField first; // there is always at least one text field available - and this is it!
170

171         Border JavaDoc thinBorder; // We're very short of room when editing a tree cell, so we have the thinnest border possible.
172

173         SmartNode node; // A local pointer to the node being edited.
174

175         RDN displayRDN; // the original RDN to display.
176

177         /**
178          * The constructor sets up our panel. We extend CBPanel with its
179          * GridBagLayout to allow us to space the components with thin '+'
180          * signs between fat text fields in the multi-valued RDNs. The
181          * constructor does little except set up the border, and construct
182          * the 'first' text field (which is always present).
183          */

184          
185         CellEditorGUI()
186         {
187             makeHeavy();
188             thinBorder = UIManager.getBorder("Tree.editorBorder");
189             first = new JTextField();
190             first.setBorder(thinBorder);
191             first.setText("bloop!");
192             add(first);
193
194         }
195
196      
197         /**
198          * Sets up the GUI to display a (possibly multi-valued)
199          * RDN (accessed via the passed SmartNode). This
200          * creates the necessary text fields (and any 'plus sign'
201          * labels) to populate this object for display.
202          * @param node the node to edit, containing a potentially
203          * multi-valued rdn.
204          */

205
206         void setValue(SmartNode node)
207         {
208             this.node = node;
209
210             RDN rdn = node.getRDN();
211
212             int size = rdn.size();
213
214             multi = node.isMultiValued();
215         
216             trimExcessComponents(); // just clearing the decks.
217

218             Dimension prefSize = renderer.getPreferredSize();
219         
220             setSize(prefSize);
221
222             first.setText(rdn.getRawVal(0)); // this is the last step for single valued RDNs
223

224             /*
225              * Handle possible multi-valued components by
226              * alternately adding '+' sign labels and
227              * more text fields.
228              */

229              
230             for (int i=1; i<size; i++)
231             {
232                 makeLight();
233                 JLabel plus = new JLabel("+");
234                 plus.setForeground(Color.red);
235                 add(plus);
236                 makeHeavy();
237                 JTextField nextField = new JTextField(rdn.getRawVal(i));
238                 nextField.setBorder(thinBorder);
239                 nextField.addActionListener(listener);
240                 add(nextField);
241             }
242             
243         }
244      
245         /**
246          * Removes all fields, except the first text field.
247          */

248          
249         protected void trimExcessComponents()
250         {
251             for (int i=getComponentCount()-1; i>0; i--)
252             {
253                 remove(i);
254             }
255         }
256          
257      
258         /**
259          * Constructs the RDN from the text fields the user
260          * has edited.
261          * @return the newly edited RDN.
262          */

263          
264         RDN getValue()
265         {
266             RDN returnRDN = node.getRDN();
267             
268             try
269             {
270 /*
271                 if (multi==false)
272                 {
273                     returnRDN.setRawVal(first.getText());
274                     return returnRDN;
275                 }
276                 else
277                 {
278 */

279                     int size = getComponentCount();
280                     for (int i=0; i<size; i = i+2)
281                     {
282                         JTextField currentTextField = (JTextField) getComponent(i);
283                         String JavaDoc text = currentTextField.getText();
284                         text = text.trim();
285                         if (text.length() == 0)
286                             text = " ";
287                         returnRDN.setRawVal(text, (i/2));
288                     }
289                     return returnRDN;
290 // }
291
}
292             catch (NamingException JavaDoc e)
293             {
294                 CBUtility.error(CBIntText.get("Invalid Name"), null);
295 //TODO: this needs work, as it currently returns an invalid rdn below!
296

297
298             }
299             return returnRDN;
300         }
301         
302         /**
303          * <p>A bit of a hack occuring here - we only really allow for
304          * a single listener, and we add that to all the component text
305          * fields created for the multi-valued rdns.</p>
306          *
307          * <p>If we ever needed to do this properly, we could eliminate
308          * this method altogether, and read the complete listener list
309          * in 'setMultiValued(...)'.</p>
310          *
311          * @param l the sole listener for this object.
312          *
313          */

314          
315         void addActionListener(ActionListener JavaDoc l)
316         {
317             listener = l;
318             first.addActionListener(l);
319         }
320         
321        /**
322          * Overrides <code>JTextField.getPreferredSize</code> to
323          * return the preferred size based on current font, if set,
324          * or else use renderer's font.
325          * @return the preferred size for the cell renderer (as it appears in the tree).
326          */

327          
328         public Dimension getPreferredSize()
329         {
330             Dimension size = super.getPreferredSize();
331             
332             // If not font has been set, prefer the renderers (the SmartTreeCellRenderers) height.
333
if(renderer != null )
334             {
335                 Dimension rSize = renderer.getPreferredSize();
336                 size.height = rSize.height;
337             }
338             
339             if (multi)
340                 size.width += 30; // add a bit of elbow room for multi-valued rdn...
341

342             return size;
343         }
344     }
345
346     /**
347      * A custom CellEditor that extends DefaultCellEditor, and changes the
348      * internal editor delegate used to be the CellEditorGUI defined above.
349      * (why they didn't allow DefaultCellEditor to be created with an
350      * arbitrary editor component, who knows - the architecture is all there.).
351      *
352      */

353      
354     public class MyTreeCellEditor extends DefaultCellEditor
355     {
356     
357         CellEditorGUI cellDisplay;
358         
359         /**
360          * Constructor automatically creates the editor with a
361          * CellEditorGUI delegate.
362          */

363          
364         public MyTreeCellEditor()
365         {
366             super(new JCheckBox()); // needed, because Sun screwed up writing DefaultCellEditor.
367

368             cellDisplay = new CellEditorGUI();
369             
370             editorComponent = cellDisplay;
371             
372             this.clickCountToStart = 2;
373             
374             delegate = new EditorDelegate()
375             {
376                 public void setValue(Object JavaDoc value)
377                 {
378                     cellDisplay.setValue((SmartNode)value);
379                 }
380     
381                 public Object JavaDoc getCellEditorValue()
382                 {
383                     return cellDisplay.getValue();
384                 }
385             };
386             
387             cellDisplay.addActionListener(delegate);
388         }
389         
390         /**
391          * Returns the editor component, which is the internal CellEditorGUI
392          * object created in the constructor, after setting the value it is
393          * to display/edit.
394          */

395             
396         public Component getTreeCellEditorComponent(JTree tree, Object JavaDoc value,
397                             boolean isSelected,
398                             boolean expanded,
399                             boolean leaf, int row)
400         {
401             cellDisplay.setBackground(tree.getBackground());
402             delegate.setValue(value);
403             return editorComponent;
404         }
405         
406
407
408         
409     }
410
411 }
Popular Tags