KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > synth > SynthTreeUI


1 /*
2  * @(#)SynthTreeUI.java 1.23 04/05/27
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.plaf.synth;
8
9 import javax.swing.*;
10 import javax.swing.event.*;
11 import java.awt.*;
12 import java.awt.event.*;
13 import java.awt.datatransfer.*;
14 import java.awt.dnd.*;
15 import java.beans.*;
16 import java.io.*;
17 import java.util.*;
18 import javax.swing.plaf.*;
19 import javax.swing.plaf.basic.*;
20 import javax.swing.tree.*;
21 import javax.swing.text.Position JavaDoc;
22 import sun.swing.plaf.synth.*;
23
24 /**
25  * Skinnable TreeUI.
26  *
27  * @version 1.23, 05/27/04
28  * @author Scott Violet
29  */

30 class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener,
31                                SynthUI {
32     private SynthStyle JavaDoc style;
33     private SynthStyle JavaDoc cellStyle;
34
35     private SynthContext JavaDoc paintContext;
36
37     private boolean drawHorizontalLines;
38     private boolean drawVerticalLines;
39
40     private int leadRow;
41
42     private int padding;
43
44     private boolean useTreeColors;
45
46     private Icon expandedIconWrapper;
47
48
49     public static ComponentUI createUI(JComponent x) {
50     return new SynthTreeUI JavaDoc();
51     }
52
53     SynthTreeUI() {
54         expandedIconWrapper = new ExpandedIconWrapper();
55     }
56
57     public Icon getExpandedIcon() {
58     return expandedIconWrapper;
59     }
60
61     protected void installDefaults() {
62         updateStyle(tree);
63     }
64
65     private void updateStyle(JTree tree) {
66         SynthContext JavaDoc context = getContext(tree, ENABLED);
67         SynthStyle JavaDoc oldStyle = style;
68
69         style = SynthLookAndFeel.updateStyle(context, this);
70         if (style != oldStyle) {
71             Object JavaDoc value;
72
73             setExpandedIcon(style.getIcon(context, "Tree.expandedIcon"));
74             setCollapsedIcon(style.getIcon(context, "Tree.collapsedIcon"));
75
76             setLeftChildIndent(style.getInt(context, "Tree.leftChildIndent",
77                                             0));
78             setRightChildIndent(style.getInt(context, "Tree.rightChildIndent",
79                                              0));
80
81             drawHorizontalLines = style.getBoolean(
82                           context, "Tree.drawHorizontalLines",true);
83             drawVerticalLines = style.getBoolean(
84                         context, "Tree.drawVerticalLines", true);
85
86             value = style.get(context, "Tree.rowHeight");
87             if (value != null) {
88                 LookAndFeel.installProperty(tree, "rowHeight", value);
89             }
90
91             value = style.get(context, "Tree.scrollsOnExpand");
92             LookAndFeel.installProperty(tree, "scrollsOnExpand",
93                                         value != null? value : Boolean.TRUE);
94
95             padding = style.getInt(context, "Tree.padding", 0);
96
97             largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0);
98
99             useTreeColors = style.getBoolean(context,
100                                   "Tree.rendererUseTreeColors", true);
101             
102             Boolean JavaDoc showsRootHandles = style.getBoolean(
103                     context, "Tree.showsRootHandles", Boolean.TRUE);
104             LookAndFeel.installProperty(
105                     tree, JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles);
106
107             if (oldStyle != null) {
108                 uninstallKeyboardActions();
109                 installKeyboardActions();
110             }
111         }
112         context.dispose();
113
114         context = getContext(tree, Region.TREE_CELL, ENABLED);
115         cellStyle = SynthLookAndFeel.updateStyle(context, this);
116         context.dispose();
117     }
118
119     protected void installListeners() {
120         super.installListeners();
121         tree.addPropertyChangeListener(this);
122     }
123
124     public SynthContext JavaDoc getContext(JComponent c) {
125         return getContext(c, getComponentState(c));
126     }
127
128     private SynthContext JavaDoc getContext(JComponent c, int state) {
129         return SynthContext.getContext(SynthContext JavaDoc.class, c,
130                     SynthLookAndFeel.getRegion(c), style, state);
131     }
132
133     private Region JavaDoc getRegion(JTree c) {
134         return SynthLookAndFeel.getRegion(c);
135     }
136
137     private int getComponentState(JComponent c) {
138         return SynthLookAndFeel.getComponentState(c);
139     }
140
141     private SynthContext JavaDoc getContext(JComponent c, Region JavaDoc region) {
142         return getContext(c, region, getComponentState(c, region));
143     }
144
145     private SynthContext JavaDoc getContext(JComponent c, Region JavaDoc region, int state) {
146         return SynthContext.getContext(SynthContext JavaDoc.class, c,
147                                        region, cellStyle, state);
148     }
149
150     private int getComponentState(JComponent c, Region JavaDoc region) {
151         // Always treat the cell as selected, will be adjusted appropriately
152
// when painted.
153
return ENABLED | SELECTED;
154     }
155
156     protected TreeCellEditor createDefaultCellEditor() {
157         TreeCellRenderer renderer = tree.getCellRenderer();
158         DefaultTreeCellEditor editor;
159
160     if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) {
161         editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer)
162                                              renderer);
163     }
164         else {
165             editor = new SynthTreeCellEditor(tree, null);
166         }
167         return editor;
168     }
169
170     protected TreeCellRenderer createDefaultCellRenderer() {
171         return new SynthTreeCellRenderer();
172     }
173
174     protected void uninstallDefaults() {
175         SynthContext JavaDoc context = getContext(tree, ENABLED);
176
177         style.uninstallDefaults(context);
178         context.dispose();
179         style = null;
180
181         context = getContext(tree, Region.TREE_CELL, ENABLED);
182         cellStyle.uninstallDefaults(context);
183         context.dispose();
184         cellStyle = null;
185
186
187     if (tree.getTransferHandler() instanceof UIResource) {
188         tree.setTransferHandler(null);
189     }
190     }
191
192     protected void uninstallListeners() {
193         super.uninstallListeners();
194         tree.removePropertyChangeListener(this);
195     }
196
197     public void update(Graphics g, JComponent c) {
198         SynthContext JavaDoc context = getContext(c);
199
200         SynthLookAndFeel.update(context, g);
201         context.getPainter().paintTreeBackground(context,
202                           g, 0, 0, c.getWidth(), c.getHeight());
203         paint(context, g);
204         context.dispose();
205     }
206
207     public void paintBorder(SynthContext JavaDoc context, Graphics g, int x,
208                             int y, int w, int h) {
209         context.getPainter().paintTreeBorder(context, g, x, y, w, h);
210     }
211
212     public void paint(Graphics g, JComponent c) {
213         SynthContext JavaDoc context = getContext(c);
214
215         paint(context, g);
216         context.dispose();
217     }
218
219     private void adjustCellBounds(JTree tree, Rectangle bounds, Insets i){
220         if (bounds != null) {
221             if (i == null) {
222                 i = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
223             }
224             bounds.x += i.left;
225             bounds.y += i.top;
226         }
227     }
228
229     private void updateLeadRow() {
230     leadRow = getRowForPath(tree, tree.getLeadSelectionPath());
231     }
232
233     protected void paint(SynthContext JavaDoc context, Graphics g) {
234         paintContext = context;
235
236         updateLeadRow();
237
238     Rectangle paintBounds = g.getClipBounds();
239     Insets insets = tree.getInsets();
240     TreePath initialPath = getClosestPathForLocation(tree, 0,
241                                                          paintBounds.y);
242     Enumeration paintingEnumerator = treeState.getVisiblePathsFrom
243                                           (initialPath);
244     int row = treeState.getRowForPath(initialPath);
245     int endY = paintBounds.y + paintBounds.height;
246         TreeModel treeModel = tree.getModel();
247         SynthContext JavaDoc cellContext = getContext(tree, Region.TREE_CELL);
248
249     drawingCache.clear();
250
251         setHashColor(context.getStyle().getColor(context,
252                                                 ColorType.FOREGROUND));
253
254     if (paintingEnumerator != null) {
255             // First pass, draw the rows
256

257         boolean done = false;
258         boolean isExpanded;
259         boolean hasBeenExpanded;
260         boolean isLeaf;
261         Rectangle boundsBuffer = new Rectangle();
262             Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0);
263         Rectangle bounds;
264         TreePath path;
265             TreeCellRenderer renderer = tree.getCellRenderer();
266             DefaultTreeCellRenderer dtcr = (renderer instanceof
267                        DefaultTreeCellRenderer) ? (DefaultTreeCellRenderer)
268                        renderer : null;
269
270             configureRenderer(cellContext);
271         while (!done && paintingEnumerator.hasMoreElements()) {
272         path = (TreePath)paintingEnumerator.nextElement();
273         if (path != null) {
274             isLeaf = treeModel.isLeaf(path.getLastPathComponent());
275             if (isLeaf) {
276             isExpanded = hasBeenExpanded = false;
277                     }
278             else {
279             isExpanded = treeState.getExpandedState(path);
280             hasBeenExpanded = tree.hasBeenExpanded(path);
281             }
282             bounds = treeState.getBounds(path, boundsBuffer);
283                     adjustCellBounds(tree, bounds, insets);
284                     rowBounds.y = bounds.y;
285                     rowBounds.height = bounds.height;
286             paintRow(renderer, dtcr, context, cellContext, g,
287                              paintBounds, insets, bounds, rowBounds, path,
288                              row, isExpanded, hasBeenExpanded, isLeaf);
289             if ((bounds.y + bounds.height) >= endY) {
290             done = true;
291                     }
292         }
293         else {
294             done = true;
295         }
296         row++;
297         }
298
299         // Draw the connecting lines and controls.
300
// Find each parent and have them draw a line to their last child
301
boolean rootVisible = tree.isRootVisible();
302             TreePath parentPath = initialPath;
303         parentPath = parentPath.getParentPath();
304         while (parentPath != null) {
305                 paintVerticalPartOfLeg(g, paintBounds, insets, parentPath);
306         drawingCache.put(parentPath, Boolean.TRUE);
307         parentPath = parentPath.getParentPath();
308         }
309         done = false;
310             paintingEnumerator = treeState.getVisiblePathsFrom(initialPath);
311         while (!done && paintingEnumerator.hasMoreElements()) {
312         path = (TreePath)paintingEnumerator.nextElement();
313         if (path != null) {
314             isLeaf = treeModel.isLeaf(path.getLastPathComponent());
315             if (isLeaf) {
316             isExpanded = hasBeenExpanded = false;
317                     }
318             else {
319             isExpanded = treeState.getExpandedState(path);
320             hasBeenExpanded = tree.hasBeenExpanded(path);
321             }
322             bounds = treeState.getBounds(path, boundsBuffer);
323                     adjustCellBounds(tree, bounds, insets);
324             // See if the vertical line to the parent has been drawn.
325
parentPath = path.getParentPath();
326             if (parentPath != null) {
327             if (drawingCache.get(parentPath) == null) {
328                             paintVerticalPartOfLeg(g, paintBounds, insets,
329                                                    parentPath);
330                 drawingCache.put(parentPath, Boolean.TRUE);
331             }
332             paintHorizontalPartOfLeg(g,
333                                                  paintBounds, insets, bounds,
334                                                  path, row, isExpanded,
335                          hasBeenExpanded, isLeaf);
336             }
337             else if (rootVisible && row == 0) {
338             paintHorizontalPartOfLeg(g,
339                                                  paintBounds, insets, bounds,
340                                                  path, row, isExpanded,
341                          hasBeenExpanded, isLeaf);
342             }
343             if (shouldPaintExpandControl(path, row, isExpanded,
344                                                  hasBeenExpanded, isLeaf)) {
345             paintExpandControl(g, paintBounds,
346                                            insets, bounds, path, row,
347                                            isExpanded, hasBeenExpanded,isLeaf);
348             }
349             if ((bounds.y + bounds.height) >= endY) {
350             done = true;
351                     }
352         }
353         else {
354             done = true;
355         }
356         row++;
357         }
358     }
359         cellContext.dispose();
360     // Empty out the renderer pane, allowing renderers to be gc'ed.
361
rendererPane.removeAll();
362     }
363
364     private void configureRenderer(SynthContext JavaDoc context) {
365         TreeCellRenderer renderer = tree.getCellRenderer();
366
367         if (renderer instanceof DefaultTreeCellRenderer) {
368             DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer;
369             SynthStyle JavaDoc style = context.getStyle();
370
371             context.setComponentState(ENABLED | SELECTED);
372             Color color = r.getTextSelectionColor();
373             if (color == null || (color instanceof UIResource)) {
374                 r.setTextSelectionColor(style.getColor(
375                                      context, ColorType.TEXT_FOREGROUND));
376             }
377             color = r.getBackgroundSelectionColor();
378             if (color == null || (color instanceof UIResource)) {
379                 r.setBackgroundSelectionColor(style.getColor(
380                                         context, ColorType.TEXT_BACKGROUND));
381             }
382
383             context.setComponentState(ENABLED);
384             color = r.getTextNonSelectionColor();
385             if (color == null || color instanceof UIResource) {
386                 r.setTextNonSelectionColor(style.getColor(
387                                         context, ColorType.TEXT_FOREGROUND));
388             }
389             color = r.getBackgroundNonSelectionColor();
390             if (color instanceof UIResource) {
391                 r.setBackgroundNonSelectionColor(style.getColor(
392                                   context, ColorType.TEXT_BACKGROUND));
393             }
394         }
395     }
396
397     protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
398                         Insets insets, Rectangle bounds,
399                         TreePath path, int row,
400                         boolean isExpanded,
401                         boolean hasBeenExpanded, boolean
402                         isLeaf) {
403         if (drawHorizontalLines) {
404             super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds,
405                                            path, row, isExpanded,
406                                            hasBeenExpanded, isLeaf);
407         }
408     }
409
410     protected void paintHorizontalLine(Graphics g, JComponent c, int y,
411                       int left, int right) {
412         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
413             paintContext, "Tree.horizontalLine", g, left, y, right, y);
414     }
415
416     protected void paintVerticalPartOfLeg(Graphics g,
417                                           Rectangle clipBounds, Insets insets,
418                                           TreePath path) {
419         if (drawVerticalLines) {
420             super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
421         }
422     }
423
424     protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
425                     int bottom) {
426         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
427             paintContext, "Tree.verticalLine", g, x, top, x, bottom);
428     }
429
430     protected void paintRow(TreeCellRenderer renderer,
431                DefaultTreeCellRenderer dtcr, SynthContext JavaDoc treeContext,
432                SynthContext JavaDoc cellContext, Graphics g, Rectangle clipBounds,
433                Insets insets, Rectangle bounds, Rectangle rowBounds,
434                TreePath path, int row, boolean isExpanded,
435                boolean hasBeenExpanded, boolean isLeaf) {
436     // Don't paint the renderer if editing this row.
437
boolean selected = tree.isRowSelected(row);
438
439         if (selected) {
440             cellContext.setComponentState(ENABLED | SELECTED);
441         }
442         else {
443             cellContext.setComponentState(ENABLED);
444         }
445         if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof
446                              UIResource)) {
447             dtcr.setBorderSelectionColor(style.getColor(
448                                              cellContext, ColorType.FOCUS));
449         }
450         SynthLookAndFeel.updateSubregion(cellContext, g, rowBounds);
451         cellContext.getPainter().paintTreeCellBackground(cellContext, g,
452                     rowBounds.x, rowBounds.y, rowBounds.width,
453                     rowBounds.height);
454         cellContext.getPainter().paintTreeCellBorder(cellContext, g,
455                     rowBounds.x, rowBounds.y, rowBounds.width,
456                     rowBounds.height);
457     if (editingComponent != null && editingRow == row) {
458         return;
459         }
460
461     int leadIndex;
462
463     if (tree.hasFocus()) {
464         leadIndex = leadRow;
465     }
466     else {
467         leadIndex = -1;
468         }
469
470     Component component = renderer.getTreeCellRendererComponent(
471                          tree, path.getLastPathComponent(),
472                          selected, isExpanded, isLeaf, row,
473                          (leadIndex == row));
474
475     rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y,
476                     bounds.width, bounds.height, true);
477     }
478
479     protected void drawCentered(Component c, Graphics graphics, Icon icon,
480                 int x, int y) {
481         int w = SynthIcon.getIconWidth(icon, paintContext);
482         int h = SynthIcon.getIconHeight(icon, paintContext);
483
484     SynthIcon.paintIcon(icon, paintContext, graphics, x - w/2, y - h/2, w,
485                             h);
486     }
487
488     public void propertyChange(PropertyChangeEvent event) {
489         if (SynthLookAndFeel.shouldUpdateStyle(event)) {
490             updateStyle((JTree)event.getSource());
491         }
492     }
493
494     protected int getRowX(int row, int depth) {
495         return super.getRowX(row, depth) + padding;
496     }
497
498
499     private class SynthTreeCellRenderer extends DefaultTreeCellRenderer
500                                implements UIResource {
501         SynthTreeCellRenderer() {
502         }
503         public String JavaDoc getName() {
504             return "Tree.cellRenderer";
505         }
506         public Component getTreeCellRendererComponent(JTree tree, Object JavaDoc value,
507                                                       boolean sel,
508                                                       boolean expanded,
509                                                       boolean leaf, int row,
510                                                       boolean hasFocus) {
511             if (!useTreeColors && (sel || hasFocus)) {
512                 SynthLookAndFeel.setSelectedUI((SynthLabelUI JavaDoc)SynthLookAndFeel.
513                              getUIOfType(getUI(), SynthLabelUI JavaDoc.class),
514                                    sel, hasFocus, tree.isEnabled());
515             }
516             else {
517                 SynthLookAndFeel.resetSelectedUI();
518             }
519             return super.getTreeCellRendererComponent(tree, value, sel,
520                                                       expanded, leaf, row, hasFocus);
521         }
522         public void paint(Graphics g) {
523             paintComponent(g);
524             if (hasFocus) {
525                 SynthContext JavaDoc context = getContext(tree, Region.TREE_CELL);
526
527                 if (context.getStyle() == null) {
528                     assert false: "SynthTreeCellRenderer is being used " +
529                         "outside of UI that created it";
530                     return;
531                 }
532                 int imageOffset = 0;
533                 Icon currentI = getIcon();
534
535                 if(currentI != null && getText() != null) {
536                     imageOffset = currentI.getIconWidth() +
537                                           Math.max(0, getIconTextGap() - 1);
538                 }
539                 if (selected) {
540                     context.setComponentState(ENABLED | SELECTED);
541                 }
542                 else {
543                     context.setComponentState(ENABLED);
544                 }
545                 if(getComponentOrientation().isLeftToRight()) {
546                     context.getPainter().paintTreeCellFocus(context, g,
547                             imageOffset, 0, getWidth() - imageOffset,
548                             getHeight());
549                 }
550                 else {
551                     context.getPainter().paintTreeCellFocus(context, g,
552                             0, 0, getWidth() - imageOffset, getHeight());
553                 }
554                 context.dispose();
555             }
556             SynthLookAndFeel.resetSelectedUI();
557         }
558     }
559
560
561     private static class SynthTreeCellEditor extends DefaultTreeCellEditor {
562         public SynthTreeCellEditor(JTree tree,
563                                    DefaultTreeCellRenderer renderer) {
564             super(tree, renderer);
565             setBorderSelectionColor(null);
566         }
567
568         protected TreeCellEditor createTreeCellEditor() {
569             JTextField tf = new JTextField() {
570                 public String JavaDoc getName() {
571                     return "Tree.cellEditor";
572                 }
573             };
574             DefaultCellEditor editor = new DefaultCellEditor(tf);
575
576             // One click to edit.
577
editor.setClickCountToStart(1);
578             return editor;
579         }
580     }
581
582
583     //
584
// BasicTreeUI directly uses expandIcon outside of the Synth methods.
585
// To get the correct context we return an instance of this that fetches
586
// the SynthContext as needed.
587
//
588
private class ExpandedIconWrapper extends SynthIcon {
589         public void paintIcon(SynthContext JavaDoc context, Graphics g, int x,
590                               int y, int w, int h) {
591             if (context == null) {
592                 context = getContext(tree);
593                 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
594                 context.dispose();
595             }
596             else {
597                 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
598             }
599         }
600
601         public int getIconWidth(SynthContext JavaDoc context) {
602             int width;
603             if (context == null) {
604                 context = getContext(tree);
605                 width = SynthIcon.getIconWidth(expandedIcon, context);
606                 context.dispose();
607             }
608             else {
609                 width = SynthIcon.getIconWidth(expandedIcon, context);
610             }
611             return width;
612         }
613
614         public int getIconHeight(SynthContext JavaDoc context) {
615             int height;
616             if (context == null) {
617                 context = getContext(tree);
618                 height = SynthIcon.getIconHeight(expandedIcon, context);
619                 context.dispose();
620             }
621             else {
622                 height = SynthIcon.getIconHeight(expandedIcon, context);
623             }
624             return height;
625         }
626     }
627 }
628
Popular Tags