1 /*
   2  * Copyright (c) 2011, 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.  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 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 import com.sun.javafx.accessible.providers.AccessibleProvider;
  38 import com.sun.javafx.accessible.providers.AccessibleStageProvider;
  39 
  40 /**
  41  * @author Richard Bair
  42  */
  43 public class StubStage implements TKStage {
  44 
  45     private NotificationSender notificationSender = new NotificationSender();
  46 
  47     @Override
  48     public void setTKStageListener(TKStageListener listener) {
  49         notificationSender.setListener(listener);
  50     }
  51 
  52     @Override
  53     public TKScene createTKScene(boolean depthBuffer, boolean antiAliasing, AccessControlContext acc) {
  54         return new StubScene();
  55     }
  56 
  57     @Override
  58     public void setScene(TKScene scene) {
  59         if (scene != null) {
  60             StubScene s = (StubScene) scene;
  61             s.stage = this;
  62             notificationSender.setScene(s);
  63             if (visible && width != -1 && height != -1)
  64                 s.getListener().changedSize(width, height);
  65         }
  66     }
  67 
  68     public int numTimesSetSizeAndLocation;
  69 
  70     // Platform place/resize the window with some
  71     // "default" value. Pretending that the values
  72     // below are those platform defaults.
  73     public float x = 16;
  74     public float y = 12;
  75     public float width = 256;
  76     public float height = 192;
  77 
  78     public boolean visible;
  79     public float opacity;
  80 
  81     @Override
  82     public void setBounds(float x, float y, boolean xSet, boolean ySet,
  83                           float width, float height,
  84                           float contentWidth, float contentHeight,
  85                           float xGravity, float yGravity)
  86     {
  87         numTimesSetSizeAndLocation++;
  88 
  89         boolean locationChanged = false;
  90 
  91         if (xSet && (this.x != x)) {
  92             this.x = x;
  93             locationChanged = true;
  94         }
  95 
  96         if (ySet && (this.y != y)) {
  97             this.y = y;
  98             locationChanged = true;
  99         }
 100 
 101         if (locationChanged) {
 102             notificationSender.changedLocation(x, y);
 103         }
 104 
 105         boolean sizeChanged = false;
 106 
 107         if (width > 0) {
 108             if (this.width != width) {
 109                 this.width = width;
 110                 sizeChanged = true;
 111             }
 112         } else if (contentWidth > 0) {
 113             if (this.width != contentWidth) {
 114                 this.width = contentWidth;
 115                 sizeChanged = true;
 116             }
 117         }
 118 
 119         if (height > 0) {
 120             if (this.height != height) {
 121                 this.height = height;
 122                 sizeChanged = true;
 123             }
 124         } else if (contentHeight > 0) {
 125             if (this.height != contentHeight) {
 126                 this.height = contentHeight;
 127                 sizeChanged = true;
 128             }
 129         }
 130 
 131         if (sizeChanged) {
 132             notificationSender.changedSize(width, height);
 133         }
 134     }
 135 
 136     // Just a helper method
 137     public void setSize(float w, float h) {
 138         setBounds(0, 0, false, false, w, h, 0, 0, 0, 0);
 139     }
 140 
 141     // Just a helper method
 142     public void setLocation(float x, float y) {
 143         setBounds(x, y, true, true, 0, 0, 0, 0, 0, 0);
 144     }
 145 
 146     @Override
 147     public void setIcons(List icons) {
 148     }
 149 
 150     @Override
 151     public void setTitle(String title) {
 152     }
 153 
 154     @Override
 155     public void setVisible(boolean visible) {
 156         this.visible = visible;
 157 
 158         if (!visible) {
 159             notificationSender.changedFocused(false, FocusCause.DEACTIVATED);
 160         }
 161 
 162         notificationSender.changedLocation(x, y);
 163         notificationSender.changedSize(width, height);
 164     }
 165 
 166     @Override
 167     public void setOpacity(float opacity) {
 168         this.opacity = opacity;
 169     }
 170 
 171     @Override
 172     public void setIconified(boolean iconified) {
 173         notificationSender.changedIconified(iconified);
 174     }
 175 
 176     @Override
 177     public void setMaximized(boolean maximized) {
 178         notificationSender.changedMaximized(maximized);
 179     }
 180 
 181     @Override
 182     public void setAlwaysOnTop(boolean alwaysOnTop) {
 183     }
 184 
 185     @Override
 186     public void setResizable(boolean resizable) {
 187         notificationSender.changedResizable(resizable);
 188     }
 189 
 190     @Override
 191     public void setImportant(boolean important) {
 192     }
 193 
 194     @Override
 195     public void setFullScreen(boolean fullScreen) {
 196         notificationSender.changedFullscreen(fullScreen);
 197     }
 198 
 199     @Override
 200     public void requestFocus() {
 201         notificationSender.changedFocused(true, FocusCause.ACTIVATED);
 202     }
 203 
 204     @Override
 205     public void requestFocus(FocusCause cause) {
 206         notificationSender.changedFocused(true, cause);
 207     }
 208 
 209     @Override
 210     public void toBack() {
 211     }
 212 
 213     @Override
 214     public void toFront() {
 215     }
 216 
 217     @Override
 218     public void close() {
 219     }
 220 
 221     private boolean focusGrabbed;
 222 
 223     @Override
 224     public boolean grabFocus() {
 225         focusGrabbed = true;
 226         return true;
 227     }
 228 
 229     @Override
 230     public void ungrabFocus() {
 231         focusGrabbed = false;
 232     }
 233 
 234     public boolean isFocusGrabbed() {
 235         return focusGrabbed;
 236     }
 237 
 238     @Override
 239     public void setMinimumSize(int minWidth, int minHeight) {
 240     }
 241 
 242     @Override
 243     public void setMaximumSize(int maxWidth, int maxHeight) {
 244     }
 245 
 246     public void holdNotifications() {
 247         notificationSender.holdNotifications();
 248     }
 249 
 250     public void releaseNotifications() {
 251         notificationSender.releaseNotifications();
 252     }
 253 
 254     public void releaseSingleNotification() {
 255         notificationSender.releaseSingleNotification();
 256     }
 257 
 258     protected final TKStageListener getNotificationSender() {
 259         return notificationSender;
 260     }
 261 
 262     @Override
 263     public void requestInput(String text, int type, double width, double height,
 264                                 double Mxx, double Mxy, double Mxz, double Mxt,
 265                                 double Myx, double Myy, double Myz, double Myt,
 266                                 double Mzx, double Mzy, double Mzz, double Mzt) {
 267         throw new UnsupportedOperationException("Not supported yet.");
 268     }
 269 
 270     @Override
 271     public void releaseInput() {
 272         throw new UnsupportedOperationException("Not supported yet.");
 273     }
 274 
 275     /**
 276      *
 277      * Accessibility glue for native
 278      *
 279      */
 280 
 281     /**
 282      * Initialize Accessiblility
 283      *
 284      * @param ac    the Glass accessible root object.
 285      */
 286     @Override public void setAccessibilityInitIsComplete(Object ac) {
 287         // TODO: Add code later
 288     }
 289 
 290     /**
 291      * Create accessible Glass object corresponding to stage
 292      *
 293      * @param ac    the FX accessible root/stage node.
 294      *
 295      * @return the Glass AccessibleRoot object.
 296      */
 297     @Override
 298     public Object accessibleCreateStageProvider(AccessibleStageProvider ac) {
 299         // TODO: Add code later
 300         return null ;
 301     }
 302 
 303     /**
 304      * Create accessible native object corresponding to controls
 305      *
 306      * @param ac
 307      * returns native Object
 308      */
 309     @Override public Object accessibleCreateBasicProvider(AccessibleProvider ac) {
 310         // TODO: Add code later
 311         return null;
 312     }
 313 
 314     /**
 315      * Delete accessible native object corresponding to controls
 316      *
 317      * @param nativeAcc
 318      * returns native Object
 319      */
 320     @Override public void accessibleDestroyBasicProvider(Object nativeAcc) {
 321         // TODO: Add code later
 322     }
 323 
 324     /**
 325      * Fire accessible event
 326      *
 327      * @param eventID   identifies the event.
 328      */
 329     @Override public void accessibleFireEvent(Object nativeAcc, int eventID) {
 330         // TODO: Add code later
 331     }
 332 
 333     /** Fire accessible property change event
 334      *
 335      * @param propertyId    identifies the property
 336      * @param oldProperty   the old value of the property
 337      * @param newProperty   the new value of the property
 338      */
 339     @Override public void accessibleFirePropertyChange(Object nativeAcc, int propertyId, int oldProperty,
 340                                              int newProperty ) {
 341         // TODO: Add code later
 342     }
 343 
 344     @Override public void accessibleFirePropertyChange(Object nativeAcc, int propertyId, boolean oldProperty,
 345                                              boolean newProperty ) {
 346         // TODO: Add code later
 347     }
 348 
 349     private interface Notification {
 350         void execute(TKStageListener listener);
 351     }
 352 
 353     private static final class NotificationSender implements TKStageListener {
 354         private final Queue<Notification> queue =
 355                 new LinkedList<Notification>();
 356 
 357         private boolean hold;
 358         private TKStageListener listener;
 359         private StubScene scene;
 360 
 361         public void setListener(final TKStageListener listener) {
 362             this.listener = listener;
 363         }
 364 
 365         public void setScene(final StubScene scene) {
 366             this.scene = scene;
 367         }
 368 
 369         public void holdNotifications() {
 370             hold = true;
 371         }
 372 
 373         public void releaseNotifications() {
 374             hold = false;
 375             flush();
 376         }
 377 
 378         private void releaseSingleNotification() {
 379             queue.poll().execute(listener);
 380         }
 381 
 382         @Override
 383         public void changedLocation(final float x, final float y) {
 384             process(new Notification() {
 385                         @Override
 386                         public void execute(final TKStageListener listener) {
 387                             listener.changedLocation(x, y);
 388                         }
 389                     });
 390         }
 391 
 392         @Override
 393         public void changedSize(final float width, final float height) {
 394             process(new Notification() {
 395                         @Override
 396                         public void execute(final TKStageListener listener) {
 397                             listener.changedSize(width, height);
 398                             if (scene != null && width != -1 && height != -1) {
 399                                 scene.getListener().changedSize(width, height);
 400                             }
 401                         }
 402                     });
 403         }
 404 
 405         @Override
 406         public void changedFocused(final boolean focused,
 407                                    final FocusCause cause) {
 408             process(new Notification() {
 409                         @Override
 410                         public void execute(final TKStageListener listener) {
 411                             listener.changedFocused(focused, cause);
 412                         }
 413                     });
 414         }
 415 
 416         @Override
 417         public void changedIconified(final boolean iconified) {
 418             process(new Notification() {
 419                         @Override
 420                         public void execute(final TKStageListener listener) {
 421                             listener.changedIconified(iconified);
 422                         }
 423                     });
 424         }
 425 
 426         @Override
 427         public void changedMaximized(final boolean maximized) {
 428             process(new Notification() {
 429                         @Override
 430                         public void execute(final TKStageListener listener) {
 431                             listener.changedMaximized(maximized);
 432                         }
 433                     });
 434         }
 435 
 436 
 437         @Override
 438         public void changedResizable(final boolean resizable) {
 439             process(new Notification() {
 440                         @Override
 441                         public void execute(final TKStageListener listener) {
 442                             listener.changedResizable(resizable);
 443                         }
 444                     });
 445         }
 446 
 447         @Override
 448         public void changedFullscreen(final boolean fs) {
 449             process(new Notification() {
 450                         @Override
 451                         public void execute(final TKStageListener listener) {
 452                             listener.changedFullscreen(fs);
 453                         }
 454                     });
 455         }
 456 
 457         @Override
 458         public void closing() {
 459             process(new Notification() {
 460                         @Override
 461                         public void execute(final TKStageListener listener) {
 462                             listener.closing();
 463                         }
 464                     });
 465         }
 466 
 467         @Override
 468         public void closed() {
 469             process(new Notification() {
 470                         @Override
 471                         public void execute(final TKStageListener listener) {
 472                             listener.closed();
 473                         }
 474                     });
 475         }
 476 
 477         @Override
 478         public void focusUngrab() {
 479             process(new Notification() {
 480                         @Override
 481                         public void execute(final TKStageListener listener) {
 482                             listener.focusUngrab();
 483                         }
 484                     });
 485         }
 486 
 487         private void process(final Notification notification) {
 488             if (hold) {
 489                 queue.offer(notification);
 490                 return;
 491             }
 492 
 493             if (listener != null) {
 494                 notification.execute(listener);
 495             }
 496         }
 497 
 498         private void flush() {
 499             if (listener == null) {
 500                 queue.clear();
 501                 return;
 502             }
 503 
 504             Notification nextNotification = queue.poll();
 505             while (nextNotification != null) {
 506                 nextNotification.execute(listener);
 507                 nextNotification = queue.poll();
 508             }
 509         }
 510 
 511         /**
 512         * Initialize accessibility
 513         */
 514         public void initAccessibleTKStageListener() {
 515             // TODO: Add code later
 516         }
 517 
 518     }
 519 
 520     public void setRTL(boolean b) {
 521     }
 522 }