Code
class ColumnInsertLayerUI extends LayerUI<JScrollPane> {
private static final Color LINE_COLOR = new Color(0x00_78_D7);
private static final int LINE_WIDTH = 4;
private final Rectangle2D line = new Rectangle2D.Double();
private final Ellipse2D plus = new Ellipse2D.Double(0d, 0d, 10d, 10d);
@Override public void paint(Graphics g, JComponent c) {
super.paint(g, c);
if (c instanceof JLayer && !line.isEmpty()) {
JScrollPane scroll = (JScrollPane) ((JLayer<?>) c).getView();
JTableHeader header =
((JTable) scroll.getViewport().getView()).getTableHeader();
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Point pt0 = line.getBounds().getLocation();
Point pt1 = SwingUtilities.convertPoint(header, pt0, c);
g2.translate(pt1.getX() - pt0.getX(), pt1.getY() - pt0.getY());
// paint Insert Line
g2.setPaint(LINE_COLOR);
g2.fill(line);
// paint Plus Icon
g2.setPaint(Color.WHITE);
g2.fill(plus);
g2.setPaint(LINE_COLOR);
double cx = plus.getCenterX();
double cy = plus.getCenterY();
double w2 = plus.getWidth() / 2d;
double h2 = plus.getHeight() / 2d;
g2.draw(new Line2D.Double(cx - w2, cy, cx + w2, cy));
g2.draw(new Line2D.Double(cx, cy - h2, cx, cy + h2));
g2.draw(plus);
g2.dispose();
}
}
private void updateLineLocation(JScrollPane scroll, Point loc) {
JTable table = (JTable) scroll.getViewport().getView();
JTableHeader header = table.getTableHeader();
Rectangle rect = scroll.getVisibleRect();
JScrollBar bar = scroll.getHorizontalScrollBar();
int scrollHeight = bar.isVisible() ? bar.getHeight() : 0;
Dimension d = new Dimension(
LINE_WIDTH, rect.height - scrollHeight);
for (int i = 0; i < table.getColumnCount(); i++) {
if (canInsert(header, loc, i, d)) {
return;
}
}
}
private boolean canInsert(
JTableHeader header, Point loc, int i, Dimension d) {
Rectangle r = header.getHeaderRect(i);
Rectangle r1 = getWestRect(r, i);
Rectangle r2 = getEastRect(r);
boolean hit = false;
if (r1.contains(loc)) {
updateInsertLineLocation(r1, loc, d, header);
hit = true;
} else if (r2.contains(loc)) {
updateInsertLineLocation(r2, loc, d, header);
hit = true;
} else if (r.contains(loc)) {
line.setFrame(0d, 0d, 0d, 0d);
header.setCursor(Cursor.getDefaultCursor());
hit = true;
}
return hit;
}
private Rectangle getWestRect(Rectangle r, int i) {
Rectangle rect = r.getBounds();
Rectangle bounds = plus.getBounds();
if (i != 0) {
rect.x -= bounds.width / 2;
}
rect.setSize(bounds.getSize());
return rect;
}
private Rectangle getEastRect(Rectangle r) {
Rectangle rect = r.getBounds();
Rectangle bounds = plus.getBounds();
rect.x += rect.width - bounds.width / 2;
rect.setSize(bounds.getSize());
return rect;
}
private void updateInsertLineLocation(
Rectangle r, Point loc, Dimension d, Component c) {
if (r.contains(loc)) {
double cx = r.getCenterX();
double cy = r.getCenterY();
line.setFrame(
cx - d.getWidth() / 2d, r.getY(), d.width, d.height);
double pw = plus.getWidth() / 2d;
double ph = plus.getHeight() / 2d;
plus.setFrameFromCenter(cx, cy, cx - pw, cy - ph);
c.setCursor(Cursor.getDefaultCursor());
} else {
line.setFrame(0d, 0d, 0d, 0d);
c.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
}
}
@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 protected void processMouseEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
super.processMouseEvent(e, l);
if (e.getID() == MouseEvent.MOUSE_CLICKED) {
JScrollPane scroll = l.getView();
Point pt = e.getPoint();
if (plus.contains(pt) && !line.isEmpty()) {
JTable table = (JTable) scroll.getViewport().getView();
TableModel model = table.getModel();
int columnCount = table.getColumnCount();
int maxColumn = model.getColumnCount();
if (columnCount < maxColumn) {
int idx = table.columnAtPoint(
line.getBounds().getLocation());
TableColumn column = new TableColumn(columnCount);
column.setHeaderValue("Column" + columnCount);
table.addColumn(column);
table.moveColumn(columnCount, idx + 1);
updateLineLocation(scroll, pt);
}
}
l.repaint(scroll.getBounds());
}
}
@Override protected void processMouseMotionEvent(
MouseEvent e, JLayer<? extends JScrollPane> l) {
super.processMouseMotionEvent(e, l);
Component c = e.getComponent();
int id = e.getID();
JScrollPane scroll = l.getView();
if (id == MouseEvent.MOUSE_MOVED && c instanceof JTableHeader) {
updateLineLocation(scroll, e.getPoint());
} else {
line.setFrame(0d, 0d, 0d, 0d);
}
l.repaint(scroll.getBounds());
}
}
References
Thanks for sharing valuable information
ReplyDeleteGuidewire training In Hyderabad
Great tutorial! The explanation is clear and practical, especially for developers working with Java Swing tables. Thanks for sharing this useful tip!
ReplyDeleteAzure Data Engineer Training in Hyderabad