Browse Source

Paint lead selection of tree.

Respect expand controls when making row visible while navigating.
pull/198/head
weisj 4 years ago
parent
commit
fb0c82548c
  1. 4
      core/src/main/java/com/github/weisj/darklaf/graphics/PaintUtil.java
  2. 7
      core/src/main/java/com/github/weisj/darklaf/ui/cell/CellUtil.java
  3. 271
      core/src/main/java/com/github/weisj/darklaf/ui/tree/DarkTreeUI.java
  4. 1
      core/src/main/resources/com/github/weisj/darklaf/properties/ui/tree.properties

4
core/src/main/java/com/github/weisj/darklaf/graphics/PaintUtil.java

@ -243,6 +243,10 @@ public class PaintUtil {
g.fillRect(x, y + height - thickness, width, thickness);
}
public static void drawRect(final Graphics g, final Rectangle r, final Insets lineWidths) {
drawRect(g, r.x, r.y, r.width, r.height, lineWidths);
}
public static void drawRect(final Graphics g, final int x, final int y,
final int width, final int height, final Insets lineWidths) {
g.fillRect(x, y, width, lineWidths.top);

7
core/src/main/java/com/github/weisj/darklaf/ui/cell/CellUtil.java

@ -461,9 +461,10 @@ public class CellUtil {
return c;
}
protected static boolean hasFocus(final Component c, final Component comp) {
return comp.hasFocus()
|| (DarkUIUtil.hasFocus(c) || DarkUIUtil.getParentOfType(JPopupMenu.class, c, 4) != null);
protected static boolean hasFocus(final Component cellComponent, final Component parentComponent) {
return parentComponent.hasFocus()
|| (DarkUIUtil.hasFocus(cellComponent)
|| DarkUIUtil.getParentOfType(JPopupMenu.class, cellComponent, 4) != null);
}
public static void setSelectedFlag(final Component comp, final boolean selected) {

271
core/src/main/java/com/github/weisj/darklaf/ui/tree/DarkTreeUI.java

@ -36,6 +36,7 @@ import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.*;
import com.github.weisj.darklaf.graphics.PaintUtil;
import com.github.weisj.darklaf.ui.cell.CellConstants;
import com.github.weisj.darklaf.ui.cell.CellUtil;
import com.github.weisj.darklaf.ui.cell.DarkCellRendererPane;
@ -62,49 +63,7 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
public static final String KEY_IS_TREE_EDITOR = "JComponent.isTreeEditor";
public static final String KEY_IS_TREE_RENDERER = "JComponent.isTreeRenderer";
private final MouseListener selectionListener = new MouseAdapter() {
boolean handled = false;
@Override
public void mousePressed(final MouseEvent e) {
handled = false;
tree.repaint();
if (!isSelected(e)) {
handled = true;
handle(e);
}
}
@Override
public void mouseReleased(final MouseEvent e) {
if (!handled) {
handle(e);
}
}
private void handle(final MouseEvent e) {
final JTree tree = (JTree) e.getSource();
if (SwingUtilities.isLeftMouseButton(e) && !e.isPopupTrigger()) {
// if we can't stop any ongoing editing, do nothing
if (isEditing(tree) && tree.getInvokesStopCellEditing() && !stopEditing(tree)) {
return;
}
final TreePath pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY());
if (pressedPath != null) {
Rectangle bounds = getPathBounds(tree, pressedPath);
if (e.getY() >= bounds.y + bounds.height) {
return;
}
if (bounds.contains(e.getPoint()) || isLocationInExpandControl(pressedPath, e.getX(), e.getY())) {
return;
}
if (tree.getDragEnabled() || !startEditing(pressedPath, e)) {
selectPathForEvent(pressedPath, e);
}
}
}
}
};
protected MouseListener selectionListener;
protected Color lineColor;
protected Color focusSelectedLineColor;
protected Color selectedLineColor;
@ -116,6 +75,9 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
protected Icon collapsedSelected;
protected Icon collapsedFocus;
protected Icon collapsed;
protected Insets leadSelectionBorderInsets;
private boolean oldRepaintAllRowValue;
protected CellHintPopupListener<JTree, ?> popupListener;
@ -166,6 +128,8 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
collapsedSelected = UIManager.getIcon("Tree.collapsed.selected.unfocused.icon");
collapsedFocus = UIManager.getIcon("Tree.collapsed.unselected.focused.icon");
collapsed = UIManager.getIcon("Tree.collapsed.unselected.unfocused.icon");
leadSelectionBorderInsets = UIManager.getInsets("Tree.leadSelectionBorderInsets");
if (leadSelectionBorderInsets == null) leadSelectionBorderInsets = new Insets(1, 1, 1, 1);
PropertyUtil.installBooleanProperty(tree, KEY_RENDER_BOOLEAN_AS_CHECKBOX, "Tree.renderBooleanAsCheckBox");
PropertyUtil.installProperty(tree, KEY_BOOLEAN_RENDER_TYPE, UIManager.getString("Tree.booleanRenderType"));
PropertyUtil.installProperty(tree, KEY_LINE_STYLE, UIManager.getString("Tree.defaultLineStyle"));
@ -184,9 +148,14 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
popupListener.install();
}
tree.addPropertyChangeListener(this);
selectionListener = createMouseSelectionListener();
tree.addMouseListener(selectionListener);
}
protected MouseListener createMouseSelectionListener() {
return new DarkTreeMouseListener();
}
protected CellHintPopupListener<JTree, ?> createPopupMouseListener() {
return new CellHintPopupListener<>(new TreeCellContainer(tree, this));
}
@ -202,8 +171,8 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
final InputMap inputMap = tree.getInputMap(JComponent.WHEN_FOCUSED);
inputMap.put(KeyStroke.getKeyStroke("pressed LEFT"), "collapse_or_move_up");
inputMap.put(KeyStroke.getKeyStroke("pressed RIGHT"), "expand_or_move_down");
inputMap.put(KeyStroke.getKeyStroke("pressed DOWN"), "move_up");
inputMap.put(KeyStroke.getKeyStroke("pressed UP"), "move_down");
inputMap.put(KeyStroke.getKeyStroke("pressed DOWN"), "move_down");
inputMap.put(KeyStroke.getKeyStroke("pressed UP"), "move_up");
inputMap.put(KeyStroke.getKeyStroke("pressed ENTER"), "toggle_edit");
final ActionMap actionMap = tree.getActionMap();
@ -213,26 +182,17 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
actionMap.put("expand_or_move_down", new TreeUIAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final Object source = e.getSource();
if (source instanceof JTree) {
JTree tree = (JTree) source;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow != -1) {
TreePath selectionPath = tree.getPathForRow(selectionRow);
if (selectionPath != null) {
boolean leaf = tree.getModel().isLeaf(selectionPath.getLastPathComponent());
if (leaf || tree.isExpanded(selectionRow)) {
int newRow = Math.min(selectionRow + 1, tree.getRowCount() - 1);
tree.setSelectionRow(newRow);
tree.scrollRowToVisible(newRow);
tree.repaint();
return;
}
}
}
JTree tree = getTree(e);
if (tree == null) return;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
if (isLeaf(selectionRow) || tree.isExpanded(selectionRow)) {
moveTo(tree, selectionRow + 1);
} else {
expandAction.actionPerformed(e);
tree.repaint();
}
tree.repaint();
}
});
}
@ -240,83 +200,108 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
actionMap.put("collapse_or_move_up", new TreeUIAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final Object source = e.getSource();
if (source instanceof JTree) {
JTree tree = (JTree) source;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
final JTree tree = getTree(e);
if (tree == null) return;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
TreePath selectionPath = tree.getPathForRow(selectionRow);
if (selectionPath == null) return;
if (tree.getModel().isLeaf(selectionPath.getLastPathComponent())
|| tree.isCollapsed(selectionRow)) {
final TreePath parentPath = tree.getPathForRow(selectionRow).getParentPath();
if (parentPath != null) {
if (parentPath.getParentPath() != null || tree.isRootVisible()) {
final int parentRow = tree.getRowForPath(parentPath);
tree.scrollRowToVisible(parentRow);
tree.setSelectionRow(parentRow);
}
}
} else {
tree.collapseRow(selectionRow);
}
tree.repaint();
if (isLeaf(selectionRow) || tree.isCollapsed(selectionRow)) {
moveTo(tree, selectionRow - 1);
} else {
tree.collapseRow(selectionRow);
}
tree.repaint();
}
});
actionMap.put("move_up", new TreeUIAction() {
actionMap.put("move_down", new TreeUIAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final Object source = e.getSource();
if (source instanceof JTree) {
JTree tree = (JTree) source;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
int newRow = Math.min(selectionRow + 1, tree.getRowCount() - 1);
tree.setSelectionRow(newRow);
tree.scrollRowToVisible(newRow);
tree.repaint();
}
move(getTree(e), 1);
}
});
actionMap.put("move_down", new TreeUIAction() {
actionMap.put("move_up", new TreeUIAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final Object source = e.getSource();
if (source instanceof JTree) {
JTree tree = (JTree) source;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
int newRow = Math.max(selectionRow - 1, 0);
tree.setSelectionRow(newRow);
tree.scrollRowToVisible(newRow);
tree.repaint();
}
move(getTree(e), -1);
}
});
actionMap.put("toggle_edit", new TreeUIAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final Object source = e.getSource();
if (source instanceof JTree) {
JTree tree = (JTree) source;
if (tree.isEditing()) {
stopEditing(tree);
return;
}
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
startEditingAtPath(tree, getPathForRow(tree, selectionRow));
}
toggleEdit(getTree(e));
}
});
}
protected JTree getTree(final ActionEvent e) {
return DarkUIUtil.nullableCast(JTree.class, e.getSource());
}
protected void move(final JTree tree, final int offset) {
if (tree == null) return;
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
moveTo(tree, selectionRow + offset);
}
protected void moveTo(final JTree tree, final int row) {
int newRow = Math.max(Math.min(row, tree.getRowCount() - 1), 0);
tree.setSelectionRow(newRow);
scrollRowToVisible(tree, newRow);
tree.repaint();
}
protected void scrollRowToVisible(final JTree tree, final int row) {
Rectangle bounds = tree.getRowBounds(row);
if (!isLeaf(row)) {
boolean expanded = tree.isExpanded(row);
Icon icon = expanded ? getExpandedIcon() : getCollapsedIcon();
boolean ltr = tree.getComponentOrientation().isLeftToRight();
int ident = getRightChildIndent();
int extra = ident - 1 + icon.getIconWidth() / 2;
if (ltr) bounds.x -= extra;
bounds.width += extra;
}
tree.scrollRectToVisible(bounds);
}
protected void collapse(final JTree tree) {
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
TreePath selectionPath = tree.getPathForRow(selectionRow);
if (selectionPath == null) return;
if (tree.getModel().isLeaf(selectionPath.getLastPathComponent())
|| tree.isCollapsed(selectionRow)) {
final TreePath parentPath = tree.getPathForRow(selectionRow).getParentPath();
if (parentPath != null) {
if (parentPath.getParentPath() != null || tree.isRootVisible()) {
final int parentRow = tree.getRowForPath(parentPath);
scrollRowToVisible(tree, parentRow);
tree.setSelectionRow(parentRow);
}
}
} else {
tree.collapseRow(selectionRow);
}
tree.repaint();
}
protected void toggleEdit(final JTree tree) {
if (tree == null) return;
if (tree.isEditing()) {
stopEditing(tree);
return;
}
int selectionRow = tree.getLeadSelectionRow();
if (selectionRow == -1) return;
startEditingAtPath(tree, getPathForRow(tree, selectionRow));
}
@Override
protected FocusListener createFocusListener() {
return new FocusListener() {
@ -384,6 +369,7 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
popupListener = null;
}
tree.removeMouseListener(selectionListener);
selectionListener = null;
tree.removePropertyChangeListener(this);
}
@ -547,7 +533,10 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
rowGraphics.setColor(CellUtil.getTreeBackground(tree, selected, row));
rowGraphics.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
if (!selected && tree.getLeadSelectionRow() == row && tree.hasFocus()) {
rowGraphics.setColor(CellUtil.getTreeBackground(tree, true, row));
PaintUtil.drawRect(rowGraphics, bounds, leadSelectionBorderInsets);
}
rowGraphics.dispose();
}
}
@ -773,4 +762,48 @@ public class DarkTreeUI extends BasicTreeUI implements PropertyChangeListener, C
}
private abstract static class TreeUIAction extends AbstractAction implements UIResource {}
private class DarkTreeMouseListener extends MouseAdapter {
boolean handled = false;
@Override
public void mousePressed(final MouseEvent e) {
handled = false;
tree.repaint();
if (!isSelected(e)) {
handled = true;
handle(e);
}
}
@Override
public void mouseReleased(final MouseEvent e) {
if (!handled) {
handle(e);
}
}
private void handle(final MouseEvent e) {
final JTree tree = (JTree) e.getSource();
if (SwingUtilities.isLeftMouseButton(e) && !e.isPopupTrigger()) {
// if we can't stop any ongoing editing, do nothing
if (isEditing(tree) && tree.getInvokesStopCellEditing() && !stopEditing(tree)) {
return;
}
final TreePath pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY());
if (pressedPath != null) {
Rectangle bounds = getPathBounds(tree, pressedPath);
if (e.getY() >= bounds.y + bounds.height) {
return;
}
if (bounds.contains(e.getPoint()) || isLocationInExpandControl(pressedPath, e.getX(), e.getY())) {
return;
}
if (tree.getDragEnabled() || !startEditing(pressedPath, e)) {
selectPathForEvent(pressedPath, e);
}
}
}
}
}
}

1
core/src/main/resources/com/github/weisj/darklaf/properties/ui/tree.properties

@ -69,6 +69,7 @@ Tree.booleanRenderType = checkBox
Tree.defaultLineStyle = line
Tree.showFullRowInPopup = true
Tree.leadSelectionBorderInsets = 1,1,1,1
Tree.editorBorderInsets = 2,5,2,5
#Icons

Loading…
Cancel
Save