8bc4da4f20d405f6024bcdcc7fa8f372e62122af
[idea/community.git] / platform / platform-api / src / com / intellij / ui / ColoredTreeCellRenderer.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.ui;
17
18 import com.intellij.util.ui.EmptyIcon;
19 import com.intellij.util.ui.UIUtil;
20 import org.jetbrains.annotations.Nls;
21 import org.jetbrains.annotations.NotNull;
22
23 import javax.swing.*;
24 import javax.swing.tree.TreeCellRenderer;
25 import java.awt.*;
26
27 /**
28  * @author Vladimir Kondratyev
29  */
30 public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent implements TreeCellRenderer{
31   private static final Icon LOADING_NODE_ICON = new EmptyIcon(8, 16);
32
33   /**
34    * Defines whether the tree is selected or not
35    */
36   protected boolean mySelected;
37   /**
38    * Defines whether the tree has focus or not
39    */
40   protected boolean myFocused;
41
42   protected JTree myTree;
43   private boolean myOpaque = true;
44
45   public final Component getTreeCellRendererComponent(
46     JTree tree,
47     Object value,
48     boolean selected,
49     boolean expanded,
50     boolean leaf,
51     int row,
52     boolean hasFocus
53   ){
54     myTree = tree;
55
56     clear();
57
58     mySelected = selected;
59     myFocused = tree.hasFocus();
60
61     // We paint background if and only if tree path is selected and tree has focus.
62     // If path is selected and tree is not focused then we just paint focused border.
63     if (UIUtil.isFullRowSelectionLAF()) {
64         setBackground(selected ? UIUtil.getTreeSelectionBackground() : null);
65     }
66     else {
67       if (selected) {
68         setPaintFocusBorder(true);
69         if (myFocused) {
70           setBackground(UIUtil.getTreeSelectionBackground());
71         }
72         else {
73           setBackground(null);
74         }
75       }
76       else {
77         setBackground(null);
78       }
79     }
80
81     if (value instanceof LoadingNode) {
82       setForeground(Color.gray);
83       setIcon(LOADING_NODE_ICON);
84     }
85     else {
86       setForeground(tree.getForeground());
87       setIcon(null);
88     }
89
90     if (UIUtil.isUnderNimbusLookAndFeel() && selected && hasFocus) {
91       super.setOpaque(false);  // avoid erasing Nimbus focus frame
92       super.setIconOpaque(false);
93     }
94     else {
95       super.setOpaque(myOpaque || selected && hasFocus || selected && tree.hasFocus()); // draw selection background even for non-opaque tree
96     }
97     customizeCellRenderer(tree, value, selected, expanded, leaf, row, hasFocus);
98
99     if (getFont() == null) {
100       setFont(tree.getFont());
101     }
102
103     return this;
104   }
105
106   public void setOpaque(boolean isOpaque) {
107     myOpaque = isOpaque;
108     super.setOpaque(isOpaque);
109   }
110
111   /**
112    * When the item is selected then we use default tree's selection foreground.
113    * It guaranties readability of selected text in any LAF.
114    */
115   public void append(@NotNull @Nls String fragment, @NotNull SimpleTextAttributes attributes, boolean isMainText) {
116     if (mySelected && (myFocused || UIUtil.isUnderNimbusLookAndFeel())) {
117       super.append(fragment, new SimpleTextAttributes(attributes.getStyle(), UIUtil.getTreeSelectionForeground()), isMainText);
118     }
119     else {
120       super.append(fragment, attributes, isMainText);
121     }
122   }
123
124   /**
125    * This method is invoked only for customization of component.
126    * All component attributes are cleared when this method is being invoked.
127    */
128   public abstract void customizeCellRenderer(
129     JTree tree,
130     Object value,
131     boolean selected,
132     boolean expanded,
133     boolean leaf,
134     int row,
135     boolean hasFocus
136   );
137 }