1 /*
   2  * Copyright (c) 2011, 2017, 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 /**
  26  * @test
  27  * @key headful
  28  * @bug 6427244 8144240 8166003 8169879
  29  * @summary Test that pressing HOME correctly moves caret in I18N document.
  30  * @author Sergey Groznyh
  31  * @library ../../../regtesthelpers
  32  * @build JRobot
  33  * @run main bug6427244
  34  */
  35 
  36 import java.awt.Container;
  37 import java.awt.Dimension;
  38 import java.awt.Point;
  39 import java.awt.Shape;
  40 import java.awt.event.KeyEvent;
  41 import javax.swing.JComponent;
  42 import javax.swing.JFrame;
  43 import javax.swing.JTextPane;
  44 import javax.swing.SwingUtilities;
  45 import javax.swing.text.Position;
  46 
  47 public class bug6427244 {
  48     private static final JRobot ROBOT = JRobot.getRobot();
  49 
  50     final static int TP_SIZE = 200;
  51     final static String[] SPACES = new String[] {
  52         "\u0020", // ASCII space
  53         "\u2002", // EN space
  54         "\u2003", // EM space
  55         "\u2004", // THREE-PER-EM space
  56         "\u2005", // ... etc.
  57         "\u2006",
  58         //"\u2007",
  59         "\u2008",
  60         "\u2009",
  61         "\u200a",
  62         "\u200b",
  63         "\u205f",
  64         "\u3000",
  65     };
  66     final static String[] WORDS = new String[] {
  67         "It", "is", "a", "long", "paragraph", "for", "testing", "GlyphPainter2\n\n",
  68     };
  69 
  70     public static void main(String[] args) {
  71         bug6427244 t = new bug6427244();
  72         for (String space: SPACES) {
  73             t.init(space);
  74             t.testCaretPosition();
  75         }
  76 
  77         System.out.println("OK");
  78         // Dispose the test interface upon completion
  79         t.destroyTestInterface();
  80     }
  81 
  82     void init(final String space) {
  83         try {
  84             SwingUtilities.invokeAndWait(new Runnable() {
  85                 public void run() {
  86                     String text = null;
  87                     for (String word: WORDS) {
  88                         if (text == null) {
  89                             text = "";
  90                         } else {
  91                             text += space;
  92                         }
  93                         text += word;
  94                     }
  95                     tp = new JTextPane();
  96                     tp.setText(text +
  97                             "Some arabic: \u062a\u0641\u0627\u062d and some not.");
  98                     if (jf == null) {
  99                         jf = new JFrame();
 100                         jf.setTitle("bug6427244");
 101                         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 102                         jf.setSize(TP_SIZE, TP_SIZE);
 103                         jf.setVisible(true);
 104                     }
 105                     Container c = jf.getContentPane();
 106                     c.removeAll();
 107                     c.add(tp);
 108                     c.invalidate();
 109                     c.validate();
 110                     dim = c.getSize();
 111                 }
 112             });
 113             blockTillDisplayed(tp);
 114             ROBOT.waitForIdle();
 115         } catch (Exception ex) {
 116             throw new RuntimeException(ex);
 117         }
 118     }
 119 
 120     void destroyTestInterface() {
 121         try {
 122             SwingUtilities.invokeAndWait(new Runnable() {
 123                 @Override
 124                 public void run() {
 125                     // Dispose the frame
 126                     jf.dispose();
 127                  }
 128             });
 129         } catch (Exception ex) {
 130             // No-op
 131         }
 132     }
 133 
 134     void blockTillDisplayed(JComponent comp) throws Exception {
 135         while (comp != null && isCompVisible == false) {
 136             try {
 137                 SwingUtilities.invokeAndWait(new Runnable() {
 138                     @Override
 139                     public void run() {
 140                         isCompVisible = comp.isVisible();
 141                      }
 142                 });
 143 
 144                 if (isCompVisible == false) {
 145                     // A short wait for component to be visible
 146                     Thread.sleep(1000);
 147                 }
 148             } catch (InterruptedException ex) {
 149                 // No-op. Thread resumed from sleep
 150             } catch (Exception ex) {
 151                 throw new RuntimeException(ex);
 152             }
 153         }
 154     }
 155 
 156     public void testCaretPosition() {
 157         final Point p[] = new Point[1];
 158         try {
 159             SwingUtilities.invokeAndWait(new Runnable() {
 160                 public void run() {
 161                     p[0] = tp.getLocationOnScreen();
 162 
 163                     // the right-top corner position
 164                     p[0].x += (dim.width - 5);
 165                     p[0].y += 5;
 166                 }
 167             });
 168         } catch (Exception ex) {
 169             throw new RuntimeException(ex);
 170         }
 171         ROBOT.mouseMove(p[0].x, p[0].y);
 172         ROBOT.clickMouse();
 173         ROBOT.hitKey(KeyEvent.VK_HOME);
 174         ROBOT.waitForIdle();
 175         // this will fail if caret moves out of the 1st line.
 176         if (getCaretOrdinate() != 0) {
 177             // Dispose the test interface upon completion
 178             destroyTestInterface();
 179             throw new RuntimeException("Test Failed.");
 180         }
 181     }
 182 
 183     int getCaretOrdinate() {
 184         final int[] y = new int[1];
 185         try {
 186             SwingUtilities.invokeAndWait(new Runnable() {
 187                 public void run() {
 188                     Shape s;
 189                     try {
 190                         s = tp.getUI().getRootView(tp).modelToView(
 191                                         tp.getCaretPosition(), tp.getBounds(),
 192                                         Position.Bias.Forward);
 193                     } catch (Exception e) {
 194                         throw new RuntimeException(e);
 195                     }
 196                     y[0] = s.getBounds().y;
 197                 }
 198             });
 199         } catch (Exception e) {
 200             throw new RuntimeException(e);
 201         }
 202         return y[0];
 203     }
 204 
 205     private JFrame jf;
 206     private JTextPane tp;
 207     private Dimension dim;
 208     private volatile boolean isCompVisible = false;
 209 }