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 }