Hello,
I built the recent OpenJDK8u and OpenJDK9 sources (openjdk_versions.txt)
with the patch shown in the output_diff.txt attachment.
I applied your patch for JDK-8133864 : Wrong display, when the document
I18n properties is true.
And I applied my patch for JDK-7169915 : Swing Table Layout bad repaint
of the row.
All works fine in OpenJDK8u and the document is well displayed. The
table appears as I expected with all its lines and columns (JDK-8133864
solved), size and borders included even if we write some text inside
(JDK-7169915 solved). I can modify it as I want.
But with OpenJDK9, the display of the document is wrong. The table
appears as I expected with all its lines and columns (JDK-8133864
solved), size and borders included (JDK-7169915 solved) but the entire
document display is modified, the table is displayed on a new line. And
the document became unuseable, I can't modify it as I want.
This morning, I ran the same test programme (CodeBug.java in attachment)
with the Oracle JDK9 b114 (i.e. OpenJDK9 only with your patch for
JDK-8133864) : The table appears as I expected with all its lines and
columns (JDK-8133864 solved) but the size and borders are bad repainted
when we write some text inside (JDK-7169915 solved). And the document
became unuseable too, I can't modify it as I want.
My conclusion :
1- JDK-8133864 is solved with your PATCH.
2- JDK-7169915 could be solved with my PATCH.
3- There is regression between JDK8 and JDK9 may be in the Views
arrangement.
Best regards.
----------------------------------------------------------------------------------------------------------------------
Hello,
Could you apply the modification I suggested 4 years ago about the Bug :
JDK-7169915 : Swing Table Layout bad repaint of the row.
The test case I had sent in 2012 is the same I used in : JDK-8133864
Wrong display, when the document I18n properties is true.
A version of this test (called I18nLayoutTest.java) is now candidate as
part of tests for JDK 9 (/test/javax/swing/text/TableView/)
Yours faithfully.
--
Abossolo Foh Guy
71 rue Guy de Maupassant
69500 Bron
diff --git a/src/share/classes/javax/swing/text/CompositeView.java b/src/share/classes/javax/swing/text/CompositeView.java
--- a/src/share/classes/javax/swing/text/CompositeView.java
+++ b/src/share/classes/javax/swing/text/CompositeView.java
@@ -24,7 +24,7 @@
*/
package javax.swing.text;
-import java.util.Vector;
+import java.util.*;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.SwingConstants;
@@ -182,9 +182,14 @@
views = ZERO;
}
+ Set<View> set = new HashSet<>(Arrays.asList(views));
// update parent reference on removed views
for (int i = offset; i < offset + length; i++) {
- if (children[i].getParent() == this) {
+ View child = children[i];
+ if (child.getParent() == this && !set.contains(child)) {
+ // update parent reference on removed views
+ //for (int i = offset; i < offset + length; i++) {
+ // if (children[i].getParent() == this) {
// in FlowView.java view might be referenced
// from two super-views as a child. see logicalView
children[i].setParent(null);
diff --git a/src/share/classes/javax/swing/text/TableView.java b/src/share/classes/javax/swing/text/TableView.java
--- a/src/share/classes/javax/swing/text/TableView.java
+++ b/src/share/classes/javax/swing/text/TableView.java
@@ -78,6 +78,8 @@
super(elem, View.Y_AXIS);
rows = new Vector<TableRow>();
gridValid = false;
+ // Bug 1 (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ totalColumnRequirements = new SizeRequirements();
}
/**
@@ -345,6 +347,14 @@
// continue normal layout
super.layoutMinorAxis(targetSpan, axis, offsets, spans);
}
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ @Override
+ public void preferenceChanged(View child, boolean width, boolean height) {
+ // Instead of clean columnRequirements in calculateColumnRequirements we could use invalidateGrid()
+ //invalidateGrid();
+ super.preferenceChanged(child, width, height);
+ }
/**
* Calculate the requirements for the minor axis. This is called by
@@ -377,6 +387,11 @@
r.preferred = (int) pref;
r.maximum = (int) max;
r.alignment = 0;
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ totalColumnRequirements.minimum = r.minimum;
+ totalColumnRequirements.preferred = r.preferred;
+ totalColumnRequirements.maximum = r.maximum;
return r;
}
@@ -406,6 +421,15 @@
* into consideration any constraining maximums.
*/
void calculateColumnRequirements(int axis) {
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ // (see preferenceChanged for another solution)
+ // clean columnRequirements
+ for (SizeRequirements req : columnRequirements) {
+ req.minimum = 0;
+ req.preferred = 0;
+ req.maximum = Integer.MAX_VALUE;
+ }
+
// pass 1 - single column cells
boolean hasMultiColumn = false;
int nrows = getRowCount();
@@ -576,10 +600,13 @@
int[] columnSpans;
int[] columnOffsets;
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ SizeRequirements totalColumnRequirements;
+
SizeRequirements[] columnRequirements;
Vector<TableRow> rows;
boolean gridValid;
- static final private BitSet EMPTY = new BitSet();
+ private static final BitSet EMPTY = new BitSet();
/**
* View of a row in a row-centric table.
@@ -645,6 +672,56 @@
super.replace(offset, length, views);
invalidateGrid();
}
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ // The major axis requirements for a row are dictated by the column
+ // requirements. These methods use the value calculated by
+ // TableView.
+ protected SizeRequirements calculateMajorAxisRequirements(int axis, SizeRequirements r) {
+ SizeRequirements req = new SizeRequirements();
+ req.minimum = totalColumnRequirements.minimum;
+ req.maximum = totalColumnRequirements.maximum;
+ req.preferred = totalColumnRequirements.preferred;
+ req.alignment = 0f;
+ return req;
+ }
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ public float getMinimumSpan(int axis) {
+ float value;
+
+ if (axis == View.X_AXIS) {
+ value = totalColumnRequirements.minimum + getLeftInset() + getRightInset();
+ } else {
+ value = super.getMinimumSpan(axis);
+ }
+ return value;
+ }
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ public float getMaximumSpan(int axis) {
+ float value;
+
+ if (axis == View.X_AXIS) {
+ // We're flexible.
+ value = (float) Integer.MAX_VALUE;
+ } else {
+ value = super.getMaximumSpan(axis);
+ }
+ return value;
+ }
+
+ // Bug (JDK-7072926 : Swing Table Layout Update) & (JDK-7169915 : Swing Table Layout bad repaint of the row)
+ public float getPreferredSpan(int axis) {
+ float value;
+
+ if (axis == View.X_AXIS) {
+ value = totalColumnRequirements.preferred + getLeftInset() + getRightInset();
+ } else {
+ value = super.getPreferredSpan(axis);
+ }
+ return value;
+ }
/**
* Perform layout for the major axis of the box (i.e. the
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build
1.8.0-internal-scientificare2015_2016_04_18_16_37-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)
openjdk version "9-internal"
OpenJDK Runtime Environment (build
9-internal+0-2016-04-18-052846.scientificware2015.9dev)
OpenJDK 64-Bit Server VM (build
9-internal+0-2016-04-18-052846.scientificware2015.9dev, mixed mode)
//package CodeBug;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.text.*;
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
public class CodeBug extends JFrame {
JEditorPane edit = new JEditorPane();
public CodeBug() {
super("Code example for a TableView bug");
setUndecorated(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
edit.setEditorKit(new CodeBugEditorKit());
initCodeBug();
this.getContentPane().add(new JScrollPane(edit));
this.setSize(300, 200);
this.setLocationRelativeTo(null);
edit.getDocument().putProperty("i18n", Boolean.TRUE);
}
private void initCodeBug() {
CodeBugDocument doc = (CodeBugDocument) edit.getDocument();
try {
doc.insertString(0, "TextB TextE", null);
} catch (BadLocationException ex) {
}
doc.insertTable(6, 4, 3);
try {
doc.insertString(7, "Cell11", null);
doc.insertString(14, "Cell12", null);
doc.insertString(21, "Cell13", null);
doc.insertString(28, "Cell21", null);
doc.insertString(35, "Cell22", null);
doc.insertString(42, "Cell23", null);
doc.insertString(49, "Cell31", null);
doc.insertString(56, "Cell32", null);
doc.insertString(63, "Cell33", null);
doc.insertString(70, "Cell41", null);
doc.insertString(77, "Cell42", null);
doc.insertString(84, "Cell43", null);
} catch (BadLocationException ex) {
}
}
public static void main(String[] args) {
CodeBug m = new CodeBug();
m.setVisible(true);
}
}
//-------------------------------------------------------------------------------
class CodeBugEditorKit extends StyledEditorKit {
ViewFactory defaultFactory = new TableFactory();
@Override
public ViewFactory getViewFactory() {
return defaultFactory;
}
@Override
public Document createDefaultDocument() {
return new CodeBugDocument();
}
}
//-------------------------------------------------------------------------------
class TableFactory implements ViewFactory {
@Override
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(CodeBugDocument.ELEMENT_TABLE)) {
return new tableView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
// default to text display
return new LabelView(elem);
}
}
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
class tableView extends TableView implements ViewFactory {
public tableView(Element elem) {
super(elem);
}
@Override
public ViewFactory getViewFactory() {
return this;
}
@Override
public float getMinimumSpan(int axis) {
return getPreferredSpan(axis);
}
@Override
public float getMaximumSpan(int axis) {
return getPreferredSpan(axis);
}
@Override
public float getAlignment(int axis) {
return 0.5f;
}
@Override
public void paint(Graphics g, Shape allocation) {
super.paint(g, allocation);
Rectangle alloc = allocation.getBounds();
int lastY = alloc.y + alloc.height - 1;
g.drawLine(alloc.x, lastY, alloc.x + alloc.width, lastY);
}
@Override
protected void paintChild(Graphics g, Rectangle alloc, int index) {
super.paintChild(g, alloc, index);
int lastX = alloc.x + alloc.width;
g.drawLine(alloc.x, alloc.y, lastX, alloc.y);
}
@Override
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(CodeBugDocument.ELEMENT_TR)) {
return new trView(elem);
} else if (kind.equals(CodeBugDocument.ELEMENT_TD)) {
return new BoxView(elem, View.Y_AXIS);
}
}
// default is to delegate to the normal factory
View p = getParent();
if (p != null) {
ViewFactory f = p.getViewFactory();
if (f != null) {
return f.create(elem);
}
}
return null;
}
public class trView extends TableRow {
public trView(Element elem) {
super(elem);
}
public float getMinimumSpan(int axis) {
return getPreferredSpan(axis);
}
public float getMaximumSpan(int axis) {
return getPreferredSpan(axis);
}
public float getAlignment(int axis) {
return 0f;
}
@Override
protected void paintChild(Graphics g, Rectangle alloc, int index) {
super.paintChild(g, alloc, index);
int lastY = alloc.y + alloc.height - 1;
g.drawLine(alloc.x, alloc.y, alloc.x, lastY);
int lastX = alloc.x + alloc.width;
g.drawLine(lastX, alloc.y, lastX, lastY);
}
};
}
//-------------------------------------------------------------------------------
class CodeBugDocument extends DefaultStyledDocument {
public static final String ELEMENT_TABLE = "table";
public static final String ELEMENT_TR = "table cells row";
public static final String ELEMENT_TD = "table data cell";
public CodeBugDocument() {
//putProperty("i18n", Boolean.TRUE);
}
protected void insertTable(int offset, int rowCount, int colCount) {
try {
ArrayList Specs = new ArrayList();
ElementSpec gapTag = new ElementSpec(new SimpleAttributeSet(), ElementSpec.ContentType, "\n".toCharArray(), 0, 1);
gapTag.setDirection(ElementSpec.JoinPreviousDirection);
Specs.add(gapTag);
SimpleAttributeSet tableAttrs = new SimpleAttributeSet();
tableAttrs.addAttribute(ElementNameAttribute, ELEMENT_TABLE);
ElementSpec tableStart = new ElementSpec(tableAttrs, ElementSpec.StartTagType);
Specs.add(tableStart); //start table tag
fillRowSpecs(Specs, rowCount, colCount);
ElementSpec[] spec = new ElementSpec[Specs.size()];
Specs.toArray(spec);
this.insert(offset, spec);
} catch (BadLocationException ex) {
}
}
protected void fillRowSpecs(ArrayList Specs, int rowCount, int colCount) {
SimpleAttributeSet rowAttrs = new SimpleAttributeSet();
rowAttrs.addAttribute(ElementNameAttribute, ELEMENT_TR);
for (int i = 0; i < rowCount; i++) {
ElementSpec rowStart = new ElementSpec(rowAttrs, ElementSpec.StartTagType);
Specs.add(rowStart);
fillCellSpecs(Specs, colCount);
ElementSpec rowEnd = new ElementSpec(rowAttrs, ElementSpec.EndTagType);
Specs.add(rowEnd);
}
}
protected void fillCellSpecs(ArrayList Specs, int colCount) {
for (int i = 0; i < colCount; i++) {
SimpleAttributeSet cellAttrs = new SimpleAttributeSet();
cellAttrs.addAttribute(ElementNameAttribute, ELEMENT_TD);
ElementSpec cellStart = new ElementSpec(cellAttrs, ElementSpec.StartTagType);
Specs.add(cellStart);
ElementSpec parStart = new ElementSpec(new SimpleAttributeSet(), ElementSpec.StartTagType);
Specs.add(parStart);
ElementSpec parContent = new ElementSpec(new SimpleAttributeSet(), ElementSpec.ContentType, "\n".toCharArray(), 0, 1);
Specs.add(parContent);
ElementSpec parEnd = new ElementSpec(new SimpleAttributeSet(), ElementSpec.EndTagType);
Specs.add(parEnd);
ElementSpec cellEnd = new ElementSpec(cellAttrs, ElementSpec.EndTagType);
Specs.add(cellEnd);
}
}
}