/*
 * Copyright 2000-2012 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;

  protected JTree myTree;

  private boolean myOpaque = true;
  public final Component getTreeCellRendererComponent(
    JTree tree,
    Object value,
    boolean selected,
    boolean expanded,
    boolean leaf,
    int row,
    boolean hasFocus
  ){
    myTree = tree;

    clear();

    mySelected = selected;
    myFocused = hasFocus;

    // 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 (hasFocus) {
          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); // draw selection background even for non-opaque tree
    }

    if (tree.getUI() instanceof WideSelectionTreeUI && UIUtil.isUnderAquaBasedLookAndFeel()) {
      setMyBorder(null);
      setIpad(new Insets(0, 2,  0, 2));
    }

    if (getFont() == null) {
      setFont(tree.getFont());
    }

    customizeCellRenderer(tree, value, selected, expanded, leaf, row, hasFocus);

    return this;
  }

  public JTree getTree() {
    return myTree;
  }

  public void setOpaque(boolean isOpaque) {
    myOpaque = isOpaque;
    super.setOpaque(isOpaque);
  }

  /**
   * When the item is selected then we use default tree's selection foreground.
   * It guaranties readability of selected text in any LAF.
   */
  public void append(@NotNull @Nls String fragment, @NotNull SimpleTextAttributes attributes, boolean isMainText) {
    if (mySelected && myFocused) {
      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(
    JTree tree,
    Object value,
    boolean selected,
    boolean expanded,
    boolean leaf,
    int row,
    boolean hasFocus
  );
}

@@ -17,17 +17,17 @@
 2000-201
-2
+3
  JetBrai
@@ -1310,16 +1310,55 @@
 Focused;
+%0A  private boolean myFocusedCalculated;
 %0A%0A  prot
@@ -1681,19 +1681,26 @@
 used
- = hasFocus
+Calculated = false
 ;%0A%0A 
@@ -2377,24 +2377,27 @@
     if (
-ha
+i
 sFocus
+ed()
 ) %7B%0A    
@@ -3390,16 +3390,43 @@
 hasFocus
+ %7C%7C selected && isFocused()
 ); // dr
@@ -3866,24 +3866,277 @@
 yTree;%0A  %7D%0A%0A
+  protected final boolean isFocused() %7B%0A    if (!myFocusedCalculated) %7B%0A      myFocused = calcFocusedState();%0A      myFocusedCalculated = true;%0A    %7D%0A    return myFocused;%0A  %7D%0A%0A  protected boolean calcFocusedState() %7B%0A    return myTree.hasFocus();%0A  %7D%0A%0A
   public voi
@@ -4518,25 +4518,27 @@
 cted && 
-my
+is
 Focused
+()
 ) %7B%0A    

I was wrong. rollback