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 }