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;// NB: change this to true to test everything
  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 
  91     public static void main(String args[]) {
  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 
 107     // In regular testing, we select just few components to test
 108     // randomly. If full testing required, select many ("all").
 109     void selectObjectsToTest(boolean doSwing) {
 110         allToplevels.clear();
 111         allComponents.clear();
 112         if(testEverything) {
 113             allToplevels.addAll(0, awtToplevels);
 114             allComponents.addAll(0, awtComponents);
 115             if(doSwing) {
 116                 allToplevels.addAll(allToplevels.size(), swingToplevels);
 117                 allComponents.addAll(allComponents.size(), swingComponents);
 118             }
 119         }else{
 120             //select a random of each
 121             int i = (int)(java.lang.Math.random()*awtToplevels.size());
 122             allToplevels.add(awtToplevels.get(i));
 123             i = (int)(java.lang.Math.random()*awtComponents.size());
 124             allComponents.add(awtComponents.get(i));
 125             if(doSwing) {
 126                 i = (int)(java.lang.Math.random()*swingToplevels.size());
 127                 allToplevels.add(swingToplevels.get(i));
 128                 i = (int)(java.lang.Math.random()*swingComponents.size());
 129                 allComponents.add(swingComponents.get(i));
 130             }
 131         }
 132     }
 133 
 134     // create Frame, add an AWT component to it,
 135     // hide it (or not) and position a new toplevel
 136     // relativeTo
 137     void doAWTTest(boolean isHidden) {
 138         boolean res;
 139         ExtendedRobot robot;
 140         try {
 141             robot = new ExtendedRobot();
 142         }catch(Exception ex) {
 143             ex.printStackTrace();
 144             throw new RuntimeException("Failed: "+ex.getMessage());
 145         }
 146         Frame container = new Frame("Frame");
 147         container.setBounds(100,100,300,300);
 148         container.setLayout(new GridLayout(3,1));
 149         container.add(placeholder);
 150         container.setVisible(true);
 151         selectObjectsToTest(false);
 152         for(Component c: allComponents) {
 153             placeholder.setText((isHidden ? "Hidden: " : "Below is ")+ c.getClass().getName());
 154             c.setVisible(true);
 155             container.add(c);
 156             container.doLayout();
 157             if(isHidden) {
 158                 c.setVisible(false);
 159             }
 160             robot.waitForIdle(delay);
 161             for(Window w: allToplevels) {
 162                 w.setLocationRelativeTo(c);
 163                 w.setVisible(true);
 164                 robot.waitForIdle(delay);
 165                 res = compareLocations(w, c, robot);
 166                 System.out.println(c.getClass().getName()+"   \t: "+w.getClass().getName()+
 167                     ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
 168                     (res ? "" : "Failed"));
 169                 if(!res) {
 170                     throw new RuntimeException("Test failed.");
 171                 }
 172                 w.dispose();
 173             }
 174             container.remove(c);
 175             robot.waitForIdle(delay);
 176         }
 177         container.dispose();
 178     }
 179 
 180     // Create JFrame, add an AWT or Swing component to it,
 181     // hide it (or not) and position a new toplevel
 182     // relativeTo
 183     void doSwingTest(boolean isHidden) throws InterruptedException,
 184                        java.lang.reflect.InvocationTargetException {
 185         boolean res;
 186         ExtendedRobot robot;
 187         try {
 188             robot = new ExtendedRobot();
 189         }catch(Exception ex) {
 190             ex.printStackTrace();
 191             throw new RuntimeException("Failed: "+ex.getMessage());
 192         }
 193 
 194         EventQueue.invokeAndWait( () -> {
 195             JFrame jframe = new JFrame("jframe");
 196             jframe.setSize(200,100);
 197             swingToplevels.add(jframe);
 198             JFrame ujframe = new JFrame("ujframe");
 199             ujframe.setSize(200,100);
 200             ujframe.setUndecorated(true);
 201             swingToplevels.add(ujframe);
 202             JWindow jwin = new JWindow();
 203             jwin.setSize(200,100);
 204             swingToplevels.add(jwin);
 205             JDialog jdia = new JDialog((Frame)null, "JDialog");
 206             jdia.setSize(200,100);
 207             swingToplevels.add(jdia);
 208             jcontainer = new JFrame("JFrame");
 209             jcontainer.setBounds(100,100,300,300);
 210             jcontainer.setLayout(new GridLayout(3,1));
 211             jcontainer.add(jplaceholder);
 212             jcontainer.setVisible(true);
 213             selectObjectsToTest(true);
 214         });
 215         robot.waitForIdle(delay);
 216 
 217         for(Component c: allComponents) {
 218             EventQueue.invokeAndWait( () -> {
 219                 jplaceholder.setText((isHidden ? "Hidden: " : "Below is: ")+ c.getClass().getName());
 220                 c.setVisible(true);
 221                 jcontainer.add(c);
 222                 jcontainer.doLayout();
 223                 if(isHidden) {
 224                     c.setVisible(false);
 225                 }
 226             });
 227             robot.waitForIdle(delay);
 228             for(Window w: allToplevels) {
 229                 EventQueue.invokeAndWait( () -> {
 230                     w.setLocationRelativeTo(c);
 231                     w.setVisible(true);
 232                 });
 233                 robot.waitForIdle(delay);
 234                 res = compareLocations(w, c, robot);
 235                 System.out.println(c.getClass().getName()+"   \t: "+w.getClass().getName()+
 236                     ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+
 237                     (res ? "" : "Failed"));
 238                 EventQueue.invokeAndWait( () -> {
 239                     w.dispose();
 240                 });
 241                 robot.waitForIdle();
 242                 if(!res) {
 243                     throw new RuntimeException("Test failed.");
 244                 }
 245             }
 246             EventQueue.invokeAndWait( () -> {
 247                 jcontainer.remove(c);
 248             });
 249             robot.waitForIdle(delay);
 250         }
 251         EventQueue.invokeAndWait( () -> {
 252             jcontainer.dispose();
 253         });
 254     }
 255 
 256     // Check, finally, if w  either is concentric with c
 257     // or sits in the center of the screen (if c is hidden)
 258     boolean compareLocations(final Window w, final Component c, ExtendedRobot robot) {
 259         final Point pc = new Point();
 260         final Point pw = new Point();
 261         try {
 262             EventQueue.invokeAndWait( () -> {
 263                 pw.setLocation(w.getLocationOnScreen());
 264                 pw.translate(w.getWidth()/2, w.getHeight()/2);
 265                 if(!c.isVisible()) {
 266                     Rectangle screenRect = w.getGraphicsConfiguration().getBounds();
 267                     pc.setLocation(screenRect.x+screenRect.width/2,
 268                                    screenRect.y+screenRect.height/2);
 269                 }else{
 270                     pc.setLocation(c.getLocationOnScreen());
 271                     pc.translate(c.getWidth()/2, c.getHeight()/2);
 272                 }
 273             });
 274         } catch(InterruptedException ie) {
 275             throw new RuntimeException("Interrupted");
 276         } catch(java.lang.reflect.InvocationTargetException ite) {
 277             ite.printStackTrace();
 278             throw new RuntimeException("InvocationTarget?");
 279         }
 280         robot.waitForIdle(delay);
 281         // Compare with 1 tolerance to forgive possible rounding errors
 282         if(pc.x - pw.x > 1 ||
 283            pc.x - pw.x < -1 ||
 284            pc.y - pw.y > 1 ||
 285            pc.y - pw.y < -1 ) {
 286             System.out.println("Center of "+(c.isVisible() ? "Component:" : "screen:")+pc);
 287             System.out.println("Center of Window:"+pw);
 288             System.out.println("Centers of "+w+" and "+c+" do not coincide");
 289             return false;
 290         }
 291         return true;
 292     }
 293 }