File: TableViewLayoutTest.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (467 lines) | stat: -rw-r--r-- 16,277 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
/*
 * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @key headful
 * @bug 8133864 8158209
 * @summary  Wrong display, when the document I18n properties is true.
 */
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

public class TableViewLayoutTest extends JFrame {

    private static double yCaret;
    private static double xCaret;

    // Number of iteration to verify the stability of the test with different robot delays :
    // Work well with robot.delay(50) in hitKey method.
    // But if the robot delay is too low, the test is not stable.
    // Put this to 100, and reduce robot delay sometimes answers may be different.
    private static int tn = 2;

    // The four caret positions to test.
    private static double yCarFLTab;
    private static double yCarLLTab;
    private static double xCarBTab;
    private static double xCarETab;

    // The caret coordonate differences along axis after the insertion and the removing cycle.
    // 0 if the table layout is right.
    private static double dyCarFLTab;
    private static double dyCarLLTab;
    private static double dxCarBTab;
    private static double dxCarETab;

    private static JEditorPane edit = new JEditorPane();
    private static TableViewLayoutTest frame;

    private static String Prop = "\n";
    private static boolean isTabWrong = Boolean.FALSE;

    private static Boolean isI18n = false;

    public TableViewLayoutTest() {

        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.pack();
        this.setLocationRelativeTo(null);

        edit.addCaretListener(new CaretListener() {
            public void caretUpdate(CaretEvent e) {
                JTextComponent textComp = (JTextComponent) e.getSource();
                try {
                    Rectangle rect = textComp.getUI().modelToView(textComp, e.getDot());
                    yCaret = rect.getY();
                    xCaret = rect.getX();
                } catch (BadLocationException ex) {
                    throw new RuntimeException("Failed to get pixel position of caret", ex);
                }
            }
        });
    }

    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) throws Exception {

        for (int i = 0; i < tn; i++) {
            Robot rob = new Robot();

            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    frame = new TableViewLayoutTest();
                    frame.setVisible(true);
                }
            });

            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    //Enable or disable i18n.
                    isI18n = !isI18n;
                    edit.getDocument().putProperty("i18n", isI18n);

                    //Made a change to update table layout.
                    //Without any change the table i18n property change is not take in account.
                    edit.select(11, 12);
                    edit.replaceSelection("1");

                    //Catch the four caret positions to test before insertions.
                    edit.setCaretPosition(6);
                    xCarBTab = xCaret;
                    edit.setCaretPosition(91);
                    xCarETab = xCaret;

                    edit.setCaretPosition(74);
                    yCarLLTab = yCaret;
                    edit.setCaretPosition(11);
                    yCarFLTab = yCaret;
                }
            });

            hitKey(rob, KeyEvent.VK_T);
            hitKey(rob, KeyEvent.VK_E);
            hitKey(rob, KeyEvent.VK_S);
            hitKey(rob, KeyEvent.VK_T);
            hitKey(rob, KeyEvent.VK_BACK_SPACE);
            hitKey(rob, KeyEvent.VK_BACK_SPACE);
            hitKey(rob, KeyEvent.VK_BACK_SPACE);
            hitKey(rob, KeyEvent.VK_BACK_SPACE);

            rob.waitForIdle();

            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    //Calculate caret coordinate differences and catch caret positions after insertions.
                    edit.setCaretPosition(6);
                    dxCarBTab = Math.abs(xCarBTab - xCaret);
                    edit.setCaretPosition(91);
                    dxCarETab = Math.abs(xCarETab - xCaret);

                    edit.setCaretPosition(74);
                    dyCarLLTab = Math.abs(yCarLLTab - yCaret);
                    edit.setCaretPosition(11);
                    dyCarFLTab = Math.abs(yCarFLTab - yCaret);

                    edit.setCaretPosition(74);
                    yCarLLTab = yCaret;
                    edit.setCaretPosition(11);
                    yCarFLTab = yCaret;
                }
            });

            Object dp = edit.getDocument().getProperty("i18n");
            Boolean isI18n = dp instanceof Boolean ? (Boolean) dp : Boolean.FALSE;
            String i18n = isI18n ? "\nWhen i18n enable, " : "\nWhen i18n disable, ";

            if (Math.abs(yCarFLTab - yCarLLTab) < 10) {
                isTabWrong = Boolean.TRUE;
                Prop = Prop + i18n + "test can't be completed : TableView layout wrong, lines overlap, see JDK-8133864.";
            } else {
                if (dyCarFLTab != 0 || dyCarLLTab != 0) {
                    isTabWrong = Boolean.TRUE;
                    Prop = Prop + i18n + "TableView layout wrong : Table high change when inserts and removes caracters, bug never reported yet. First Line dy=" + dyCarFLTab + " Last Line dy=" + dyCarLLTab;
                }
                if (dxCarBTab != 0 || dxCarETab != 0) {
                    isTabWrong = Boolean.TRUE;
                    Prop = Prop + i18n + "TableView layout wrong : Table width change when inserts and removes caracters, see JDK-8158209 and JDK-7169915. Before Table dx=" + dxCarBTab + " After Table dx=" + dxCarETab;
                }
            }
            rob.waitForIdle();

            SwingUtilities.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    frame.dispose();
                }
            });
        }
        if (isTabWrong) {
            throw new RuntimeException(Prop);
        }

        System.out.println("ok");
    }

    private static void hitKey(Robot robot, int k) throws Exception {
        robot.delay(50);
        robot.keyPress(k);
        robot.keyRelease(k);
        robot.delay(50);
    }
}

//------------------------------------------------------------------------------
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 void setParent(View parent) {
        super.setParent(parent);
    }

    @Override
    public void setSize(float width, float height) {
        super.setSize(width, height);
    }

    @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 float getPreferredSpan(int axis) {
        if (axis == 0) {
            return super.getPreferredSpan(0);
        }
        float preferredSpan = super.getPreferredSpan(axis);
        return preferredSpan;
    }

    @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 {

        @Override
        public void setParent(View parent) {
            super.setParent(parent);
        }

        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);
            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);
        }
    }
}