Limit the area where JTableHeader
column reordering drags can be initiated to the top half of the TableColumn
and perform mouse cursor changes and draw drag handle icons on the JLayer
.
Code
class ColumnDragLayerUI extends LayerUI<JScrollPane> {
private final Rectangle draggableRect = new Rectangle();
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
if (!draggableRect.isEmpty()) {
Graphics2D g2 = (Graphics2D) g.create();
// g2.fill(draggableRect);
Icon icon = new DragAreaIcon();
int x = (int) (draggableRect.getCenterX() - icon.getIconWidth() / 2d);
int y = draggableRect.y + 1;
icon.paintIcon(c, g2, x, y);
g2.dispose();
}
}
@Override protected void processMouseEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
super.processMouseEvent(e, l);
Component c = e.getComponent();
if (c instanceof JTableHeader) {
JTableHeader header = (JTableHeader) c;
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
Point pt = e.getPoint();
updateIconAndCursor(header, pt, l);
} else if (e.getID() == MouseEvent.MOUSE_RELEASED) {
header.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
draggableRect.setSize(0, 0);
}
}
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
Component c = e.getComponent();
if (c instanceof JTableHeader) {
JTableHeader header = (JTableHeader) c;
if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
TableColumn draggedColumn = header.getDraggedColumn();
if (!draggableRect.isEmpty() && draggedColumn != null) {
EventQueue.invokeLater(() -> {
int modelIndex = draggedColumn.getModelIndex();
int viewIndex = header.getTable().convertColumnIndexToView(modelIndex);
Rectangle rect = header.getHeaderRect(viewIndex);
rect.x += header.getDraggedDistance();
draggableRect.setRect(SwingUtilities.convertRectangle(header, rect, l));
header.repaint(rect);
});
} else {
e.consume(); // Refuse to start drag
}
} else if (e.getID() == MouseEvent.MOUSE_MOVED) {
Point pt = e.getPoint();
updateIconAndCursor(header, pt, l);
header.repaint();
}
} else {
c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
draggableRect.setSize(0, 0);
}
}
private void updateIconAndCursor(JTableHeader header, Point pt, JLayer<?> l) {
Rectangle r = header.getHeaderRect(header.columnAtPoint(pt));
r.height /= 2;
if (r.contains(pt)) {
header.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
draggableRect.setRect(SwingUtilities.convertRectangle(header, r, l));
} else {
header.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
draggableRect.setSize(0, 0);
}
}
}
No comments:
Post a Comment