OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / tree / DefaultTreeCellRenderer.java
1 /* DefaultTreeCellRenderer.java 
2  Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc.
3  
4  This file is part of GNU Classpath.
5
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.
10
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.
15
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.
20
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.
25
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. */
37
38
39 package javax.swing.tree;
40
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Dimension;
44 import java.awt.Font;
45 import java.awt.FontMetrics;
46 import java.awt.Graphics;
47 import java.awt.Insets;
48 import java.awt.Rectangle;
49
50 import javax.swing.Icon;
51 import javax.swing.JLabel;
52 import javax.swing.JTree;
53 import javax.swing.LookAndFeel;
54 import javax.swing.SwingUtilities;
55 import javax.swing.UIManager;
56 import javax.swing.border.Border;
57 import javax.swing.plaf.UIResource;
58
59 /**
60  * A default implementation of the {@link TreeCellRenderer} interface.
61  * 
62  * @author Andrew Selkirk
63  */
64 public class DefaultTreeCellRenderer
65   extends JLabel
66   implements TreeCellRenderer
67 {
68
69   /**
70    * A flag indicating the current selection status.
71    */
72   protected boolean selected;
73
74   /**
75    * A flag indicating the current focus status.
76    */
77   protected boolean hasFocus;
78
79   /**
80    * Indicates if the focus border is also drawn around the icon.
81    */
82   private boolean drawsFocusBorderAroundIcon;
83
84   /**
85    * The icon used to represent non-leaf nodes that are closed.
86    * 
87    * @see #setClosedIcon(Icon)
88    */
89   protected transient Icon closedIcon;
90
91   /**
92    * The icon used to represent leaf nodes.
93    * 
94    * @see #setLeafIcon(Icon)
95    */
96   protected transient Icon leafIcon;
97
98   /**
99    * The icon used to represent non-leaf nodes that are open.
100    * 
101    * @see #setOpenIcon(Icon)
102    */
103   protected transient Icon openIcon;
104
105   /**
106    * The color used for text in selected cells.
107    * 
108    * @see #setTextSelectionColor(Color)
109    */
110   protected Color textSelectionColor;
111
112   /**
113    * The color used for text in non-selected cells.
114    * 
115    * @see #setTextNonSelectionColor(Color)
116    */
117   protected Color textNonSelectionColor;
118
119   /**
120    * The background color for selected cells.
121    * 
122    * @see #setBackgroundSelectionColor(Color)
123    */
124   protected Color backgroundSelectionColor;
125
126   /**
127    * The background color for non-selected cells.
128    * 
129    * @see #setBackgroundNonSelectionColor(Color)
130    */
131   protected Color backgroundNonSelectionColor;
132
133   /**
134    * The border color for selected tree cells.
135    * 
136    * @see #setBorderSelectionColor(Color)
137    */
138   protected Color borderSelectionColor;
139
140   /**
141    * Creates a new tree cell renderer with defaults appropriate for the 
142    * current {@link LookAndFeel}.
143    */
144   public DefaultTreeCellRenderer()
145   {
146     setLeafIcon(getDefaultLeafIcon());
147     setOpenIcon(getDefaultOpenIcon());
148     setClosedIcon(getDefaultClosedIcon());
149
150     setTextNonSelectionColor(UIManager.getColor("Tree.textForeground"));
151     setTextSelectionColor(UIManager.getColor("Tree.selectionForeground"));
152     setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground"));
153     setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground"));
154     setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor"));
155     Object val = UIManager.get("Tree.drawsFocusBorderAroundIcon");
156     drawsFocusBorderAroundIcon = val != null && ((Boolean) val).booleanValue();
157   }
158
159   /**
160    * Returns the default icon for non-leaf tree cells that are open (expanded).
161    * The icon is fetched from the defaults table for the current 
162    * {@link LookAndFeel} using the key <code>Tree.openIcon</code>.
163    * 
164    * @return The default icon.
165    */
166   public Icon getDefaultOpenIcon()
167   {
168     return UIManager.getIcon("Tree.openIcon");
169   }
170
171   /**
172    * Returns the default icon for non-leaf tree cells that are closed (not 
173    * expanded).  The icon is fetched from the defaults table for the current 
174    * {@link LookAndFeel} using the key <code>Tree.closedIcon</code>.
175    * 
176    * @return The default icon.
177    */
178   public Icon getDefaultClosedIcon()
179   {
180     return UIManager.getIcon("Tree.closedIcon");
181   }
182
183   /**
184    * Returns the default icon for leaf tree cells.  The icon is fetched from 
185    * the defaults table for the current {@link LookAndFeel} using the key 
186    * <code>Tree.leafIcon</code>.
187    * 
188    * @return The default icon.
189    */
190   public Icon getDefaultLeafIcon()
191   {
192     return UIManager.getIcon("Tree.leafIcon");
193   }
194
195   /**
196    * Sets the icon to be displayed for non-leaf nodes that are open (expanded).
197    * Set this to <code>null</code> if no icon is required.
198    * 
199    * @param icon  the icon (<code>null</code> permitted).
200    * 
201    * @see #getOpenIcon()
202    */
203   public void setOpenIcon(Icon icon)
204   {
205     openIcon = icon;
206   }
207
208   /**
209    * Returns the icon displayed for non-leaf nodes that are open (expanded).  
210    * The default value is initialised from the {@link LookAndFeel}.
211    * 
212    * @return The open icon (possibly <code>null</code>).
213    * 
214    * @see #setOpenIcon(Icon)
215    */
216   public Icon getOpenIcon()
217   {
218     return openIcon;
219   }
220
221   /**
222    * Sets the icon to be displayed for non-leaf nodes that are closed.  Set 
223    * this to <code>null</code> if no icon is required.
224    * 
225    * @param icon  the icon (<code>null</code> permitted).
226    * 
227    * @see #getClosedIcon()
228    */
229   public void setClosedIcon(Icon icon)
230   {
231     closedIcon = icon;
232   }
233
234   /**
235    * Returns the icon displayed for non-leaf nodes that are closed.  The 
236    * default value is initialised from the {@link LookAndFeel}.
237    * 
238    * @return The closed icon (possibly <code>null</code>).
239    * 
240    * @see #setClosedIcon(Icon)
241    */
242   public Icon getClosedIcon()
243   {
244     return closedIcon;
245   }
246
247   /**
248    * Sets the icon to be displayed for leaf nodes.  Set this to 
249    * <code>null</code> if no icon is required.
250    * 
251    * @param icon  the icon (<code>null</code> permitted).
252    * 
253    * @see #getLeafIcon()
254    */
255   public void setLeafIcon(Icon icon)
256   {
257     leafIcon = icon;
258   }
259
260   /**
261    * Returns the icon displayed for leaf nodes.  The default value is 
262    * initialised from the {@link LookAndFeel}.
263    * 
264    * @return The leaf icon (possibly <code>null</code>).
265    * 
266    * @see #setLeafIcon(Icon)
267    */
268   public Icon getLeafIcon()
269   {
270     return leafIcon;
271   }
272
273   /**
274    * Sets the text color for tree cells that are selected.
275    * 
276    * @param c  the color (<code>null</code> permitted).
277    * 
278    * @see #getTextSelectionColor()
279    */
280   public void setTextSelectionColor(Color c)
281   {
282     textSelectionColor = c;
283   }
284
285   /**
286    * Returns the text color for tree cells that are selected.
287    * The default value is obtained from the {@link LookAndFeel} defaults
288    * table using the key <code>Tree.selectionForeground</code>.
289    * 
290    * @return The text color for tree cells that are selected.
291    * 
292    * @see #setTextSelectionColor(Color)
293    */
294   public Color getTextSelectionColor()
295   {
296     return textSelectionColor;
297   }
298
299   /**
300    * Sets the text color for tree cells that are not selected.
301    * 
302    * @param c  the color (<code>null</code> permitted).
303    * 
304    * @see #getTextNonSelectionColor()
305    */
306   public void setTextNonSelectionColor(Color c)
307   {
308     textNonSelectionColor = c;
309   }
310
311   /**
312    * Returns the text color for tree cells that are not selected.
313    * The default value is obtained from the {@link LookAndFeel} defaults
314    * table using the key <code>Tree.selectionForeground</code>.
315    * 
316    * @return The background color for tree cells that are not selected.
317    * 
318    * @see #setTextgroundNonSelectionColor(Color)
319    */
320   public Color getTextNonSelectionColor()
321   {
322     return textNonSelectionColor;
323   }
324
325   /**
326    * Sets the background color for tree cells that are selected.
327    * 
328    * @param c  the color (<code>null</code> permitted).
329    * 
330    * @see #getBackgroundSelectionColor()
331    */
332   public void setBackgroundSelectionColor(Color c)
333   {
334     backgroundSelectionColor = c;
335   }
336
337   /**
338    * Returns the background color for tree cells that are selected.
339    * The default value is obtained from the {@link LookAndFeel} defaults
340    * table using the key <code>Tree.selectionBackground</code>.
341    * 
342    * @return The background color for tree cells that are selected.
343    * 
344    * @see #setBackgroundSelectionColor(Color)
345    */
346   public Color getBackgroundSelectionColor()
347   {
348     return backgroundSelectionColor;
349   }
350
351   /**
352    * Sets the background color for tree cells that are not selected.
353    * 
354    * @param c  the color (<code>null</code> permitted).
355    * 
356    * @see #getBackgroundNonSelectionColor()
357    */
358   public void setBackgroundNonSelectionColor(Color c)
359   {
360     backgroundNonSelectionColor = c;
361   }
362
363   /**
364    * Returns the background color for tree cells that are not selected.
365    * The default value is obtained from the {@link LookAndFeel} defaults
366    * table using the key <code>Tree.textBackground</code>.
367    * 
368    * @return The background color for tree cells that are not selected.
369    * 
370    * @see #setBackgroundNonSelectionColor(Color)
371    */
372   public Color getBackgroundNonSelectionColor()
373   {
374     return backgroundNonSelectionColor;
375   }
376
377   /**
378    * Sets the border color for tree cells that are selected.
379    * 
380    * @param c  the color (<code>null</code> permitted).
381    * 
382    * @see #getBorderSelectionColor()
383    */
384   public void setBorderSelectionColor(Color c)
385   {
386     borderSelectionColor = c;
387   }
388
389   /**
390    * Returns the border color for tree cells that are selected.
391    * The default value is obtained from the {@link LookAndFeel} defaults
392    * table using the key <code>Tree.selectionBorderColor</code>.
393    * 
394    * @return The border color for tree cells that are selected.
395    * 
396    * @see #setBorderSelectionColor(Color)
397    */
398   public Color getBorderSelectionColor()
399   {
400     return borderSelectionColor;
401   }
402
403   /**
404    * Sets the font.
405    * 
406    * @param f the font.
407    * 
408    * @see #getFont()
409    */
410   public void setFont(Font f)
411   {
412     if (f != null && f instanceof UIResource)
413       f = null;
414     super.setFont(f);
415   }
416
417   /**
418    * Sets the background color.
419    * 
420    * @param c the color.
421    */
422   public void setBackground(Color c)
423   {
424     if (c != null && c instanceof UIResource)
425       c = null;
426     super.setBackground(c);
427   }
428
429   /**
430    * Returns a component (in fact <code>this</code>) that can be used to
431    * render a tree cell with the specified state.
432    * 
433    * @param tree  the tree that the cell belongs to.
434    * @param val  the cell value.
435    * @param selected  indicates whether or not the cell is selected.
436    * @param expanded  indicates whether or not the cell is expanded.
437    * @param leaf  indicates whether or not the cell is a leaf in the tree.
438    * @param row  the row index.
439    * @param hasFocus  indicates whether or not the cell has the focus.
440    * 
441    * @return <code>this</code>.
442    */
443   public Component getTreeCellRendererComponent(JTree tree, Object val,
444                                                 boolean selected,
445                                                 boolean expanded, boolean leaf,
446                                                 int row, boolean hasFocus)
447   {
448     if (leaf)
449       setIcon(getLeafIcon());
450     else if (expanded)
451       setIcon(getOpenIcon());
452     else
453       setIcon(getClosedIcon());
454
455     setText(val.toString());
456     this.selected = selected;
457     this.hasFocus = hasFocus;
458     setHorizontalAlignment(LEFT);
459     setOpaque(false);
460     setVerticalAlignment(CENTER);
461     setEnabled(true);
462     super.setFont(UIManager.getFont("Tree.font"));
463
464     if (selected)
465       {
466         super.setBackground(getBackgroundSelectionColor());
467         setForeground(getTextSelectionColor());
468         
469         if (hasFocus)
470           setBorderSelectionColor(UIManager.getLookAndFeelDefaults().
471                                   getColor("Tree.selectionBorderColor"));
472         else
473           setBorderSelectionColor(null);
474       }
475     else
476       {
477         super.setBackground(getBackgroundNonSelectionColor());
478         setForeground(getTextNonSelectionColor());
479         setBorderSelectionColor(null);
480       }
481
482     return this;
483   }
484
485   /**
486    * Returns the current font.
487    * 
488    * @return The current font.
489    * 
490    * @see #setFont(Font)
491    */
492   public Font getFont()
493   {
494     return super.getFont();
495   }
496
497   /**
498    * Paints the value. The background is filled based on selected.
499    * 
500    * @param g the graphics device.
501    */
502   public void paint(Graphics g)
503   {
504     // Determine background color.
505     Color bgColor;
506     if (selected)
507       bgColor = getBackgroundSelectionColor();
508     else
509       {
510         bgColor = getBackgroundNonSelectionColor();
511         if (bgColor == null)
512           bgColor = getBackground();
513       }
514     // Paint background.
515     int xOffset = -1;
516     if (bgColor != null)
517       {
518         Icon i = getIcon();
519         xOffset = getXOffset();
520         g.setColor(bgColor);
521         g.fillRect(xOffset, 0, getWidth() - xOffset, getHeight());
522       }
523
524     if (hasFocus)
525       {
526         if (drawsFocusBorderAroundIcon)
527           xOffset = 0;
528         else if (xOffset == -1)
529           xOffset = getXOffset();
530         paintFocus(g, xOffset, 0, getWidth() - xOffset, getHeight());
531       }
532     super.paint(g);
533   }
534
535   /**
536    * Paints the focus indicator.
537    */
538   private void paintFocus(Graphics g, int x, int y, int w, int h)
539   {
540     Color col = getBorderSelectionColor();
541     if (col != null)
542       {
543         g.setColor(col);
544         g.drawRect(x, y, w - 1, h - 1);
545       }
546   }
547
548   /**
549    * Determines the X offset of the label that is caused by
550    * the icon.
551    *
552    * @return the X offset of the label
553    */
554   private int getXOffset()
555   {
556     Icon i = getIcon();
557     int offs = 0;
558     if (i != null && getText() != null)
559       offs = i.getIconWidth() + Math.max(0, getIconTextGap() - 1);
560     return offs;
561   }
562
563   /**
564    * Returns the preferred size of the cell.
565    * 
566    * @return The preferred size of the cell.
567    */
568   public Dimension getPreferredSize()
569   {
570     Dimension size = super.getPreferredSize();
571     size.width += 3;
572     return size;
573   } 
574
575   /**
576    * For performance reasons, this method is overridden to do nothing.
577    */
578   public void validate()
579   {
580     // Overridden for performance reasons.
581   } 
582
583   /**
584    * For performance reasons, this method is overridden to do nothing.
585    */
586   public void revalidate()
587   {
588     // Overridden for performance reasons.
589   } 
590
591   /**
592    * For performance reasons, this method is overridden to do nothing.
593    * 
594    * @param tm ignored
595    * @param x coordinate of the region to mark as dirty
596    * @param y coordinate of the region to mark as dirty
597    * @param width dimension of the region to mark as dirty
598    * @param height dimension of the region to mark as dirty
599    */
600   public void repaint(long tm, int x, int y, int width, int height)
601   {
602     // Overridden for performance reasons.
603   } 
604
605   /**
606    * For performance reasons, this method is overridden to do nothing.
607    * 
608    * @param area  the area to repaint.
609    */
610   public void repaint(Rectangle area)
611   {
612     // Overridden for performance reasons.
613   } 
614
615   /**
616    * For performance reasons, this method is overridden to do nothing.
617    * 
618    * @param name  the property name.
619    * @param oldValue  the old value.
620    * @param newValue  the new value.
621    */
622   protected void firePropertyChange(String name, Object oldValue, 
623                                     Object newValue)
624   {
625     // Overridden for performance reasons.
626   }
627
628   /**
629    * For performance reasons, this method is overridden to do nothing.
630    * 
631    * @param name  the property name.
632    * @param oldValue  the old value.
633    * @param newValue  the new value.
634    */
635   public void firePropertyChange(String name, byte oldValue, byte newValue)
636   {
637     // Overridden for performance reasons.
638   }
639
640   /**
641    * For performance reasons, this method is overridden to do nothing.
642    * 
643    * @param name  the property name.
644    * @param oldValue  the old value.
645    * @param newValue  the new value.
646    */
647   public void firePropertyChange(String name, char oldValue, char newValue)
648   {
649     // Overridden for performance reasons.
650   }
651
652   /**
653    * For performance reasons, this method is overridden to do nothing.
654    * 
655    * @param name  the property name.
656    * @param oldValue  the old value.
657    * @param newValue  the new value.
658    */
659   public void firePropertyChange(String name, short oldValue, short newValue)
660   {
661     // Overridden for performance reasons.
662   } 
663
664   /**
665    * For performance reasons, this method is overridden to do nothing.
666    * 
667    * @param name  the property name.
668    * @param oldValue  the old value.
669    * @param newValue  the new value.
670    */
671   public void firePropertyChange(String name, int oldValue, int newValue)
672   {
673     // Overridden for performance reasons.
674   }
675
676   /**
677    * For performance reasons, this method is overridden to do nothing.
678    * 
679    * @param name  the property name.
680    * @param oldValue  the old value.
681    * @param newValue  the new value.
682    */
683   public void firePropertyChange(String name, long oldValue, long newValue)
684   {
685     // Overridden for performance reasons.
686   }
687
688   /**
689    * For performance reasons, this method is overridden to do nothing.
690    * 
691    * @param name  the property name.
692    * @param oldValue  the old value.
693    * @param newValue  the new value.
694    */
695   public void firePropertyChange(String name, float oldValue, float newValue)
696   {
697     // Overridden for performance reasons.
698   }
699
700   /**
701    * For performance reasons, this method is overridden to do nothing.
702    * 
703    * @param name  the property name.
704    * @param oldValue  the old value.
705    * @param newValue  the new value.
706    */
707   public void firePropertyChange(String name, double oldValue, double newValue)
708   {
709     //  Overridden for performance reasons.
710   }
711
712   /**
713    * For performance reasons, this method is overridden to do nothing.
714    * 
715    * @param name  the property name.
716    * @param oldValue  the old value.
717    * @param newValue  the new value.
718    */
719   public void firePropertyChange(String name, boolean oldValue, 
720                                  boolean newValue)
721   {
722     //  Overridden for performance reasons.
723   } 
724
725