Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / javax / swing / tree / DefaultTreeCellEditor.java
blobae8b99c2fe5c69740f12e4bc76c88281284d4359
1 /* DefaultTreeCellEditor.java --
2 Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax.swing.tree;
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Container;
44 import java.awt.Dimension;
45 import java.awt.Font;
46 import java.awt.FontMetrics;
47 import java.awt.Graphics;
48 import java.awt.Insets;
49 import java.awt.Rectangle;
50 import java.awt.event.ActionEvent;
51 import java.awt.event.ActionListener;
52 import java.awt.event.MouseEvent;
53 import java.io.IOException;
54 import java.io.ObjectInputStream;
55 import java.io.ObjectOutputStream;
56 import java.util.EventObject;
58 import javax.swing.DefaultCellEditor;
59 import javax.swing.Icon;
60 import javax.swing.JTextField;
61 import javax.swing.JTree;
62 import javax.swing.SwingUtilities;
63 import javax.swing.UIDefaults;
64 import javax.swing.UIManager;
65 import javax.swing.border.Border;
66 import javax.swing.event.CellEditorListener;
67 import javax.swing.event.EventListenerList;
68 import javax.swing.event.TreeSelectionEvent;
69 import javax.swing.event.TreeSelectionListener;
71 /**
72 * DefaultTreeCellEditor
73 * @author Andrew Selkirk
75 public class DefaultTreeCellEditor
76 implements ActionListener, TreeCellEditor, TreeSelectionListener
78 /**
79 * EditorContainer
81 public class EditorContainer extends Container
83 /**
84 * Creates an <code>EditorContainer</code> object.
86 public EditorContainer()
88 // Do nothing here.
91 /**
92 * This method only exists for API compatibility and is useless as it does
93 * nothing. It got probably introduced by accident.
95 public void EditorContainer()
97 // Do nothing here.
101 * Returns the preferred size for the Container.
103 * @return Dimension of EditorContainer
105 public Dimension getPreferredSize()
107 Dimension containerSize = super.getPreferredSize();
108 containerSize.width += DefaultTreeCellEditor.this.offset;
109 return containerSize;
113 * Overrides Container.paint to paint the node's icon and use the selection
114 * color for the background.
116 * @param g -
117 * the specified Graphics window
119 public void paint(Graphics g)
121 Rectangle tr = tree.getPathBounds(lastPath);
122 if (tr != null)
124 Insets i = ((DefaultTextField) editingComponent).getBorder()
125 .getBorderInsets(this);
126 int textIconGap = 3;
127 tr.x -= i.left;
129 // paints icon
130 if (editingIcon != null)
132 editingIcon.paintIcon(this, g, tr.x - editingIcon.
133 getIconWidth()/2, tr.y + i.top + i.bottom);
134 tr.x += editingIcon.getIconWidth()/2 + textIconGap;
137 tr.width += offset;
139 // paint background
140 g.translate(tr.x, tr.y);
141 editingComponent.setSize(new Dimension(tr.width, tr.height));
142 editingComponent.paint(g);
143 g.translate(-tr.x, -tr.y);
145 super.paint(g);
149 * Lays out this Container. If editing, the editor will be placed at offset
150 * in the x direction and 0 for y.
152 public void doLayout()
154 if (DefaultTreeCellEditor.this.tree.isEditing())
155 setLocation(offset, 0);
156 super.doLayout();
161 * DefaultTextField
163 public class DefaultTextField extends JTextField
166 * border
168 protected Border border;
171 * Creates a <code>DefaultTextField</code> object.
173 * @param border the border to use
175 public DefaultTextField(Border border)
177 this.border = border;
181 * Gets the font of this component.
182 * @return this component's font; if a font has not been set for
183 * this component, the font of its parent is returned (if the parent
184 * is not null, otherwise null is returned).
186 public Font getFont()
188 Font font = super.getFont();
189 if (font == null)
191 Component parent = getParent();
192 if (parent != null)
193 return parent.getFont();
194 return null;
196 return font;
200 * Returns the border of the text field.
202 * @return the border
204 public Border getBorder()
206 return border;
210 * Overrides JTextField.getPreferredSize to return the preferred size
211 * based on current font, if set, or else use renderer's font.
213 * @return the Dimension of this textfield.
215 public Dimension getPreferredSize()
217 String s = getText();
219 Font f = getFont();
221 if (f != null)
223 FontMetrics fm = getToolkit().getFontMetrics(f);
225 return new Dimension(SwingUtilities.computeStringWidth(fm, s),
226 fm.getHeight());
228 return renderer.getPreferredSize();
232 private EventListenerList listenerList = new EventListenerList();
235 * Editor handling the editing.
237 protected TreeCellEditor realEditor;
240 * Renderer, used to get border and offsets from.
242 protected DefaultTreeCellRenderer renderer;
245 * Editing container, will contain the editorComponent.
247 protected Container editingContainer;
250 * Component used in editing, obtained from the editingContainer.
252 protected transient Component editingComponent;
255 * As of Java 2 platform v1.4 this field should no longer be used.
256 * If you wish to provide similar behavior you should directly
257 * override isCellEditable.
259 protected boolean canEdit;
262 * Used in editing. Indicates x position to place editingComponent.
264 protected transient int offset;
267 * JTree instance listening too.
269 protected transient JTree tree;
272 * Last path that was selected.
274 protected transient TreePath lastPath;
277 * Used before starting the editing session.
279 protected transient javax.swing.Timer timer;
282 * Row that was last passed into getTreeCellEditorComponent.
284 protected transient int lastRow;
287 * True if the border selection color should be drawn.
289 protected Color borderSelectionColor;
292 * Icon to use when editing.
294 protected transient Icon editingIcon;
297 * Font to paint with, null indicates font of renderer is to be used.
299 protected Font font;
302 * Helper field used to save the last path seen while the timer was
303 * running.
305 private TreePath tPath;
308 * Constructs a DefaultTreeCellEditor object for a JTree using the
309 * specified renderer and a default editor. (Use this constructor
310 * for normal editing.)
312 * @param tree - a JTree object
313 * @param renderer - a DefaultTreeCellRenderer object
315 public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
317 this(tree, renderer, null);
321 * Constructs a DefaultTreeCellEditor object for a JTree using the specified
322 * renderer and the specified editor. (Use this constructor
323 * for specialized editing.)
325 * @param tree - a JTree object
326 * @param renderer - a DefaultTreeCellRenderer object
327 * @param editor - a TreeCellEditor object
329 public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
330 TreeCellEditor editor)
332 setTree(tree);
333 this.renderer = renderer;
335 if (editor == null)
336 editor = createTreeCellEditor();
337 realEditor = editor;
339 lastPath = tree.getLeadSelectionPath();
340 tree.addTreeSelectionListener(this);
341 editingContainer = createContainer();
342 setFont(UIManager.getFont("Tree.font"));
343 setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor"));
344 editingIcon = renderer.getIcon();
345 timer = new javax.swing.Timer(1200, this);
349 * Configures the editing component whenever it is null.
351 * @param tree the tree to configure to component for.
352 * @param renderer the renderer used to set up the nodes
353 * @param editor the editor used
355 private void configureEditingComponent(JTree tree,
356 DefaultTreeCellRenderer renderer,
357 TreeCellEditor editor)
359 if (tree != null && lastPath != null)
361 Object val = lastPath.getLastPathComponent();
362 boolean isLeaf = tree.getModel().isLeaf(val);
363 boolean expanded = tree.isExpanded(lastPath);
364 determineOffset(tree, val, true, expanded, isLeaf, lastRow);
366 // set up icon
367 if (isLeaf)
368 renderer.setIcon(renderer.getLeafIcon());
369 else if (expanded)
370 renderer.setIcon(renderer.getOpenIcon());
371 else
372 renderer.setIcon(renderer.getClosedIcon());
373 editingIcon = renderer.getIcon();
375 editingComponent = getTreeCellEditorComponent(tree, val, true,
376 expanded, isLeaf, lastRow);
381 * writeObject
383 * @param value0
384 * TODO
385 * @exception IOException
386 * TODO
388 private void writeObject(ObjectOutputStream value0) throws IOException
390 // TODO
394 * readObject
395 * @param value0 TODO
396 * @exception IOException TODO
397 * @exception ClassNotFoundException TODO
399 private void readObject(ObjectInputStream value0)
400 throws IOException, ClassNotFoundException
402 // TODO
406 * Sets the color to use for the border.
407 * @param newColor - the new border color
409 public void setBorderSelectionColor(Color newColor)
411 this.borderSelectionColor = newColor;
415 * Returns the color the border is drawn.
416 * @return Color
418 public Color getBorderSelectionColor()
420 return borderSelectionColor;
424 * Sets the font to edit with. null indicates the renderers
425 * font should be used. This will NOT override any font you have
426 * set in the editor the receiver was instantied with. If null for
427 * an editor was passed in, a default editor will be created that
428 * will pick up this font.
430 * @param font - the editing Font
432 public void setFont(Font font)
434 if (font != null)
435 this.font = font;
436 else
437 this.font = renderer.getFont();
441 * Gets the font used for editing.
443 * @return the editing font
445 public Font getFont()
447 return font;
451 * Configures the editor. Passed onto the realEditor.
452 * Sets an initial value for the editor. This will cause
453 * the editor to stopEditing and lose any partially edited value
454 * if the editor is editing when this method is called.
455 * Returns the component that should be added to the client's Component
456 * hierarchy. Once installed in the client's hierarchy this component will
457 * then be able to draw and receive user input.
459 * @param tree - the JTree that is asking the editor to edit; this parameter can be null
460 * @param value - the value of the cell to be edited
461 * @param isSelected - true is the cell is to be rendered with selection highlighting
462 * @param expanded - true if the node is expanded
463 * @param leaf - true if the node is a leaf node
464 * @param row - the row index of the node being edited
466 * @return the component for editing
468 public Component getTreeCellEditorComponent(JTree tree, Object value,
469 boolean isSelected, boolean expanded,
470 boolean leaf, int row)
472 if (realEditor == null)
473 createTreeCellEditor();
475 return realEditor.getTreeCellEditorComponent(tree, value, isSelected,
476 expanded, leaf, row);
480 * Returns the value currently being edited.
482 * @return the value currently being edited
484 public Object getCellEditorValue()
486 return editingComponent;
490 * If the realEditor returns true to this message, prepareForEditing
491 * is messaged and true is returned.
493 * @param event - the event the editor should use to consider whether to begin editing or not
494 * @return true if editing can be started
496 public boolean isCellEditable(EventObject event)
498 if (editingComponent == null)
499 configureEditingComponent(tree, renderer, realEditor);
501 if (editingComponent != null && realEditor.isCellEditable(event))
503 prepareForEditing();
504 return true;
507 // Cell may not be currently editable, but may need to start timer.
508 if (shouldStartEditingTimer(event))
509 startEditingTimer();
510 else if (timer.isRunning())
511 timer.stop();
512 return false;
516 * Messages the realEditor for the return value.
518 * @param event -
519 * the event the editor should use to start editing
520 * @return true if the editor would like the editing cell to be selected;
521 * otherwise returns false
523 public boolean shouldSelectCell(EventObject event)
525 return true;
529 * If the realEditor will allow editing to stop, the realEditor
530 * is removed and true is returned, otherwise false is returned.
531 * @return true if editing was stopped; false otherwise
533 public boolean stopCellEditing()
535 if (editingComponent != null && realEditor.stopCellEditing())
537 timer.stop();
538 return true;
540 return false;
544 * Messages cancelCellEditing to the realEditor and removes it
545 * from this instance.
547 public void cancelCellEditing()
549 if (editingComponent != null)
551 timer.stop();
552 realEditor.cancelCellEditing();
557 * Adds a <code>CellEditorListener</code> object to this editor.
559 * @param listener the listener to add
561 public void addCellEditorListener(CellEditorListener listener)
563 realEditor.addCellEditorListener(listener);
567 * Removes a <code>CellEditorListener</code> object.
569 * @param listener the listener to remove
571 public void removeCellEditorListener(CellEditorListener listener)
573 realEditor.removeCellEditorListener(listener);
577 * Returns all added <code>CellEditorListener</code> objects to this editor.
579 * @return an array of listeners
581 * @since 1.4
583 public CellEditorListener[] getCellEditorListeners()
585 return (CellEditorListener[]) listenerList.getListeners(CellEditorListener.class);
589 * Resets lastPath.
591 * @param e - the event that characterizes the change.
593 public void valueChanged(TreeSelectionEvent e)
595 tPath = lastPath;
596 lastPath = e.getNewLeadSelectionPath();
597 lastRow = tree.getRowForPath(lastPath);
598 configureEditingComponent(tree, renderer, realEditor);
602 * Messaged when the timer fires, this will start the editing session.
604 * @param e the event that characterizes the action.
606 public void actionPerformed(ActionEvent e)
608 if (lastPath != null && tPath != null && tPath.equals(lastPath))
610 tree.startEditingAtPath(lastPath);
611 timer.stop();
616 * Sets the tree currently editing for. This is needed to add a selection
617 * listener.
619 * @param newTree -
620 * the new tree to be edited
622 protected void setTree(JTree newTree)
624 tree = newTree;
628 * Returns true if event is a MouseEvent and the click count is 1.
630 * @param event - the event being studied
631 * @return true if editing should start
633 protected boolean shouldStartEditingTimer(EventObject event)
635 if ((event instanceof MouseEvent) &&
636 ((MouseEvent) event).getClickCount() == 1)
637 return true;
638 return false;
642 * Starts the editing timer.
644 protected void startEditingTimer()
646 if (timer == null)
647 timer = new javax.swing.Timer(1200, this);
648 if (!timer.isRunning())
649 timer.start();
653 * Returns true if event is null, or it is a MouseEvent with
654 * a click count > 2 and inHitRegion returns true.
656 * @param event - the event being studied
657 * @return true if event is null, or it is a MouseEvent with
658 * a click count > 2 and inHitRegion returns true
660 protected boolean canEditImmediately(EventObject event)
662 if (event == null || !(event instanceof MouseEvent) || (((MouseEvent) event).
663 getClickCount() > 2 && inHitRegion(((MouseEvent) event).getX(),
664 ((MouseEvent) event).getY())))
665 return true;
666 return false;
670 * Returns true if the passed in location is a valid mouse location
671 * to start editing from. This is implemented to return false if x is
672 * less than or equal to the width of the icon and icon
673 * gap displayed by the renderer. In other words this returns true if
674 * the user clicks over the text part displayed by the renderer, and
675 * false otherwise.
677 * @param x - the x-coordinate of the point
678 * @param y - the y-coordinate of the point
680 * @return true if the passed in location is a valid mouse location
682 protected boolean inHitRegion(int x, int y)
684 Rectangle bounds = tree.getPathBounds(lastPath);
686 return bounds.contains(x, y);
690 * determineOffset
691 * @param tree -
692 * @param value -
693 * @param isSelected -
694 * @param expanded -
695 * @param leaf -
696 * @param row -
698 protected void determineOffset(JTree tree, Object value, boolean isSelected,
699 boolean expanded, boolean leaf, int row)
701 renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded,
702 leaf, row, true);
703 Icon c = renderer.getIcon();
704 if (c != null)
705 offset = renderer.getIconTextGap() + c.getIconWidth();
706 else
707 offset = 0;
711 * Invoked just before editing is to start. Will add the
712 * editingComponent to the editingContainer.
714 protected void prepareForEditing()
716 editingContainer.add(editingComponent);
720 * Creates the container to manage placement of editingComponent.
722 * @return the container to manage the placement of the editingComponent.
724 protected Container createContainer()
726 return new DefaultTreeCellEditor.EditorContainer();
730 * This is invoked if a TreeCellEditor is not supplied in the constructor.
731 * It returns a TextField editor.
733 * @return a new TextField editor
735 protected TreeCellEditor createTreeCellEditor()
737 realEditor = new DefaultCellEditor(new DefaultTreeCellEditor.DefaultTextField(
738 UIManager.getBorder("Tree.selectionBorder")));
739 return realEditor;