package com.gordon.tree;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import com.gordon.tree.CustomBorderDemo.GradientTitleBorder;
public class NodeRolloverDemo extends JPanel {
private JTree tree = new JTree();
private int mouseOverRow = -1;
/**
* Demonstrates how to highlight a node in a tree when the mouse is over it.
*/
private NodeRolloverDemo() {
setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(tree);
add(scrollPane, BorderLayout.CENTER);
tree.setModel(createModel());
tree.addMouseMotionListener(mouseOverListener);
tree.setCellRenderer(renderer);
}
/**
* MouseMotionListener that listens for changes in the selected row and
* calls repaint.
*/
private MouseMotionListener mouseOverListener = new MouseMotionAdapter() {
private int currentRow;
@Override
public void mouseMoved(MouseEvent e) {
currentRow = tree.getClosestRowForLocation(e.getX(), e.getY());
if (currentRow != mouseOverRow) {
mouseOverRow = currentRow;
repaint();
}
}
};
/**
* Renderer the row that the mouse is over Yellow
*/
private DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded,
leaf, row, hasFocus);
if (row == mouseOverRow) {
setBackgroundNonSelectionColor(Color.YELLOW);
this.setBorder(new GradientTitleBorder("",
new Color(0x418EDC), new Color(0x6B91B8), Color.WHITE,
25));
} else {
setBackgroundNonSelectionColor(UIManager
.getColor("Tree.textBackground"));
this.setBorder(null);
}
return this;
}
};
/**
* Custom border class, paints a titled border using a gradient.
*/
public class GradientTitleBorder implements Border {
private String title;
private int titleHeight;
private Insets insets = new Insets(titleHeight, 0, 0, 0);
private Color primaryColor;
private Color secondaryColor;
private Color fontColor;
private Color shadowColor;
private int indent = 5;
private Font titleFont;
/**
* Constructtor that assumes a title height.
*
* @param title -
* string to display
* @param primaryColor -
* first color of gradient
* @param secondaryColor -
* second color of gradient (lower)
* @param fontColor -
* color for the font
*/
public GradientTitleBorder(String title, Color primaryColor,
Color secondaryColor, Color fontColor) {
this(title, primaryColor, secondaryColor, fontColor, 30);
}
/**
* Full option constructor
*
* @param title -
* string to display
* @param primaryColor -
* first color of gradient
* @param secondaryColor -
* second color of gradient (lower)
* @param fontColor -
* color for the font
* @param titleHeight -
* height of the title bar
*/
public GradientTitleBorder(String title, Color primaryColor,
Color secondaryColor, Color fontColor, int titleHeight) {
this.title = title;
this.titleHeight = titleHeight;
this.insets = new Insets(titleHeight, 2, 2, 2);
this.primaryColor = primaryColor;
this.shadowColor = primaryColor.darker();
this.secondaryColor = secondaryColor;
this.fontColor = fontColor;
this.titleFont = UIManager.getFont("TitledBorder.font").deriveFont(
Font.BOLD);
}
/**
* Creates a GradientTitleBorder with default values.
*
* @param title
*/
public GradientTitleBorder(String title) {
this(title, Color.BLACK, Color.GRAY, Color.WHITE, 30);
}
/**
*
*/
public Insets getBorderInsets(Component c) {
return insets;
}
/**
*
*/
public boolean isBorderOpaque() {
return false;
}
/**
* paint the border, being carefull to stay inside the insets.
*/
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(x, y, primaryColor, x, y
+ titleHeight, secondaryColor);
g2d.setPaint(gp);
g2d.fillRect(x, y, width, titleHeight);
g2d.setColor(shadowColor);
g2d.drawRect(x, y - 49, width - 1, titleHeight);
g2d.setFont(titleFont);
g2d.setColor(shadowColor);
int titleOffset = (titleHeight / 2) + (c.getFont().getSize() / 2)
- 1;
g2d.drawString(title, x + insets.left + indent + 1, y + titleOffset
+ 1);
g2d.setColor(fontColor);
g2d.drawString(title, x + insets.left + indent, y + titleOffset);
g2d.setColor(shadowColor);
g2d.drawRect(x, y - 1, width - 1, height);
}
}
/**
* Start the demo on the Event Dispatch Thread.
*
* @param args
* the command line arguments
*/
public static void main(String[] args) {
// turn bold fonts off in metal
UIManager.put("swing.boldMetal", Boolean.FALSE);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame demoFrame = new JFrame();
demoFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demoFrame.setContentPane(new NodeRolloverDemo());
demoFrame.pack();
demoFrame.setVisible(true);
}
});
}
/**
* Creates the demos tree model which contains java books.
*
* @return the demos tree model
*/
private DefaultTreeModel createModel() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Books");
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode book = null;
category = new DefaultMutableTreeNode("Books for Java Programmers");
root.add(category);
// original Tutorial
book = new DefaultMutableTreeNode(
"The Java Tutorial: A Short Course on the Basics");
category.add(book);
// Tutorial Continued
book = new DefaultMutableTreeNode(
"The Java Tutorial Continued: The Rest of the JDK");
category.add(book);
// JFC Swing Tutorial
book = new DefaultMutableTreeNode(
"The JFC Swing Tutorial: A Guide to Constructing GUIs");
category.add(book);
// Bloch
book = new DefaultMutableTreeNode(
"Effective Java Programming Language Guide");
category.add(book);
// Arnold/Gosling
book = new DefaultMutableTreeNode("The Java Programming Language");
category.add(book);
// Chan
book = new DefaultMutableTreeNode("The Java Developers Almanac");
category.add(book);
category = new DefaultMutableTreeNode("Books for Java Implementers");
root.add(category);
// VM
book = new DefaultMutableTreeNode(
"The Java Virtual Machine Specification");
category.add(book);
// Language Spec
book = new DefaultMutableTreeNode("The Java Language Specification");
category.add(book);
return new DefaultTreeModel(root);
}
}