Skip to content

Commit cf2f895

Browse files
hansonrhansonr
authored andcommitted
JSTableUI fix for removed rows or columns
1 parent 781ee58 commit cf2f895

File tree

4 files changed

+108
-44
lines changed

4 files changed

+108
-44
lines changed

sources/net.sf.j2s.java.core/src/javax/swing/CellRendererPane.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public void paintComponent(Graphics g, Component c, Container p, int x, int y, i
175175
if (p instanceof JTable)
176176
DOMNode.setTopLeftAbsolute(ui.domNode, ((JTable) p).getRowMargin() / 2, ((JTable) p).getColumnModel().getColumnMargin() / 2);
177177
if (c instanceof JLabel)
178-
DOMNode.setStyles(ui.domNode, "overflow", "hidden");
178+
DOMNode.setStyle(ui.domNode, "overflow", "hidden");
179179
// if (!ui.doPaintBackground())
180180
// return;
181181
// ui.setTainted(false);

sources/net.sf.j2s.java.core/src/swingjs/plaf/CellHolder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
public abstract class CellHolder {
1717

1818
static String getRowColumnID(JSComponentUI holder, int row, int col) {
19-
return holder.id + "_tab" + (row >= 0 ? "_row" + row : "") + "_col" + col;
19+
return holder.id + "_tab" + (row >= 0 ? "_row" + row : "") + (col >= 0 ? "_col" + col : "");
2020
}
2121

2222
static DOMNode createCellOuterNode(JSComponentUI tableOrHeader, int row, int col) {

sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTableHeaderUI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ protected void addChildrenToDOM(Component[] children, int n) {
168168
if (headdiv != null)
169169
DOMNode.dispose(headdiv);
170170
headdiv = DOMNode.createElement("div", rid);
171-
DOMNode.setStyles(headdiv, "height", thh + "px");
171+
DOMNode.setStyle(headdiv, "height", thh + "px");
172172
domNode.appendChild(headdiv);
173173
for (int col = 0, tx = 0; col < ncols; col++) {
174174
DOMNode td = CellHolder.createCellOuterNode(this, -1, col);

sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTableUI.java

Lines changed: 105 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.awt.event.MouseEvent;
5050
import java.beans.PropertyChangeEvent;
5151
import java.beans.PropertyChangeListener;
52+
import java.util.BitSet;
5253
import java.util.Enumeration;
5354

5455
import javax.swing.Action;
@@ -107,7 +108,7 @@ public class JSTableUI extends JSPanelUI {
107108
private int oldWidth;
108109
private int oldHeight;
109110
private Object oldFont;
110-
111+
111112
private boolean isScrolling, justLaidOut;
112113

113114
public void setScrolling() {
@@ -134,7 +135,7 @@ public DOMNode updateDOMNode() {
134135
if (domNode == null) {
135136
domNode = newDOMObject("div", id);
136137
enableJSKeys(true);
137-
DOMNode.setStyles(domNode, "outline", "none");
138+
DOMNode.setStyle(domNode, "outline", "none");
138139
// bindJSKeyEvents(domNode, true);
139140
}
140141
if (rebuild) {
@@ -319,7 +320,7 @@ protected void addChildrenToDOM(Component[] children, int n) {
319320
havePainted = false;
320321
int ncols = table.getColumnCount();
321322
int rowCount = table.getRowCount();
322-
int[] cw = getColumnWidths();
323+
getColumnWidths(true);
323324
int rminy, rmaxy, rminx, rmaxx;
324325
table.computeVisibleRect(tmpRect);
325326
rminx = tmpRect.x;
@@ -340,24 +341,37 @@ protected void addChildrenToDOM(Component[] children, int n) {
340341
rmaxy = tmpRect.y + tmpRect.height;
341342
if (tmpRect.height != 0) {
342343
currentRowMin = 0;
343-
addElements(rminx, rminy, rmaxx, rmaxy, cw, h, 0, rowCount, 0, ncols);
344+
addElements(rminx, rminy, rmaxx, rmaxy, h, 0, rowCount, 0, ncols);
344345
}
345346
}
346347
}
347348

348349
private void setHidden(boolean b) {
349-
DOMNode.setStyles(domNode, "visibility", b ? "hidden" : "visible");
350+
DOMNode.setStyle(domNode, "visibility", b ? "hidden" : "visible");
350351
}
351352

352353
private int[] cw = new int[10];
353-
354-
private int[] getColumnWidths() {
354+
private int[] cwOld = new int[10];
355+
356+
private void getColumnWidths(boolean isNew) {
355357
int ncols = table.getColumnCount();
356-
if (ncols > cw.length)
358+
if (ncols > cw.length) {
357359
cw = new int[ncols];
358-
for (int col = 0; col < ncols; col++)
359-
cw[col] = table.getColumnModel().getColumn(col).getWidth();
360-
return cw;
360+
cwOld = new int[ncols];
361+
}
362+
if (isNew)
363+
bsRowTainted.clear();
364+
boolean colTainted = false;
365+
TableColumnModel cm = table.getColumnModel();
366+
for (int col = 0; col < ncols; col++) {
367+
int w = cw[col] = cm.getColumn(col).getWidth();
368+
if (!isNew && cwOld[col] != w) {
369+
colTainted = true;
370+
}
371+
cwOld[col] = w;
372+
}
373+
if (colTainted)
374+
bsRowTainted.set(0, table.getRowCount());
361375
}
362376

363377
/**
@@ -375,7 +389,7 @@ private int[] getColumnWidths() {
375389
* @param col1
376390
* @param col2
377391
*/
378-
private DOMNode addElements(int rminx, int rminy, int rmaxx, int rmaxy, int[] cw, int h, int row1, int row2,
392+
private DOMNode addElements(int rminx, int rminy, int rmaxx, int rmaxy, int h, int row1, int row2,
379393
int col1, int col2) {
380394
int col, tx0;
381395
for (col = 0, tx0 = 0; col < col1; tx0 += cw[col++]) {
@@ -385,13 +399,15 @@ private DOMNode addElements(int rminx, int rminy, int rmaxx, int rmaxy, int[] cw
385399
if (ty + h < rminy)
386400
continue;
387401
String rid = id + "_tab_row" + row;
402+
// Note that rows will end up in unpredictable order, but that does not matter.
403+
// All that matters is that they have the right y and height value.
388404
DOMNode tr = DOMNode.getElement(rid);
389405
boolean rowExists = (tr != null);
390406
if (!rowExists) {
391407
tr = DOMNode.createElement("div", rid);
392408
domNode.appendChild(tr);
393409
}
394-
DOMNode.setStyles(tr, "height", h + "px");
410+
DOMNode.setStyle(tr, "height", h + "px");
395411
col = col1;
396412
for (int w, tx = tx0; col < col2 && tx < rmaxx; col++, tx += w) {
397413
w = cw[col];
@@ -402,7 +418,7 @@ private DOMNode addElements(int rminx, int rminy, int rmaxx, int rmaxy, int[] cw
402418
td = CellHolder.createCellOuterNode(this, row, col);
403419
tr.appendChild(td);
404420
}
405-
DOMNode.setStyles(td, "width", w + "px", "height", h + "px", "left", tx + "px", "top", ty + "px");
421+
DOMNode.setStyles(td, "left", tx + "px", "width", w + "px", "height", "inherit", "top", ty + "px");
406422
updateCellNode(td, row, col, w, h);
407423
if (rminx < 0)
408424
return td;
@@ -2114,15 +2130,18 @@ public void paint(Graphics g, JComponent c) {
21142130
// or from JComponent.paintComponent (initially, or from resize, for instance)
21152131

21162132
//table.getFillsViewportHeight();
2117-
Rectangle clip = getClip();
21182133
int rc = table.getRowCount();
2134+
int cc = table.getColumnCount();
2135+
checkRemoveCells(rc, cc);
2136+
// 2020.08.04 g.getClipBounds works now, no need for the hack.
2137+
Rectangle clip = g.getClipBounds(myClip);
21192138
int rh = table.getRowHeight();
21202139
if (getScrollPane() != null) {
21212140
DOMNode.setStyles(outerNode, "overflow", "hidden", "height", (rc * rh) + "px");
21222141
}
21232142
table.computeVisibleRect(tmpRect);
21242143

2125-
if (rc <= 0 || table.getColumnCount() <= 0 ||
2144+
if (rc <= 0 || cc <= 0 ||
21262145
// this check prevents us from painting the entire table
21272146
// when the clip doesn't intersect our bounds at all
21282147
!tmpRect.intersects(clip)) {
@@ -2226,67 +2245,108 @@ public void paint(Graphics g, JComponent c) {
22262245
setHidden(false);
22272246
}
22282247

2229-
private Rectangle myClip = new Rectangle();
2230-
private Rectangle getClip() {
2231-
if (table.parent instanceof JViewport) {
2232-
JSViewportUI ui = ((JSViewportUI)table.parent.getUI());
2233-
if (isNewModel) {
2234-
ui.myClip.x = ui.myClip.y = 0;
2235-
isNewModel = false;
2248+
private int lastRowCount, lastColCount;
2249+
2250+
private void checkRemoveCells(int nrows, int ncols) {
2251+
if (nrows < lastRowCount) {
2252+
// remove all missing rows
2253+
for (int r = nrows; r < lastRowCount; r++) {
2254+
DOMNode node = CellHolder.findCellNode(this, null, r, -1);
2255+
if (node != null) {
2256+
DOMNode.remove(node);
2257+
}
22362258
}
2237-
return ui.myClip;
22382259
}
2239-
myClip.width = table.getWidth();
2240-
myClip.height = table.getHeight();
2241-
return myClip;
2260+
if (ncols < lastColCount) {
2261+
// remove all extra columns for visible rows only
2262+
for (int r = 0; r < nrows; r++) {
2263+
for (int c = ncols; c < lastColCount; c++) {
2264+
DOMNode node = CellHolder.findCellNode(this, null, r, c);
2265+
if (node != null) {
2266+
DOMNode.remove(node);
2267+
// if (j == 0)
2268+
// bsRowTainted.set(i);
2269+
// DOMNode.setVisible(node, false);
2270+
}
2271+
}
2272+
}
2273+
}
2274+
lastColCount = ncols;
2275+
lastRowCount = nrows;
22422276
}
22432277

2278+
private Rectangle myClip = new Rectangle();
2279+
// private Rectangle getClip(Graphics g) {
2280+
// if (table.parent instanceof JViewport) {
2281+
//// abandoned -- not necessary
2282+
// JSViewportUI ui = ((JSViewportUI)table.parent.getUI());
2283+
// if (isNewModel) {
2284+
// ui.myClip.x = ui.myClip.y = 0;
2285+
// isNewModel = false;
2286+
// }
2287+
// return ui.myClip;
2288+
// } else {
2289+
// myClip.width = table.getWidth();
2290+
// myClip.height = table.getHeight();
2291+
// }
2292+
// return myClip;
2293+
// }
2294+
2295+
/**
2296+
* In SwingJS, track when columns have been resized so that we can ensure that, when cells
2297+
* are painted, their TD elements are correctly positioned and sized.
2298+
*/
2299+
private BitSet bsRowTainted = new BitSet();
2300+
22442301
private void paintCells(Graphics g, int rMin0, int rMax0, int rMin, int rMax, int cMin, int cMax) {
22452302
TableColumnModel cm = table.getColumnModel();
22462303
int columnMargin = cm.getColumnMargin();
22472304

22482305
int h = table.getRowHeight();
2249-
int[] cw = getColumnWidths();
2306+
2307+
boolean forceNew = (dragging || justLaidOut);
22502308

2251-
TableColumn aColumn;
2309+
getColumnWidths(false);
22522310
int columnWidth;
22532311

2254-
boolean forceNew = (dragging || justLaidOut);// || rMin == rMax && cMin == cMax);
2255-
22562312
if (table.getComponentOrientation().isLeftToRight()) {
22572313
for (int row = rMin0; row <= rMax0; row++) {
22582314
table._getCellRect(row, cMin, false, cellRect);
2315+
boolean colTainted = bsRowTainted.get(row);
22592316
DOMNode tr = DOMNode.getElement(id + "_tab_row" + row);
22602317
for (int column = cMin; column <= cMax; column++) {
2261-
aColumn = cm.getColumn(column);
2262-
columnWidth = aColumn.getWidth();
2318+
columnWidth = cw[column];
22632319
cellRect.width = columnWidth - columnMargin;
22642320
// if (aColumn != draggedColumn) {
2265-
paintCell(g, cellRect, row, column, cw, h, tr, forceNew);
2321+
paintCell(g, cellRect, row, column, h, tr, forceNew, colTainted);
22662322
// }
22672323
cellRect.x += columnWidth;
22682324
}
2325+
if (colTainted)
2326+
bsRowTainted.clear(row);
22692327
}
22702328
} else {
22712329
for (int row = rMin0; row <= rMax0; row++) {
22722330
table._getCellRect(row, cMin, false, cellRect);
2273-
aColumn = cm.getColumn(cMin);
2331+
// aColumn = cm.getColumn(cMin);
22742332
// if (aColumn != draggedColumn) {
22752333
// columnWidth = aColumn.getWidth();
22762334
// cellRect.width = columnWidth - columnMargin;
22772335
// paintCell(g, cellRect, row, cMin, cw, h);
22782336
// }
22792337
DOMNode tr = DOMNode.getElement(id + "_tab_row" + row);
2338+
boolean colTainted = bsRowTainted.get(row);
22802339
for (int column = cMin; column <= cMax; column++) {
2281-
aColumn = cm.getColumn(column);
2282-
columnWidth = aColumn.getWidth();
2340+
columnWidth = cw[column];
22832341
cellRect.width = columnWidth - columnMargin;
22842342
if (column != cMin)
22852343
cellRect.x -= columnWidth;
22862344
// if (aColumn != draggedColumn) {
2287-
paintCell(g, cellRect, row, column, cw, h, tr, forceNew);
2345+
paintCell(g, cellRect, row, column, h, tr, forceNew, colTainted);
22882346
// }
22892347
}
2348+
if (colTainted)
2349+
bsRowTainted.clear(row);
22902350
}
22912351
}
22922352

@@ -2304,8 +2364,8 @@ private void paintCells(Graphics g, int rMin0, int rMax0, int rMin, int rMax, in
23042364
havePainted = true;
23052365
}
23062366

2307-
private void paintCell(Graphics g, Rectangle cellRect, int row, int col, int[] cw, int h, DOMNode tr,
2308-
boolean forceNew) {
2367+
private void paintCell(Graphics g, Rectangle cellRect, int row, int col, int h, DOMNode tr,
2368+
boolean forceNew, boolean colTainted) {
23092369

23102370
if (table.isEditing() && table.getEditingRow() == row && table.getEditingColumn() == col) {
23112371
Component component = table.getEditorComponent();
@@ -2319,8 +2379,12 @@ private void paintCell(Graphics g, Rectangle cellRect, int row, int col, int[] c
23192379
DOMNode td = (forceNew || tr == null ? null : CellHolder.findCellNode(this, null, row, col));
23202380
boolean newtd = (td == null);
23212381
if (newtd) {
2322-
td = addElements(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, cw, h, row,
2382+
td = addElements(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, h, row,
23232383
row + 1, col, col + 1);
2384+
} else if (colTainted) {
2385+
DOMNode.setStyles(td, "left", cellRect.x + "px", "width", cw[col] + "px", "display", null);
2386+
} else {
2387+
DOMNode.setStyle(td, "display", null);
23242388
}
23252389
boolean fullPaint = (newtd || !havePainted || !isScrolling || table.getSelectedRowCount() > 0);
23262390
TableCellRenderer renderer = (fullPaint ? table.getCellRenderer(row, col)

0 commit comments

Comments
 (0)