You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
822 lines
28 KiB
822 lines
28 KiB
/*
|
|
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
package javax.swing.plaf.synth;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Graphics;
|
|
import java.awt.Insets;
|
|
import java.awt.Rectangle;
|
|
import java.beans.PropertyChangeEvent;
|
|
import java.beans.PropertyChangeListener;
|
|
import java.util.Enumeration;
|
|
import javax.swing.DefaultCellEditor;
|
|
import javax.swing.Icon;
|
|
import javax.swing.JComponent;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.JTree;
|
|
import javax.swing.LookAndFeel;
|
|
import javax.swing.plaf.ComponentUI;
|
|
import javax.swing.plaf.UIResource;
|
|
import javax.swing.plaf.basic.BasicTreeUI;
|
|
import javax.swing.tree.DefaultTreeCellEditor;
|
|
import javax.swing.tree.DefaultTreeCellRenderer;
|
|
import javax.swing.tree.TreeCellEditor;
|
|
import javax.swing.tree.TreeCellRenderer;
|
|
import javax.swing.tree.TreeModel;
|
|
import javax.swing.tree.TreePath;
|
|
import sun.swing.plaf.synth.SynthIcon;
|
|
|
|
/**
|
|
* Provides the Synth L&F UI delegate for
|
|
* {@link javax.swing.JTree}.
|
|
*
|
|
* @author Scott Violet
|
|
* @since 1.7
|
|
*/
|
|
public class SynthTreeUI extends BasicTreeUI
|
|
implements PropertyChangeListener, SynthUI {
|
|
private SynthStyle style;
|
|
private SynthStyle cellStyle;
|
|
|
|
private SynthContext paintContext;
|
|
|
|
private boolean drawHorizontalLines;
|
|
private boolean drawVerticalLines;
|
|
|
|
private Object linesStyle;
|
|
|
|
private int padding;
|
|
|
|
private boolean useTreeColors;
|
|
|
|
private Icon expandedIconWrapper = new ExpandedIconWrapper();
|
|
|
|
/**
|
|
* Creates a new UI object for the given component.
|
|
*
|
|
* @param x component to create UI object for
|
|
* @return the UI object
|
|
*/
|
|
public static ComponentUI createUI(JComponent x) {
|
|
return new SynthTreeUI();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public Icon getExpandedIcon() {
|
|
return expandedIconWrapper;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void installDefaults() {
|
|
updateStyle(tree);
|
|
}
|
|
|
|
private void updateStyle(JTree tree) {
|
|
SynthContext context = getContext(tree, ENABLED);
|
|
SynthStyle oldStyle = style;
|
|
|
|
style = SynthLookAndFeel.updateStyle(context, this);
|
|
if (style != oldStyle) {
|
|
Object value;
|
|
|
|
setExpandedIcon(style.getIcon(context, "Tree.expandedIcon"));
|
|
setCollapsedIcon(style.getIcon(context, "Tree.collapsedIcon"));
|
|
|
|
setLeftChildIndent(style.getInt(context, "Tree.leftChildIndent",
|
|
0));
|
|
setRightChildIndent(style.getInt(context, "Tree.rightChildIndent",
|
|
0));
|
|
|
|
drawHorizontalLines = style.getBoolean(
|
|
context, "Tree.drawHorizontalLines",true);
|
|
drawVerticalLines = style.getBoolean(
|
|
context, "Tree.drawVerticalLines", true);
|
|
linesStyle = style.get(context, "Tree.linesStyle");
|
|
|
|
value = style.get(context, "Tree.rowHeight");
|
|
if (value != null) {
|
|
LookAndFeel.installProperty(tree, "rowHeight", value);
|
|
}
|
|
|
|
value = style.get(context, "Tree.scrollsOnExpand");
|
|
LookAndFeel.installProperty(tree, "scrollsOnExpand",
|
|
value != null? value : Boolean.TRUE);
|
|
|
|
padding = style.getInt(context, "Tree.padding", 0);
|
|
|
|
largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0);
|
|
|
|
useTreeColors = style.getBoolean(context,
|
|
"Tree.rendererUseTreeColors", true);
|
|
|
|
Boolean showsRootHandles = style.getBoolean(
|
|
context, "Tree.showsRootHandles", Boolean.TRUE);
|
|
LookAndFeel.installProperty(
|
|
tree, JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles);
|
|
|
|
if (oldStyle != null) {
|
|
uninstallKeyboardActions();
|
|
installKeyboardActions();
|
|
}
|
|
}
|
|
context.dispose();
|
|
|
|
context = getContext(tree, Region.TREE_CELL, ENABLED);
|
|
cellStyle = SynthLookAndFeel.updateStyle(context, this);
|
|
context.dispose();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void installListeners() {
|
|
super.installListeners();
|
|
tree.addPropertyChangeListener(this);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public SynthContext getContext(JComponent c) {
|
|
return getContext(c, SynthLookAndFeel.getComponentState(c));
|
|
}
|
|
|
|
private SynthContext getContext(JComponent c, int state) {
|
|
return SynthContext.getContext(c, style, state);
|
|
}
|
|
|
|
private SynthContext getContext(JComponent c, Region region) {
|
|
return getContext(c, region, getComponentState(c, region));
|
|
}
|
|
|
|
private SynthContext getContext(JComponent c, Region region, int state) {
|
|
return SynthContext.getContext(c, region, cellStyle, state);
|
|
}
|
|
|
|
private int getComponentState(JComponent c, Region region) {
|
|
// Always treat the cell as selected, will be adjusted appropriately
|
|
// when painted.
|
|
return ENABLED | SELECTED;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected TreeCellEditor createDefaultCellEditor() {
|
|
TreeCellRenderer renderer = tree.getCellRenderer();
|
|
DefaultTreeCellEditor editor;
|
|
|
|
if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) {
|
|
editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer)
|
|
renderer);
|
|
}
|
|
else {
|
|
editor = new SynthTreeCellEditor(tree, null);
|
|
}
|
|
return editor;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected TreeCellRenderer createDefaultCellRenderer() {
|
|
return new SynthTreeCellRenderer();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void uninstallDefaults() {
|
|
SynthContext context = getContext(tree, ENABLED);
|
|
|
|
style.uninstallDefaults(context);
|
|
context.dispose();
|
|
style = null;
|
|
|
|
context = getContext(tree, Region.TREE_CELL, ENABLED);
|
|
cellStyle.uninstallDefaults(context);
|
|
context.dispose();
|
|
cellStyle = null;
|
|
|
|
|
|
if (tree.getTransferHandler() instanceof UIResource) {
|
|
tree.setTransferHandler(null);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void uninstallListeners() {
|
|
super.uninstallListeners();
|
|
tree.removePropertyChangeListener(this);
|
|
}
|
|
|
|
/**
|
|
* Notifies this UI delegate to repaint the specified component.
|
|
* This method paints the component background, then calls
|
|
* the {@link #paint(SynthContext,Graphics)} method.
|
|
*
|
|
* <p>In general, this method does not need to be overridden by subclasses.
|
|
* All Look and Feel rendering code should reside in the {@code paint} method.
|
|
*
|
|
* @param g the {@code Graphics} object used for painting
|
|
* @param c the component being painted
|
|
* @see #paint(SynthContext,Graphics)
|
|
*/
|
|
@Override
|
|
public void update(Graphics g, JComponent c) {
|
|
SynthContext context = getContext(c);
|
|
|
|
SynthLookAndFeel.update(context, g);
|
|
context.getPainter().paintTreeBackground(context,
|
|
g, 0, 0, c.getWidth(), c.getHeight());
|
|
paint(context, g);
|
|
context.dispose();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public void paintBorder(SynthContext context, Graphics g, int x,
|
|
int y, int w, int h) {
|
|
context.getPainter().paintTreeBorder(context, g, x, y, w, h);
|
|
}
|
|
|
|
/**
|
|
* Paints the specified component according to the Look and Feel.
|
|
* <p>This method is not used by Synth Look and Feel.
|
|
* Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
|
|
*
|
|
* @param g the {@code Graphics} object used for painting
|
|
* @param c the component being painted
|
|
* @see #paint(SynthContext,Graphics)
|
|
*/
|
|
@Override
|
|
public void paint(Graphics g, JComponent c) {
|
|
SynthContext context = getContext(c);
|
|
|
|
paint(context, g);
|
|
context.dispose();
|
|
}
|
|
|
|
/**
|
|
* Paints the specified component.
|
|
*
|
|
* @param context context for the component being painted
|
|
* @param g the {@code Graphics} object used for painting
|
|
* @see #update(Graphics,JComponent)
|
|
*/
|
|
protected void paint(SynthContext context, Graphics g) {
|
|
paintContext = context;
|
|
|
|
updateLeadSelectionRow();
|
|
|
|
Rectangle paintBounds = g.getClipBounds();
|
|
Insets insets = tree.getInsets();
|
|
TreePath initialPath = getClosestPathForLocation(tree, 0,
|
|
paintBounds.y);
|
|
Enumeration paintingEnumerator = treeState.getVisiblePathsFrom
|
|
(initialPath);
|
|
int row = treeState.getRowForPath(initialPath);
|
|
int endY = paintBounds.y + paintBounds.height;
|
|
TreeModel treeModel = tree.getModel();
|
|
SynthContext cellContext = getContext(tree, Region.TREE_CELL);
|
|
|
|
drawingCache.clear();
|
|
|
|
setHashColor(context.getStyle().getColor(context,
|
|
ColorType.FOREGROUND));
|
|
|
|
if (paintingEnumerator != null) {
|
|
// First pass, draw the rows
|
|
|
|
boolean done = false;
|
|
boolean isExpanded;
|
|
boolean hasBeenExpanded;
|
|
boolean isLeaf;
|
|
Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0);
|
|
Rectangle bounds;
|
|
TreePath path;
|
|
TreeCellRenderer renderer = tree.getCellRenderer();
|
|
DefaultTreeCellRenderer dtcr = (renderer instanceof
|
|
DefaultTreeCellRenderer) ? (DefaultTreeCellRenderer)
|
|
renderer : null;
|
|
|
|
configureRenderer(cellContext);
|
|
while (!done && paintingEnumerator.hasMoreElements()) {
|
|
path = (TreePath)paintingEnumerator.nextElement();
|
|
bounds = getPathBounds(tree, path);
|
|
if ((path != null) && (bounds != null)) {
|
|
isLeaf = treeModel.isLeaf(path.getLastPathComponent());
|
|
if (isLeaf) {
|
|
isExpanded = hasBeenExpanded = false;
|
|
}
|
|
else {
|
|
isExpanded = treeState.getExpandedState(path);
|
|
hasBeenExpanded = tree.hasBeenExpanded(path);
|
|
}
|
|
rowBounds.y = bounds.y;
|
|
rowBounds.height = bounds.height;
|
|
paintRow(renderer, dtcr, context, cellContext, g,
|
|
paintBounds, insets, bounds, rowBounds, path,
|
|
row, isExpanded, hasBeenExpanded, isLeaf);
|
|
if ((bounds.y + bounds.height) >= endY) {
|
|
done = true;
|
|
}
|
|
}
|
|
else {
|
|
done = true;
|
|
}
|
|
row++;
|
|
}
|
|
|
|
// Draw the connecting lines and controls.
|
|
// Find each parent and have them draw a line to their last child
|
|
boolean rootVisible = tree.isRootVisible();
|
|
TreePath parentPath = initialPath;
|
|
parentPath = parentPath.getParentPath();
|
|
while (parentPath != null) {
|
|
paintVerticalPartOfLeg(g, paintBounds, insets, parentPath);
|
|
drawingCache.put(parentPath, Boolean.TRUE);
|
|
parentPath = parentPath.getParentPath();
|
|
}
|
|
done = false;
|
|
paintingEnumerator = treeState.getVisiblePathsFrom(initialPath);
|
|
while (!done && paintingEnumerator.hasMoreElements()) {
|
|
path = (TreePath)paintingEnumerator.nextElement();
|
|
bounds = getPathBounds(tree, path);
|
|
if ((path != null) && (bounds != null)) {
|
|
isLeaf = treeModel.isLeaf(path.getLastPathComponent());
|
|
if (isLeaf) {
|
|
isExpanded = hasBeenExpanded = false;
|
|
}
|
|
else {
|
|
isExpanded = treeState.getExpandedState(path);
|
|
hasBeenExpanded = tree.hasBeenExpanded(path);
|
|
}
|
|
// See if the vertical line to the parent has been drawn.
|
|
parentPath = path.getParentPath();
|
|
if (parentPath != null) {
|
|
if (drawingCache.get(parentPath) == null) {
|
|
paintVerticalPartOfLeg(g, paintBounds, insets,
|
|
parentPath);
|
|
drawingCache.put(parentPath, Boolean.TRUE);
|
|
}
|
|
paintHorizontalPartOfLeg(g,
|
|
paintBounds, insets, bounds,
|
|
path, row, isExpanded,
|
|
hasBeenExpanded, isLeaf);
|
|
}
|
|
else if (rootVisible && row == 0) {
|
|
paintHorizontalPartOfLeg(g,
|
|
paintBounds, insets, bounds,
|
|
path, row, isExpanded,
|
|
hasBeenExpanded, isLeaf);
|
|
}
|
|
if (shouldPaintExpandControl(path, row, isExpanded,
|
|
hasBeenExpanded, isLeaf)) {
|
|
paintExpandControl(g, paintBounds,
|
|
insets, bounds, path, row,
|
|
isExpanded, hasBeenExpanded,isLeaf);
|
|
}
|
|
if ((bounds.y + bounds.height) >= endY) {
|
|
done = true;
|
|
}
|
|
}
|
|
else {
|
|
done = true;
|
|
}
|
|
row++;
|
|
}
|
|
}
|
|
cellContext.dispose();
|
|
|
|
paintDropLine(g);
|
|
|
|
// Empty out the renderer pane, allowing renderers to be gc'ed.
|
|
rendererPane.removeAll();
|
|
|
|
paintContext = null;
|
|
}
|
|
|
|
private void configureRenderer(SynthContext context) {
|
|
TreeCellRenderer renderer = tree.getCellRenderer();
|
|
|
|
if (renderer instanceof DefaultTreeCellRenderer) {
|
|
DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer;
|
|
SynthStyle style = context.getStyle();
|
|
|
|
context.setComponentState(ENABLED | SELECTED);
|
|
Color color = r.getTextSelectionColor();
|
|
if (color == null || (color instanceof UIResource)) {
|
|
r.setTextSelectionColor(style.getColor(
|
|
context, ColorType.TEXT_FOREGROUND));
|
|
}
|
|
color = r.getBackgroundSelectionColor();
|
|
if (color == null || (color instanceof UIResource)) {
|
|
r.setBackgroundSelectionColor(style.getColor(
|
|
context, ColorType.TEXT_BACKGROUND));
|
|
}
|
|
|
|
context.setComponentState(ENABLED);
|
|
color = r.getTextNonSelectionColor();
|
|
if (color == null || color instanceof UIResource) {
|
|
r.setTextNonSelectionColor(style.getColorForState(
|
|
context, ColorType.TEXT_FOREGROUND));
|
|
}
|
|
color = r.getBackgroundNonSelectionColor();
|
|
if (color == null || color instanceof UIResource) {
|
|
r.setBackgroundNonSelectionColor(style.getColorForState(
|
|
context, ColorType.TEXT_BACKGROUND));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
|
|
Insets insets, Rectangle bounds,
|
|
TreePath path, int row,
|
|
boolean isExpanded,
|
|
boolean hasBeenExpanded, boolean
|
|
isLeaf) {
|
|
if (drawHorizontalLines) {
|
|
super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds,
|
|
path, row, isExpanded,
|
|
hasBeenExpanded, isLeaf);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintHorizontalLine(Graphics g, JComponent c, int y,
|
|
int left, int right) {
|
|
paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
|
|
paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintVerticalPartOfLeg(Graphics g,
|
|
Rectangle clipBounds, Insets insets,
|
|
TreePath path) {
|
|
if (drawVerticalLines) {
|
|
super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
|
|
int bottom) {
|
|
paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
|
|
paintContext, "Tree.verticalLine", g, x, top, x, bottom, linesStyle);
|
|
}
|
|
|
|
private void paintRow(TreeCellRenderer renderer,
|
|
DefaultTreeCellRenderer dtcr, SynthContext treeContext,
|
|
SynthContext cellContext, Graphics g, Rectangle clipBounds,
|
|
Insets insets, Rectangle bounds, Rectangle rowBounds,
|
|
TreePath path, int row, boolean isExpanded,
|
|
boolean hasBeenExpanded, boolean isLeaf) {
|
|
// Don't paint the renderer if editing this row.
|
|
boolean selected = tree.isRowSelected(row);
|
|
|
|
JTree.DropLocation dropLocation = tree.getDropLocation();
|
|
boolean isDrop = dropLocation != null
|
|
&& dropLocation.getChildIndex() == -1
|
|
&& path == dropLocation.getPath();
|
|
|
|
int state = ENABLED;
|
|
if (selected || isDrop) {
|
|
state |= SELECTED;
|
|
}
|
|
|
|
if (tree.isFocusOwner() && row == getLeadSelectionRow()) {
|
|
state |= FOCUSED;
|
|
}
|
|
|
|
cellContext.setComponentState(state);
|
|
|
|
if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof
|
|
UIResource)) {
|
|
dtcr.setBorderSelectionColor(style.getColor(
|
|
cellContext, ColorType.FOCUS));
|
|
}
|
|
SynthLookAndFeel.updateSubregion(cellContext, g, rowBounds);
|
|
cellContext.getPainter().paintTreeCellBackground(cellContext, g,
|
|
rowBounds.x, rowBounds.y, rowBounds.width,
|
|
rowBounds.height);
|
|
cellContext.getPainter().paintTreeCellBorder(cellContext, g,
|
|
rowBounds.x, rowBounds.y, rowBounds.width,
|
|
rowBounds.height);
|
|
if (editingComponent != null && editingRow == row) {
|
|
return;
|
|
}
|
|
|
|
int leadIndex;
|
|
|
|
if (tree.hasFocus()) {
|
|
leadIndex = getLeadSelectionRow();
|
|
}
|
|
else {
|
|
leadIndex = -1;
|
|
}
|
|
|
|
Component component = renderer.getTreeCellRendererComponent(
|
|
tree, path.getLastPathComponent(),
|
|
selected, isExpanded, isLeaf, row,
|
|
(leadIndex == row));
|
|
|
|
rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y,
|
|
bounds.width, bounds.height, true);
|
|
}
|
|
|
|
private int findCenteredX(int x, int iconWidth) {
|
|
return tree.getComponentOrientation().isLeftToRight()
|
|
? x - (int)Math.ceil(iconWidth / 2.0)
|
|
: x - (int)Math.floor(iconWidth / 2.0);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintExpandControl(Graphics g, Rectangle clipBounds,
|
|
Insets insets, Rectangle bounds, TreePath path, int row,
|
|
boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
|
|
//modify the paintContext's state to match the state for the row
|
|
//this is a hack in that it requires knowledge of the subsequent
|
|
//method calls. The point is, the context used in drawCentered
|
|
//should reflect the state of the row, not of the tree.
|
|
boolean isSelected = tree.getSelectionModel().isPathSelected(path);
|
|
int state = paintContext.getComponentState();
|
|
if (isSelected) {
|
|
paintContext.setComponentState(state | SynthConstants.SELECTED);
|
|
}
|
|
super.paintExpandControl(g, clipBounds, insets, bounds, path, row,
|
|
isExpanded, hasBeenExpanded, isLeaf);
|
|
paintContext.setComponentState(state);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void drawCentered(Component c, Graphics graphics, Icon icon,
|
|
int x, int y) {
|
|
int w = SynthIcon.getIconWidth(icon, paintContext);
|
|
int h = SynthIcon.getIconHeight(icon, paintContext);
|
|
|
|
SynthIcon.paintIcon(icon, paintContext, graphics,
|
|
findCenteredX(x, w),
|
|
y - h/2, w, h);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public void propertyChange(PropertyChangeEvent event) {
|
|
if (SynthLookAndFeel.shouldUpdateStyle(event)) {
|
|
updateStyle((JTree)event.getSource());
|
|
}
|
|
|
|
if ("dropLocation" == event.getPropertyName()) {
|
|
JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue();
|
|
repaintDropLocation(oldValue);
|
|
repaintDropLocation(tree.getDropLocation());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected void paintDropLine(Graphics g) {
|
|
JTree.DropLocation loc = tree.getDropLocation();
|
|
if (!isDropLine(loc)) {
|
|
return;
|
|
}
|
|
|
|
Color c = (Color)style.get(paintContext, "Tree.dropLineColor");
|
|
if (c != null) {
|
|
g.setColor(c);
|
|
Rectangle rect = getDropLineRect(loc);
|
|
g.fillRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
}
|
|
|
|
private void repaintDropLocation(JTree.DropLocation loc) {
|
|
if (loc == null) {
|
|
return;
|
|
}
|
|
|
|
Rectangle r;
|
|
|
|
if (isDropLine(loc)) {
|
|
r = getDropLineRect(loc);
|
|
} else {
|
|
r = tree.getPathBounds(loc.getPath());
|
|
if (r != null) {
|
|
r.x = 0;
|
|
r.width = tree.getWidth();
|
|
}
|
|
}
|
|
|
|
if (r != null) {
|
|
tree.repaint(r);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected int getRowX(int row, int depth) {
|
|
return super.getRowX(row, depth) + padding;
|
|
}
|
|
|
|
|
|
private class SynthTreeCellRenderer extends DefaultTreeCellRenderer
|
|
implements UIResource {
|
|
SynthTreeCellRenderer() {
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "Tree.cellRenderer";
|
|
}
|
|
|
|
@Override
|
|
public Component getTreeCellRendererComponent(JTree tree, Object value,
|
|
boolean sel,
|
|
boolean expanded,
|
|
boolean leaf, int row,
|
|
boolean hasFocus) {
|
|
if (!useTreeColors && (sel || hasFocus)) {
|
|
SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel.
|
|
getUIOfType(getUI(), SynthLabelUI.class),
|
|
sel, hasFocus, tree.isEnabled(), false);
|
|
}
|
|
else {
|
|
SynthLookAndFeel.resetSelectedUI();
|
|
}
|
|
return super.getTreeCellRendererComponent(tree, value, sel,
|
|
expanded, leaf, row, hasFocus);
|
|
}
|
|
|
|
@Override
|
|
public void paint(Graphics g) {
|
|
paintComponent(g);
|
|
if (hasFocus) {
|
|
SynthContext context = getContext(tree, Region.TREE_CELL);
|
|
|
|
if (context.getStyle() == null) {
|
|
assert false: "SynthTreeCellRenderer is being used " +
|
|
"outside of UI that created it";
|
|
return;
|
|
}
|
|
int imageOffset = 0;
|
|
Icon currentI = getIcon();
|
|
|
|
if(currentI != null && getText() != null) {
|
|
imageOffset = currentI.getIconWidth() +
|
|
Math.max(0, getIconTextGap() - 1);
|
|
}
|
|
if (selected) {
|
|
context.setComponentState(ENABLED | SELECTED);
|
|
}
|
|
else {
|
|
context.setComponentState(ENABLED);
|
|
}
|
|
if(getComponentOrientation().isLeftToRight()) {
|
|
context.getPainter().paintTreeCellFocus(context, g,
|
|
imageOffset, 0, getWidth() - imageOffset,
|
|
getHeight());
|
|
}
|
|
else {
|
|
context.getPainter().paintTreeCellFocus(context, g,
|
|
0, 0, getWidth() - imageOffset, getHeight());
|
|
}
|
|
context.dispose();
|
|
}
|
|
SynthLookAndFeel.resetSelectedUI();
|
|
}
|
|
}
|
|
|
|
|
|
private static class SynthTreeCellEditor extends DefaultTreeCellEditor {
|
|
public SynthTreeCellEditor(JTree tree,
|
|
DefaultTreeCellRenderer renderer) {
|
|
super(tree, renderer);
|
|
setBorderSelectionColor(null);
|
|
}
|
|
|
|
@Override
|
|
protected TreeCellEditor createTreeCellEditor() {
|
|
JTextField tf = new JTextField() {
|
|
@Override
|
|
public String getName() {
|
|
return "Tree.cellEditor";
|
|
}
|
|
};
|
|
DefaultCellEditor editor = new DefaultCellEditor(tf);
|
|
|
|
// One click to edit.
|
|
editor.setClickCountToStart(1);
|
|
return editor;
|
|
}
|
|
}
|
|
|
|
//
|
|
// BasicTreeUI directly uses expandIcon outside of the Synth methods.
|
|
// To get the correct context we return an instance of this that fetches
|
|
// the SynthContext as needed.
|
|
//
|
|
private class ExpandedIconWrapper extends SynthIcon {
|
|
public void paintIcon(SynthContext context, Graphics g, int x,
|
|
int y, int w, int h) {
|
|
if (context == null) {
|
|
context = getContext(tree);
|
|
SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
|
|
context.dispose();
|
|
}
|
|
else {
|
|
SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h);
|
|
}
|
|
}
|
|
|
|
public int getIconWidth(SynthContext context) {
|
|
int width;
|
|
if (context == null) {
|
|
context = getContext(tree);
|
|
width = SynthIcon.getIconWidth(expandedIcon, context);
|
|
context.dispose();
|
|
}
|
|
else {
|
|
width = SynthIcon.getIconWidth(expandedIcon, context);
|
|
}
|
|
return width;
|
|
}
|
|
|
|
public int getIconHeight(SynthContext context) {
|
|
int height;
|
|
if (context == null) {
|
|
context = getContext(tree);
|
|
height = SynthIcon.getIconHeight(expandedIcon, context);
|
|
context.dispose();
|
|
}
|
|
else {
|
|
height = SynthIcon.getIconHeight(expandedIcon, context);
|
|
}
|
|
return height;
|
|
}
|
|
}
|
|
}
|