blob: 132d9b6e55b0ac06ecb59e51b71d87da86ccb559 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.WideSelectionTreeUI;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
/**
* @author Vladimir Kondratyev
*/
public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent implements TreeCellRenderer{
private static final Icon LOADING_NODE_ICON = new EmptyIcon(8, 16);
/**
* Defines whether the tree is selected or not
*/
protected boolean mySelected;
/**
* Defines whether the tree has focus or not
*/
private boolean myFocused;
private boolean myFocusedCalculated;
protected JTree myTree;
private boolean myOpaque = true;
@Override
public final Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus){
myTree = tree;
clear();
mySelected = selected;
myFocusedCalculated = false;
// We paint background if and only if tree path is selected and tree has focus.
// If path is selected and tree is not focused then we just paint focused border.
if (UIUtil.isFullRowSelectionLAF()) {
setBackground(selected ? UIUtil.getTreeSelectionBackground() : null);
}
else if (tree.getUI() instanceof WideSelectionTreeUI && ((WideSelectionTreeUI)tree.getUI()).isWideSelection()) {
setPaintFocusBorder(false);
if (selected) {
setBackground(hasFocus ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeUnfocusedSelectionBackground());
}
}
else if (selected) {
setPaintFocusBorder(true);
if (isFocused()) {
setBackground(UIUtil.getTreeSelectionBackground());
}
else {
setBackground(null);
}
}
else {
setBackground(null);
}
if (value instanceof LoadingNode) {
setForeground(JBColor.GRAY);
setIcon(LOADING_NODE_ICON);
}
else {
setForeground(tree.getForeground());
setIcon(null);
}
if (UIUtil.isUnderGTKLookAndFeel()){
super.setOpaque(false); // avoid nasty background
super.setIconOpaque(false);
}
else if (UIUtil.isUnderNimbusLookAndFeel() && selected && hasFocus) {
super.setOpaque(false); // avoid erasing Nimbus focus frame
super.setIconOpaque(false);
}
else if (tree.getUI() instanceof WideSelectionTreeUI && ((WideSelectionTreeUI)tree.getUI()).isWideSelection()) {
super.setOpaque(false); // avoid erasing Nimbus focus frame
super.setIconOpaque(false);
}
else {
super.setOpaque(myOpaque || selected && hasFocus || selected && isFocused()); // draw selection background even for non-opaque tree
}
if (tree.getUI() instanceof WideSelectionTreeUI && UIUtil.isUnderAquaBasedLookAndFeel()) {
setMyBorder(null);
setIpad(new Insets(0, 2, 0, 2));
}
customizeCellRenderer(tree, value, selected, expanded, leaf, row, hasFocus);
return this;
}
public JTree getTree() {
return myTree;
}
protected final boolean isFocused() {
if (!myFocusedCalculated) {
myFocused = calcFocusedState();
myFocusedCalculated = true;
}
return myFocused;
}
protected boolean calcFocusedState() {
return myTree.hasFocus();
}
@Override
public void setOpaque(boolean isOpaque) {
myOpaque = isOpaque;
super.setOpaque(isOpaque);
}
@Override
public Font getFont() {
Font font = super.getFont();
// Cell renderers could have no parent and no explicit set font.
// Take tree font in this case.
if (font != null) return font;
JTree tree = getTree();
return tree != null ? tree.getFont() : null;
}
/**
* When the item is selected then we use default tree's selection foreground.
* It guaranties readability of selected text in any LAF.
*/
@Override
public void append(@NotNull @Nls String fragment, @NotNull SimpleTextAttributes attributes, boolean isMainText) {
if (mySelected && isFocused()) {
super.append(fragment, new SimpleTextAttributes(attributes.getStyle(), UIUtil.getTreeSelectionForeground()), isMainText);
}
else if (mySelected && UIUtil.isUnderAquaBasedLookAndFeel()) {
super.append(fragment, new SimpleTextAttributes(attributes.getStyle(), UIUtil.getTreeForeground()), isMainText);
}
else {
super.append(fragment, attributes, isMainText);
}
}
/**
* This method is invoked only for customization of component.
* All component attributes are cleared when this method is being invoked.
*/
public abstract void customizeCellRenderer(@NotNull JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus);
}