1 /*
   2  * Copyright (c) 2011, 2015, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.com.sun.javafx.pgstub;
  27 
  28 import java.security.AccessControlContext;
  29 import java.util.LinkedList;
  30 import java.util.List;
  31 import java.util.Queue;
  32 
  33 import com.sun.javafx.tk.FocusCause;
  34 import com.sun.javafx.tk.TKScene;
  35 import com.sun.javafx.tk.TKStage;
  36 import com.sun.javafx.tk.TKStageListener;
  37 
  38 /**
  39  * @author Richard Bair
  40  */
  41 public class StubStage implements TKStage {
  42 
  43     private NotificationSender notificationSender = new NotificationSender();
  44 
  45     @Override
  46     public void setTKStageListener(TKStageListener listener) {
  47         notificationSender.setListener(listener);
  48     }
  49 
  50     @Override
  51     public TKScene createTKScene(boolean depthBuffer, boolean msaa, AccessControlContext acc) {
  52         return new StubScene();
  53     }
  54 
  55     @Override
  56     public void setScene(TKScene scene) {
  57         if (scene != null) {
  58             StubScene s = (StubScene) scene;
  59             s.stage = this;
  60             notificationSender.setScene(s);
  61             if (visible && width != -1 && height != -1)
  62                 s.getListener().changedSize(width, height);
  63         }
  64     }
  65 
  66     public int numTimesSetSizeAndLocation;
  67 
  68     // Platform place/resize the window with some
  69     // "default" value. Pretending that the values
  70     // below are those platform defaults.
  71     public float x = 16;
  72     public float y = 12;
  73     public float width = 256;
  74     public float height = 192;
  75 
  76     public boolean visible;
  77     public float opacity;
  78 
  79     @Override
  80     public void setBounds(float x, float y, boolean xSet, boolean ySet,
  81                           float width, float height,
  82                           float contentWidth, float contentHeight,
  83                           float xGravity, float yGravity)
  84     {
  85         numTimesSetSizeAndLocation++;
  86 
  87         boolean locationChanged = false;
  88 
  89         if (xSet && (this.x != x)) {
  90             this.x = x;
  91             locationChanged = true;
  92         }
  93 
  94         if (ySet && (this.y != y)) {
  95             this.y = y;
  96             locationChanged = true;
  97         }
  98 
  99         if (locationChanged) {
 100             notificationSender.changedLocation(x, y);
 101         }
 102 
 103         boolean sizeChanged = false;
 104 
 105         if (width > 0) {
 106             if (this.width != width) {
 107                 this.width = width;
 108                 sizeChanged = true;
 109             }
 110         } else if (contentWidth > 0) {
 111             if (this.width != contentWidth) {
 112                 this.width = contentWidth;
 113                 sizeChanged = true;
 114             }
 115         }
 116 
 117         if (height > 0) {
 118             if (this.height != height) {
 119                 this.height = height;
 120                 sizeChanged = true;
 121             }
 122         } else if (contentHeight > 0) {
 123             if (this.height != contentHeight) {
 124                 this.height = contentHeight;
 125                 sizeChanged = true;
 126             }
 127         }
 128 
 129         if (sizeChanged) {
 130             notificationSender.changedSize(width, height);
 131         }
 132     }
 133 
 134     @Override
 135     public float getUIScale() {
 136         return 1.0f;
 137     }
 138 
 139     @Override
 140     public float getRenderScale() {
 141         return 1.0f;
 142     }
 143 
 144     // Just a helper method
 145     public void setSize(float w, float h) {
 146         setBounds(0, 0, false, false, w, h, 0, 0, 0, 0);
 147     }
 148 
 149     // Just a helper method
 150     public void setLocation(float x, float y) {
 151         setBounds(x, y, true, true, 0, 0, 0, 0, 0, 0);
 152     }
 153 
 154     @Override
 155     public void setIcons(List icons) {
 156     }
 157 
 158     @Override
 159     public void setTitle(String title) {
 160     }
 161 
 162     @Override
 163     public void setVisible(boolean visible) {
 164         this.visible = visible;
 165 
 166         if (!visible) {
 167             notificationSender.changedFocused(false, FocusCause.DEACTIVATED);
 168         }
 169 
 170         notificationSender.changedLocation(x, y);
 171         notificationSender.changedSize(width, height);
 172     }
 173 
 174     @Override
 175     public void setOpacity(float opacity) {
 176         this.opacity = opacity;
 177     }
 178 
 179     @Override
 180     public void setIconified(boolean iconified) {
 181         notificationSender.changedIconified(iconified);
 182     }
 183 
 184     @Override
 185     public void setMaximized(boolean maximized) {
 186         notificationSender.changedMaximized(maximized);
 187     }
 188 
 189     @Override
 190     public void setAlwaysOnTop(boolean alwaysOnTop) {
 191         notificationSender.changedAlwaysOnTop(alwaysOnTop);
 192     }
 193 
 194     @Override
 195     public void setResizable(boolean resizable) {
 196         notificationSender.changedResizable(resizable);
 197     }
 198 
 199     @Override
 200     public void setImportant(boolean important) {
 201     }
 202 
 203     @Override
 204     public void setFullScreen(boolean fullScreen) {
 205         notificationSender.changedFullscreen(fullScreen);
 206     }
 207 
 208     @Override
 209     public void requestFocus() {
 210         notificationSender.changedFocused(true, FocusCause.ACTIVATED);
 211     }
 212 
 213     @Override
 214     public void requestFocus(FocusCause cause) {
 215         notificationSender.changedFocused(true, cause);
 216     }
 217 
 218     @Override
 219     public void toBack() {
 220     }
 221 
 222     @Override
 223     public void toFront() {
 224     }
 225 
 226     @Override
 227     public void close() {
 228     }
 229 
 230     private boolean focusGrabbed;
 231 
 232     @Override
 233     public boolean grabFocus() {
 234         focusGrabbed = true;
 235         return true;
 236     }
 237 
 238     @Override
 239     public void ungrabFocus() {
 240         focusGrabbed = false;
 241     }
 242 
 243     public boolean isFocusGrabbed() {
 244         return focusGrabbed;
 245     }
 246 
 247     @Override
 248     public void setMinimumSize(int minWidth, int minHeight) {
 249     }
 250 
 251     @Override
 252     public void setMaximumSize(int maxWidth, int maxHeight) {
 253     }
 254 
 255     public void holdNotifications() {
 256         notificationSender.holdNotifications();
 257     }
 258 
 259     public void releaseNotifications() {
 260         notificationSender.releaseNotifications();
 261     }
 262 
 263     public void releaseSingleNotification() {
 264         notificationSender.releaseSingleNotification();
 265     }
 266 
 267     protected final TKStageListener getNotificationSender() {
 268         return notificationSender;
 269     }
 270 
 271     @Override
 272     public void requestInput(String text, int type, double width, double height,
 273                                 double Mxx, double Mxy, double Mxz, double Mxt,
 274                                 double Myx, double Myy, double Myz, double Myt,
 275                                 double Mzx, double Mzy, double Mzz, double Mzt) {
 276         throw new UnsupportedOperationException("Not supported yet.");
 277     }
 278 
 279     @Override
 280     public void releaseInput() {
 281         throw new UnsupportedOperationException("Not supported yet.");
 282     }
 283 
 284     private interface Notification {
 285         void execute(TKStageListener listener);
 286     }
 287 
 288     private static final class NotificationSender implements TKStageListener {
 289         private final Queue<Notification> queue =
 290                 new LinkedList<Notification>();
 291 
 292         private boolean hold;
 293         private TKStageListener listener;
 294         private StubScene scene;
 295 
 296         public void setListener(final TKStageListener listener) {
 297             this.listener = listener;
 298         }
 299 
 300         public void setScene(final StubScene scene) {
 301             this.scene = scene;
 302         }
 303 
 304         public void holdNotifications() {
 305             hold = true;
 306         }
 307 
 308         public void releaseNotifications() {
 309             hold = false;
 310             flush();
 311         }
 312 
 313         private void releaseSingleNotification() {
 314             queue.poll().execute(listener);
 315         }
 316 
 317         @Override
 318         public void changedLocation(final float x, final float y) {
 319             process(listener1 -> listener1.changedLocation(x, y));
 320         }
 321 
 322         @Override
 323         public void changedSize(final float width, final float height) {
 324             process(listener1 -> {
 325                 listener1.changedSize(width, height);
 326                 if (scene != null && width != -1 && height != -1) {
 327                     scene.getListener().changedSize(width, height);
 328                 }
 329             });
 330         }
 331 
 332         @Override
 333         public void changedFocused(final boolean focused,
 334                                    final FocusCause cause) {
 335             process(listener1 -> listener1.changedFocused(focused, cause));
 336         }
 337 
 338         @Override
 339         public void changedIconified(final boolean iconified) {
 340             process(listener1 -> listener1.changedIconified(iconified));
 341         }
 342 
 343         @Override
 344         public void changedMaximized(final boolean maximized) {
 345             process(listener1 -> listener1.changedMaximized(maximized));
 346         }
 347 
 348         public void changedAlwaysOnTop(boolean alwaysOnTop) {
 349             process(listener1 -> listener1.changedAlwaysOnTop(alwaysOnTop));
 350         }
 351 
 352 
 353         @Override
 354         public void changedResizable(final boolean resizable) {
 355             process(listener1 -> listener1.changedResizable(resizable));
 356         }
 357 
 358         @Override
 359         public void changedFullscreen(final boolean fs) {
 360             process(listener1 -> listener1.changedFullscreen(fs));
 361         }
 362 
 363         @Override
 364         public void closing() {
 365             process(listener1 -> listener1.closing());
 366         }
 367 
 368         @Override
 369         public void closed() {
 370             process(listener1 -> listener1.closed());
 371         }
 372 
 373         @Override
 374         public void focusUngrab() {
 375             process(listener1 -> listener1.focusUngrab());
 376         }
 377 
 378         private void process(final Notification notification) {
 379             if (hold) {
 380                 queue.offer(notification);
 381                 return;
 382             }
 383 
 384             if (listener != null) {
 385                 notification.execute(listener);
 386             }
 387         }
 388 
 389         private void flush() {
 390             if (listener == null) {
 391                 queue.clear();
 392                 return;
 393             }
 394 
 395             Notification nextNotification = queue.poll();
 396             while (nextNotification != null) {
 397                 nextNotification.execute(listener);
 398                 nextNotification = queue.poll();
 399             }
 400         }
 401 
 402         /**
 403         * Initialize accessibility
 404         */
 405         public void initAccessibleTKStageListener() {
 406             // TODO: Add code later
 407         }
 408 
 409         @Override
 410         public void changedScreen(Object from, Object to) {
 411             // TODO: Add code later
 412         }
 413 
 414     }
 415 
 416     public void setRTL(boolean b) {
 417     }
 418 }