1 /*
   2  * Copyright (c) 2011, 2013, 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 (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 setResizable(boolean resizable) {
 183         notificationSender.changedResizable(resizable);
 184     }
 185 
 186     @Override
 187     public void setImportant(boolean important) {
 188     }
 189 
 190     @Override
 191     public void setFullScreen(boolean fullScreen) {
 192         notificationSender.changedFullscreen(fullScreen);
 193     }
 194 
 195     @Override
 196     public void requestFocus() {
 197         notificationSender.changedFocused(true, FocusCause.ACTIVATED);
 198     }
 199 
 200     @Override
 201     public void requestFocus(FocusCause cause) {
 202         notificationSender.changedFocused(true, cause);
 203     }
 204 
 205     @Override
 206     public void toBack() {
 207     }
 208 
 209     @Override
 210     public void toFront() {
 211     }
 212 
 213     @Override
 214     public void close() {
 215     }
 216 
 217     private boolean focusGrabbed;
 218 
 219     @Override
 220     public boolean grabFocus() {
 221         focusGrabbed = true;
 222         return true;
 223     }
 224 
 225     @Override
 226     public void ungrabFocus() {
 227         focusGrabbed = false;
 228     }
 229 
 230     public boolean isFocusGrabbed() {
 231         return focusGrabbed;
 232     }
 233 
 234     @Override
 235     public void setMinimumSize(int minWidth, int minHeight) {
 236     }
 237 
 238     @Override
 239     public void setMaximumSize(int maxWidth, int maxHeight) {
 240     }
 241 
 242     public void holdNotifications() {
 243         notificationSender.holdNotifications();
 244     }
 245 
 246     public void releaseNotifications() {
 247         notificationSender.releaseNotifications();
 248     }
 249 
 250     public void releaseSingleNotification() {
 251         notificationSender.releaseSingleNotification();
 252     }
 253 
 254     protected final TKStageListener getNotificationSender() {
 255         return notificationSender;
 256     }
 257 
 258     @Override
 259     public void requestInput(String text, int type, double width, double height,
 260                                 double Mxx, double Mxy, double Mxz, double Mxt,
 261                                 double Myx, double Myy, double Myz, double Myt,
 262                                 double Mzx, double Mzy, double Mzz, double Mzt) {
 263         throw new UnsupportedOperationException("Not supported yet.");
 264     }
 265 
 266     @Override
 267     public void releaseInput() {
 268         throw new UnsupportedOperationException("Not supported yet.");
 269     }
 270 
 271     /**
 272      *
 273      * Accessibility glue for native
 274      *
 275      */
 276 
 277     /**
 278      * Initialize Accessiblility
 279      *
 280      * @param ac    the Glass accessible root object.
 281      */
 282     @Override public void setAccessibilityInitIsComplete(Object ac) {
 283         // TODO: Add code later
 284     }
 285 
 286     /**
 287      * Create accessible Glass object corresponding to stage
 288      *
 289      * @param ac    the FX accessible root/stage node.
 290      *
 291      * @return the Glass AccessibleRoot object.
 292      */
 293     @Override
 294     public Object accessibleCreateStageProvider(AccessibleStageProvider ac) {
 295         // TODO: Add code later
 296         return null ;
 297     }
 298 
 299     /**
 300      * Create accessible native object corresponding to controls
 301      *
 302      * @param ac
 303      * returns native Object
 304      */
 305     @Override public Object accessibleCreateBasicProvider(AccessibleProvider ac) {
 306         // TODO: Add code later
 307         return null;
 308     }
 309 
 310     /**
 311      * Delete accessible native object corresponding to controls
 312      *
 313      * @param nativeAcc
 314      * returns native Object
 315      */
 316     @Override public void accessibleDestroyBasicProvider(Object nativeAcc) {
 317         // TODO: Add code later
 318     }
 319 
 320     /**
 321      * Fire accessible event
 322      *
 323      * @param eventID   identifies the event.
 324      */
 325     @Override public void accessibleFireEvent(Object nativeAcc, int eventID) {
 326         // TODO: Add code later
 327     }
 328 
 329     /** Fire accessible property change event
 330      *
 331      * @param propertyId    identifies the property
 332      * @param oldProperty   the old value of the property
 333      * @param newProperty   the new value of the property
 334      */
 335     @Override public void accessibleFirePropertyChange(Object nativeAcc, int propertyId, int oldProperty,
 336                                              int newProperty ) {
 337         // TODO: Add code later
 338     }
 339 
 340     @Override public void accessibleFirePropertyChange(Object nativeAcc, int propertyId, boolean oldProperty,
 341                                              boolean newProperty ) {
 342         // TODO: Add code later
 343     }
 344 
 345     private interface Notification {
 346         void execute(TKStageListener listener);
 347     }
 348 
 349     private static final class NotificationSender implements TKStageListener {
 350         private final Queue<Notification> queue =
 351                 new LinkedList<Notification>();
 352 
 353         private boolean hold;
 354         private TKStageListener listener;
 355         private StubScene scene;
 356 
 357         public void setListener(final TKStageListener listener) {
 358             this.listener = listener;
 359         }
 360 
 361         public void setScene(final StubScene scene) {
 362             this.scene = scene;
 363         }
 364 
 365         public void holdNotifications() {
 366             hold = true;
 367         }
 368 
 369         public void releaseNotifications() {
 370             hold = false;
 371             flush();
 372         }
 373 
 374         private void releaseSingleNotification() {
 375             queue.poll().execute(listener);
 376         }
 377 
 378         @Override
 379         public void changedLocation(final float x, final float y) {
 380             process(new Notification() {
 381                         @Override
 382                         public void execute(final TKStageListener listener) {
 383                             listener.changedLocation(x, y);
 384                         }
 385                     });
 386         }
 387 
 388         @Override
 389         public void changedSize(final float width, final float height) {
 390             process(new Notification() {
 391                         @Override
 392                         public void execute(final TKStageListener listener) {
 393                             listener.changedSize(width, height);
 394                             if (scene != null && width != -1 && height != -1) {
 395                                 scene.getListener().changedSize(width, height);
 396                             }
 397                         }
 398                     });
 399         }
 400 
 401         @Override
 402         public void changedFocused(final boolean focused,
 403                                    final FocusCause cause) {
 404             process(new Notification() {
 405                         @Override
 406                         public void execute(final TKStageListener listener) {
 407                             listener.changedFocused(focused, cause);
 408                         }
 409                     });
 410         }
 411 
 412         @Override
 413         public void changedIconified(final boolean iconified) {
 414             process(new Notification() {
 415                         @Override
 416                         public void execute(final TKStageListener listener) {
 417                             listener.changedIconified(iconified);
 418                         }
 419                     });
 420         }
 421 
 422         @Override
 423         public void changedMaximized(final boolean maximized) {
 424             process(new Notification() {
 425                         @Override
 426                         public void execute(final TKStageListener listener) {
 427                             listener.changedMaximized(maximized);
 428                         }
 429                     });
 430         }
 431 
 432 
 433         @Override
 434         public void changedResizable(final boolean resizable) {
 435             process(new Notification() {
 436                         @Override
 437                         public void execute(final TKStageListener listener) {
 438                             listener.changedResizable(resizable);
 439                         }
 440                     });
 441         }
 442 
 443         @Override
 444         public void changedFullscreen(final boolean fs) {
 445             process(new Notification() {
 446                         @Override
 447                         public void execute(final TKStageListener listener) {
 448                             listener.changedFullscreen(fs);
 449                         }
 450                     });
 451         }
 452 
 453         @Override
 454         public void closing() {
 455             process(new Notification() {
 456                         @Override
 457                         public void execute(final TKStageListener listener) {
 458                             listener.closing();
 459                         }
 460                     });
 461         }
 462 
 463         @Override
 464         public void closed() {
 465             process(new Notification() {
 466                         @Override
 467                         public void execute(final TKStageListener listener) {
 468                             listener.closed();
 469                         }
 470                     });
 471         }
 472 
 473         @Override
 474         public void focusUngrab() {
 475             process(new Notification() {
 476                         @Override
 477                         public void execute(final TKStageListener listener) {
 478                             listener.focusUngrab();
 479                         }
 480                     });
 481         }
 482 
 483         private void process(final Notification notification) {
 484             if (hold) {
 485                 queue.offer(notification);
 486                 return;
 487             }
 488 
 489             if (listener != null) {
 490                 notification.execute(listener);
 491             }
 492         }
 493 
 494         private void flush() {
 495             if (listener == null) {
 496                 queue.clear();
 497                 return;
 498             }
 499 
 500             Notification nextNotification = queue.poll();
 501             while (nextNotification != null) {
 502                 nextNotification.execute(listener);
 503                 nextNotification = queue.poll();
 504             }
 505         }
 506 
 507         /**
 508         * Initialize accessibility
 509         */
 510         public void initAccessibleTKStageListener() {
 511             // TODO: Add code later
 512         }
 513 
 514     }
 515 
 516     public void setRTL(boolean b) {
 517     }
 518 }