1 /* 2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8133864 27 * @summary Wrong display, when the document I18n properties is true. 28 * @author Semyon Sadetsky 29 * @run main I18nLayoutTest 30 */ 31 32 import javax.swing.*; 33 import javax.swing.text.*; 34 import java.awt.*; 35 import java.util.ArrayList; 36 37 public class I18nLayoutTest extends JFrame { 38 39 private static int height; 40 JEditorPane edit = new JEditorPane(); 41 private static I18nLayoutTest frame; 42 43 public I18nLayoutTest() { 44 super("Code example for a TableView bug"); 45 setUndecorated(true); 46 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 47 edit.setEditorKit(new CodeBugEditorKit()); 48 initCodeBug(); 49 this.getContentPane().add(new JScrollPane(edit)); 50 this.pack(); 51 this.setLocationRelativeTo(null); 52 53 } 54 55 private void initCodeBug() { 56 CodeBugDocument doc = (CodeBugDocument) edit.getDocument(); 57 try { 58 doc.insertString(0, "TextB TextE", null); 59 } catch (BadLocationException ex) { 60 } 61 doc.insertTable(6, 4, 3); 62 try { 63 doc.insertString(7, "Cell11", null); 64 doc.insertString(14, "Cell12", null); 65 doc.insertString(21, "Cell13", null); 66 doc.insertString(28, "Cell21", null); 67 doc.insertString(35, "Cell22", null); 68 doc.insertString(42, "Cell23", null); 69 doc.insertString(49, "Cell31", null); 70 doc.insertString(56, "Cell32", null); 71 doc.insertString(63, "Cell33", null); 72 doc.insertString(70, "Cell41", null); 73 doc.insertString(77, "Cell42", null); 74 doc.insertString(84, "Cell43", null); 75 } catch (BadLocationException ex) { 76 } 77 } 78 79 public static void main(String[] args) throws Exception { 80 SwingUtilities.invokeAndWait(new Runnable() { 81 @Override 82 public void run() { 83 frame = new I18nLayoutTest(); 84 frame.setVisible(true); 85 } 86 }); 87 Robot robot = new Robot(); 88 robot.delay(200); 89 robot.waitForIdle(); 90 SwingUtilities.invokeAndWait(new Runnable() { 91 @Override 92 public void run() { 93 height = frame.getHeight(); 94 } 95 }); 96 SwingUtilities.invokeAndWait(new Runnable() { 97 @Override 98 public void run() { 99 frame.dispose(); 100 } 101 }); 102 if (height < 32) { 103 throw new RuntimeException( 104 "TableView layout height is wrong " + height); 105 } 106 System.out.println("ok"); 107 } 108 } 109 110 //------------------------------------------------------------------------------ 111 class CodeBugEditorKit extends StyledEditorKit { 112 113 ViewFactory defaultFactory = new TableFactory(); 114 115 @Override 116 public ViewFactory getViewFactory() { 117 return defaultFactory; 118 } 119 120 @Override 121 public Document createDefaultDocument() { 122 return new CodeBugDocument(); 123 } 124 } 125 //------------------------------------------------------------------------------ 126 127 class TableFactory implements ViewFactory { 128 129 @Override 130 public View create(Element elem) { 131 String kind = elem.getName(); 132 if (kind != null) { 133 if (kind.equals(AbstractDocument.ContentElementName)) { 134 return new LabelView(elem); 135 } else if (kind.equals(AbstractDocument.ParagraphElementName)) { 136 return new ParagraphView(elem); 137 } else if (kind.equals(AbstractDocument.SectionElementName)) { 138 return new BoxView(elem, View.Y_AXIS); 139 } else if (kind.equals(StyleConstants.ComponentElementName)) { 140 return new ComponentView(elem); 141 } else if (kind.equals(CodeBugDocument.ELEMENT_TABLE)) { 142 return new tableView(elem); 143 } else if (kind.equals(StyleConstants.IconElementName)) { 144 return new IconView(elem); 145 } 146 } 147 // default to text display 148 return new LabelView(elem); 149 150 } 151 } 152 //------------------------------------------------------------------------------ 153 154 //------------------------------------------------------------------------------ 155 class tableView extends TableView implements ViewFactory { 156 157 public tableView(Element elem) { 158 super(elem); 159 } 160 161 @Override 162 public void setParent(View parent) { 163 super.setParent(parent); 164 } 165 166 @Override 167 public void setSize(float width, float height) { 168 super.setSize(width, height); 169 } 170 171 @Override 172 public ViewFactory getViewFactory() { 173 return this; 174 } 175 176 @Override 177 public float getMinimumSpan(int axis) { 178 return getPreferredSpan(axis); 179 } 180 181 @Override 182 public float getMaximumSpan(int axis) { 183 return getPreferredSpan(axis); 184 } 185 186 @Override 187 public float getAlignment(int axis) { 188 return 0.5f; 189 } 190 191 @Override 192 public float getPreferredSpan(int axis) { 193 if (axis == 0) return super.getPreferredSpan(0); 194 float preferredSpan = super.getPreferredSpan(axis); 195 return preferredSpan; 196 } 197 198 @Override 199 public void paint(Graphics g, Shape allocation) { 200 super.paint(g, allocation); 201 Rectangle alloc = allocation.getBounds(); 202 int lastY = alloc.y + alloc.height - 1; 203 g.drawLine(alloc.x, lastY, alloc.x + alloc.width, lastY); 204 } 205 206 @Override 207 protected void paintChild(Graphics g, Rectangle alloc, int index) { 208 super.paintChild(g, alloc, index); 209 int lastX = alloc.x + alloc.width; 210 g.drawLine(alloc.x, alloc.y, lastX, alloc.y); 211 } 212 213 @Override 214 public View create(Element elem) { 215 String kind = elem.getName(); 216 if (kind != null) { 217 if (kind.equals(CodeBugDocument.ELEMENT_TR)) { 218 return new trView(elem); 219 } else if (kind.equals(CodeBugDocument.ELEMENT_TD)) { 220 return new BoxView(elem, View.Y_AXIS); 221 222 } 223 } 224 225 // default is to delegate to the normal factory 226 View p = getParent(); 227 if (p != null) { 228 ViewFactory f = p.getViewFactory(); 229 if (f != null) { 230 return f.create(elem); 231 } 232 } 233 234 return null; 235 } 236 237 public class trView extends TableRow { 238 @Override 239 public void setParent(View parent) { 240 super.setParent(parent); 241 } 242 243 public trView(Element elem) { 244 super(elem); 245 } 246 247 public float getMinimumSpan(int axis) { 248 return getPreferredSpan(axis); 249 } 250 251 public float getMaximumSpan(int axis) { 252 return getPreferredSpan(axis); 253 } 254 255 public float getAlignment(int axis) { 256 return 0f; 257 } 258 259 @Override 260 protected void paintChild(Graphics g, Rectangle alloc, int index) { 261 super.paintChild(g, alloc, index); 262 int lastY = alloc.y + alloc.height - 1; 263 g.drawLine(alloc.x, alloc.y, alloc.x, lastY); 264 int lastX = alloc.x + alloc.width; 265 g.drawLine(lastX, alloc.y, lastX, lastY); 266 } 267 } 268 269 ; 270 } 271 272 //------------------------------------------------------------------------------ 273 class CodeBugDocument extends DefaultStyledDocument { 274 275 public static final String ELEMENT_TABLE = "table"; 276 public static final String ELEMENT_TR = "table cells row"; 277 public static final String ELEMENT_TD = "table data cell"; 278 279 public CodeBugDocument() { 280 putProperty("i18n", Boolean.TRUE); 281 } 282 283 284 protected void insertTable(int offset, int rowCount, int colCount) { 285 try { 286 ArrayList Specs = new ArrayList(); 287 ElementSpec gapTag = new ElementSpec(new SimpleAttributeSet(), 288 ElementSpec.ContentType, "\n".toCharArray(), 0, 1); 289 Specs.add(gapTag); 290 291 SimpleAttributeSet tableAttrs = new SimpleAttributeSet(); 292 tableAttrs.addAttribute(ElementNameAttribute, ELEMENT_TABLE); 293 ElementSpec tableStart = 294 new ElementSpec(tableAttrs, ElementSpec.StartTagType); 295 Specs.add(tableStart); //start table tag 296 297 298 fillRowSpecs(Specs, rowCount, colCount); 299 300 ElementSpec[] spec = new ElementSpec[Specs.size()]; 301 Specs.toArray(spec); 302 303 this.insert(offset, spec); 304 } catch (BadLocationException ex) { 305 } 306 } 307 308 protected void fillRowSpecs(ArrayList Specs, int rowCount, int colCount) { 309 SimpleAttributeSet rowAttrs = new SimpleAttributeSet(); 310 rowAttrs.addAttribute(ElementNameAttribute, ELEMENT_TR); 311 for (int i = 0; i < rowCount; i++) { 312 ElementSpec rowStart = 313 new ElementSpec(rowAttrs, ElementSpec.StartTagType); 314 Specs.add(rowStart); 315 316 fillCellSpecs(Specs, colCount); 317 318 ElementSpec rowEnd = 319 new ElementSpec(rowAttrs, ElementSpec.EndTagType); 320 Specs.add(rowEnd); 321 } 322 323 } 324 325 protected void fillCellSpecs(ArrayList Specs, int colCount) { 326 for (int i = 0; i < colCount; i++) { 327 SimpleAttributeSet cellAttrs = new SimpleAttributeSet(); 328 cellAttrs.addAttribute(ElementNameAttribute, ELEMENT_TD); 329 330 ElementSpec cellStart = 331 new ElementSpec(cellAttrs, ElementSpec.StartTagType); 332 Specs.add(cellStart); 333 334 ElementSpec parStart = new ElementSpec(new SimpleAttributeSet(), 335 ElementSpec.StartTagType); 336 Specs.add(parStart); 337 ElementSpec parContent = new ElementSpec(new SimpleAttributeSet(), 338 ElementSpec.ContentType, "\n".toCharArray(), 0, 1); 339 Specs.add(parContent); 340 ElementSpec parEnd = new ElementSpec(new SimpleAttributeSet(), 341 ElementSpec.EndTagType); 342 Specs.add(parEnd); 343 ElementSpec cellEnd = 344 new ElementSpec(cellAttrs, ElementSpec.EndTagType); 345 Specs.add(cellEnd); 346 } 347 } 348 }