001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.ui.components.tree;
042:
043: import org.netbeans.lib.profiler.ui.UIConstants;
044: import org.netbeans.lib.profiler.ui.components.tree.TreeCellRendererPersistent;
045: import java.awt.*;
046: import javax.swing.*;
047: import javax.swing.plaf.ColorUIResource;
048: import javax.swing.plaf.FontUIResource;
049:
050: public class EnhancedTreeCellRenderer extends JPanel implements
051: TreeCellRendererPersistent {
052: //~ Instance fields ----------------------------------------------------------------------------------------------------------
053:
054: protected Color backgroundNonSelectionColor;
055: protected Color backgroundSelectionColor = UIConstants.TABLE_SELECTION_BACKGROUND_COLOR;
056: protected Color borderSelectionColor;
057: protected Color textNonSelectionColor;
058:
059: // Colors
060: protected Color textSelectionColor = UIConstants.TABLE_SELECTION_FOREGROUND_COLOR;
061: protected boolean hasFocus;
062: protected boolean selected;
063:
064: // Icons
065: private transient Icon closedIcon = UIManager
066: .getIcon("Tree.closedIcon"); // NOI18N
067: private transient Icon leafIcon = UIManager
068: .getIcon("Tree.leafIcon"); // NOI18N
069: private transient Icon openIcon = UIManager
070: .getIcon("Tree.openIcon"); // NOI18N
071: private BorderLayout borderLayout;
072:
073: // subcomponents
074: private JLabel label1;
075: private JLabel label2;
076: private JLabel label3;
077: private JTree tree;
078:
079: //~ Constructors -------------------------------------------------------------------------------------------------------------
080:
081: /**
082: * Returns a new instance of DefaultTreeCellRenderer. Alignment is
083: * set to left aligned. Icons and text color are determined from the
084: * UIManager.
085: */
086: public EnhancedTreeCellRenderer() {
087: setOpaque(false);
088:
089: label1 = new JLabel();
090: label2 = new JLabel();
091: label3 = new JLabel();
092:
093: label2.setFont(label1.getFont().deriveFont(Font.BOLD));
094:
095: setLayout(borderLayout = new BorderLayout());
096:
097: JPanel innerPanel = new JPanel();
098: innerPanel.setOpaque(false);
099: innerPanel.setLayout(new BorderLayout());
100:
101: add(label1, BorderLayout.WEST);
102: add(innerPanel, BorderLayout.CENTER);
103: innerPanel.add(label2, BorderLayout.WEST);
104: innerPanel.add(label3, BorderLayout.CENTER);
105:
106: label1.setHorizontalAlignment(JLabel.LEFT);
107:
108: setLeafIcon(UIManager.getIcon("Tree.leafIcon")); // NOI18N
109: setClosedIcon(UIManager.getIcon("Tree.closedIcon")); // NOI18N
110: setOpenIcon(UIManager.getIcon("Tree.openIcon")); // NOI18N
111:
112: setTextSelectionColor(UIManager
113: .getColor("Tree.selectionForeground")); // NOI18N
114: setTextNonSelectionColor(UIManager
115: .getColor("Tree.textForeground")); // NOI18N
116: setBackgroundSelectionColor(UIManager
117: .getColor("Tree.selectionBackground")); // NOI18N
118: setBackgroundNonSelectionColor(UIManager
119: .getColor("Tree.textBackground")); // NOI18N
120: setBorderSelectionColor(UIManager
121: .getColor("Tree.selectionBorderColor")); // NOI18N
122: }
123:
124: //~ Methods ------------------------------------------------------------------------------------------------------------------
125:
126: /**
127: * Subclassed to map <code>ColorUIResource</code>s to null. If
128: * <code>color</code> is null, or a <code>ColorUIResource</code>, this
129: * has the effect of letting the background color of the JTree show
130: * through. On the other hand, if <code>color</code> is non-null, and not
131: * a <code>ColorUIResource</code>, the background becomes
132: * <code>color</code>.
133: */
134: public void setBackground(Color color) {
135: if (color instanceof ColorUIResource) {
136: color = null;
137: }
138:
139: super .setBackground(color);
140: }
141:
142: /**
143: * Sets the background color to be used for non selected nodes.
144: */
145: public void setBackgroundNonSelectionColor(Color newColor) {
146: backgroundNonSelectionColor = newColor;
147: }
148:
149: /**
150: * Returns the background color to be used for non selected nodes.
151: */
152: public Color getBackgroundNonSelectionColor() {
153: return backgroundNonSelectionColor;
154: }
155:
156: /**
157: * Sets the color to use for the background if node is selected.
158: */
159: public void setBackgroundSelectionColor(Color newColor) {
160: backgroundSelectionColor = newColor;
161: }
162:
163: /**
164: * Returns the color to use for the background if node is selected.
165: */
166: public Color getBackgroundSelectionColor() {
167: return backgroundSelectionColor;
168: }
169:
170: /**
171: * Sets the color to use for the border.
172: */
173: public void setBorderSelectionColor(Color newColor) {
174: borderSelectionColor = newColor;
175: }
176:
177: /**
178: * Returns the color the border is drawn.
179: */
180: public Color getBorderSelectionColor() {
181: return borderSelectionColor;
182: }
183:
184: /**
185: * Sets the icon used to represent non-leaf nodes that are not expanded.
186: */
187: public void setClosedIcon(Icon newIcon) {
188: closedIcon = newIcon;
189: }
190:
191: /**
192: * Returns the icon used to represent non-leaf nodes that are not
193: * expanded.
194: */
195: public Icon getClosedIcon() {
196: return closedIcon;
197: }
198:
199: /**
200: * Subclassed to map <code>FontUIResource</code>s to null. If
201: * <code>font</code> is null, or a <code>FontUIResource</code>, this
202: * has the effect of letting the font of the JTree show
203: * through. On the other hand, if <code>font</code> is non-null, and not
204: * a <code>FontUIResource</code>, the font becomes <code>font</code>.
205: */
206: public void setFont(Font font) {
207: if (font instanceof FontUIResource) {
208: font = null;
209: }
210:
211: super .setFont(font);
212: }
213:
214: /**
215: * Gets the font of this component.
216: *
217: * @return this component's font; if a font has not been set
218: * for this component, the font of its parent is returned
219: */
220: public Font getFont() {
221: Font font = super .getFont();
222:
223: if ((font == null) && (tree != null)) {
224: // Strive to return a non-null value, otherwise the html support
225: // will typically pick up the wrong font in certain situations.
226: font = tree.getFont();
227: }
228:
229: return font;
230: }
231:
232: /**
233: * Sets the icon used to represent leaf nodes.
234: */
235: public void setLeafIcon(Icon newIcon) {
236: leafIcon = newIcon;
237: }
238:
239: /**
240: * Returns the icon used to represent leaf nodes.
241: */
242: public Icon getLeafIcon() {
243: return leafIcon;
244: }
245:
246: /**
247: * Sets the icon used to represent non-leaf nodes that are expanded.
248: */
249: public void setOpenIcon(Icon newIcon) {
250: openIcon = newIcon;
251: }
252:
253: /**
254: * Returns the icon used to represent non-leaf nodes that are expanded.
255: */
256: public Icon getOpenIcon() {
257: return openIcon;
258: }
259:
260: /**
261: * Overrides <code>JComponent.getPreferredSize</code> to
262: * return slightly wider preferred size value.
263: */
264: public Dimension getPreferredSize() {
265: Dimension retDimension = super .getPreferredSize();
266:
267: if (retDimension != null) {
268: retDimension = new Dimension(retDimension.width + 3,
269: retDimension.height);
270: }
271:
272: return retDimension;
273: }
274:
275: /**
276: * Sets the color the text is drawn with when the node isn't selected.
277: */
278: public void setTextNonSelectionColor(Color newColor) {
279: textNonSelectionColor = newColor;
280: }
281:
282: /**
283: * Returns the color the text is drawn with when the node isn't selected.
284: */
285: public Color getTextNonSelectionColor() {
286: return textNonSelectionColor;
287: }
288:
289: /**
290: * Sets the color the text is drawn with when the node is selected.
291: */
292: public void setTextSelectionColor(Color newColor) {
293: textSelectionColor = newColor;
294: }
295:
296: /**
297: * Returns the color the text is drawn with when the node is selected.
298: */
299: public Color getTextSelectionColor() {
300: return textSelectionColor;
301: }
302:
303: /**
304: * Configures the renderer based on the passed in components.
305: * The value is set from messaging the tree with
306: * <code>convertValueToText</code>, which ultimately invokes
307: * <code>toString</code> on <code>value</code>.
308: * The foreground color is set based on the selection and the icon
309: * is set based on on leaf and expanded.
310: */
311: public Component getTreeCellRendererComponent(JTree tree,
312: Object value, boolean sel, boolean expanded, boolean leaf,
313: int row, boolean hasFocus) {
314: String stringValue = tree.convertValueToText(value, sel,
315: expanded, leaf, row, hasFocus);
316:
317: this .tree = tree;
318: this .hasFocus = hasFocus;
319:
320: String firstLabel = getLabel1Text(value, stringValue);
321: label1.setText(firstLabel);
322:
323: if ("".equals(firstLabel)) {
324: borderLayout.setHgap(label1.getIconTextGap()); // NOI18N
325: } else {
326: borderLayout.setHgap(0);
327: }
328:
329: label2.setText(getLabel2Text(value, stringValue));
330: label3.setText(getLabel3Text(value, stringValue));
331:
332: if (sel) {
333: label1.setForeground(getTextSelectionColor());
334: label2.setForeground(getTextSelectionColor());
335:
336: Color c = getTextSelectionColor();
337: label3.setForeground(c.equals(Color.BLACK) ? Color.GRAY : c
338: .brighter());
339: } else {
340: label1.setForeground(getTextNonSelectionColor());
341: label2.setForeground(getTextNonSelectionColor());
342:
343: Color c = getTextNonSelectionColor();
344: label3.setForeground(c.equals(Color.BLACK) ? Color.GRAY : c
345: .brighter());
346: }
347:
348: if (!tree.isEnabled()) {
349: label1.setEnabled(false);
350: label2.setEnabled(false);
351: label3.setEnabled(false);
352:
353: if (leaf) {
354: label1.setDisabledIcon(getLeafIcon(value));
355: } else if (expanded) {
356: label1.setDisabledIcon(getOpenIcon(value));
357: } else {
358: label1.setDisabledIcon(getClosedIcon(value));
359: }
360: } else {
361: label1.setEnabled(true);
362: label2.setEnabled(true);
363: label3.setEnabled(true);
364:
365: if (leaf) {
366: label1.setIcon(getLeafIcon(value));
367: } else if (expanded) {
368: label1.setIcon(getOpenIcon(value));
369: } else {
370: label1.setIcon(getClosedIcon(value));
371: }
372: }
373:
374: label1.setComponentOrientation(tree.getComponentOrientation()); // TODO [ian]: what does this mean wrt label2, label3
375:
376: selected = sel;
377:
378: return this ;
379: }
380:
381: public Component getTreeCellRendererComponentPersistent(JTree tree,
382: Object value, boolean sel, boolean expanded, boolean leaf,
383: int row, boolean hasFocus) {
384: EnhancedTreeCellRenderer renderer = new EnhancedTreeCellRenderer();
385: renderer.setLeafIcon(leafIcon);
386: renderer.setClosedIcon(closedIcon);
387: renderer.setOpenIcon(openIcon);
388:
389: return renderer.getTreeCellRendererComponent(tree, value, sel,
390: expanded, leaf, row, hasFocus);
391: }
392:
393: /**
394: * Overridden for performance reasons.
395: * See the <a href="#override">Implementation Note</a>
396: * for more information.
397: */
398: public void firePropertyChange(String propertyName, byte oldValue,
399: byte newValue) {
400: }
401:
402: /**
403: * Overridden for performance reasons.
404: * See the <a href="#override">Implementation Note</a>
405: * for more information.
406: */
407: public void firePropertyChange(String propertyName, char oldValue,
408: char newValue) {
409: }
410:
411: /**
412: * Overridden for performance reasons.
413: * See the <a href="#override">Implementation Note</a>
414: * for more information.
415: */
416: public void firePropertyChange(String propertyName, short oldValue,
417: short newValue) {
418: }
419:
420: /**
421: * Overridden for performance reasons.
422: * See the <a href="#override">Implementation Note</a>
423: * for more information.
424: */
425: public void firePropertyChange(String propertyName, int oldValue,
426: int newValue) {
427: }
428:
429: /**
430: * Overridden for performance reasons.
431: * See the <a href="#override">Implementation Note</a>
432: * for more information.
433: */
434: public void firePropertyChange(String propertyName, long oldValue,
435: long newValue) {
436: }
437:
438: /**
439: * Overridden for performance reasons.
440: * See the <a href="#override">Implementation Note</a>
441: * for more information.
442: */
443: public void firePropertyChange(String propertyName, float oldValue,
444: float newValue) {
445: }
446:
447: /**
448: * Overridden for performance reasons.
449: * See the <a href="#override">Implementation Note</a>
450: * for more information.
451: */
452: public void firePropertyChange(String propertyName,
453: double oldValue, double newValue) {
454: }
455:
456: /**
457: * Overridden for performance reasons.
458: * See the <a href="#override">Implementation Note</a>
459: * for more information.
460: */
461: public void firePropertyChange(String propertyName,
462: boolean oldValue, boolean newValue) {
463: }
464:
465: /**
466: * Paints the value. The background is filled based on selected.
467: */
468: public void paint(Graphics g) {
469: Color bColor;
470:
471: if (selected) {
472: bColor = getBackgroundSelectionColor();
473: } else {
474: bColor = getBackgroundNonSelectionColor();
475:
476: if (bColor == null) {
477: bColor = getBackground();
478: }
479: }
480:
481: if (bColor != null) {
482: g.setColor(bColor);
483: g.fillRect(0, 0, getWidth(), getHeight());
484: }
485:
486: if (hasFocus) {
487: Color bsColor = getBorderSelectionColor();
488:
489: if (bsColor != null) {
490: g.setColor(bsColor);
491: g.drawRect(0, 0, getWidth(), getHeight());
492: }
493: }
494:
495: super .paint(g);
496: }
497:
498: protected Icon getClosedIcon(Object value) {
499: return getClosedIcon();
500: }
501:
502: /**
503: * @param node The node value
504: * @param value Entire tree node text
505: * @return First part to display in plain font
506: */
507: protected String getLabel1Text(Object node, String value) {
508: return value;
509: }
510:
511: /**
512: * @param node The node value
513: * @param value Entire tree node text
514: * @return Middle part to display in bold font
515: */
516: protected String getLabel2Text(Object node, String value) {
517: return ""; // NOI18N
518: }
519:
520: /**
521: * @param node The node value
522: * @param value Entire tree node text
523: * @return Lat part to display in gray font
524: */
525: protected String getLabel3Text(Object node, String value) {
526: return ""; // NOI18N
527: }
528:
529: protected Icon getLeafIcon(Object value) {
530: return getLeafIcon();
531: }
532:
533: protected Icon getOpenIcon(Object value) {
534: return getOpenIcon();
535: }
536:
537: /**
538: * Overridden for performance reasons.
539: * See the <a href="#override">Implementation Note</a>
540: * for more information.
541: */
542: protected void firePropertyChange(String propertyName,
543: Object oldValue, Object newValue) {
544: // Strings get interned...
545: if (propertyName == "text") { // NOI18N
546: super.firePropertyChange(propertyName, oldValue, newValue);
547: }
548: }
549: }
|