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 }