1 /*
   2  * Copyright (c) 2014, 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 import java.awt.*;
  25 import java.util.ArrayList;
  26 import javax.swing.*;
  27 
  28 /*
  29 @test
  30 @summary Toplevel should be correctly positioned as relative to a component:
  31        so that their centers coincide 
  32        or, if the component is hidden, centered on the screen.
  33 @bug 8036915
  34 @library ../../../../lib/testlibrary
  35 @build ExtendedRobot
  36 @run main/timeout=1200 SetLocationRelativeToTest
  37 */
  38 
  39 public class SetLocationRelativeToTest {
  40     private static int delay = 500;
  41     private static boolean testEverything = false;
  42     java.util.List<Window> awtToplevels = new ArrayList<Window>();
  43     java.util.List<Window> swingToplevels = new ArrayList<Window>();
  44     java.util.List<Window> allToplevels = new ArrayList<Window>();
  45     java.util.List<Component> awtComponents = new ArrayList<Component>();
  46     java.util.List<Component> swingComponents = new ArrayList<Component>();
  47     java.util.List<Component> allComponents = new ArrayList<Component>();
  48     Label placeholder = new Label();
  49     JLabel jplaceholder = new JLabel();
  50     JFrame jcontainer;
  51     public SetLocationRelativeToTest() {
  52         Frame frame = new Frame("Frame");
  53         frame.setSize(200,100);
  54         Frame uframe = new Frame("U.Frame");
  55         uframe.setUndecorated(true);
  56         uframe.setSize(200,100);
  57         Window window = new Window(frame);
  58         window.setSize(200,100);
  59         Dialog dialog = new Dialog(frame, "Dialog");
  60         dialog.setSize(200,100);
  61         awtToplevels.add(frame);
  62         awtToplevels.add(uframe);
  63         awtToplevels.add(window);
  64         awtToplevels.add(dialog);
  65 
  66         awtComponents.add(new TextArea("Am a TextArea"));
  67         awtComponents.add(new TextField("Am a TextField"));
  68         awtComponents.add(new Button("Press"));
  69         awtComponents.add(new Label("Label"));
  70         Choice aChoice = new Choice();
  71         aChoice.add("One");
  72         aChoice.add("Two");
  73         awtComponents.add(aChoice);
  74         awtComponents.add(new Canvas());
  75         awtComponents.add(new List(4));
  76         awtComponents.add(new Checkbox("Me CheckBox"));
  77         awtComponents.add(new Scrollbar());
  78 
  79         swingComponents.add(new JTextArea("Am a JTextArea"));
  80         swingComponents.add(new JTextField("Am a JTextField"));
  81         swingComponents.add(new JButton("Press"));
  82         swingComponents.add(new JLabel("JLabel"));
  83         JComboBox jcombo = new JComboBox();
  84         swingComponents.add(jcombo);
  85         swingComponents.add(new JPanel());
  86         swingComponents.add(new JList());
  87         swingComponents.add(new JCheckBox("Me JCheckBox"));
  88         swingComponents.add(new JScrollBar());
  89     }
  90     public static void main(String args[]) {
  91         testEverything = false; // NB: change this to true to test everything
  92         SetLocationRelativeToTest test = new SetLocationRelativeToTest();
  93         test.doAWTTest(true);
  94         test.doAWTTest(false);
  95         try {
  96             test.doSwingTest(true);
  97             test.doSwingTest(false);
  98         }catch(InterruptedException ie) {
  99             ie.printStackTrace();
 100         }catch(java.lang.reflect.InvocationTargetException ite) {
 101             ite.printStackTrace();
 102             throw new RuntimeException("InvocationTarget?");
 103         }
 104         return;
 105     }
 106     // In regular testing, we select just few components to test 
 107     // randomly. If full testing required, select many ("all").
 108     void selectObjectsToTest(boolean doSwing) {
 109         allToplevels.clear();
 110         allComponents.clear();
 111         if(testEverything) {
 112             allToplevels.addAll(0, awtToplevels);
 113             allComponents.addAll(0, awtComponents);
 114             if(doSwing) {
 115                 allToplevels.addAll(allToplevels.size(), swingToplevels); 
 116                 allComponents.addAll(allComponents.size(), swingComponents);
 117             }
 118         }else{
 119             //select a random of each
 120             int i = (int)(java.lang.Math.random()*awtToplevels.size());
 121             allToplevels.add(awtToplevels.get(i));
 122             i = (int)(java.lang.Math.random()*awtComponents.size());
 123             allComponents.add(awtComponents.get(i));
 124             if(doSwing) {
 125                 i = (int)(java.lang.Math.random()*swingToplevels.size());
 126                 allToplevels.add(swingToplevels.get(i));
 127                 i = (int)(java.lang.Math.random()*swingComponents.size());
 128                 allComponents.add(swingComponents.get(i));
 129             }
 130         }
 131     }
 132     // create Frame, add an AWT component to it,
 133     // hide it (or not) and position a new toplevel
 134     // relativeTo
 135     void doAWTTest(boolean isHidden) {
 136         boolean res;
 137         ExtendedRobot robot;
 138         try {
 139             robot = new ExtendedRobot();
 140         }catch(Exception ex) {
 141             ex.printStackTrace();
 142             throw new RuntimeException("Failed: "+ex.getMessage());
 143         }
 144         Frame container = new Frame("Frame");
 145         container.setBounds(100,100,300,300);
 146         container.setLayout(new GridLayout(3,1));
 147         container.add(placeholder);
 148         container.setVisible(true);
 149         selectObjectsToTest(false);
 150         for(Component c: allComponents) {
 151             placeholder.setText((isHidden ? "Hidden " : "Below ")+ "is "+c.getClass().getName());
 152             c.setVisible(true);
 153             container.add(c);
 154             container.doLayout();
 155             if(isHidden) {
 156                 c.setVisible(false);
 157             }
 158             robot.waitForIdle(delay);
 159             for(Window w: allToplevels) {
 160                 w.setLocationRelativeTo(c);
 161                 w.setVisible(true);
 162                 robot.waitForIdle(delay);
 163                 res = compareLocations(w, c, robot);
 164                 System.out.println(c.getClass().getName()+"   \t: "+w.getClass().getName()+
 165                     ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
 166                     (res ? "" : "Failed"));
 167                 if(!res) {
 168                     throw new RuntimeException("Test failed.");
 169                 }
 170                 w.dispose();
 171             }
 172             container.remove(c);
 173             robot.waitForIdle(delay);
 174         }
 175         container.dispose();
 176     }
 177     // Create JFrame, add an AWT or Swing component to it,
 178     // hide it (or not) and position a new toplevel
 179     // relativeTo
 180     void doSwingTest(boolean isHidden) throws InterruptedException, 
 181                        java.lang.reflect.InvocationTargetException {
 182         boolean res;
 183         ExtendedRobot robot;
 184         try {
 185             robot = new ExtendedRobot();
 186         }catch(Exception ex) {
 187             ex.printStackTrace();
 188             throw new RuntimeException("Failed: "+ex.getMessage());
 189         }
 190 
 191         EventQueue.invokeAndWait( () -> {
 192             JFrame jframe = new JFrame("jframe");
 193             jframe.setSize(200,100);
 194             swingToplevels.add(jframe);
 195             JFrame ujframe = new JFrame("ujframe");
 196             ujframe.setSize(200,100);
 197             ujframe.setUndecorated(true);
 198             swingToplevels.add(ujframe);
 199             JWindow jwin = new JWindow();
 200             jwin.setSize(200,100);
 201             swingToplevels.add(jwin);
 202             JDialog jdia = new JDialog((Frame)null, "JDialog");
 203             jdia.setSize(200,100);
 204             swingToplevels.add(jdia);
 205             jcontainer = new JFrame("JFrame");
 206             jcontainer.setBounds(100,100,300,300);
 207             jcontainer.setLayout(new GridLayout(3,1));
 208             jcontainer.add(jplaceholder);
 209             jcontainer.setVisible(true);
 210             selectObjectsToTest(true);
 211         });
 212         robot.waitForIdle(delay);
 213 
 214         for(Component c: allComponents) {
 215             EventQueue.invokeAndWait( () -> {
 216                 jplaceholder.setText((isHidden ? "Hidden " : "Below ")+ "is "+c.getClass().getName());
 217                 c.setVisible(true);
 218                 jcontainer.add(c);
 219                 jcontainer.doLayout();
 220                 if(isHidden) {
 221                     c.setVisible(false);
 222                 }
 223             });
 224             robot.waitForIdle(delay);
 225             for(Window w: allToplevels) {
 226                 EventQueue.invokeAndWait( () -> {
 227                     w.setLocationRelativeTo(c);
 228                     w.setVisible(true);
 229                 });
 230                 robot.waitForIdle(delay);
 231                 res = compareLocations(w, c, robot);
 232                 System.out.println(c.getClass().getName()+"   \t: "+w.getClass().getName()+
 233                     ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
 234                     (res ? "" : "Failed"));
 235                 EventQueue.invokeAndWait( () -> {
 236                     w.dispose();
 237                 });
 238                 robot.waitForIdle();
 239                 if(!res) {
 240                     throw new RuntimeException("Test failed.");
 241                 }
 242             }
 243             EventQueue.invokeAndWait( () -> {
 244                 jcontainer.remove(c);
 245             });
 246             robot.waitForIdle(delay);
 247         }
 248         EventQueue.invokeAndWait( () -> {
 249             jcontainer.dispose();
 250         });
 251     }
 252     // Check, finally, if w  either is concentric with c
 253     // or sits in the center of the screen (if c is hidden)
 254     boolean compareLocations(final Window w, final Component c, ExtendedRobot robot) {
 255         final Point pc = new Point();
 256         final Point pw = new Point();
 257         try {
 258             EventQueue.invokeAndWait( () -> {
 259                 pw.setLocation(w.getLocationOnScreen());
 260                 pw.translate(w.getWidth()/2, w.getHeight()/2);
 261                 if(!c.isVisible()) {
 262                     Rectangle screenRect = w.getGraphicsConfiguration().getBounds();
 263                     pc.setLocation(screenRect.x+screenRect.width/2,
 264                                    screenRect.y+screenRect.height/2);
 265                 }else{
 266                     pc.setLocation(c.getLocationOnScreen());
 267                     pc.translate(c.getWidth()/2, c.getHeight()/2);
 268                 }
 269             });
 270         } catch(InterruptedException ie) {
 271             throw new RuntimeException("Interrupted");
 272         } catch(java.lang.reflect.InvocationTargetException ite) {
 273             ite.printStackTrace();
 274             throw new RuntimeException("InvocationTarget?");
 275         }
 276         robot.waitForIdle(delay);
 277         // Compare with 1 tolerance to forgive possible rounding errors
 278         if(pc.x - pw.x > 1 || 
 279            pc.x - pw.x < -1 ||
 280            pc.y - pw.y > 1 ||
 281            pc.y - pw.y < -1 ) {
 282             System.out.println("Center of "+(c.isVisible() ? "Component:" : "screen:")+pc);
 283             System.out.println("Center of Window:"+pw);
 284             System.out.println("Centers of "+w+" and "+c+" do not coincide");
 285             return false;
 286         }
 287         return true;    
 288     }
 289 }