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