Work tree rows by their whole line, and outline the hovered one
Swing hit-tests a tree row only as far as its label, so a click past the end of the name did nothing. Rows are now found by their vertical band alone, which covers selection, the context menus, double-click join and middle-click info; the expand handle to the left of a label still works the row without selecting it. The hovered row is outlined across that same full width, so what a click would act on is visible before making it. Spacers, which nothing can be done with, are skipped, and the outline gives way to the drag-and-drop indicator while a drag is in progress. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import javax.swing.plaf.basic.BasicTreeUI;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.List;
|
||||
@@ -159,6 +160,7 @@ public final class ServerTreePanel extends JScrollPane {
|
||||
tree.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
selectRowUnder(e);
|
||||
maybePopup(e);
|
||||
}
|
||||
|
||||
@@ -183,6 +185,21 @@ public final class ServerTreePanel extends JScrollPane {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the row a press landed on. A row acts on its whole line, but Swing's own
|
||||
* hit testing stops at the end of the label, so a press further right would leave
|
||||
* the selection where it was.
|
||||
*/
|
||||
private void selectRowUnder(MouseEvent e) {
|
||||
if (!SwingUtilities.isLeftMouseButton(e) && !e.isPopupTrigger()) return;
|
||||
TreePath path = tree.pathAt(e.getY());
|
||||
if (path == null || path.equals(tree.getSelectionPath())) return;
|
||||
Rectangle bounds = tree.getPathBounds(path);
|
||||
// Left of the label is the expand handle, which Swing works the row without selecting it.
|
||||
if (bounds != null && e.getX() < bounds.x) return;
|
||||
tree.setSelectionPath(path);
|
||||
}
|
||||
|
||||
public void setSelfClientId(int id) {
|
||||
this.selfClientId = id;
|
||||
}
|
||||
@@ -198,7 +215,7 @@ public final class ServerTreePanel extends JScrollPane {
|
||||
}
|
||||
|
||||
private Object nodeAt(MouseEvent e) {
|
||||
TreePath path = tree.getPathForLocation(e.getX(), e.getY());
|
||||
TreePath path = tree.pathAt(e.getY());
|
||||
if (path == null) return null;
|
||||
DefaultMutableTreeNode n = (DefaultMutableTreeNode) path.getLastPathComponent();
|
||||
return n.getUserObject();
|
||||
@@ -206,7 +223,7 @@ public final class ServerTreePanel extends JScrollPane {
|
||||
|
||||
private void maybePopup(MouseEvent e) {
|
||||
if (!e.isPopupTrigger()) return;
|
||||
TreePath path = tree.getPathForLocation(e.getX(), e.getY());
|
||||
TreePath path = tree.pathAt(e.getY());
|
||||
if (path == null) return;
|
||||
tree.setSelectionPath(path);
|
||||
Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject();
|
||||
|
||||
Reference in New Issue
Block a user