Showing the changes to java/pkg/java/awt (1011 of 18352 files). Show all
Unified · Split
Binary file not shown.
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 1997, 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 java.awt; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Thrown when a serious Abstract Window Toolkit error has occurred. | ||
| 30 | * | ||
| 31 | * @author Arthur van Hoff | ||
| 32 | */ | ||
| 33 | public class AWTError extends Error { | ||
| 34 | |||
| 35 | /* | ||
| 36 | * JDK 1.1 serialVersionUID | ||
| 37 | */ | ||
| 38 | private static final long serialVersionUID = -1819846354050686206L; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Constructs an instance of <code>AWTError</code> with the specified | ||
| 42 | * detail message. | ||
| 43 | * @param msg the detail message. | ||
| 44 | * @since JDK1.0 | ||
| 45 | */ | ||
| 46 | public AWTError(String msg) { | ||
| 47 | super(msg); | ||
| 48 | } | ||
| 49 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,611 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1996, 2011, 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 java.awt; | ||
| 27 | |||
| 28 | import java.util.EventObject; | ||
| 29 | import java.awt.event.*; | ||
| 30 | import java.awt.peer.ComponentPeer; | ||
| 31 | import java.awt.peer.LightweightPeer; | ||
| 32 | import java.lang.reflect.Field; | ||
| 33 | import sun.awt.AWTAccessor; | ||
| 34 | import sun.util.logging.PlatformLogger; | ||
| 35 | |||
| 36 | import java.security.AccessControlContext; | ||
| 37 | import java.security.AccessController; | ||
| 38 | import java.io.ObjectInputStream; | ||
| 39 | import java.io.IOException; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * The root event class for all AWT events. | ||
| 43 | * This class and its subclasses supercede the original | ||
| 44 | * java.awt.Event class. | ||
| 45 | * Subclasses of this root AWTEvent class defined outside of the | ||
| 46 | * java.awt.event package should define event ID values greater than | ||
| 47 | * the value defined by RESERVED_ID_MAX. | ||
| 48 | * <p> | ||
| 49 | * The event masks defined in this class are needed by Component subclasses | ||
| 50 | * which are using Component.enableEvents() to select for event types not | ||
| 51 | * selected by registered listeners. If a listener is registered on a | ||
| 52 | * component, the appropriate event mask is already set internally by the | ||
| 53 | * component. | ||
| 54 | * <p> | ||
| 55 | * The masks are also used to specify to which types of events an | ||
| 56 | * AWTEventListener should listen. The masks are bitwise-ORed together | ||
| 57 | * and passed to Toolkit.addAWTEventListener. | ||
| 58 | * | ||
| 59 | * @see Component#enableEvents | ||
| 60 | * @see Toolkit#addAWTEventListener | ||
| 61 | * | ||
| 62 | * @see java.awt.event.ActionEvent | ||
| 63 | * @see java.awt.event.AdjustmentEvent | ||
| 64 | * @see java.awt.event.ComponentEvent | ||
| 65 | * @see java.awt.event.ContainerEvent | ||
| 66 | * @see java.awt.event.FocusEvent | ||
| 67 | * @see java.awt.event.InputMethodEvent | ||
| 68 | * @see java.awt.event.InvocationEvent | ||
| 69 | * @see java.awt.event.ItemEvent | ||
| 70 | * @see java.awt.event.HierarchyEvent | ||
| 71 | * @see java.awt.event.KeyEvent | ||
| 72 | * @see java.awt.event.MouseEvent | ||
| 73 | * @see java.awt.event.MouseWheelEvent | ||
| 74 | * @see java.awt.event.PaintEvent | ||
| 75 | * @see java.awt.event.TextEvent | ||
| 76 | * @see java.awt.event.WindowEvent | ||
| 77 | * | ||
| 78 | * @author Carl Quinn | ||
| 79 | * @author Amy Fowler | ||
| 80 | * @since 1.1 | ||
| 81 | */ | ||
| 82 | public abstract class AWTEvent extends EventObject { | ||
| 83 | private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.AWTEvent"); | ||
| 84 | private byte bdata[]; | ||
| 85 | |||
| 86 | /** | ||
| 87 | * The event's id. | ||
| 88 | * @serial | ||
| 89 | * @see #getID() | ||
| 90 | * @see #AWTEvent | ||
| 91 | */ | ||
| 92 | protected int id; | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Controls whether or not the event is sent back down to the peer once the | ||
| 96 | * source has processed it - false means it's sent to the peer; true means | ||
| 97 | * it's not. Semantic events always have a 'true' value since they were | ||
| 98 | * generated by the peer in response to a low-level event. | ||
| 99 | * @serial | ||
| 100 | * @see #consume | ||
| 101 | * @see #isConsumed | ||
| 102 | */ | ||
| 103 | protected boolean consumed = false; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * The event's AccessControlContext. | ||
| 107 | */ | ||
| 108 | private transient volatile AccessControlContext acc = | ||
| 109 | AccessController.getContext(); | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Returns the acc this event was constructed with. | ||
| 113 | */ | ||
| 114 | final AccessControlContext getAccessControlContext() { | ||
| 115 | if (acc == null) { | ||
| 116 | throw new SecurityException("AWTEvent is missing AccessControlContext"); | ||
| 117 | } | ||
| 118 | return acc; | ||
| 119 | } | ||
| 120 | |||
| 121 | transient boolean focusManagerIsDispatching = false; | ||
| 122 | transient boolean isPosted; | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Indicates whether this AWTEvent was generated by the system as | ||
| 126 | * opposed to by user code. | ||
| 127 | */ | ||
| 128 | private transient boolean isSystemGenerated; | ||
| 129 | |||
| 130 | /** | ||
| 131 | * The event mask for selecting component events. | ||
| 132 | */ | ||
| 133 | public final static long COMPONENT_EVENT_MASK = 0x01; | ||
| 134 | |||
| 135 | /** | ||
| 136 | * The event mask for selecting container events. | ||
| 137 | */ | ||
| 138 | public final static long CONTAINER_EVENT_MASK = 0x02; | ||
| 139 | |||
| 140 | /** | ||
| 141 | * The event mask for selecting focus events. | ||
| 142 | */ | ||
| 143 | public final static long FOCUS_EVENT_MASK = 0x04; | ||
| 144 | |||
| 145 | /** | ||
| 146 | * The event mask for selecting key events. | ||
| 147 | */ | ||
| 148 | public final static long KEY_EVENT_MASK = 0x08; | ||
| 149 | |||
| 150 | /** | ||
| 151 | * The event mask for selecting mouse events. | ||
| 152 | */ | ||
| 153 | public final static long MOUSE_EVENT_MASK = 0x10; | ||
| 154 | |||
| 155 | /** | ||
| 156 | * The event mask for selecting mouse motion events. | ||
| 157 | */ | ||
| 158 | public final static long MOUSE_MOTION_EVENT_MASK = 0x20; | ||
| 159 | |||
| 160 | /** | ||
| 161 | * The event mask for selecting window events. | ||
| 162 | */ | ||
| 163 | public final static long WINDOW_EVENT_MASK = 0x40; | ||
| 164 | |||
| 165 | /** | ||
| 166 | * The event mask for selecting action events. | ||
| 167 | */ | ||
| 168 | public final static long ACTION_EVENT_MASK = 0x80; | ||
| 169 | |||
| 170 | /** | ||
| 171 | * The event mask for selecting adjustment events. | ||
| 172 | */ | ||
| 173 | public final static long ADJUSTMENT_EVENT_MASK = 0x100; | ||
| 174 | |||
| 175 | /** | ||
| 176 | * The event mask for selecting item events. | ||
| 177 | */ | ||
| 178 | public final static long ITEM_EVENT_MASK = 0x200; | ||
| 179 | |||
| 180 | /** | ||
| 181 | * The event mask for selecting text events. | ||
| 182 | */ | ||
| 183 | public final static long TEXT_EVENT_MASK = 0x400; | ||
| 184 | |||
| 185 | /** | ||
| 186 | * The event mask for selecting input method events. | ||
| 187 | */ | ||
| 188 | public final static long INPUT_METHOD_EVENT_MASK = 0x800; | ||
| 189 | |||
| 190 | /** | ||
| 191 | * The pseudo event mask for enabling input methods. | ||
| 192 | * We're using one bit in the eventMask so we don't need | ||
| 193 | * a separate field inputMethodsEnabled. | ||
| 194 | */ | ||
| 195 | final static long INPUT_METHODS_ENABLED_MASK = 0x1000; | ||
| 196 | |||
| 197 | /** | ||
| 198 | * The event mask for selecting paint events. | ||
| 199 | */ | ||
| 200 | public final static long PAINT_EVENT_MASK = 0x2000; | ||
| 201 | |||
| 202 | /** | ||
| 203 | * The event mask for selecting invocation events. | ||
| 204 | */ | ||
| 205 | public final static long INVOCATION_EVENT_MASK = 0x4000; | ||
| 206 | |||
| 207 | /** | ||
| 208 | * The event mask for selecting hierarchy events. | ||
| 209 | */ | ||
| 210 | public final static long HIERARCHY_EVENT_MASK = 0x8000; | ||
| 211 | |||
| 212 | /** | ||
| 213 | * The event mask for selecting hierarchy bounds events. | ||
| 214 | */ | ||
| 215 | public final static long HIERARCHY_BOUNDS_EVENT_MASK = 0x10000; | ||
| 216 | |||
| 217 | /** | ||
| 218 | * The event mask for selecting mouse wheel events. | ||
| 219 | * @since 1.4 | ||
| 220 | */ | ||
| 221 | public final static long MOUSE_WHEEL_EVENT_MASK = 0x20000; | ||
| 222 | |||
| 223 | /** | ||
| 224 | * The event mask for selecting window state events. | ||
| 225 | * @since 1.4 | ||
| 226 | */ | ||
| 227 | public final static long WINDOW_STATE_EVENT_MASK = 0x40000; | ||
| 228 | |||
| 229 | /** | ||
| 230 | * The event mask for selecting window focus events. | ||
| 231 | * @since 1.4 | ||
| 232 | */ | ||
| 233 | public final static long WINDOW_FOCUS_EVENT_MASK = 0x80000; | ||
| 234 | |||
| 235 | /** | ||
| 236 | * WARNING: there are more mask defined privately. See | ||
| 237 | * SunToolkit.GRAB_EVENT_MASK. | ||
| 238 | */ | ||
| 239 | |||
| 240 | /** | ||
| 241 | * The maximum value for reserved AWT event IDs. Programs defining | ||
| 242 | * their own event IDs should use IDs greater than this value. | ||
| 243 | */ | ||
| 244 | public final static int RESERVED_ID_MAX = 1999; | ||
| 245 | |||
| 246 | // security stuff | ||
| 247 | private static Field inputEvent_CanAccessSystemClipboard_Field = null; | ||
| 248 | |||
| 249 | /* | ||
| 250 | * JDK 1.1 serialVersionUID | ||
| 251 | */ | ||
| 252 | private static final long serialVersionUID = -1825314779160409405L; | ||
| 253 | |||
| 254 | static { | ||
| 255 | /* ensure that the necessary native libraries are loaded */ | ||
| 256 | Toolkit.loadLibraries(); | ||
| 257 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 258 | initIDs(); | ||
| 259 | } | ||
| 260 | AWTAccessor.setAWTEventAccessor( | ||
| 261 | new AWTAccessor.AWTEventAccessor() { | ||
| 262 | public void setPosted(AWTEvent ev) { | ||
| 263 | ev.isPosted = true; | ||
| 264 | } | ||
| 265 | public void setSystemGenerated(AWTEvent ev) { | ||
| 266 | ev.isSystemGenerated = true; | ||
| 267 | } | ||
| 268 | public boolean isSystemGenerated(AWTEvent ev) { | ||
| 269 | return ev.isSystemGenerated; | ||
| 270 | } | ||
| 271 | |||
| 272 | public AccessControlContext getAccessControlContext(AWTEvent ev) { | ||
| 273 | return ev.getAccessControlContext(); | ||
| 274 | } | ||
| 275 | }); | ||
| 276 | } | ||
| 277 | |||
| 278 | private static synchronized Field get_InputEvent_CanAccessSystemClipboard() { | ||
| 279 | if (inputEvent_CanAccessSystemClipboard_Field == null) { | ||
| 280 | inputEvent_CanAccessSystemClipboard_Field = | ||
| 281 | (Field)java.security.AccessController.doPrivileged( | ||
| 282 | new java.security.PrivilegedAction() { | ||
| 283 | public Object run() { | ||
| 284 | Field field = null; | ||
| 285 | try { | ||
| 286 | field = InputEvent.class. | ||
| 287 | getDeclaredField("canAccessSystemClipboard"); | ||
| 288 | field.setAccessible(true); | ||
| 289 | return field; | ||
| 290 | } catch (SecurityException e) { | ||
| 291 | if (log.isLoggable(PlatformLogger.FINE)) { | ||
| 292 | log.fine("AWTEvent.get_InputEvent_CanAccessSystemClipboard() got SecurityException ", e); | ||
| 293 | } | ||
| 294 | } catch (NoSuchFieldException e) { | ||
| 295 | if (log.isLoggable(PlatformLogger.FINE)) { | ||
| 296 | log.fine("AWTEvent.get_InputEvent_CanAccessSystemClipboard() got NoSuchFieldException ", e); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | return null; | ||
| 300 | } | ||
| 301 | }); | ||
| 302 | } | ||
| 303 | |||
| 304 | return inputEvent_CanAccessSystemClipboard_Field; | ||
| 305 | } | ||
| 306 | |||
| 307 | /** | ||
| 308 | * Initialize JNI field and method IDs for fields that may be | ||
| 309 | * accessed from C. | ||
| 310 | */ | ||
| 311 | private static native void initIDs(); | ||
| 312 | |||
| 313 | /** | ||
| 314 | * Constructs an AWTEvent object from the parameters of a 1.0-style event. | ||
| 315 | * @param event the old-style event | ||
| 316 | */ | ||
| 317 | public AWTEvent(Event event) { | ||
| 318 | this(event.target, event.id); | ||
| 319 | } | ||
| 320 | |||
| 321 | /** | ||
| 322 | * Constructs an AWTEvent object with the specified source object and type. | ||
| 323 | * | ||
| 324 | * @param source the object where the event originated | ||
| 325 | * @param id the event type | ||
| 326 | */ | ||
| 327 | public AWTEvent(Object source, int id) { | ||
| 328 | super(source); | ||
| 329 | this.id = id; | ||
| 330 | switch(id) { | ||
| 331 | case ActionEvent.ACTION_PERFORMED: | ||
| 332 | case ItemEvent.ITEM_STATE_CHANGED: | ||
| 333 | case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: | ||
| 334 | case TextEvent.TEXT_VALUE_CHANGED: | ||
| 335 | consumed = true; | ||
| 336 | break; | ||
| 337 | default: | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | /** | ||
| 342 | * Retargets an event to a new source. This method is typically used to | ||
| 343 | * retarget an event to a lightweight child Component of the original | ||
| 344 | * heavyweight source. | ||
| 345 | * <p> | ||
| 346 | * This method is intended to be used only by event targeting subsystems, | ||
| 347 | * such as client-defined KeyboardFocusManagers. It is not for general | ||
| 348 | * client use. | ||
| 349 | * | ||
| 350 | * @param newSource the new Object to which the event should be dispatched | ||
| 351 | * @since 1.4 | ||
| 352 | */ | ||
| 353 | public void setSource(Object newSource) { | ||
| 354 | if (source == newSource) { | ||
| 355 | return; | ||
| 356 | } | ||
| 357 | |||
| 358 | Component comp = null; | ||
| 359 | if (newSource instanceof Component) { | ||
| 360 | comp = (Component)newSource; | ||
| 361 | while (comp != null && comp.peer != null && | ||
| 362 | (comp.peer instanceof LightweightPeer)) { | ||
| 363 | comp = comp.parent; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | synchronized (this) { | ||
| 368 | source = newSource; | ||
| 369 | if (comp != null) { | ||
| 370 | ComponentPeer peer = comp.peer; | ||
| 371 | if (peer != null) { | ||
| 372 | nativeSetSource(peer); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | private native void nativeSetSource(ComponentPeer peer); | ||
| 379 | |||
| 380 | /** | ||
| 381 | * Returns the event type. | ||
| 382 | */ | ||
| 383 | public int getID() { | ||
| 384 | return id; | ||
| 385 | } | ||
| 386 | |||
| 387 | /** | ||
| 388 | * Returns a String representation of this object. | ||
| 389 | */ | ||
| 390 | public String toString() { | ||
| 391 | String srcName = null; | ||
| 392 | if (source instanceof Component) { | ||
| 393 | srcName = ((Component)source).getName(); | ||
| 394 | } else if (source instanceof MenuComponent) { | ||
| 395 | srcName = ((MenuComponent)source).getName(); | ||
| 396 | } | ||
| 397 | return getClass().getName() + "[" + paramString() + "] on " + | ||
| 398 | (srcName != null? srcName : source); | ||
| 399 | } | ||
| 400 | |||
| 401 | /** | ||
| 402 | * Returns a string representing the state of this <code>Event</code>. | ||
| 403 | * This method is intended to be used only for debugging purposes, and the | ||
| 404 | * content and format of the returned string may vary between | ||
| 405 | * implementations. The returned string may be empty but may not be | ||
| 406 | * <code>null</code>. | ||
| 407 | * | ||
| 408 | * @return a string representation of this event | ||
| 409 | */ | ||
| 410 | public String paramString() { | ||
| 411 | return ""; | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Consumes this event, if this event can be consumed. Only low-level, | ||
| 416 | * system events can be consumed | ||
| 417 | */ | ||
| 418 | protected void consume() { | ||
| 419 | switch(id) { | ||
| 420 | case KeyEvent.KEY_PRESSED: | ||
| 421 | case KeyEvent.KEY_RELEASED: | ||
| 422 | case MouseEvent.MOUSE_PRESSED: | ||
| 423 | case MouseEvent.MOUSE_RELEASED: | ||
| 424 | case MouseEvent.MOUSE_MOVED: | ||
| 425 | case MouseEvent.MOUSE_DRAGGED: | ||
| 426 | case MouseEvent.MOUSE_ENTERED: | ||
| 427 | case MouseEvent.MOUSE_EXITED: | ||
| 428 | case MouseEvent.MOUSE_WHEEL: | ||
| 429 | case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: | ||
| 430 | case InputMethodEvent.CARET_POSITION_CHANGED: | ||
| 431 | consumed = true; | ||
| 432 | break; | ||
| 433 | default: | ||
| 434 | // event type cannot be consumed | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | /** | ||
| 439 | * Returns whether this event has been consumed. | ||
| 440 | */ | ||
| 441 | protected boolean isConsumed() { | ||
| 442 | return consumed; | ||
| 443 | } | ||
| 444 | |||
| 445 | /** | ||
| 446 | * Converts a new event to an old one (used for compatibility). | ||
| 447 | * If the new event cannot be converted (because no old equivalent | ||
| 448 | * exists) then this returns null. | ||
| 449 | * | ||
| 450 | * Note: this method is here instead of in each individual new | ||
| 451 | * event class in java.awt.event because we don't want to make | ||
| 452 | * it public and it needs to be called from java.awt. | ||
| 453 | */ | ||
| 454 | Event convertToOld() { | ||
| 455 | Object src = getSource(); | ||
| 456 | int newid = id; | ||
| 457 | |||
| 458 | switch(id) { | ||
| 459 | case KeyEvent.KEY_PRESSED: | ||
| 460 | case KeyEvent.KEY_RELEASED: | ||
| 461 | KeyEvent ke = (KeyEvent)this; | ||
| 462 | if (ke.isActionKey()) { | ||
| 463 | newid = (id == KeyEvent.KEY_PRESSED? | ||
| 464 | Event.KEY_ACTION : Event.KEY_ACTION_RELEASE); | ||
| 465 | } | ||
| 466 | int keyCode = ke.getKeyCode(); | ||
| 467 | if (keyCode == KeyEvent.VK_SHIFT || | ||
| 468 | keyCode == KeyEvent.VK_CONTROL || | ||
| 469 | keyCode == KeyEvent.VK_ALT) { | ||
| 470 | return null; // suppress modifier keys in old event model. | ||
| 471 | } | ||
| 472 | // no mask for button1 existed in old Event - strip it out | ||
| 473 | return new Event(src, ke.getWhen(), newid, 0, 0, | ||
| 474 | Event.getOldEventKey(ke), | ||
| 475 | (ke.getModifiers() & ~InputEvent.BUTTON1_MASK)); | ||
| 476 | |||
| 477 | case MouseEvent.MOUSE_PRESSED: | ||
| 478 | case MouseEvent.MOUSE_RELEASED: | ||
| 479 | case MouseEvent.MOUSE_MOVED: | ||
| 480 | case MouseEvent.MOUSE_DRAGGED: | ||
| 481 | case MouseEvent.MOUSE_ENTERED: | ||
| 482 | case MouseEvent.MOUSE_EXITED: | ||
| 483 | MouseEvent me = (MouseEvent)this; | ||
| 484 | // no mask for button1 existed in old Event - strip it out | ||
| 485 | Event olde = new Event(src, me.getWhen(), newid, | ||
| 486 | me.getX(), me.getY(), 0, | ||
| 487 | (me.getModifiers() & ~InputEvent.BUTTON1_MASK)); | ||
| 488 | olde.clickCount = me.getClickCount(); | ||
| 489 | return olde; | ||
| 490 | |||
| 491 | case FocusEvent.FOCUS_GAINED: | ||
| 492 | return new Event(src, Event.GOT_FOCUS, null); | ||
| 493 | |||
| 494 | case FocusEvent.FOCUS_LOST: | ||
| 495 | return new Event(src, Event.LOST_FOCUS, null); | ||
| 496 | |||
| 497 | case WindowEvent.WINDOW_CLOSING: | ||
| 498 | case WindowEvent.WINDOW_ICONIFIED: | ||
| 499 | case WindowEvent.WINDOW_DEICONIFIED: | ||
| 500 | return new Event(src, newid, null); | ||
| 501 | |||
| 502 | case ComponentEvent.COMPONENT_MOVED: | ||
| 503 | if (src instanceof Frame || src instanceof Dialog) { | ||
| 504 | Point p = ((Component)src).getLocation(); | ||
| 505 | return new Event(src, 0, Event.WINDOW_MOVED, p.x, p.y, 0, 0); | ||
| 506 | } | ||
| 507 | break; | ||
| 508 | |||
| 509 | case ActionEvent.ACTION_PERFORMED: | ||
| 510 | ActionEvent ae = (ActionEvent)this; | ||
| 511 | String cmd; | ||
| 512 | if (src instanceof Button) { | ||
| 513 | cmd = ((Button)src).getLabel(); | ||
| 514 | } else if (src instanceof MenuItem) { | ||
| 515 | cmd = ((MenuItem)src).getLabel(); | ||
| 516 | } else { | ||
| 517 | cmd = ae.getActionCommand(); | ||
| 518 | } | ||
| 519 | return new Event(src, 0, newid, 0, 0, 0, ae.getModifiers(), cmd); | ||
| 520 | |||
| 521 | case ItemEvent.ITEM_STATE_CHANGED: | ||
| 522 | ItemEvent ie = (ItemEvent)this; | ||
| 523 | Object arg; | ||
| 524 | if (src instanceof List) { | ||
| 525 | newid = (ie.getStateChange() == ItemEvent.SELECTED? | ||
| 526 | Event.LIST_SELECT : Event.LIST_DESELECT); | ||
| 527 | arg = ie.getItem(); | ||
| 528 | } else { | ||
| 529 | newid = Event.ACTION_EVENT; | ||
| 530 | if (src instanceof Choice) { | ||
| 531 | arg = ie.getItem(); | ||
| 532 | |||
| 533 | } else { // Checkbox | ||
| 534 | arg = Boolean.valueOf(ie.getStateChange() == ItemEvent.SELECTED); | ||
| 535 | } | ||
| 536 | } | ||
| 537 | return new Event(src, newid, arg); | ||
| 538 | |||
| 539 | case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: | ||
| 540 | AdjustmentEvent aje = (AdjustmentEvent)this; | ||
| 541 | switch(aje.getAdjustmentType()) { | ||
| 542 | case AdjustmentEvent.UNIT_INCREMENT: | ||
| 543 | newid = Event.SCROLL_LINE_DOWN; | ||
| 544 | break; | ||
| 545 | case AdjustmentEvent.UNIT_DECREMENT: | ||
| 546 | newid = Event.SCROLL_LINE_UP; | ||
| 547 | break; | ||
| 548 | case AdjustmentEvent.BLOCK_INCREMENT: | ||
| 549 | newid = Event.SCROLL_PAGE_DOWN; | ||
| 550 | break; | ||
| 551 | case AdjustmentEvent.BLOCK_DECREMENT: | ||
| 552 | newid = Event.SCROLL_PAGE_UP; | ||
| 553 | break; | ||
| 554 | case AdjustmentEvent.TRACK: | ||
| 555 | if (aje.getValueIsAdjusting()) { | ||
| 556 | newid = Event.SCROLL_ABSOLUTE; | ||
| 557 | } | ||
| 558 | else { | ||
| 559 | newid = Event.SCROLL_END; | ||
| 560 | } | ||
| 561 | break; | ||
| 562 | default: | ||
| 563 | return null; | ||
| 564 | } | ||
| 565 | return new Event(src, newid, Integer.valueOf(aje.getValue())); | ||
| 566 | |||
| 567 | default: | ||
| 568 | } | ||
| 569 | return null; | ||
| 570 | } | ||
| 571 | |||
| 572 | /** | ||
| 573 | * Copies all private data from this event into that. | ||
| 574 | * Space is allocated for the copied data that will be | ||
| 575 | * freed when the that is finalized. Upon completion, | ||
| 576 | * this event is not changed. | ||
| 577 | */ | ||
| 578 | void copyPrivateDataInto(AWTEvent that) { | ||
| 579 | that.bdata = this.bdata; | ||
| 580 | // Copy canAccessSystemClipboard value from this into that. | ||
| 581 | if (this instanceof InputEvent && that instanceof InputEvent) { | ||
| 582 | Field field = get_InputEvent_CanAccessSystemClipboard(); | ||
| 583 | if (field != null) { | ||
| 584 | try { | ||
| 585 | boolean b = field.getBoolean(this); | ||
| 586 | field.setBoolean(that, b); | ||
| 587 | } catch(IllegalAccessException e) { | ||
| 588 | if (log.isLoggable(PlatformLogger.FINE)) { | ||
| 589 | log.fine("AWTEvent.copyPrivateDataInto() got IllegalAccessException ", e); | ||
| 590 | } | ||
| 591 | } | ||
| 592 | } | ||
| 593 | } | ||
| 594 | that.isSystemGenerated = this.isSystemGenerated; | ||
| 595 | } | ||
| 596 | |||
| 597 | void dispatched() { | ||
| 598 | if (this instanceof InputEvent) { | ||
| 599 | Field field = get_InputEvent_CanAccessSystemClipboard(); | ||
| 600 | if (field != null) { | ||
| 601 | try { | ||
| 602 | field.setBoolean(this, false); | ||
| 603 | } catch(IllegalAccessException e) { | ||
| 604 | if (log.isLoggable(PlatformLogger.FINE)) { | ||
| 605 | log.fine("AWTEvent.dispatched() got IllegalAccessException ", e); | ||
| 606 | } | ||
| 607 | } | ||
| 608 | } | ||
| 609 | } | ||
| 610 | } | ||
| 611 | } // class AWTEvent | ||
Binary file not shown.
| @@ -0,0 +1,1032 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1996, 2006, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.event.*; | ||
| 28 | import java.lang.reflect.Array; | ||
| 29 | import java.util.EventListener; | ||
| 30 | import java.io.Serializable; | ||
| 31 | import java.io.ObjectOutputStream; | ||
| 32 | import java.io.IOException; | ||
| 33 | import java.util.EventListener; | ||
| 34 | |||
| 35 | |||
| 36 | /** | ||
| 37 | * {@code AWTEventMulticaster} implements efficient and thread-safe multi-cast | ||
| 38 | * event dispatching for the AWT events defined in the {@code java.awt.event} | ||
| 39 | * package. | ||
| 40 | * <p> | ||
| 41 | * The following example illustrates how to use this class: | ||
| 42 | * | ||
| 43 | * <pre><code> | ||
| 44 | * public myComponent extends Component { | ||
| 45 | * ActionListener actionListener = null; | ||
| 46 | * | ||
| 47 | * public synchronized void addActionListener(ActionListener l) { | ||
| 48 | * actionListener = AWTEventMulticaster.add(actionListener, l); | ||
| 49 | * } | ||
| 50 | * public synchronized void removeActionListener(ActionListener l) { | ||
| 51 | * actionListener = AWTEventMulticaster.remove(actionListener, l); | ||
| 52 | * } | ||
| 53 | * public void processEvent(AWTEvent e) { | ||
| 54 | * // when event occurs which causes "action" semantic | ||
| 55 | * ActionListener listener = actionListener; | ||
| 56 | * if (listener != null) { | ||
| 57 | * listener.actionPerformed(new ActionEvent()); | ||
| 58 | * } | ||
| 59 | * } | ||
| 60 | * } | ||
| 61 | * </code></pre> | ||
| 62 | * The important point to note is the first argument to the {@code | ||
| 63 | * add} and {@code remove} methods is the field maintaining the | ||
| 64 | * listeners. In addition you must assign the result of the {@code add} | ||
| 65 | * and {@code remove} methods to the field maintaining the listeners. | ||
| 66 | * <p> | ||
| 67 | * {@code AWTEventMulticaster} is implemented as a pair of {@code | ||
| 68 | * EventListeners} that are set at construction time. {@code | ||
| 69 | * AWTEventMulticaster} is immutable. The {@code add} and {@code | ||
| 70 | * remove} methods do not alter {@code AWTEventMulticaster} in | ||
| 71 | * anyway. If necessary, a new {@code AWTEventMulticaster} is | ||
| 72 | * created. In this way it is safe to add and remove listeners during | ||
| 73 | * the process of an event dispatching. However, event listeners | ||
| 74 | * added during the process of an event dispatch operation are not | ||
| 75 | * notified of the event currently being dispatched. | ||
| 76 | * <p> | ||
| 77 | * All of the {@code add} methods allow {@code null} arguments. If the | ||
| 78 | * first argument is {@code null}, the second argument is returned. If | ||
| 79 | * the first argument is not {@code null} and the second argument is | ||
| 80 | * {@code null}, the first argument is returned. If both arguments are | ||
| 81 | * {@code non-null}, a new {@code AWTEventMulticaster} is created using | ||
| 82 | * the two arguments and returned. | ||
| 83 | * <p> | ||
| 84 | * For the {@code remove} methods that take two arguments, the following is | ||
| 85 | * returned: | ||
| 86 | * <ul> | ||
| 87 | * <li>{@code null}, if the first argument is {@code null}, or | ||
| 88 | * the arguments are equal, by way of {@code ==}. | ||
| 89 | * <li>the first argument, if the first argument is not an instance of | ||
| 90 | * {@code AWTEventMulticaster}. | ||
| 91 | * <li>result of invoking {@code remove(EventListener)} on the | ||
| 92 | * first argument, supplying the second argument to the | ||
| 93 | * {@code remove(EventListener)} method. | ||
| 94 | * </ul> | ||
| 95 | * <p>Swing makes use of | ||
| 96 | * {@link javax.swing.event.EventListenerList EventListenerList} for | ||
| 97 | * similar logic. Refer to it for details. | ||
| 98 | * | ||
| 99 | * @see javax.swing.event.EventListenerList | ||
| 100 | * | ||
| 101 | * @author John Rose | ||
| 102 | * @author Amy Fowler | ||
| 103 | * @since 1.1 | ||
| 104 | */ | ||
| 105 | |||
| 106 | public class AWTEventMulticaster implements | ||
| 107 | ComponentListener, ContainerListener, FocusListener, KeyListener, | ||
| 108 | MouseListener, MouseMotionListener, WindowListener, WindowFocusListener, | ||
| 109 | WindowStateListener, ActionListener, ItemListener, AdjustmentListener, | ||
| 110 | TextListener, InputMethodListener, HierarchyListener, | ||
| 111 | HierarchyBoundsListener, MouseWheelListener { | ||
| 112 | |||
| 113 | protected final EventListener a, b; | ||
| 114 | |||
| 115 | /** | ||
| 116 | * Creates an event multicaster instance which chains listener-a | ||
| 117 | * with listener-b. Input parameters <code>a</code> and <code>b</code> | ||
| 118 | * should not be <code>null</code>, though implementations may vary in | ||
| 119 | * choosing whether or not to throw <code>NullPointerException</code> | ||
| 120 | * in that case. | ||
| 121 | * @param a listener-a | ||
| 122 | * @param b listener-b | ||
| 123 | */ | ||
| 124 | protected AWTEventMulticaster(EventListener a, EventListener b) { | ||
| 125 | this.a = a; this.b = b; | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * Removes a listener from this multicaster. | ||
| 130 | * <p> | ||
| 131 | * The returned multicaster contains all the listeners in this | ||
| 132 | * multicaster with the exception of all occurrences of {@code oldl}. | ||
| 133 | * If the resulting multicaster contains only one regular listener | ||
| 134 | * the regular listener may be returned. If the resulting multicaster | ||
| 135 | * is empty, then {@code null} may be returned instead. | ||
| 136 | * <p> | ||
| 137 | * No exception is thrown if {@code oldl} is {@code null}. | ||
| 138 | * | ||
| 139 | * @param oldl the listener to be removed | ||
| 140 | * @return resulting listener | ||
| 141 | */ | ||
| 142 | protected EventListener remove(EventListener oldl) { | ||
| 143 | if (oldl == a) return b; | ||
| 144 | if (oldl == b) return a; | ||
| 145 | EventListener a2 = removeInternal(a, oldl); | ||
| 146 | EventListener b2 = removeInternal(b, oldl); | ||
| 147 | if (a2 == a && b2 == b) { | ||
| 148 | return this; // it's not here | ||
| 149 | } | ||
| 150 | return addInternal(a2, b2); | ||
| 151 | } | ||
| 152 | |||
| 153 | /** | ||
| 154 | * Handles the componentResized event by invoking the | ||
| 155 | * componentResized methods on listener-a and listener-b. | ||
| 156 | * @param e the component event | ||
| 157 | */ | ||
| 158 | public void componentResized(ComponentEvent e) { | ||
| 159 | ((ComponentListener)a).componentResized(e); | ||
| 160 | ((ComponentListener)b).componentResized(e); | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Handles the componentMoved event by invoking the | ||
| 165 | * componentMoved methods on listener-a and listener-b. | ||
| 166 | * @param e the component event | ||
| 167 | */ | ||
| 168 | public void componentMoved(ComponentEvent e) { | ||
| 169 | ((ComponentListener)a).componentMoved(e); | ||
| 170 | ((ComponentListener)b).componentMoved(e); | ||
| 171 | } | ||
| 172 | |||
| 173 | /** | ||
| 174 | * Handles the componentShown event by invoking the | ||
| 175 | * componentShown methods on listener-a and listener-b. | ||
| 176 | * @param e the component event | ||
| 177 | */ | ||
| 178 | public void componentShown(ComponentEvent e) { | ||
| 179 | ((ComponentListener)a).componentShown(e); | ||
| 180 | ((ComponentListener)b).componentShown(e); | ||
| 181 | } | ||
| 182 | |||
| 183 | /** | ||
| 184 | * Handles the componentHidden event by invoking the | ||
| 185 | * componentHidden methods on listener-a and listener-b. | ||
| 186 | * @param e the component event | ||
| 187 | */ | ||
| 188 | public void componentHidden(ComponentEvent e) { | ||
| 189 | ((ComponentListener)a).componentHidden(e); | ||
| 190 | ((ComponentListener)b).componentHidden(e); | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * Handles the componentAdded container event by invoking the | ||
| 195 | * componentAdded methods on listener-a and listener-b. | ||
| 196 | * @param e the component event | ||
| 197 | */ | ||
| 198 | public void componentAdded(ContainerEvent e) { | ||
| 199 | ((ContainerListener)a).componentAdded(e); | ||
| 200 | ((ContainerListener)b).componentAdded(e); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Handles the componentRemoved container event by invoking the | ||
| 205 | * componentRemoved methods on listener-a and listener-b. | ||
| 206 | * @param e the component event | ||
| 207 | */ | ||
| 208 | public void componentRemoved(ContainerEvent e) { | ||
| 209 | ((ContainerListener)a).componentRemoved(e); | ||
| 210 | ((ContainerListener)b).componentRemoved(e); | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * Handles the focusGained event by invoking the | ||
| 215 | * focusGained methods on listener-a and listener-b. | ||
| 216 | * @param e the focus event | ||
| 217 | */ | ||
| 218 | public void focusGained(FocusEvent e) { | ||
| 219 | ((FocusListener)a).focusGained(e); | ||
| 220 | ((FocusListener)b).focusGained(e); | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * Handles the focusLost event by invoking the | ||
| 225 | * focusLost methods on listener-a and listener-b. | ||
| 226 | * @param e the focus event | ||
| 227 | */ | ||
| 228 | public void focusLost(FocusEvent e) { | ||
| 229 | ((FocusListener)a).focusLost(e); | ||
| 230 | ((FocusListener)b).focusLost(e); | ||
| 231 | } | ||
| 232 | |||
| 233 | /** | ||
| 234 | * Handles the keyTyped event by invoking the | ||
| 235 | * keyTyped methods on listener-a and listener-b. | ||
| 236 | * @param e the key event | ||
| 237 | */ | ||
| 238 | public void keyTyped(KeyEvent e) { | ||
| 239 | ((KeyListener)a).keyTyped(e); | ||
| 240 | ((KeyListener)b).keyTyped(e); | ||
| 241 | } | ||
| 242 | |||
| 243 | /** | ||
| 244 | * Handles the keyPressed event by invoking the | ||
| 245 | * keyPressed methods on listener-a and listener-b. | ||
| 246 | * @param e the key event | ||
| 247 | */ | ||
| 248 | public void keyPressed(KeyEvent e) { | ||
| 249 | ((KeyListener)a).keyPressed(e); | ||
| 250 | ((KeyListener)b).keyPressed(e); | ||
| 251 | } | ||
| 252 | |||
| 253 | /** | ||
| 254 | * Handles the keyReleased event by invoking the | ||
| 255 | * keyReleased methods on listener-a and listener-b. | ||
| 256 | * @param e the key event | ||
| 257 | */ | ||
| 258 | public void keyReleased(KeyEvent e) { | ||
| 259 | ((KeyListener)a).keyReleased(e); | ||
| 260 | ((KeyListener)b).keyReleased(e); | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * Handles the mouseClicked event by invoking the | ||
| 265 | * mouseClicked methods on listener-a and listener-b. | ||
| 266 | * @param e the mouse event | ||
| 267 | */ | ||
| 268 | public void mouseClicked(MouseEvent e) { | ||
| 269 | ((MouseListener)a).mouseClicked(e); | ||
| 270 | ((MouseListener)b).mouseClicked(e); | ||
| 271 | } | ||
| 272 | |||
| 273 | /** | ||
| 274 | * Handles the mousePressed event by invoking the | ||
| 275 | * mousePressed methods on listener-a and listener-b. | ||
| 276 | * @param e the mouse event | ||
| 277 | */ | ||
| 278 | public void mousePressed(MouseEvent e) { | ||
| 279 | ((MouseListener)a).mousePressed(e); | ||
| 280 | ((MouseListener)b).mousePressed(e); | ||
| 281 | } | ||
| 282 | |||
| 283 | /** | ||
| 284 | * Handles the mouseReleased event by invoking the | ||
| 285 | * mouseReleased methods on listener-a and listener-b. | ||
| 286 | * @param e the mouse event | ||
| 287 | */ | ||
| 288 | public void mouseReleased(MouseEvent e) { | ||
| 289 | ((MouseListener)a).mouseReleased(e); | ||
| 290 | ((MouseListener)b).mouseReleased(e); | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * Handles the mouseEntered event by invoking the | ||
| 295 | * mouseEntered methods on listener-a and listener-b. | ||
| 296 | * @param e the mouse event | ||
| 297 | */ | ||
| 298 | public void mouseEntered(MouseEvent e) { | ||
| 299 | ((MouseListener)a).mouseEntered(e); | ||
| 300 | ((MouseListener)b).mouseEntered(e); | ||
| 301 | } | ||
| 302 | |||
| 303 | /** | ||
| 304 | * Handles the mouseExited event by invoking the | ||
| 305 | * mouseExited methods on listener-a and listener-b. | ||
| 306 | * @param e the mouse event | ||
| 307 | */ | ||
| 308 | public void mouseExited(MouseEvent e) { | ||
| 309 | ((MouseListener)a).mouseExited(e); | ||
| 310 | ((MouseListener)b).mouseExited(e); | ||
| 311 | } | ||
| 312 | |||
| 313 | /** | ||
| 314 | * Handles the mouseDragged event by invoking the | ||
| 315 | * mouseDragged methods on listener-a and listener-b. | ||
| 316 | * @param e the mouse event | ||
| 317 | */ | ||
| 318 | public void mouseDragged(MouseEvent e) { | ||
| 319 | ((MouseMotionListener)a).mouseDragged(e); | ||
| 320 | ((MouseMotionListener)b).mouseDragged(e); | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * Handles the mouseMoved event by invoking the | ||
| 325 | * mouseMoved methods on listener-a and listener-b. | ||
| 326 | * @param e the mouse event | ||
| 327 | */ | ||
| 328 | public void mouseMoved(MouseEvent e) { | ||
| 329 | ((MouseMotionListener)a).mouseMoved(e); | ||
| 330 | ((MouseMotionListener)b).mouseMoved(e); | ||
| 331 | } | ||
| 332 | |||
| 333 | /** | ||
| 334 | * Handles the windowOpened event by invoking the | ||
| 335 | * windowOpened methods on listener-a and listener-b. | ||
| 336 | * @param e the window event | ||
| 337 | */ | ||
| 338 | public void windowOpened(WindowEvent e) { | ||
| 339 | ((WindowListener)a).windowOpened(e); | ||
| 340 | ((WindowListener)b).windowOpened(e); | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Handles the windowClosing event by invoking the | ||
| 345 | * windowClosing methods on listener-a and listener-b. | ||
| 346 | * @param e the window event | ||
| 347 | */ | ||
| 348 | public void windowClosing(WindowEvent e) { | ||
| 349 | ((WindowListener)a).windowClosing(e); | ||
| 350 | ((WindowListener)b).windowClosing(e); | ||
| 351 | } | ||
| 352 | |||
| 353 | /** | ||
| 354 | * Handles the windowClosed event by invoking the | ||
| 355 | * windowClosed methods on listener-a and listener-b. | ||
| 356 | * @param e the window event | ||
| 357 | */ | ||
| 358 | public void windowClosed(WindowEvent e) { | ||
| 359 | ((WindowListener)a).windowClosed(e); | ||
| 360 | ((WindowListener)b).windowClosed(e); | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Handles the windowIconified event by invoking the | ||
| 365 | * windowIconified methods on listener-a and listener-b. | ||
| 366 | * @param e the window event | ||
| 367 | */ | ||
| 368 | public void windowIconified(WindowEvent e) { | ||
| 369 | ((WindowListener)a).windowIconified(e); | ||
| 370 | ((WindowListener)b).windowIconified(e); | ||
| 371 | } | ||
| 372 | |||
| 373 | /** | ||
| 374 | * Handles the windowDeiconfied event by invoking the | ||
| 375 | * windowDeiconified methods on listener-a and listener-b. | ||
| 376 | * @param e the window event | ||
| 377 | */ | ||
| 378 | public void windowDeiconified(WindowEvent e) { | ||
| 379 | ((WindowListener)a).windowDeiconified(e); | ||
| 380 | ((WindowListener)b).windowDeiconified(e); | ||
| 381 | } | ||
| 382 | |||
| 383 | /** | ||
| 384 | * Handles the windowActivated event by invoking the | ||
| 385 | * windowActivated methods on listener-a and listener-b. | ||
| 386 | * @param e the window event | ||
| 387 | */ | ||
| 388 | public void windowActivated(WindowEvent e) { | ||
| 389 | ((WindowListener)a).windowActivated(e); | ||
| 390 | ((WindowListener)b).windowActivated(e); | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * Handles the windowDeactivated event by invoking the | ||
| 395 | * windowDeactivated methods on listener-a and listener-b. | ||
| 396 | * @param e the window event | ||
| 397 | */ | ||
| 398 | public void windowDeactivated(WindowEvent e) { | ||
| 399 | ((WindowListener)a).windowDeactivated(e); | ||
| 400 | ((WindowListener)b).windowDeactivated(e); | ||
| 401 | } | ||
| 402 | |||
| 403 | /** | ||
| 404 | * Handles the windowStateChanged event by invoking the | ||
| 405 | * windowStateChanged methods on listener-a and listener-b. | ||
| 406 | * @param e the window event | ||
| 407 | * @since 1.4 | ||
| 408 | */ | ||
| 409 | public void windowStateChanged(WindowEvent e) { | ||
| 410 | ((WindowStateListener)a).windowStateChanged(e); | ||
| 411 | ((WindowStateListener)b).windowStateChanged(e); | ||
| 412 | } | ||
| 413 | |||
| 414 | |||
| 415 | /** | ||
| 416 | * Handles the windowGainedFocus event by invoking the windowGainedFocus | ||
| 417 | * methods on listener-a and listener-b. | ||
| 418 | * @param e the window event | ||
| 419 | * @since 1.4 | ||
| 420 | */ | ||
| 421 | public void windowGainedFocus(WindowEvent e) { | ||
| 422 | ((WindowFocusListener)a).windowGainedFocus(e); | ||
| 423 | ((WindowFocusListener)b).windowGainedFocus(e); | ||
| 424 | } | ||
| 425 | |||
| 426 | /** | ||
| 427 | * Handles the windowLostFocus event by invoking the windowLostFocus | ||
| 428 | * methods on listener-a and listener-b. | ||
| 429 | * @param e the window event | ||
| 430 | * @since 1.4 | ||
| 431 | */ | ||
| 432 | public void windowLostFocus(WindowEvent e) { | ||
| 433 | ((WindowFocusListener)a).windowLostFocus(e); | ||
| 434 | ((WindowFocusListener)b).windowLostFocus(e); | ||
| 435 | } | ||
| 436 | |||
| 437 | /** | ||
| 438 | * Handles the actionPerformed event by invoking the | ||
| 439 | * actionPerformed methods on listener-a and listener-b. | ||
| 440 | * @param e the action event | ||
| 441 | */ | ||
| 442 | public void actionPerformed(ActionEvent e) { | ||
| 443 | ((ActionListener)a).actionPerformed(e); | ||
| 444 | ((ActionListener)b).actionPerformed(e); | ||
| 445 | } | ||
| 446 | |||
| 447 | /** | ||
| 448 | * Handles the itemStateChanged event by invoking the | ||
| 449 | * itemStateChanged methods on listener-a and listener-b. | ||
| 450 | * @param e the item event | ||
| 451 | */ | ||
| 452 | public void itemStateChanged(ItemEvent e) { | ||
| 453 | ((ItemListener)a).itemStateChanged(e); | ||
| 454 | ((ItemListener)b).itemStateChanged(e); | ||
| 455 | } | ||
| 456 | |||
| 457 | /** | ||
| 458 | * Handles the adjustmentValueChanged event by invoking the | ||
| 459 | * adjustmentValueChanged methods on listener-a and listener-b. | ||
| 460 | * @param e the adjustment event | ||
| 461 | */ | ||
| 462 | public void adjustmentValueChanged(AdjustmentEvent e) { | ||
| 463 | ((AdjustmentListener)a).adjustmentValueChanged(e); | ||
| 464 | ((AdjustmentListener)b).adjustmentValueChanged(e); | ||
| 465 | } | ||
| 466 | public void textValueChanged(TextEvent e) { | ||
| 467 | ((TextListener)a).textValueChanged(e); | ||
| 468 | ((TextListener)b).textValueChanged(e); | ||
| 469 | } | ||
| 470 | |||
| 471 | /** | ||
| 472 | * Handles the inputMethodTextChanged event by invoking the | ||
| 473 | * inputMethodTextChanged methods on listener-a and listener-b. | ||
| 474 | * @param e the item event | ||
| 475 | */ | ||
| 476 | public void inputMethodTextChanged(InputMethodEvent e) { | ||
| 477 | ((InputMethodListener)a).inputMethodTextChanged(e); | ||
| 478 | ((InputMethodListener)b).inputMethodTextChanged(e); | ||
| 479 | } | ||
| 480 | |||
| 481 | /** | ||
| 482 | * Handles the caretPositionChanged event by invoking the | ||
| 483 | * caretPositionChanged methods on listener-a and listener-b. | ||
| 484 | * @param e the item event | ||
| 485 | */ | ||
| 486 | public void caretPositionChanged(InputMethodEvent e) { | ||
| 487 | ((InputMethodListener)a).caretPositionChanged(e); | ||
| 488 | ((InputMethodListener)b).caretPositionChanged(e); | ||
| 489 | } | ||
| 490 | |||
| 491 | /** | ||
| 492 | * Handles the hierarchyChanged event by invoking the | ||
| 493 | * hierarchyChanged methods on listener-a and listener-b. | ||
| 494 | * @param e the item event | ||
| 495 | * @since 1.3 | ||
| 496 | */ | ||
| 497 | public void hierarchyChanged(HierarchyEvent e) { | ||
| 498 | ((HierarchyListener)a).hierarchyChanged(e); | ||
| 499 | ((HierarchyListener)b).hierarchyChanged(e); | ||
| 500 | } | ||
| 501 | |||
| 502 | /** | ||
| 503 | * Handles the ancestorMoved event by invoking the | ||
| 504 | * ancestorMoved methods on listener-a and listener-b. | ||
| 505 | * @param e the item event | ||
| 506 | * @since 1.3 | ||
| 507 | */ | ||
| 508 | public void ancestorMoved(HierarchyEvent e) { | ||
| 509 | ((HierarchyBoundsListener)a).ancestorMoved(e); | ||
| 510 | ((HierarchyBoundsListener)b).ancestorMoved(e); | ||
| 511 | } | ||
| 512 | |||
| 513 | /** | ||
| 514 | * Handles the ancestorResized event by invoking the | ||
| 515 | * ancestorResized methods on listener-a and listener-b. | ||
| 516 | * @param e the item event | ||
| 517 | * @since 1.3 | ||
| 518 | */ | ||
| 519 | public void ancestorResized(HierarchyEvent e) { | ||
| 520 | ((HierarchyBoundsListener)a).ancestorResized(e); | ||
| 521 | ((HierarchyBoundsListener)b).ancestorResized(e); | ||
| 522 | } | ||
| 523 | |||
| 524 | /** | ||
| 525 | * Handles the mouseWheelMoved event by invoking the | ||
| 526 | * mouseWheelMoved methods on listener-a and listener-b. | ||
| 527 | * @param e the mouse event | ||
| 528 | * @since 1.4 | ||
| 529 | */ | ||
| 530 | public void mouseWheelMoved(MouseWheelEvent e) { | ||
| 531 | ((MouseWheelListener)a).mouseWheelMoved(e); | ||
| 532 | ((MouseWheelListener)b).mouseWheelMoved(e); | ||
| 533 | } | ||
| 534 | |||
| 535 | /** | ||
| 536 | * Adds component-listener-a with component-listener-b and | ||
| 537 | * returns the resulting multicast listener. | ||
| 538 | * @param a component-listener-a | ||
| 539 | * @param b component-listener-b | ||
| 540 | */ | ||
| 541 | public static ComponentListener add(ComponentListener a, ComponentListener b) { | ||
| 542 | return (ComponentListener)addInternal(a, b); | ||
| 543 | } | ||
| 544 | |||
| 545 | /** | ||
| 546 | * Adds container-listener-a with container-listener-b and | ||
| 547 | * returns the resulting multicast listener. | ||
| 548 | * @param a container-listener-a | ||
| 549 | * @param b container-listener-b | ||
| 550 | */ | ||
| 551 | public static ContainerListener add(ContainerListener a, ContainerListener b) { | ||
| 552 | return (ContainerListener)addInternal(a, b); | ||
| 553 | } | ||
| 554 | |||
| 555 | /** | ||
| 556 | * Adds focus-listener-a with focus-listener-b and | ||
| 557 | * returns the resulting multicast listener. | ||
| 558 | * @param a focus-listener-a | ||
| 559 | * @param b focus-listener-b | ||
| 560 | */ | ||
| 561 | public static FocusListener add(FocusListener a, FocusListener b) { | ||
| 562 | return (FocusListener)addInternal(a, b); | ||
| 563 | } | ||
| 564 | |||
| 565 | /** | ||
| 566 | * Adds key-listener-a with key-listener-b and | ||
| 567 | * returns the resulting multicast listener. | ||
| 568 | * @param a key-listener-a | ||
| 569 | * @param b key-listener-b | ||
| 570 | */ | ||
| 571 | public static KeyListener add(KeyListener a, KeyListener b) { | ||
| 572 | return (KeyListener)addInternal(a, b); | ||
| 573 | } | ||
| 574 | |||
| 575 | /** | ||
| 576 | * Adds mouse-listener-a with mouse-listener-b and | ||
| 577 | * returns the resulting multicast listener. | ||
| 578 | * @param a mouse-listener-a | ||
| 579 | * @param b mouse-listener-b | ||
| 580 | */ | ||
| 581 | public static MouseListener add(MouseListener a, MouseListener b) { | ||
| 582 | return (MouseListener)addInternal(a, b); | ||
| 583 | } | ||
| 584 | |||
| 585 | /** | ||
| 586 | * Adds mouse-motion-listener-a with mouse-motion-listener-b and | ||
| 587 | * returns the resulting multicast listener. | ||
| 588 | * @param a mouse-motion-listener-a | ||
| 589 | * @param b mouse-motion-listener-b | ||
| 590 | */ | ||
| 591 | public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) { | ||
| 592 | return (MouseMotionListener)addInternal(a, b); | ||
| 593 | } | ||
| 594 | |||
| 595 | /** | ||
| 596 | * Adds window-listener-a with window-listener-b and | ||
| 597 | * returns the resulting multicast listener. | ||
| 598 | * @param a window-listener-a | ||
| 599 | * @param b window-listener-b | ||
| 600 | */ | ||
| 601 | public static WindowListener add(WindowListener a, WindowListener b) { | ||
| 602 | return (WindowListener)addInternal(a, b); | ||
| 603 | } | ||
| 604 | |||
| 605 | /** | ||
| 606 | * Adds window-state-listener-a with window-state-listener-b | ||
| 607 | * and returns the resulting multicast listener. | ||
| 608 | * @param a window-state-listener-a | ||
| 609 | * @param b window-state-listener-b | ||
| 610 | * @since 1.4 | ||
| 611 | */ | ||
| 612 | public static WindowStateListener add(WindowStateListener a, | ||
| 613 | WindowStateListener b) { | ||
| 614 | return (WindowStateListener)addInternal(a, b); | ||
| 615 | } | ||
| 616 | |||
| 617 | /** | ||
| 618 | * Adds window-focus-listener-a with window-focus-listener-b | ||
| 619 | * and returns the resulting multicast listener. | ||
| 620 | * @param a window-focus-listener-a | ||
| 621 | * @param b window-focus-listener-b | ||
| 622 | * @since 1.4 | ||
| 623 | */ | ||
| 624 | public static WindowFocusListener add(WindowFocusListener a, | ||
| 625 | WindowFocusListener b) { | ||
| 626 | return (WindowFocusListener)addInternal(a, b); | ||
| 627 | } | ||
| 628 | |||
| 629 | /** | ||
| 630 | * Adds action-listener-a with action-listener-b and | ||
| 631 | * returns the resulting multicast listener. | ||
| 632 | * @param a action-listener-a | ||
| 633 | * @param b action-listener-b | ||
| 634 | */ | ||
| 635 | public static ActionListener add(ActionListener a, ActionListener b) { | ||
| 636 | return (ActionListener)addInternal(a, b); | ||
| 637 | } | ||
| 638 | |||
| 639 | /** | ||
| 640 | * Adds item-listener-a with item-listener-b and | ||
| 641 | * returns the resulting multicast listener. | ||
| 642 | * @param a item-listener-a | ||
| 643 | * @param b item-listener-b | ||
| 644 | */ | ||
| 645 | public static ItemListener add(ItemListener a, ItemListener b) { | ||
| 646 | return (ItemListener)addInternal(a, b); | ||
| 647 | } | ||
| 648 | |||
| 649 | /** | ||
| 650 | * Adds adjustment-listener-a with adjustment-listener-b and | ||
| 651 | * returns the resulting multicast listener. | ||
| 652 | * @param a adjustment-listener-a | ||
| 653 | * @param b adjustment-listener-b | ||
| 654 | */ | ||
| 655 | public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) { | ||
| 656 | return (AdjustmentListener)addInternal(a, b); | ||
| 657 | } | ||
| 658 | public static TextListener add(TextListener a, TextListener b) { | ||
| 659 | return (TextListener)addInternal(a, b); | ||
| 660 | } | ||
| 661 | |||
| 662 | /** | ||
| 663 | * Adds input-method-listener-a with input-method-listener-b and | ||
| 664 | * returns the resulting multicast listener. | ||
| 665 | * @param a input-method-listener-a | ||
| 666 | * @param b input-method-listener-b | ||
| 667 | */ | ||
| 668 | public static InputMethodListener add(InputMethodListener a, InputMethodListener b) { | ||
| 669 | return (InputMethodListener)addInternal(a, b); | ||
| 670 | } | ||
| 671 | |||
| 672 | /** | ||
| 673 | * Adds hierarchy-listener-a with hierarchy-listener-b and | ||
| 674 | * returns the resulting multicast listener. | ||
| 675 | * @param a hierarchy-listener-a | ||
| 676 | * @param b hierarchy-listener-b | ||
| 677 | * @since 1.3 | ||
| 678 | */ | ||
| 679 | public static HierarchyListener add(HierarchyListener a, HierarchyListener b) { | ||
| 680 | return (HierarchyListener)addInternal(a, b); | ||
| 681 | } | ||
| 682 | |||
| 683 | /** | ||
| 684 | * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and | ||
| 685 | * returns the resulting multicast listener. | ||
| 686 | * @param a hierarchy-bounds-listener-a | ||
| 687 | * @param b hierarchy-bounds-listener-b | ||
| 688 | * @since 1.3 | ||
| 689 | */ | ||
| 690 | public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) { | ||
| 691 | return (HierarchyBoundsListener)addInternal(a, b); | ||
| 692 | } | ||
| 693 | |||
| 694 | /** | ||
| 695 | * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and | ||
| 696 | * returns the resulting multicast listener. | ||
| 697 | * @param a mouse-wheel-listener-a | ||
| 698 | * @param b mouse-wheel-listener-b | ||
| 699 | * @since 1.4 | ||
| 700 | */ | ||
| 701 | public static MouseWheelListener add(MouseWheelListener a, | ||
| 702 | MouseWheelListener b) { | ||
| 703 | return (MouseWheelListener)addInternal(a, b); | ||
| 704 | } | ||
| 705 | |||
| 706 | /** | ||
| 707 | * Removes the old component-listener from component-listener-l and | ||
| 708 | * returns the resulting multicast listener. | ||
| 709 | * @param l component-listener-l | ||
| 710 | * @param oldl the component-listener being removed | ||
| 711 | */ | ||
| 712 | public static ComponentListener remove(ComponentListener l, ComponentListener oldl) { | ||
| 713 | return (ComponentListener) removeInternal(l, oldl); | ||
| 714 | } | ||
| 715 | |||
| 716 | /** | ||
| 717 | * Removes the old container-listener from container-listener-l and | ||
| 718 | * returns the resulting multicast listener. | ||
| 719 | * @param l container-listener-l | ||
| 720 | * @param oldl the container-listener being removed | ||
| 721 | */ | ||
| 722 | public static ContainerListener remove(ContainerListener l, ContainerListener oldl) { | ||
| 723 | return (ContainerListener) removeInternal(l, oldl); | ||
| 724 | } | ||
| 725 | |||
| 726 | /** | ||
| 727 | * Removes the old focus-listener from focus-listener-l and | ||
| 728 | * returns the resulting multicast listener. | ||
| 729 | * @param l focus-listener-l | ||
| 730 | * @param oldl the focus-listener being removed | ||
| 731 | */ | ||
| 732 | public static FocusListener remove(FocusListener l, FocusListener oldl) { | ||
| 733 | return (FocusListener) removeInternal(l, oldl); | ||
| 734 | } | ||
| 735 | |||
| 736 | /** | ||
| 737 | * Removes the old key-listener from key-listener-l and | ||
| 738 | * returns the resulting multicast listener. | ||
| 739 | * @param l key-listener-l | ||
| 740 | * @param oldl the key-listener being removed | ||
| 741 | */ | ||
| 742 | public static KeyListener remove(KeyListener l, KeyListener oldl) { | ||
| 743 | return (KeyListener) removeInternal(l, oldl); | ||
| 744 | } | ||
| 745 | |||
| 746 | /** | ||
| 747 | * Removes the old mouse-listener from mouse-listener-l and | ||
| 748 | * returns the resulting multicast listener. | ||
| 749 | * @param l mouse-listener-l | ||
| 750 | * @param oldl the mouse-listener being removed | ||
| 751 | */ | ||
| 752 | public static MouseListener remove(MouseListener l, MouseListener oldl) { | ||
| 753 | return (MouseListener) removeInternal(l, oldl); | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | ||
| 757 | * Removes the old mouse-motion-listener from mouse-motion-listener-l | ||
| 758 | * and returns the resulting multicast listener. | ||
| 759 | * @param l mouse-motion-listener-l | ||
| 760 | * @param oldl the mouse-motion-listener being removed | ||
| 761 | */ | ||
| 762 | public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) { | ||
| 763 | return (MouseMotionListener) removeInternal(l, oldl); | ||
| 764 | } | ||
| 765 | |||
| 766 | /** | ||
| 767 | * Removes the old window-listener from window-listener-l and | ||
| 768 | * returns the resulting multicast listener. | ||
| 769 | * @param l window-listener-l | ||
| 770 | * @param oldl the window-listener being removed | ||
| 771 | */ | ||
| 772 | public static WindowListener remove(WindowListener l, WindowListener oldl) { | ||
| 773 | return (WindowListener) removeInternal(l, oldl); | ||
| 774 | } | ||
| 775 | |||
| 776 | /** | ||
| 777 | * Removes the old window-state-listener from window-state-listener-l | ||
| 778 | * and returns the resulting multicast listener. | ||
| 779 | * @param l window-state-listener-l | ||
| 780 | * @param oldl the window-state-listener being removed | ||
| 781 | * @since 1.4 | ||
| 782 | */ | ||
| 783 | public static WindowStateListener remove(WindowStateListener l, | ||
| 784 | WindowStateListener oldl) { | ||
| 785 | return (WindowStateListener) removeInternal(l, oldl); | ||
| 786 | } | ||
| 787 | |||
| 788 | /** | ||
| 789 | * Removes the old window-focus-listener from window-focus-listener-l | ||
| 790 | * and returns the resulting multicast listener. | ||
| 791 | * @param l window-focus-listener-l | ||
| 792 | * @param oldl the window-focus-listener being removed | ||
| 793 | * @since 1.4 | ||
| 794 | */ | ||
| 795 | public static WindowFocusListener remove(WindowFocusListener l, | ||
| 796 | WindowFocusListener oldl) { | ||
| 797 | return (WindowFocusListener) removeInternal(l, oldl); | ||
| 798 | } | ||
| 799 | |||
| 800 | /** | ||
| 801 | * Removes the old action-listener from action-listener-l and | ||
| 802 | * returns the resulting multicast listener. | ||
| 803 | * @param l action-listener-l | ||
| 804 | * @param oldl the action-listener being removed | ||
| 805 | */ | ||
| 806 | public static ActionListener remove(ActionListener l, ActionListener oldl) { | ||
| 807 | return (ActionListener) removeInternal(l, oldl); | ||
| 808 | } | ||
| 809 | |||
| 810 | /** | ||
| 811 | * Removes the old item-listener from item-listener-l and | ||
| 812 | * returns the resulting multicast listener. | ||
| 813 | * @param l item-listener-l | ||
| 814 | * @param oldl the item-listener being removed | ||
| 815 | */ | ||
| 816 | public static ItemListener remove(ItemListener l, ItemListener oldl) { | ||
| 817 | return (ItemListener) removeInternal(l, oldl); | ||
| 818 | } | ||
| 819 | |||
| 820 | /** | ||
| 821 | * Removes the old adjustment-listener from adjustment-listener-l and | ||
| 822 | * returns the resulting multicast listener. | ||
| 823 | * @param l adjustment-listener-l | ||
| 824 | * @param oldl the adjustment-listener being removed | ||
| 825 | */ | ||
| 826 | public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) { | ||
| 827 | return (AdjustmentListener) removeInternal(l, oldl); | ||
| 828 | } | ||
| 829 | public static TextListener remove(TextListener l, TextListener oldl) { | ||
| 830 | return (TextListener) removeInternal(l, oldl); | ||
| 831 | } | ||
| 832 | |||
| 833 | /** | ||
| 834 | * Removes the old input-method-listener from input-method-listener-l and | ||
| 835 | * returns the resulting multicast listener. | ||
| 836 | * @param l input-method-listener-l | ||
| 837 | * @param oldl the input-method-listener being removed | ||
| 838 | */ | ||
| 839 | public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) { | ||
| 840 | return (InputMethodListener) removeInternal(l, oldl); | ||
| 841 | } | ||
| 842 | |||
| 843 | /** | ||
| 844 | * Removes the old hierarchy-listener from hierarchy-listener-l and | ||
| 845 | * returns the resulting multicast listener. | ||
| 846 | * @param l hierarchy-listener-l | ||
| 847 | * @param oldl the hierarchy-listener being removed | ||
| 848 | * @since 1.3 | ||
| 849 | */ | ||
| 850 | public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) { | ||
| 851 | return (HierarchyListener) removeInternal(l, oldl); | ||
| 852 | } | ||
| 853 | |||
| 854 | /** | ||
| 855 | * Removes the old hierarchy-bounds-listener from | ||
| 856 | * hierarchy-bounds-listener-l and returns the resulting multicast | ||
| 857 | * listener. | ||
| 858 | * @param l hierarchy-bounds-listener-l | ||
| 859 | * @param oldl the hierarchy-bounds-listener being removed | ||
| 860 | * @since 1.3 | ||
| 861 | */ | ||
| 862 | public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) { | ||
| 863 | return (HierarchyBoundsListener) removeInternal(l, oldl); | ||
| 864 | } | ||
| 865 | |||
| 866 | /** | ||
| 867 | * Removes the old mouse-wheel-listener from mouse-wheel-listener-l | ||
| 868 | * and returns the resulting multicast listener. | ||
| 869 | * @param l mouse-wheel-listener-l | ||
| 870 | * @param oldl the mouse-wheel-listener being removed | ||
| 871 | * @since 1.4 | ||
| 872 | */ | ||
| 873 | public static MouseWheelListener remove(MouseWheelListener l, | ||
| 874 | MouseWheelListener oldl) { | ||
| 875 | return (MouseWheelListener) removeInternal(l, oldl); | ||
| 876 | } | ||
| 877 | |||
| 878 | /** | ||
| 879 | * Returns the resulting multicast listener from adding listener-a | ||
| 880 | * and listener-b together. | ||
| 881 | * If listener-a is null, it returns listener-b; | ||
| 882 | * If listener-b is null, it returns listener-a | ||
| 883 | * If neither are null, then it creates and returns | ||
| 884 | * a new AWTEventMulticaster instance which chains a with b. | ||
| 885 | * @param a event listener-a | ||
| 886 | * @param b event listener-b | ||
| 887 | */ | ||
| 888 | protected static EventListener addInternal(EventListener a, EventListener b) { | ||
| 889 | if (a == null) return b; | ||
| 890 | if (b == null) return a; | ||
| 891 | return new AWTEventMulticaster(a, b); | ||
| 892 | } | ||
| 893 | |||
| 894 | /** | ||
| 895 | * Returns the resulting multicast listener after removing the | ||
| 896 | * old listener from listener-l. | ||
| 897 | * If listener-l equals the old listener OR listener-l is null, | ||
| 898 | * returns null. | ||
| 899 | * Else if listener-l is an instance of AWTEventMulticaster, | ||
| 900 | * then it removes the old listener from it. | ||
| 901 | * Else, returns listener l. | ||
| 902 | * @param l the listener being removed from | ||
| 903 | * @param oldl the listener being removed | ||
| 904 | */ | ||
| 905 | protected static EventListener removeInternal(EventListener l, EventListener oldl) { | ||
| 906 | if (l == oldl || l == null) { | ||
| 907 | return null; | ||
| 908 | } else if (l instanceof AWTEventMulticaster) { | ||
| 909 | return ((AWTEventMulticaster)l).remove(oldl); | ||
| 910 | } else { | ||
| 911 | return l; // it's not here | ||
| 912 | } | ||
| 913 | } | ||
| 914 | |||
| 915 | |||
| 916 | /* Serialization support. | ||
| 917 | */ | ||
| 918 | |||
| 919 | protected void saveInternal(ObjectOutputStream s, String k) throws IOException { | ||
| 920 | if (a instanceof AWTEventMulticaster) { | ||
| 921 | ((AWTEventMulticaster)a).saveInternal(s, k); | ||
| 922 | } | ||
| 923 | else if (a instanceof Serializable) { | ||
| 924 | s.writeObject(k); | ||
| 925 | s.writeObject(a); | ||
| 926 | } | ||
| 927 | |||
| 928 | if (b instanceof AWTEventMulticaster) { | ||
| 929 | ((AWTEventMulticaster)b).saveInternal(s, k); | ||
| 930 | } | ||
| 931 | else if (b instanceof Serializable) { | ||
| 932 | s.writeObject(k); | ||
| 933 | s.writeObject(b); | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 937 | protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException { | ||
| 938 | if (l == null) { | ||
| 939 | return; | ||
| 940 | } | ||
| 941 | else if (l instanceof AWTEventMulticaster) { | ||
| 942 | ((AWTEventMulticaster)l).saveInternal(s, k); | ||
| 943 | } | ||
| 944 | else if (l instanceof Serializable) { | ||
| 945 | s.writeObject(k); | ||
| 946 | s.writeObject(l); | ||
| 947 | } | ||
| 948 | } | ||
| 949 | |||
| 950 | /* | ||
| 951 | * Recursive method which returns a count of the number of listeners in | ||
| 952 | * EventListener, handling the (common) case of l actually being an | ||
| 953 | * AWTEventMulticaster. Additionally, only listeners of type listenerType | ||
| 954 | * are counted. Method modified to fix bug 4513402. -bchristi | ||
| 955 | */ | ||
| 956 | private static int getListenerCount(EventListener l, Class listenerType) { | ||
| 957 | if (l instanceof AWTEventMulticaster) { | ||
| 958 | AWTEventMulticaster mc = (AWTEventMulticaster)l; | ||
| 959 | return getListenerCount(mc.a, listenerType) + | ||
| 960 | getListenerCount(mc.b, listenerType); | ||
| 961 | } | ||
| 962 | else { | ||
| 963 | // Only count listeners of correct type | ||
| 964 | return listenerType.isInstance(l) ? 1 : 0; | ||
| 965 | } | ||
| 966 | } | ||
| 967 | |||
| 968 | /* | ||
| 969 | * Recusive method which populates EventListener array a with EventListeners | ||
| 970 | * from l. l is usually an AWTEventMulticaster. Bug 4513402 revealed that | ||
| 971 | * if l differed in type from the element type of a, an ArrayStoreException | ||
| 972 | * would occur. Now l is only inserted into a if it's of the appropriate | ||
| 973 | * type. -bchristi | ||
| 974 | */ | ||
| 975 | private static int populateListenerArray(EventListener[] a, EventListener l, int index) { | ||
| 976 | if (l instanceof AWTEventMulticaster) { | ||
| 977 | AWTEventMulticaster mc = (AWTEventMulticaster)l; | ||
| 978 | int lhs = populateListenerArray(a, mc.a, index); | ||
| 979 | return populateListenerArray(a, mc.b, lhs); | ||
| 980 | } | ||
| 981 | else if (a.getClass().getComponentType().isInstance(l)) { | ||
| 982 | a[index] = l; | ||
| 983 | return index + 1; | ||
| 984 | } | ||
| 985 | // Skip nulls, instances of wrong class | ||
| 986 | else { | ||
| 987 | return index; | ||
| 988 | } | ||
| 989 | } | ||
| 990 | |||
| 991 | /** | ||
| 992 | * Returns an array of all the objects chained as | ||
| 993 | * <code><em>Foo</em>Listener</code>s by the specified | ||
| 994 | * <code>java.util.EventListener</code>. | ||
| 995 | * <code><em>Foo</em>Listener</code>s are chained by the | ||
| 996 | * <code>AWTEventMulticaster</code> using the | ||
| 997 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 998 | * If a <code>null</code> listener is specified, this method returns an | ||
| 999 | * empty array. If the specified listener is not an instance of | ||
| 1000 | * <code>AWTEventMulticaster</code>, this method returns an array which | ||
| 1001 | * contains only the specified listener. If no such listeners are chanined, | ||
| 1002 | * this method returns an empty array. | ||
| 1003 | * | ||
| 1004 | * @param l the specified <code>java.util.EventListener</code> | ||
| 1005 | * @param listenerType the type of listeners requested; this parameter | ||
| 1006 | * should specify an interface that descends from | ||
| 1007 | * <code>java.util.EventListener</code> | ||
| 1008 | * @return an array of all objects chained as | ||
| 1009 | * <code><em>Foo</em>Listener</code>s by the specified multicast | ||
| 1010 | * listener, or an empty array if no such listeners have been | ||
| 1011 | * chained by the specified multicast listener | ||
| 1012 | * @exception NullPointerException if the specified | ||
| 1013 | * {@code listenertype} parameter is {@code null} | ||
| 1014 | * @exception ClassCastException if <code>listenerType</code> | ||
| 1015 | * doesn't specify a class or interface that implements | ||
| 1016 | * <code>java.util.EventListener</code> | ||
| 1017 | * | ||
| 1018 | * @since 1.4 | ||
| 1019 | */ | ||
| 1020 | public static <T extends EventListener> T[] | ||
| 1021 | getListeners(EventListener l, Class<T> listenerType) | ||
| 1022 | { | ||
| 1023 | if (listenerType == null) { | ||
| 1024 | throw new NullPointerException ("Listener type should not be null"); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | int n = getListenerCount(l, listenerType); | ||
| 1028 | T[] result = (T[])Array.newInstance(listenerType, n); | ||
| 1029 | populateListenerArray(result, l, 0); | ||
| 1030 | return result; | ||
| 1031 | } | ||
| 1032 | } | ||
Binary file not shown.
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 1997, 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 | package java.awt; | ||
| 26 | |||
| 27 | |||
| 28 | /** | ||
| 29 | * Signals that an Absract Window Toolkit exception has occurred. | ||
| 30 | * | ||
| 31 | * @author Arthur van Hoff | ||
| 32 | */ | ||
| 33 | public class AWTException extends Exception { | ||
| 34 | |||
| 35 | /* | ||
| 36 | * JDK 1.1 serialVersionUID | ||
| 37 | */ | ||
| 38 | private static final long serialVersionUID = -1900414231151323879L; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Constructs an instance of <code>AWTException</code> with the | ||
| 42 | * specified detail message. A detail message is an | ||
| 43 | * instance of <code>String</code> that describes this particular | ||
| 44 | * exception. | ||
| 45 | * @param msg the detail message | ||
| 46 | * @since JDK1.0 | ||
| 47 | */ | ||
| 48 | public AWTException(String msg) { | ||
| 49 | super(msg); | ||
| 50 | } | ||
| 51 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,865 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2009, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.event.KeyEvent; | ||
| 28 | import java.awt.event.InputEvent; | ||
| 29 | import java.util.Collections; | ||
| 30 | import java.util.HashMap; | ||
| 31 | import java.util.Map; | ||
| 32 | import java.util.StringTokenizer; | ||
| 33 | import java.io.Serializable; | ||
| 34 | import java.security.AccessController; | ||
| 35 | import java.security.PrivilegedAction; | ||
| 36 | import java.lang.reflect.Constructor; | ||
| 37 | import java.lang.reflect.InvocationTargetException; | ||
| 38 | import java.lang.reflect.Modifier; | ||
| 39 | import java.lang.reflect.Field; | ||
| 40 | |||
| 41 | /** | ||
| 42 | * An <code>AWTKeyStroke</code> represents a key action on the | ||
| 43 | * keyboard, or equivalent input device. <code>AWTKeyStroke</code>s | ||
| 44 | * can correspond to only a press or release of a | ||
| 45 | * particular key, just as <code>KEY_PRESSED</code> and | ||
| 46 | * <code>KEY_RELEASED</code> <code>KeyEvent</code>s do; | ||
| 47 | * alternately, they can correspond to typing a specific Java character, just | ||
| 48 | * as <code>KEY_TYPED</code> <code>KeyEvent</code>s do. | ||
| 49 | * In all cases, <code>AWTKeyStroke</code>s can specify modifiers | ||
| 50 | * (alt, shift, control, meta, altGraph, or a combination thereof) which must be present | ||
| 51 | * during the action for an exact match. | ||
| 52 | * <p> | ||
| 53 | * <code>AWTKeyStrokes</code> are immutable, and are intended | ||
| 54 | * to be unique. Client code should never create an | ||
| 55 | * <code>AWTKeyStroke</code> on its own, but should instead use | ||
| 56 | * a variant of <code>getAWTKeyStroke</code>. Client use of these factory | ||
| 57 | * methods allows the <code>AWTKeyStroke</code> implementation | ||
| 58 | * to cache and share instances efficiently. | ||
| 59 | * | ||
| 60 | * @see #getAWTKeyStroke | ||
| 61 | * | ||
| 62 | * @author Arnaud Weber | ||
| 63 | * @author David Mendenhall | ||
| 64 | * @since 1.4 | ||
| 65 | */ | ||
| 66 | public class AWTKeyStroke implements Serializable { | ||
| 67 | static final long serialVersionUID = -6430539691155161871L; | ||
| 68 | |||
| 69 | private static Map cache; | ||
| 70 | private static AWTKeyStroke cacheKey; | ||
| 71 | private static Constructor ctor = getCtor(AWTKeyStroke.class); | ||
| 72 | private static Map modifierKeywords; | ||
| 73 | /** | ||
| 74 | * Associates VK_XXX (as a String) with code (as Integer). This is | ||
| 75 | * done to avoid the overhead of the reflective call to find the | ||
| 76 | * constant. | ||
| 77 | */ | ||
| 78 | private static VKCollection vks; | ||
| 79 | |||
| 80 | private char keyChar = KeyEvent.CHAR_UNDEFINED; | ||
| 81 | private int keyCode = KeyEvent.VK_UNDEFINED; | ||
| 82 | private int modifiers; | ||
| 83 | private boolean onKeyRelease; | ||
| 84 | |||
| 85 | static { | ||
| 86 | /* ensure that the necessary native libraries are loaded */ | ||
| 87 | Toolkit.loadLibraries(); | ||
| 88 | } | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Constructs an <code>AWTKeyStroke</code> with default values. | ||
| 92 | * The default values used are: | ||
| 93 | * <table border="1" summary="AWTKeyStroke default values"> | ||
| 94 | * <tr><th>Property</th><th>Default Value</th></tr> | ||
| 95 | * <tr> | ||
| 96 | * <td>Key Char</td> | ||
| 97 | * <td><code>KeyEvent.CHAR_UNDEFINED</code></td> | ||
| 98 | * </tr> | ||
| 99 | * <tr> | ||
| 100 | * <td>Key Code</td> | ||
| 101 | * <td><code>KeyEvent.VK_UNDEFINED</code></td> | ||
| 102 | * </tr> | ||
| 103 | * <tr> | ||
| 104 | * <td>Modifiers</td> | ||
| 105 | * <td>none</td> | ||
| 106 | * </tr> | ||
| 107 | * <tr> | ||
| 108 | * <td>On key release?</td> | ||
| 109 | * <td><code>false</code></td> | ||
| 110 | * </tr> | ||
| 111 | * </table> | ||
| 112 | * | ||
| 113 | * <code>AWTKeyStroke</code>s should not be constructed | ||
| 114 | * by client code. Use a variant of <code>getAWTKeyStroke</code> | ||
| 115 | * instead. | ||
| 116 | * | ||
| 117 | * @see #getAWTKeyStroke | ||
| 118 | */ | ||
| 119 | protected AWTKeyStroke() { | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Constructs an <code>AWTKeyStroke</code> with the specified | ||
| 124 | * values. <code>AWTKeyStroke</code>s should not be constructed | ||
| 125 | * by client code. Use a variant of <code>getAWTKeyStroke</code> | ||
| 126 | * instead. | ||
| 127 | * | ||
| 128 | * @param keyChar the character value for a keyboard key | ||
| 129 | * @param keyCode the key code for this <code>AWTKeyStroke</code> | ||
| 130 | * @param modifiers a bitwise-ored combination of any modifiers | ||
| 131 | * @param onKeyRelease <code>true</code> if this | ||
| 132 | * <code>AWTKeyStroke</code> corresponds | ||
| 133 | * to a key release; <code>false</code> otherwise | ||
| 134 | * @see #getAWTKeyStroke | ||
| 135 | */ | ||
| 136 | protected AWTKeyStroke(char keyChar, int keyCode, int modifiers, | ||
| 137 | boolean onKeyRelease) { | ||
| 138 | this.keyChar = keyChar; | ||
| 139 | this.keyCode = keyCode; | ||
| 140 | this.modifiers = modifiers; | ||
| 141 | this.onKeyRelease = onKeyRelease; | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Registers a new class which the factory methods in | ||
| 146 | * <code>AWTKeyStroke</code> will use when generating new | ||
| 147 | * instances of <code>AWTKeyStroke</code>s. After invoking this | ||
| 148 | * method, the factory methods will return instances of the specified | ||
| 149 | * Class. The specified Class must be either <code>AWTKeyStroke</code> | ||
| 150 | * or derived from <code>AWTKeyStroke</code>, and it must have a | ||
| 151 | * no-arg constructor. The constructor can be of any accessibility, | ||
| 152 | * including <code>private</code>. This operation | ||
| 153 | * flushes the current <code>AWTKeyStroke</code> cache. | ||
| 154 | * | ||
| 155 | * @param subclass the new Class of which the factory methods should create | ||
| 156 | * instances | ||
| 157 | * @throws IllegalArgumentException if subclass is <code>null</code>, | ||
| 158 | * or if subclass does not have a no-arg constructor | ||
| 159 | * @throws ClassCastException if subclass is not | ||
| 160 | * <code>AWTKeyStroke</code>, or a class derived from | ||
| 161 | * <code>AWTKeyStroke</code> | ||
| 162 | */ | ||
| 163 | protected static void registerSubclass(Class<?> subclass) { | ||
| 164 | if (subclass == null) { | ||
| 165 | throw new IllegalArgumentException("subclass cannot be null"); | ||
| 166 | } | ||
| 167 | if (AWTKeyStroke.ctor.getDeclaringClass().equals(subclass)) { | ||
| 168 | // Already registered | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | if (!AWTKeyStroke.class.isAssignableFrom(subclass)) { | ||
| 172 | throw new ClassCastException("subclass is not derived from AWTKeyStroke"); | ||
| 173 | } | ||
| 174 | |||
| 175 | Constructor ctor = getCtor(subclass); | ||
| 176 | |||
| 177 | String couldNotInstantiate = "subclass could not be instantiated"; | ||
| 178 | |||
| 179 | if (ctor == null) { | ||
| 180 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 181 | } | ||
| 182 | try { | ||
| 183 | AWTKeyStroke stroke = (AWTKeyStroke)ctor.newInstance((Object[]) null); | ||
| 184 | if (stroke == null) { | ||
| 185 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 186 | } | ||
| 187 | } catch (NoSuchMethodError e) { | ||
| 188 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 189 | } catch (ExceptionInInitializerError e) { | ||
| 190 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 191 | } catch (InstantiationException e) { | ||
| 192 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 193 | } catch (IllegalAccessException e) { | ||
| 194 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 195 | } catch (InvocationTargetException e) { | ||
| 196 | throw new IllegalArgumentException(couldNotInstantiate); | ||
| 197 | } | ||
| 198 | |||
| 199 | synchronized (AWTKeyStroke.class) { | ||
| 200 | AWTKeyStroke.ctor = ctor; | ||
| 201 | cache = null; | ||
| 202 | cacheKey = null; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | /* returns noarg Constructor for class with accessible flag. No security | ||
| 207 | threat as accessible flag is set only for this Constructor object, | ||
| 208 | not for Class constructor. | ||
| 209 | */ | ||
| 210 | private static Constructor getCtor(final Class clazz) | ||
| 211 | { | ||
| 212 | Object ctor = AccessController.doPrivileged(new PrivilegedAction() { | ||
| 213 | public Object run() { | ||
| 214 | try { | ||
| 215 | Constructor ctor = clazz.getDeclaredConstructor((Class[]) null); | ||
| 216 | if (ctor != null) { | ||
| 217 | ctor.setAccessible(true); | ||
| 218 | } | ||
| 219 | return ctor; | ||
| 220 | } catch (SecurityException e) { | ||
| 221 | } catch (NoSuchMethodException e) { | ||
| 222 | } | ||
| 223 | return null; | ||
| 224 | } | ||
| 225 | }); | ||
| 226 | return (Constructor)ctor; | ||
| 227 | } | ||
| 228 | |||
| 229 | private static synchronized AWTKeyStroke getCachedStroke | ||
| 230 | (char keyChar, int keyCode, int modifiers, boolean onKeyRelease) | ||
| 231 | { | ||
| 232 | if (cache == null) { | ||
| 233 | cache = new HashMap(); | ||
| 234 | } | ||
| 235 | |||
| 236 | if (cacheKey == null) { | ||
| 237 | try { | ||
| 238 | cacheKey = (AWTKeyStroke)ctor.newInstance((Object[]) null); | ||
| 239 | } catch (InstantiationException e) { | ||
| 240 | assert(false); | ||
| 241 | } catch (IllegalAccessException e) { | ||
| 242 | assert(false); | ||
| 243 | } catch (InvocationTargetException e) { | ||
| 244 | assert(false); | ||
| 245 | } | ||
| 246 | } | ||
| 247 | cacheKey.keyChar = keyChar; | ||
| 248 | cacheKey.keyCode = keyCode; | ||
| 249 | cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers)); | ||
| 250 | cacheKey.onKeyRelease = onKeyRelease; | ||
| 251 | |||
| 252 | AWTKeyStroke stroke = (AWTKeyStroke)cache.get(cacheKey); | ||
| 253 | if (stroke == null) { | ||
| 254 | stroke = cacheKey; | ||
| 255 | cache.put(stroke, stroke); | ||
| 256 | cacheKey = null; | ||
| 257 | } | ||
| 258 | |||
| 259 | return stroke; | ||
| 260 | } | ||
| 261 | |||
| 262 | /** | ||
| 263 | * Returns a shared instance of an <code>AWTKeyStroke</code> | ||
| 264 | * that represents a <code>KEY_TYPED</code> event for the | ||
| 265 | * specified character. | ||
| 266 | * | ||
| 267 | * @param keyChar the character value for a keyboard key | ||
| 268 | * @return an <code>AWTKeyStroke</code> object for that key | ||
| 269 | */ | ||
| 270 | public static AWTKeyStroke getAWTKeyStroke(char keyChar) { | ||
| 271 | return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false); | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 275 | * Returns a shared instance of an {@code AWTKeyStroke} | ||
| 276 | * that represents a {@code KEY_TYPED} event for the | ||
| 277 | * specified Character object and a set of modifiers. Note | ||
| 278 | * that the first parameter is of type Character rather than | ||
| 279 | * char. This is to avoid inadvertent clashes with | ||
| 280 | * calls to <code>getAWTKeyStroke(int keyCode, int modifiers)</code>. | ||
| 281 | * | ||
| 282 | * The modifiers consist of any combination of following:<ul> | ||
| 283 | * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK | ||
| 284 | * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK | ||
| 285 | * <li>java.awt.event.InputEvent.META_DOWN_MASK | ||
| 286 | * <li>java.awt.event.InputEvent.ALT_DOWN_MASK | ||
| 287 | * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK | ||
| 288 | * </ul> | ||
| 289 | * The old modifiers listed below also can be used, but they are | ||
| 290 | * mapped to _DOWN_ modifiers. <ul> | ||
| 291 | * <li>java.awt.event.InputEvent.SHIFT_MASK | ||
| 292 | * <li>java.awt.event.InputEvent.CTRL_MASK | ||
| 293 | * <li>java.awt.event.InputEvent.META_MASK | ||
| 294 | * <li>java.awt.event.InputEvent.ALT_MASK | ||
| 295 | * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK | ||
| 296 | * </ul> | ||
| 297 | * also can be used, but they are mapped to _DOWN_ modifiers. | ||
| 298 | * | ||
| 299 | * Since these numbers are all different powers of two, any combination of | ||
| 300 | * them is an integer in which each bit represents a different modifier | ||
| 301 | * key. Use 0 to specify no modifiers. | ||
| 302 | * | ||
| 303 | * @param keyChar the Character object for a keyboard character | ||
| 304 | * @param modifiers a bitwise-ored combination of any modifiers | ||
| 305 | * @return an <code>AWTKeyStroke</code> object for that key | ||
| 306 | * @throws IllegalArgumentException if <code>keyChar</code> is | ||
| 307 | * <code>null</code> | ||
| 308 | * | ||
| 309 | * @see java.awt.event.InputEvent | ||
| 310 | */ | ||
| 311 | public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers) | ||
| 312 | { | ||
| 313 | if (keyChar == null) { | ||
| 314 | throw new IllegalArgumentException("keyChar cannot be null"); | ||
| 315 | } | ||
| 316 | return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED, | ||
| 317 | modifiers, false); | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Returns a shared instance of an <code>AWTKeyStroke</code>, | ||
| 322 | * given a numeric key code and a set of modifiers, specifying | ||
| 323 | * whether the key is activated when it is pressed or released. | ||
| 324 | * <p> | ||
| 325 | * The "virtual key" constants defined in | ||
| 326 | * <code>java.awt.event.KeyEvent</code> can be | ||
| 327 | * used to specify the key code. For example:<ul> | ||
| 328 | * <li><code>java.awt.event.KeyEvent.VK_ENTER</code> | ||
| 329 | * <li><code>java.awt.event.KeyEvent.VK_TAB</code> | ||
| 330 | * <li><code>java.awt.event.KeyEvent.VK_SPACE</code> | ||
| 331 | * </ul> | ||
| 332 | * Alternatively, the key code may be obtained by calling | ||
| 333 | * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>. | ||
| 334 | * | ||
| 335 | * The modifiers consist of any combination of:<ul> | ||
| 336 | * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK | ||
| 337 | * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK | ||
| 338 | * <li>java.awt.event.InputEvent.META_DOWN_MASK | ||
| 339 | * <li>java.awt.event.InputEvent.ALT_DOWN_MASK | ||
| 340 | * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK | ||
| 341 | * </ul> | ||
| 342 | * The old modifiers <ul> | ||
| 343 | * <li>java.awt.event.InputEvent.SHIFT_MASK | ||
| 344 | * <li>java.awt.event.InputEvent.CTRL_MASK | ||
| 345 | * <li>java.awt.event.InputEvent.META_MASK | ||
| 346 | * <li>java.awt.event.InputEvent.ALT_MASK | ||
| 347 | * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK | ||
| 348 | * </ul> | ||
| 349 | * also can be used, but they are mapped to _DOWN_ modifiers. | ||
| 350 | * | ||
| 351 | * Since these numbers are all different powers of two, any combination of | ||
| 352 | * them is an integer in which each bit represents a different modifier | ||
| 353 | * key. Use 0 to specify no modifiers. | ||
| 354 | * | ||
| 355 | * @param keyCode an int specifying the numeric code for a keyboard key | ||
| 356 | * @param modifiers a bitwise-ored combination of any modifiers | ||
| 357 | * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code> | ||
| 358 | * should represent a key release; <code>false</code> otherwise | ||
| 359 | * @return an AWTKeyStroke object for that key | ||
| 360 | * | ||
| 361 | * @see java.awt.event.KeyEvent | ||
| 362 | * @see java.awt.event.InputEvent | ||
| 363 | */ | ||
| 364 | public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers, | ||
| 365 | boolean onKeyRelease) { | ||
| 366 | return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, | ||
| 367 | onKeyRelease); | ||
| 368 | } | ||
| 369 | |||
| 370 | /** | ||
| 371 | * Returns a shared instance of an <code>AWTKeyStroke</code>, | ||
| 372 | * given a numeric key code and a set of modifiers. The returned | ||
| 373 | * <code>AWTKeyStroke</code> will correspond to a key press. | ||
| 374 | * <p> | ||
| 375 | * The "virtual key" constants defined in | ||
| 376 | * <code>java.awt.event.KeyEvent</code> can be | ||
| 377 | * used to specify the key code. For example:<ul> | ||
| 378 | * <li><code>java.awt.event.KeyEvent.VK_ENTER</code> | ||
| 379 | * <li><code>java.awt.event.KeyEvent.VK_TAB</code> | ||
| 380 | * <li><code>java.awt.event.KeyEvent.VK_SPACE</code> | ||
| 381 | * </ul> | ||
| 382 | * The modifiers consist of any combination of:<ul> | ||
| 383 | * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK | ||
| 384 | * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK | ||
| 385 | * <li>java.awt.event.InputEvent.META_DOWN_MASK | ||
| 386 | * <li>java.awt.event.InputEvent.ALT_DOWN_MASK | ||
| 387 | * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK | ||
| 388 | * </ul> | ||
| 389 | * The old modifiers <ul> | ||
| 390 | * <li>java.awt.event.InputEvent.SHIFT_MASK | ||
| 391 | * <li>java.awt.event.InputEvent.CTRL_MASK | ||
| 392 | * <li>java.awt.event.InputEvent.META_MASK | ||
| 393 | * <li>java.awt.event.InputEvent.ALT_MASK | ||
| 394 | * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK | ||
| 395 | * </ul> | ||
| 396 | * also can be used, but they are mapped to _DOWN_ modifiers. | ||
| 397 | * | ||
| 398 | * Since these numbers are all different powers of two, any combination of | ||
| 399 | * them is an integer in which each bit represents a different modifier | ||
| 400 | * key. Use 0 to specify no modifiers. | ||
| 401 | * | ||
| 402 | * @param keyCode an int specifying the numeric code for a keyboard key | ||
| 403 | * @param modifiers a bitwise-ored combination of any modifiers | ||
| 404 | * @return an <code>AWTKeyStroke</code> object for that key | ||
| 405 | * | ||
| 406 | * @see java.awt.event.KeyEvent | ||
| 407 | * @see java.awt.event.InputEvent | ||
| 408 | */ | ||
| 409 | public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) { | ||
| 410 | return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, | ||
| 411 | false); | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Returns an <code>AWTKeyStroke</code> which represents the | ||
| 416 | * stroke which generated a given <code>KeyEvent</code>. | ||
| 417 | * <p> | ||
| 418 | * This method obtains the keyChar from a <code>KeyTyped</code> | ||
| 419 | * event, and the keyCode from a <code>KeyPressed</code> or | ||
| 420 | * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are | ||
| 421 | * obtained for all three types of <code>KeyEvent</code>. | ||
| 422 | * | ||
| 423 | * @param anEvent the <code>KeyEvent</code> from which to | ||
| 424 | * obtain the <code>AWTKeyStroke</code> | ||
| 425 | * @throws NullPointerException if <code>anEvent</code> is null | ||
| 426 | * @return the <code>AWTKeyStroke</code> that precipitated the event | ||
| 427 | */ | ||
| 428 | public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) { | ||
| 429 | int id = anEvent.getID(); | ||
| 430 | switch(id) { | ||
| 431 | case KeyEvent.KEY_PRESSED: | ||
| 432 | case KeyEvent.KEY_RELEASED: | ||
| 433 | return getCachedStroke(KeyEvent.CHAR_UNDEFINED, | ||
| 434 | anEvent.getKeyCode(), | ||
| 435 | anEvent.getModifiers(), | ||
| 436 | (id == KeyEvent.KEY_RELEASED)); | ||
| 437 | case KeyEvent.KEY_TYPED: | ||
| 438 | return getCachedStroke(anEvent.getKeyChar(), | ||
| 439 | KeyEvent.VK_UNDEFINED, | ||
| 440 | anEvent.getModifiers(), | ||
| 441 | false); | ||
| 442 | default: | ||
| 443 | // Invalid ID for this KeyEvent | ||
| 444 | return null; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | /** | ||
| 449 | * Parses a string and returns an <code>AWTKeyStroke</code>. | ||
| 450 | * The string must have the following syntax: | ||
| 451 | * <pre> | ||
| 452 | * <modifiers>* (<typedID> | <pressedReleasedID>) | ||
| 453 | * | ||
| 454 | * modifiers := shift | control | ctrl | meta | alt | altGraph | ||
| 455 | * typedID := typed <typedKey> | ||
| 456 | * typedKey := string of length 1 giving Unicode character. | ||
| 457 | * pressedReleasedID := (pressed | released) key | ||
| 458 | * key := KeyEvent key code name, i.e. the name following "VK_". | ||
| 459 | * </pre> | ||
| 460 | * If typed, pressed or released is not specified, pressed is assumed. Here | ||
| 461 | * are some examples: | ||
| 462 | * <pre> | ||
| 463 | * "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0); | ||
| 464 | * "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK); | ||
| 465 | * "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK); | ||
| 466 | * "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true); | ||
| 467 | * "typed a" => getAWTKeyStroke('a'); | ||
| 468 | * </pre> | ||
| 469 | * | ||
| 470 | * @param s a String formatted as described above | ||
| 471 | * @return an <code>AWTKeyStroke</code> object for that String | ||
| 472 | * @throws IllegalArgumentException if <code>s</code> is <code>null</code>, | ||
| 473 | * or is formatted incorrectly | ||
| 474 | */ | ||
| 475 | public static AWTKeyStroke getAWTKeyStroke(String s) { | ||
| 476 | if (s == null) { | ||
| 477 | throw new IllegalArgumentException("String cannot be null"); | ||
| 478 | } | ||
| 479 | |||
| 480 | final String errmsg = "String formatted incorrectly"; | ||
| 481 | |||
| 482 | StringTokenizer st = new StringTokenizer(s, " "); | ||
| 483 | |||
| 484 | int mask = 0; | ||
| 485 | boolean released = false; | ||
| 486 | boolean typed = false; | ||
| 487 | boolean pressed = false; | ||
| 488 | |||
| 489 | synchronized (AWTKeyStroke.class) { | ||
| 490 | if (modifierKeywords == null) { | ||
| 491 | Map uninitializedMap = new HashMap(8, 1.0f); | ||
| 492 | uninitializedMap.put("shift", | ||
| 493 | Integer.valueOf(InputEvent.SHIFT_DOWN_MASK | ||
| 494 | |InputEvent.SHIFT_MASK)); | ||
| 495 | uninitializedMap.put("control", | ||
| 496 | Integer.valueOf(InputEvent.CTRL_DOWN_MASK | ||
| 497 | |InputEvent.CTRL_MASK)); | ||
| 498 | uninitializedMap.put("ctrl", | ||
| 499 | Integer.valueOf(InputEvent.CTRL_DOWN_MASK | ||
| 500 | |InputEvent.CTRL_MASK)); | ||
| 501 | uninitializedMap.put("meta", | ||
| 502 | Integer.valueOf(InputEvent.META_DOWN_MASK | ||
| 503 | |InputEvent.META_MASK)); | ||
| 504 | uninitializedMap.put("alt", | ||
| 505 | Integer.valueOf(InputEvent.ALT_DOWN_MASK | ||
| 506 | |InputEvent.ALT_MASK)); | ||
| 507 | uninitializedMap.put("altGraph", | ||
| 508 | Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK | ||
| 509 | |InputEvent.ALT_GRAPH_MASK)); | ||
| 510 | uninitializedMap.put("button1", | ||
| 511 | Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK)); | ||
| 512 | uninitializedMap.put("button2", | ||
| 513 | Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK)); | ||
| 514 | uninitializedMap.put("button3", | ||
| 515 | Integer.valueOf(InputEvent.BUTTON3_DOWN_MASK)); | ||
| 516 | modifierKeywords = | ||
| 517 | Collections.synchronizedMap(uninitializedMap); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | int count = st.countTokens(); | ||
| 522 | |||
| 523 | for (int i = 1; i <= count; i++) { | ||
| 524 | String token = st.nextToken(); | ||
| 525 | |||
| 526 | if (typed) { | ||
| 527 | if (token.length() != 1 || i != count) { | ||
| 528 | throw new IllegalArgumentException(errmsg); | ||
| 529 | } | ||
| 530 | return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED, | ||
| 531 | mask, false); | ||
| 532 | } | ||
| 533 | |||
| 534 | if (pressed || released || i == count) { | ||
| 535 | if (i != count) { | ||
| 536 | throw new IllegalArgumentException(errmsg); | ||
| 537 | } | ||
| 538 | |||
| 539 | String keyCodeName = "VK_" + token; | ||
| 540 | int keyCode = getVKValue(keyCodeName); | ||
| 541 | |||
| 542 | return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, | ||
| 543 | mask, released); | ||
| 544 | } | ||
| 545 | |||
| 546 | if (token.equals("released")) { | ||
| 547 | released = true; | ||
| 548 | continue; | ||
| 549 | } | ||
| 550 | if (token.equals("pressed")) { | ||
| 551 | pressed = true; | ||
| 552 | continue; | ||
| 553 | } | ||
| 554 | if (token.equals("typed")) { | ||
| 555 | typed = true; | ||
| 556 | continue; | ||
| 557 | } | ||
| 558 | |||
| 559 | Integer tokenMask = (Integer)modifierKeywords.get(token); | ||
| 560 | if (tokenMask != null) { | ||
| 561 | mask |= tokenMask.intValue(); | ||
| 562 | } else { | ||
| 563 | throw new IllegalArgumentException(errmsg); | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 567 | throw new IllegalArgumentException(errmsg); | ||
| 568 | } | ||
| 569 | |||
| 570 | private static VKCollection getVKCollection() { | ||
| 571 | if (vks == null) { | ||
| 572 | vks = new VKCollection(); | ||
| 573 | } | ||
| 574 | return vks; | ||
| 575 | } | ||
| 576 | /** | ||
| 577 | * Returns the integer constant for the KeyEvent.VK field named | ||
| 578 | * <code>key</code>. This will throw an | ||
| 579 | * <code>IllegalArgumentException</code> if <code>key</code> is | ||
| 580 | * not a valid constant. | ||
| 581 | */ | ||
| 582 | private static int getVKValue(String key) { | ||
| 583 | VKCollection vkCollect = getVKCollection(); | ||
| 584 | |||
| 585 | Integer value = vkCollect.findCode(key); | ||
| 586 | |||
| 587 | if (value == null) { | ||
| 588 | int keyCode = 0; | ||
| 589 | final String errmsg = "String formatted incorrectly"; | ||
| 590 | |||
| 591 | try { | ||
| 592 | keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class); | ||
| 593 | } catch (NoSuchFieldException nsfe) { | ||
| 594 | throw new IllegalArgumentException(errmsg); | ||
| 595 | } catch (IllegalAccessException iae) { | ||
| 596 | throw new IllegalArgumentException(errmsg); | ||
| 597 | } | ||
| 598 | value = Integer.valueOf(keyCode); | ||
| 599 | vkCollect.put(key, value); | ||
| 600 | } | ||
| 601 | return value.intValue(); | ||
| 602 | } | ||
| 603 | |||
| 604 | /** | ||
| 605 | * Returns the character for this <code>AWTKeyStroke</code>. | ||
| 606 | * | ||
| 607 | * @return a char value | ||
| 608 | * @see #getAWTKeyStroke(char) | ||
| 609 | * @see KeyEvent#getKeyChar | ||
| 610 | */ | ||
| 611 | public final char getKeyChar() { | ||
| 612 | return keyChar; | ||
| 613 | } | ||
| 614 | |||
| 615 | /** | ||
| 616 | * Returns the numeric key code for this <code>AWTKeyStroke</code>. | ||
| 617 | * | ||
| 618 | * @return an int containing the key code value | ||
| 619 | * @see #getAWTKeyStroke(int,int) | ||
| 620 | * @see KeyEvent#getKeyCode | ||
| 621 | */ | ||
| 622 | public final int getKeyCode() { | ||
| 623 | return keyCode; | ||
| 624 | } | ||
| 625 | |||
| 626 | /** | ||
| 627 | * Returns the modifier keys for this <code>AWTKeyStroke</code>. | ||
| 628 | * | ||
| 629 | * @return an int containing the modifiers | ||
| 630 | * @see #getAWTKeyStroke(int,int) | ||
| 631 | */ | ||
| 632 | public final int getModifiers() { | ||
| 633 | return modifiers; | ||
| 634 | } | ||
| 635 | |||
| 636 | /** | ||
| 637 | * Returns whether this <code>AWTKeyStroke</code> represents a key release. | ||
| 638 | * | ||
| 639 | * @return <code>true</code> if this <code>AWTKeyStroke</code> | ||
| 640 | * represents a key release; <code>false</code> otherwise | ||
| 641 | * @see #getAWTKeyStroke(int,int,boolean) | ||
| 642 | */ | ||
| 643 | public final boolean isOnKeyRelease() { | ||
| 644 | return onKeyRelease; | ||
| 645 | } | ||
| 646 | |||
| 647 | /** | ||
| 648 | * Returns the type of <code>KeyEvent</code> which corresponds to | ||
| 649 | * this <code>AWTKeyStroke</code>. | ||
| 650 | * | ||
| 651 | * @return <code>KeyEvent.KEY_PRESSED</code>, | ||
| 652 | * <code>KeyEvent.KEY_TYPED</code>, | ||
| 653 | * or <code>KeyEvent.KEY_RELEASED</code> | ||
| 654 | * @see java.awt.event.KeyEvent | ||
| 655 | */ | ||
| 656 | public final int getKeyEventType() { | ||
| 657 | if (keyCode == KeyEvent.VK_UNDEFINED) { | ||
| 658 | return KeyEvent.KEY_TYPED; | ||
| 659 | } else { | ||
| 660 | return (onKeyRelease) | ||
| 661 | ? KeyEvent.KEY_RELEASED | ||
| 662 | : KeyEvent.KEY_PRESSED; | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 666 | /** | ||
| 667 | * Returns a numeric value for this object that is likely to be unique, | ||
| 668 | * making it a good choice as the index value in a hash table. | ||
| 669 | * | ||
| 670 | * @return an int that represents this object | ||
| 671 | */ | ||
| 672 | public int hashCode() { | ||
| 673 | return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) + | ||
| 674 | (onKeyRelease ? 1 : 2); | ||
| 675 | } | ||
| 676 | |||
| 677 | /** | ||
| 678 | * Returns true if this object is identical to the specified object. | ||
| 679 | * | ||
| 680 | * @param anObject the Object to compare this object to | ||
| 681 | * @return true if the objects are identical | ||
| 682 | */ | ||
| 683 | public final boolean equals(Object anObject) { | ||
| 684 | if (anObject instanceof AWTKeyStroke) { | ||
| 685 | AWTKeyStroke ks = (AWTKeyStroke)anObject; | ||
| 686 | return (ks.keyChar == keyChar && ks.keyCode == keyCode && | ||
| 687 | ks.onKeyRelease == onKeyRelease && | ||
| 688 | ks.modifiers == modifiers); | ||
| 689 | } | ||
| 690 | return false; | ||
| 691 | } | ||
| 692 | |||
| 693 | /** | ||
| 694 | * Returns a string that displays and identifies this object's properties. | ||
| 695 | * The <code>String</code> returned by this method can be passed | ||
| 696 | * as a parameter to <code>getAWTKeyStroke(String)</code> to produce | ||
| 697 | * a key stroke equal to this key stroke. | ||
| 698 | * | ||
| 699 | * @return a String representation of this object | ||
| 700 | * @see #getAWTKeyStroke(String) | ||
| 701 | */ | ||
| 702 | public String toString() { | ||
| 703 | if (keyCode == KeyEvent.VK_UNDEFINED) { | ||
| 704 | return getModifiersText(modifiers) + "typed " + keyChar; | ||
| 705 | } else { | ||
| 706 | return getModifiersText(modifiers) + | ||
| 707 | (onKeyRelease ? "released" : "pressed") + " " + | ||
| 708 | getVKText(keyCode); | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | static String getModifiersText(int modifiers) { | ||
| 713 | StringBuilder buf = new StringBuilder(); | ||
| 714 | |||
| 715 | if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) { | ||
| 716 | buf.append("shift "); | ||
| 717 | } | ||
| 718 | if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) { | ||
| 719 | buf.append("ctrl "); | ||
| 720 | } | ||
| 721 | if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) { | ||
| 722 | buf.append("meta "); | ||
| 723 | } | ||
| 724 | if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) { | ||
| 725 | buf.append("alt "); | ||
| 726 | } | ||
| 727 | if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) { | ||
| 728 | buf.append("altGraph "); | ||
| 729 | } | ||
| 730 | if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) { | ||
| 731 | buf.append("button1 "); | ||
| 732 | } | ||
| 733 | if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) { | ||
| 734 | buf.append("button2 "); | ||
| 735 | } | ||
| 736 | if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) { | ||
| 737 | buf.append("button3 "); | ||
| 738 | } | ||
| 739 | |||
| 740 | return buf.toString(); | ||
| 741 | } | ||
| 742 | |||
| 743 | static String getVKText(int keyCode) { | ||
| 744 | VKCollection vkCollect = getVKCollection(); | ||
| 745 | Integer key = Integer.valueOf(keyCode); | ||
| 746 | String name = vkCollect.findName(key); | ||
| 747 | if (name != null) { | ||
| 748 | return name.substring(3); | ||
| 749 | } | ||
| 750 | int expected_modifiers = | ||
| 751 | (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL); | ||
| 752 | |||
| 753 | Field[] fields = KeyEvent.class.getDeclaredFields(); | ||
| 754 | for (int i = 0; i < fields.length; i++) { | ||
| 755 | try { | ||
| 756 | if (fields[i].getModifiers() == expected_modifiers | ||
| 757 | && fields[i].getType() == Integer.TYPE | ||
| 758 | && fields[i].getName().startsWith("VK_") | ||
| 759 | && fields[i].getInt(KeyEvent.class) == keyCode) | ||
| 760 | { | ||
| 761 | name = fields[i].getName(); | ||
| 762 | vkCollect.put(name, key); | ||
| 763 | return name.substring(3); | ||
| 764 | } | ||
| 765 | } catch (IllegalAccessException e) { | ||
| 766 | assert(false); | ||
| 767 | } | ||
| 768 | } | ||
| 769 | return "UNKNOWN"; | ||
| 770 | } | ||
| 771 | |||
| 772 | /** | ||
| 773 | * Returns a cached instance of <code>AWTKeyStroke</code> (or a subclass of | ||
| 774 | * <code>AWTKeyStroke</code>) which is equal to this instance. | ||
| 775 | * | ||
| 776 | * @return a cached instance which is equal to this instance | ||
| 777 | */ | ||
| 778 | protected Object readResolve() throws java.io.ObjectStreamException { | ||
| 779 | synchronized (AWTKeyStroke.class) { | ||
| 780 | Class newClass = getClass(); | ||
| 781 | if (!newClass.equals(ctor.getDeclaringClass())) { | ||
| 782 | registerSubclass(newClass); | ||
| 783 | } | ||
| 784 | return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 788 | private static int mapOldModifiers(int modifiers) { | ||
| 789 | if ((modifiers & InputEvent.SHIFT_MASK) != 0) { | ||
| 790 | modifiers |= InputEvent.SHIFT_DOWN_MASK; | ||
| 791 | } | ||
| 792 | if ((modifiers & InputEvent.ALT_MASK) != 0) { | ||
| 793 | modifiers |= InputEvent.ALT_DOWN_MASK; | ||
| 794 | } | ||
| 795 | if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) { | ||
| 796 | modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; | ||
| 797 | } | ||
| 798 | if ((modifiers & InputEvent.CTRL_MASK) != 0) { | ||
| 799 | modifiers |= InputEvent.CTRL_DOWN_MASK; | ||
| 800 | } | ||
| 801 | if ((modifiers & InputEvent.META_MASK) != 0) { | ||
| 802 | modifiers |= InputEvent.META_DOWN_MASK; | ||
| 803 | } | ||
| 804 | |||
| 805 | modifiers &= InputEvent.SHIFT_DOWN_MASK | ||
| 806 | | InputEvent.ALT_DOWN_MASK | ||
| 807 | | InputEvent.ALT_GRAPH_DOWN_MASK | ||
| 808 | | InputEvent.CTRL_DOWN_MASK | ||
| 809 | | InputEvent.META_DOWN_MASK | ||
| 810 | | InputEvent.BUTTON1_DOWN_MASK | ||
| 811 | | InputEvent.BUTTON2_DOWN_MASK | ||
| 812 | | InputEvent.BUTTON3_DOWN_MASK; | ||
| 813 | |||
| 814 | return modifiers; | ||
| 815 | } | ||
| 816 | |||
| 817 | private static int mapNewModifiers(int modifiers) { | ||
| 818 | if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) { | ||
| 819 | modifiers |= InputEvent.SHIFT_MASK; | ||
| 820 | } | ||
| 821 | if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) { | ||
| 822 | modifiers |= InputEvent.ALT_MASK; | ||
| 823 | } | ||
| 824 | if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) { | ||
| 825 | modifiers |= InputEvent.ALT_GRAPH_MASK; | ||
| 826 | } | ||
| 827 | if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) { | ||
| 828 | modifiers |= InputEvent.CTRL_MASK; | ||
| 829 | } | ||
| 830 | if ((modifiers & InputEvent.META_DOWN_MASK) != 0) { | ||
| 831 | modifiers |= InputEvent.META_MASK; | ||
| 832 | } | ||
| 833 | |||
| 834 | return modifiers; | ||
| 835 | } | ||
| 836 | |||
| 837 | } | ||
| 838 | |||
| 839 | class VKCollection { | ||
| 840 | Map code2name; | ||
| 841 | Map name2code; | ||
| 842 | |||
| 843 | public VKCollection() { | ||
| 844 | code2name = new HashMap(); | ||
| 845 | name2code = new HashMap(); | ||
| 846 | } | ||
| 847 | |||
| 848 | public synchronized void put(String name, Integer code) { | ||
| 849 | assert((name != null) && (code != null)); | ||
| 850 | assert(findName(code) == null); | ||
| 851 | assert(findCode(name) == null); | ||
| 852 | code2name.put(code, name); | ||
| 853 | name2code.put(name, code); | ||
| 854 | } | ||
| 855 | |||
| 856 | public synchronized Integer findCode(String name) { | ||
| 857 | assert(name != null); | ||
| 858 | return (Integer)name2code.get(name); | ||
| 859 | } | ||
| 860 | |||
| 861 | public synchronized String findName(Integer code) { | ||
| 862 | assert(code != null); | ||
| 863 | return (String)code2name.get(code); | ||
| 864 | } | ||
| 865 | } | ||
Binary file not shown.
| @@ -0,0 +1,237 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2009, 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 java.awt; | ||
| 27 | |||
| 28 | import java.security.BasicPermission; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * This class is for AWT permissions. | ||
| 32 | * An <code>AWTPermission</code> contains a target name but | ||
| 33 | * no actions list; you either have the named permission | ||
| 34 | * or you don't. | ||
| 35 | * | ||
| 36 | * <P> | ||
| 37 | * The target name is the name of the AWT permission (see below). The naming | ||
| 38 | * convention follows the hierarchical property naming convention. | ||
| 39 | * Also, an asterisk could be used to represent all AWT permissions. | ||
| 40 | * | ||
| 41 | * <P> | ||
| 42 | * The following table lists all the possible <code>AWTPermission</code> | ||
| 43 | * target names, and for each provides a description of what the | ||
| 44 | * permission allows and a discussion of the risks of granting code | ||
| 45 | * the permission. | ||
| 46 | * <P> | ||
| 47 | * | ||
| 48 | * <table border=1 cellpadding=5 summary="AWTPermission target names, descriptions, and associated risks."> | ||
| 49 | * <tr> | ||
| 50 | * <th>Permission Target Name</th> | ||
| 51 | * <th>What the Permission Allows</th> | ||
| 52 | * <th>Risks of Allowing this Permission</th> | ||
| 53 | * </tr> | ||
| 54 | * | ||
| 55 | * <tr> | ||
| 56 | * <td>accessClipboard</td> | ||
| 57 | * <td>Posting and retrieval of information to and from the AWT clipboard</td> | ||
| 58 | * <td>This would allow malfeasant code to share | ||
| 59 | * potentially sensitive or confidential information.</td> | ||
| 60 | * </tr> | ||
| 61 | * | ||
| 62 | * <tr> | ||
| 63 | * <td>accessEventQueue</td> | ||
| 64 | * <td>Access to the AWT event queue</td> | ||
| 65 | * <td>After retrieving the AWT event queue, | ||
| 66 | * malicious code may peek at and even remove existing events | ||
| 67 | * from its event queue, as well as post bogus events which may purposefully | ||
| 68 | * cause the application or applet to misbehave in an insecure manner.</td> | ||
| 69 | * </tr> | ||
| 70 | * | ||
| 71 | * <tr> | ||
| 72 | * <td>accessSystemTray</td> | ||
| 73 | * <td>Access to the AWT SystemTray instance</td> | ||
| 74 | * <td>This would allow malicious code to add tray icons to the system tray. | ||
| 75 | * First, such an icon may look like the icon of some known application | ||
| 76 | * (such as a firewall or anti-virus) and order a user to do something unsafe | ||
| 77 | * (with help of balloon messages). Second, the system tray may be glutted with | ||
| 78 | * tray icons so that no one could add a tray icon anymore.</td> | ||
| 79 | * </tr> | ||
| 80 | * | ||
| 81 | * <tr> | ||
| 82 | * <td>createRobot</td> | ||
| 83 | * <td>Create java.awt.Robot objects</td> | ||
| 84 | * <td>The java.awt.Robot object allows code to generate native-level | ||
| 85 | * mouse and keyboard events as well as read the screen. It could allow | ||
| 86 | * malicious code to control the system, run other programs, read the | ||
| 87 | * display, and deny mouse and keyboard access to the user.</td> | ||
| 88 | * </tr> | ||
| 89 | * | ||
| 90 | * <tr> | ||
| 91 | * <td>fullScreenExclusive</td> | ||
| 92 | * <td>Enter full-screen exclusive mode</td> | ||
| 93 | * <td>Entering full-screen exclusive mode allows direct access to | ||
| 94 | * low-level graphics card memory. This could be used to spoof the | ||
| 95 | * system, since the program is in direct control of rendering. Depending on | ||
| 96 | * the implementation, the security warning may not be shown for the windows | ||
| 97 | * used to enter the full-screen exclusive mode (assuming that the {@code | ||
| 98 | * fullScreenExclusive} permission has been granted to this application). Note | ||
| 99 | * that this behavior does not mean that the {@code | ||
| 100 | * showWindowWithoutWarningBanner} permission will be automatically granted to | ||
| 101 | * the application which has the {@code fullScreenExclusive} permission: | ||
| 102 | * non-full-screen windows will continue to be shown with the security | ||
| 103 | * warning.</td> | ||
| 104 | * </tr> | ||
| 105 | * | ||
| 106 | * <tr> | ||
| 107 | * <td>listenToAllAWTEvents</td> | ||
| 108 | * <td>Listen to all AWT events, system-wide</td> | ||
| 109 | * <td>After adding an AWT event listener, | ||
| 110 | * malicious code may scan all AWT events dispatched in the system, | ||
| 111 | * allowing it to read all user input (such as passwords). Each | ||
| 112 | * AWT event listener is called from within the context of that | ||
| 113 | * event queue's EventDispatchThread, so if the accessEventQueue | ||
| 114 | * permission is also enabled, malicious code could modify the | ||
| 115 | * contents of AWT event queues system-wide, causing the application | ||
| 116 | * or applet to misbehave in an insecure manner.</td> | ||
| 117 | * </tr> | ||
| 118 | * | ||
| 119 | * <tr> | ||
| 120 | * <td>readDisplayPixels</td> | ||
| 121 | * <td>Readback of pixels from the display screen</td> | ||
| 122 | * <td>Interfaces such as the java.awt.Composite interface or the | ||
| 123 | * java.awt.Robot class allow arbitrary code to examine pixels on the | ||
| 124 | * display enable malicious code to snoop on the activities of the user.</td> | ||
| 125 | * </tr> | ||
| 126 | * | ||
| 127 | * <tr> | ||
| 128 | * <td>replaceKeyboardFocusManager</td> | ||
| 129 | * <td>Sets the <code>KeyboardFocusManager</code> for | ||
| 130 | * a particular thread. | ||
| 131 | * <td>When <code>SecurityManager</code> is installed, the invoking | ||
| 132 | * thread must be granted this permission in order to replace | ||
| 133 | * the current <code>KeyboardFocusManager</code>. If permission | ||
| 134 | * is not granted, a <code>SecurityException</code> will be thrown. | ||
| 135 | * </tr> | ||
| 136 | * | ||
| 137 | * <tr> | ||
| 138 | * <td>setAppletStub</td> | ||
| 139 | * <td>Setting the stub which implements Applet container services</td> | ||
| 140 | * <td>Malicious code could set an applet's stub and result in unexpected | ||
| 141 | * behavior or denial of service to an applet.</td> | ||
| 142 | * </tr> | ||
| 143 | * | ||
| 144 | * <tr> | ||
| 145 | * <td>setWindowAlwaysOnTop</td> | ||
| 146 | * <td>Setting always-on-top property of the window: {@link Window#setAlwaysOnTop}</td> | ||
| 147 | * <td>The malicious window might make itself look and behave like a real full desktop, so that | ||
| 148 | * information entered by the unsuspecting user is captured and subsequently misused </td> | ||
| 149 | * </tr> | ||
| 150 | * | ||
| 151 | * <tr> | ||
| 152 | * <td>showWindowWithoutWarningBanner</td> | ||
| 153 | * <td>Display of a window without also displaying a banner warning | ||
| 154 | * that the window was created by an applet</td> | ||
| 155 | * <td>Without this warning, | ||
| 156 | * an applet may pop up windows without the user knowing that they | ||
| 157 | * belong to an applet. Since users may make security-sensitive | ||
| 158 | * decisions based on whether or not the window belongs to an applet | ||
| 159 | * (entering a username and password into a dialog box, for example), | ||
| 160 | * disabling this warning banner may allow applets to trick the user | ||
| 161 | * into entering such information.</td> | ||
| 162 | * </tr> | ||
| 163 | * | ||
| 164 | * <tr> | ||
| 165 | * <td>toolkitModality</td> | ||
| 166 | * <td>Creating {@link Dialog.ModalityType#TOOLKIT_MODAL TOOLKIT_MODAL} dialogs | ||
| 167 | * and setting the {@link Dialog.ModalExclusionType#TOOLKIT_EXCLUDE | ||
| 168 | * TOOLKIT_EXCLUDE} window property.</td> | ||
| 169 | * <td>When a toolkit-modal dialog is shown from an applet, it blocks all other | ||
| 170 | * applets in the browser. When launching applications from Java Web Start, | ||
| 171 | * its windows (such as the security dialog) may also be blocked by toolkit-modal | ||
| 172 | * dialogs, shown from these applications.</td> | ||
| 173 | * </tr> | ||
| 174 | * | ||
| 175 | * <tr> | ||
| 176 | * <td>watchMousePointer</td> | ||
| 177 | * <td>Getting the information about the mouse pointer position at any | ||
| 178 | * time</td> | ||
| 179 | * <td>Constantly watching the mouse pointer, | ||
| 180 | * an applet can make guesses about what the user is doing, i.e. moving | ||
| 181 | * the mouse to the lower left corner of the screen most likely means that | ||
| 182 | * the user is about to launch an application. If a virtual keypad is used | ||
| 183 | * so that keyboard is emulated using the mouse, an applet may guess what | ||
| 184 | * is being typed.</td> | ||
| 185 | * </tr> | ||
| 186 | * </table> | ||
| 187 | * | ||
| 188 | * @see java.security.BasicPermission | ||
| 189 | * @see java.security.Permission | ||
| 190 | * @see java.security.Permissions | ||
| 191 | * @see java.security.PermissionCollection | ||
| 192 | * @see java.lang.SecurityManager | ||
| 193 | * | ||
| 194 | * | ||
| 195 | * @author Marianne Mueller | ||
| 196 | * @author Roland Schemers | ||
| 197 | */ | ||
| 198 | |||
| 199 | public final class AWTPermission extends BasicPermission { | ||
| 200 | |||
| 201 | /** use serialVersionUID from the Java 2 platform for interoperability */ | ||
| 202 | private static final long serialVersionUID = 8890392402588814465L; | ||
| 203 | |||
| 204 | /** | ||
| 205 | * Creates a new <code>AWTPermission</code> with the specified name. | ||
| 206 | * The name is the symbolic name of the <code>AWTPermission</code>, | ||
| 207 | * such as "topLevelWindow", "systemClipboard", etc. An asterisk | ||
| 208 | * may be used to indicate all AWT permissions. | ||
| 209 | * | ||
| 210 | * @param name the name of the AWTPermission | ||
| 211 | * | ||
| 212 | * @throws NullPointerException if <code>name</code> is <code>null</code>. | ||
| 213 | * @throws IllegalArgumentException if <code>name</code> is empty. | ||
| 214 | */ | ||
| 215 | |||
| 216 | public AWTPermission(String name) | ||
| 217 | { | ||
| 218 | super(name); | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Creates a new <code>AWTPermission</code> object with the specified name. | ||
| 223 | * The name is the symbolic name of the <code>AWTPermission</code>, and the | ||
| 224 | * actions string is currently unused and should be <code>null</code>. | ||
| 225 | * | ||
| 226 | * @param name the name of the <code>AWTPermission</code> | ||
| 227 | * @param actions should be <code>null</code> | ||
| 228 | * | ||
| 229 | * @throws NullPointerException if <code>name</code> is <code>null</code>. | ||
| 230 | * @throws IllegalArgumentException if <code>name</code> is empty. | ||
| 231 | */ | ||
| 232 | |||
| 233 | public AWTPermission(String name, String actions) | ||
| 234 | { | ||
| 235 | super(name, actions); | ||
| 236 | } | ||
| 237 | } | ||
Binary file not shown.
| @@ -0,0 +1,59 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2002, 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 java.awt; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * An interface for events that know how to dispatch themselves. | ||
| 30 | * By implementing this interface an event can be placed upon the event | ||
| 31 | * queue and its <code>dispatch()</code> method will be called when the event | ||
| 32 | * is dispatched, using the <code>EventDispatchThread</code>. | ||
| 33 | * <p> | ||
| 34 | * This is a very useful mechanism for avoiding deadlocks. If | ||
| 35 | * a thread is executing in a critical section (i.e., it has entered | ||
| 36 | * one or more monitors), calling other synchronized code may | ||
| 37 | * cause deadlocks. To avoid the potential deadlocks, an | ||
| 38 | * <code>ActiveEvent</code> can be created to run the second section of | ||
| 39 | * code at later time. If there is contention on the monitor, | ||
| 40 | * the second thread will simply block until the first thread | ||
| 41 | * has finished its work and exited its monitors. | ||
| 42 | * <p> | ||
| 43 | * For security reasons, it is often desirable to use an <code>ActiveEvent</code> | ||
| 44 | * to avoid calling untrusted code from a critical thread. For | ||
| 45 | * instance, peer implementations can use this facility to avoid | ||
| 46 | * making calls into user code from a system thread. Doing so avoids | ||
| 47 | * potential deadlocks and denial-of-service attacks. | ||
| 48 | * | ||
| 49 | * @author Timothy Prinzing | ||
| 50 | * @since 1.2 | ||
| 51 | */ | ||
| 52 | public interface ActiveEvent { | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Dispatch the event to its target, listeners of the events source, | ||
| 56 | * or do whatever it is this event is supposed to do. | ||
| 57 | */ | ||
| 58 | public void dispatch(); | ||
| 59 | } | ||
Binary file not shown.
| @@ -0,0 +1,159 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1996, 2003, 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 java.awt; | ||
| 27 | |||
| 28 | import java.awt.event.*; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The interface for objects which have an adjustable numeric value | ||
| 32 | * contained within a bounded range of values. | ||
| 33 | * | ||
| 34 | * @author Amy Fowler | ||
| 35 | * @author Tim Prinzing | ||
| 36 | */ | ||
| 37 | |||
| 38 | public interface Adjustable { | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Indicates that the <code>Adjustable</code> has horizontal orientation. | ||
| 42 | */ | ||
| 43 | public static final int HORIZONTAL = 0; | ||
| 44 | |||
| 45 | /** | ||
| 46 | * Indicates that the <code>Adjustable</code> has vertical orientation. | ||
| 47 | */ | ||
| 48 | public static final int VERTICAL = 1; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Indicates that the <code>Adjustable</code> has no orientation. | ||
| 52 | */ | ||
| 53 | public static final int NO_ORIENTATION = 2; | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Gets the orientation of the adjustable object. | ||
| 57 | * @return the orientation of the adjustable object; | ||
| 58 | * either <code>HORIZONTAL</code>, <code>VERTICAL</code>, | ||
| 59 | * or <code>NO_ORIENTATION</code> | ||
| 60 | */ | ||
| 61 | int getOrientation(); | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Sets the minimum value of the adjustable object. | ||
| 65 | * @param min the minimum value | ||
| 66 | */ | ||
| 67 | void setMinimum(int min); | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Gets the minimum value of the adjustable object. | ||
| 71 | * @return the minimum value of the adjustable object | ||
| 72 | */ | ||
| 73 | int getMinimum(); | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Sets the maximum value of the adjustable object. | ||
| 77 | * @param max the maximum value | ||
| 78 | */ | ||
| 79 | void setMaximum(int max); | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Gets the maximum value of the adjustable object. | ||
| 83 | * @return the maximum value of the adjustable object | ||
| 84 | */ | ||
| 85 | int getMaximum(); | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Sets the unit value increment for the adjustable object. | ||
| 89 | * @param u the unit increment | ||
| 90 | */ | ||
| 91 | void setUnitIncrement(int u); | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Gets the unit value increment for the adjustable object. | ||
| 95 | * @return the unit value increment for the adjustable object | ||
| 96 | */ | ||
| 97 | int getUnitIncrement(); | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Sets the block value increment for the adjustable object. | ||
| 101 | * @param b the block increment | ||
| 102 | */ | ||
| 103 | void setBlockIncrement(int b); | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Gets the block value increment for the adjustable object. | ||
| 107 | * @return the block value increment for the adjustable object | ||
| 108 | */ | ||
| 109 | int getBlockIncrement(); | ||
| 110 | |||
| 111 | /** | ||
| 112 | * Sets the length of the proportional indicator of the | ||
| 113 | * adjustable object. | ||
| 114 | * @param v the length of the indicator | ||
| 115 | */ | ||
| 116 | void setVisibleAmount(int v); | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Gets the length of the proportional indicator. | ||
| 120 | * @return the length of the proportional indicator | ||
| 121 | */ | ||
| 122 | int getVisibleAmount(); | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Sets the current value of the adjustable object. If | ||
| 126 | * the value supplied is less than <code>minimum</code> | ||
| 127 | * or greater than <code>maximum</code> - <code>visibleAmount</code>, | ||
| 128 | * then one of those values is substituted, as appropriate. | ||
| 129 | * <p> | ||
| 130 | * Calling this method does not fire an | ||
| 131 | * <code>AdjustmentEvent</code>. | ||
| 132 | * | ||
| 133 | * @param v the current value, between <code>minimum</code> | ||
| 134 | * and <code>maximum</code> - <code>visibleAmount</code> | ||
| 135 | */ | ||
| 136 | void setValue(int v); | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Gets the current value of the adjustable object. | ||
| 140 | * @return the current value of the adjustable object | ||
| 141 | */ | ||
| 142 | int getValue(); | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Adds a listener to receive adjustment events when the value of | ||
| 146 | * the adjustable object changes. | ||
| 147 | * @param l the listener to receive events | ||
| 148 | * @see AdjustmentEvent | ||
| 149 | */ | ||
| 150 | void addAdjustmentListener(AdjustmentListener l); | ||
| 151 | |||
| 152 | /** | ||
| 153 | * Removes an adjustment listener. | ||
| 154 | * @param l the listener being removed | ||
| 155 | * @see AdjustmentEvent | ||
| 156 | */ | ||
| 157 | void removeAdjustmentListener(AdjustmentListener l); | ||
| 158 | |||
| 159 | } | ||
Binary file not shown.
| @@ -0,0 +1,805 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2010, 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 java.awt; | ||
| 27 | |||
| 28 | import java.awt.image.ColorModel; | ||
| 29 | import sun.java2d.SunCompositeContext; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * The <code>AlphaComposite</code> class implements basic alpha | ||
| 33 | * compositing rules for combining source and destination colors | ||
| 34 | * to achieve blending and transparency effects with graphics and | ||
| 35 | * images. | ||
| 36 | * The specific rules implemented by this class are the basic set | ||
| 37 | * of 12 rules described in | ||
| 38 | * T. Porter and T. Duff, "Compositing Digital Images", SIGGRAPH 84, | ||
| 39 | * 253-259. | ||
| 40 | * The rest of this documentation assumes some familiarity with the | ||
| 41 | * definitions and concepts outlined in that paper. | ||
| 42 | * | ||
| 43 | * <p> | ||
| 44 | * This class extends the standard equations defined by Porter and | ||
| 45 | * Duff to include one additional factor. | ||
| 46 | * An instance of the <code>AlphaComposite</code> class can contain | ||
| 47 | * an alpha value that is used to modify the opacity or coverage of | ||
| 48 | * every source pixel before it is used in the blending equations. | ||
| 49 | * | ||
| 50 | * <p> | ||
| 51 | * It is important to note that the equations defined by the Porter | ||
| 52 | * and Duff paper are all defined to operate on color components | ||
| 53 | * that are premultiplied by their corresponding alpha components. | ||
| 54 | * Since the <code>ColorModel</code> and <code>Raster</code> classes | ||
| 55 | * allow the storage of pixel data in either premultiplied or | ||
| 56 | * non-premultiplied form, all input data must be normalized into | ||
| 57 | * premultiplied form before applying the equations and all results | ||
| 58 | * might need to be adjusted back to the form required by the destination | ||
| 59 | * before the pixel values are stored. | ||
| 60 | * | ||
| 61 | * <p> | ||
| 62 | * Also note that this class defines only the equations | ||
| 63 | * for combining color and alpha values in a purely mathematical | ||
| 64 | * sense. The accurate application of its equations depends | ||
| 65 | * on the way the data is retrieved from its sources and stored | ||
| 66 | * in its destinations. | ||
| 67 | * See <a href="#caveats">Implementation Caveats</a> | ||
| 68 | * for further information. | ||
| 69 | * | ||
| 70 | * <p> | ||
| 71 | * The following factors are used in the description of the blending | ||
| 72 | * equation in the Porter and Duff paper: | ||
| 73 | * | ||
| 74 | * <blockquote> | ||
| 75 | * <table summary="layout"> | ||
| 76 | * <tr><th align=left>Factor <th align=left>Definition | ||
| 77 | * <tr><td><em>A<sub>s</sub></em><td>the alpha component of the source pixel | ||
| 78 | * <tr><td><em>C<sub>s</sub></em><td>a color component of the source pixel in premultiplied form | ||
| 79 | * <tr><td><em>A<sub>d</sub></em><td>the alpha component of the destination pixel | ||
| 80 | * <tr><td><em>C<sub>d</sub></em><td>a color component of the destination pixel in premultiplied form | ||
| 81 | * <tr><td><em>F<sub>s</sub></em><td>the fraction of the source pixel that contributes to the output | ||
| 82 | * <tr><td><em>F<sub>d</sub></em><td>the fraction of the destination pixel that contributes | ||
| 83 | * to the output | ||
| 84 | * <tr><td><em>A<sub>r</sub></em><td>the alpha component of the result | ||
| 85 | * <tr><td><em>C<sub>r</sub></em><td>a color component of the result in premultiplied form | ||
| 86 | * </table> | ||
| 87 | * </blockquote> | ||
| 88 | * | ||
| 89 | * <p> | ||
| 90 | * Using these factors, Porter and Duff define 12 ways of choosing | ||
| 91 | * the blending factors <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em> to | ||
| 92 | * produce each of 12 desirable visual effects. | ||
| 93 | * The equations for determining <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em> | ||
| 94 | * are given in the descriptions of the 12 static fields | ||
| 95 | * that specify visual effects. | ||
| 96 | * For example, | ||
| 97 | * the description for | ||
| 98 | * <a href="#SRC_OVER"><code>SRC_OVER</code></a> | ||
| 99 | * specifies that <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>). | ||
| 100 | * Once a set of equations for determining the blending factors is | ||
| 101 | * known they can then be applied to each pixel to produce a result | ||
| 102 | * using the following set of equations: | ||
| 103 | * | ||
| 104 | * <pre> | ||
| 105 | * <em>F<sub>s</sub></em> = <em>f</em>(<em>A<sub>d</sub></em>) | ||
| 106 | * <em>F<sub>d</sub></em> = <em>f</em>(<em>A<sub>s</sub></em>) | ||
| 107 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>F<sub>s</sub></em> + <em>A<sub>d</sub></em>*<em>F<sub>d</sub></em> | ||
| 108 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>F<sub>s</sub></em> + <em>C<sub>d</sub></em>*<em>F<sub>d</sub></em></pre> | ||
| 109 | * | ||
| 110 | * <p> | ||
| 111 | * The following factors will be used to discuss our extensions to | ||
| 112 | * the blending equation in the Porter and Duff paper: | ||
| 113 | * | ||
| 114 | * <blockquote> | ||
| 115 | * <table summary="layout"> | ||
| 116 | * <tr><th align=left>Factor <th align=left>Definition | ||
| 117 | * <tr><td><em>C<sub>sr</sub></em> <td>one of the raw color components of the source pixel | ||
| 118 | * <tr><td><em>C<sub>dr</sub></em> <td>one of the raw color components of the destination pixel | ||
| 119 | * <tr><td><em>A<sub>ac</sub></em> <td>the "extra" alpha component from the AlphaComposite instance | ||
| 120 | * <tr><td><em>A<sub>sr</sub></em> <td>the raw alpha component of the source pixel | ||
| 121 | * <tr><td><em>A<sub>dr</sub></em><td>the raw alpha component of the destination pixel | ||
| 122 | * <tr><td><em>A<sub>df</sub></em> <td>the final alpha component stored in the destination | ||
| 123 | * <tr><td><em>C<sub>df</sub></em> <td>the final raw color component stored in the destination | ||
| 124 | * </table> | ||
| 125 | *</blockquote> | ||
| 126 | * | ||
| 127 | * <h3>Preparing Inputs</h3> | ||
| 128 | * | ||
| 129 | * <p> | ||
| 130 | * The <code>AlphaComposite</code> class defines an additional alpha | ||
| 131 | * value that is applied to the source alpha. | ||
| 132 | * This value is applied as if an implicit SRC_IN rule were first | ||
| 133 | * applied to the source pixel against a pixel with the indicated | ||
| 134 | * alpha by multiplying both the raw source alpha and the raw | ||
| 135 | * source colors by the alpha in the <code>AlphaComposite</code>. | ||
| 136 | * This leads to the following equation for producing the alpha | ||
| 137 | * used in the Porter and Duff blending equation: | ||
| 138 | * | ||
| 139 | * <pre> | ||
| 140 | * <em>A<sub>s</sub></em> = <em>A<sub>sr</sub></em> * <em>A<sub>ac</sub></em> </pre> | ||
| 141 | * | ||
| 142 | * All of the raw source color components need to be multiplied | ||
| 143 | * by the alpha in the <code>AlphaComposite</code> instance. | ||
| 144 | * Additionally, if the source was not in premultiplied form | ||
| 145 | * then the color components also need to be multiplied by the | ||
| 146 | * source alpha. | ||
| 147 | * Thus, the equation for producing the source color components | ||
| 148 | * for the Porter and Duff equation depends on whether the source | ||
| 149 | * pixels are premultiplied or not: | ||
| 150 | * | ||
| 151 | * <pre> | ||
| 152 | * <em>C<sub>s</sub></em> = <em>C<sub>sr</sub></em> * <em>A<sub>sr</sub></em> * <em>A<sub>ac</sub></em> (if source is not premultiplied) | ||
| 153 | * <em>C<sub>s</sub></em> = <em>C<sub>sr</sub></em> * <em>A<sub>ac</sub></em> (if source is premultiplied) </pre> | ||
| 154 | * | ||
| 155 | * No adjustment needs to be made to the destination alpha: | ||
| 156 | * | ||
| 157 | * <pre> | ||
| 158 | * <em>A<sub>d</sub></em> = <em>A<sub>dr</sub></em> </pre> | ||
| 159 | * | ||
| 160 | * <p> | ||
| 161 | * The destination color components need to be adjusted only if | ||
| 162 | * they are not in premultiplied form: | ||
| 163 | * | ||
| 164 | * <pre> | ||
| 165 | * <em>C<sub>d</sub></em> = <em>C<sub>dr</sub></em> * <em>A<sub>d</sub></em> (if destination is not premultiplied) | ||
| 166 | * <em>C<sub>d</sub></em> = <em>C<sub>dr</sub></em> (if destination is premultiplied) </pre> | ||
| 167 | * | ||
| 168 | * <h3>Applying the Blending Equation</h3> | ||
| 169 | * | ||
| 170 | * <p> | ||
| 171 | * The adjusted <em>A<sub>s</sub></em>, <em>A<sub>d</sub></em>, | ||
| 172 | * <em>C<sub>s</sub></em>, and <em>C<sub>d</sub></em> are used in the standard | ||
| 173 | * Porter and Duff equations to calculate the blending factors | ||
| 174 | * <em>F<sub>s</sub></em> and <em>F<sub>d</sub></em> and then the resulting | ||
| 175 | * premultiplied components <em>A<sub>r</sub></em> and <em>C<sub>r</sub></em>. | ||
| 176 | * | ||
| 177 | * <p> | ||
| 178 | * <h3>Preparing Results</h3> | ||
| 179 | * | ||
| 180 | * <p> | ||
| 181 | * The results only need to be adjusted if they are to be stored | ||
| 182 | * back into a destination buffer that holds data that is not | ||
| 183 | * premultiplied, using the following equations: | ||
| 184 | * | ||
| 185 | * <pre> | ||
| 186 | * <em>A<sub>df</sub></em> = <em>A<sub>r</sub></em> | ||
| 187 | * <em>C<sub>df</sub></em> = <em>C<sub>r</sub></em> (if dest is premultiplied) | ||
| 188 | * <em>C<sub>df</sub></em> = <em>C<sub>r</sub></em> / <em>A<sub>r</sub></em> (if dest is not premultiplied) </pre> | ||
| 189 | * | ||
| 190 | * Note that since the division is undefined if the resulting alpha | ||
| 191 | * is zero, the division in that case is omitted to avoid the "divide | ||
| 192 | * by zero" and the color components are left as | ||
| 193 | * all zeros. | ||
| 194 | * | ||
| 195 | * <p> | ||
| 196 | * <h3>Performance Considerations</h3> | ||
| 197 | * | ||
| 198 | * <p> | ||
| 199 | * For performance reasons, it is preferrable that | ||
| 200 | * <code>Raster</code> objects passed to the <code>compose</code> | ||
| 201 | * method of a {@link CompositeContext} object created by the | ||
| 202 | * <code>AlphaComposite</code> class have premultiplied data. | ||
| 203 | * If either the source <code>Raster</code> | ||
| 204 | * or the destination <code>Raster</code> | ||
| 205 | * is not premultiplied, however, | ||
| 206 | * appropriate conversions are performed before and after the compositing | ||
| 207 | * operation. | ||
| 208 | * | ||
| 209 | * <h3><a name="caveats">Implementation Caveats</a></h3> | ||
| 210 | * | ||
| 211 | * <ul> | ||
| 212 | * <li> | ||
| 213 | * Many sources, such as some of the opaque image types listed | ||
| 214 | * in the <code>BufferedImage</code> class, do not store alpha values | ||
| 215 | * for their pixels. Such sources supply an alpha of 1.0 for | ||
| 216 | * all of their pixels. | ||
| 217 | * | ||
| 218 | * <p> | ||
| 219 | * <li> | ||
| 220 | * Many destinations also have no place to store the alpha values | ||
| 221 | * that result from the blending calculations performed by this class. | ||
| 222 | * Such destinations thus implicitly discard the resulting | ||
| 223 | * alpha values that this class produces. | ||
| 224 | * It is recommended that such destinations should treat their stored | ||
| 225 | * color values as non-premultiplied and divide the resulting color | ||
| 226 | * values by the resulting alpha value before storing the color | ||
| 227 | * values and discarding the alpha value. | ||
| 228 | * | ||
| 229 | * <p> | ||
| 230 | * <li> | ||
| 231 | * The accuracy of the results depends on the manner in which pixels | ||
| 232 | * are stored in the destination. | ||
| 233 | * An image format that provides at least 8 bits of storage per color | ||
| 234 | * and alpha component is at least adequate for use as a destination | ||
| 235 | * for a sequence of a few to a dozen compositing operations. | ||
| 236 | * An image format with fewer than 8 bits of storage per component | ||
| 237 | * is of limited use for just one or two compositing operations | ||
| 238 | * before the rounding errors dominate the results. | ||
| 239 | * An image format | ||
| 240 | * that does not separately store | ||
| 241 | * color components is not a | ||
| 242 | * good candidate for any type of translucent blending. | ||
| 243 | * For example, <code>BufferedImage.TYPE_BYTE_INDEXED</code> | ||
| 244 | * should not be used as a destination for a blending operation | ||
| 245 | * because every operation | ||
| 246 | * can introduce large errors, due to | ||
| 247 | * the need to choose a pixel from a limited palette to match the | ||
| 248 | * results of the blending equations. | ||
| 249 | * | ||
| 250 | * <p> | ||
| 251 | * <li> | ||
| 252 | * Nearly all formats store pixels as discrete integers rather than | ||
| 253 | * the floating point values used in the reference equations above. | ||
| 254 | * The implementation can either scale the integer pixel | ||
| 255 | * values into floating point values in the range 0.0 to 1.0 or | ||
| 256 | * use slightly modified versions of the equations | ||
| 257 | * that operate entirely in the integer domain and yet produce | ||
| 258 | * analogous results to the reference equations. | ||
| 259 | * | ||
| 260 | * <p> | ||
| 261 | * Typically the integer values are related to the floating point | ||
| 262 | * values in such a way that the integer 0 is equated | ||
| 263 | * to the floating point value 0.0 and the integer | ||
| 264 | * 2^<em>n</em>-1 (where <em>n</em> is the number of bits | ||
| 265 | * in the representation) is equated to 1.0. | ||
| 266 | * For 8-bit representations, this means that 0x00 | ||
| 267 | * represents 0.0 and 0xff represents | ||
| 268 | * 1.0. | ||
| 269 | * | ||
| 270 | * <p> | ||
| 271 | * <li> | ||
| 272 | * The internal implementation can approximate some of the equations | ||
| 273 | * and it can also eliminate some steps to avoid unnecessary operations. | ||
| 274 | * For example, consider a discrete integer image with non-premultiplied | ||
| 275 | * alpha values that uses 8 bits per component for storage. | ||
| 276 | * The stored values for a | ||
| 277 | * nearly transparent darkened red might be: | ||
| 278 | * | ||
| 279 | * <pre> | ||
| 280 | * (A, R, G, B) = (0x01, 0xb0, 0x00, 0x00)</pre> | ||
| 281 | * | ||
| 282 | * <p> | ||
| 283 | * If integer math were being used and this value were being | ||
| 284 | * composited in | ||
| 285 | * <a href="#SRC"><code>SRC</code></a> | ||
| 286 | * mode with no extra alpha, then the math would | ||
| 287 | * indicate that the results were (in integer format): | ||
| 288 | * | ||
| 289 | * <pre> | ||
| 290 | * (A, R, G, B) = (0x01, 0x01, 0x00, 0x00)</pre> | ||
| 291 | * | ||
| 292 | * <p> | ||
| 293 | * Note that the intermediate values, which are always in premultiplied | ||
| 294 | * form, would only allow the integer red component to be either 0x00 | ||
| 295 | * or 0x01. When we try to store this result back into a destination | ||
| 296 | * that is not premultiplied, dividing out the alpha will give us | ||
| 297 | * very few choices for the non-premultiplied red value. | ||
| 298 | * In this case an implementation that performs the math in integer | ||
| 299 | * space without shortcuts is likely to end up with the final pixel | ||
| 300 | * values of: | ||
| 301 | * | ||
| 302 | * <pre> | ||
| 303 | * (A, R, G, B) = (0x01, 0xff, 0x00, 0x00)</pre> | ||
| 304 | * | ||
| 305 | * <p> | ||
| 306 | * (Note that 0x01 divided by 0x01 gives you 1.0, which is equivalent | ||
| 307 | * to the value 0xff in an 8-bit storage format.) | ||
| 308 | * | ||
| 309 | * <p> | ||
| 310 | * Alternately, an implementation that uses floating point math | ||
| 311 | * might produce more accurate results and end up returning to the | ||
| 312 | * original pixel value with little, if any, roundoff error. | ||
| 313 | * Or, an implementation using integer math might decide that since | ||
| 314 | * the equations boil down to a virtual NOP on the color values | ||
| 315 | * if performed in a floating point space, it can transfer the | ||
| 316 | * pixel untouched to the destination and avoid all the math entirely. | ||
| 317 | * | ||
| 318 | * <p> | ||
| 319 | * These implementations all attempt to honor the | ||
| 320 | * same equations, but use different tradeoffs of integer and | ||
| 321 | * floating point math and reduced or full equations. | ||
| 322 | * To account for such differences, it is probably best to | ||
| 323 | * expect only that the premultiplied form of the results to | ||
| 324 | * match between implementations and image formats. In this | ||
| 325 | * case both answers, expressed in premultiplied form would | ||
| 326 | * equate to: | ||
| 327 | * | ||
| 328 | * <pre> | ||
| 329 | * (A, R, G, B) = (0x01, 0x01, 0x00, 0x00)</pre> | ||
| 330 | * | ||
| 331 | * <p> | ||
| 332 | * and thus they would all match. | ||
| 333 | * | ||
| 334 | * <p> | ||
| 335 | * <li> | ||
| 336 | * Because of the technique of simplifying the equations for | ||
| 337 | * calculation efficiency, some implementations might perform | ||
| 338 | * differently when encountering result alpha values of 0.0 | ||
| 339 | * on a non-premultiplied destination. | ||
| 340 | * Note that the simplification of removing the divide by alpha | ||
| 341 | * in the case of the SRC rule is technically not valid if the | ||
| 342 | * denominator (alpha) is 0. | ||
| 343 | * But, since the results should only be expected to be accurate | ||
| 344 | * when viewed in premultiplied form, a resulting alpha of 0 | ||
| 345 | * essentially renders the resulting color components irrelevant | ||
| 346 | * and so exact behavior in this case should not be expected. | ||
| 347 | * </ul> | ||
| 348 | * @see Composite | ||
| 349 | * @see CompositeContext | ||
| 350 | */ | ||
| 351 | |||
| 352 | public final class AlphaComposite implements Composite { | ||
| 353 | /** | ||
| 354 | * Both the color and the alpha of the destination are cleared | ||
| 355 | * (Porter-Duff Clear rule). | ||
| 356 | * Neither the source nor the destination is used as input. | ||
| 357 | *<p> | ||
| 358 | * <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = 0, thus: | ||
| 359 | *<pre> | ||
| 360 | * <em>A<sub>r</sub></em> = 0 | ||
| 361 | * <em>C<sub>r</sub></em> = 0 | ||
| 362 | *</pre> | ||
| 363 | */ | ||
| 364 | public static final int CLEAR = 1; | ||
| 365 | |||
| 366 | /** | ||
| 367 | * The source is copied to the destination | ||
| 368 | * (Porter-Duff Source rule). | ||
| 369 | * The destination is not used as input. | ||
| 370 | *<p> | ||
| 371 | * <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = 0, thus: | ||
| 372 | *<pre> | ||
| 373 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em> | ||
| 374 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em> | ||
| 375 | *</pre> | ||
| 376 | */ | ||
| 377 | public static final int SRC = 2; | ||
| 378 | |||
| 379 | /** | ||
| 380 | * The destination is left untouched | ||
| 381 | * (Porter-Duff Destination rule). | ||
| 382 | *<p> | ||
| 383 | * <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = 1, thus: | ||
| 384 | *<pre> | ||
| 385 | * <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em> | ||
| 386 | * <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em> | ||
| 387 | *</pre> | ||
| 388 | * @since 1.4 | ||
| 389 | */ | ||
| 390 | public static final int DST = 9; | ||
| 391 | // Note that DST was added in 1.4 so it is numbered out of order... | ||
| 392 | |||
| 393 | /** | ||
| 394 | * The source is composited over the destination | ||
| 395 | * (Porter-Duff Source Over Destination rule). | ||
| 396 | *<p> | ||
| 397 | * <em>F<sub>s</sub></em> = 1 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus: | ||
| 398 | *<pre> | ||
| 399 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em> + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 400 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em> + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 401 | *</pre> | ||
| 402 | */ | ||
| 403 | public static final int SRC_OVER = 3; | ||
| 404 | |||
| 405 | /** | ||
| 406 | * The destination is composited over the source and | ||
| 407 | * the result replaces the destination | ||
| 408 | * (Porter-Duff Destination Over Source rule). | ||
| 409 | *<p> | ||
| 410 | * <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = 1, thus: | ||
| 411 | *<pre> | ||
| 412 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em> | ||
| 413 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em> | ||
| 414 | *</pre> | ||
| 415 | */ | ||
| 416 | public static final int DST_OVER = 4; | ||
| 417 | |||
| 418 | /** | ||
| 419 | * The part of the source lying inside of the destination replaces | ||
| 420 | * the destination | ||
| 421 | * (Porter-Duff Source In Destination rule). | ||
| 422 | *<p> | ||
| 423 | * <em>F<sub>s</sub></em> = <em>A<sub>d</sub></em> and <em>F<sub>d</sub></em> = 0, thus: | ||
| 424 | *<pre> | ||
| 425 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>A<sub>d</sub></em> | ||
| 426 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>A<sub>d</sub></em> | ||
| 427 | *</pre> | ||
| 428 | */ | ||
| 429 | public static final int SRC_IN = 5; | ||
| 430 | |||
| 431 | /** | ||
| 432 | * The part of the destination lying inside of the source | ||
| 433 | * replaces the destination | ||
| 434 | * (Porter-Duff Destination In Source rule). | ||
| 435 | *<p> | ||
| 436 | * <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = <em>A<sub>s</sub></em>, thus: | ||
| 437 | *<pre> | ||
| 438 | * <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>*<em>A<sub>s</sub></em> | ||
| 439 | * <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>*<em>A<sub>s</sub></em> | ||
| 440 | *</pre> | ||
| 441 | */ | ||
| 442 | public static final int DST_IN = 6; | ||
| 443 | |||
| 444 | /** | ||
| 445 | * The part of the source lying outside of the destination | ||
| 446 | * replaces the destination | ||
| 447 | * (Porter-Duff Source Held Out By Destination rule). | ||
| 448 | *<p> | ||
| 449 | * <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = 0, thus: | ||
| 450 | *<pre> | ||
| 451 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) | ||
| 452 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) | ||
| 453 | *</pre> | ||
| 454 | */ | ||
| 455 | public static final int SRC_OUT = 7; | ||
| 456 | |||
| 457 | /** | ||
| 458 | * The part of the destination lying outside of the source | ||
| 459 | * replaces the destination | ||
| 460 | * (Porter-Duff Destination Held Out By Source rule). | ||
| 461 | *<p> | ||
| 462 | * <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus: | ||
| 463 | *<pre> | ||
| 464 | * <em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 465 | * <em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 466 | *</pre> | ||
| 467 | */ | ||
| 468 | public static final int DST_OUT = 8; | ||
| 469 | |||
| 470 | // Rule 9 is DST which is defined above where it fits into the | ||
| 471 | // list logically, rather than numerically | ||
| 472 | // | ||
| 473 | // public static final int DST = 9; | ||
| 474 | |||
| 475 | /** | ||
| 476 | * The part of the source lying inside of the destination | ||
| 477 | * is composited onto the destination | ||
| 478 | * (Porter-Duff Source Atop Destination rule). | ||
| 479 | *<p> | ||
| 480 | * <em>F<sub>s</sub></em> = <em>A<sub>d</sub></em> and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus: | ||
| 481 | *<pre> | ||
| 482 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*<em>A<sub>d</sub></em> + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) = <em>A<sub>d</sub></em> | ||
| 483 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*<em>A<sub>d</sub></em> + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 484 | *</pre> | ||
| 485 | * @since 1.4 | ||
| 486 | */ | ||
| 487 | public static final int SRC_ATOP = 10; | ||
| 488 | |||
| 489 | /** | ||
| 490 | * The part of the destination lying inside of the source | ||
| 491 | * is composited over the source and replaces the destination | ||
| 492 | * (Porter-Duff Destination Atop Source rule). | ||
| 493 | *<p> | ||
| 494 | * <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = <em>A<sub>s</sub></em>, thus: | ||
| 495 | *<pre> | ||
| 496 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em>*<em>A<sub>s</sub></em> = <em>A<sub>s</sub></em> | ||
| 497 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em>*<em>A<sub>s</sub></em> | ||
| 498 | *</pre> | ||
| 499 | * @since 1.4 | ||
| 500 | */ | ||
| 501 | public static final int DST_ATOP = 11; | ||
| 502 | |||
| 503 | /** | ||
| 504 | * The part of the source that lies outside of the destination | ||
| 505 | * is combined with the part of the destination that lies outside | ||
| 506 | * of the source | ||
| 507 | * (Porter-Duff Source Xor Destination rule). | ||
| 508 | *<p> | ||
| 509 | * <em>F<sub>s</sub></em> = (1-<em>A<sub>d</sub></em>) and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus: | ||
| 510 | *<pre> | ||
| 511 | * <em>A<sub>r</sub></em> = <em>A<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 512 | * <em>C<sub>r</sub></em> = <em>C<sub>s</sub></em>*(1-<em>A<sub>d</sub></em>) + <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>) | ||
| 513 | *</pre> | ||
| 514 | * @since 1.4 | ||
| 515 | */ | ||
| 516 | public static final int XOR = 12; | ||
| 517 | |||
| 518 | /** | ||
| 519 | * <code>AlphaComposite</code> object that implements the opaque CLEAR rule | ||
| 520 | * with an alpha of 1.0f. | ||
| 521 | * @see #CLEAR | ||
| 522 | */ | ||
| 523 | public static final AlphaComposite Clear = new AlphaComposite(CLEAR); | ||
| 524 | |||
| 525 | /** | ||
| 526 | * <code>AlphaComposite</code> object that implements the opaque SRC rule | ||
| 527 | * with an alpha of 1.0f. | ||
| 528 | * @see #SRC | ||
| 529 | */ | ||
| 530 | public static final AlphaComposite Src = new AlphaComposite(SRC); | ||
| 531 | |||
| 532 | /** | ||
| 533 | * <code>AlphaComposite</code> object that implements the opaque DST rule | ||
| 534 | * with an alpha of 1.0f. | ||
| 535 | * @see #DST | ||
| 536 | * @since 1.4 | ||
| 537 | */ | ||
| 538 | public static final AlphaComposite Dst = new AlphaComposite(DST); | ||
| 539 | |||
| 540 | /** | ||
| 541 | * <code>AlphaComposite</code> object that implements the opaque SRC_OVER rule | ||
| 542 | * with an alpha of 1.0f. | ||
| 543 | * @see #SRC_OVER | ||
| 544 | */ | ||
| 545 | public static final AlphaComposite SrcOver = new AlphaComposite(SRC_OVER); | ||
| 546 | |||
| 547 | /** | ||
| 548 | * <code>AlphaComposite</code> object that implements the opaque DST_OVER rule | ||
| 549 | * with an alpha of 1.0f. | ||
| 550 | * @see #DST_OVER | ||
| 551 | */ | ||
| 552 | public static final AlphaComposite DstOver = new AlphaComposite(DST_OVER); | ||
| 553 | |||
| 554 | /** | ||
| 555 | * <code>AlphaComposite</code> object that implements the opaque SRC_IN rule | ||
| 556 | * with an alpha of 1.0f. | ||
| 557 | * @see #SRC_IN | ||
| 558 | */ | ||
| 559 | public static final AlphaComposite SrcIn = new AlphaComposite(SRC_IN); | ||
| 560 | |||
| 561 | /** | ||
| 562 | * <code>AlphaComposite</code> object that implements the opaque DST_IN rule | ||
| 563 | * with an alpha of 1.0f. | ||
| 564 | * @see #DST_IN | ||
| 565 | */ | ||
| 566 | public static final AlphaComposite DstIn = new AlphaComposite(DST_IN); | ||
| 567 | |||
| 568 | /** | ||
| 569 | * <code>AlphaComposite</code> object that implements the opaque SRC_OUT rule | ||
| 570 | * with an alpha of 1.0f. | ||
| 571 | * @see #SRC_OUT | ||
| 572 | */ | ||
| 573 | public static final AlphaComposite SrcOut = new AlphaComposite(SRC_OUT); | ||
| 574 | |||
| 575 | /** | ||
| 576 | * <code>AlphaComposite</code> object that implements the opaque DST_OUT rule | ||
| 577 | * with an alpha of 1.0f. | ||
| 578 | * @see #DST_OUT | ||
| 579 | */ | ||
| 580 | public static final AlphaComposite DstOut = new AlphaComposite(DST_OUT); | ||
| 581 | |||
| 582 | /** | ||
| 583 | * <code>AlphaComposite</code> object that implements the opaque SRC_ATOP rule | ||
| 584 | * with an alpha of 1.0f. | ||
| 585 | * @see #SRC_ATOP | ||
| 586 | * @since 1.4 | ||
| 587 | */ | ||
| 588 | public static final AlphaComposite SrcAtop = new AlphaComposite(SRC_ATOP); | ||
| 589 | |||
| 590 | /** | ||
| 591 | * <code>AlphaComposite</code> object that implements the opaque DST_ATOP rule | ||
| 592 | * with an alpha of 1.0f. | ||
| 593 | * @see #DST_ATOP | ||
| 594 | * @since 1.4 | ||
| 595 | */ | ||
| 596 | public static final AlphaComposite DstAtop = new AlphaComposite(DST_ATOP); | ||
| 597 | |||
| 598 | /** | ||
| 599 | * <code>AlphaComposite</code> object that implements the opaque XOR rule | ||
| 600 | * with an alpha of 1.0f. | ||
| 601 | * @see #XOR | ||
| 602 | * @since 1.4 | ||
| 603 | */ | ||
| 604 | public static final AlphaComposite Xor = new AlphaComposite(XOR); | ||
| 605 | |||
| 606 | private static final int MIN_RULE = CLEAR; | ||
| 607 | private static final int MAX_RULE = XOR; | ||
| 608 | |||
| 609 | float extraAlpha; | ||
| 610 | int rule; | ||
| 611 | |||
| 612 | private AlphaComposite(int rule) { | ||
| 613 | this(rule, 1.0f); | ||
| 614 | } | ||
| 615 | |||
| 616 | private AlphaComposite(int rule, float alpha) { | ||
| 617 | if (rule < MIN_RULE || rule > MAX_RULE) { | ||
| 618 | throw new IllegalArgumentException("unknown composite rule"); | ||
| 619 | } | ||
| 620 | if (alpha >= 0.0f && alpha <= 1.0f) { | ||
| 621 | this.rule = rule; | ||
| 622 | this.extraAlpha = alpha; | ||
| 623 | } else { | ||
| 624 | throw new IllegalArgumentException("alpha value out of range"); | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | /** | ||
| 629 | * Creates an <code>AlphaComposite</code> object with the specified rule. | ||
| 630 | * @param rule the compositing rule | ||
| 631 | * @throws IllegalArgumentException if <code>rule</code> is not one of | ||
| 632 | * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, | ||
| 633 | * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, | ||
| 634 | * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, | ||
| 635 | * {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR} | ||
| 636 | */ | ||
| 637 | public static AlphaComposite getInstance(int rule) { | ||
| 638 | switch (rule) { | ||
| 639 | case CLEAR: | ||
| 640 | return Clear; | ||
| 641 | case SRC: | ||
| 642 | return Src; | ||
| 643 | case DST: | ||
| 644 | return Dst; | ||
| 645 | case SRC_OVER: | ||
| 646 | return SrcOver; | ||
| 647 | case DST_OVER: | ||
| 648 | return DstOver; | ||
| 649 | case SRC_IN: | ||
| 650 | return SrcIn; | ||
| 651 | case DST_IN: | ||
| 652 | return DstIn; | ||
| 653 | case SRC_OUT: | ||
| 654 | return SrcOut; | ||
| 655 | case DST_OUT: | ||
| 656 | return DstOut; | ||
| 657 | case SRC_ATOP: | ||
| 658 | return SrcAtop; | ||
| 659 | case DST_ATOP: | ||
| 660 | return DstAtop; | ||
| 661 | case XOR: | ||
| 662 | return Xor; | ||
| 663 | default: | ||
| 664 | throw new IllegalArgumentException("unknown composite rule"); | ||
| 665 | } | ||
| 666 | } | ||
| 667 | |||
| 668 | /** | ||
| 669 | * Creates an <code>AlphaComposite</code> object with the specified rule and | ||
| 670 | * the constant alpha to multiply with the alpha of the source. | ||
| 671 | * The source is multiplied with the specified alpha before being composited | ||
| 672 | * with the destination. | ||
| 673 | * @param rule the compositing rule | ||
| 674 | * @param alpha the constant alpha to be multiplied with the alpha of | ||
| 675 | * the source. <code>alpha</code> must be a floating point number in the | ||
| 676 | * inclusive range [0.0, 1.0]. | ||
| 677 | * @throws IllegalArgumentException if | ||
| 678 | * <code>alpha</code> is less than 0.0 or greater than 1.0, or if | ||
| 679 | * <code>rule</code> is not one of | ||
| 680 | * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, | ||
| 681 | * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, | ||
| 682 | * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, | ||
| 683 | * {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR} | ||
| 684 | */ | ||
| 685 | public static AlphaComposite getInstance(int rule, float alpha) { | ||
| 686 | if (alpha == 1.0f) { | ||
| 687 | return getInstance(rule); | ||
| 688 | } | ||
| 689 | return new AlphaComposite(rule, alpha); | ||
| 690 | } | ||
| 691 | |||
| 692 | /** | ||
| 693 | * Creates a context for the compositing operation. | ||
| 694 | * The context contains state that is used in performing | ||
| 695 | * the compositing operation. | ||
| 696 | * @param srcColorModel the {@link ColorModel} of the source | ||
| 697 | * @param dstColorModel the <code>ColorModel</code> of the destination | ||
| 698 | * @return the <code>CompositeContext</code> object to be used to perform | ||
| 699 | * compositing operations. | ||
| 700 | */ | ||
| 701 | public CompositeContext createContext(ColorModel srcColorModel, | ||
| 702 | ColorModel dstColorModel, | ||
| 703 | RenderingHints hints) { | ||
| 704 | return new SunCompositeContext(this, srcColorModel, dstColorModel); | ||
| 705 | } | ||
| 706 | |||
| 707 | /** | ||
| 708 | * Returns the alpha value of this <code>AlphaComposite</code>. If this | ||
| 709 | * <code>AlphaComposite</code> does not have an alpha value, 1.0 is returned. | ||
| 710 | * @return the alpha value of this <code>AlphaComposite</code>. | ||
| 711 | */ | ||
| 712 | public float getAlpha() { | ||
| 713 | return extraAlpha; | ||
| 714 | } | ||
| 715 | |||
| 716 | /** | ||
| 717 | * Returns the compositing rule of this <code>AlphaComposite</code>. | ||
| 718 | * @return the compositing rule of this <code>AlphaComposite</code>. | ||
| 719 | */ | ||
| 720 | public int getRule() { | ||
| 721 | return rule; | ||
| 722 | } | ||
| 723 | |||
| 724 | /** | ||
| 725 | * Returns a similar <code>AlphaComposite</code> object that uses | ||
| 726 | * the specified compositing rule. | ||
| 727 | * If this object already uses the specified compositing rule, | ||
| 728 | * this object is returned. | ||
| 729 | * @return an <code>AlphaComposite</code> object derived from | ||
| 730 | * this object that uses the specified compositing rule. | ||
| 731 | * @param rule the compositing rule | ||
| 732 | * @throws IllegalArgumentException if | ||
| 733 | * <code>rule</code> is not one of | ||
| 734 | * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, | ||
| 735 | * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, | ||
| 736 | * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, | ||
| 737 | * {@link #SRC_ATOP}, {@link #DST_ATOP}, or {@link #XOR} | ||
| 738 | * @since 1.6 | ||
| 739 | */ | ||
| 740 | public AlphaComposite derive(int rule) { | ||
| 741 | return (this.rule == rule) | ||
| 742 | ? this | ||
| 743 | : getInstance(rule, this.extraAlpha); | ||
| 744 | } | ||
| 745 | |||
| 746 | /** | ||
| 747 | * Returns a similar <code>AlphaComposite</code> object that uses | ||
| 748 | * the specified alpha value. | ||
| 749 | * If this object already has the specified alpha value, | ||
| 750 | * this object is returned. | ||
| 751 | * @return an <code>AlphaComposite</code> object derived from | ||
| 752 | * this object that uses the specified alpha value. | ||
| 753 | * @param alpha the constant alpha to be multiplied with the alpha of | ||
| 754 | * the source. <code>alpha</code> must be a floating point number in the | ||
| 755 | * inclusive range [0.0, 1.0]. | ||
| 756 | * @throws IllegalArgumentException if | ||
| 757 | * <code>alpha</code> is less than 0.0 or greater than 1.0 | ||
| 758 | * @since 1.6 | ||
| 759 | */ | ||
| 760 | public AlphaComposite derive(float alpha) { | ||
| 761 | return (this.extraAlpha == alpha) | ||
| 762 | ? this | ||
| 763 | : getInstance(this.rule, alpha); | ||
| 764 | } | ||
| 765 | |||
| 766 | /** | ||
| 767 | * Returns the hashcode for this composite. | ||
| 768 | * @return a hash code for this composite. | ||
| 769 | */ | ||
| 770 | public int hashCode() { | ||
| 771 | return (Float.floatToIntBits(extraAlpha) * 31 + rule); | ||
| 772 | } | ||
| 773 | |||
| 774 | /** | ||
| 775 | * Determines whether the specified object is equal to this | ||
| 776 | * <code>AlphaComposite</code>. | ||
| 777 | * <p> | ||
| 778 | * The result is <code>true</code> if and only if | ||
| 779 | * the argument is not <code>null</code> and is an | ||
| 780 | * <code>AlphaComposite</code> object that has the same | ||
| 781 | * compositing rule and alpha value as this object. | ||
| 782 | * | ||
| 783 | * @param obj the <code>Object</code> to test for equality | ||
| 784 | * @return <code>true</code> if <code>obj</code> equals this | ||
| 785 | * <code>AlphaComposite</code>; <code>false</code> otherwise. | ||
| 786 | */ | ||
| 787 | public boolean equals(Object obj) { | ||
| 788 | if (!(obj instanceof AlphaComposite)) { | ||
| 789 | return false; | ||
| 790 | } | ||
| 791 | |||
| 792 | AlphaComposite ac = (AlphaComposite) obj; | ||
| 793 | |||
| 794 | if (rule != ac.rule) { | ||
| 795 | return false; | ||
| 796 | } | ||
| 797 | |||
| 798 | if (extraAlpha != ac.extraAlpha) { | ||
| 799 | return false; | ||
| 800 | } | ||
| 801 | |||
| 802 | return true; | ||
| 803 | } | ||
| 804 | |||
| 805 | } | ||
Binary file not shown.
| @@ -0,0 +1,56 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1999, 2007, 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 java.awt; | ||
| 27 | |||
| 28 | import sun.util.logging.PlatformLogger; | ||
| 29 | |||
| 30 | abstract class AttributeValue { | ||
| 31 | private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.AttributeValue"); | ||
| 32 | private final int value; | ||
| 33 | private final String[] names; | ||
| 34 | |||
| 35 | protected AttributeValue(int value, String[] names) { | ||
| 36 | if (log.isLoggable(PlatformLogger.FINEST)) { | ||
| 37 | log.finest("value = " + value + ", names = " + names); | ||
| 38 | } | ||
| 39 | |||
| 40 | if (log.isLoggable(PlatformLogger.FINER)) { | ||
| 41 | if ((value < 0) || (names == null) || (value >= names.length)) { | ||
| 42 | log.finer("Assertion failed"); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | this.value = value; | ||
| 46 | this.names = names; | ||
| 47 | } | ||
| 48 | // This hashCode is used by the sun.awt implementation as an array | ||
| 49 | // index. | ||
| 50 | public int hashCode() { | ||
| 51 | return value; | ||
| 52 | } | ||
| 53 | public String toString() { | ||
| 54 | return names[value]; | ||
| 55 | } | ||
| 56 | } | ||
Binary file not shown.
| @@ -0,0 +1,445 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2010, 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 java.awt; | ||
| 27 | |||
| 28 | import java.beans.ConstructorProperties; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The <code>BasicStroke</code> class defines a basic set of rendering | ||
| 32 | * attributes for the outlines of graphics primitives, which are rendered | ||
| 33 | * with a {@link Graphics2D} object that has its Stroke attribute set to | ||
| 34 | * this <code>BasicStroke</code>. | ||
| 35 | * The rendering attributes defined by <code>BasicStroke</code> describe | ||
| 36 | * the shape of the mark made by a pen drawn along the outline of a | ||
| 37 | * {@link Shape} and the decorations applied at the ends and joins of | ||
| 38 | * path segments of the <code>Shape</code>. | ||
| 39 | * These rendering attributes include: | ||
| 40 | * <dl compact> | ||
| 41 | * <dt><i>width</i> | ||
| 42 | * <dd>The pen width, measured perpendicularly to the pen trajectory. | ||
| 43 | * <dt><i>end caps</i> | ||
| 44 | * <dd>The decoration applied to the ends of unclosed subpaths and | ||
| 45 | * dash segments. Subpaths that start and end on the same point are | ||
| 46 | * still considered unclosed if they do not have a CLOSE segment. | ||
| 47 | * See {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE} | ||
| 48 | * for more information on the CLOSE segment. | ||
| 49 | * The three different decorations are: {@link #CAP_BUTT}, | ||
| 50 | * {@link #CAP_ROUND}, and {@link #CAP_SQUARE}. | ||
| 51 | * <dt><i>line joins</i> | ||
| 52 | * <dd>The decoration applied at the intersection of two path segments | ||
| 53 | * and at the intersection of the endpoints of a subpath that is closed | ||
| 54 | * using {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE}. | ||
| 55 | * The three different decorations are: {@link #JOIN_BEVEL}, | ||
| 56 | * {@link #JOIN_MITER}, and {@link #JOIN_ROUND}. | ||
| 57 | * <dt><i>miter limit</i> | ||
| 58 | * <dd>The limit to trim a line join that has a JOIN_MITER decoration. | ||
| 59 | * A line join is trimmed when the ratio of miter length to stroke | ||
| 60 | * width is greater than the miterlimit value. The miter length is | ||
| 61 | * the diagonal length of the miter, which is the distance between | ||
| 62 | * the inside corner and the outside corner of the intersection. | ||
| 63 | * The smaller the angle formed by two line segments, the longer | ||
| 64 | * the miter length and the sharper the angle of intersection. The | ||
| 65 | * default miterlimit value of 10.0f causes all angles less than | ||
| 66 | * 11 degrees to be trimmed. Trimming miters converts | ||
| 67 | * the decoration of the line join to bevel. | ||
| 68 | * <dt><i>dash attributes</i> | ||
| 69 | * <dd>The definition of how to make a dash pattern by alternating | ||
| 70 | * between opaque and transparent sections. | ||
| 71 | * </dl> | ||
| 72 | * All attributes that specify measurements and distances controlling | ||
| 73 | * the shape of the returned outline are measured in the same | ||
| 74 | * coordinate system as the original unstroked <code>Shape</code> | ||
| 75 | * argument. When a <code>Graphics2D</code> object uses a | ||
| 76 | * <code>Stroke</code> object to redefine a path during the execution | ||
| 77 | * of one of its <code>draw</code> methods, the geometry is supplied | ||
| 78 | * in its original form before the <code>Graphics2D</code> transform | ||
| 79 | * attribute is applied. Therefore, attributes such as the pen width | ||
| 80 | * are interpreted in the user space coordinate system of the | ||
| 81 | * <code>Graphics2D</code> object and are subject to the scaling and | ||
| 82 | * shearing effects of the user-space-to-device-space transform in that | ||
| 83 | * particular <code>Graphics2D</code>. | ||
| 84 | * For example, the width of a rendered shape's outline is determined | ||
| 85 | * not only by the width attribute of this <code>BasicStroke</code>, | ||
| 86 | * but also by the transform attribute of the | ||
| 87 | * <code>Graphics2D</code> object. Consider this code: | ||
| 88 | * <blockquote><tt> | ||
| 89 | * // sets the Graphics2D object's Tranform attribute | ||
| 90 | * g2d.scale(10, 10); | ||
| 91 | * // sets the Graphics2D object's Stroke attribute | ||
| 92 | * g2d.setStroke(new BasicStroke(1.5f)); | ||
| 93 | * </tt></blockquote> | ||
| 94 | * Assuming there are no other scaling transforms added to the | ||
| 95 | * <code>Graphics2D</code> object, the resulting line | ||
| 96 | * will be approximately 15 pixels wide. | ||
| 97 | * As the example code demonstrates, a floating-point line | ||
| 98 | * offers better precision, especially when large transforms are | ||
| 99 | * used with a <code>Graphics2D</code> object. | ||
| 100 | * When a line is diagonal, the exact width depends on how the | ||
| 101 | * rendering pipeline chooses which pixels to fill as it traces the | ||
| 102 | * theoretical widened outline. The choice of which pixels to turn | ||
| 103 | * on is affected by the antialiasing attribute because the | ||
| 104 | * antialiasing rendering pipeline can choose to color | ||
| 105 | * partially-covered pixels. | ||
| 106 | * <p> | ||
| 107 | * For more information on the user space coordinate system and the | ||
| 108 | * rendering process, see the <code>Graphics2D</code> class comments. | ||
| 109 | * @see Graphics2D | ||
| 110 | * @author Jim Graham | ||
| 111 | */ | ||
| 112 | public class BasicStroke implements Stroke { | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Joins path segments by extending their outside edges until | ||
| 116 | * they meet. | ||
| 117 | */ | ||
| 118 | public final static int JOIN_MITER = 0; | ||
| 119 | |||
| 120 | /** | ||
| 121 | * Joins path segments by rounding off the corner at a radius | ||
| 122 | * of half the line width. | ||
| 123 | */ | ||
| 124 | public final static int JOIN_ROUND = 1; | ||
| 125 | |||
| 126 | /** | ||
| 127 | * Joins path segments by connecting the outer corners of their | ||
| 128 | * wide outlines with a straight segment. | ||
| 129 | */ | ||
| 130 | public final static int JOIN_BEVEL = 2; | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Ends unclosed subpaths and dash segments with no added | ||
| 134 | * decoration. | ||
| 135 | */ | ||
| 136 | public final static int CAP_BUTT = 0; | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Ends unclosed subpaths and dash segments with a round | ||
| 140 | * decoration that has a radius equal to half of the width | ||
| 141 | * of the pen. | ||
| 142 | */ | ||
| 143 | public final static int CAP_ROUND = 1; | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Ends unclosed subpaths and dash segments with a square | ||
| 147 | * projection that extends beyond the end of the segment | ||
| 148 | * to a distance equal to half of the line width. | ||
| 149 | */ | ||
| 150 | public final static int CAP_SQUARE = 2; | ||
| 151 | |||
| 152 | float width; | ||
| 153 | |||
| 154 | int join; | ||
| 155 | int cap; | ||
| 156 | float miterlimit; | ||
| 157 | |||
| 158 | float dash[]; | ||
| 159 | float dash_phase; | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Constructs a new <code>BasicStroke</code> with the specified | ||
| 163 | * attributes. | ||
| 164 | * @param width the width of this <code>BasicStroke</code>. The | ||
| 165 | * width must be greater than or equal to 0.0f. If width is | ||
| 166 | * set to 0.0f, the stroke is rendered as the thinnest | ||
| 167 | * possible line for the target device and the antialias | ||
| 168 | * hint setting. | ||
| 169 | * @param cap the decoration of the ends of a <code>BasicStroke</code> | ||
| 170 | * @param join the decoration applied where path segments meet | ||
| 171 | * @param miterlimit the limit to trim the miter join. The miterlimit | ||
| 172 | * must be greater than or equal to 1.0f. | ||
| 173 | * @param dash the array representing the dashing pattern | ||
| 174 | * @param dash_phase the offset to start the dashing pattern | ||
| 175 | * @throws IllegalArgumentException if <code>width</code> is negative | ||
| 176 | * @throws IllegalArgumentException if <code>cap</code> is not either | ||
| 177 | * CAP_BUTT, CAP_ROUND or CAP_SQUARE | ||
| 178 | * @throws IllegalArgumentException if <code>miterlimit</code> is less | ||
| 179 | * than 1 and <code>join</code> is JOIN_MITER | ||
| 180 | * @throws IllegalArgumentException if <code>join</code> is not | ||
| 181 | * either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | ||
| 182 | * @throws IllegalArgumentException if <code>dash_phase</code> | ||
| 183 | * is negative and <code>dash</code> is not <code>null</code> | ||
| 184 | * @throws IllegalArgumentException if the length of | ||
| 185 | * <code>dash</code> is zero | ||
| 186 | * @throws IllegalArgumentException if dash lengths are all zero. | ||
| 187 | */ | ||
| 188 | @ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" }) | ||
| 189 | public BasicStroke(float width, int cap, int join, float miterlimit, | ||
| 190 | float dash[], float dash_phase) { | ||
| 191 | if (width < 0.0f) { | ||
| 192 | throw new IllegalArgumentException("negative width"); | ||
| 193 | } | ||
| 194 | if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) { | ||
| 195 | throw new IllegalArgumentException("illegal end cap value"); | ||
| 196 | } | ||
| 197 | if (join == JOIN_MITER) { | ||
| 198 | if (miterlimit < 1.0f) { | ||
| 199 | throw new IllegalArgumentException("miter limit < 1"); | ||
| 200 | } | ||
| 201 | } else if (join != JOIN_ROUND && join != JOIN_BEVEL) { | ||
| 202 | throw new IllegalArgumentException("illegal line join value"); | ||
| 203 | } | ||
| 204 | if (dash != null) { | ||
| 205 | if (dash_phase < 0.0f) { | ||
| 206 | throw new IllegalArgumentException("negative dash phase"); | ||
| 207 | } | ||
| 208 | boolean allzero = true; | ||
| 209 | for (int i = 0; i < dash.length; i++) { | ||
| 210 | float d = dash[i]; | ||
| 211 | if (d > 0.0) { | ||
| 212 | allzero = false; | ||
| 213 | } else if (d < 0.0) { | ||
| 214 | throw new IllegalArgumentException("negative dash length"); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | if (allzero) { | ||
| 218 | throw new IllegalArgumentException("dash lengths all zero"); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | this.width = width; | ||
| 222 | this.cap = cap; | ||
| 223 | this.join = join; | ||
| 224 | this.miterlimit = miterlimit; | ||
| 225 | if (dash != null) { | ||
| 226 | this.dash = (float []) dash.clone(); | ||
| 227 | } | ||
| 228 | this.dash_phase = dash_phase; | ||
| 229 | } | ||
| 230 | |||
| 231 | /** | ||
| 232 | * Constructs a solid <code>BasicStroke</code> with the specified | ||
| 233 | * attributes. | ||
| 234 | * @param width the width of the <code>BasicStroke</code> | ||
| 235 | * @param cap the decoration of the ends of a <code>BasicStroke</code> | ||
| 236 | * @param join the decoration applied where path segments meet | ||
| 237 | * @param miterlimit the limit to trim the miter join | ||
| 238 | * @throws IllegalArgumentException if <code>width</code> is negative | ||
| 239 | * @throws IllegalArgumentException if <code>cap</code> is not either | ||
| 240 | * CAP_BUTT, CAP_ROUND or CAP_SQUARE | ||
| 241 | * @throws IllegalArgumentException if <code>miterlimit</code> is less | ||
| 242 | * than 1 and <code>join</code> is JOIN_MITER | ||
| 243 | * @throws IllegalArgumentException if <code>join</code> is not | ||
| 244 | * either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | ||
| 245 | */ | ||
| 246 | public BasicStroke(float width, int cap, int join, float miterlimit) { | ||
| 247 | this(width, cap, join, miterlimit, null, 0.0f); | ||
| 248 | } | ||
| 249 | |||
| 250 | /** | ||
| 251 | * Constructs a solid <code>BasicStroke</code> with the specified | ||
| 252 | * attributes. The <code>miterlimit</code> parameter is | ||
| 253 | * unnecessary in cases where the default is allowable or the | ||
| 254 | * line joins are not specified as JOIN_MITER. | ||
| 255 | * @param width the width of the <code>BasicStroke</code> | ||
| 256 | * @param cap the decoration of the ends of a <code>BasicStroke</code> | ||
| 257 | * @param join the decoration applied where path segments meet | ||
| 258 | * @throws IllegalArgumentException if <code>width</code> is negative | ||
| 259 | * @throws IllegalArgumentException if <code>cap</code> is not either | ||
| 260 | * CAP_BUTT, CAP_ROUND or CAP_SQUARE | ||
| 261 | * @throws IllegalArgumentException if <code>join</code> is not | ||
| 262 | * either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | ||
| 263 | */ | ||
| 264 | public BasicStroke(float width, int cap, int join) { | ||
| 265 | this(width, cap, join, 10.0f, null, 0.0f); | ||
| 266 | } | ||
| 267 | |||
| 268 | /** | ||
| 269 | * Constructs a solid <code>BasicStroke</code> with the specified | ||
| 270 | * line width and with default values for the cap and join | ||
| 271 | * styles. | ||
| 272 | * @param width the width of the <code>BasicStroke</code> | ||
| 273 | * @throws IllegalArgumentException if <code>width</code> is negative | ||
| 274 | */ | ||
| 275 | public BasicStroke(float width) { | ||
| 276 | this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f); | ||
| 277 | } | ||
| 278 | |||
| 279 | /** | ||
| 280 | * Constructs a new <code>BasicStroke</code> with defaults for all | ||
| 281 | * attributes. | ||
| 282 | * The default attributes are a solid line of width 1.0, CAP_SQUARE, | ||
| 283 | * JOIN_MITER, a miter limit of 10.0. | ||
| 284 | */ | ||
| 285 | public BasicStroke() { | ||
| 286 | this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f); | ||
| 287 | } | ||
| 288 | |||
| 289 | |||
| 290 | /** | ||
| 291 | * Returns a <code>Shape</code> whose interior defines the | ||
| 292 | * stroked outline of a specified <code>Shape</code>. | ||
| 293 | * @param s the <code>Shape</code> boundary be stroked | ||
| 294 | * @return the <code>Shape</code> of the stroked outline. | ||
| 295 | */ | ||
| 296 | public Shape createStrokedShape(Shape s) { | ||
| 297 | sun.java2d.pipe.RenderingEngine re = | ||
| 298 | sun.java2d.pipe.RenderingEngine.getInstance(); | ||
| 299 | return re.createStrokedShape(s, width, cap, join, miterlimit, | ||
| 300 | dash, dash_phase); | ||
| 301 | } | ||
| 302 | |||
| 303 | /** | ||
| 304 | * Returns the line width. Line width is represented in user space, | ||
| 305 | * which is the default-coordinate space used by Java 2D. See the | ||
| 306 | * <code>Graphics2D</code> class comments for more information on | ||
| 307 | * the user space coordinate system. | ||
| 308 | * @return the line width of this <code>BasicStroke</code>. | ||
| 309 | * @see Graphics2D | ||
| 310 | */ | ||
| 311 | public float getLineWidth() { | ||
| 312 | return width; | ||
| 313 | } | ||
| 314 | |||
| 315 | /** | ||
| 316 | * Returns the end cap style. | ||
| 317 | * @return the end cap style of this <code>BasicStroke</code> as one | ||
| 318 | * of the static <code>int</code> values that define possible end cap | ||
| 319 | * styles. | ||
| 320 | */ | ||
| 321 | public int getEndCap() { | ||
| 322 | return cap; | ||
| 323 | } | ||
| 324 | |||
| 325 | /** | ||
| 326 | * Returns the line join style. | ||
| 327 | * @return the line join style of the <code>BasicStroke</code> as one | ||
| 328 | * of the static <code>int</code> values that define possible line | ||
| 329 | * join styles. | ||
| 330 | */ | ||
| 331 | public int getLineJoin() { | ||
| 332 | return join; | ||
| 333 | } | ||
| 334 | |||
| 335 | /** | ||
| 336 | * Returns the limit of miter joins. | ||
| 337 | * @return the limit of miter joins of the <code>BasicStroke</code>. | ||
| 338 | */ | ||
| 339 | public float getMiterLimit() { | ||
| 340 | return miterlimit; | ||
| 341 | } | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Returns the array representing the lengths of the dash segments. | ||
| 345 | * Alternate entries in the array represent the user space lengths | ||
| 346 | * of the opaque and transparent segments of the dashes. | ||
| 347 | * As the pen moves along the outline of the <code>Shape</code> | ||
| 348 | * to be stroked, the user space | ||
| 349 | * distance that the pen travels is accumulated. The distance | ||
| 350 | * value is used to index into the dash array. | ||
| 351 | * The pen is opaque when its current cumulative distance maps | ||
| 352 | * to an even element of the dash array and transparent otherwise. | ||
| 353 | * @return the dash array. | ||
| 354 | */ | ||
| 355 | public float[] getDashArray() { | ||
| 356 | if (dash == null) { | ||
| 357 | return null; | ||
| 358 | } | ||
| 359 | |||
| 360 | return (float[]) dash.clone(); | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Returns the current dash phase. | ||
| 365 | * The dash phase is a distance specified in user coordinates that | ||
| 366 | * represents an offset into the dashing pattern. In other words, the dash | ||
| 367 | * phase defines the point in the dashing pattern that will correspond to | ||
| 368 | * the beginning of the stroke. | ||
| 369 | * @return the dash phase as a <code>float</code> value. | ||
| 370 | */ | ||
| 371 | public float getDashPhase() { | ||
| 372 | return dash_phase; | ||
| 373 | } | ||
| 374 | |||
| 375 | /** | ||
| 376 | * Returns the hashcode for this stroke. | ||
| 377 | * @return a hash code for this stroke. | ||
| 378 | */ | ||
| 379 | public int hashCode() { | ||
| 380 | int hash = Float.floatToIntBits(width); | ||
| 381 | hash = hash * 31 + join; | ||
| 382 | hash = hash * 31 + cap; | ||
| 383 | hash = hash * 31 + Float.floatToIntBits(miterlimit); | ||
| 384 | if (dash != null) { | ||
| 385 | hash = hash * 31 + Float.floatToIntBits(dash_phase); | ||
| 386 | for (int i = 0; i < dash.length; i++) { | ||
| 387 | hash = hash * 31 + Float.floatToIntBits(dash[i]); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | return hash; | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * Returns true if this BasicStroke represents the same | ||
| 395 | * stroking operation as the given argument. | ||
| 396 | */ | ||
| 397 | /** | ||
| 398 | * Tests if a specified object is equal to this <code>BasicStroke</code> | ||
| 399 | * by first testing if it is a <code>BasicStroke</code> and then comparing | ||
| 400 | * its width, join, cap, miter limit, dash, and dash phase attributes with | ||
| 401 | * those of this <code>BasicStroke</code>. | ||
| 402 | * @param obj the specified object to compare to this | ||
| 403 | * <code>BasicStroke</code> | ||
| 404 | * @return <code>true</code> if the width, join, cap, miter limit, dash, and | ||
| 405 | * dash phase are the same for both objects; | ||
| 406 | * <code>false</code> otherwise. | ||
| 407 | */ | ||
| 408 | public boolean equals(Object obj) { | ||
| 409 | if (!(obj instanceof BasicStroke)) { | ||
| 410 | return false; | ||
| 411 | } | ||
| 412 | |||
| 413 | BasicStroke bs = (BasicStroke) obj; | ||
| 414 | if (width != bs.width) { | ||
| 415 | return false; | ||
| 416 | } | ||
| 417 | |||
| 418 | if (join != bs.join) { | ||
| 419 | return false; | ||
| 420 | } | ||
| 421 | |||
| 422 | if (cap != bs.cap) { | ||
| 423 | return false; | ||
| 424 | } | ||
| 425 | |||
| 426 | if (miterlimit != bs.miterlimit) { | ||
| 427 | return false; | ||
| 428 | } | ||
| 429 | |||
| 430 | if (dash != null) { | ||
| 431 | if (dash_phase != bs.dash_phase) { | ||
| 432 | return false; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (!java.util.Arrays.equals(dash, bs.dash)) { | ||
| 436 | return false; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | else if (bs.dash != null) { | ||
| 440 | return false; | ||
| 441 | } | ||
| 442 | |||
| 443 | return true; | ||
| 444 | } | ||
| 445 | } | ||
Binary file not shown.
| @@ -0,0 +1,887 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2006, 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 java.awt; | ||
| 27 | |||
| 28 | import java.util.Hashtable; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * A border layout lays out a container, arranging and resizing | ||
| 32 | * its components to fit in five regions: | ||
| 33 | * north, south, east, west, and center. | ||
| 34 | * Each region may contain no more than one component, and | ||
| 35 | * is identified by a corresponding constant: | ||
| 36 | * <code>NORTH</code>, <code>SOUTH</code>, <code>EAST</code>, | ||
| 37 | * <code>WEST</code>, and <code>CENTER</code>. When adding a | ||
| 38 | * component to a container with a border layout, use one of these | ||
| 39 | * five constants, for example: | ||
| 40 | * <pre> | ||
| 41 | * Panel p = new Panel(); | ||
| 42 | * p.setLayout(new BorderLayout()); | ||
| 43 | * p.add(new Button("Okay"), BorderLayout.SOUTH); | ||
| 44 | * </pre> | ||
| 45 | * As a convenience, <code>BorderLayout</code> interprets the | ||
| 46 | * absence of a string specification the same as the constant | ||
| 47 | * <code>CENTER</code>: | ||
| 48 | * <pre> | ||
| 49 | * Panel p2 = new Panel(); | ||
| 50 | * p2.setLayout(new BorderLayout()); | ||
| 51 | * p2.add(new TextArea()); // Same as p.add(new TextArea(), BorderLayout.CENTER); | ||
| 52 | * </pre> | ||
| 53 | * <p> | ||
| 54 | * In addition, <code>BorderLayout</code> supports the relative | ||
| 55 | * positioning constants, <code>PAGE_START</code>, <code>PAGE_END</code>, | ||
| 56 | * <code>LINE_START</code>, and <code>LINE_END</code>. | ||
| 57 | * In a container whose <code>ComponentOrientation</code> is set to | ||
| 58 | * <code>ComponentOrientation.LEFT_TO_RIGHT</code>, these constants map to | ||
| 59 | * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and | ||
| 60 | * <code>EAST</code>, respectively. | ||
| 61 | * <p> | ||
| 62 | * For compatibility with previous releases, <code>BorderLayout</code> | ||
| 63 | * also includes the relative positioning constants <code>BEFORE_FIRST_LINE</code>, | ||
| 64 | * <code>AFTER_LAST_LINE</code>, <code>BEFORE_LINE_BEGINS</code> and | ||
| 65 | * <code>AFTER_LINE_ENDS</code>. These are equivalent to | ||
| 66 | * <code>PAGE_START</code>, <code>PAGE_END</code>, <code>LINE_START</code> | ||
| 67 | * and <code>LINE_END</code> respectively. For | ||
| 68 | * consistency with the relative positioning constants used by other | ||
| 69 | * components, the latter constants are preferred. | ||
| 70 | * <p> | ||
| 71 | * Mixing both absolute and relative positioning constants can lead to | ||
| 72 | * unpredicable results. If | ||
| 73 | * you use both types, the relative constants will take precedence. | ||
| 74 | * For example, if you add components using both the <code>NORTH</code> | ||
| 75 | * and <code>PAGE_START</code> constants in a container whose | ||
| 76 | * orientation is <code>LEFT_TO_RIGHT</code>, only the | ||
| 77 | * <code>PAGE_START</code> will be layed out. | ||
| 78 | * <p> | ||
| 79 | * NOTE: Currently (in the Java 2 platform v1.2), | ||
| 80 | * <code>BorderLayout</code> does not support vertical | ||
| 81 | * orientations. The <code>isVertical</code> setting on the container's | ||
| 82 | * <code>ComponentOrientation</code> is not respected. | ||
| 83 | * <p> | ||
| 84 | * The components are laid out according to their | ||
| 85 | * preferred sizes and the constraints of the container's size. | ||
| 86 | * The <code>NORTH</code> and <code>SOUTH</code> components may | ||
| 87 | * be stretched horizontally; the <code>EAST</code> and | ||
| 88 | * <code>WEST</code> components may be stretched vertically; | ||
| 89 | * the <code>CENTER</code> component may stretch both horizontally | ||
| 90 | * and vertically to fill any space left over. | ||
| 91 | * <p> | ||
| 92 | * Here is an example of five buttons in an applet laid out using | ||
| 93 | * the <code>BorderLayout</code> layout manager: | ||
| 94 | * <p> | ||
| 95 | * <img src="doc-files/BorderLayout-1.gif" | ||
| 96 | * alt="Diagram of an applet demonstrating BorderLayout. | ||
| 97 | * Each section of the BorderLayout contains a Button corresponding to its position in the layout, one of: | ||
| 98 | * North, West, Center, East, or South." | ||
| 99 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 100 | * <p> | ||
| 101 | * The code for this applet is as follows: | ||
| 102 | * <p> | ||
| 103 | * <hr><blockquote><pre> | ||
| 104 | * import java.awt.*; | ||
| 105 | * import java.applet.Applet; | ||
| 106 | * | ||
| 107 | * public class buttonDir extends Applet { | ||
| 108 | * public void init() { | ||
| 109 | * setLayout(new BorderLayout()); | ||
| 110 | * add(new Button("North"), BorderLayout.NORTH); | ||
| 111 | * add(new Button("South"), BorderLayout.SOUTH); | ||
| 112 | * add(new Button("East"), BorderLayout.EAST); | ||
| 113 | * add(new Button("West"), BorderLayout.WEST); | ||
| 114 | * add(new Button("Center"), BorderLayout.CENTER); | ||
| 115 | * } | ||
| 116 | * } | ||
| 117 | * </pre></blockquote><hr> | ||
| 118 | * <p> | ||
| 119 | * @author Arthur van Hoff | ||
| 120 | * @see java.awt.Container#add(String, Component) | ||
| 121 | * @see java.awt.ComponentOrientation | ||
| 122 | * @since JDK1.0 | ||
| 123 | */ | ||
| 124 | public class BorderLayout implements LayoutManager2, | ||
| 125 | java.io.Serializable { | ||
| 126 | /** | ||
| 127 | * Constructs a border layout with the horizontal gaps | ||
| 128 | * between components. | ||
| 129 | * The horizontal gap is specified by <code>hgap</code>. | ||
| 130 | * | ||
| 131 | * @see #getHgap() | ||
| 132 | * @see #setHgap(int) | ||
| 133 | * | ||
| 134 | * @serial | ||
| 135 | */ | ||
| 136 | int hgap; | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Constructs a border layout with the vertical gaps | ||
| 140 | * between components. | ||
| 141 | * The vertical gap is specified by <code>vgap</code>. | ||
| 142 | * | ||
| 143 | * @see #getVgap() | ||
| 144 | * @see #setVgap(int) | ||
| 145 | * @serial | ||
| 146 | */ | ||
| 147 | int vgap; | ||
| 148 | |||
| 149 | /** | ||
| 150 | * Constant to specify components location to be the | ||
| 151 | * north portion of the border layout. | ||
| 152 | * @serial | ||
| 153 | * @see #getChild(String, boolean) | ||
| 154 | * @see #addLayoutComponent | ||
| 155 | * @see #getLayoutAlignmentX | ||
| 156 | * @see #getLayoutAlignmentY | ||
| 157 | * @see #removeLayoutComponent | ||
| 158 | */ | ||
| 159 | Component north; | ||
| 160 | /** | ||
| 161 | * Constant to specify components location to be the | ||
| 162 | * west portion of the border layout. | ||
| 163 | * @serial | ||
| 164 | * @see #getChild(String, boolean) | ||
| 165 | * @see #addLayoutComponent | ||
| 166 | * @see #getLayoutAlignmentX | ||
| 167 | * @see #getLayoutAlignmentY | ||
| 168 | * @see #removeLayoutComponent | ||
| 169 | */ | ||
| 170 | Component west; | ||
| 171 | /** | ||
| 172 | * Constant to specify components location to be the | ||
| 173 | * east portion of the border layout. | ||
| 174 | * @serial | ||
| 175 | * @see #getChild(String, boolean) | ||
| 176 | * @see #addLayoutComponent | ||
| 177 | * @see #getLayoutAlignmentX | ||
| 178 | * @see #getLayoutAlignmentY | ||
| 179 | * @see #removeLayoutComponent | ||
| 180 | */ | ||
| 181 | Component east; | ||
| 182 | /** | ||
| 183 | * Constant to specify components location to be the | ||
| 184 | * south portion of the border layout. | ||
| 185 | * @serial | ||
| 186 | * @see #getChild(String, boolean) | ||
| 187 | * @see #addLayoutComponent | ||
| 188 | * @see #getLayoutAlignmentX | ||
| 189 | * @see #getLayoutAlignmentY | ||
| 190 | * @see #removeLayoutComponent | ||
| 191 | */ | ||
| 192 | Component south; | ||
| 193 | /** | ||
| 194 | * Constant to specify components location to be the | ||
| 195 | * center portion of the border layout. | ||
| 196 | * @serial | ||
| 197 | * @see #getChild(String, boolean) | ||
| 198 | * @see #addLayoutComponent | ||
| 199 | * @see #getLayoutAlignmentX | ||
| 200 | * @see #getLayoutAlignmentY | ||
| 201 | * @see #removeLayoutComponent | ||
| 202 | */ | ||
| 203 | Component center; | ||
| 204 | |||
| 205 | /** | ||
| 206 | * | ||
| 207 | * A relative positioning constant, that can be used instead of | ||
| 208 | * north, south, east, west or center. | ||
| 209 | * mixing the two types of constants can lead to unpredicable results. If | ||
| 210 | * you use both types, the relative constants will take precedence. | ||
| 211 | * For example, if you add components using both the <code>NORTH</code> | ||
| 212 | * and <code>BEFORE_FIRST_LINE</code> constants in a container whose | ||
| 213 | * orientation is <code>LEFT_TO_RIGHT</code>, only the | ||
| 214 | * <code>BEFORE_FIRST_LINE</code> will be layed out. | ||
| 215 | * This will be the same for lastLine, firstItem, lastItem. | ||
| 216 | * @serial | ||
| 217 | */ | ||
| 218 | Component firstLine; | ||
| 219 | /** | ||
| 220 | * A relative positioning constant, that can be used instead of | ||
| 221 | * north, south, east, west or center. | ||
| 222 | * Please read Description for firstLine. | ||
| 223 | * @serial | ||
| 224 | */ | ||
| 225 | Component lastLine; | ||
| 226 | /** | ||
| 227 | * A relative positioning constant, that can be used instead of | ||
| 228 | * north, south, east, west or center. | ||
| 229 | * Please read Description for firstLine. | ||
| 230 | * @serial | ||
| 231 | */ | ||
| 232 | Component firstItem; | ||
| 233 | /** | ||
| 234 | * A relative positioning constant, that can be used instead of | ||
| 235 | * north, south, east, west or center. | ||
| 236 | * Please read Description for firstLine. | ||
| 237 | * @serial | ||
| 238 | */ | ||
| 239 | Component lastItem; | ||
| 240 | |||
| 241 | /** | ||
| 242 | * The north layout constraint (top of container). | ||
| 243 | */ | ||
| 244 | public static final String NORTH = "North"; | ||
| 245 | |||
| 246 | /** | ||
| 247 | * The south layout constraint (bottom of container). | ||
| 248 | */ | ||
| 249 | public static final String SOUTH = "South"; | ||
| 250 | |||
| 251 | /** | ||
| 252 | * The east layout constraint (right side of container). | ||
| 253 | */ | ||
| 254 | public static final String EAST = "East"; | ||
| 255 | |||
| 256 | /** | ||
| 257 | * The west layout constraint (left side of container). | ||
| 258 | */ | ||
| 259 | public static final String WEST = "West"; | ||
| 260 | |||
| 261 | /** | ||
| 262 | * The center layout constraint (middle of container). | ||
| 263 | */ | ||
| 264 | public static final String CENTER = "Center"; | ||
| 265 | |||
| 266 | /** | ||
| 267 | * Synonym for PAGE_START. Exists for compatibility with previous | ||
| 268 | * versions. PAGE_START is preferred. | ||
| 269 | * | ||
| 270 | * @see #PAGE_START | ||
| 271 | * @since 1.2 | ||
| 272 | */ | ||
| 273 | public static final String BEFORE_FIRST_LINE = "First"; | ||
| 274 | |||
| 275 | /** | ||
| 276 | * Synonym for PAGE_END. Exists for compatibility with previous | ||
| 277 | * versions. PAGE_END is preferred. | ||
| 278 | * | ||
| 279 | * @see #PAGE_END | ||
| 280 | * @since 1.2 | ||
| 281 | */ | ||
| 282 | public static final String AFTER_LAST_LINE = "Last"; | ||
| 283 | |||
| 284 | /** | ||
| 285 | * Synonym for LINE_START. Exists for compatibility with previous | ||
| 286 | * versions. LINE_START is preferred. | ||
| 287 | * | ||
| 288 | * @see #LINE_START | ||
| 289 | * @since 1.2 | ||
| 290 | */ | ||
| 291 | public static final String BEFORE_LINE_BEGINS = "Before"; | ||
| 292 | |||
| 293 | /** | ||
| 294 | * Synonym for LINE_END. Exists for compatibility with previous | ||
| 295 | * versions. LINE_END is preferred. | ||
| 296 | * | ||
| 297 | * @see #LINE_END | ||
| 298 | * @since 1.2 | ||
| 299 | */ | ||
| 300 | public static final String AFTER_LINE_ENDS = "After"; | ||
| 301 | |||
| 302 | /** | ||
| 303 | * The component comes before the first line of the layout's content. | ||
| 304 | * For Western, left-to-right and top-to-bottom orientations, this is | ||
| 305 | * equivalent to NORTH. | ||
| 306 | * | ||
| 307 | * @see java.awt.Component#getComponentOrientation | ||
| 308 | * @since 1.4 | ||
| 309 | */ | ||
| 310 | public static final String PAGE_START = BEFORE_FIRST_LINE; | ||
| 311 | |||
| 312 | /** | ||
| 313 | * The component comes after the last line of the layout's content. | ||
| 314 | * For Western, left-to-right and top-to-bottom orientations, this is | ||
| 315 | * equivalent to SOUTH. | ||
| 316 | * | ||
| 317 | * @see java.awt.Component#getComponentOrientation | ||
| 318 | * @since 1.4 | ||
| 319 | */ | ||
| 320 | public static final String PAGE_END = AFTER_LAST_LINE; | ||
| 321 | |||
| 322 | /** | ||
| 323 | * The component goes at the beginning of the line direction for the | ||
| 324 | * layout. For Western, left-to-right and top-to-bottom orientations, | ||
| 325 | * this is equivalent to WEST. | ||
| 326 | * | ||
| 327 | * @see java.awt.Component#getComponentOrientation | ||
| 328 | * @since 1.4 | ||
| 329 | */ | ||
| 330 | public static final String LINE_START = BEFORE_LINE_BEGINS; | ||
| 331 | |||
| 332 | /** | ||
| 333 | * The component goes at the end of the line direction for the | ||
| 334 | * layout. For Western, left-to-right and top-to-bottom orientations, | ||
| 335 | * this is equivalent to EAST. | ||
| 336 | * | ||
| 337 | * @see java.awt.Component#getComponentOrientation | ||
| 338 | * @since 1.4 | ||
| 339 | */ | ||
| 340 | public static final String LINE_END = AFTER_LINE_ENDS; | ||
| 341 | |||
| 342 | /* | ||
| 343 | * JDK 1.1 serialVersionUID | ||
| 344 | */ | ||
| 345 | private static final long serialVersionUID = -8658291919501921765L; | ||
| 346 | |||
| 347 | /** | ||
| 348 | * Constructs a new border layout with | ||
| 349 | * no gaps between components. | ||
| 350 | */ | ||
| 351 | public BorderLayout() { | ||
| 352 | this(0, 0); | ||
| 353 | } | ||
| 354 | |||
| 355 | /** | ||
| 356 | * Constructs a border layout with the specified gaps | ||
| 357 | * between components. | ||
| 358 | * The horizontal gap is specified by <code>hgap</code> | ||
| 359 | * and the vertical gap is specified by <code>vgap</code>. | ||
| 360 | * @param hgap the horizontal gap. | ||
| 361 | * @param vgap the vertical gap. | ||
| 362 | */ | ||
| 363 | public BorderLayout(int hgap, int vgap) { | ||
| 364 | this.hgap = hgap; | ||
| 365 | this.vgap = vgap; | ||
| 366 | } | ||
| 367 | |||
| 368 | /** | ||
| 369 | * Returns the horizontal gap between components. | ||
| 370 | * @since JDK1.1 | ||
| 371 | */ | ||
| 372 | public int getHgap() { | ||
| 373 | return hgap; | ||
| 374 | } | ||
| 375 | |||
| 376 | /** | ||
| 377 | * Sets the horizontal gap between components. | ||
| 378 | * @param hgap the horizontal gap between components | ||
| 379 | * @since JDK1.1 | ||
| 380 | */ | ||
| 381 | public void setHgap(int hgap) { | ||
| 382 | this.hgap = hgap; | ||
| 383 | } | ||
| 384 | |||
| 385 | /** | ||
| 386 | * Returns the vertical gap between components. | ||
| 387 | * @since JDK1.1 | ||
| 388 | */ | ||
| 389 | public int getVgap() { | ||
| 390 | return vgap; | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 394 | * Sets the vertical gap between components. | ||
| 395 | * @param vgap the vertical gap between components | ||
| 396 | * @since JDK1.1 | ||
| 397 | */ | ||
| 398 | public void setVgap(int vgap) { | ||
| 399 | this.vgap = vgap; | ||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * Adds the specified component to the layout, using the specified | ||
| 404 | * constraint object. For border layouts, the constraint must be | ||
| 405 | * one of the following constants: <code>NORTH</code>, | ||
| 406 | * <code>SOUTH</code>, <code>EAST</code>, | ||
| 407 | * <code>WEST</code>, or <code>CENTER</code>. | ||
| 408 | * <p> | ||
| 409 | * Most applications do not call this method directly. This method | ||
| 410 | * is called when a component is added to a container using the | ||
| 411 | * <code>Container.add</code> method with the same argument types. | ||
| 412 | * @param comp the component to be added. | ||
| 413 | * @param constraints an object that specifies how and where | ||
| 414 | * the component is added to the layout. | ||
| 415 | * @see java.awt.Container#add(java.awt.Component, java.lang.Object) | ||
| 416 | * @exception IllegalArgumentException if the constraint object is not | ||
| 417 | * a string, or if it not one of the five specified | ||
| 418 | * constants. | ||
| 419 | * @since JDK1.1 | ||
| 420 | */ | ||
| 421 | public void addLayoutComponent(Component comp, Object constraints) { | ||
| 422 | synchronized (comp.getTreeLock()) { | ||
| 423 | if ((constraints == null) || (constraints instanceof String)) { | ||
| 424 | addLayoutComponent((String)constraints, comp); | ||
| 425 | } else { | ||
| 426 | throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)"); | ||
| 427 | } | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | /** | ||
| 432 | * @deprecated replaced by <code>addLayoutComponent(Component, Object)</code>. | ||
| 433 | */ | ||
| 434 | @Deprecated | ||
| 435 | public void addLayoutComponent(String name, Component comp) { | ||
| 436 | synchronized (comp.getTreeLock()) { | ||
| 437 | /* Special case: treat null the same as "Center". */ | ||
| 438 | if (name == null) { | ||
| 439 | name = "Center"; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* Assign the component to one of the known regions of the layout. | ||
| 443 | */ | ||
| 444 | if ("Center".equals(name)) { | ||
| 445 | center = comp; | ||
| 446 | } else if ("North".equals(name)) { | ||
| 447 | north = comp; | ||
| 448 | } else if ("South".equals(name)) { | ||
| 449 | south = comp; | ||
| 450 | } else if ("East".equals(name)) { | ||
| 451 | east = comp; | ||
| 452 | } else if ("West".equals(name)) { | ||
| 453 | west = comp; | ||
| 454 | } else if (BEFORE_FIRST_LINE.equals(name)) { | ||
| 455 | firstLine = comp; | ||
| 456 | } else if (AFTER_LAST_LINE.equals(name)) { | ||
| 457 | lastLine = comp; | ||
| 458 | } else if (BEFORE_LINE_BEGINS.equals(name)) { | ||
| 459 | firstItem = comp; | ||
| 460 | } else if (AFTER_LINE_ENDS.equals(name)) { | ||
| 461 | lastItem = comp; | ||
| 462 | } else { | ||
| 463 | throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name); | ||
| 464 | } | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | /** | ||
| 469 | * Removes the specified component from this border layout. This | ||
| 470 | * method is called when a container calls its <code>remove</code> or | ||
| 471 | * <code>removeAll</code> methods. Most applications do not call this | ||
| 472 | * method directly. | ||
| 473 | * @param comp the component to be removed. | ||
| 474 | * @see java.awt.Container#remove(java.awt.Component) | ||
| 475 | * @see java.awt.Container#removeAll() | ||
| 476 | */ | ||
| 477 | public void removeLayoutComponent(Component comp) { | ||
| 478 | synchronized (comp.getTreeLock()) { | ||
| 479 | if (comp == center) { | ||
| 480 | center = null; | ||
| 481 | } else if (comp == north) { | ||
| 482 | north = null; | ||
| 483 | } else if (comp == south) { | ||
| 484 | south = null; | ||
| 485 | } else if (comp == east) { | ||
| 486 | east = null; | ||
| 487 | } else if (comp == west) { | ||
| 488 | west = null; | ||
| 489 | } | ||
| 490 | if (comp == firstLine) { | ||
| 491 | firstLine = null; | ||
| 492 | } else if (comp == lastLine) { | ||
| 493 | lastLine = null; | ||
| 494 | } else if (comp == firstItem) { | ||
| 495 | firstItem = null; | ||
| 496 | } else if (comp == lastItem) { | ||
| 497 | lastItem = null; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | /** | ||
| 503 | * Gets the component that was added using the given constraint | ||
| 504 | * | ||
| 505 | * @param constraints the desired constraint, one of <code>CENTER</code>, | ||
| 506 | * <code>NORTH</code>, <code>SOUTH</code>, | ||
| 507 | * <code>WEST</code>, <code>EAST</code>, | ||
| 508 | * <code>PAGE_START</code>, <code>PAGE_END</code>, | ||
| 509 | * <code>LINE_START</code>, <code>LINE_END</code> | ||
| 510 | * @return the component at the given location, or <code>null</code> if | ||
| 511 | * the location is empty | ||
| 512 | * @exception IllegalArgumentException if the constraint object is | ||
| 513 | * not one of the nine specified constants | ||
| 514 | * @see #addLayoutComponent(java.awt.Component, java.lang.Object) | ||
| 515 | * @since 1.5 | ||
| 516 | */ | ||
| 517 | public Component getLayoutComponent(Object constraints) { | ||
| 518 | if (CENTER.equals(constraints)) { | ||
| 519 | return center; | ||
| 520 | } else if (NORTH.equals(constraints)) { | ||
| 521 | return north; | ||
| 522 | } else if (SOUTH.equals(constraints)) { | ||
| 523 | return south; | ||
| 524 | } else if (WEST.equals(constraints)) { | ||
| 525 | return west; | ||
| 526 | } else if (EAST.equals(constraints)) { | ||
| 527 | return east; | ||
| 528 | } else if (PAGE_START.equals(constraints)) { | ||
| 529 | return firstLine; | ||
| 530 | } else if (PAGE_END.equals(constraints)) { | ||
| 531 | return lastLine; | ||
| 532 | } else if (LINE_START.equals(constraints)) { | ||
| 533 | return firstItem; | ||
| 534 | } else if (LINE_END.equals(constraints)) { | ||
| 535 | return lastItem; | ||
| 536 | } else { | ||
| 537 | throw new IllegalArgumentException("cannot get component: unknown constraint: " + constraints); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | |||
| 541 | |||
| 542 | /** | ||
| 543 | * Returns the component that corresponds to the given constraint location | ||
| 544 | * based on the target <code>Container</code>'s component orientation. | ||
| 545 | * Components added with the relative constraints <code>PAGE_START</code>, | ||
| 546 | * <code>PAGE_END</code>, <code>LINE_START</code>, and <code>LINE_END</code> | ||
| 547 | * take precedence over components added with the explicit constraints | ||
| 548 | * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and <code>EAST</code>. | ||
| 549 | * The <code>Container</code>'s component orientation is used to determine the location of components | ||
| 550 | * added with <code>LINE_START</code> and <code>LINE_END</code>. | ||
| 551 | * | ||
| 552 | * @param constraints the desired absolute position, one of <code>CENTER</code>, | ||
| 553 | * <code>NORTH</code>, <code>SOUTH</code>, | ||
| 554 | * <code>EAST</code>, <code>WEST</code> | ||
| 555 | * @param target the {@code Container} used to obtain | ||
| 556 | * the constraint location based on the target | ||
| 557 | * {@code Container}'s component orientation. | ||
| 558 | * @return the component at the given location, or <code>null</code> if | ||
| 559 | * the location is empty | ||
| 560 | * @exception IllegalArgumentException if the constraint object is | ||
| 561 | * not one of the five specified constants | ||
| 562 | * @exception NullPointerException if the target parameter is null | ||
| 563 | * @see #addLayoutComponent(java.awt.Component, java.lang.Object) | ||
| 564 | * @since 1.5 | ||
| 565 | */ | ||
| 566 | public Component getLayoutComponent(Container target, Object constraints) { | ||
| 567 | boolean ltr = target.getComponentOrientation().isLeftToRight(); | ||
| 568 | Component result = null; | ||
| 569 | |||
| 570 | if (NORTH.equals(constraints)) { | ||
| 571 | result = (firstLine != null) ? firstLine : north; | ||
| 572 | } else if (SOUTH.equals(constraints)) { | ||
| 573 | result = (lastLine != null) ? lastLine : south; | ||
| 574 | } else if (WEST.equals(constraints)) { | ||
| 575 | result = ltr ? firstItem : lastItem; | ||
| 576 | if (result == null) { | ||
| 577 | result = west; | ||
| 578 | } | ||
| 579 | } else if (EAST.equals(constraints)) { | ||
| 580 | result = ltr ? lastItem : firstItem; | ||
| 581 | if (result == null) { | ||
| 582 | result = east; | ||
| 583 | } | ||
| 584 | } else if (CENTER.equals(constraints)) { | ||
| 585 | result = center; | ||
| 586 | } else { | ||
| 587 | throw new IllegalArgumentException("cannot get component: invalid constraint: " + constraints); | ||
| 588 | } | ||
| 589 | |||
| 590 | return result; | ||
| 591 | } | ||
| 592 | |||
| 593 | |||
| 594 | /** | ||
| 595 | * Gets the constraints for the specified component | ||
| 596 | * | ||
| 597 | * @param comp the component to be queried | ||
| 598 | * @return the constraint for the specified component, | ||
| 599 | * or null if component is null or is not present | ||
| 600 | * in this layout | ||
| 601 | * @see #addLayoutComponent(java.awt.Component, java.lang.Object) | ||
| 602 | * @since 1.5 | ||
| 603 | */ | ||
| 604 | public Object getConstraints(Component comp) { | ||
| 605 | //fix for 6242148 : API method java.awt.BorderLayout.getConstraints(null) should return null | ||
| 606 | if (comp == null){ | ||
| 607 | return null; | ||
| 608 | } | ||
| 609 | if (comp == center) { | ||
| 610 | return CENTER; | ||
| 611 | } else if (comp == north) { | ||
| 612 | return NORTH; | ||
| 613 | } else if (comp == south) { | ||
| 614 | return SOUTH; | ||
| 615 | } else if (comp == west) { | ||
| 616 | return WEST; | ||
| 617 | } else if (comp == east) { | ||
| 618 | return EAST; | ||
| 619 | } else if (comp == firstLine) { | ||
| 620 | return PAGE_START; | ||
| 621 | } else if (comp == lastLine) { | ||
| 622 | return PAGE_END; | ||
| 623 | } else if (comp == firstItem) { | ||
| 624 | return LINE_START; | ||
| 625 | } else if (comp == lastItem) { | ||
| 626 | return LINE_END; | ||
| 627 | } | ||
| 628 | return null; | ||
| 629 | } | ||
| 630 | |||
| 631 | /** | ||
| 632 | * Determines the minimum size of the <code>target</code> container | ||
| 633 | * using this layout manager. | ||
| 634 | * <p> | ||
| 635 | * This method is called when a container calls its | ||
| 636 | * <code>getMinimumSize</code> method. Most applications do not call | ||
| 637 | * this method directly. | ||
| 638 | * @param target the container in which to do the layout. | ||
| 639 | * @return the minimum dimensions needed to lay out the subcomponents | ||
| 640 | * of the specified container. | ||
| 641 | * @see java.awt.Container | ||
| 642 | * @see java.awt.BorderLayout#preferredLayoutSize | ||
| 643 | * @see java.awt.Container#getMinimumSize() | ||
| 644 | */ | ||
| 645 | public Dimension minimumLayoutSize(Container target) { | ||
| 646 | synchronized (target.getTreeLock()) { | ||
| 647 | Dimension dim = new Dimension(0, 0); | ||
| 648 | |||
| 649 | boolean ltr = target.getComponentOrientation().isLeftToRight(); | ||
| 650 | Component c = null; | ||
| 651 | |||
| 652 | if ((c=getChild(EAST,ltr)) != null) { | ||
| 653 | Dimension d = c.getMinimumSize(); | ||
| 654 | dim.width += d.width + hgap; | ||
| 655 | dim.height = Math.max(d.height, dim.height); | ||
| 656 | } | ||
| 657 | if ((c=getChild(WEST,ltr)) != null) { | ||
| 658 | Dimension d = c.getMinimumSize(); | ||
| 659 | dim.width += d.width + hgap; | ||
| 660 | dim.height = Math.max(d.height, dim.height); | ||
| 661 | } | ||
| 662 | if ((c=getChild(CENTER,ltr)) != null) { | ||
| 663 | Dimension d = c.getMinimumSize(); | ||
| 664 | dim.width += d.width; | ||
| 665 | dim.height = Math.max(d.height, dim.height); | ||
| 666 | } | ||
| 667 | if ((c=getChild(NORTH,ltr)) != null) { | ||
| 668 | Dimension d = c.getMinimumSize(); | ||
| 669 | dim.width = Math.max(d.width, dim.width); | ||
| 670 | dim.height += d.height + vgap; | ||
| 671 | } | ||
| 672 | if ((c=getChild(SOUTH,ltr)) != null) { | ||
| 673 | Dimension d = c.getMinimumSize(); | ||
| 674 | dim.width = Math.max(d.width, dim.width); | ||
| 675 | dim.height += d.height + vgap; | ||
| 676 | } | ||
| 677 | |||
| 678 | Insets insets = target.getInsets(); | ||
| 679 | dim.width += insets.left + insets.right; | ||
| 680 | dim.height += insets.top + insets.bottom; | ||
| 681 | |||
| 682 | return dim; | ||
| 683 | } | ||
| 684 | } | ||
| 685 | |||
| 686 | /** | ||
| 687 | * Determines the preferred size of the <code>target</code> | ||
| 688 | * container using this layout manager, based on the components | ||
| 689 | * in the container. | ||
| 690 | * <p> | ||
| 691 | * Most applications do not call this method directly. This method | ||
| 692 | * is called when a container calls its <code>getPreferredSize</code> | ||
| 693 | * method. | ||
| 694 | * @param target the container in which to do the layout. | ||
| 695 | * @return the preferred dimensions to lay out the subcomponents | ||
| 696 | * of the specified container. | ||
| 697 | * @see java.awt.Container | ||
| 698 | * @see java.awt.BorderLayout#minimumLayoutSize | ||
| 699 | * @see java.awt.Container#getPreferredSize() | ||
| 700 | */ | ||
| 701 | public Dimension preferredLayoutSize(Container target) { | ||
| 702 | synchronized (target.getTreeLock()) { | ||
| 703 | Dimension dim = new Dimension(0, 0); | ||
| 704 | |||
| 705 | boolean ltr = target.getComponentOrientation().isLeftToRight(); | ||
| 706 | Component c = null; | ||
| 707 | |||
| 708 | if ((c=getChild(EAST,ltr)) != null) { | ||
| 709 | Dimension d = c.getPreferredSize(); | ||
| 710 | dim.width += d.width + hgap; | ||
| 711 | dim.height = Math.max(d.height, dim.height); | ||
| 712 | } | ||
| 713 | if ((c=getChild(WEST,ltr)) != null) { | ||
| 714 | Dimension d = c.getPreferredSize(); | ||
| 715 | dim.width += d.width + hgap; | ||
| 716 | dim.height = Math.max(d.height, dim.height); | ||
| 717 | } | ||
| 718 | if ((c=getChild(CENTER,ltr)) != null) { | ||
| 719 | Dimension d = c.getPreferredSize(); | ||
| 720 | dim.width += d.width; | ||
| 721 | dim.height = Math.max(d.height, dim.height); | ||
| 722 | } | ||
| 723 | if ((c=getChild(NORTH,ltr)) != null) { | ||
| 724 | Dimension d = c.getPreferredSize(); | ||
| 725 | dim.width = Math.max(d.width, dim.width); | ||
| 726 | dim.height += d.height + vgap; | ||
| 727 | } | ||
| 728 | if ((c=getChild(SOUTH,ltr)) != null) { | ||
| 729 | Dimension d = c.getPreferredSize(); | ||
| 730 | dim.width = Math.max(d.width, dim.width); | ||
| 731 | dim.height += d.height + vgap; | ||
| 732 | } | ||
| 733 | |||
| 734 | Insets insets = target.getInsets(); | ||
| 735 | dim.width += insets.left + insets.right; | ||
| 736 | dim.height += insets.top + insets.bottom; | ||
| 737 | |||
| 738 | return dim; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | /** | ||
| 743 | * Returns the maximum dimensions for this layout given the components | ||
| 744 | * in the specified target container. | ||
| 745 | * @param target the component which needs to be laid out | ||
| 746 | * @see Container | ||
| 747 | * @see #minimumLayoutSize | ||
| 748 | * @see #preferredLayoutSize | ||
| 749 | */ | ||
| 750 | public Dimension maximumLayoutSize(Container target) { | ||
| 751 | return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); | ||
| 752 | } | ||
| 753 | |||
| 754 | /** | ||
| 755 | * Returns the alignment along the x axis. This specifies how | ||
| 756 | * the component would like to be aligned relative to other | ||
| 757 | * components. The value should be a number between 0 and 1 | ||
| 758 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 759 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 760 | */ | ||
| 761 | public float getLayoutAlignmentX(Container parent) { | ||
| 762 | return 0.5f; | ||
| 763 | } | ||
| 764 | |||
| 765 | /** | ||
| 766 | * Returns the alignment along the y axis. This specifies how | ||
| 767 | * the component would like to be aligned relative to other | ||
| 768 | * components. The value should be a number between 0 and 1 | ||
| 769 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 770 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 771 | */ | ||
| 772 | public float getLayoutAlignmentY(Container parent) { | ||
| 773 | return 0.5f; | ||
| 774 | } | ||
| 775 | |||
| 776 | /** | ||
| 777 | * Invalidates the layout, indicating that if the layout manager | ||
| 778 | * has cached information it should be discarded. | ||
| 779 | */ | ||
| 780 | public void invalidateLayout(Container target) { | ||
| 781 | } | ||
| 782 | |||
| 783 | /** | ||
| 784 | * Lays out the container argument using this border layout. | ||
| 785 | * <p> | ||
| 786 | * This method actually reshapes the components in the specified | ||
| 787 | * container in order to satisfy the constraints of this | ||
| 788 | * <code>BorderLayout</code> object. The <code>NORTH</code> | ||
| 789 | * and <code>SOUTH</code> components, if any, are placed at | ||
| 790 | * the top and bottom of the container, respectively. The | ||
| 791 | * <code>WEST</code> and <code>EAST</code> components are | ||
| 792 | * then placed on the left and right, respectively. Finally, | ||
| 793 | * the <code>CENTER</code> object is placed in any remaining | ||
| 794 | * space in the middle. | ||
| 795 | * <p> | ||
| 796 | * Most applications do not call this method directly. This method | ||
| 797 | * is called when a container calls its <code>doLayout</code> method. | ||
| 798 | * @param target the container in which to do the layout. | ||
| 799 | * @see java.awt.Container | ||
| 800 | * @see java.awt.Container#doLayout() | ||
| 801 | */ | ||
| 802 | public void layoutContainer(Container target) { | ||
| 803 | synchronized (target.getTreeLock()) { | ||
| 804 | Insets insets = target.getInsets(); | ||
| 805 | int top = insets.top; | ||
| 806 | int bottom = target.height - insets.bottom; | ||
| 807 | int left = insets.left; | ||
| 808 | int right = target.width - insets.right; | ||
| 809 | |||
| 810 | boolean ltr = target.getComponentOrientation().isLeftToRight(); | ||
| 811 | Component c = null; | ||
| 812 | |||
| 813 | if ((c=getChild(NORTH,ltr)) != null) { | ||
| 814 | c.setSize(right - left, c.height); | ||
| 815 | Dimension d = c.getPreferredSize(); | ||
| 816 | c.setBounds(left, top, right - left, d.height); | ||
| 817 | top += d.height + vgap; | ||
| 818 | } | ||
| 819 | if ((c=getChild(SOUTH,ltr)) != null) { | ||
| 820 | c.setSize(right - left, c.height); | ||
| 821 | Dimension d = c.getPreferredSize(); | ||
| 822 | c.setBounds(left, bottom - d.height, right - left, d.height); | ||
| 823 | bottom -= d.height + vgap; | ||
| 824 | } | ||
| 825 | if ((c=getChild(EAST,ltr)) != null) { | ||
| 826 | c.setSize(c.width, bottom - top); | ||
| 827 | Dimension d = c.getPreferredSize(); | ||
| 828 | c.setBounds(right - d.width, top, d.width, bottom - top); | ||
| 829 | right -= d.width + hgap; | ||
| 830 | } | ||
| 831 | if ((c=getChild(WEST,ltr)) != null) { | ||
| 832 | c.setSize(c.width, bottom - top); | ||
| 833 | Dimension d = c.getPreferredSize(); | ||
| 834 | c.setBounds(left, top, d.width, bottom - top); | ||
| 835 | left += d.width + hgap; | ||
| 836 | } | ||
| 837 | if ((c=getChild(CENTER,ltr)) != null) { | ||
| 838 | c.setBounds(left, top, right - left, bottom - top); | ||
| 839 | } | ||
| 840 | } | ||
| 841 | } | ||
| 842 | |||
| 843 | /** | ||
| 844 | * Get the component that corresponds to the given constraint location | ||
| 845 | * | ||
| 846 | * @param key The desired absolute position, | ||
| 847 | * either NORTH, SOUTH, EAST, or WEST. | ||
| 848 | * @param ltr Is the component line direction left-to-right? | ||
| 849 | */ | ||
| 850 | private Component getChild(String key, boolean ltr) { | ||
| 851 | Component result = null; | ||
| 852 | |||
| 853 | if (key == NORTH) { | ||
| 854 | result = (firstLine != null) ? firstLine : north; | ||
| 855 | } | ||
| 856 | else if (key == SOUTH) { | ||
| 857 | result = (lastLine != null) ? lastLine : south; | ||
| 858 | } | ||
| 859 | else if (key == WEST) { | ||
| 860 | result = ltr ? firstItem : lastItem; | ||
| 861 | if (result == null) { | ||
| 862 | result = west; | ||
| 863 | } | ||
| 864 | } | ||
| 865 | else if (key == EAST) { | ||
| 866 | result = ltr ? lastItem : firstItem; | ||
| 867 | if (result == null) { | ||
| 868 | result = east; | ||
| 869 | } | ||
| 870 | } | ||
| 871 | else if (key == CENTER) { | ||
| 872 | result = center; | ||
| 873 | } | ||
| 874 | if (result != null && !result.visible) { | ||
| 875 | result = null; | ||
| 876 | } | ||
| 877 | return result; | ||
| 878 | } | ||
| 879 | |||
| 880 | /** | ||
| 881 | * Returns a string representation of the state of this border layout. | ||
| 882 | * @return a string representation of this border layout. | ||
| 883 | */ | ||
| 884 | public String toString() { | ||
| 885 | return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; | ||
| 886 | } | ||
| 887 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,217 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2006, 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 java.awt; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Capabilities and properties of buffers. | ||
| 30 | * | ||
| 31 | * @see java.awt.image.BufferStrategy#getCapabilities() | ||
| 32 | * @see GraphicsConfiguration#getBufferCapabilities | ||
| 33 | * @author Michael Martak | ||
| 34 | * @since 1.4 | ||
| 35 | */ | ||
| 36 | public class BufferCapabilities implements Cloneable { | ||
| 37 | |||
| 38 | private ImageCapabilities frontCaps; | ||
| 39 | private ImageCapabilities backCaps; | ||
| 40 | private FlipContents flipContents; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Creates a new object for specifying buffering capabilities | ||
| 44 | * @param frontCaps the capabilities of the front buffer; cannot be | ||
| 45 | * <code>null</code> | ||
| 46 | * @param backCaps the capabilities of the back and intermediate buffers; | ||
| 47 | * cannot be <code>null</code> | ||
| 48 | * @param flipContents the contents of the back buffer after page-flipping, | ||
| 49 | * <code>null</code> if page flipping is not used (implies blitting) | ||
| 50 | * @exception IllegalArgumentException if frontCaps or backCaps are | ||
| 51 | * <code>null</code> | ||
| 52 | */ | ||
| 53 | public BufferCapabilities(ImageCapabilities frontCaps, | ||
| 54 | ImageCapabilities backCaps, FlipContents flipContents) { | ||
| 55 | if (frontCaps == null || backCaps == null) { | ||
| 56 | throw new IllegalArgumentException( | ||
| 57 | "Image capabilities specified cannot be null"); | ||
| 58 | } | ||
| 59 | this.frontCaps = frontCaps; | ||
| 60 | this.backCaps = backCaps; | ||
| 61 | this.flipContents = flipContents; | ||
| 62 | } | ||
| 63 | |||
| 64 | /** | ||
| 65 | * @return the image capabilities of the front (displayed) buffer | ||
| 66 | */ | ||
| 67 | public ImageCapabilities getFrontBufferCapabilities() { | ||
| 68 | return frontCaps; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * @return the image capabilities of all back buffers (intermediate buffers | ||
| 73 | * are considered back buffers) | ||
| 74 | */ | ||
| 75 | public ImageCapabilities getBackBufferCapabilities() { | ||
| 76 | return backCaps; | ||
| 77 | } | ||
| 78 | |||
| 79 | /** | ||
| 80 | * @return whether or not the buffer strategy uses page flipping; a set of | ||
| 81 | * buffers that uses page flipping | ||
| 82 | * can swap the contents internally between the front buffer and one or | ||
| 83 | * more back buffers by switching the video pointer (or by copying memory | ||
| 84 | * internally). A non-flipping set of | ||
| 85 | * buffers uses blitting to copy the contents from one buffer to | ||
| 86 | * another; when this is the case, <code>getFlipContents</code> returns | ||
| 87 | * <code>null</code> | ||
| 88 | */ | ||
| 89 | public boolean isPageFlipping() { | ||
| 90 | return (getFlipContents() != null); | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * @return the resulting contents of the back buffer after page-flipping. | ||
| 95 | * This value is <code>null</code> when the <code>isPageFlipping</code> | ||
| 96 | * returns <code>false</code>, implying blitting. It can be one of | ||
| 97 | * <code>FlipContents.UNDEFINED</code> | ||
| 98 | * (the assumed default), <code>FlipContents.BACKGROUND</code>, | ||
| 99 | * <code>FlipContents.PRIOR</code>, or | ||
| 100 | * <code>FlipContents.COPIED</code>. | ||
| 101 | * @see #isPageFlipping | ||
| 102 | * @see FlipContents#UNDEFINED | ||
| 103 | * @see FlipContents#BACKGROUND | ||
| 104 | * @see FlipContents#PRIOR | ||
| 105 | * @see FlipContents#COPIED | ||
| 106 | */ | ||
| 107 | public FlipContents getFlipContents() { | ||
| 108 | return flipContents; | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * @return whether page flipping is only available in full-screen mode. If this | ||
| 113 | * is <code>true</code>, full-screen exclusive mode is required for | ||
| 114 | * page-flipping. | ||
| 115 | * @see #isPageFlipping | ||
| 116 | * @see GraphicsDevice#setFullScreenWindow | ||
| 117 | */ | ||
| 118 | public boolean isFullScreenRequired() { | ||
| 119 | return false; | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * @return whether or not | ||
| 124 | * page flipping can be performed using more than two buffers (one or more | ||
| 125 | * intermediate buffers as well as the front and back buffer). | ||
| 126 | * @see #isPageFlipping | ||
| 127 | */ | ||
| 128 | public boolean isMultiBufferAvailable() { | ||
| 129 | return false; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * @return a copy of this BufferCapabilities object. | ||
| 134 | */ | ||
| 135 | public Object clone() { | ||
| 136 | try { | ||
| 137 | return super.clone(); | ||
| 138 | } catch (CloneNotSupportedException e) { | ||
| 139 | // Since we implement Cloneable, this should never happen | ||
| 140 | throw new InternalError(); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | // Inner class FlipContents | ||
| 145 | /** | ||
| 146 | * A type-safe enumeration of the possible back buffer contents after | ||
| 147 | * page-flipping | ||
| 148 | * @since 1.4 | ||
| 149 | */ | ||
| 150 | public static final class FlipContents extends AttributeValue { | ||
| 151 | |||
| 152 | private static int I_UNDEFINED = 0; | ||
| 153 | private static int I_BACKGROUND = 1; | ||
| 154 | private static int I_PRIOR = 2; | ||
| 155 | private static int I_COPIED = 3; | ||
| 156 | |||
| 157 | private static final String NAMES[] = | ||
| 158 | { "undefined", "background", "prior", "copied" }; | ||
| 159 | |||
| 160 | /** | ||
| 161 | * When flip contents are <code>UNDEFINED</code>, the | ||
| 162 | * contents of the back buffer are undefined after flipping. | ||
| 163 | * @see #isPageFlipping | ||
| 164 | * @see #getFlipContents | ||
| 165 | * @see #BACKGROUND | ||
| 166 | * @see #PRIOR | ||
| 167 | * @see #COPIED | ||
| 168 | */ | ||
| 169 | public static final FlipContents UNDEFINED = | ||
| 170 | new FlipContents(I_UNDEFINED); | ||
| 171 | |||
| 172 | /** | ||
| 173 | * When flip contents are <code>BACKGROUND</code>, the | ||
| 174 | * contents of the back buffer are cleared with the background color after | ||
| 175 | * flipping. | ||
| 176 | * @see #isPageFlipping | ||
| 177 | * @see #getFlipContents | ||
| 178 | * @see #UNDEFINED | ||
| 179 | * @see #PRIOR | ||
| 180 | * @see #COPIED | ||
| 181 | */ | ||
| 182 | public static final FlipContents BACKGROUND = | ||
| 183 | new FlipContents(I_BACKGROUND); | ||
| 184 | |||
| 185 | /** | ||
| 186 | * When flip contents are <code>PRIOR</code>, the | ||
| 187 | * contents of the back buffer are the prior contents of the front buffer | ||
| 188 | * (a true page flip). | ||
| 189 | * @see #isPageFlipping | ||
| 190 | * @see #getFlipContents | ||
| 191 | * @see #UNDEFINED | ||
| 192 | * @see #BACKGROUND | ||
| 193 | * @see #COPIED | ||
| 194 | */ | ||
| 195 | public static final FlipContents PRIOR = | ||
| 196 | new FlipContents(I_PRIOR); | ||
| 197 | |||
| 198 | /** | ||
| 199 | * When flip contents are <code>COPIED</code>, the | ||
| 200 | * contents of the back buffer are copied to the front buffer when | ||
| 201 | * flipping. | ||
| 202 | * @see #isPageFlipping | ||
| 203 | * @see #getFlipContents | ||
| 204 | * @see #UNDEFINED | ||
| 205 | * @see #BACKGROUND | ||
| 206 | * @see #PRIOR | ||
| 207 | */ | ||
| 208 | public static final FlipContents COPIED = | ||
| 209 | new FlipContents(I_COPIED); | ||
| 210 | |||
| 211 | private FlipContents(int type) { | ||
| 212 | super(type, NAMES); | ||
| 213 | } | ||
| 214 | |||
| 215 | } // Inner class FlipContents | ||
| 216 | |||
| 217 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,675 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2008, 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 java.awt; | ||
| 27 | |||
| 28 | import java.awt.peer.ButtonPeer; | ||
| 29 | import java.util.EventListener; | ||
| 30 | import java.awt.event.*; | ||
| 31 | import java.io.ObjectOutputStream; | ||
| 32 | import java.io.ObjectInputStream; | ||
| 33 | import java.io.IOException; | ||
| 34 | import javax.accessibility.*; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * This class creates a labeled button. The application can cause | ||
| 38 | * some action to happen when the button is pushed. This image | ||
| 39 | * depicts three views of a "<code>Quit</code>" button as it appears | ||
| 40 | * under the Solaris operating system: | ||
| 41 | * <p> | ||
| 42 | * <img src="doc-files/Button-1.gif" alt="The following context describes the graphic" | ||
| 43 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 44 | * <p> | ||
| 45 | * The first view shows the button as it appears normally. | ||
| 46 | * The second view shows the button | ||
| 47 | * when it has input focus. Its outline is darkened to let the | ||
| 48 | * user know that it is an active object. The third view shows the | ||
| 49 | * button when the user clicks the mouse over the button, and thus | ||
| 50 | * requests that an action be performed. | ||
| 51 | * <p> | ||
| 52 | * The gesture of clicking on a button with the mouse | ||
| 53 | * is associated with one instance of <code>ActionEvent</code>, | ||
| 54 | * which is sent out when the mouse is both pressed and released | ||
| 55 | * over the button. If an application is interested in knowing | ||
| 56 | * when the button has been pressed but not released, as a separate | ||
| 57 | * gesture, it can specialize <code>processMouseEvent</code>, | ||
| 58 | * or it can register itself as a listener for mouse events by | ||
| 59 | * calling <code>addMouseListener</code>. Both of these methods are | ||
| 60 | * defined by <code>Component</code>, the abstract superclass of | ||
| 61 | * all components. | ||
| 62 | * <p> | ||
| 63 | * When a button is pressed and released, AWT sends an instance | ||
| 64 | * of <code>ActionEvent</code> to the button, by calling | ||
| 65 | * <code>processEvent</code> on the button. The button's | ||
| 66 | * <code>processEvent</code> method receives all events | ||
| 67 | * for the button; it passes an action event along by | ||
| 68 | * calling its own <code>processActionEvent</code> method. | ||
| 69 | * The latter method passes the action event on to any action | ||
| 70 | * listeners that have registered an interest in action | ||
| 71 | * events generated by this button. | ||
| 72 | * <p> | ||
| 73 | * If an application wants to perform some action based on | ||
| 74 | * a button being pressed and released, it should implement | ||
| 75 | * <code>ActionListener</code> and register the new listener | ||
| 76 | * to receive events from this button, by calling the button's | ||
| 77 | * <code>addActionListener</code> method. The application can | ||
| 78 | * make use of the button's action command as a messaging protocol. | ||
| 79 | * | ||
| 80 | * @author Sami Shaio | ||
| 81 | * @see java.awt.event.ActionEvent | ||
| 82 | * @see java.awt.event.ActionListener | ||
| 83 | * @see java.awt.Component#processMouseEvent | ||
| 84 | * @see java.awt.Component#addMouseListener | ||
| 85 | * @since JDK1.0 | ||
| 86 | */ | ||
| 87 | public class Button extends Component implements Accessible { | ||
| 88 | |||
| 89 | /** | ||
| 90 | * The button's label. This value may be null. | ||
| 91 | * @serial | ||
| 92 | * @see #getLabel() | ||
| 93 | * @see #setLabel(String) | ||
| 94 | */ | ||
| 95 | String label; | ||
| 96 | |||
| 97 | /** | ||
| 98 | * The action to be performed once a button has been | ||
| 99 | * pressed. This value may be null. | ||
| 100 | * @serial | ||
| 101 | * @see #getActionCommand() | ||
| 102 | * @see #setActionCommand(String) | ||
| 103 | */ | ||
| 104 | String actionCommand; | ||
| 105 | |||
| 106 | transient ActionListener actionListener; | ||
| 107 | |||
| 108 | private static final String base = "button"; | ||
| 109 | private static int nameCounter = 0; | ||
| 110 | |||
| 111 | /* | ||
| 112 | * JDK 1.1 serialVersionUID | ||
| 113 | */ | ||
| 114 | private static final long serialVersionUID = -8774683716313001058L; | ||
| 115 | |||
| 116 | |||
| 117 | static { | ||
| 118 | /* ensure that the necessary native libraries are loaded */ | ||
| 119 | Toolkit.loadLibraries(); | ||
| 120 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 121 | initIDs(); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Initialize JNI field and method IDs for fields that may be | ||
| 127 | * accessed from C. | ||
| 128 | */ | ||
| 129 | private static native void initIDs(); | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Constructs a button with an empty string for its label. | ||
| 133 | * | ||
| 134 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 135 | * returns true | ||
| 136 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 137 | */ | ||
| 138 | public Button() throws HeadlessException { | ||
| 139 | this(""); | ||
| 140 | } | ||
| 141 | |||
| 142 | /** | ||
| 143 | * Constructs a button with the specified label. | ||
| 144 | * | ||
| 145 | * @param label a string label for the button, or | ||
| 146 | * <code>null</code> for no label | ||
| 147 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 148 | * returns true | ||
| 149 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 150 | */ | ||
| 151 | public Button(String label) throws HeadlessException { | ||
| 152 | GraphicsEnvironment.checkHeadless(); | ||
| 153 | this.label = label; | ||
| 154 | } | ||
| 155 | |||
| 156 | /** | ||
| 157 | * Construct a name for this component. Called by getName() when the | ||
| 158 | * name is null. | ||
| 159 | */ | ||
| 160 | String constructComponentName() { | ||
| 161 | synchronized (Button.class) { | ||
| 162 | return base + nameCounter++; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Creates the peer of the button. The button's peer allows the | ||
| 168 | * application to change the look of the button without changing | ||
| 169 | * its functionality. | ||
| 170 | * | ||
| 171 | * @see java.awt.Toolkit#createButton(java.awt.Button) | ||
| 172 | * @see java.awt.Component#getToolkit() | ||
| 173 | */ | ||
| 174 | public void addNotify() { | ||
| 175 | synchronized(getTreeLock()) { | ||
| 176 | if (peer == null) | ||
| 177 | peer = getToolkit().createButton(this); | ||
| 178 | super.addNotify(); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * Gets the label of this button. | ||
| 184 | * | ||
| 185 | * @return the button's label, or <code>null</code> | ||
| 186 | * if the button has no label. | ||
| 187 | * @see java.awt.Button#setLabel | ||
| 188 | */ | ||
| 189 | public String getLabel() { | ||
| 190 | return label; | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * Sets the button's label to be the specified string. | ||
| 195 | * | ||
| 196 | * @param label the new label, or <code>null</code> | ||
| 197 | * if the button has no label. | ||
| 198 | * @see java.awt.Button#getLabel | ||
| 199 | */ | ||
| 200 | public void setLabel(String label) { | ||
| 201 | boolean testvalid = false; | ||
| 202 | |||
| 203 | synchronized (this) { | ||
| 204 | if (label != this.label && (this.label == null || | ||
| 205 | !this.label.equals(label))) { | ||
| 206 | this.label = label; | ||
| 207 | ButtonPeer peer = (ButtonPeer)this.peer; | ||
| 208 | if (peer != null) { | ||
| 209 | peer.setLabel(label); | ||
| 210 | } | ||
| 211 | testvalid = true; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | // This could change the preferred size of the Component. | ||
| 216 | if (testvalid) { | ||
| 217 | invalidateIfValid(); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Sets the command name for the action event fired | ||
| 223 | * by this button. By default this action command is | ||
| 224 | * set to match the label of the button. | ||
| 225 | * | ||
| 226 | * @param command a string used to set the button's | ||
| 227 | * action command. | ||
| 228 | * If the string is <code>null</code> then the action command | ||
| 229 | * is set to match the label of the button. | ||
| 230 | * @see java.awt.event.ActionEvent | ||
| 231 | * @since JDK1.1 | ||
| 232 | */ | ||
| 233 | public void setActionCommand(String command) { | ||
| 234 | actionCommand = command; | ||
| 235 | } | ||
| 236 | |||
| 237 | /** | ||
| 238 | * Returns the command name of the action event fired by this button. | ||
| 239 | * If the command name is <code>null</code> (default) then this method | ||
| 240 | * returns the label of the button. | ||
| 241 | */ | ||
| 242 | public String getActionCommand() { | ||
| 243 | return (actionCommand == null? label : actionCommand); | ||
| 244 | } | ||
| 245 | |||
| 246 | /** | ||
| 247 | * Adds the specified action listener to receive action events from | ||
| 248 | * this button. Action events occur when a user presses or releases | ||
| 249 | * the mouse over this button. | ||
| 250 | * If l is null, no exception is thrown and no action is performed. | ||
| 251 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 252 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 253 | * | ||
| 254 | * @param l the action listener | ||
| 255 | * @see #removeActionListener | ||
| 256 | * @see #getActionListeners | ||
| 257 | * @see java.awt.event.ActionListener | ||
| 258 | * @since JDK1.1 | ||
| 259 | */ | ||
| 260 | public synchronized void addActionListener(ActionListener l) { | ||
| 261 | if (l == null) { | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | actionListener = AWTEventMulticaster.add(actionListener, l); | ||
| 265 | newEventsOnly = true; | ||
| 266 | } | ||
| 267 | |||
| 268 | /** | ||
| 269 | * Removes the specified action listener so that it no longer | ||
| 270 | * receives action events from this button. Action events occur | ||
| 271 | * when a user presses or releases the mouse over this button. | ||
| 272 | * If l is null, no exception is thrown and no action is performed. | ||
| 273 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 274 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 275 | * | ||
| 276 | * @param l the action listener | ||
| 277 | * @see #addActionListener | ||
| 278 | * @see #getActionListeners | ||
| 279 | * @see java.awt.event.ActionListener | ||
| 280 | * @since JDK1.1 | ||
| 281 | */ | ||
| 282 | public synchronized void removeActionListener(ActionListener l) { | ||
| 283 | if (l == null) { | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | actionListener = AWTEventMulticaster.remove(actionListener, l); | ||
| 287 | } | ||
| 288 | |||
| 289 | /** | ||
| 290 | * Returns an array of all the action listeners | ||
| 291 | * registered on this button. | ||
| 292 | * | ||
| 293 | * @return all of this button's <code>ActionListener</code>s | ||
| 294 | * or an empty array if no action | ||
| 295 | * listeners are currently registered | ||
| 296 | * | ||
| 297 | * @see #addActionListener | ||
| 298 | * @see #removeActionListener | ||
| 299 | * @see java.awt.event.ActionListener | ||
| 300 | * @since 1.4 | ||
| 301 | */ | ||
| 302 | public synchronized ActionListener[] getActionListeners() { | ||
| 303 | return (ActionListener[]) (getListeners(ActionListener.class)); | ||
| 304 | } | ||
| 305 | |||
| 306 | /** | ||
| 307 | * Returns an array of all the objects currently registered | ||
| 308 | * as <code><em>Foo</em>Listener</code>s | ||
| 309 | * upon this <code>Button</code>. | ||
| 310 | * <code><em>Foo</em>Listener</code>s are registered using the | ||
| 311 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 312 | * | ||
| 313 | * <p> | ||
| 314 | * You can specify the <code>listenerType</code> argument | ||
| 315 | * with a class literal, such as | ||
| 316 | * <code><em>Foo</em>Listener.class</code>. | ||
| 317 | * For example, you can query a | ||
| 318 | * <code>Button</code> <code>b</code> | ||
| 319 | * for its action listeners with the following code: | ||
| 320 | * | ||
| 321 | * <pre>ActionListener[] als = (ActionListener[])(b.getListeners(ActionListener.class));</pre> | ||
| 322 | * | ||
| 323 | * If no such listeners exist, this method returns an empty array. | ||
| 324 | * | ||
| 325 | * @param listenerType the type of listeners requested; this parameter | ||
| 326 | * should specify an interface that descends from | ||
| 327 | * <code>java.util.EventListener</code> | ||
| 328 | * @return an array of all objects registered as | ||
| 329 | * <code><em>Foo</em>Listener</code>s on this button, | ||
| 330 | * or an empty array if no such | ||
| 331 | * listeners have been added | ||
| 332 | * @exception ClassCastException if <code>listenerType</code> | ||
| 333 | * doesn't specify a class or interface that implements | ||
| 334 | * <code>java.util.EventListener</code> | ||
| 335 | * | ||
| 336 | * @see #getActionListeners | ||
| 337 | * @since 1.3 | ||
| 338 | */ | ||
| 339 | public <T extends EventListener> T[] getListeners(Class<T> listenerType) { | ||
| 340 | EventListener l = null; | ||
| 341 | if (listenerType == ActionListener.class) { | ||
| 342 | l = actionListener; | ||
| 343 | } else { | ||
| 344 | return super.getListeners(listenerType); | ||
| 345 | } | ||
| 346 | return AWTEventMulticaster.getListeners(l, listenerType); | ||
| 347 | } | ||
| 348 | |||
| 349 | // REMIND: remove when filtering is done at lower level | ||
| 350 | boolean eventEnabled(AWTEvent e) { | ||
| 351 | if (e.id == ActionEvent.ACTION_PERFORMED) { | ||
| 352 | if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 || | ||
| 353 | actionListener != null) { | ||
| 354 | return true; | ||
| 355 | } | ||
| 356 | return false; | ||
| 357 | } | ||
| 358 | return super.eventEnabled(e); | ||
| 359 | } | ||
| 360 | |||
| 361 | /** | ||
| 362 | * Processes events on this button. If an event is | ||
| 363 | * an instance of <code>ActionEvent</code>, this method invokes | ||
| 364 | * the <code>processActionEvent</code> method. Otherwise, | ||
| 365 | * it invokes <code>processEvent</code> on the superclass. | ||
| 366 | * <p>Note that if the event parameter is <code>null</code> | ||
| 367 | * the behavior is unspecified and may result in an | ||
| 368 | * exception. | ||
| 369 | * | ||
| 370 | * @param e the event | ||
| 371 | * @see java.awt.event.ActionEvent | ||
| 372 | * @see java.awt.Button#processActionEvent | ||
| 373 | * @since JDK1.1 | ||
| 374 | */ | ||
| 375 | protected void processEvent(AWTEvent e) { | ||
| 376 | if (e instanceof ActionEvent) { | ||
| 377 | processActionEvent((ActionEvent)e); | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | super.processEvent(e); | ||
| 381 | } | ||
| 382 | |||
| 383 | /** | ||
| 384 | * Processes action events occurring on this button | ||
| 385 | * by dispatching them to any registered | ||
| 386 | * <code>ActionListener</code> objects. | ||
| 387 | * <p> | ||
| 388 | * This method is not called unless action events are | ||
| 389 | * enabled for this button. Action events are enabled | ||
| 390 | * when one of the following occurs: | ||
| 391 | * <p><ul> | ||
| 392 | * <li>An <code>ActionListener</code> object is registered | ||
| 393 | * via <code>addActionListener</code>. | ||
| 394 | * <li>Action events are enabled via <code>enableEvents</code>. | ||
| 395 | * </ul> | ||
| 396 | * <p>Note that if the event parameter is <code>null</code> | ||
| 397 | * the behavior is unspecified and may result in an | ||
| 398 | * exception. | ||
| 399 | * | ||
| 400 | * @param e the action event | ||
| 401 | * @see java.awt.event.ActionListener | ||
| 402 | * @see java.awt.Button#addActionListener | ||
| 403 | * @see java.awt.Component#enableEvents | ||
| 404 | * @since JDK1.1 | ||
| 405 | */ | ||
| 406 | protected void processActionEvent(ActionEvent e) { | ||
| 407 | ActionListener listener = actionListener; | ||
| 408 | if (listener != null) { | ||
| 409 | listener.actionPerformed(e); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | /** | ||
| 414 | * Returns a string representing the state of this <code>Button</code>. | ||
| 415 | * This method is intended to be used only for debugging purposes, and the | ||
| 416 | * content and format of the returned string may vary between | ||
| 417 | * implementations. The returned string may be empty but may not be | ||
| 418 | * <code>null</code>. | ||
| 419 | * | ||
| 420 | * @return the parameter string of this button | ||
| 421 | */ | ||
| 422 | protected String paramString() { | ||
| 423 | return super.paramString() + ",label=" + label; | ||
| 424 | } | ||
| 425 | |||
| 426 | |||
| 427 | /* Serialization support. | ||
| 428 | */ | ||
| 429 | |||
| 430 | /* | ||
| 431 | * Button Serial Data Version. | ||
| 432 | * @serial | ||
| 433 | */ | ||
| 434 | private int buttonSerializedDataVersion = 1; | ||
| 435 | |||
| 436 | /** | ||
| 437 | * Writes default serializable fields to stream. Writes | ||
| 438 | * a list of serializable <code>ActionListeners</code> | ||
| 439 | * as optional data. The non-serializable | ||
| 440 | * <code>ActionListeners</code> are detected and | ||
| 441 | * no attempt is made to serialize them. | ||
| 442 | * | ||
| 443 | * @serialData <code>null</code> terminated sequence of 0 or | ||
| 444 | * more pairs: the pair consists of a <code>String</code> | ||
| 445 | * and an <code>Object</code>; the <code>String</code> | ||
| 446 | * indicates the type of object and is one of the following: | ||
| 447 | * <code>actionListenerK</code> indicating an | ||
| 448 | * <code>ActionListener</code> object | ||
| 449 | * | ||
| 450 | * @param s the <code>ObjectOutputStream</code> to write | ||
| 451 | * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) | ||
| 452 | * @see java.awt.Component#actionListenerK | ||
| 453 | * @see #readObject(ObjectInputStream) | ||
| 454 | */ | ||
| 455 | private void writeObject(ObjectOutputStream s) | ||
| 456 | throws IOException | ||
| 457 | { | ||
| 458 | s.defaultWriteObject(); | ||
| 459 | |||
| 460 | AWTEventMulticaster.save(s, actionListenerK, actionListener); | ||
| 461 | s.writeObject(null); | ||
| 462 | } | ||
| 463 | |||
| 464 | /** | ||
| 465 | * Reads the <code>ObjectInputStream</code> and if | ||
| 466 | * it isn't <code>null</code> adds a listener to | ||
| 467 | * receive action events fired by the button. | ||
| 468 | * Unrecognized keys or values will be ignored. | ||
| 469 | * | ||
| 470 | * @param s the <code>ObjectInputStream</code> to read | ||
| 471 | * @exception HeadlessException if | ||
| 472 | * <code>GraphicsEnvironment.isHeadless</code> returns | ||
| 473 | * <code>true</code> | ||
| 474 | * @serial | ||
| 475 | * @see #removeActionListener(ActionListener) | ||
| 476 | * @see #addActionListener(ActionListener) | ||
| 477 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 478 | * @see #writeObject(ObjectOutputStream) | ||
| 479 | */ | ||
| 480 | private void readObject(ObjectInputStream s) | ||
| 481 | throws ClassNotFoundException, IOException, HeadlessException | ||
| 482 | { | ||
| 483 | GraphicsEnvironment.checkHeadless(); | ||
| 484 | s.defaultReadObject(); | ||
| 485 | |||
| 486 | Object keyOrNull; | ||
| 487 | while(null != (keyOrNull = s.readObject())) { | ||
| 488 | String key = ((String)keyOrNull).intern(); | ||
| 489 | |||
| 490 | if (actionListenerK == key) | ||
| 491 | addActionListener((ActionListener)(s.readObject())); | ||
| 492 | |||
| 493 | else // skip value for unrecognized key | ||
| 494 | s.readObject(); | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | |||
| 499 | ///////////////// | ||
| 500 | // Accessibility support | ||
| 501 | //////////////// | ||
| 502 | |||
| 503 | /** | ||
| 504 | * Gets the <code>AccessibleContext</code> associated with | ||
| 505 | * this <code>Button</code>. For buttons, the | ||
| 506 | * <code>AccessibleContext</code> takes the form of an | ||
| 507 | * <code>AccessibleAWTButton</code>. | ||
| 508 | * A new <code>AccessibleAWTButton</code> instance is | ||
| 509 | * created if necessary. | ||
| 510 | * | ||
| 511 | * @return an <code>AccessibleAWTButton</code> that serves as the | ||
| 512 | * <code>AccessibleContext</code> of this <code>Button</code> | ||
| 513 | * @beaninfo | ||
| 514 | * expert: true | ||
| 515 | * description: The AccessibleContext associated with this Button. | ||
| 516 | * @since 1.3 | ||
| 517 | */ | ||
| 518 | public AccessibleContext getAccessibleContext() { | ||
| 519 | if (accessibleContext == null) { | ||
| 520 | accessibleContext = new AccessibleAWTButton(); | ||
| 521 | } | ||
| 522 | return accessibleContext; | ||
| 523 | } | ||
| 524 | |||
| 525 | /** | ||
| 526 | * This class implements accessibility support for the | ||
| 527 | * <code>Button</code> class. It provides an implementation of the | ||
| 528 | * Java Accessibility API appropriate to button user-interface elements. | ||
| 529 | * @since 1.3 | ||
| 530 | */ | ||
| 531 | protected class AccessibleAWTButton extends AccessibleAWTComponent | ||
| 532 | implements AccessibleAction, AccessibleValue | ||
| 533 | { | ||
| 534 | /* | ||
| 535 | * JDK 1.3 serialVersionUID | ||
| 536 | */ | ||
| 537 | private static final long serialVersionUID = -5932203980244017102L; | ||
| 538 | |||
| 539 | /** | ||
| 540 | * Get the accessible name of this object. | ||
| 541 | * | ||
| 542 | * @return the localized name of the object -- can be null if this | ||
| 543 | * object does not have a name | ||
| 544 | */ | ||
| 545 | public String getAccessibleName() { | ||
| 546 | if (accessibleName != null) { | ||
| 547 | return accessibleName; | ||
| 548 | } else { | ||
| 549 | if (getLabel() == null) { | ||
| 550 | return super.getAccessibleName(); | ||
| 551 | } else { | ||
| 552 | return getLabel(); | ||
| 553 | } | ||
| 554 | } | ||
| 555 | } | ||
| 556 | |||
| 557 | /** | ||
| 558 | * Get the AccessibleAction associated with this object. In the | ||
| 559 | * implementation of the Java Accessibility API for this class, | ||
| 560 | * return this object, which is responsible for implementing the | ||
| 561 | * AccessibleAction interface on behalf of itself. | ||
| 562 | * | ||
| 563 | * @return this object | ||
| 564 | */ | ||
| 565 | public AccessibleAction getAccessibleAction() { | ||
| 566 | return this; | ||
| 567 | } | ||
| 568 | |||
| 569 | /** | ||
| 570 | * Get the AccessibleValue associated with this object. In the | ||
| 571 | * implementation of the Java Accessibility API for this class, | ||
| 572 | * return this object, which is responsible for implementing the | ||
| 573 | * AccessibleValue interface on behalf of itself. | ||
| 574 | * | ||
| 575 | * @return this object | ||
| 576 | */ | ||
| 577 | public AccessibleValue getAccessibleValue() { | ||
| 578 | return this; | ||
| 579 | } | ||
| 580 | |||
| 581 | /** | ||
| 582 | * Returns the number of Actions available in this object. The | ||
| 583 | * default behavior of a button is to have one action - toggle | ||
| 584 | * the button. | ||
| 585 | * | ||
| 586 | * @return 1, the number of Actions in this object | ||
| 587 | */ | ||
| 588 | public int getAccessibleActionCount() { | ||
| 589 | return 1; | ||
| 590 | } | ||
| 591 | |||
| 592 | /** | ||
| 593 | * Return a description of the specified action of the object. | ||
| 594 | * | ||
| 595 | * @param i zero-based index of the actions | ||
| 596 | */ | ||
| 597 | public String getAccessibleActionDescription(int i) { | ||
| 598 | if (i == 0) { | ||
| 599 | // [[[PENDING: WDW -- need to provide a localized string]]] | ||
| 600 | return "click"; | ||
| 601 | } else { | ||
| 602 | return null; | ||
| 603 | } | ||
| 604 | } | ||
| 605 | |||
| 606 | /** | ||
| 607 | * Perform the specified Action on the object | ||
| 608 | * | ||
| 609 | * @param i zero-based index of actions | ||
| 610 | * @return true if the the action was performed; else false. | ||
| 611 | */ | ||
| 612 | public boolean doAccessibleAction(int i) { | ||
| 613 | if (i == 0) { | ||
| 614 | // Simulate a button click | ||
| 615 | Toolkit.getEventQueue().postEvent( | ||
| 616 | new ActionEvent(Button.this, | ||
| 617 | ActionEvent.ACTION_PERFORMED, | ||
| 618 | Button.this.getActionCommand())); | ||
| 619 | return true; | ||
| 620 | } else { | ||
| 621 | return false; | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | /** | ||
| 626 | * Get the value of this object as a Number. | ||
| 627 | * | ||
| 628 | * @return An Integer of 0 if this isn't selected or an Integer of 1 if | ||
| 629 | * this is selected. | ||
| 630 | * @see javax.swing.AbstractButton#isSelected() | ||
| 631 | */ | ||
| 632 | public Number getCurrentAccessibleValue() { | ||
| 633 | return Integer.valueOf(0); | ||
| 634 | } | ||
| 635 | |||
| 636 | /** | ||
| 637 | * Set the value of this object as a Number. | ||
| 638 | * | ||
| 639 | * @return True if the value was set. | ||
| 640 | */ | ||
| 641 | public boolean setCurrentAccessibleValue(Number n) { | ||
| 642 | return false; | ||
| 643 | } | ||
| 644 | |||
| 645 | /** | ||
| 646 | * Get the minimum value of this object as a Number. | ||
| 647 | * | ||
| 648 | * @return An Integer of 0. | ||
| 649 | */ | ||
| 650 | public Number getMinimumAccessibleValue() { | ||
| 651 | return Integer.valueOf(0); | ||
| 652 | } | ||
| 653 | |||
| 654 | /** | ||
| 655 | * Get the maximum value of this object as a Number. | ||
| 656 | * | ||
| 657 | * @return An Integer of 0. | ||
| 658 | */ | ||
| 659 | public Number getMaximumAccessibleValue() { | ||
| 660 | return Integer.valueOf(0); | ||
| 661 | } | ||
| 662 | |||
| 663 | /** | ||
| 664 | * Get the role of this object. | ||
| 665 | * | ||
| 666 | * @return an instance of AccessibleRole describing the role of the | ||
| 667 | * object | ||
| 668 | * @see AccessibleRole | ||
| 669 | */ | ||
| 670 | public AccessibleRole getAccessibleRole() { | ||
| 671 | return AccessibleRole.PUSH_BUTTON; | ||
| 672 | } | ||
| 673 | } // inner class AccessibleAWTButton | ||
| 674 | |||
| 675 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,254 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2010, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.image.BufferStrategy; | ||
| 28 | import java.awt.peer.CanvasPeer; | ||
| 29 | import javax.accessibility.*; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * A <code>Canvas</code> component represents a blank rectangular | ||
| 33 | * area of the screen onto which the application can draw or from | ||
| 34 | * which the application can trap input events from the user. | ||
| 35 | * <p> | ||
| 36 | * An application must subclass the <code>Canvas</code> class in | ||
| 37 | * order to get useful functionality such as creating a custom | ||
| 38 | * component. The <code>paint</code> method must be overridden | ||
| 39 | * in order to perform custom graphics on the canvas. | ||
| 40 | * | ||
| 41 | * @author Sami Shaio | ||
| 42 | * @since JDK1.0 | ||
| 43 | */ | ||
| 44 | public class Canvas extends Component implements Accessible { | ||
| 45 | |||
| 46 | private static final String base = "canvas"; | ||
| 47 | private static int nameCounter = 0; | ||
| 48 | |||
| 49 | /* | ||
| 50 | * JDK 1.1 serialVersionUID | ||
| 51 | */ | ||
| 52 | private static final long serialVersionUID = -2284879212465893870L; | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Constructs a new Canvas. | ||
| 56 | */ | ||
| 57 | public Canvas() { | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Constructs a new Canvas given a GraphicsConfiguration object. | ||
| 62 | * | ||
| 63 | * @param config a reference to a GraphicsConfiguration object. | ||
| 64 | * | ||
| 65 | * @see GraphicsConfiguration | ||
| 66 | */ | ||
| 67 | public Canvas(GraphicsConfiguration config) { | ||
| 68 | this(); | ||
| 69 | setGraphicsConfiguration(config); | ||
| 70 | } | ||
| 71 | |||
| 72 | @Override | ||
| 73 | void setGraphicsConfiguration(GraphicsConfiguration gc) { | ||
| 74 | synchronized(getTreeLock()) { | ||
| 75 | CanvasPeer peer = (CanvasPeer)getPeer(); | ||
| 76 | if (peer != null) { | ||
| 77 | gc = peer.getAppropriateGraphicsConfiguration(gc); | ||
| 78 | } | ||
| 79 | super.setGraphicsConfiguration(gc); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * Construct a name for this component. Called by getName() when the | ||
| 85 | * name is null. | ||
| 86 | */ | ||
| 87 | String constructComponentName() { | ||
| 88 | synchronized (Canvas.class) { | ||
| 89 | return base + nameCounter++; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Creates the peer of the canvas. This peer allows you to change the | ||
| 95 | * user interface of the canvas without changing its functionality. | ||
| 96 | * @see java.awt.Toolkit#createCanvas(java.awt.Canvas) | ||
| 97 | * @see java.awt.Component#getToolkit() | ||
| 98 | */ | ||
| 99 | public void addNotify() { | ||
| 100 | synchronized (getTreeLock()) { | ||
| 101 | if (peer == null) | ||
| 102 | peer = getToolkit().createCanvas(this); | ||
| 103 | super.addNotify(); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | /** | ||
| 108 | * Paints this canvas. | ||
| 109 | * <p> | ||
| 110 | * Most applications that subclass <code>Canvas</code> should | ||
| 111 | * override this method in order to perform some useful operation | ||
| 112 | * (typically, custom painting of the canvas). | ||
| 113 | * The default operation is simply to clear the canvas. | ||
| 114 | * Applications that override this method need not call | ||
| 115 | * super.paint(g). | ||
| 116 | * | ||
| 117 | * @param g the specified Graphics context | ||
| 118 | * @see #update(Graphics) | ||
| 119 | * @see Component#paint(Graphics) | ||
| 120 | */ | ||
| 121 | public void paint(Graphics g) { | ||
| 122 | g.clearRect(0, 0, width, height); | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Updates this canvas. | ||
| 127 | * <p> | ||
| 128 | * This method is called in response to a call to <code>repaint</code>. | ||
| 129 | * The canvas is first cleared by filling it with the background | ||
| 130 | * color, and then completely redrawn by calling this canvas's | ||
| 131 | * <code>paint</code> method. | ||
| 132 | * Note: applications that override this method should either call | ||
| 133 | * super.update(g) or incorporate the functionality described | ||
| 134 | * above into their own code. | ||
| 135 | * | ||
| 136 | * @param g the specified Graphics context | ||
| 137 | * @see #paint(Graphics) | ||
| 138 | * @see Component#update(Graphics) | ||
| 139 | */ | ||
| 140 | public void update(Graphics g) { | ||
| 141 | g.clearRect(0, 0, width, height); | ||
| 142 | paint(g); | ||
| 143 | } | ||
| 144 | |||
| 145 | boolean postsOldMouseEvents() { | ||
| 146 | return true; | ||
| 147 | } | ||
| 148 | |||
| 149 | /** | ||
| 150 | * Creates a new strategy for multi-buffering on this component. | ||
| 151 | * Multi-buffering is useful for rendering performance. This method | ||
| 152 | * attempts to create the best strategy available with the number of | ||
| 153 | * buffers supplied. It will always create a <code>BufferStrategy</code> | ||
| 154 | * with that number of buffers. | ||
| 155 | * A page-flipping strategy is attempted first, then a blitting strategy | ||
| 156 | * using accelerated buffers. Finally, an unaccelerated blitting | ||
| 157 | * strategy is used. | ||
| 158 | * <p> | ||
| 159 | * Each time this method is called, | ||
| 160 | * the existing buffer strategy for this component is discarded. | ||
| 161 | * @param numBuffers number of buffers to create, including the front buffer | ||
| 162 | * @exception IllegalArgumentException if numBuffers is less than 1. | ||
| 163 | * @exception IllegalStateException if the component is not displayable | ||
| 164 | * @see #isDisplayable | ||
| 165 | * @see #getBufferStrategy | ||
| 166 | * @since 1.4 | ||
| 167 | */ | ||
| 168 | public void createBufferStrategy(int numBuffers) { | ||
| 169 | super.createBufferStrategy(numBuffers); | ||
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * Creates a new strategy for multi-buffering on this component with the | ||
| 174 | * required buffer capabilities. This is useful, for example, if only | ||
| 175 | * accelerated memory or page flipping is desired (as specified by the | ||
| 176 | * buffer capabilities). | ||
| 177 | * <p> | ||
| 178 | * Each time this method | ||
| 179 | * is called, the existing buffer strategy for this component is discarded. | ||
| 180 | * @param numBuffers number of buffers to create | ||
| 181 | * @param caps the required capabilities for creating the buffer strategy; | ||
| 182 | * cannot be <code>null</code> | ||
| 183 | * @exception AWTException if the capabilities supplied could not be | ||
| 184 | * supported or met; this may happen, for example, if there is not enough | ||
| 185 | * accelerated memory currently available, or if page flipping is specified | ||
| 186 | * but not possible. | ||
| 187 | * @exception IllegalArgumentException if numBuffers is less than 1, or if | ||
| 188 | * caps is <code>null</code> | ||
| 189 | * @see #getBufferStrategy | ||
| 190 | * @since 1.4 | ||
| 191 | */ | ||
| 192 | public void createBufferStrategy(int numBuffers, | ||
| 193 | BufferCapabilities caps) throws AWTException { | ||
| 194 | super.createBufferStrategy(numBuffers, caps); | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 198 | * Returns the <code>BufferStrategy</code> used by this component. This | ||
| 199 | * method will return null if a <code>BufferStrategy</code> has not yet | ||
| 200 | * been created or has been disposed. | ||
| 201 | * | ||
| 202 | * @return the buffer strategy used by this component | ||
| 203 | * @see #createBufferStrategy | ||
| 204 | * @since 1.4 | ||
| 205 | */ | ||
| 206 | public BufferStrategy getBufferStrategy() { | ||
| 207 | return super.getBufferStrategy(); | ||
| 208 | } | ||
| 209 | |||
| 210 | /* | ||
| 211 | * --- Accessibility Support --- | ||
| 212 | * | ||
| 213 | */ | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Gets the AccessibleContext associated with this Canvas. | ||
| 217 | * For canvases, the AccessibleContext takes the form of an | ||
| 218 | * AccessibleAWTCanvas. | ||
| 219 | * A new AccessibleAWTCanvas instance is created if necessary. | ||
| 220 | * | ||
| 221 | * @return an AccessibleAWTCanvas that serves as the | ||
| 222 | * AccessibleContext of this Canvas | ||
| 223 | * @since 1.3 | ||
| 224 | */ | ||
| 225 | public AccessibleContext getAccessibleContext() { | ||
| 226 | if (accessibleContext == null) { | ||
| 227 | accessibleContext = new AccessibleAWTCanvas(); | ||
| 228 | } | ||
| 229 | return accessibleContext; | ||
| 230 | } | ||
| 231 | |||
| 232 | /** | ||
| 233 | * This class implements accessibility support for the | ||
| 234 | * <code>Canvas</code> class. It provides an implementation of the | ||
| 235 | * Java Accessibility API appropriate to canvas user-interface elements. | ||
| 236 | * @since 1.3 | ||
| 237 | */ | ||
| 238 | protected class AccessibleAWTCanvas extends AccessibleAWTComponent | ||
| 239 | { | ||
| 240 | private static final long serialVersionUID = -6325592262103146699L; | ||
| 241 | |||
| 242 | /** | ||
| 243 | * Get the role of this object. | ||
| 244 | * | ||
| 245 | * @return an instance of AccessibleRole describing the role of the | ||
| 246 | * object | ||
| 247 | * @see AccessibleRole | ||
| 248 | */ | ||
| 249 | public AccessibleRole getAccessibleRole() { | ||
| 250 | return AccessibleRole.CANVAS; | ||
| 251 | } | ||
| 252 | |||
| 253 | } // inner class AccessibleAWTCanvas | ||
| 254 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,612 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2006, 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 java.awt; | ||
| 27 | |||
| 28 | import java.util.Hashtable; | ||
| 29 | import java.util.Vector; | ||
| 30 | import java.util.Enumeration; | ||
| 31 | |||
| 32 | import java.io.Serializable; | ||
| 33 | import java.io.ObjectInputStream; | ||
| 34 | import java.io.ObjectOutputStream; | ||
| 35 | import java.io.ObjectStreamField; | ||
| 36 | import java.io.IOException; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * A <code>CardLayout</code> object is a layout manager for a | ||
| 40 | * container. It treats each component in the container as a card. | ||
| 41 | * Only one card is visible at a time, and the container acts as | ||
| 42 | * a stack of cards. The first component added to a | ||
| 43 | * <code>CardLayout</code> object is the visible component when the | ||
| 44 | * container is first displayed. | ||
| 45 | * <p> | ||
| 46 | * The ordering of cards is determined by the container's own internal | ||
| 47 | * ordering of its component objects. <code>CardLayout</code> | ||
| 48 | * defines a set of methods that allow an application to flip | ||
| 49 | * through these cards sequentially, or to show a specified card. | ||
| 50 | * The {@link CardLayout#addLayoutComponent} | ||
| 51 | * method can be used to associate a string identifier with a given card | ||
| 52 | * for fast random access. | ||
| 53 | * | ||
| 54 | * @author Arthur van Hoff | ||
| 55 | * @see java.awt.Container | ||
| 56 | * @since JDK1.0 | ||
| 57 | */ | ||
| 58 | |||
| 59 | public class CardLayout implements LayoutManager2, | ||
| 60 | Serializable { | ||
| 61 | |||
| 62 | private static final long serialVersionUID = -4328196481005934313L; | ||
| 63 | |||
| 64 | /* | ||
| 65 | * This creates a Vector to store associated | ||
| 66 | * pairs of components and their names. | ||
| 67 | * @see java.util.Vector | ||
| 68 | */ | ||
| 69 | Vector vector = new Vector(); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * A pair of Component and String that represents its name. | ||
| 73 | */ | ||
| 74 | class Card implements Serializable { | ||
| 75 | static final long serialVersionUID = 6640330810709497518L; | ||
| 76 | public String name; | ||
| 77 | public Component comp; | ||
| 78 | public Card(String cardName, Component cardComponent) { | ||
| 79 | name = cardName; | ||
| 80 | comp = cardComponent; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Index of Component currently displayed by CardLayout. | ||
| 86 | */ | ||
| 87 | int currentCard = 0; | ||
| 88 | |||
| 89 | |||
| 90 | /* | ||
| 91 | * A cards horizontal Layout gap (inset). It specifies | ||
| 92 | * the space between the left and right edges of a | ||
| 93 | * container and the current component. | ||
| 94 | * This should be a non negative Integer. | ||
| 95 | * @see getHgap() | ||
| 96 | * @see setHgap() | ||
| 97 | */ | ||
| 98 | int hgap; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * A cards vertical Layout gap (inset). It specifies | ||
| 102 | * the space between the top and bottom edges of a | ||
| 103 | * container and the current component. | ||
| 104 | * This should be a non negative Integer. | ||
| 105 | * @see getVgap() | ||
| 106 | * @see setVgap() | ||
| 107 | */ | ||
| 108 | int vgap; | ||
| 109 | |||
| 110 | /** | ||
| 111 | * @serialField tab Hashtable | ||
| 112 | * deprectated, for forward compatibility only | ||
| 113 | * @serialField hgap int | ||
| 114 | * @serialField vgap int | ||
| 115 | * @serialField vector Vector | ||
| 116 | * @serialField currentCard int | ||
| 117 | */ | ||
| 118 | private static final ObjectStreamField[] serialPersistentFields = { | ||
| 119 | new ObjectStreamField("tab", Hashtable.class), | ||
| 120 | new ObjectStreamField("hgap", Integer.TYPE), | ||
| 121 | new ObjectStreamField("vgap", Integer.TYPE), | ||
| 122 | new ObjectStreamField("vector", Vector.class), | ||
| 123 | new ObjectStreamField("currentCard", Integer.TYPE) | ||
| 124 | }; | ||
| 125 | |||
| 126 | /** | ||
| 127 | * Creates a new card layout with gaps of size zero. | ||
| 128 | */ | ||
| 129 | public CardLayout() { | ||
| 130 | this(0, 0); | ||
| 131 | } | ||
| 132 | |||
| 133 | /** | ||
| 134 | * Creates a new card layout with the specified horizontal and | ||
| 135 | * vertical gaps. The horizontal gaps are placed at the left and | ||
| 136 | * right edges. The vertical gaps are placed at the top and bottom | ||
| 137 | * edges. | ||
| 138 | * @param hgap the horizontal gap. | ||
| 139 | * @param vgap the vertical gap. | ||
| 140 | */ | ||
| 141 | public CardLayout(int hgap, int vgap) { | ||
| 142 | this.hgap = hgap; | ||
| 143 | this.vgap = vgap; | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Gets the horizontal gap between components. | ||
| 148 | * @return the horizontal gap between components. | ||
| 149 | * @see java.awt.CardLayout#setHgap(int) | ||
| 150 | * @see java.awt.CardLayout#getVgap() | ||
| 151 | * @since JDK1.1 | ||
| 152 | */ | ||
| 153 | public int getHgap() { | ||
| 154 | return hgap; | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Sets the horizontal gap between components. | ||
| 159 | * @param hgap the horizontal gap between components. | ||
| 160 | * @see java.awt.CardLayout#getHgap() | ||
| 161 | * @see java.awt.CardLayout#setVgap(int) | ||
| 162 | * @since JDK1.1 | ||
| 163 | */ | ||
| 164 | public void setHgap(int hgap) { | ||
| 165 | this.hgap = hgap; | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * Gets the vertical gap between components. | ||
| 170 | * @return the vertical gap between components. | ||
| 171 | * @see java.awt.CardLayout#setVgap(int) | ||
| 172 | * @see java.awt.CardLayout#getHgap() | ||
| 173 | */ | ||
| 174 | public int getVgap() { | ||
| 175 | return vgap; | ||
| 176 | } | ||
| 177 | |||
| 178 | /** | ||
| 179 | * Sets the vertical gap between components. | ||
| 180 | * @param vgap the vertical gap between components. | ||
| 181 | * @see java.awt.CardLayout#getVgap() | ||
| 182 | * @see java.awt.CardLayout#setHgap(int) | ||
| 183 | * @since JDK1.1 | ||
| 184 | */ | ||
| 185 | public void setVgap(int vgap) { | ||
| 186 | this.vgap = vgap; | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * Adds the specified component to this card layout's internal | ||
| 191 | * table of names. The object specified by <code>constraints</code> | ||
| 192 | * must be a string. The card layout stores this string as a key-value | ||
| 193 | * pair that can be used for random access to a particular card. | ||
| 194 | * By calling the <code>show</code> method, an application can | ||
| 195 | * display the component with the specified name. | ||
| 196 | * @param comp the component to be added. | ||
| 197 | * @param constraints a tag that identifies a particular | ||
| 198 | * card in the layout. | ||
| 199 | * @see java.awt.CardLayout#show(java.awt.Container, java.lang.String) | ||
| 200 | * @exception IllegalArgumentException if the constraint is not a string. | ||
| 201 | */ | ||
| 202 | public void addLayoutComponent(Component comp, Object constraints) { | ||
| 203 | synchronized (comp.getTreeLock()) { | ||
| 204 | if (constraints == null){ | ||
| 205 | constraints = ""; | ||
| 206 | } | ||
| 207 | if (constraints instanceof String) { | ||
| 208 | addLayoutComponent((String)constraints, comp); | ||
| 209 | } else { | ||
| 210 | throw new IllegalArgumentException("cannot add to layout: constraint must be a string"); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | ||
| 216 | * @deprecated replaced by | ||
| 217 | * <code>addLayoutComponent(Component, Object)</code>. | ||
| 218 | */ | ||
| 219 | @Deprecated | ||
| 220 | public void addLayoutComponent(String name, Component comp) { | ||
| 221 | synchronized (comp.getTreeLock()) { | ||
| 222 | if (!vector.isEmpty()) { | ||
| 223 | comp.setVisible(false); | ||
| 224 | } | ||
| 225 | for (int i=0; i < vector.size(); i++) { | ||
| 226 | if (((Card)vector.get(i)).name.equals(name)) { | ||
| 227 | ((Card)vector.get(i)).comp = comp; | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | vector.add(new Card(name, comp)); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /** | ||
| 236 | * Removes the specified component from the layout. | ||
| 237 | * If the card was visible on top, the next card underneath it is shown. | ||
| 238 | * @param comp the component to be removed. | ||
| 239 | * @see java.awt.Container#remove(java.awt.Component) | ||
| 240 | * @see java.awt.Container#removeAll() | ||
| 241 | */ | ||
| 242 | public void removeLayoutComponent(Component comp) { | ||
| 243 | synchronized (comp.getTreeLock()) { | ||
| 244 | for (int i = 0; i < vector.size(); i++) { | ||
| 245 | if (((Card)vector.get(i)).comp == comp) { | ||
| 246 | // if we remove current component we should show next one | ||
| 247 | if (comp.isVisible() && (comp.getParent() != null)) { | ||
| 248 | next(comp.getParent()); | ||
| 249 | } | ||
| 250 | |||
| 251 | vector.remove(i); | ||
| 252 | |||
| 253 | // correct currentCard if this is necessary | ||
| 254 | if (currentCard > i) { | ||
| 255 | currentCard--; | ||
| 256 | } | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * Determines the preferred size of the container argument using | ||
| 265 | * this card layout. | ||
| 266 | * @param parent the parent container in which to do the layout | ||
| 267 | * @return the preferred dimensions to lay out the subcomponents | ||
| 268 | * of the specified container | ||
| 269 | * @see java.awt.Container#getPreferredSize | ||
| 270 | * @see java.awt.CardLayout#minimumLayoutSize | ||
| 271 | */ | ||
| 272 | public Dimension preferredLayoutSize(Container parent) { | ||
| 273 | synchronized (parent.getTreeLock()) { | ||
| 274 | Insets insets = parent.getInsets(); | ||
| 275 | int ncomponents = parent.getComponentCount(); | ||
| 276 | int w = 0; | ||
| 277 | int h = 0; | ||
| 278 | |||
| 279 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 280 | Component comp = parent.getComponent(i); | ||
| 281 | Dimension d = comp.getPreferredSize(); | ||
| 282 | if (d.width > w) { | ||
| 283 | w = d.width; | ||
| 284 | } | ||
| 285 | if (d.height > h) { | ||
| 286 | h = d.height; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | return new Dimension(insets.left + insets.right + w + hgap*2, | ||
| 290 | insets.top + insets.bottom + h + vgap*2); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * Calculates the minimum size for the specified panel. | ||
| 296 | * @param parent the parent container in which to do the layout | ||
| 297 | * @return the minimum dimensions required to lay out the | ||
| 298 | * subcomponents of the specified container | ||
| 299 | * @see java.awt.Container#doLayout | ||
| 300 | * @see java.awt.CardLayout#preferredLayoutSize | ||
| 301 | */ | ||
| 302 | public Dimension minimumLayoutSize(Container parent) { | ||
| 303 | synchronized (parent.getTreeLock()) { | ||
| 304 | Insets insets = parent.getInsets(); | ||
| 305 | int ncomponents = parent.getComponentCount(); | ||
| 306 | int w = 0; | ||
| 307 | int h = 0; | ||
| 308 | |||
| 309 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 310 | Component comp = parent.getComponent(i); | ||
| 311 | Dimension d = comp.getMinimumSize(); | ||
| 312 | if (d.width > w) { | ||
| 313 | w = d.width; | ||
| 314 | } | ||
| 315 | if (d.height > h) { | ||
| 316 | h = d.height; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | return new Dimension(insets.left + insets.right + w + hgap*2, | ||
| 320 | insets.top + insets.bottom + h + vgap*2); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | /** | ||
| 325 | * Returns the maximum dimensions for this layout given the components | ||
| 326 | * in the specified target container. | ||
| 327 | * @param target the component which needs to be laid out | ||
| 328 | * @see Container | ||
| 329 | * @see #minimumLayoutSize | ||
| 330 | * @see #preferredLayoutSize | ||
| 331 | */ | ||
| 332 | public Dimension maximumLayoutSize(Container target) { | ||
| 333 | return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); | ||
| 334 | } | ||
| 335 | |||
| 336 | /** | ||
| 337 | * Returns the alignment along the x axis. This specifies how | ||
| 338 | * the component would like to be aligned relative to other | ||
| 339 | * components. The value should be a number between 0 and 1 | ||
| 340 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 341 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 342 | */ | ||
| 343 | public float getLayoutAlignmentX(Container parent) { | ||
| 344 | return 0.5f; | ||
| 345 | } | ||
| 346 | |||
| 347 | /** | ||
| 348 | * Returns the alignment along the y axis. This specifies how | ||
| 349 | * the component would like to be aligned relative to other | ||
| 350 | * components. The value should be a number between 0 and 1 | ||
| 351 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 352 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 353 | */ | ||
| 354 | public float getLayoutAlignmentY(Container parent) { | ||
| 355 | return 0.5f; | ||
| 356 | } | ||
| 357 | |||
| 358 | /** | ||
| 359 | * Invalidates the layout, indicating that if the layout manager | ||
| 360 | * has cached information it should be discarded. | ||
| 361 | */ | ||
| 362 | public void invalidateLayout(Container target) { | ||
| 363 | } | ||
| 364 | |||
| 365 | /** | ||
| 366 | * Lays out the specified container using this card layout. | ||
| 367 | * <p> | ||
| 368 | * Each component in the <code>parent</code> container is reshaped | ||
| 369 | * to be the size of the container, minus space for surrounding | ||
| 370 | * insets, horizontal gaps, and vertical gaps. | ||
| 371 | * | ||
| 372 | * @param parent the parent container in which to do the layout | ||
| 373 | * @see java.awt.Container#doLayout | ||
| 374 | */ | ||
| 375 | public void layoutContainer(Container parent) { | ||
| 376 | synchronized (parent.getTreeLock()) { | ||
| 377 | Insets insets = parent.getInsets(); | ||
| 378 | int ncomponents = parent.getComponentCount(); | ||
| 379 | Component comp = null; | ||
| 380 | boolean currentFound = false; | ||
| 381 | |||
| 382 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 383 | comp = parent.getComponent(i); | ||
| 384 | comp.setBounds(hgap + insets.left, vgap + insets.top, | ||
| 385 | parent.width - (hgap*2 + insets.left + insets.right), | ||
| 386 | parent.height - (vgap*2 + insets.top + insets.bottom)); | ||
| 387 | if (comp.isVisible()) { | ||
| 388 | currentFound = true; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | if (!currentFound && ncomponents > 0) { | ||
| 393 | parent.getComponent(0).setVisible(true); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | /** | ||
| 399 | * Make sure that the Container really has a CardLayout installed. | ||
| 400 | * Otherwise havoc can ensue! | ||
| 401 | */ | ||
| 402 | void checkLayout(Container parent) { | ||
| 403 | if (parent.getLayout() != this) { | ||
| 404 | throw new IllegalArgumentException("wrong parent for CardLayout"); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | /** | ||
| 409 | * Flips to the first card of the container. | ||
| 410 | * @param parent the parent container in which to do the layout | ||
| 411 | * @see java.awt.CardLayout#last | ||
| 412 | */ | ||
| 413 | public void first(Container parent) { | ||
| 414 | synchronized (parent.getTreeLock()) { | ||
| 415 | checkLayout(parent); | ||
| 416 | int ncomponents = parent.getComponentCount(); | ||
| 417 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 418 | Component comp = parent.getComponent(i); | ||
| 419 | if (comp.isVisible()) { | ||
| 420 | comp.setVisible(false); | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | if (ncomponents > 0) { | ||
| 425 | currentCard = 0; | ||
| 426 | parent.getComponent(0).setVisible(true); | ||
| 427 | parent.validate(); | ||
| 428 | } | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | /** | ||
| 433 | * Flips to the next card of the specified container. If the | ||
| 434 | * currently visible card is the last one, this method flips to the | ||
| 435 | * first card in the layout. | ||
| 436 | * @param parent the parent container in which to do the layout | ||
| 437 | * @see java.awt.CardLayout#previous | ||
| 438 | */ | ||
| 439 | public void next(Container parent) { | ||
| 440 | synchronized (parent.getTreeLock()) { | ||
| 441 | checkLayout(parent); | ||
| 442 | int ncomponents = parent.getComponentCount(); | ||
| 443 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 444 | Component comp = parent.getComponent(i); | ||
| 445 | if (comp.isVisible()) { | ||
| 446 | comp.setVisible(false); | ||
| 447 | currentCard = (i + 1) % ncomponents; | ||
| 448 | comp = parent.getComponent(currentCard); | ||
| 449 | comp.setVisible(true); | ||
| 450 | parent.validate(); | ||
| 451 | return; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | showDefaultComponent(parent); | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | /** | ||
| 459 | * Flips to the previous card of the specified container. If the | ||
| 460 | * currently visible card is the first one, this method flips to the | ||
| 461 | * last card in the layout. | ||
| 462 | * @param parent the parent container in which to do the layout | ||
| 463 | * @see java.awt.CardLayout#next | ||
| 464 | */ | ||
| 465 | public void previous(Container parent) { | ||
| 466 | synchronized (parent.getTreeLock()) { | ||
| 467 | checkLayout(parent); | ||
| 468 | int ncomponents = parent.getComponentCount(); | ||
| 469 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 470 | Component comp = parent.getComponent(i); | ||
| 471 | if (comp.isVisible()) { | ||
| 472 | comp.setVisible(false); | ||
| 473 | currentCard = ((i > 0) ? i-1 : ncomponents-1); | ||
| 474 | comp = parent.getComponent(currentCard); | ||
| 475 | comp.setVisible(true); | ||
| 476 | parent.validate(); | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | showDefaultComponent(parent); | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | void showDefaultComponent(Container parent) { | ||
| 485 | if (parent.getComponentCount() > 0) { | ||
| 486 | currentCard = 0; | ||
| 487 | parent.getComponent(0).setVisible(true); | ||
| 488 | parent.validate(); | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | /** | ||
| 493 | * Flips to the last card of the container. | ||
| 494 | * @param parent the parent container in which to do the layout | ||
| 495 | * @see java.awt.CardLayout#first | ||
| 496 | */ | ||
| 497 | public void last(Container parent) { | ||
| 498 | synchronized (parent.getTreeLock()) { | ||
| 499 | checkLayout(parent); | ||
| 500 | int ncomponents = parent.getComponentCount(); | ||
| 501 | for (int i = 0 ; i < ncomponents ; i++) { | ||
| 502 | Component comp = parent.getComponent(i); | ||
| 503 | if (comp.isVisible()) { | ||
| 504 | comp.setVisible(false); | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | } | ||
| 508 | if (ncomponents > 0) { | ||
| 509 | currentCard = ncomponents - 1; | ||
| 510 | parent.getComponent(currentCard).setVisible(true); | ||
| 511 | parent.validate(); | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | /** | ||
| 517 | * Flips to the component that was added to this layout with the | ||
| 518 | * specified <code>name</code>, using <code>addLayoutComponent</code>. | ||
| 519 | * If no such component exists, then nothing happens. | ||
| 520 | * @param parent the parent container in which to do the layout | ||
| 521 | * @param name the component name | ||
| 522 | * @see java.awt.CardLayout#addLayoutComponent(java.awt.Component, java.lang.Object) | ||
| 523 | */ | ||
| 524 | public void show(Container parent, String name) { | ||
| 525 | synchronized (parent.getTreeLock()) { | ||
| 526 | checkLayout(parent); | ||
| 527 | Component next = null; | ||
| 528 | int ncomponents = vector.size(); | ||
| 529 | for (int i = 0; i < ncomponents; i++) { | ||
| 530 | Card card = (Card)vector.get(i); | ||
| 531 | if (card.name.equals(name)) { | ||
| 532 | next = card.comp; | ||
| 533 | currentCard = i; | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | if ((next != null) && !next.isVisible()) { | ||
| 538 | ncomponents = parent.getComponentCount(); | ||
| 539 | for (int i = 0; i < ncomponents; i++) { | ||
| 540 | Component comp = parent.getComponent(i); | ||
| 541 | if (comp.isVisible()) { | ||
| 542 | comp.setVisible(false); | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | next.setVisible(true); | ||
| 547 | parent.validate(); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | /** | ||
| 553 | * Returns a string representation of the state of this card layout. | ||
| 554 | * @return a string representation of this card layout. | ||
| 555 | */ | ||
| 556 | public String toString() { | ||
| 557 | return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]"; | ||
| 558 | } | ||
| 559 | |||
| 560 | /** | ||
| 561 | * Reads serializable fields from stream. | ||
| 562 | */ | ||
| 563 | private void readObject(ObjectInputStream s) | ||
| 564 | throws ClassNotFoundException, IOException | ||
| 565 | { | ||
| 566 | ObjectInputStream.GetField f = s.readFields(); | ||
| 567 | |||
| 568 | hgap = f.get("hgap", 0); | ||
| 569 | vgap = f.get("vgap", 0); | ||
| 570 | |||
| 571 | if (f.defaulted("vector")) { | ||
| 572 | // pre-1.4 stream | ||
| 573 | Hashtable tab = (Hashtable)f.get("tab", null); | ||
| 574 | vector = new Vector(); | ||
| 575 | if (tab != null && !tab.isEmpty()) { | ||
| 576 | for (Enumeration e = tab.keys() ; e.hasMoreElements() ; ) { | ||
| 577 | String key = (String)e.nextElement(); | ||
| 578 | Component comp = (Component)tab.get(key); | ||
| 579 | vector.add(new Card(key, comp)); | ||
| 580 | if (comp.isVisible()) { | ||
| 581 | currentCard = vector.size() - 1; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | } | ||
| 585 | } else { | ||
| 586 | vector = (Vector)f.get("vector", null); | ||
| 587 | currentCard = f.get("currentCard", 0); | ||
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 591 | /** | ||
| 592 | * Writes serializable fields to stream. | ||
| 593 | */ | ||
| 594 | private void writeObject(ObjectOutputStream s) | ||
| 595 | throws IOException | ||
| 596 | { | ||
| 597 | Hashtable tab = new Hashtable(); | ||
| 598 | int ncomponents = vector.size(); | ||
| 599 | for (int i = 0; i < ncomponents; i++) { | ||
| 600 | Card card = (Card)vector.get(i); | ||
| 601 | tab.put(card.name, card.comp); | ||
| 602 | } | ||
| 603 | |||
| 604 | ObjectOutputStream.PutField f = s.putFields(); | ||
| 605 | f.put("hgap", hgap); | ||
| 606 | f.put("vgap", vgap); | ||
| 607 | f.put("vector", vector); | ||
| 608 | f.put("currentCard", currentCard); | ||
| 609 | f.put("tab", tab); | ||
| 610 | s.writeFields(); | ||
| 611 | } | ||
| 612 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,866 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2008, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.peer.CheckboxPeer; | ||
| 28 | import java.awt.event.*; | ||
| 29 | import java.util.EventListener; | ||
| 30 | import java.io.ObjectOutputStream; | ||
| 31 | import java.io.ObjectInputStream; | ||
| 32 | import java.io.IOException; | ||
| 33 | import javax.accessibility.*; | ||
| 34 | |||
| 35 | |||
| 36 | /** | ||
| 37 | * A check box is a graphical component that can be in either an | ||
| 38 | * "on" (<code>true</code>) or "off" (<code>false</code>) state. | ||
| 39 | * Clicking on a check box changes its state from | ||
| 40 | * "on" to "off," or from "off" to "on." | ||
| 41 | * <p> | ||
| 42 | * The following code example creates a set of check boxes in | ||
| 43 | * a grid layout: | ||
| 44 | * <p> | ||
| 45 | * <hr><blockquote><pre> | ||
| 46 | * setLayout(new GridLayout(3, 1)); | ||
| 47 | * add(new Checkbox("one", null, true)); | ||
| 48 | * add(new Checkbox("two")); | ||
| 49 | * add(new Checkbox("three")); | ||
| 50 | * </pre></blockquote><hr> | ||
| 51 | * <p> | ||
| 52 | * This image depicts the check boxes and grid layout | ||
| 53 | * created by this code example: | ||
| 54 | * <p> | ||
| 55 | * <img src="doc-files/Checkbox-1.gif" alt="The following context describes the graphic." | ||
| 56 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 57 | * <p> | ||
| 58 | * The button labeled <code>one</code> is in the "on" state, and the | ||
| 59 | * other two are in the "off" state. In this example, which uses the | ||
| 60 | * <code>GridLayout</code> class, the states of the three check | ||
| 61 | * boxes are set independently. | ||
| 62 | * <p> | ||
| 63 | * Alternatively, several check boxes can be grouped together under | ||
| 64 | * the control of a single object, using the | ||
| 65 | * <code>CheckboxGroup</code> class. | ||
| 66 | * In a check box group, at most one button can be in the "on" | ||
| 67 | * state at any given time. Clicking on a check box to turn it on | ||
| 68 | * forces any other check box in the same group that is on | ||
| 69 | * into the "off" state. | ||
| 70 | * | ||
| 71 | * @author Sami Shaio | ||
| 72 | * @see java.awt.GridLayout | ||
| 73 | * @see java.awt.CheckboxGroup | ||
| 74 | * @since JDK1.0 | ||
| 75 | */ | ||
| 76 | public class Checkbox extends Component implements ItemSelectable, Accessible { | ||
| 77 | |||
| 78 | static { | ||
| 79 | /* ensure that the necessary native libraries are loaded */ | ||
| 80 | Toolkit.loadLibraries(); | ||
| 81 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 82 | initIDs(); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | /** | ||
| 87 | * The label of the Checkbox. | ||
| 88 | * This field can be null. | ||
| 89 | * @serial | ||
| 90 | * @see #getLabel() | ||
| 91 | * @see #setLabel(String) | ||
| 92 | */ | ||
| 93 | String label; | ||
| 94 | |||
| 95 | /** | ||
| 96 | * The state of the <code>Checkbox</code>. | ||
| 97 | * @serial | ||
| 98 | * @see #getState() | ||
| 99 | * @see #setState(boolean) | ||
| 100 | */ | ||
| 101 | boolean state; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * The check box group. | ||
| 105 | * This field can be null indicating that the checkbox | ||
| 106 | * is not a group checkbox. | ||
| 107 | * @serial | ||
| 108 | * @see #getCheckboxGroup() | ||
| 109 | * @see #setCheckboxGroup(CheckboxGroup) | ||
| 110 | */ | ||
| 111 | CheckboxGroup group; | ||
| 112 | |||
| 113 | transient ItemListener itemListener; | ||
| 114 | |||
| 115 | private static final String base = "checkbox"; | ||
| 116 | private static int nameCounter = 0; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * JDK 1.1 serialVersionUID | ||
| 120 | */ | ||
| 121 | private static final long serialVersionUID = 7270714317450821763L; | ||
| 122 | |||
| 123 | /** | ||
| 124 | * Helper function for setState and CheckboxGroup.setSelectedCheckbox | ||
| 125 | * Should remain package-private. | ||
| 126 | */ | ||
| 127 | void setStateInternal(boolean state) { | ||
| 128 | this.state = state; | ||
| 129 | CheckboxPeer peer = (CheckboxPeer)this.peer; | ||
| 130 | if (peer != null) { | ||
| 131 | peer.setState(state); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Creates a check box with an empty string for its label. | ||
| 137 | * The state of this check box is set to "off," and it is not | ||
| 138 | * part of any check box group. | ||
| 139 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 140 | * returns true | ||
| 141 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 142 | */ | ||
| 143 | public Checkbox() throws HeadlessException { | ||
| 144 | this("", false, null); | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | * Creates a check box with the specified label. The state | ||
| 149 | * of this check box is set to "off," and it is not part of | ||
| 150 | * any check box group. | ||
| 151 | * | ||
| 152 | * @param label a string label for this check box, | ||
| 153 | * or <code>null</code> for no label. | ||
| 154 | * @exception HeadlessException if | ||
| 155 | * <code>GraphicsEnvironment.isHeadless</code> | ||
| 156 | * returns <code>true</code> | ||
| 157 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 158 | */ | ||
| 159 | public Checkbox(String label) throws HeadlessException { | ||
| 160 | this(label, false, null); | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Creates a check box with the specified label | ||
| 165 | * and sets the specified state. | ||
| 166 | * This check box is not part of any check box group. | ||
| 167 | * | ||
| 168 | * @param label a string label for this check box, | ||
| 169 | * or <code>null</code> for no label | ||
| 170 | * @param state the initial state of this check box | ||
| 171 | * @exception HeadlessException if | ||
| 172 | * <code>GraphicsEnvironment.isHeadless</code> | ||
| 173 | * returns <code>true</code> | ||
| 174 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 175 | */ | ||
| 176 | public Checkbox(String label, boolean state) throws HeadlessException { | ||
| 177 | this(label, state, null); | ||
| 178 | } | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Constructs a Checkbox with the specified label, set to the | ||
| 182 | * specified state, and in the specified check box group. | ||
| 183 | * | ||
| 184 | * @param label a string label for this check box, | ||
| 185 | * or <code>null</code> for no label. | ||
| 186 | * @param state the initial state of this check box. | ||
| 187 | * @param group a check box group for this check box, | ||
| 188 | * or <code>null</code> for no group. | ||
| 189 | * @exception HeadlessException if | ||
| 190 | * <code>GraphicsEnvironment.isHeadless</code> | ||
| 191 | * returns <code>true</code> | ||
| 192 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 193 | * @since JDK1.1 | ||
| 194 | */ | ||
| 195 | public Checkbox(String label, boolean state, CheckboxGroup group) | ||
| 196 | throws HeadlessException { | ||
| 197 | GraphicsEnvironment.checkHeadless(); | ||
| 198 | this.label = label; | ||
| 199 | this.state = state; | ||
| 200 | this.group = group; | ||
| 201 | if (state && (group != null)) { | ||
| 202 | group.setSelectedCheckbox(this); | ||
| 203 | } | ||
| 204 | } | ||
| 205 | |||
| 206 | /** | ||
| 207 | * Creates a check box with the specified label, in the specified | ||
| 208 | * check box group, and set to the specified state. | ||
| 209 | * | ||
| 210 | * @param label a string label for this check box, | ||
| 211 | * or <code>null</code> for no label. | ||
| 212 | * @param group a check box group for this check box, | ||
| 213 | * or <code>null</code> for no group. | ||
| 214 | * @param state the initial state of this check box. | ||
| 215 | * @exception HeadlessException if | ||
| 216 | * <code>GraphicsEnvironment.isHeadless</code> | ||
| 217 | * returns <code>true</code> | ||
| 218 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 219 | * @since JDK1.1 | ||
| 220 | */ | ||
| 221 | public Checkbox(String label, CheckboxGroup group, boolean state) | ||
| 222 | throws HeadlessException { | ||
| 223 | this(label, state, group); | ||
| 224 | } | ||
| 225 | |||
| 226 | /** | ||
| 227 | * Constructs a name for this component. Called by | ||
| 228 | * <code>getName</code> when the name is <code>null</code>. | ||
| 229 | * | ||
| 230 | * @return a name for this component | ||
| 231 | */ | ||
| 232 | String constructComponentName() { | ||
| 233 | synchronized (Checkbox.class) { | ||
| 234 | return base + nameCounter++; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | /** | ||
| 239 | * Creates the peer of the Checkbox. The peer allows you to change the | ||
| 240 | * look of the Checkbox without changing its functionality. | ||
| 241 | * | ||
| 242 | * @see java.awt.Toolkit#createCheckbox(java.awt.Checkbox) | ||
| 243 | * @see java.awt.Component#getToolkit() | ||
| 244 | */ | ||
| 245 | public void addNotify() { | ||
| 246 | synchronized (getTreeLock()) { | ||
| 247 | if (peer == null) | ||
| 248 | peer = getToolkit().createCheckbox(this); | ||
| 249 | super.addNotify(); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | /** | ||
| 254 | * Gets the label of this check box. | ||
| 255 | * | ||
| 256 | * @return the label of this check box, or <code>null</code> | ||
| 257 | * if this check box has no label. | ||
| 258 | * @see #setLabel(String) | ||
| 259 | */ | ||
| 260 | public String getLabel() { | ||
| 261 | return label; | ||
| 262 | } | ||
| 263 | |||
| 264 | /** | ||
| 265 | * Sets this check box's label to be the string argument. | ||
| 266 | * | ||
| 267 | * @param label a string to set as the new label, or | ||
| 268 | * <code>null</code> for no label. | ||
| 269 | * @see #getLabel | ||
| 270 | */ | ||
| 271 | public void setLabel(String label) { | ||
| 272 | boolean testvalid = false; | ||
| 273 | |||
| 274 | synchronized (this) { | ||
| 275 | if (label != this.label && (this.label == null || | ||
| 276 | !this.label.equals(label))) { | ||
| 277 | this.label = label; | ||
| 278 | CheckboxPeer peer = (CheckboxPeer)this.peer; | ||
| 279 | if (peer != null) { | ||
| 280 | peer.setLabel(label); | ||
| 281 | } | ||
| 282 | testvalid = true; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | // This could change the preferred size of the Component. | ||
| 287 | if (testvalid) { | ||
| 288 | invalidateIfValid(); | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | /** | ||
| 293 | * Determines whether this check box is in the "on" or "off" state. | ||
| 294 | * The boolean value <code>true</code> indicates the "on" state, | ||
| 295 | * and <code>false</code> indicates the "off" state. | ||
| 296 | * | ||
| 297 | * @return the state of this check box, as a boolean value | ||
| 298 | * @see #setState | ||
| 299 | */ | ||
| 300 | public boolean getState() { | ||
| 301 | return state; | ||
| 302 | } | ||
| 303 | |||
| 304 | /** | ||
| 305 | * Sets the state of this check box to the specified state. | ||
| 306 | * The boolean value <code>true</code> indicates the "on" state, | ||
| 307 | * and <code>false</code> indicates the "off" state. | ||
| 308 | * | ||
| 309 | * <p>Note that this method should be primarily used to | ||
| 310 | * initialize the state of the checkbox. Programmatically | ||
| 311 | * setting the state of the checkbox will <i>not</i> trigger | ||
| 312 | * an <code>ItemEvent</code>. The only way to trigger an | ||
| 313 | * <code>ItemEvent</code> is by user interaction. | ||
| 314 | * | ||
| 315 | * @param state the boolean state of the check box | ||
| 316 | * @see #getState | ||
| 317 | */ | ||
| 318 | public void setState(boolean state) { | ||
| 319 | /* Cannot hold check box lock when calling group.setSelectedCheckbox. */ | ||
| 320 | CheckboxGroup group = this.group; | ||
| 321 | if (group != null) { | ||
| 322 | if (state) { | ||
| 323 | group.setSelectedCheckbox(this); | ||
| 324 | } else if (group.getSelectedCheckbox() == this) { | ||
| 325 | state = true; | ||
| 326 | } | ||
| 327 | } | ||
| 328 | setStateInternal(state); | ||
| 329 | } | ||
| 330 | |||
| 331 | /** | ||
| 332 | * Returns an array (length 1) containing the checkbox | ||
| 333 | * label or null if the checkbox is not selected. | ||
| 334 | * @see ItemSelectable | ||
| 335 | */ | ||
| 336 | public Object[] getSelectedObjects() { | ||
| 337 | if (state) { | ||
| 338 | Object[] items = new Object[1]; | ||
| 339 | items[0] = label; | ||
| 340 | return items; | ||
| 341 | } | ||
| 342 | return null; | ||
| 343 | } | ||
| 344 | |||
| 345 | /** | ||
| 346 | * Determines this check box's group. | ||
| 347 | * @return this check box's group, or <code>null</code> | ||
| 348 | * if the check box is not part of a check box group. | ||
| 349 | * @see #setCheckboxGroup(CheckboxGroup) | ||
| 350 | */ | ||
| 351 | public CheckboxGroup getCheckboxGroup() { | ||
| 352 | return group; | ||
| 353 | } | ||
| 354 | |||
| 355 | /** | ||
| 356 | * Sets this check box's group to the specified check box group. | ||
| 357 | * If this check box is already in a different check box group, | ||
| 358 | * it is first taken out of that group. | ||
| 359 | * <p> | ||
| 360 | * If the state of this check box is <code>true</code> and the new | ||
| 361 | * group already has a check box selected, this check box's state | ||
| 362 | * is changed to <code>false</code>. If the state of this check | ||
| 363 | * box is <code>true</code> and the new group has no check box | ||
| 364 | * selected, this check box becomes the selected checkbox for | ||
| 365 | * the new group and its state is <code>true</code>. | ||
| 366 | * | ||
| 367 | * @param g the new check box group, or <code>null</code> | ||
| 368 | * to remove this check box from any check box group | ||
| 369 | * @see #getCheckboxGroup | ||
| 370 | */ | ||
| 371 | public void setCheckboxGroup(CheckboxGroup g) { | ||
| 372 | CheckboxGroup oldGroup; | ||
| 373 | boolean oldState; | ||
| 374 | |||
| 375 | /* Do nothing if this check box has already belonged | ||
| 376 | * to the check box group g. | ||
| 377 | */ | ||
| 378 | if (this.group == g) { | ||
| 379 | return; | ||
| 380 | } | ||
| 381 | |||
| 382 | synchronized (this) { | ||
| 383 | oldGroup = this.group; | ||
| 384 | oldState = getState(); | ||
| 385 | |||
| 386 | this.group = g; | ||
| 387 | CheckboxPeer peer = (CheckboxPeer)this.peer; | ||
| 388 | if (peer != null) { | ||
| 389 | peer.setCheckboxGroup(g); | ||
| 390 | } | ||
| 391 | if (this.group != null && getState()) { | ||
| 392 | if (this.group.getSelectedCheckbox() != null) { | ||
| 393 | setState(false); | ||
| 394 | } else { | ||
| 395 | this.group.setSelectedCheckbox(this); | ||
| 396 | } | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | /* Locking check box below could cause deadlock with | ||
| 401 | * CheckboxGroup's setSelectedCheckbox method. | ||
| 402 | * | ||
| 403 | * Fix for 4726853 by kdm@sparc.spb.su | ||
| 404 | * Here we should check if this check box was selected | ||
| 405 | * in the previous group and set selected check box to | ||
| 406 | * null for that group if so. | ||
| 407 | */ | ||
| 408 | if (oldGroup != null && oldState) { | ||
| 409 | oldGroup.setSelectedCheckbox(null); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 413 | /** | ||
| 414 | * Adds the specified item listener to receive item events from | ||
| 415 | * this check box. Item events are sent to listeners in response | ||
| 416 | * to user input, but not in response to calls to setState(). | ||
| 417 | * If l is null, no exception is thrown and no action is performed. | ||
| 418 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 419 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 420 | * | ||
| 421 | * @param l the item listener | ||
| 422 | * @see #removeItemListener | ||
| 423 | * @see #getItemListeners | ||
| 424 | * @see #setState | ||
| 425 | * @see java.awt.event.ItemEvent | ||
| 426 | * @see java.awt.event.ItemListener | ||
| 427 | * @since JDK1.1 | ||
| 428 | */ | ||
| 429 | public synchronized void addItemListener(ItemListener l) { | ||
| 430 | if (l == null) { | ||
| 431 | return; | ||
| 432 | } | ||
| 433 | itemListener = AWTEventMulticaster.add(itemListener, l); | ||
| 434 | newEventsOnly = true; | ||
| 435 | } | ||
| 436 | |||
| 437 | /** | ||
| 438 | * Removes the specified item listener so that the item listener | ||
| 439 | * no longer receives item events from this check box. | ||
| 440 | * If l is null, no exception is thrown and no action is performed. | ||
| 441 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 442 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 443 | * | ||
| 444 | * @param l the item listener | ||
| 445 | * @see #addItemListener | ||
| 446 | * @see #getItemListeners | ||
| 447 | * @see java.awt.event.ItemEvent | ||
| 448 | * @see java.awt.event.ItemListener | ||
| 449 | * @since JDK1.1 | ||
| 450 | */ | ||
| 451 | public synchronized void removeItemListener(ItemListener l) { | ||
| 452 | if (l == null) { | ||
| 453 | return; | ||
| 454 | } | ||
| 455 | itemListener = AWTEventMulticaster.remove(itemListener, l); | ||
| 456 | } | ||
| 457 | |||
| 458 | /** | ||
| 459 | * Returns an array of all the item listeners | ||
| 460 | * registered on this checkbox. | ||
| 461 | * | ||
| 462 | * @return all of this checkbox's <code>ItemListener</code>s | ||
| 463 | * or an empty array if no item | ||
| 464 | * listeners are currently registered | ||
| 465 | * | ||
| 466 | * @see #addItemListener | ||
| 467 | * @see #removeItemListener | ||
| 468 | * @see java.awt.event.ItemEvent | ||
| 469 | * @see java.awt.event.ItemListener | ||
| 470 | * @since 1.4 | ||
| 471 | */ | ||
| 472 | public synchronized ItemListener[] getItemListeners() { | ||
| 473 | return (ItemListener[]) (getListeners(ItemListener.class)); | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * Returns an array of all the objects currently registered | ||
| 478 | * as <code><em>Foo</em>Listener</code>s | ||
| 479 | * upon this <code>Checkbox</code>. | ||
| 480 | * <code><em>Foo</em>Listener</code>s are registered using the | ||
| 481 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 482 | * | ||
| 483 | * <p> | ||
| 484 | * You can specify the <code>listenerType</code> argument | ||
| 485 | * with a class literal, such as | ||
| 486 | * <code><em>Foo</em>Listener.class</code>. | ||
| 487 | * For example, you can query a | ||
| 488 | * <code>Checkbox</code> <code>c</code> | ||
| 489 | * for its item listeners with the following code: | ||
| 490 | * | ||
| 491 | * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre> | ||
| 492 | * | ||
| 493 | * If no such listeners exist, this method returns an empty array. | ||
| 494 | * | ||
| 495 | * @param listenerType the type of listeners requested; this parameter | ||
| 496 | * should specify an interface that descends from | ||
| 497 | * <code>java.util.EventListener</code> | ||
| 498 | * @return an array of all objects registered as | ||
| 499 | * <code><em>Foo</em>Listener</code>s on this checkbox, | ||
| 500 | * or an empty array if no such | ||
| 501 | * listeners have been added | ||
| 502 | * @exception ClassCastException if <code>listenerType</code> | ||
| 503 | * doesn't specify a class or interface that implements | ||
| 504 | * <code>java.util.EventListener</code> | ||
| 505 | * | ||
| 506 | * @see #getItemListeners | ||
| 507 | * @since 1.3 | ||
| 508 | */ | ||
| 509 | public <T extends EventListener> T[] getListeners(Class<T> listenerType) { | ||
| 510 | EventListener l = null; | ||
| 511 | if (listenerType == ItemListener.class) { | ||
| 512 | l = itemListener; | ||
| 513 | } else { | ||
| 514 | return super.getListeners(listenerType); | ||
| 515 | } | ||
| 516 | return AWTEventMulticaster.getListeners(l, listenerType); | ||
| 517 | } | ||
| 518 | |||
| 519 | // REMIND: remove when filtering is done at lower level | ||
| 520 | boolean eventEnabled(AWTEvent e) { | ||
| 521 | if (e.id == ItemEvent.ITEM_STATE_CHANGED) { | ||
| 522 | if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 || | ||
| 523 | itemListener != null) { | ||
| 524 | return true; | ||
| 525 | } | ||
| 526 | return false; | ||
| 527 | } | ||
| 528 | return super.eventEnabled(e); | ||
| 529 | } | ||
| 530 | |||
| 531 | /** | ||
| 532 | * Processes events on this check box. | ||
| 533 | * If the event is an instance of <code>ItemEvent</code>, | ||
| 534 | * this method invokes the <code>processItemEvent</code> method. | ||
| 535 | * Otherwise, it calls its superclass's <code>processEvent</code> method. | ||
| 536 | * <p>Note that if the event parameter is <code>null</code> | ||
| 537 | * the behavior is unspecified and may result in an | ||
| 538 | * exception. | ||
| 539 | * | ||
| 540 | * @param e the event | ||
| 541 | * @see java.awt.event.ItemEvent | ||
| 542 | * @see #processItemEvent | ||
| 543 | * @since JDK1.1 | ||
| 544 | */ | ||
| 545 | protected void processEvent(AWTEvent e) { | ||
| 546 | if (e instanceof ItemEvent) { | ||
| 547 | processItemEvent((ItemEvent)e); | ||
| 548 | return; | ||
| 549 | } | ||
| 550 | super.processEvent(e); | ||
| 551 | } | ||
| 552 | |||
| 553 | /** | ||
| 554 | * Processes item events occurring on this check box by | ||
| 555 | * dispatching them to any registered | ||
| 556 | * <code>ItemListener</code> objects. | ||
| 557 | * <p> | ||
| 558 | * This method is not called unless item events are | ||
| 559 | * enabled for this component. Item events are enabled | ||
| 560 | * when one of the following occurs: | ||
| 561 | * <p><ul> | ||
| 562 | * <li>An <code>ItemListener</code> object is registered | ||
| 563 | * via <code>addItemListener</code>. | ||
| 564 | * <li>Item events are enabled via <code>enableEvents</code>. | ||
| 565 | * </ul> | ||
| 566 | * <p>Note that if the event parameter is <code>null</code> | ||
| 567 | * the behavior is unspecified and may result in an | ||
| 568 | * exception. | ||
| 569 | * | ||
| 570 | * @param e the item event | ||
| 571 | * @see java.awt.event.ItemEvent | ||
| 572 | * @see java.awt.event.ItemListener | ||
| 573 | * @see #addItemListener | ||
| 574 | * @see java.awt.Component#enableEvents | ||
| 575 | * @since JDK1.1 | ||
| 576 | */ | ||
| 577 | protected void processItemEvent(ItemEvent e) { | ||
| 578 | ItemListener listener = itemListener; | ||
| 579 | if (listener != null) { | ||
| 580 | listener.itemStateChanged(e); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | /** | ||
| 585 | * Returns a string representing the state of this <code>Checkbox</code>. | ||
| 586 | * This method is intended to be used only for debugging purposes, and the | ||
| 587 | * content and format of the returned string may vary between | ||
| 588 | * implementations. The returned string may be empty but may not be | ||
| 589 | * <code>null</code>. | ||
| 590 | * | ||
| 591 | * @return the parameter string of this check box | ||
| 592 | */ | ||
| 593 | protected String paramString() { | ||
| 594 | String str = super.paramString(); | ||
| 595 | String label = this.label; | ||
| 596 | if (label != null) { | ||
| 597 | str += ",label=" + label; | ||
| 598 | } | ||
| 599 | return str + ",state=" + state; | ||
| 600 | } | ||
| 601 | |||
| 602 | |||
| 603 | /* Serialization support. | ||
| 604 | */ | ||
| 605 | |||
| 606 | /* | ||
| 607 | * Serialized data version | ||
| 608 | * @serial | ||
| 609 | */ | ||
| 610 | private int checkboxSerializedDataVersion = 1; | ||
| 611 | |||
| 612 | /** | ||
| 613 | * Writes default serializable fields to stream. Writes | ||
| 614 | * a list of serializable <code>ItemListeners</code> | ||
| 615 | * as optional data. The non-serializable | ||
| 616 | * <code>ItemListeners</code> are detected and | ||
| 617 | * no attempt is made to serialize them. | ||
| 618 | * | ||
| 619 | * @param s the <code>ObjectOutputStream</code> to write | ||
| 620 | * @serialData <code>null</code> terminated sequence of 0 | ||
| 621 | * or more pairs; the pair consists of a <code>String</code> | ||
| 622 | * and an <code>Object</code>; the <code>String</code> indicates | ||
| 623 | * the type of object and is one of the following: | ||
| 624 | * <code>itemListenerK</code> indicating an | ||
| 625 | * <code>ItemListener</code> object | ||
| 626 | * | ||
| 627 | * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) | ||
| 628 | * @see java.awt.Component#itemListenerK | ||
| 629 | * @see #readObject(ObjectInputStream) | ||
| 630 | */ | ||
| 631 | private void writeObject(ObjectOutputStream s) | ||
| 632 | throws java.io.IOException | ||
| 633 | { | ||
| 634 | s.defaultWriteObject(); | ||
| 635 | |||
| 636 | AWTEventMulticaster.save(s, itemListenerK, itemListener); | ||
| 637 | s.writeObject(null); | ||
| 638 | } | ||
| 639 | |||
| 640 | /** | ||
| 641 | * Reads the <code>ObjectInputStream</code> and if it | ||
| 642 | * isn't <code>null</code> adds a listener to receive | ||
| 643 | * item events fired by the <code>Checkbox</code>. | ||
| 644 | * Unrecognized keys or values will be ignored. | ||
| 645 | * | ||
| 646 | * @param s the <code>ObjectInputStream</code> to read | ||
| 647 | * @exception HeadlessException if | ||
| 648 | * <code>GraphicsEnvironment.isHeadless</code> returns | ||
| 649 | * <code>true</code> | ||
| 650 | * @serial | ||
| 651 | * @see #removeItemListener(ItemListener) | ||
| 652 | * @see #addItemListener(ItemListener) | ||
| 653 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 654 | * @see #writeObject(ObjectOutputStream) | ||
| 655 | */ | ||
| 656 | private void readObject(ObjectInputStream s) | ||
| 657 | throws ClassNotFoundException, IOException, HeadlessException | ||
| 658 | { | ||
| 659 | GraphicsEnvironment.checkHeadless(); | ||
| 660 | s.defaultReadObject(); | ||
| 661 | |||
| 662 | Object keyOrNull; | ||
| 663 | while(null != (keyOrNull = s.readObject())) { | ||
| 664 | String key = ((String)keyOrNull).intern(); | ||
| 665 | |||
| 666 | if (itemListenerK == key) | ||
| 667 | addItemListener((ItemListener)(s.readObject())); | ||
| 668 | |||
| 669 | else // skip value for unrecognized key | ||
| 670 | s.readObject(); | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | /** | ||
| 675 | * Initialize JNI field and method ids | ||
| 676 | */ | ||
| 677 | private static native void initIDs(); | ||
| 678 | |||
| 679 | |||
| 680 | ///////////////// | ||
| 681 | // Accessibility support | ||
| 682 | //////////////// | ||
| 683 | |||
| 684 | |||
| 685 | /** | ||
| 686 | * Gets the AccessibleContext associated with this Checkbox. | ||
| 687 | * For checkboxes, the AccessibleContext takes the form of an | ||
| 688 | * AccessibleAWTCheckbox. | ||
| 689 | * A new AccessibleAWTCheckbox is created if necessary. | ||
| 690 | * | ||
| 691 | * @return an AccessibleAWTCheckbox that serves as the | ||
| 692 | * AccessibleContext of this Checkbox | ||
| 693 | * @since 1.3 | ||
| 694 | */ | ||
| 695 | public AccessibleContext getAccessibleContext() { | ||
| 696 | if (accessibleContext == null) { | ||
| 697 | accessibleContext = new AccessibleAWTCheckbox(); | ||
| 698 | } | ||
| 699 | return accessibleContext; | ||
| 700 | } | ||
| 701 | |||
| 702 | /** | ||
| 703 | * This class implements accessibility support for the | ||
| 704 | * <code>Checkbox</code> class. It provides an implementation of the | ||
| 705 | * Java Accessibility API appropriate to checkbox user-interface elements. | ||
| 706 | * @since 1.3 | ||
| 707 | */ | ||
| 708 | protected class AccessibleAWTCheckbox extends AccessibleAWTComponent | ||
| 709 | implements ItemListener, AccessibleAction, AccessibleValue | ||
| 710 | { | ||
| 711 | /* | ||
| 712 | * JDK 1.3 serialVersionUID | ||
| 713 | */ | ||
| 714 | private static final long serialVersionUID = 7881579233144754107L; | ||
| 715 | |||
| 716 | public AccessibleAWTCheckbox() { | ||
| 717 | super(); | ||
| 718 | Checkbox.this.addItemListener(this); | ||
| 719 | } | ||
| 720 | |||
| 721 | /** | ||
| 722 | * Fire accessible property change events when the state of the | ||
| 723 | * toggle button changes. | ||
| 724 | */ | ||
| 725 | public void itemStateChanged(ItemEvent e) { | ||
| 726 | Checkbox cb = (Checkbox) e.getSource(); | ||
| 727 | if (Checkbox.this.accessibleContext != null) { | ||
| 728 | if (cb.getState()) { | ||
| 729 | Checkbox.this.accessibleContext.firePropertyChange( | ||
| 730 | AccessibleContext.ACCESSIBLE_STATE_PROPERTY, | ||
| 731 | null, AccessibleState.CHECKED); | ||
| 732 | } else { | ||
| 733 | Checkbox.this.accessibleContext.firePropertyChange( | ||
| 734 | AccessibleContext.ACCESSIBLE_STATE_PROPERTY, | ||
| 735 | AccessibleState.CHECKED, null); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | } | ||
| 739 | |||
| 740 | /** | ||
| 741 | * Get the AccessibleAction associated with this object. In the | ||
| 742 | * implementation of the Java Accessibility API for this class, | ||
| 743 | * return this object, which is responsible for implementing the | ||
| 744 | * AccessibleAction interface on behalf of itself. | ||
| 745 | * | ||
| 746 | * @return this object | ||
| 747 | */ | ||
| 748 | public AccessibleAction getAccessibleAction() { | ||
| 749 | return this; | ||
| 750 | } | ||
| 751 | |||
| 752 | /** | ||
| 753 | * Get the AccessibleValue associated with this object. In the | ||
| 754 | * implementation of the Java Accessibility API for this class, | ||
| 755 | * return this object, which is responsible for implementing the | ||
| 756 | * AccessibleValue interface on behalf of itself. | ||
| 757 | * | ||
| 758 | * @return this object | ||
| 759 | */ | ||
| 760 | public AccessibleValue getAccessibleValue() { | ||
| 761 | return this; | ||
| 762 | } | ||
| 763 | |||
| 764 | /** | ||
| 765 | * Returns the number of Actions available in this object. | ||
| 766 | * If there is more than one, the first one is the "default" | ||
| 767 | * action. | ||
| 768 | * | ||
| 769 | * @return the number of Actions in this object | ||
| 770 | */ | ||
| 771 | public int getAccessibleActionCount() { | ||
| 772 | return 0; // To be fully implemented in a future release | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * Return a description of the specified action of the object. | ||
| 777 | * | ||
| 778 | * @param i zero-based index of the actions | ||
| 779 | */ | ||
| 780 | public String getAccessibleActionDescription(int i) { | ||
| 781 | return null; // To be fully implemented in a future release | ||
| 782 | } | ||
| 783 | |||
| 784 | /** | ||
| 785 | * Perform the specified Action on the object | ||
| 786 | * | ||
| 787 | * @param i zero-based index of actions | ||
| 788 | * @return true if the the action was performed; else false. | ||
| 789 | */ | ||
| 790 | public boolean doAccessibleAction(int i) { | ||
| 791 | return false; // To be fully implemented in a future release | ||
| 792 | } | ||
| 793 | |||
| 794 | /** | ||
| 795 | * Get the value of this object as a Number. If the value has not been | ||
| 796 | * set, the return value will be null. | ||
| 797 | * | ||
| 798 | * @return value of the object | ||
| 799 | * @see #setCurrentAccessibleValue | ||
| 800 | */ | ||
| 801 | public Number getCurrentAccessibleValue() { | ||
| 802 | return null; // To be fully implemented in a future release | ||
| 803 | } | ||
| 804 | |||
| 805 | /** | ||
| 806 | * Set the value of this object as a Number. | ||
| 807 | * | ||
| 808 | * @return True if the value was set; else False | ||
| 809 | * @see #getCurrentAccessibleValue | ||
| 810 | */ | ||
| 811 | public boolean setCurrentAccessibleValue(Number n) { | ||
| 812 | return false; // To be fully implemented in a future release | ||
| 813 | } | ||
| 814 | |||
| 815 | /** | ||
| 816 | * Get the minimum value of this object as a Number. | ||
| 817 | * | ||
| 818 | * @return Minimum value of the object; null if this object does not | ||
| 819 | * have a minimum value | ||
| 820 | * @see #getMaximumAccessibleValue | ||
| 821 | */ | ||
| 822 | public Number getMinimumAccessibleValue() { | ||
| 823 | return null; // To be fully implemented in a future release | ||
| 824 | } | ||
| 825 | |||
| 826 | /** | ||
| 827 | * Get the maximum value of this object as a Number. | ||
| 828 | * | ||
| 829 | * @return Maximum value of the object; null if this object does not | ||
| 830 | * have a maximum value | ||
| 831 | * @see #getMinimumAccessibleValue | ||
| 832 | */ | ||
| 833 | public Number getMaximumAccessibleValue() { | ||
| 834 | return null; // To be fully implemented in a future release | ||
| 835 | } | ||
| 836 | |||
| 837 | /** | ||
| 838 | * Get the role of this object. | ||
| 839 | * | ||
| 840 | * @return an instance of AccessibleRole describing the role of | ||
| 841 | * the object | ||
| 842 | * @see AccessibleRole | ||
| 843 | */ | ||
| 844 | public AccessibleRole getAccessibleRole() { | ||
| 845 | return AccessibleRole.CHECK_BOX; | ||
| 846 | } | ||
| 847 | |||
| 848 | /** | ||
| 849 | * Get the state set of this object. | ||
| 850 | * | ||
| 851 | * @return an instance of AccessibleState containing the current state | ||
| 852 | * of the object | ||
| 853 | * @see AccessibleState | ||
| 854 | */ | ||
| 855 | public AccessibleStateSet getAccessibleStateSet() { | ||
| 856 | AccessibleStateSet states = super.getAccessibleStateSet(); | ||
| 857 | if (getState()) { | ||
| 858 | states.add(AccessibleState.CHECKED); | ||
| 859 | } | ||
| 860 | return states; | ||
| 861 | } | ||
| 862 | |||
| 863 | |||
| 864 | } // inner class AccessibleAWTCheckbox | ||
| 865 | |||
| 866 | } | ||
Binary file not shown.
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2004, 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 | package java.awt; | ||
| 26 | |||
| 27 | /** | ||
| 28 | * The <code>CheckboxGroup</code> class is used to group together | ||
| 29 | * a set of <code>Checkbox</code> buttons. | ||
| 30 | * <p> | ||
| 31 | * Exactly one check box button in a <code>CheckboxGroup</code> can | ||
| 32 | * be in the "on" state at any given time. Pushing any | ||
| 33 | * button sets its state to "on" and forces any other button that | ||
| 34 | * is in the "on" state into the "off" state. | ||
| 35 | * <p> | ||
| 36 | * The following code example produces a new check box group, | ||
| 37 | * with three check boxes: | ||
| 38 | * <p> | ||
| 39 | * <hr><blockquote><pre> | ||
| 40 | * setLayout(new GridLayout(3, 1)); | ||
| 41 | * CheckboxGroup cbg = new CheckboxGroup(); | ||
| 42 | * add(new Checkbox("one", cbg, true)); | ||
| 43 | * add(new Checkbox("two", cbg, false)); | ||
| 44 | * add(new Checkbox("three", cbg, false)); | ||
| 45 | * </pre></blockquote><hr> | ||
| 46 | * <p> | ||
| 47 | * This image depicts the check box group created by this example: | ||
| 48 | * <p> | ||
| 49 | * <img src="doc-files/CheckboxGroup-1.gif" | ||
| 50 | * alt="Shows three checkboxes, arranged vertically, labeled one, two, and three. Checkbox one is in the on state." | ||
| 51 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 52 | * <p> | ||
| 53 | * @author Sami Shaio | ||
| 54 | * @see java.awt.Checkbox | ||
| 55 | * @since JDK1.0 | ||
| 56 | */ | ||
| 57 | public class CheckboxGroup implements java.io.Serializable { | ||
| 58 | /** | ||
| 59 | * The current choice. | ||
| 60 | * @serial | ||
| 61 | * @see #getCurrent() | ||
| 62 | * @see #setCurrent(Checkbox) | ||
| 63 | */ | ||
| 64 | Checkbox selectedCheckbox = null; | ||
| 65 | |||
| 66 | /* | ||
| 67 | * JDK 1.1 serialVersionUID | ||
| 68 | */ | ||
| 69 | private static final long serialVersionUID = 3729780091441768983L; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Creates a new instance of <code>CheckboxGroup</code>. | ||
| 73 | */ | ||
| 74 | public CheckboxGroup() { | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Gets the current choice from this check box group. | ||
| 79 | * The current choice is the check box in this | ||
| 80 | * group that is currently in the "on" state, | ||
| 81 | * or <code>null</code> if all check boxes in the | ||
| 82 | * group are off. | ||
| 83 | * @return the check box that is currently in the | ||
| 84 | * "on" state, or <code>null</code>. | ||
| 85 | * @see java.awt.Checkbox | ||
| 86 | * @see java.awt.CheckboxGroup#setSelectedCheckbox | ||
| 87 | * @since JDK1.1 | ||
| 88 | */ | ||
| 89 | public Checkbox getSelectedCheckbox() { | ||
| 90 | return getCurrent(); | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * @deprecated As of JDK version 1.1, | ||
| 95 | * replaced by <code>getSelectedCheckbox()</code>. | ||
| 96 | */ | ||
| 97 | @Deprecated | ||
| 98 | public Checkbox getCurrent() { | ||
| 99 | return selectedCheckbox; | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * Sets the currently selected check box in this group | ||
| 104 | * to be the specified check box. | ||
| 105 | * This method sets the state of that check box to "on" and | ||
| 106 | * sets all other check boxes in the group to be off. | ||
| 107 | * <p> | ||
| 108 | * If the check box argument is <tt>null</tt>, all check boxes | ||
| 109 | * in this check box group are deselected. If the check box argument | ||
| 110 | * belongs to a different check box group, this method does | ||
| 111 | * nothing. | ||
| 112 | * @param box the <code>Checkbox</code> to set as the | ||
| 113 | * current selection. | ||
| 114 | * @see java.awt.Checkbox | ||
| 115 | * @see java.awt.CheckboxGroup#getSelectedCheckbox | ||
| 116 | * @since JDK1.1 | ||
| 117 | */ | ||
| 118 | public void setSelectedCheckbox(Checkbox box) { | ||
| 119 | setCurrent(box); | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * @deprecated As of JDK version 1.1, | ||
| 124 | * replaced by <code>setSelectedCheckbox(Checkbox)</code>. | ||
| 125 | */ | ||
| 126 | @Deprecated | ||
| 127 | public synchronized void setCurrent(Checkbox box) { | ||
| 128 | if (box != null && box.group != this) { | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | Checkbox oldChoice = this.selectedCheckbox; | ||
| 132 | this.selectedCheckbox = box; | ||
| 133 | if (oldChoice != null && oldChoice != box && oldChoice.group == this) { | ||
| 134 | oldChoice.setState(false); | ||
| 135 | } | ||
| 136 | if (box != null && oldChoice != box && !box.getState()) { | ||
| 137 | box.setStateInternal(true); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Returns a string representation of this check box group, | ||
| 143 | * including the value of its current selection. | ||
| 144 | * @return a string representation of this check box group. | ||
| 145 | */ | ||
| 146 | public String toString() { | ||
| 147 | return getClass().getName() + "[selectedCheckbox=" + selectedCheckbox + "]"; | ||
| 148 | } | ||
| 149 | |||
| 150 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,633 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2006, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.peer.CheckboxMenuItemPeer; | ||
| 28 | import java.awt.event.*; | ||
| 29 | import java.util.EventListener; | ||
| 30 | import java.io.ObjectOutputStream; | ||
| 31 | import java.io.ObjectInputStream; | ||
| 32 | import java.io.IOException; | ||
| 33 | import javax.accessibility.*; | ||
| 34 | |||
| 35 | |||
| 36 | /** | ||
| 37 | * This class represents a check box that can be included in a menu. | ||
| 38 | * Selecting the check box in the menu changes its state from | ||
| 39 | * "on" to "off" or from "off" to "on." | ||
| 40 | * <p> | ||
| 41 | * The following picture depicts a menu which contains an instance | ||
| 42 | * of <code>CheckBoxMenuItem</code>: | ||
| 43 | * <p> | ||
| 44 | * <img src="doc-files/MenuBar-1.gif" | ||
| 45 | * alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state." | ||
| 46 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 47 | * <p> | ||
| 48 | * The item labeled <code>Check</code> shows a check box menu item | ||
| 49 | * in its "off" state. | ||
| 50 | * <p> | ||
| 51 | * When a check box menu item is selected, AWT sends an item event to | ||
| 52 | * the item. Since the event is an instance of <code>ItemEvent</code>, | ||
| 53 | * the <code>processEvent</code> method examines the event and passes | ||
| 54 | * it along to <code>processItemEvent</code>. The latter method redirects | ||
| 55 | * the event to any <code>ItemListener</code> objects that have | ||
| 56 | * registered an interest in item events generated by this menu item. | ||
| 57 | * | ||
| 58 | * @author Sami Shaio | ||
| 59 | * @see java.awt.event.ItemEvent | ||
| 60 | * @see java.awt.event.ItemListener | ||
| 61 | * @since JDK1.0 | ||
| 62 | */ | ||
| 63 | public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Accessible { | ||
| 64 | |||
| 65 | static { | ||
| 66 | /* ensure that the necessary native libraries are loaded */ | ||
| 67 | Toolkit.loadLibraries(); | ||
| 68 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 69 | initIDs(); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * The state of a checkbox menu item | ||
| 75 | * @serial | ||
| 76 | * @see #getState() | ||
| 77 | * @see #setState(boolean) | ||
| 78 | */ | ||
| 79 | boolean state = false; | ||
| 80 | |||
| 81 | transient ItemListener itemListener; | ||
| 82 | |||
| 83 | private static final String base = "chkmenuitem"; | ||
| 84 | private static int nameCounter = 0; | ||
| 85 | |||
| 86 | /* | ||
| 87 | * JDK 1.1 serialVersionUID | ||
| 88 | */ | ||
| 89 | private static final long serialVersionUID = 6190621106981774043L; | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Create a check box menu item with an empty label. | ||
| 93 | * The item's state is initially set to "off." | ||
| 94 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 95 | * returns true | ||
| 96 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 97 | * @since JDK1.1 | ||
| 98 | */ | ||
| 99 | public CheckboxMenuItem() throws HeadlessException { | ||
| 100 | this("", false); | ||
| 101 | } | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Create a check box menu item with the specified label. | ||
| 105 | * The item's state is initially set to "off." | ||
| 106 | |||
| 107 | * @param label a string label for the check box menu item, | ||
| 108 | * or <code>null</code> for an unlabeled menu item. | ||
| 109 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 110 | * returns true | ||
| 111 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 112 | */ | ||
| 113 | public CheckboxMenuItem(String label) throws HeadlessException { | ||
| 114 | this(label, false); | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Create a check box menu item with the specified label and state. | ||
| 119 | * @param label a string label for the check box menu item, | ||
| 120 | * or <code>null</code> for an unlabeled menu item. | ||
| 121 | * @param state the initial state of the menu item, where | ||
| 122 | * <code>true</code> indicates "on" and | ||
| 123 | * <code>false</code> indicates "off." | ||
| 124 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 125 | * returns true | ||
| 126 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 127 | * @since JDK1.1 | ||
| 128 | */ | ||
| 129 | public CheckboxMenuItem(String label, boolean state) | ||
| 130 | throws HeadlessException { | ||
| 131 | super(label); | ||
| 132 | this.state = state; | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Construct a name for this MenuComponent. Called by getName() when | ||
| 137 | * the name is null. | ||
| 138 | */ | ||
| 139 | String constructComponentName() { | ||
| 140 | synchronized (CheckboxMenuItem.class) { | ||
| 141 | return base + nameCounter++; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Creates the peer of the checkbox item. This peer allows us to | ||
| 147 | * change the look of the checkbox item without changing its | ||
| 148 | * functionality. | ||
| 149 | * Most applications do not call this method directly. | ||
| 150 | * @see java.awt.Toolkit#createCheckboxMenuItem(java.awt.CheckboxMenuItem) | ||
| 151 | * @see java.awt.Component#getToolkit() | ||
| 152 | */ | ||
| 153 | public void addNotify() { | ||
| 154 | synchronized (getTreeLock()) { | ||
| 155 | if (peer == null) | ||
| 156 | peer = Toolkit.getDefaultToolkit().createCheckboxMenuItem(this); | ||
| 157 | super.addNotify(); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Determines whether the state of this check box menu item | ||
| 163 | * is "on" or "off." | ||
| 164 | * | ||
| 165 | * @return the state of this check box menu item, where | ||
| 166 | * <code>true</code> indicates "on" and | ||
| 167 | * <code>false</code> indicates "off" | ||
| 168 | * @see #setState | ||
| 169 | */ | ||
| 170 | public boolean getState() { | ||
| 171 | return state; | ||
| 172 | } | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Sets this check box menu item to the specifed state. | ||
| 176 | * The boolean value <code>true</code> indicates "on" while | ||
| 177 | * <code>false</code> indicates "off." | ||
| 178 | * | ||
| 179 | * <p>Note that this method should be primarily used to | ||
| 180 | * initialize the state of the check box menu item. | ||
| 181 | * Programmatically setting the state of the check box | ||
| 182 | * menu item will <i>not</i> trigger | ||
| 183 | * an <code>ItemEvent</code>. The only way to trigger an | ||
| 184 | * <code>ItemEvent</code> is by user interaction. | ||
| 185 | * | ||
| 186 | * @param b <code>true</code> if the check box | ||
| 187 | * menu item is on, otherwise <code>false</code> | ||
| 188 | * @see #getState | ||
| 189 | */ | ||
| 190 | public synchronized void setState(boolean b) { | ||
| 191 | state = b; | ||
| 192 | CheckboxMenuItemPeer peer = (CheckboxMenuItemPeer)this.peer; | ||
| 193 | if (peer != null) { | ||
| 194 | peer.setState(b); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | /** | ||
| 199 | * Returns the an array (length 1) containing the checkbox menu item | ||
| 200 | * label or null if the checkbox is not selected. | ||
| 201 | * @see ItemSelectable | ||
| 202 | */ | ||
| 203 | public synchronized Object[] getSelectedObjects() { | ||
| 204 | if (state) { | ||
| 205 | Object[] items = new Object[1]; | ||
| 206 | items[0] = label; | ||
| 207 | return items; | ||
| 208 | } | ||
| 209 | return null; | ||
| 210 | } | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Adds the specified item listener to receive item events from | ||
| 214 | * this check box menu item. Item events are sent in response to user | ||
| 215 | * actions, but not in response to calls to setState(). | ||
| 216 | * If l is null, no exception is thrown and no action is performed. | ||
| 217 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 218 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 219 | * | ||
| 220 | * @param l the item listener | ||
| 221 | * @see #removeItemListener | ||
| 222 | * @see #getItemListeners | ||
| 223 | * @see #setState | ||
| 224 | * @see java.awt.event.ItemEvent | ||
| 225 | * @see java.awt.event.ItemListener | ||
| 226 | * @since JDK1.1 | ||
| 227 | */ | ||
| 228 | public synchronized void addItemListener(ItemListener l) { | ||
| 229 | if (l == null) { | ||
| 230 | return; | ||
| 231 | } | ||
| 232 | itemListener = AWTEventMulticaster.add(itemListener, l); | ||
| 233 | newEventsOnly = true; | ||
| 234 | } | ||
| 235 | |||
| 236 | /** | ||
| 237 | * Removes the specified item listener so that it no longer receives | ||
| 238 | * item events from this check box menu item. | ||
| 239 | * If l is null, no exception is thrown and no action is performed. | ||
| 240 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 241 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 242 | * | ||
| 243 | * @param l the item listener | ||
| 244 | * @see #addItemListener | ||
| 245 | * @see #getItemListeners | ||
| 246 | * @see java.awt.event.ItemEvent | ||
| 247 | * @see java.awt.event.ItemListener | ||
| 248 | * @since JDK1.1 | ||
| 249 | */ | ||
| 250 | public synchronized void removeItemListener(ItemListener l) { | ||
| 251 | if (l == null) { | ||
| 252 | return; | ||
| 253 | } | ||
| 254 | itemListener = AWTEventMulticaster.remove(itemListener, l); | ||
| 255 | } | ||
| 256 | |||
| 257 | /** | ||
| 258 | * Returns an array of all the item listeners | ||
| 259 | * registered on this checkbox menuitem. | ||
| 260 | * | ||
| 261 | * @return all of this checkbox menuitem's <code>ItemListener</code>s | ||
| 262 | * or an empty array if no item | ||
| 263 | * listeners are currently registered | ||
| 264 | * | ||
| 265 | * @see #addItemListener | ||
| 266 | * @see #removeItemListener | ||
| 267 | * @see java.awt.event.ItemEvent | ||
| 268 | * @see java.awt.event.ItemListener | ||
| 269 | * @since 1.4 | ||
| 270 | */ | ||
| 271 | public synchronized ItemListener[] getItemListeners() { | ||
| 272 | return (ItemListener[])(getListeners(ItemListener.class)); | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * Returns an array of all the objects currently registered | ||
| 277 | * as <code><em>Foo</em>Listener</code>s | ||
| 278 | * upon this <code>CheckboxMenuItem</code>. | ||
| 279 | * <code><em>Foo</em>Listener</code>s are registered using the | ||
| 280 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 281 | * | ||
| 282 | * <p> | ||
| 283 | * You can specify the <code>listenerType</code> argument | ||
| 284 | * with a class literal, such as | ||
| 285 | * <code><em>Foo</em>Listener.class</code>. | ||
| 286 | * For example, you can query a | ||
| 287 | * <code>CheckboxMenuItem</code> <code>c</code> | ||
| 288 | * for its item listeners with the following code: | ||
| 289 | * | ||
| 290 | * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre> | ||
| 291 | * | ||
| 292 | * If no such listeners exist, this method returns an empty array. | ||
| 293 | * | ||
| 294 | * @param listenerType the type of listeners requested; this parameter | ||
| 295 | * should specify an interface that descends from | ||
| 296 | * <code>java.util.EventListener</code> | ||
| 297 | * @return an array of all objects registered as | ||
| 298 | * <code><em>Foo</em>Listener</code>s on this checkbox menuitem, | ||
| 299 | * or an empty array if no such | ||
| 300 | * listeners have been added | ||
| 301 | * @exception ClassCastException if <code>listenerType</code> | ||
| 302 | * doesn't specify a class or interface that implements | ||
| 303 | * <code>java.util.EventListener</code> | ||
| 304 | * | ||
| 305 | * @see #getItemListeners | ||
| 306 | * @since 1.3 | ||
| 307 | */ | ||
| 308 | public <T extends EventListener> T[] getListeners(Class<T> listenerType) { | ||
| 309 | EventListener l = null; | ||
| 310 | if (listenerType == ItemListener.class) { | ||
| 311 | l = itemListener; | ||
| 312 | } else { | ||
| 313 | return super.getListeners(listenerType); | ||
| 314 | } | ||
| 315 | return AWTEventMulticaster.getListeners(l, listenerType); | ||
| 316 | } | ||
| 317 | |||
| 318 | // REMIND: remove when filtering is done at lower level | ||
| 319 | boolean eventEnabled(AWTEvent e) { | ||
| 320 | if (e.id == ItemEvent.ITEM_STATE_CHANGED) { | ||
| 321 | if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 || | ||
| 322 | itemListener != null) { | ||
| 323 | return true; | ||
| 324 | } | ||
| 325 | return false; | ||
| 326 | } | ||
| 327 | return super.eventEnabled(e); | ||
| 328 | } | ||
| 329 | |||
| 330 | /** | ||
| 331 | * Processes events on this check box menu item. | ||
| 332 | * If the event is an instance of <code>ItemEvent</code>, | ||
| 333 | * this method invokes the <code>processItemEvent</code> method. | ||
| 334 | * If the event is not an item event, | ||
| 335 | * it invokes <code>processEvent</code> on the superclass. | ||
| 336 | * <p> | ||
| 337 | * Check box menu items currently support only item events. | ||
| 338 | * <p>Note that if the event parameter is <code>null</code> | ||
| 339 | * the behavior is unspecified and may result in an | ||
| 340 | * exception. | ||
| 341 | * | ||
| 342 | * @param e the event | ||
| 343 | * @see java.awt.event.ItemEvent | ||
| 344 | * @see #processItemEvent | ||
| 345 | * @since JDK1.1 | ||
| 346 | */ | ||
| 347 | protected void processEvent(AWTEvent e) { | ||
| 348 | if (e instanceof ItemEvent) { | ||
| 349 | processItemEvent((ItemEvent)e); | ||
| 350 | return; | ||
| 351 | } | ||
| 352 | super.processEvent(e); | ||
| 353 | } | ||
| 354 | |||
| 355 | /** | ||
| 356 | * Processes item events occurring on this check box menu item by | ||
| 357 | * dispatching them to any registered <code>ItemListener</code> objects. | ||
| 358 | * <p> | ||
| 359 | * This method is not called unless item events are | ||
| 360 | * enabled for this menu item. Item events are enabled | ||
| 361 | * when one of the following occurs: | ||
| 362 | * <p><ul> | ||
| 363 | * <li>An <code>ItemListener</code> object is registered | ||
| 364 | * via <code>addItemListener</code>. | ||
| 365 | * <li>Item events are enabled via <code>enableEvents</code>. | ||
| 366 | * </ul> | ||
| 367 | * <p>Note that if the event parameter is <code>null</code> | ||
| 368 | * the behavior is unspecified and may result in an | ||
| 369 | * exception. | ||
| 370 | * | ||
| 371 | * @param e the item event | ||
| 372 | * @see java.awt.event.ItemEvent | ||
| 373 | * @see java.awt.event.ItemListener | ||
| 374 | * @see #addItemListener | ||
| 375 | * @see java.awt.MenuItem#enableEvents | ||
| 376 | * @since JDK1.1 | ||
| 377 | */ | ||
| 378 | protected void processItemEvent(ItemEvent e) { | ||
| 379 | ItemListener listener = itemListener; | ||
| 380 | if (listener != null) { | ||
| 381 | listener.itemStateChanged(e); | ||
| 382 | } | ||
| 383 | } | ||
| 384 | |||
| 385 | /* | ||
| 386 | * Post an ItemEvent and toggle state. | ||
| 387 | */ | ||
| 388 | void doMenuEvent(long when, int modifiers) { | ||
| 389 | setState(!state); | ||
| 390 | Toolkit.getEventQueue().postEvent( | ||
| 391 | new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, | ||
| 392 | getLabel(), | ||
| 393 | state ? ItemEvent.SELECTED : | ||
| 394 | ItemEvent.DESELECTED)); | ||
| 395 | } | ||
| 396 | |||
| 397 | /** | ||
| 398 | * Returns a string representing the state of this | ||
| 399 | * <code>CheckBoxMenuItem</code>. This | ||
| 400 | * method is intended to be used only for debugging purposes, and the | ||
| 401 | * content and format of the returned string may vary between | ||
| 402 | * implementations. The returned string may be empty but may not be | ||
| 403 | * <code>null</code>. | ||
| 404 | * | ||
| 405 | * @return the parameter string of this check box menu item | ||
| 406 | */ | ||
| 407 | public String paramString() { | ||
| 408 | return super.paramString() + ",state=" + state; | ||
| 409 | } | ||
| 410 | |||
| 411 | /* Serialization support. | ||
| 412 | */ | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Serial Data Version | ||
| 416 | * @serial | ||
| 417 | */ | ||
| 418 | private int checkboxMenuItemSerializedDataVersion = 1; | ||
| 419 | |||
| 420 | /** | ||
| 421 | * Writes default serializable fields to stream. Writes | ||
| 422 | * a list of serializable <code>ItemListeners</code> | ||
| 423 | * as optional data. The non-serializable | ||
| 424 | * <code>ItemListeners</code> are detected and | ||
| 425 | * no attempt is made to serialize them. | ||
| 426 | * | ||
| 427 | * @param s the <code>ObjectOutputStream</code> to write | ||
| 428 | * @serialData <code>null</code> terminated sequence of | ||
| 429 | * 0 or more pairs; the pair consists of a <code>String</code> | ||
| 430 | * and an <code>Object</code>; the <code>String</code> indicates | ||
| 431 | * the type of object and is one of the following: | ||
| 432 | * <code>itemListenerK</code> indicating an | ||
| 433 | * <code>ItemListener</code> object | ||
| 434 | * | ||
| 435 | * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) | ||
| 436 | * @see java.awt.Component#itemListenerK | ||
| 437 | * @see #readObject(ObjectInputStream) | ||
| 438 | */ | ||
| 439 | private void writeObject(ObjectOutputStream s) | ||
| 440 | throws java.io.IOException | ||
| 441 | { | ||
| 442 | s.defaultWriteObject(); | ||
| 443 | |||
| 444 | AWTEventMulticaster.save(s, itemListenerK, itemListener); | ||
| 445 | s.writeObject(null); | ||
| 446 | } | ||
| 447 | |||
| 448 | /* | ||
| 449 | * Reads the <code>ObjectInputStream</code> and if it | ||
| 450 | * isn't <code>null</code> adds a listener to receive | ||
| 451 | * item events fired by the <code>Checkbox</code> menu item. | ||
| 452 | * Unrecognized keys or values will be ignored. | ||
| 453 | * | ||
| 454 | * @param s the <code>ObjectInputStream</code> to read | ||
| 455 | * @serial | ||
| 456 | * @see removeActionListener() | ||
| 457 | * @see addActionListener() | ||
| 458 | * @see #writeObject | ||
| 459 | */ | ||
| 460 | private void readObject(ObjectInputStream s) | ||
| 461 | throws ClassNotFoundException, IOException | ||
| 462 | { | ||
| 463 | s.defaultReadObject(); | ||
| 464 | |||
| 465 | Object keyOrNull; | ||
| 466 | while(null != (keyOrNull = s.readObject())) { | ||
| 467 | String key = ((String)keyOrNull).intern(); | ||
| 468 | |||
| 469 | if (itemListenerK == key) | ||
| 470 | addItemListener((ItemListener)(s.readObject())); | ||
| 471 | |||
| 472 | else // skip value for unrecognized key | ||
| 473 | s.readObject(); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | /** | ||
| 478 | * Initialize JNI field and method IDs | ||
| 479 | */ | ||
| 480 | private static native void initIDs(); | ||
| 481 | |||
| 482 | |||
| 483 | ///////////////// | ||
| 484 | // Accessibility support | ||
| 485 | //////////////// | ||
| 486 | |||
| 487 | /** | ||
| 488 | * Gets the AccessibleContext associated with this CheckboxMenuItem. | ||
| 489 | * For checkbox menu items, the AccessibleContext takes the | ||
| 490 | * form of an AccessibleAWTCheckboxMenuItem. | ||
| 491 | * A new AccessibleAWTCheckboxMenuItem is created if necessary. | ||
| 492 | * | ||
| 493 | * @return an AccessibleAWTCheckboxMenuItem that serves as the | ||
| 494 | * AccessibleContext of this CheckboxMenuItem | ||
| 495 | * @since 1.3 | ||
| 496 | */ | ||
| 497 | public AccessibleContext getAccessibleContext() { | ||
| 498 | if (accessibleContext == null) { | ||
| 499 | accessibleContext = new AccessibleAWTCheckboxMenuItem(); | ||
| 500 | } | ||
| 501 | return accessibleContext; | ||
| 502 | } | ||
| 503 | |||
| 504 | /** | ||
| 505 | * Inner class of CheckboxMenuItem used to provide default support for | ||
| 506 | * accessibility. This class is not meant to be used directly by | ||
| 507 | * application developers, but is instead meant only to be | ||
| 508 | * subclassed by menu component developers. | ||
| 509 | * <p> | ||
| 510 | * This class implements accessibility support for the | ||
| 511 | * <code>CheckboxMenuItem</code> class. It provides an implementation | ||
| 512 | * of the Java Accessibility API appropriate to checkbox menu item | ||
| 513 | * user-interface elements. | ||
| 514 | * @since 1.3 | ||
| 515 | */ | ||
| 516 | protected class AccessibleAWTCheckboxMenuItem extends AccessibleAWTMenuItem | ||
| 517 | implements AccessibleAction, AccessibleValue | ||
| 518 | { | ||
| 519 | /* | ||
| 520 | * JDK 1.3 serialVersionUID | ||
| 521 | */ | ||
| 522 | private static final long serialVersionUID = -1122642964303476L; | ||
| 523 | |||
| 524 | /** | ||
| 525 | * Get the AccessibleAction associated with this object. In the | ||
| 526 | * implementation of the Java Accessibility API for this class, | ||
| 527 | * return this object, which is responsible for implementing the | ||
| 528 | * AccessibleAction interface on behalf of itself. | ||
| 529 | * | ||
| 530 | * @return this object | ||
| 531 | */ | ||
| 532 | public AccessibleAction getAccessibleAction() { | ||
| 533 | return this; | ||
| 534 | } | ||
| 535 | |||
| 536 | /** | ||
| 537 | * Get the AccessibleValue associated with this object. In the | ||
| 538 | * implementation of the Java Accessibility API for this class, | ||
| 539 | * return this object, which is responsible for implementing the | ||
| 540 | * AccessibleValue interface on behalf of itself. | ||
| 541 | * | ||
| 542 | * @return this object | ||
| 543 | */ | ||
| 544 | public AccessibleValue getAccessibleValue() { | ||
| 545 | return this; | ||
| 546 | } | ||
| 547 | |||
| 548 | /** | ||
| 549 | * Returns the number of Actions available in this object. | ||
| 550 | * If there is more than one, the first one is the "default" | ||
| 551 | * action. | ||
| 552 | * | ||
| 553 | * @return the number of Actions in this object | ||
| 554 | */ | ||
| 555 | public int getAccessibleActionCount() { | ||
| 556 | return 0; // To be fully implemented in a future release | ||
| 557 | } | ||
| 558 | |||
| 559 | /** | ||
| 560 | * Return a description of the specified action of the object. | ||
| 561 | * | ||
| 562 | * @param i zero-based index of the actions | ||
| 563 | */ | ||
| 564 | public String getAccessibleActionDescription(int i) { | ||
| 565 | return null; // To be fully implemented in a future release | ||
| 566 | } | ||
| 567 | |||
| 568 | /** | ||
| 569 | * Perform the specified Action on the object | ||
| 570 | * | ||
| 571 | * @param i zero-based index of actions | ||
| 572 | * @return true if the action was performed; otherwise false. | ||
| 573 | */ | ||
| 574 | public boolean doAccessibleAction(int i) { | ||
| 575 | return false; // To be fully implemented in a future release | ||
| 576 | } | ||
| 577 | |||
| 578 | /** | ||
| 579 | * Get the value of this object as a Number. If the value has not been | ||
| 580 | * set, the return value will be null. | ||
| 581 | * | ||
| 582 | * @return value of the object | ||
| 583 | * @see #setCurrentAccessibleValue | ||
| 584 | */ | ||
| 585 | public Number getCurrentAccessibleValue() { | ||
| 586 | return null; // To be fully implemented in a future release | ||
| 587 | } | ||
| 588 | |||
| 589 | /** | ||
| 590 | * Set the value of this object as a Number. | ||
| 591 | * | ||
| 592 | * @return true if the value was set; otherwise false | ||
| 593 | * @see #getCurrentAccessibleValue | ||
| 594 | */ | ||
| 595 | public boolean setCurrentAccessibleValue(Number n) { | ||
| 596 | return false; // To be fully implemented in a future release | ||
| 597 | } | ||
| 598 | |||
| 599 | /** | ||
| 600 | * Get the minimum value of this object as a Number. | ||
| 601 | * | ||
| 602 | * @return Minimum value of the object; null if this object does not | ||
| 603 | * have a minimum value | ||
| 604 | * @see #getMaximumAccessibleValue | ||
| 605 | */ | ||
| 606 | public Number getMinimumAccessibleValue() { | ||
| 607 | return null; // To be fully implemented in a future release | ||
| 608 | } | ||
| 609 | |||
| 610 | /** | ||
| 611 | * Get the maximum value of this object as a Number. | ||
| 612 | * | ||
| 613 | * @return Maximum value of the object; null if this object does not | ||
| 614 | * have a maximum value | ||
| 615 | * @see #getMinimumAccessibleValue | ||
| 616 | */ | ||
| 617 | public Number getMaximumAccessibleValue() { | ||
| 618 | return null; // To be fully implemented in a future release | ||
| 619 | } | ||
| 620 | |||
| 621 | /** | ||
| 622 | * Get the role of this object. | ||
| 623 | * | ||
| 624 | * @return an instance of AccessibleRole describing the role of the | ||
| 625 | * object | ||
| 626 | */ | ||
| 627 | public AccessibleRole getAccessibleRole() { | ||
| 628 | return AccessibleRole.CHECK_BOX; | ||
| 629 | } | ||
| 630 | |||
| 631 | } // class AccessibleAWTMenuItem | ||
| 632 | |||
| 633 | } | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,811 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2008, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.util.*; | ||
| 28 | import java.awt.peer.ChoicePeer; | ||
| 29 | import java.awt.event.*; | ||
| 30 | import java.util.EventListener; | ||
| 31 | import java.io.ObjectOutputStream; | ||
| 32 | import java.io.ObjectInputStream; | ||
| 33 | import java.io.IOException; | ||
| 34 | |||
| 35 | import javax.accessibility.*; | ||
| 36 | |||
| 37 | /** | ||
| 38 | * The <code>Choice</code> class presents a pop-up menu of choices. | ||
| 39 | * The current choice is displayed as the title of the menu. | ||
| 40 | * <p> | ||
| 41 | * The following code example produces a pop-up menu: | ||
| 42 | * <p> | ||
| 43 | * <hr><blockquote><pre> | ||
| 44 | * Choice ColorChooser = new Choice(); | ||
| 45 | * ColorChooser.add("Green"); | ||
| 46 | * ColorChooser.add("Red"); | ||
| 47 | * ColorChooser.add("Blue"); | ||
| 48 | * </pre></blockquote><hr> | ||
| 49 | * <p> | ||
| 50 | * After this choice menu has been added to a panel, | ||
| 51 | * it appears as follows in its normal state: | ||
| 52 | * <p> | ||
| 53 | * <img src="doc-files/Choice-1.gif" alt="The following text describes the graphic" | ||
| 54 | * ALIGN=center HSPACE=10 VSPACE=7> | ||
| 55 | * <p> | ||
| 56 | * In the picture, <code>"Green"</code> is the current choice. | ||
| 57 | * Pushing the mouse button down on the object causes a menu to | ||
| 58 | * appear with the current choice highlighted. | ||
| 59 | * <p> | ||
| 60 | * Some native platforms do not support arbitrary resizing of | ||
| 61 | * <code>Choice</code> components and the behavior of | ||
| 62 | * <code>setSize()/getSize()</code> is bound by | ||
| 63 | * such limitations. | ||
| 64 | * Native GUI <code>Choice</code> components' size are often bound by such | ||
| 65 | * attributes as font size and length of items contained within | ||
| 66 | * the <code>Choice</code>. | ||
| 67 | * <p> | ||
| 68 | * @author Sami Shaio | ||
| 69 | * @author Arthur van Hoff | ||
| 70 | * @since JDK1.0 | ||
| 71 | */ | ||
| 72 | public class Choice extends Component implements ItemSelectable, Accessible { | ||
| 73 | /** | ||
| 74 | * The items for the <code>Choice</code>. | ||
| 75 | * This can be a <code>null</code> value. | ||
| 76 | * @serial | ||
| 77 | * @see #add(String) | ||
| 78 | * @see #addItem(String) | ||
| 79 | * @see #getItem(int) | ||
| 80 | * @see #getItemCount() | ||
| 81 | * @see #insert(String, int) | ||
| 82 | * @see #remove(String) | ||
| 83 | */ | ||
| 84 | Vector pItems; | ||
| 85 | |||
| 86 | /** | ||
| 87 | * The index of the current choice for this <code>Choice</code> | ||
| 88 | * or -1 if nothing is selected. | ||
| 89 | * @serial | ||
| 90 | * @see #getSelectedItem() | ||
| 91 | * @see #select(int) | ||
| 92 | */ | ||
| 93 | int selectedIndex = -1; | ||
| 94 | |||
| 95 | transient ItemListener itemListener; | ||
| 96 | |||
| 97 | private static final String base = "choice"; | ||
| 98 | private static int nameCounter = 0; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * JDK 1.1 serialVersionUID | ||
| 102 | */ | ||
| 103 | private static final long serialVersionUID = -4075310674757313071L; | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Creates a new choice menu. The menu initially has no items in it. | ||
| 107 | * <p> | ||
| 108 | * By default, the first item added to the choice menu becomes the | ||
| 109 | * selected item, until a different selection is made by the user | ||
| 110 | * by calling one of the <code>select</code> methods. | ||
| 111 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() | ||
| 112 | * returns true | ||
| 113 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 114 | * @see #select(int) | ||
| 115 | * @see #select(java.lang.String) | ||
| 116 | */ | ||
| 117 | public Choice() throws HeadlessException { | ||
| 118 | GraphicsEnvironment.checkHeadless(); | ||
| 119 | pItems = new Vector(); | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Constructs a name for this component. Called by | ||
| 124 | * <code>getName</code> when the name is <code>null</code>. | ||
| 125 | */ | ||
| 126 | String constructComponentName() { | ||
| 127 | synchronized (Choice.class) { | ||
| 128 | return base + nameCounter++; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Creates the <code>Choice</code>'s peer. This peer allows us | ||
| 134 | * to change the look | ||
| 135 | * of the <code>Choice</code> without changing its functionality. | ||
| 136 | * @see java.awt.Toolkit#createChoice(java.awt.Choice) | ||
| 137 | * @see java.awt.Component#getToolkit() | ||
| 138 | */ | ||
| 139 | public void addNotify() { | ||
| 140 | synchronized (getTreeLock()) { | ||
| 141 | if (peer == null) | ||
| 142 | peer = getToolkit().createChoice(this); | ||
| 143 | super.addNotify(); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | * Returns the number of items in this <code>Choice</code> menu. | ||
| 149 | * @return the number of items in this <code>Choice</code> menu | ||
| 150 | * @see #getItem | ||
| 151 | * @since JDK1.1 | ||
| 152 | */ | ||
| 153 | public int getItemCount() { | ||
| 154 | return countItems(); | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * @deprecated As of JDK version 1.1, | ||
| 159 | * replaced by <code>getItemCount()</code>. | ||
| 160 | */ | ||
| 161 | @Deprecated | ||
| 162 | public int countItems() { | ||
| 163 | return pItems.size(); | ||
| 164 | } | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Gets the string at the specified index in this | ||
| 168 | * <code>Choice</code> menu. | ||
| 169 | * @param index the index at which to begin | ||
| 170 | * @see #getItemCount | ||
| 171 | */ | ||
| 172 | public String getItem(int index) { | ||
| 173 | return getItemImpl(index); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * This is called by the native code, so client code can't | ||
| 178 | * be called on the toolkit thread. | ||
| 179 | */ | ||
| 180 | final String getItemImpl(int index) { | ||
| 181 | return (String)pItems.elementAt(index); | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Adds an item to this <code>Choice</code> menu. | ||
| 186 | * @param item the item to be added | ||
| 187 | * @exception NullPointerException if the item's value is | ||
| 188 | * <code>null</code> | ||
| 189 | * @since JDK1.1 | ||
| 190 | */ | ||
| 191 | public void add(String item) { | ||
| 192 | addItem(item); | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * Obsolete as of Java 2 platform v1.1. Please use the | ||
| 197 | * <code>add</code> method instead. | ||
| 198 | * <p> | ||
| 199 | * Adds an item to this <code>Choice</code> menu. | ||
| 200 | * @param item the item to be added | ||
| 201 | * @exception NullPointerException if the item's value is equal to | ||
| 202 | * <code>null</code> | ||
| 203 | */ | ||
| 204 | public void addItem(String item) { | ||
| 205 | synchronized (this) { | ||
| 206 | insertNoInvalidate(item, pItems.size()); | ||
| 207 | } | ||
| 208 | |||
| 209 | // This could change the preferred size of the Component. | ||
| 210 | invalidateIfValid(); | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * Inserts an item to this <code>Choice</code>, | ||
| 215 | * but does not invalidate the <code>Choice</code>. | ||
| 216 | * Client methods must provide their own synchronization before | ||
| 217 | * invoking this method. | ||
| 218 | * @param item the item to be added | ||
| 219 | * @param index the new item position | ||
| 220 | * @exception NullPointerException if the item's value is equal to | ||
| 221 | * <code>null</code> | ||
| 222 | */ | ||
| 223 | private void insertNoInvalidate(String item, int index) { | ||
| 224 | if (item == null) { | ||
| 225 | throw new | ||
| 226 | NullPointerException("cannot add null item to Choice"); | ||
| 227 | } | ||
| 228 | pItems.insertElementAt(item, index); | ||
| 229 | ChoicePeer peer = (ChoicePeer)this.peer; | ||
| 230 | if (peer != null) { | ||
| 231 | peer.add(item, index); | ||
| 232 | } | ||
| 233 | // no selection or selection shifted up | ||
| 234 | if (selectedIndex < 0 || selectedIndex >= index) { | ||
| 235 | select(0); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | /** | ||
| 241 | * Inserts the item into this choice at the specified position. | ||
| 242 | * Existing items at an index greater than or equal to | ||
| 243 | * <code>index</code> are shifted up by one to accommodate | ||
| 244 | * the new item. If <code>index</code> is greater than or | ||
| 245 | * equal to the number of items in this choice, | ||
| 246 | * <code>item</code> is added to the end of this choice. | ||
| 247 | * <p> | ||
| 248 | * If the item is the first one being added to the choice, | ||
| 249 | * then the item becomes selected. Otherwise, if the | ||
| 250 | * selected item was one of the items shifted, the first | ||
| 251 | * item in the choice becomes the selected item. If the | ||
| 252 | * selected item was no among those shifted, it remains | ||
| 253 | * the selected item. | ||
| 254 | * @param item the non-<code>null</code> item to be inserted | ||
| 255 | * @param index the position at which the item should be inserted | ||
| 256 | * @exception IllegalArgumentException if index is less than 0 | ||
| 257 | */ | ||
| 258 | public void insert(String item, int index) { | ||
| 259 | synchronized (this) { | ||
| 260 | if (index < 0) { | ||
| 261 | throw new IllegalArgumentException("index less than zero."); | ||
| 262 | } | ||
| 263 | /* if the index greater than item count, add item to the end */ | ||
| 264 | index = Math.min(index, pItems.size()); | ||
| 265 | |||
| 266 | insertNoInvalidate(item, index); | ||
| 267 | } | ||
| 268 | |||
| 269 | // This could change the preferred size of the Component. | ||
| 270 | invalidateIfValid(); | ||
| 271 | } | ||
| 272 | |||
| 273 | /** | ||
| 274 | * Removes the first occurrence of <code>item</code> | ||
| 275 | * from the <code>Choice</code> menu. If the item | ||
| 276 | * being removed is the currently selected item, | ||
| 277 | * then the first item in the choice becomes the | ||
| 278 | * selected item. Otherwise, the currently selected | ||
| 279 | * item remains selected (and the selected index is | ||
| 280 | * updated accordingly). | ||
| 281 | * @param item the item to remove from this <code>Choice</code> menu | ||
| 282 | * @exception IllegalArgumentException if the item doesn't | ||
| 283 | * exist in the choice menu | ||
| 284 | * @since JDK1.1 | ||
| 285 | */ | ||
| 286 | public void remove(String item) { | ||
| 287 | synchronized (this) { | ||
| 288 | int index = pItems.indexOf(item); | ||
| 289 | if (index < 0) { | ||
| 290 | throw new IllegalArgumentException("item " + item + | ||
| 291 | " not found in choice"); | ||
| 292 | } else { | ||
| 293 | removeNoInvalidate(index); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | // This could change the preferred size of the Component. | ||
| 298 | invalidateIfValid(); | ||
| 299 | } | ||
| 300 | |||
| 301 | /** | ||
| 302 | * Removes an item from the choice menu | ||
| 303 | * at the specified position. If the item | ||
| 304 | * being removed is the currently selected item, | ||
| 305 | * then the first item in the choice becomes the | ||
| 306 | * selected item. Otherwise, the currently selected | ||
| 307 | * item remains selected (and the selected index is | ||
| 308 | * updated accordingly). | ||
| 309 | * @param position the position of the item | ||
| 310 | * @throws IndexOutOfBoundsException if the specified | ||
| 311 | * position is out of bounds | ||
| 312 | * @since JDK1.1 | ||
| 313 | */ | ||
| 314 | public void remove(int position) { | ||
| 315 | synchronized (this) { | ||
| 316 | removeNoInvalidate(position); | ||
| 317 | } | ||
| 318 | |||
| 319 | // This could change the preferred size of the Component. | ||
| 320 | invalidateIfValid(); | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * Removes an item from the <code>Choice</code> at the | ||
| 325 | * specified position, but does not invalidate the <code>Choice</code>. | ||
| 326 | * Client methods must provide their | ||
| 327 | * own synchronization before invoking this method. | ||
| 328 | * @param position the position of the item | ||
| 329 | */ | ||
| 330 | private void removeNoInvalidate(int position) { | ||
| 331 | pItems.removeElementAt(position); | ||
| 332 | ChoicePeer peer = (ChoicePeer)this.peer; | ||
| 333 | if (peer != null) { | ||
| 334 | peer.remove(position); | ||
| 335 | } | ||
| 336 | /* Adjust selectedIndex if selected item was removed. */ | ||
| 337 | if (pItems.size() == 0) { | ||
| 338 | selectedIndex = -1; | ||
| 339 | } else if (selectedIndex == position) { | ||
| 340 | select(0); | ||
| 341 | } else if (selectedIndex > position) { | ||
| 342 | select(selectedIndex-1); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | |||
| 347 | /** | ||
| 348 | * Removes all items from the choice menu. | ||
| 349 | * @see #remove | ||
| 350 | * @since JDK1.1 | ||
| 351 | */ | ||
| 352 | public void removeAll() { | ||
| 353 | synchronized (this) { | ||
| 354 | if (peer != null) { | ||
| 355 | ((ChoicePeer)peer).removeAll(); | ||
| 356 | } | ||
| 357 | pItems.removeAllElements(); | ||
| 358 | selectedIndex = -1; | ||
| 359 | } | ||
| 360 | |||
| 361 | // This could change the preferred size of the Component. | ||
| 362 | invalidateIfValid(); | ||
| 363 | } | ||
| 364 | |||
| 365 | /** | ||
| 366 | * Gets a representation of the current choice as a string. | ||
| 367 | * @return a string representation of the currently | ||
| 368 | * selected item in this choice menu | ||
| 369 | * @see #getSelectedIndex | ||
| 370 | */ | ||
| 371 | public synchronized String getSelectedItem() { | ||
| 372 | return (selectedIndex >= 0) ? getItem(selectedIndex) : null; | ||
| 373 | } | ||
| 374 | |||
| 375 | /** | ||
| 376 | * Returns an array (length 1) containing the currently selected | ||
| 377 | * item. If this choice has no items, returns <code>null</code>. | ||
| 378 | * @see ItemSelectable | ||
| 379 | */ | ||
| 380 | public synchronized Object[] getSelectedObjects() { | ||
| 381 | if (selectedIndex >= 0) { | ||
| 382 | Object[] items = new Object[1]; | ||
| 383 | items[0] = getItem(selectedIndex); | ||
| 384 | return items; | ||
| 385 | } | ||
| 386 | return null; | ||
| 387 | } | ||
| 388 | |||
| 389 | /** | ||
| 390 | * Returns the index of the currently selected item. | ||
| 391 | * If nothing is selected, returns -1. | ||
| 392 | * | ||
| 393 | * @return the index of the currently selected item, or -1 if nothing | ||
| 394 | * is currently selected | ||
| 395 | * @see #getSelectedItem | ||
| 396 | */ | ||
| 397 | public int getSelectedIndex() { | ||
| 398 | return selectedIndex; | ||
| 399 | } | ||
| 400 | |||
| 401 | /** | ||
| 402 | * Sets the selected item in this <code>Choice</code> menu to be the | ||
| 403 | * item at the specified position. | ||
| 404 | * | ||
| 405 | * <p>Note that this method should be primarily used to | ||
| 406 | * initially select an item in this component. | ||
| 407 | * Programmatically calling this method will <i>not</i> trigger | ||
| 408 | * an <code>ItemEvent</code>. The only way to trigger an | ||
| 409 | * <code>ItemEvent</code> is by user interaction. | ||
| 410 | * | ||
| 411 | * @param pos the positon of the selected item | ||
| 412 | * @exception IllegalArgumentException if the specified | ||
| 413 | * position is greater than the | ||
| 414 | * number of items or less than zero | ||
| 415 | * @see #getSelectedItem | ||
| 416 | * @see #getSelectedIndex | ||
| 417 | */ | ||
| 418 | public synchronized void select(int pos) { | ||
| 419 | if ((pos >= pItems.size()) || (pos < 0)) { | ||
| 420 | throw new IllegalArgumentException("illegal Choice item position: " + pos); | ||
| 421 | } | ||
| 422 | if (pItems.size() > 0) { | ||
| 423 | selectedIndex = pos; | ||
| 424 | ChoicePeer peer = (ChoicePeer)this.peer; | ||
| 425 | if (peer != null) { | ||
| 426 | peer.select(pos); | ||
| 427 | } | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | /** | ||
| 432 | * Sets the selected item in this <code>Choice</code> menu | ||
| 433 | * to be the item whose name is equal to the specified string. | ||
| 434 | * If more than one item matches (is equal to) the specified string, | ||
| 435 | * the one with the smallest index is selected. | ||
| 436 | * | ||
| 437 | * <p>Note that this method should be primarily used to | ||
| 438 | * initially select an item in this component. | ||
| 439 | * Programmatically calling this method will <i>not</i> trigger | ||
| 440 | * an <code>ItemEvent</code>. The only way to trigger an | ||
| 441 | * <code>ItemEvent</code> is by user interaction. | ||
| 442 | * | ||
| 443 | * @param str the specified string | ||
| 444 | * @see #getSelectedItem | ||
| 445 | * @see #getSelectedIndex | ||
| 446 | */ | ||
| 447 | public synchronized void select(String str) { | ||
| 448 | int index = pItems.indexOf(str); | ||
| 449 | if (index >= 0) { | ||
| 450 | select(index); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | /** | ||
| 455 | * Adds the specified item listener to receive item events from | ||
| 456 | * this <code>Choice</code> menu. Item events are sent in response | ||
| 457 | * to user input, but not in response to calls to <code>select</code>. | ||
| 458 | * If l is <code>null</code>, no exception is thrown and no action | ||
| 459 | * is performed. | ||
| 460 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 461 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 462 | * @param l the item listener | ||
| 463 | * @see #removeItemListener | ||
| 464 | * @see #getItemListeners | ||
| 465 | * @see #select | ||
| 466 | * @see java.awt.event.ItemEvent | ||
| 467 | * @see java.awt.event.ItemListener | ||
| 468 | * @since JDK1.1 | ||
| 469 | */ | ||
| 470 | public synchronized void addItemListener(ItemListener l) { | ||
| 471 | if (l == null) { | ||
| 472 | return; | ||
| 473 | } | ||
| 474 | itemListener = AWTEventMulticaster.add(itemListener, l); | ||
| 475 | newEventsOnly = true; | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * Removes the specified item listener so that it no longer receives | ||
| 480 | * item events from this <code>Choice</code> menu. | ||
| 481 | * If l is <code>null</code>, no exception is thrown and no | ||
| 482 | * action is performed. | ||
| 483 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 484 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 485 | * @param l the item listener | ||
| 486 | * @see #addItemListener | ||
| 487 | * @see #getItemListeners | ||
| 488 | * @see java.awt.event.ItemEvent | ||
| 489 | * @see java.awt.event.ItemListener | ||
| 490 | * @since JDK1.1 | ||
| 491 | */ | ||
| 492 | public synchronized void removeItemListener(ItemListener l) { | ||
| 493 | if (l == null) { | ||
| 494 | return; | ||
| 495 | } | ||
| 496 | itemListener = AWTEventMulticaster.remove(itemListener, l); | ||
| 497 | } | ||
| 498 | |||
| 499 | /** | ||
| 500 | * Returns an array of all the item listeners | ||
| 501 | * registered on this choice. | ||
| 502 | * | ||
| 503 | * @return all of this choice's <code>ItemListener</code>s | ||
| 504 | * or an empty array if no item | ||
| 505 | * listeners are currently registered | ||
| 506 | * | ||
| 507 | * @see #addItemListener | ||
| 508 | * @see #removeItemListener | ||
| 509 | * @see java.awt.event.ItemEvent | ||
| 510 | * @see java.awt.event.ItemListener | ||
| 511 | * @since 1.4 | ||
| 512 | */ | ||
| 513 | public synchronized ItemListener[] getItemListeners() { | ||
| 514 | return (ItemListener[])(getListeners(ItemListener.class)); | ||
| 515 | } | ||
| 516 | |||
| 517 | /** | ||
| 518 | * Returns an array of all the objects currently registered | ||
| 519 | * as <code><em>Foo</em>Listener</code>s | ||
| 520 | * upon this <code>Choice</code>. | ||
| 521 | * <code><em>Foo</em>Listener</code>s are registered using the | ||
| 522 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 523 | * | ||
| 524 | * <p> | ||
| 525 | * You can specify the <code>listenerType</code> argument | ||
| 526 | * with a class literal, such as | ||
| 527 | * <code><em>Foo</em>Listener.class</code>. | ||
| 528 | * For example, you can query a | ||
| 529 | * <code>Choice</code> <code>c</code> | ||
| 530 | * for its item listeners with the following code: | ||
| 531 | * | ||
| 532 | * <pre>ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));</pre> | ||
| 533 | * | ||
| 534 | * If no such listeners exist, this method returns an empty array. | ||
| 535 | * | ||
| 536 | * @param listenerType the type of listeners requested; this parameter | ||
| 537 | * should specify an interface that descends from | ||
| 538 | * <code>java.util.EventListener</code> | ||
| 539 | * @return an array of all objects registered as | ||
| 540 | * <code><em>Foo</em>Listener</code>s on this choice, | ||
| 541 | * or an empty array if no such | ||
| 542 | * listeners have been added | ||
| 543 | * @exception ClassCastException if <code>listenerType</code> | ||
| 544 | * doesn't specify a class or interface that implements | ||
| 545 | * <code>java.util.EventListener</code> | ||
| 546 | * | ||
| 547 | * @see #getItemListeners | ||
| 548 | * @since 1.3 | ||
| 549 | */ | ||
| 550 | public <T extends EventListener> T[] getListeners(Class<T> listenerType) { | ||
| 551 | EventListener l = null; | ||
| 552 | if (listenerType == ItemListener.class) { | ||
| 553 | l = itemListener; | ||
| 554 | } else { | ||
| 555 | return super.getListeners(listenerType); | ||
| 556 | } | ||
| 557 | return AWTEventMulticaster.getListeners(l, listenerType); | ||
| 558 | } | ||
| 559 | |||
| 560 | // REMIND: remove when filtering is done at lower level | ||
| 561 | boolean eventEnabled(AWTEvent e) { | ||
| 562 | if (e.id == ItemEvent.ITEM_STATE_CHANGED) { | ||
| 563 | if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0 || | ||
| 564 | itemListener != null) { | ||
| 565 | return true; | ||
| 566 | } | ||
| 567 | return false; | ||
| 568 | } | ||
| 569 | return super.eventEnabled(e); | ||
| 570 | } | ||
| 571 | |||
| 572 | /** | ||
| 573 | * Processes events on this choice. If the event is an | ||
| 574 | * instance of <code>ItemEvent</code>, it invokes the | ||
| 575 | * <code>processItemEvent</code> method. Otherwise, it calls its | ||
| 576 | * superclass's <code>processEvent</code> method. | ||
| 577 | * <p>Note that if the event parameter is <code>null</code> | ||
| 578 | * the behavior is unspecified and may result in an | ||
| 579 | * exception. | ||
| 580 | * | ||
| 581 | * @param e the event | ||
| 582 | * @see java.awt.event.ItemEvent | ||
| 583 | * @see #processItemEvent | ||
| 584 | * @since JDK1.1 | ||
| 585 | */ | ||
| 586 | protected void processEvent(AWTEvent e) { | ||
| 587 | if (e instanceof ItemEvent) { | ||
| 588 | processItemEvent((ItemEvent)e); | ||
| 589 | return; | ||
| 590 | } | ||
| 591 | super.processEvent(e); | ||
| 592 | } | ||
| 593 | |||
| 594 | /** | ||
| 595 | * Processes item events occurring on this <code>Choice</code> | ||
| 596 | * menu by dispatching them to any registered | ||
| 597 | * <code>ItemListener</code> objects. | ||
| 598 | * <p> | ||
| 599 | * This method is not called unless item events are | ||
| 600 | * enabled for this component. Item events are enabled | ||
| 601 | * when one of the following occurs: | ||
| 602 | * <p><ul> | ||
| 603 | * <li>An <code>ItemListener</code> object is registered | ||
| 604 | * via <code>addItemListener</code>. | ||
| 605 | * <li>Item events are enabled via <code>enableEvents</code>. | ||
| 606 | * </ul> | ||
| 607 | * <p>Note that if the event parameter is <code>null</code> | ||
| 608 | * the behavior is unspecified and may result in an | ||
| 609 | * exception. | ||
| 610 | * | ||
| 611 | * @param e the item event | ||
| 612 | * @see java.awt.event.ItemEvent | ||
| 613 | * @see java.awt.event.ItemListener | ||
| 614 | * @see #addItemListener(ItemListener) | ||
| 615 | * @see java.awt.Component#enableEvents | ||
| 616 | * @since JDK1.1 | ||
| 617 | */ | ||
| 618 | protected void processItemEvent(ItemEvent e) { | ||
| 619 | ItemListener listener = itemListener; | ||
| 620 | if (listener != null) { | ||
| 621 | listener.itemStateChanged(e); | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | /** | ||
| 626 | * Returns a string representing the state of this <code>Choice</code> | ||
| 627 | * menu. This method is intended to be used only for debugging purposes, | ||
| 628 | * and the content and format of the returned string may vary between | ||
| 629 | * implementations. The returned string may be empty but may not be | ||
| 630 | * <code>null</code>. | ||
| 631 | * | ||
| 632 | * @return the parameter string of this <code>Choice</code> menu | ||
| 633 | */ | ||
| 634 | protected String paramString() { | ||
| 635 | return super.paramString() + ",current=" + getSelectedItem(); | ||
| 636 | } | ||
| 637 | |||
| 638 | |||
| 639 | /* Serialization support. | ||
| 640 | */ | ||
| 641 | |||
| 642 | /* | ||
| 643 | * Choice Serial Data Version. | ||
| 644 | * @serial | ||
| 645 | */ | ||
| 646 | private int choiceSerializedDataVersion = 1; | ||
| 647 | |||
| 648 | /** | ||
| 649 | * Writes default serializable fields to stream. Writes | ||
| 650 | * a list of serializable <code>ItemListeners</code> | ||
| 651 | * as optional data. The non-serializable | ||
| 652 | * <code>ItemListeners</code> are detected and | ||
| 653 | * no attempt is made to serialize them. | ||
| 654 | * | ||
| 655 | * @param s the <code>ObjectOutputStream</code> to write | ||
| 656 | * @serialData <code>null</code> terminated sequence of 0 | ||
| 657 | * or more pairs; the pair consists of a <code>String</code> | ||
| 658 | * and an <code>Object</code>; the <code>String</code> indicates | ||
| 659 | * the type of object and is one of the following: | ||
| 660 | * <code>itemListenerK</code> indicating an | ||
| 661 | * <code>ItemListener</code> object | ||
| 662 | * | ||
| 663 | * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) | ||
| 664 | * @see java.awt.Component#itemListenerK | ||
| 665 | * @see #readObject(ObjectInputStream) | ||
| 666 | */ | ||
| 667 | private void writeObject(ObjectOutputStream s) | ||
| 668 | throws java.io.IOException | ||
| 669 | { | ||
| 670 | s.defaultWriteObject(); | ||
| 671 | |||
| 672 | AWTEventMulticaster.save(s, itemListenerK, itemListener); | ||
| 673 | s.writeObject(null); | ||
| 674 | } | ||
| 675 | |||
| 676 | /** | ||
| 677 | * Reads the <code>ObjectInputStream</code> and if it | ||
| 678 | * isn't <code>null</code> adds a listener to receive | ||
| 679 | * item events fired by the <code>Choice</code> item. | ||
| 680 | * Unrecognized keys or values will be ignored. | ||
| 681 | * | ||
| 682 | * @param s the <code>ObjectInputStream</code> to read | ||
| 683 | * @exception HeadlessException if | ||
| 684 | * <code>GraphicsEnvironment.isHeadless</code> returns | ||
| 685 | * <code>true</code> | ||
| 686 | * @serial | ||
| 687 | * @see #removeItemListener(ItemListener) | ||
| 688 | * @see #addItemListener(ItemListener) | ||
| 689 | * @see java.awt.GraphicsEnvironment#isHeadless | ||
| 690 | * @see #writeObject(ObjectOutputStream) | ||
| 691 | */ | ||
| 692 | private void readObject(ObjectInputStream s) | ||
| 693 | throws ClassNotFoundException, IOException, HeadlessException | ||
| 694 | { | ||
| 695 | GraphicsEnvironment.checkHeadless(); | ||
| 696 | s.defaultReadObject(); | ||
| 697 | |||
| 698 | Object keyOrNull; | ||
| 699 | while(null != (keyOrNull = s.readObject())) { | ||
| 700 | String key = ((String)keyOrNull).intern(); | ||
| 701 | |||
| 702 | if (itemListenerK == key) | ||
| 703 | addItemListener((ItemListener)(s.readObject())); | ||
| 704 | |||
| 705 | else // skip value for unrecognized key | ||
| 706 | s.readObject(); | ||
| 707 | } | ||
| 708 | } | ||
| 709 | |||
| 710 | |||
| 711 | ///////////////// | ||
| 712 | // Accessibility support | ||
| 713 | //////////////// | ||
| 714 | |||
| 715 | |||
| 716 | /** | ||
| 717 | * Gets the <code>AccessibleContext</code> associated with this | ||
| 718 | * <code>Choice</code>. For <code>Choice</code> components, | ||
| 719 | * the <code>AccessibleContext</code> takes the form of an | ||
| 720 | * <code>AccessibleAWTChoice</code>. A new <code>AccessibleAWTChoice</code> | ||
| 721 | * instance is created if necessary. | ||
| 722 | * | ||
| 723 | * @return an <code>AccessibleAWTChoice</code> that serves as the | ||
| 724 | * <code>AccessibleContext</code> of this <code>Choice</code> | ||
| 725 | * @since 1.3 | ||
| 726 | */ | ||
| 727 | public AccessibleContext getAccessibleContext() { | ||
| 728 | if (accessibleContext == null) { | ||
| 729 | accessibleContext = new AccessibleAWTChoice(); | ||
| 730 | } | ||
| 731 | return accessibleContext; | ||
| 732 | } | ||
| 733 | |||
| 734 | /** | ||
| 735 | * This class implements accessibility support for the | ||
| 736 | * <code>Choice</code> class. It provides an implementation of the | ||
| 737 | * Java Accessibility API appropriate to choice user-interface elements. | ||
| 738 | * @since 1.3 | ||
| 739 | */ | ||
| 740 | protected class AccessibleAWTChoice extends AccessibleAWTComponent | ||
| 741 | implements AccessibleAction | ||
| 742 | { | ||
| 743 | /* | ||
| 744 | * JDK 1.3 serialVersionUID | ||
| 745 | */ | ||
| 746 | private static final long serialVersionUID = 7175603582428509322L; | ||
| 747 | |||
| 748 | public AccessibleAWTChoice() { | ||
| 749 | super(); | ||
| 750 | } | ||
| 751 | |||
| 752 | /** | ||
| 753 | * Get the AccessibleAction associated with this object. In the | ||
| 754 | * implementation of the Java Accessibility API for this class, | ||
| 755 | * return this object, which is responsible for implementing the | ||
| 756 | * AccessibleAction interface on behalf of itself. | ||
| 757 | * | ||
| 758 | * @return this object | ||
| 759 | * @see AccessibleAction | ||
| 760 | */ | ||
| 761 | public AccessibleAction getAccessibleAction() { | ||
| 762 | return this; | ||
| 763 | } | ||
| 764 | |||
| 765 | /** | ||
| 766 | * Get the role of this object. | ||
| 767 | * | ||
| 768 | * @return an instance of AccessibleRole describing the role of the | ||
| 769 | * object | ||
| 770 | * @see AccessibleRole | ||
| 771 | */ | ||
| 772 | public AccessibleRole getAccessibleRole() { | ||
| 773 | return AccessibleRole.COMBO_BOX; | ||
| 774 | } | ||
| 775 | |||
| 776 | /** | ||
| 777 | * Returns the number of accessible actions available in this object | ||
| 778 | * If there are more than one, the first one is considered the "default" | ||
| 779 | * action of the object. | ||
| 780 | * | ||
| 781 | * @return the zero-based number of Actions in this object | ||
| 782 | */ | ||
| 783 | public int getAccessibleActionCount() { | ||
| 784 | return 0; // To be fully implemented in a future release | ||
| 785 | } | ||
| 786 | |||
| 787 | /** | ||
| 788 | * Returns a description of the specified action of the object. | ||
| 789 | * | ||
| 790 | * @param i zero-based index of the actions | ||
| 791 | * @return a String description of the action | ||
| 792 | * @see #getAccessibleActionCount | ||
| 793 | */ | ||
| 794 | public String getAccessibleActionDescription(int i) { | ||
| 795 | return null; // To be fully implemented in a future release | ||
| 796 | } | ||
| 797 | |||
| 798 | /** | ||
| 799 | * Perform the specified Action on the object | ||
| 800 | * | ||
| 801 | * @param i zero-based index of actions | ||
| 802 | * @return true if the action was performed; otherwise false. | ||
| 803 | * @see #getAccessibleActionCount | ||
| 804 | */ | ||
| 805 | public boolean doAccessibleAction(int i) { | ||
| 806 | return false; // To be fully implemented in a future release | ||
| 807 | } | ||
| 808 | |||
| 809 | } // inner class AccessibleAWTChoice | ||
| 810 | |||
| 811 | } | ||
Binary file not shown.
| @@ -0,0 +1,1244 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2010, 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 java.awt; | ||
| 27 | |||
| 28 | import java.beans.ConstructorProperties; | ||
| 29 | import java.awt.image.ColorModel; | ||
| 30 | import java.awt.geom.AffineTransform; | ||
| 31 | import java.awt.geom.Rectangle2D; | ||
| 32 | import java.awt.color.ColorSpace; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * The <code>Color</code> class is used to encapsulate colors in the default | ||
| 36 | * sRGB color space or colors in arbitrary color spaces identified by a | ||
| 37 | * {@link ColorSpace}. Every color has an implicit alpha value of 1.0 or | ||
| 38 | * an explicit one provided in the constructor. The alpha value | ||
| 39 | * defines the transparency of a color and can be represented by | ||
| 40 | * a float value in the range 0.0 - 1.0 or 0 - 255. | ||
| 41 | * An alpha value of 1.0 or 255 means that the color is completely | ||
| 42 | * opaque and an alpha value of 0 or 0.0 means that the color is | ||
| 43 | * completely transparent. | ||
| 44 | * When constructing a <code>Color</code> with an explicit alpha or | ||
| 45 | * getting the color/alpha components of a <code>Color</code>, the color | ||
| 46 | * components are never premultiplied by the alpha component. | ||
| 47 | * <p> | ||
| 48 | * The default color space for the Java 2D(tm) API is sRGB, a proposed | ||
| 49 | * standard RGB color space. For further information on sRGB, | ||
| 50 | * see <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html"> | ||
| 51 | * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html | ||
| 52 | * </A>. | ||
| 53 | * <p> | ||
| 54 | * @version 10 Feb 1997 | ||
| 55 | * @author Sami Shaio | ||
| 56 | * @author Arthur van Hoff | ||
| 57 | * @see ColorSpace | ||
| 58 | * @see AlphaComposite | ||
| 59 | */ | ||
| 60 | public class Color implements Paint, java.io.Serializable { | ||
| 61 | |||
| 62 | /** | ||
| 63 | * The color white. In the default sRGB space. | ||
| 64 | */ | ||
| 65 | public final static Color white = new Color(255, 255, 255); | ||
| 66 | |||
| 67 | /** | ||
| 68 | * The color white. In the default sRGB space. | ||
| 69 | * @since 1.4 | ||
| 70 | */ | ||
| 71 | public final static Color WHITE = white; | ||
| 72 | |||
| 73 | /** | ||
| 74 | * The color light gray. In the default sRGB space. | ||
| 75 | */ | ||
| 76 | public final static Color lightGray = new Color(192, 192, 192); | ||
| 77 | |||
| 78 | /** | ||
| 79 | * The color light gray. In the default sRGB space. | ||
| 80 | * @since 1.4 | ||
| 81 | */ | ||
| 82 | public final static Color LIGHT_GRAY = lightGray; | ||
| 83 | |||
| 84 | /** | ||
| 85 | * The color gray. In the default sRGB space. | ||
| 86 | */ | ||
| 87 | public final static Color gray = new Color(128, 128, 128); | ||
| 88 | |||
| 89 | /** | ||
| 90 | * The color gray. In the default sRGB space. | ||
| 91 | * @since 1.4 | ||
| 92 | */ | ||
| 93 | public final static Color GRAY = gray; | ||
| 94 | |||
| 95 | /** | ||
| 96 | * The color dark gray. In the default sRGB space. | ||
| 97 | */ | ||
| 98 | public final static Color darkGray = new Color(64, 64, 64); | ||
| 99 | |||
| 100 | /** | ||
| 101 | * The color dark gray. In the default sRGB space. | ||
| 102 | * @since 1.4 | ||
| 103 | */ | ||
| 104 | public final static Color DARK_GRAY = darkGray; | ||
| 105 | |||
| 106 | /** | ||
| 107 | * The color black. In the default sRGB space. | ||
| 108 | */ | ||
| 109 | public final static Color black = new Color(0, 0, 0); | ||
| 110 | |||
| 111 | /** | ||
| 112 | * The color black. In the default sRGB space. | ||
| 113 | * @since 1.4 | ||
| 114 | */ | ||
| 115 | public final static Color BLACK = black; | ||
| 116 | |||
| 117 | /** | ||
| 118 | * The color red. In the default sRGB space. | ||
| 119 | */ | ||
| 120 | public final static Color red = new Color(255, 0, 0); | ||
| 121 | |||
| 122 | /** | ||
| 123 | * The color red. In the default sRGB space. | ||
| 124 | * @since 1.4 | ||
| 125 | */ | ||
| 126 | public final static Color RED = red; | ||
| 127 | |||
| 128 | /** | ||
| 129 | * The color pink. In the default sRGB space. | ||
| 130 | */ | ||
| 131 | public final static Color pink = new Color(255, 175, 175); | ||
| 132 | |||
| 133 | /** | ||
| 134 | * The color pink. In the default sRGB space. | ||
| 135 | * @since 1.4 | ||
| 136 | */ | ||
| 137 | public final static Color PINK = pink; | ||
| 138 | |||
| 139 | /** | ||
| 140 | * The color orange. In the default sRGB space. | ||
| 141 | */ | ||
| 142 | public final static Color orange = new Color(255, 200, 0); | ||
| 143 | |||
| 144 | /** | ||
| 145 | * The color orange. In the default sRGB space. | ||
| 146 | * @since 1.4 | ||
| 147 | */ | ||
| 148 | public final static Color ORANGE = orange; | ||
| 149 | |||
| 150 | /** | ||
| 151 | * The color yellow. In the default sRGB space. | ||
| 152 | */ | ||
| 153 | public final static Color yellow = new Color(255, 255, 0); | ||
| 154 | |||
| 155 | /** | ||
| 156 | * The color yellow. In the default sRGB space. | ||
| 157 | * @since 1.4 | ||
| 158 | */ | ||
| 159 | public final static Color YELLOW = yellow; | ||
| 160 | |||
| 161 | /** | ||
| 162 | * The color green. In the default sRGB space. | ||
| 163 | */ | ||
| 164 | public final static Color green = new Color(0, 255, 0); | ||
| 165 | |||
| 166 | /** | ||
| 167 | * The color green. In the default sRGB space. | ||
| 168 | * @since 1.4 | ||
| 169 | */ | ||
| 170 | public final static Color GREEN = green; | ||
| 171 | |||
| 172 | /** | ||
| 173 | * The color magenta. In the default sRGB space. | ||
| 174 | */ | ||
| 175 | public final static Color magenta = new Color(255, 0, 255); | ||
| 176 | |||
| 177 | /** | ||
| 178 | * The color magenta. In the default sRGB space. | ||
| 179 | * @since 1.4 | ||
| 180 | */ | ||
| 181 | public final static Color MAGENTA = magenta; | ||
| 182 | |||
| 183 | /** | ||
| 184 | * The color cyan. In the default sRGB space. | ||
| 185 | */ | ||
| 186 | public final static Color cyan = new Color(0, 255, 255); | ||
| 187 | |||
| 188 | /** | ||
| 189 | * The color cyan. In the default sRGB space. | ||
| 190 | * @since 1.4 | ||
| 191 | */ | ||
| 192 | public final static Color CYAN = cyan; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * The color blue. In the default sRGB space. | ||
| 196 | */ | ||
| 197 | public final static Color blue = new Color(0, 0, 255); | ||
| 198 | |||
| 199 | /** | ||
| 200 | * The color blue. In the default sRGB space. | ||
| 201 | * @since 1.4 | ||
| 202 | */ | ||
| 203 | public final static Color BLUE = blue; | ||
| 204 | |||
| 205 | /** | ||
| 206 | * The color value. | ||
| 207 | * @serial | ||
| 208 | * @see #getRGB | ||
| 209 | */ | ||
| 210 | int value; | ||
| 211 | |||
| 212 | /** | ||
| 213 | * The color value in the default sRGB <code>ColorSpace</code> as | ||
| 214 | * <code>float</code> components (no alpha). | ||
| 215 | * If <code>null</code> after object construction, this must be an | ||
| 216 | * sRGB color constructed with 8-bit precision, so compute from the | ||
| 217 | * <code>int</code> color value. | ||
| 218 | * @serial | ||
| 219 | * @see #getRGBColorComponents | ||
| 220 | * @see #getRGBComponents | ||
| 221 | */ | ||
| 222 | private float frgbvalue[] = null; | ||
| 223 | |||
| 224 | /** | ||
| 225 | * The color value in the native <code>ColorSpace</code> as | ||
| 226 | * <code>float</code> components (no alpha). | ||
| 227 | * If <code>null</code> after object construction, this must be an | ||
| 228 | * sRGB color constructed with 8-bit precision, so compute from the | ||
| 229 | * <code>int</code> color value. | ||
| 230 | * @serial | ||
| 231 | * @see #getRGBColorComponents | ||
| 232 | * @see #getRGBComponents | ||
| 233 | */ | ||
| 234 | private float fvalue[] = null; | ||
| 235 | |||
| 236 | /** | ||
| 237 | * The alpha value as a <code>float</code> component. | ||
| 238 | * If <code>frgbvalue</code> is <code>null</code>, this is not valid | ||
| 239 | * data, so compute from the <code>int</code> color value. | ||
| 240 | * @serial | ||
| 241 | * @see #getRGBComponents | ||
| 242 | * @see #getComponents | ||
| 243 | */ | ||
| 244 | private float falpha = 0.0f; | ||
| 245 | |||
| 246 | /** | ||
| 247 | * The <code>ColorSpace</code>. If <code>null</code>, then it's | ||
| 248 | * default is sRGB. | ||
| 249 | * @serial | ||
| 250 | * @see #getColor | ||
| 251 | * @see #getColorSpace | ||
| 252 | * @see #getColorComponents | ||
| 253 | */ | ||
| 254 | private ColorSpace cs = null; | ||
| 255 | |||
| 256 | /* | ||
| 257 | * JDK 1.1 serialVersionUID | ||
| 258 | */ | ||
| 259 | private static final long serialVersionUID = 118526816881161077L; | ||
| 260 | |||
| 261 | /** | ||
| 262 | * Initialize JNI field and method IDs | ||
| 263 | */ | ||
| 264 | private static native void initIDs(); | ||
| 265 | |||
| 266 | static { | ||
| 267 | /** 4112352 - Calling getDefaultToolkit() | ||
| 268 | ** here can cause this class to be accessed before it is fully | ||
| 269 | ** initialized. DON'T DO IT!!! | ||
| 270 | ** | ||
| 271 | ** Toolkit.getDefaultToolkit(); | ||
| 272 | **/ | ||
| 273 | |||
| 274 | /* ensure that the necessary native libraries are loaded */ | ||
| 275 | Toolkit.loadLibraries(); | ||
| 276 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 277 | initIDs(); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | /** | ||
| 282 | * Checks the color integer components supplied for validity. | ||
| 283 | * Throws an {@link IllegalArgumentException} if the value is out of | ||
| 284 | * range. | ||
| 285 | * @param r the Red component | ||
| 286 | * @param g the Green component | ||
| 287 | * @param b the Blue component | ||
| 288 | **/ | ||
| 289 | private static void testColorValueRange(int r, int g, int b, int a) { | ||
| 290 | boolean rangeError = false; | ||
| 291 | String badComponentString = ""; | ||
| 292 | |||
| 293 | if ( a < 0 || a > 255) { | ||
| 294 | rangeError = true; | ||
| 295 | badComponentString = badComponentString + " Alpha"; | ||
| 296 | } | ||
| 297 | if ( r < 0 || r > 255) { | ||
| 298 | rangeError = true; | ||
| 299 | badComponentString = badComponentString + " Red"; | ||
| 300 | } | ||
| 301 | if ( g < 0 || g > 255) { | ||
| 302 | rangeError = true; | ||
| 303 | badComponentString = badComponentString + " Green"; | ||
| 304 | } | ||
| 305 | if ( b < 0 || b > 255) { | ||
| 306 | rangeError = true; | ||
| 307 | badComponentString = badComponentString + " Blue"; | ||
| 308 | } | ||
| 309 | if ( rangeError == true ) { | ||
| 310 | throw new IllegalArgumentException("Color parameter outside of expected range:" | ||
| 311 | + badComponentString); | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | /** | ||
| 316 | * Checks the color <code>float</code> components supplied for | ||
| 317 | * validity. | ||
| 318 | * Throws an <code>IllegalArgumentException</code> if the value is out | ||
| 319 | * of range. | ||
| 320 | * @param r the Red component | ||
| 321 | * @param g the Green component | ||
| 322 | * @param b the Blue component | ||
| 323 | **/ | ||
| 324 | private static void testColorValueRange(float r, float g, float b, float a) { | ||
| 325 | boolean rangeError = false; | ||
| 326 | String badComponentString = ""; | ||
| 327 | if ( a < 0.0 || a > 1.0) { | ||
| 328 | rangeError = true; | ||
| 329 | badComponentString = badComponentString + " Alpha"; | ||
| 330 | } | ||
| 331 | if ( r < 0.0 || r > 1.0) { | ||
| 332 | rangeError = true; | ||
| 333 | badComponentString = badComponentString + " Red"; | ||
| 334 | } | ||
| 335 | if ( g < 0.0 || g > 1.0) { | ||
| 336 | rangeError = true; | ||
| 337 | badComponentString = badComponentString + " Green"; | ||
| 338 | } | ||
| 339 | if ( b < 0.0 || b > 1.0) { | ||
| 340 | rangeError = true; | ||
| 341 | badComponentString = badComponentString + " Blue"; | ||
| 342 | } | ||
| 343 | if ( rangeError == true ) { | ||
| 344 | throw new IllegalArgumentException("Color parameter outside of expected range:" | ||
| 345 | + badComponentString); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | /** | ||
| 350 | * Creates an opaque sRGB color with the specified red, green, | ||
| 351 | * and blue values in the range (0 - 255). | ||
| 352 | * The actual color used in rendering depends | ||
| 353 | * on finding the best match given the color space | ||
| 354 | * available for a given output device. | ||
| 355 | * Alpha is defaulted to 255. | ||
| 356 | * | ||
| 357 | * @throws IllegalArgumentException if <code>r</code>, <code>g</code> | ||
| 358 | * or <code>b</code> are outside of the range | ||
| 359 | * 0 to 255, inclusive | ||
| 360 | * @param r the red component | ||
| 361 | * @param g the green component | ||
| 362 | * @param b the blue component | ||
| 363 | * @see #getRed | ||
| 364 | * @see #getGreen | ||
| 365 | * @see #getBlue | ||
| 366 | * @see #getRGB | ||
| 367 | */ | ||
| 368 | public Color(int r, int g, int b) { | ||
| 369 | this(r, g, b, 255); | ||
| 370 | } | ||
| 371 | |||
| 372 | /** | ||
| 373 | * Creates an sRGB color with the specified red, green, blue, and alpha | ||
| 374 | * values in the range (0 - 255). | ||
| 375 | * | ||
| 376 | * @throws IllegalArgumentException if <code>r</code>, <code>g</code>, | ||
| 377 | * <code>b</code> or <code>a</code> are outside of the range | ||
| 378 | * 0 to 255, inclusive | ||
| 379 | * @param r the red component | ||
| 380 | * @param g the green component | ||
| 381 | * @param b the blue component | ||
| 382 | * @param a the alpha component | ||
| 383 | * @see #getRed | ||
| 384 | * @see #getGreen | ||
| 385 | * @see #getBlue | ||
| 386 | * @see #getAlpha | ||
| 387 | * @see #getRGB | ||
| 388 | */ | ||
| 389 | @ConstructorProperties({"red", "green", "blue", "alpha"}) | ||
| 390 | public Color(int r, int g, int b, int a) { | ||
| 391 | value = ((a & 0xFF) << 24) | | ||
| 392 | ((r & 0xFF) << 16) | | ||
| 393 | ((g & 0xFF) << 8) | | ||
| 394 | ((b & 0xFF) << 0); | ||
| 395 | testColorValueRange(r,g,b,a); | ||
| 396 | } | ||
| 397 | |||
| 398 | /** | ||
| 399 | * Creates an opaque sRGB color with the specified combined RGB value | ||
| 400 | * consisting of the red component in bits 16-23, the green component | ||
| 401 | * in bits 8-15, and the blue component in bits 0-7. The actual color | ||
| 402 | * used in rendering depends on finding the best match given the | ||
| 403 | * color space available for a particular output device. Alpha is | ||
| 404 | * defaulted to 255. | ||
| 405 | * | ||
| 406 | * @param rgb the combined RGB components | ||
| 407 | * @see java.awt.image.ColorModel#getRGBdefault | ||
| 408 | * @see #getRed | ||
| 409 | * @see #getGreen | ||
| 410 | * @see #getBlue | ||
| 411 | * @see #getRGB | ||
| 412 | */ | ||
| 413 | public Color(int rgb) { | ||
| 414 | value = 0xff000000 | rgb; | ||
| 415 | } | ||
| 416 | |||
| 417 | /** | ||
| 418 | * Creates an sRGB color with the specified combined RGBA value consisting | ||
| 419 | * of the alpha component in bits 24-31, the red component in bits 16-23, | ||
| 420 | * the green component in bits 8-15, and the blue component in bits 0-7. | ||
| 421 | * If the <code>hasalpha</code> argument is <code>false</code>, alpha | ||
| 422 | * is defaulted to 255. | ||
| 423 | * | ||
| 424 | * @param rgba the combined RGBA components | ||
| 425 | * @param hasalpha <code>true</code> if the alpha bits are valid; | ||
| 426 | * <code>false</code> otherwise | ||
| 427 | * @see java.awt.image.ColorModel#getRGBdefault | ||
| 428 | * @see #getRed | ||
| 429 | * @see #getGreen | ||
| 430 | * @see #getBlue | ||
| 431 | * @see #getAlpha | ||
| 432 | * @see #getRGB | ||
| 433 | */ | ||
| 434 | public Color(int rgba, boolean hasalpha) { | ||
| 435 | if (hasalpha) { | ||
| 436 | value = rgba; | ||
| 437 | } else { | ||
| 438 | value = 0xff000000 | rgba; | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | /** | ||
| 443 | * Creates an opaque sRGB color with the specified red, green, and blue | ||
| 444 | * values in the range (0.0 - 1.0). Alpha is defaulted to 1.0. The | ||
| 445 | * actual color used in rendering depends on finding the best | ||
| 446 | * match given the color space available for a particular output | ||
| 447 | * device. | ||
| 448 | * | ||
| 449 | * @throws IllegalArgumentException if <code>r</code>, <code>g</code> | ||
| 450 | * or <code>b</code> are outside of the range | ||
| 451 | * 0.0 to 1.0, inclusive | ||
| 452 | * @param r the red component | ||
| 453 | * @param g the green component | ||
| 454 | * @param b the blue component | ||
| 455 | * @see #getRed | ||
| 456 | * @see #getGreen | ||
| 457 | * @see #getBlue | ||
| 458 | * @see #getRGB | ||
| 459 | */ | ||
| 460 | public Color(float r, float g, float b) { | ||
| 461 | this( (int) (r*255+0.5), (int) (g*255+0.5), (int) (b*255+0.5)); | ||
| 462 | testColorValueRange(r,g,b,1.0f); | ||
| 463 | frgbvalue = new float[3]; | ||
| 464 | frgbvalue[0] = r; | ||
| 465 | frgbvalue[1] = g; | ||
| 466 | frgbvalue[2] = b; | ||
| 467 | falpha = 1.0f; | ||
| 468 | fvalue = frgbvalue; | ||
| 469 | } | ||
| 470 | |||
| 471 | /** | ||
| 472 | * Creates an sRGB color with the specified red, green, blue, and | ||
| 473 | * alpha values in the range (0.0 - 1.0). The actual color | ||
| 474 | * used in rendering depends on finding the best match given the | ||
| 475 | * color space available for a particular output device. | ||
| 476 | * @throws IllegalArgumentException if <code>r</code>, <code>g</code> | ||
| 477 | * <code>b</code> or <code>a</code> are outside of the range | ||
| 478 | * 0.0 to 1.0, inclusive | ||
| 479 | * @param r the red component | ||
| 480 | * @param g the green component | ||
| 481 | * @param b the blue component | ||
| 482 | * @param a the alpha component | ||
| 483 | * @see #getRed | ||
| 484 | * @see #getGreen | ||
| 485 | * @see #getBlue | ||
| 486 | * @see #getAlpha | ||
| 487 | * @see #getRGB | ||
| 488 | */ | ||
| 489 | public Color(float r, float g, float b, float a) { | ||
| 490 | this((int)(r*255+0.5), (int)(g*255+0.5), (int)(b*255+0.5), (int)(a*255+0.5)); | ||
| 491 | frgbvalue = new float[3]; | ||
| 492 | frgbvalue[0] = r; | ||
| 493 | frgbvalue[1] = g; | ||
| 494 | frgbvalue[2] = b; | ||
| 495 | falpha = a; | ||
| 496 | fvalue = frgbvalue; | ||
| 497 | } | ||
| 498 | |||
| 499 | /** | ||
| 500 | * Creates a color in the specified <code>ColorSpace</code> | ||
| 501 | * with the color components specified in the <code>float</code> | ||
| 502 | * array and the specified alpha. The number of components is | ||
| 503 | * determined by the type of the <code>ColorSpace</code>. For | ||
| 504 | * example, RGB requires 3 components, but CMYK requires 4 | ||
| 505 | * components. | ||
| 506 | * @param cspace the <code>ColorSpace</code> to be used to | ||
| 507 | * interpret the components | ||
| 508 | * @param components an arbitrary number of color components | ||
| 509 | * that is compatible with the <code>ColorSpace</code> | ||
| 510 | * @param alpha alpha value | ||
| 511 | * @throws IllegalArgumentException if any of the values in the | ||
| 512 | * <code>components</code> array or <code>alpha</code> is | ||
| 513 | * outside of the range 0.0 to 1.0 | ||
| 514 | * @see #getComponents | ||
| 515 | * @see #getColorComponents | ||
| 516 | */ | ||
| 517 | public Color(ColorSpace cspace, float components[], float alpha) { | ||
| 518 | boolean rangeError = false; | ||
| 519 | String badComponentString = ""; | ||
| 520 | int n = cspace.getNumComponents(); | ||
| 521 | fvalue = new float[n]; | ||
| 522 | for (int i = 0; i < n; i++) { | ||
| 523 | if (components[i] < 0.0 || components[i] > 1.0) { | ||
| 524 | rangeError = true; | ||
| 525 | badComponentString = badComponentString + "Component " + i | ||
| 526 | + " "; | ||
| 527 | } else { | ||
| 528 | fvalue[i] = components[i]; | ||
| 529 | } | ||
| 530 | } | ||
| 531 | if (alpha < 0.0 || alpha > 1.0) { | ||
| 532 | rangeError = true; | ||
| 533 | badComponentString = badComponentString + "Alpha"; | ||
| 534 | } else { | ||
| 535 | falpha = alpha; | ||
| 536 | } | ||
| 537 | if (rangeError) { | ||
| 538 | throw new IllegalArgumentException( | ||
| 539 | "Color parameter outside of expected range: " + | ||
| 540 | badComponentString); | ||
| 541 | } | ||
| 542 | frgbvalue = cspace.toRGB(fvalue); | ||
| 543 | cs = cspace; | ||
| 544 | value = ((((int)(falpha*255)) & 0xFF) << 24) | | ||
| 545 | ((((int)(frgbvalue[0]*255)) & 0xFF) << 16) | | ||
| 546 | ((((int)(frgbvalue[1]*255)) & 0xFF) << 8) | | ||
| 547 | ((((int)(frgbvalue[2]*255)) & 0xFF) << 0); | ||
| 548 | } | ||
| 549 | |||
| 550 | /** | ||
| 551 | * Returns the red component in the range 0-255 in the default sRGB | ||
| 552 | * space. | ||
| 553 | * @return the red component. | ||
| 554 | * @see #getRGB | ||
| 555 | */ | ||
| 556 | public int getRed() { | ||
| 557 | return (getRGB() >> 16) & 0xFF; | ||
| 558 | } | ||
| 559 | |||
| 560 | /** | ||
| 561 | * Returns the green component in the range 0-255 in the default sRGB | ||
| 562 | * space. | ||
| 563 | * @return the green component. | ||
| 564 | * @see #getRGB | ||
| 565 | */ | ||
| 566 | public int getGreen() { | ||
| 567 | return (getRGB() >> 8) & 0xFF; | ||
| 568 | } | ||
| 569 | |||
| 570 | /** | ||
| 571 | * Returns the blue component in the range 0-255 in the default sRGB | ||
| 572 | * space. | ||
| 573 | * @return the blue component. | ||
| 574 | * @see #getRGB | ||
| 575 | */ | ||
| 576 | public int getBlue() { | ||
| 577 | return (getRGB() >> 0) & 0xFF; | ||
| 578 | } | ||
| 579 | |||
| 580 | /** | ||
| 581 | * Returns the alpha component in the range 0-255. | ||
| 582 | * @return the alpha component. | ||
| 583 | * @see #getRGB | ||
| 584 | */ | ||
| 585 | public int getAlpha() { | ||
| 586 | return (getRGB() >> 24) & 0xff; | ||
| 587 | } | ||
| 588 | |||
| 589 | /** | ||
| 590 | * Returns the RGB value representing the color in the default sRGB | ||
| 591 | * {@link ColorModel}. | ||
| 592 | * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are | ||
| 593 | * blue). | ||
| 594 | * @return the RGB value of the color in the default sRGB | ||
| 595 | * <code>ColorModel</code>. | ||
| 596 | * @see java.awt.image.ColorModel#getRGBdefault | ||
| 597 | * @see #getRed | ||
| 598 | * @see #getGreen | ||
| 599 | * @see #getBlue | ||
| 600 | * @since JDK1.0 | ||
| 601 | */ | ||
| 602 | public int getRGB() { | ||
| 603 | return value; | ||
| 604 | } | ||
| 605 | |||
| 606 | private static final double FACTOR = 0.7; | ||
| 607 | |||
| 608 | /** | ||
| 609 | * Creates a new <code>Color</code> that is a brighter version of this | ||
| 610 | * <code>Color</code>. | ||
| 611 | * <p> | ||
| 612 | * This method applies an arbitrary scale factor to each of the three RGB | ||
| 613 | * components of this <code>Color</code> to create a brighter version | ||
| 614 | * of this <code>Color</code>. | ||
| 615 | * The {@code alpha} value is preserved. | ||
| 616 | * Although <code>brighter</code> and | ||
| 617 | * <code>darker</code> are inverse operations, the results of a | ||
| 618 | * series of invocations of these two methods might be inconsistent | ||
| 619 | * because of rounding errors. | ||
| 620 | * @return a new <code>Color</code> object that is | ||
| 621 | * a brighter version of this <code>Color</code> | ||
| 622 | * with the same {@code alpha} value. | ||
| 623 | * @see java.awt.Color#darker | ||
| 624 | * @since JDK1.0 | ||
| 625 | */ | ||
| 626 | public Color brighter() { | ||
| 627 | int r = getRed(); | ||
| 628 | int g = getGreen(); | ||
| 629 | int b = getBlue(); | ||
| 630 | int alpha = getAlpha(); | ||
| 631 | |||
| 632 | /* From 2D group: | ||
| 633 | * 1. black.brighter() should return grey | ||
| 634 | * 2. applying brighter to blue will always return blue, brighter | ||
| 635 | * 3. non pure color (non zero rgb) will eventually return white | ||
| 636 | */ | ||
| 637 | int i = (int)(1.0/(1.0-FACTOR)); | ||
| 638 | if ( r == 0 && g == 0 && b == 0) { | ||
| 639 | return new Color(i, i, i, alpha); | ||
| 640 | } | ||
| 641 | if ( r > 0 && r < i ) r = i; | ||
| 642 | if ( g > 0 && g < i ) g = i; | ||
| 643 | if ( b > 0 && b < i ) b = i; | ||
| 644 | |||
| 645 | return new Color(Math.min((int)(r/FACTOR), 255), | ||
| 646 | Math.min((int)(g/FACTOR), 255), | ||
| 647 | Math.min((int)(b/FACTOR), 255), | ||
| 648 | alpha); | ||
| 649 | } | ||
| 650 | |||
| 651 | /** | ||
| 652 | * Creates a new <code>Color</code> that is a darker version of this | ||
| 653 | * <code>Color</code>. | ||
| 654 | * <p> | ||
| 655 | * This method applies an arbitrary scale factor to each of the three RGB | ||
| 656 | * components of this <code>Color</code> to create a darker version of | ||
| 657 | * this <code>Color</code>. | ||
| 658 | * The {@code alpha} value is preserved. | ||
| 659 | * Although <code>brighter</code> and | ||
| 660 | * <code>darker</code> are inverse operations, the results of a series | ||
| 661 | * of invocations of these two methods might be inconsistent because | ||
| 662 | * of rounding errors. | ||
| 663 | * @return a new <code>Color</code> object that is | ||
| 664 | * a darker version of this <code>Color</code> | ||
| 665 | * with the same {@code alpha} value. | ||
| 666 | * @see java.awt.Color#brighter | ||
| 667 | * @since JDK1.0 | ||
| 668 | */ | ||
| 669 | public Color darker() { | ||
| 670 | return new Color(Math.max((int)(getRed() *FACTOR), 0), | ||
| 671 | Math.max((int)(getGreen()*FACTOR), 0), | ||
| 672 | Math.max((int)(getBlue() *FACTOR), 0), | ||
| 673 | getAlpha()); | ||
| 674 | } | ||
| 675 | |||
| 676 | /** | ||
| 677 | * Computes the hash code for this <code>Color</code>. | ||
| 678 | * @return a hash code value for this object. | ||
| 679 | * @since JDK1.0 | ||
| 680 | */ | ||
| 681 | public int hashCode() { | ||
| 682 | return value; | ||
| 683 | } | ||
| 684 | |||
| 685 | /** | ||
| 686 | * Determines whether another object is equal to this | ||
| 687 | * <code>Color</code>. | ||
| 688 | * <p> | ||
| 689 | * The result is <code>true</code> if and only if the argument is not | ||
| 690 | * <code>null</code> and is a <code>Color</code> object that has the same | ||
| 691 | * red, green, blue, and alpha values as this object. | ||
| 692 | * @param obj the object to test for equality with this | ||
| 693 | * <code>Color</code> | ||
| 694 | * @return <code>true</code> if the objects are the same; | ||
| 695 | * <code>false</code> otherwise. | ||
| 696 | * @since JDK1.0 | ||
| 697 | */ | ||
| 698 | public boolean equals(Object obj) { | ||
| 699 | return obj instanceof Color && ((Color)obj).getRGB() == this.getRGB(); | ||
| 700 | } | ||
| 701 | |||
| 702 | /** | ||
| 703 | * Returns a string representation of this <code>Color</code>. This | ||
| 704 | * method is intended to be used only for debugging purposes. The | ||
| 705 | * content and format of the returned string might vary between | ||
| 706 | * implementations. The returned string might be empty but cannot | ||
| 707 | * be <code>null</code>. | ||
| 708 | * | ||
| 709 | * @return a string representation of this <code>Color</code>. | ||
| 710 | */ | ||
| 711 | public String toString() { | ||
| 712 | return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]"; | ||
| 713 | } | ||
| 714 | |||
| 715 | /** | ||
| 716 | * Converts a <code>String</code> to an integer and returns the | ||
| 717 | * specified opaque <code>Color</code>. This method handles string | ||
| 718 | * formats that are used to represent octal and hexadecimal numbers. | ||
| 719 | * @param nm a <code>String</code> that represents | ||
| 720 | * an opaque color as a 24-bit integer | ||
| 721 | * @return the new <code>Color</code> object. | ||
| 722 | * @see java.lang.Integer#decode | ||
| 723 | * @exception NumberFormatException if the specified string cannot | ||
| 724 | * be interpreted as a decimal, | ||
| 725 | * octal, or hexadecimal integer. | ||
| 726 | * @since JDK1.1 | ||
| 727 | */ | ||
| 728 | public static Color decode(String nm) throws NumberFormatException { | ||
| 729 | Integer intval = Integer.decode(nm); | ||
| 730 | int i = intval.intValue(); | ||
| 731 | return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); | ||
| 732 | } | ||
| 733 | |||
| 734 | /** | ||
| 735 | * Finds a color in the system properties. | ||
| 736 | * <p> | ||
| 737 | * The argument is treated as the name of a system property to | ||
| 738 | * be obtained. The string value of this property is then interpreted | ||
| 739 | * as an integer which is then converted to a <code>Color</code> | ||
| 740 | * object. | ||
| 741 | * <p> | ||
| 742 | * If the specified property is not found or could not be parsed as | ||
| 743 | * an integer then <code>null</code> is returned. | ||
| 744 | * @param nm the name of the color property | ||
| 745 | * @return the <code>Color</code> converted from the system | ||
| 746 | * property. | ||
| 747 | * @see java.lang.System#getProperty(java.lang.String) | ||
| 748 | * @see java.lang.Integer#getInteger(java.lang.String) | ||
| 749 | * @see java.awt.Color#Color(int) | ||
| 750 | * @since JDK1.0 | ||
| 751 | */ | ||
| 752 | public static Color getColor(String nm) { | ||
| 753 | return getColor(nm, null); | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | ||
| 757 | * Finds a color in the system properties. | ||
| 758 | * <p> | ||
| 759 | * The first argument is treated as the name of a system property to | ||
| 760 | * be obtained. The string value of this property is then interpreted | ||
| 761 | * as an integer which is then converted to a <code>Color</code> | ||
| 762 | * object. | ||
| 763 | * <p> | ||
| 764 | * If the specified property is not found or cannot be parsed as | ||
| 765 | * an integer then the <code>Color</code> specified by the second | ||
| 766 | * argument is returned instead. | ||
| 767 | * @param nm the name of the color property | ||
| 768 | * @param v the default <code>Color</code> | ||
| 769 | * @return the <code>Color</code> converted from the system | ||
| 770 | * property, or the specified <code>Color</code>. | ||
| 771 | * @see java.lang.System#getProperty(java.lang.String) | ||
| 772 | * @see java.lang.Integer#getInteger(java.lang.String) | ||
| 773 | * @see java.awt.Color#Color(int) | ||
| 774 | * @since JDK1.0 | ||
| 775 | */ | ||
| 776 | public static Color getColor(String nm, Color v) { | ||
| 777 | Integer intval = Integer.getInteger(nm); | ||
| 778 | if (intval == null) { | ||
| 779 | return v; | ||
| 780 | } | ||
| 781 | int i = intval.intValue(); | ||
| 782 | return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); | ||
| 783 | } | ||
| 784 | |||
| 785 | /** | ||
| 786 | * Finds a color in the system properties. | ||
| 787 | * <p> | ||
| 788 | * The first argument is treated as the name of a system property to | ||
| 789 | * be obtained. The string value of this property is then interpreted | ||
| 790 | * as an integer which is then converted to a <code>Color</code> | ||
| 791 | * object. | ||
| 792 | * <p> | ||
| 793 | * If the specified property is not found or could not be parsed as | ||
| 794 | * an integer then the integer value <code>v</code> is used instead, | ||
| 795 | * and is converted to a <code>Color</code> object. | ||
| 796 | * @param nm the name of the color property | ||
| 797 | * @param v the default color value, as an integer | ||
| 798 | * @return the <code>Color</code> converted from the system | ||
| 799 | * property or the <code>Color</code> converted from | ||
| 800 | * the specified integer. | ||
| 801 | * @see java.lang.System#getProperty(java.lang.String) | ||
| 802 | * @see java.lang.Integer#getInteger(java.lang.String) | ||
| 803 | * @see java.awt.Color#Color(int) | ||
| 804 | * @since JDK1.0 | ||
| 805 | */ | ||
| 806 | public static Color getColor(String nm, int v) { | ||
| 807 | Integer intval = Integer.getInteger(nm); | ||
| 808 | int i = (intval != null) ? intval.intValue() : v; | ||
| 809 | return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF); | ||
| 810 | } | ||
| 811 | |||
| 812 | /** | ||
| 813 | * Converts the components of a color, as specified by the HSB | ||
| 814 | * model, to an equivalent set of values for the default RGB model. | ||
| 815 | * <p> | ||
| 816 | * The <code>saturation</code> and <code>brightness</code> components | ||
| 817 | * should be floating-point values between zero and one | ||
| 818 | * (numbers in the range 0.0-1.0). The <code>hue</code> component | ||
| 819 | * can be any floating-point number. The floor of this number is | ||
| 820 | * subtracted from it to create a fraction between 0 and 1. This | ||
| 821 | * fractional number is then multiplied by 360 to produce the hue | ||
| 822 | * angle in the HSB color model. | ||
| 823 | * <p> | ||
| 824 | * The integer that is returned by <code>HSBtoRGB</code> encodes the | ||
| 825 | * value of a color in bits 0-23 of an integer value that is the same | ||
| 826 | * format used by the method {@link #getRGB() <code>getRGB</code>}. | ||
| 827 | * This integer can be supplied as an argument to the | ||
| 828 | * <code>Color</code> constructor that takes a single integer argument. | ||
| 829 | * @param hue the hue component of the color | ||
| 830 | * @param saturation the saturation of the color | ||
| 831 | * @param brightness the brightness of the color | ||
| 832 | * @return the RGB value of the color with the indicated hue, | ||
| 833 | * saturation, and brightness. | ||
| 834 | * @see java.awt.Color#getRGB() | ||
| 835 | * @see java.awt.Color#Color(int) | ||
| 836 | * @see java.awt.image.ColorModel#getRGBdefault() | ||
| 837 | * @since JDK1.0 | ||
| 838 | */ | ||
| 839 | public static int HSBtoRGB(float hue, float saturation, float brightness) { | ||
| 840 | int r = 0, g = 0, b = 0; | ||
| 841 | if (saturation == 0) { | ||
| 842 | r = g = b = (int) (brightness * 255.0f + 0.5f); | ||
| 843 | } else { | ||
| 844 | float h = (hue - (float)Math.floor(hue)) * 6.0f; | ||
| 845 | float f = h - (float)java.lang.Math.floor(h); | ||
| 846 | float p = brightness * (1.0f - saturation); | ||
| 847 | float q = brightness * (1.0f - saturation * f); | ||
| 848 | float t = brightness * (1.0f - (saturation * (1.0f - f))); | ||
| 849 | switch ((int) h) { | ||
| 850 | case 0: | ||
| 851 | r = (int) (brightness * 255.0f + 0.5f); | ||
| 852 | g = (int) (t * 255.0f + 0.5f); | ||
| 853 | b = (int) (p * 255.0f + 0.5f); | ||
| 854 | break; | ||
| 855 | case 1: | ||
| 856 | r = (int) (q * 255.0f + 0.5f); | ||
| 857 | g = (int) (brightness * 255.0f + 0.5f); | ||
| 858 | b = (int) (p * 255.0f + 0.5f); | ||
| 859 | break; | ||
| 860 | case 2: | ||
| 861 | r = (int) (p * 255.0f + 0.5f); | ||
| 862 | g = (int) (brightness * 255.0f + 0.5f); | ||
| 863 | b = (int) (t * 255.0f + 0.5f); | ||
| 864 | break; | ||
| 865 | case 3: | ||
| 866 | r = (int) (p * 255.0f + 0.5f); | ||
| 867 | g = (int) (q * 255.0f + 0.5f); | ||
| 868 | b = (int) (brightness * 255.0f + 0.5f); | ||
| 869 | break; | ||
| 870 | case 4: | ||
| 871 | r = (int) (t * 255.0f + 0.5f); | ||
| 872 | g = (int) (p * 255.0f + 0.5f); | ||
| 873 | b = (int) (brightness * 255.0f + 0.5f); | ||
| 874 | break; | ||
| 875 | case 5: | ||
| 876 | r = (int) (brightness * 255.0f + 0.5f); | ||
| 877 | g = (int) (p * 255.0f + 0.5f); | ||
| 878 | b = (int) (q * 255.0f + 0.5f); | ||
| 879 | break; | ||
| 880 | } | ||
| 881 | } | ||
| 882 | return 0xff000000 | (r << 16) | (g << 8) | (b << 0); | ||
| 883 | } | ||
| 884 | |||
| 885 | /** | ||
| 886 | * Converts the components of a color, as specified by the default RGB | ||
| 887 | * model, to an equivalent set of values for hue, saturation, and | ||
| 888 | * brightness that are the three components of the HSB model. | ||
| 889 | * <p> | ||
| 890 | * If the <code>hsbvals</code> argument is <code>null</code>, then a | ||
| 891 | * new array is allocated to return the result. Otherwise, the method | ||
| 892 | * returns the array <code>hsbvals</code>, with the values put into | ||
| 893 | * that array. | ||
| 894 | * @param r the red component of the color | ||
| 895 | * @param g the green component of the color | ||
| 896 | * @param b the blue component of the color | ||
| 897 | * @param hsbvals the array used to return the | ||
| 898 | * three HSB values, or <code>null</code> | ||
| 899 | * @return an array of three elements containing the hue, saturation, | ||
| 900 | * and brightness (in that order), of the color with | ||
| 901 | * the indicated red, green, and blue components. | ||
| 902 | * @see java.awt.Color#getRGB() | ||
| 903 | * @see java.awt.Color#Color(int) | ||
| 904 | * @see java.awt.image.ColorModel#getRGBdefault() | ||
| 905 | * @since JDK1.0 | ||
| 906 | */ | ||
| 907 | public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) { | ||
| 908 | float hue, saturation, brightness; | ||
| 909 | if (hsbvals == null) { | ||
| 910 | hsbvals = new float[3]; | ||
| 911 | } | ||
| 912 | int cmax = (r > g) ? r : g; | ||
| 913 | if (b > cmax) cmax = b; | ||
| 914 | int cmin = (r < g) ? r : g; | ||
| 915 | if (b < cmin) cmin = b; | ||
| 916 | |||
| 917 | brightness = ((float) cmax) / 255.0f; | ||
| 918 | if (cmax != 0) | ||
| 919 | saturation = ((float) (cmax - cmin)) / ((float) cmax); | ||
| 920 | else | ||
| 921 | saturation = 0; | ||
| 922 | if (saturation == 0) | ||
| 923 | hue = 0; | ||
| 924 | else { | ||
| 925 | float redc = ((float) (cmax - r)) / ((float) (cmax - cmin)); | ||
| 926 | float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin)); | ||
| 927 | float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin)); | ||
| 928 | if (r == cmax) | ||
| 929 | hue = bluec - greenc; | ||
| 930 | else if (g == cmax) | ||
| 931 | hue = 2.0f + redc - bluec; | ||
| 932 | else | ||
| 933 | hue = 4.0f + greenc - redc; | ||
| 934 | hue = hue / 6.0f; | ||
| 935 | if (hue < 0) | ||
| 936 | hue = hue + 1.0f; | ||
| 937 | } | ||
| 938 | hsbvals[0] = hue; | ||
| 939 | hsbvals[1] = saturation; | ||
| 940 | hsbvals[2] = brightness; | ||
| 941 | return hsbvals; | ||
| 942 | } | ||
| 943 | |||
| 944 | /** | ||
| 945 | * Creates a <code>Color</code> object based on the specified values | ||
| 946 | * for the HSB color model. | ||
| 947 | * <p> | ||
| 948 | * The <code>s</code> and <code>b</code> components should be | ||
| 949 | * floating-point values between zero and one | ||
| 950 | * (numbers in the range 0.0-1.0). The <code>h</code> component | ||
| 951 | * can be any floating-point number. The floor of this number is | ||
| 952 | * subtracted from it to create a fraction between 0 and 1. This | ||
| 953 | * fractional number is then multiplied by 360 to produce the hue | ||
| 954 | * angle in the HSB color model. | ||
| 955 | * @param h the hue component | ||
| 956 | * @param s the saturation of the color | ||
| 957 | * @param b the brightness of the color | ||
| 958 | * @return a <code>Color</code> object with the specified hue, | ||
| 959 | * saturation, and brightness. | ||
| 960 | * @since JDK1.0 | ||
| 961 | */ | ||
| 962 | public static Color getHSBColor(float h, float s, float b) { | ||
| 963 | return new Color(HSBtoRGB(h, s, b)); | ||
| 964 | } | ||
| 965 | |||
| 966 | /** | ||
| 967 | * Returns a <code>float</code> array containing the color and alpha | ||
| 968 | * components of the <code>Color</code>, as represented in the default | ||
| 969 | * sRGB color space. | ||
| 970 | * If <code>compArray</code> is <code>null</code>, an array of length | ||
| 971 | * 4 is created for the return value. Otherwise, | ||
| 972 | * <code>compArray</code> must have length 4 or greater, | ||
| 973 | * and it is filled in with the components and returned. | ||
| 974 | * @param compArray an array that this method fills with | ||
| 975 | * color and alpha components and returns | ||
| 976 | * @return the RGBA components in a <code>float</code> array. | ||
| 977 | */ | ||
| 978 | public float[] getRGBComponents(float[] compArray) { | ||
| 979 | float[] f; | ||
| 980 | if (compArray == null) { | ||
| 981 | f = new float[4]; | ||
| 982 | } else { | ||
| 983 | f = compArray; | ||
| 984 | } | ||
| 985 | if (frgbvalue == null) { | ||
| 986 | f[0] = ((float)getRed())/255f; | ||
| 987 | f[1] = ((float)getGreen())/255f; | ||
| 988 | f[2] = ((float)getBlue())/255f; | ||
| 989 | f[3] = ((float)getAlpha())/255f; | ||
| 990 | } else { | ||
| 991 | f[0] = frgbvalue[0]; | ||
| 992 | f[1] = frgbvalue[1]; | ||
| 993 | f[2] = frgbvalue[2]; | ||
| 994 | f[3] = falpha; | ||
| 995 | } | ||
| 996 | return f; | ||
| 997 | } | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * Returns a <code>float</code> array containing only the color | ||
| 1001 | * components of the <code>Color</code>, in the default sRGB color | ||
| 1002 | * space. If <code>compArray</code> is <code>null</code>, an array of | ||
| 1003 | * length 3 is created for the return value. Otherwise, | ||
| 1004 | * <code>compArray</code> must have length 3 or greater, and it is | ||
| 1005 | * filled in with the components and returned. | ||
| 1006 | * @param compArray an array that this method fills with color | ||
| 1007 | * components and returns | ||
| 1008 | * @return the RGB components in a <code>float</code> array. | ||
| 1009 | */ | ||
| 1010 | public float[] getRGBColorComponents(float[] compArray) { | ||
| 1011 | float[] f; | ||
| 1012 | if (compArray == null) { | ||
| 1013 | f = new float[3]; | ||
| 1014 | } else { | ||
| 1015 | f = compArray; | ||
| 1016 | } | ||
| 1017 | if (frgbvalue == null) { | ||
| 1018 | f[0] = ((float)getRed())/255f; | ||
| 1019 | f[1] = ((float)getGreen())/255f; | ||
| 1020 | f[2] = ((float)getBlue())/255f; | ||
| 1021 | } else { | ||
| 1022 | f[0] = frgbvalue[0]; | ||
| 1023 | f[1] = frgbvalue[1]; | ||
| 1024 | f[2] = frgbvalue[2]; | ||
| 1025 | } | ||
| 1026 | return f; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | /** | ||
| 1030 | * Returns a <code>float</code> array containing the color and alpha | ||
| 1031 | * components of the <code>Color</code>, in the | ||
| 1032 | * <code>ColorSpace</code> of the <code>Color</code>. | ||
| 1033 | * If <code>compArray</code> is <code>null</code>, an array with | ||
| 1034 | * length equal to the number of components in the associated | ||
| 1035 | * <code>ColorSpace</code> plus one is created for | ||
| 1036 | * the return value. Otherwise, <code>compArray</code> must have at | ||
| 1037 | * least this length and it is filled in with the components and | ||
| 1038 | * returned. | ||
| 1039 | * @param compArray an array that this method fills with the color and | ||
| 1040 | * alpha components of this <code>Color</code> in its | ||
| 1041 | * <code>ColorSpace</code> and returns | ||
| 1042 | * @return the color and alpha components in a <code>float</code> | ||
| 1043 | * array. | ||
| 1044 | */ | ||
| 1045 | public float[] getComponents(float[] compArray) { | ||
| 1046 | if (fvalue == null) | ||
| 1047 | return getRGBComponents(compArray); | ||
| 1048 | float[] f; | ||
| 1049 | int n = fvalue.length; | ||
| 1050 | if (compArray == null) { | ||
| 1051 | f = new float[n + 1]; | ||
| 1052 | } else { | ||
| 1053 | f = compArray; | ||
| 1054 | } | ||
| 1055 | for (int i = 0; i < n; i++) { | ||
| 1056 | f[i] = fvalue[i]; | ||
| 1057 | } | ||
| 1058 | f[n] = falpha; | ||
| 1059 | return f; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | /** | ||
| 1063 | * Returns a <code>float</code> array containing only the color | ||
| 1064 | * components of the <code>Color</code>, in the | ||
| 1065 | * <code>ColorSpace</code> of the <code>Color</code>. | ||
| 1066 | * If <code>compArray</code> is <code>null</code>, an array with | ||
| 1067 | * length equal to the number of components in the associated | ||
| 1068 | * <code>ColorSpace</code> is created for | ||
| 1069 | * the return value. Otherwise, <code>compArray</code> must have at | ||
| 1070 | * least this length and it is filled in with the components and | ||
| 1071 | * returned. | ||
| 1072 | * @param compArray an array that this method fills with the color | ||
| 1073 | * components of this <code>Color</code> in its | ||
| 1074 | * <code>ColorSpace</code> and returns | ||
| 1075 | * @return the color components in a <code>float</code> array. | ||
| 1076 | */ | ||
| 1077 | public float[] getColorComponents(float[] compArray) { | ||
| 1078 | if (fvalue == null) | ||
| 1079 | return getRGBColorComponents(compArray); | ||
| 1080 | float[] f; | ||
| 1081 | int n = fvalue.length; | ||
| 1082 | if (compArray == null) { | ||
| 1083 | f = new float[n]; | ||
| 1084 | } else { | ||
| 1085 | f = compArray; | ||
| 1086 | } | ||
| 1087 | for (int i = 0; i < n; i++) { | ||
| 1088 | f[i] = fvalue[i]; | ||
| 1089 | } | ||
| 1090 | return f; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /** | ||
| 1094 | * Returns a <code>float</code> array containing the color and alpha | ||
| 1095 | * components of the <code>Color</code>, in the | ||
| 1096 | * <code>ColorSpace</code> specified by the <code>cspace</code> | ||
| 1097 | * parameter. If <code>compArray</code> is <code>null</code>, an | ||
| 1098 | * array with length equal to the number of components in | ||
| 1099 | * <code>cspace</code> plus one is created for the return value. | ||
| 1100 | * Otherwise, <code>compArray</code> must have at least this | ||
| 1101 | * length, and it is filled in with the components and returned. | ||
| 1102 | * @param cspace a specified <code>ColorSpace</code> | ||
| 1103 | * @param compArray an array that this method fills with the | ||
| 1104 | * color and alpha components of this <code>Color</code> in | ||
| 1105 | * the specified <code>ColorSpace</code> and returns | ||
| 1106 | * @return the color and alpha components in a <code>float</code> | ||
| 1107 | * array. | ||
| 1108 | */ | ||
| 1109 | public float[] getComponents(ColorSpace cspace, float[] compArray) { | ||
| 1110 | if (cs == null) { | ||
| 1111 | cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); | ||
| 1112 | } | ||
| 1113 | float f[]; | ||
| 1114 | if (fvalue == null) { | ||
| 1115 | f = new float[3]; | ||
| 1116 | f[0] = ((float)getRed())/255f; | ||
| 1117 | f[1] = ((float)getGreen())/255f; | ||
| 1118 | f[2] = ((float)getBlue())/255f; | ||
| 1119 | } else { | ||
| 1120 | f = fvalue; | ||
| 1121 | } | ||
| 1122 | float tmp[] = cs.toCIEXYZ(f); | ||
| 1123 | float tmpout[] = cspace.fromCIEXYZ(tmp); | ||
| 1124 | if (compArray == null) { | ||
| 1125 | compArray = new float[tmpout.length + 1]; | ||
| 1126 | } | ||
| 1127 | for (int i = 0 ; i < tmpout.length ; i++) { | ||
| 1128 | compArray[i] = tmpout[i]; | ||
| 1129 | } | ||
| 1130 | if (fvalue == null) { | ||
| 1131 | compArray[tmpout.length] = ((float)getAlpha())/255f; | ||
| 1132 | } else { | ||
| 1133 | compArray[tmpout.length] = falpha; | ||
| 1134 | } | ||
| 1135 | return compArray; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /** | ||
| 1139 | * Returns a <code>float</code> array containing only the color | ||
| 1140 | * components of the <code>Color</code> in the | ||
| 1141 | * <code>ColorSpace</code> specified by the <code>cspace</code> | ||
| 1142 | * parameter. If <code>compArray</code> is <code>null</code>, an array | ||
| 1143 | * with length equal to the number of components in | ||
| 1144 | * <code>cspace</code> is created for the return value. Otherwise, | ||
| 1145 | * <code>compArray</code> must have at least this length, and it is | ||
| 1146 | * filled in with the components and returned. | ||
| 1147 | * @param cspace a specified <code>ColorSpace</code> | ||
| 1148 | * @param compArray an array that this method fills with the color | ||
| 1149 | * components of this <code>Color</code> in the specified | ||
| 1150 | * <code>ColorSpace</code> | ||
| 1151 | * @return the color components in a <code>float</code> array. | ||
| 1152 | */ | ||
| 1153 | public float[] getColorComponents(ColorSpace cspace, float[] compArray) { | ||
| 1154 | if (cs == null) { | ||
| 1155 | cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); | ||
| 1156 | } | ||
| 1157 | float f[]; | ||
| 1158 | if (fvalue == null) { | ||
| 1159 | f = new float[3]; | ||
| 1160 | f[0] = ((float)getRed())/255f; | ||
| 1161 | f[1] = ((float)getGreen())/255f; | ||
| 1162 | f[2] = ((float)getBlue())/255f; | ||
| 1163 | } else { | ||
| 1164 | f = fvalue; | ||
| 1165 | } | ||
| 1166 | float tmp[] = cs.toCIEXYZ(f); | ||
| 1167 | float tmpout[] = cspace.fromCIEXYZ(tmp); | ||
| 1168 | if (compArray == null) { | ||
| 1169 | return tmpout; | ||
| 1170 | } | ||
| 1171 | for (int i = 0 ; i < tmpout.length ; i++) { | ||
| 1172 | compArray[i] = tmpout[i]; | ||
| 1173 | } | ||
| 1174 | return compArray; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | /** | ||
| 1178 | * Returns the <code>ColorSpace</code> of this <code>Color</code>. | ||
| 1179 | * @return this <code>Color</code> object's <code>ColorSpace</code>. | ||
| 1180 | */ | ||
| 1181 | public ColorSpace getColorSpace() { | ||
| 1182 | if (cs == null) { | ||
| 1183 | cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); | ||
| 1184 | } | ||
| 1185 | return cs; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | /** | ||
| 1189 | * Creates and returns a {@link PaintContext} used to | ||
| 1190 | * generate a solid color field pattern. | ||
| 1191 | * See the {@link Paint#createContext specification} of the | ||
| 1192 | * method in the {@link Paint} interface for information | ||
| 1193 | * on null parameter handling. | ||
| 1194 | * | ||
| 1195 | * @param cm the preferred {@link ColorModel} which represents the most convenient | ||
| 1196 | * format for the caller to receive the pixel data, or {@code null} | ||
| 1197 | * if there is no preference. | ||
| 1198 | * @param r the device space bounding box | ||
| 1199 | * of the graphics primitive being rendered. | ||
| 1200 | * @param r2d the user space bounding box | ||
| 1201 | * of the graphics primitive being rendered. | ||
| 1202 | * @param xform the {@link AffineTransform} from user | ||
| 1203 | * space into device space. | ||
| 1204 | * @param hints the set of hints that the context object can use to | ||
| 1205 | * choose between rendering alternatives. | ||
| 1206 | * @return the {@code PaintContext} for | ||
| 1207 | * generating color patterns. | ||
| 1208 | * @see Paint | ||
| 1209 | * @see PaintContext | ||
| 1210 | * @see ColorModel | ||
| 1211 | * @see Rectangle | ||
| 1212 | * @see Rectangle2D | ||
| 1213 | * @see AffineTransform | ||
| 1214 | * @see RenderingHints | ||
| 1215 | */ | ||
| 1216 | public synchronized PaintContext createContext(ColorModel cm, Rectangle r, | ||
| 1217 | Rectangle2D r2d, | ||
| 1218 | AffineTransform xform, | ||
| 1219 | RenderingHints hints) { | ||
| 1220 | return new ColorPaintContext(getRGB(), cm); | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | /** | ||
| 1224 | * Returns the transparency mode for this <code>Color</code>. This is | ||
| 1225 | * required to implement the <code>Paint</code> interface. | ||
| 1226 | * @return this <code>Color</code> object's transparency mode. | ||
| 1227 | * @see Paint | ||
| 1228 | * @see Transparency | ||
| 1229 | * @see #createContext | ||
| 1230 | */ | ||
| 1231 | public int getTransparency() { | ||
| 1232 | int alpha = getAlpha(); | ||
| 1233 | if (alpha == 0xff) { | ||
| 1234 | return Transparency.OPAQUE; | ||
| 1235 | } | ||
| 1236 | else if (alpha == 0) { | ||
| 1237 | return Transparency.BITMASK; | ||
| 1238 | } | ||
| 1239 | else { | ||
| 1240 | return Transparency.TRANSLUCENT; | ||
| 1241 | } | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | } | ||
Binary file not shown.
| @@ -0,0 +1,83 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2007, 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 | |||
| 27 | |||
| 28 | package java.awt; | ||
| 29 | |||
| 30 | import java.awt.image.ColorModel; | ||
| 31 | import java.awt.image.Raster; | ||
| 32 | import java.awt.image.WritableRaster; | ||
| 33 | import sun.awt.image.IntegerComponentRaster; | ||
| 34 | import java.util.Arrays; | ||
| 35 | |||
| 36 | class ColorPaintContext implements PaintContext { | ||
| 37 | int color; | ||
| 38 | WritableRaster savedTile; | ||
| 39 | |||
| 40 | protected ColorPaintContext(int color, ColorModel cm) { | ||
| 41 | this.color = color; | ||
| 42 | } | ||
| 43 | |||
| 44 | public void dispose() { | ||
| 45 | } | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Returns the RGB value representing the color in the default sRGB | ||
| 49 | * {@link ColorModel}. | ||
| 50 | * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are | ||
| 51 | * blue). | ||
| 52 | * @return the RGB value of the color in the default sRGB | ||
| 53 | * <code>ColorModel</code>. | ||
| 54 | * @see java.awt.image.ColorModel#getRGBdefault | ||
| 55 | * @see #getRed | ||
| 56 | * @see #getGreen | ||
| 57 | * @see #getBlue | ||
| 58 | */ | ||
| 59 | int getRGB() { | ||
| 60 | return color; | ||
| 61 | } | ||
| 62 | |||
| 63 | public ColorModel getColorModel() { | ||
| 64 | return ColorModel.getRGBdefault(); | ||
| 65 | } | ||
| 66 | |||
| 67 | public synchronized Raster getRaster(int x, int y, int w, int h) { | ||
| 68 | WritableRaster t = savedTile; | ||
| 69 | |||
| 70 | if (t == null || w > t.getWidth() || h > t.getHeight()) { | ||
| 71 | t = getColorModel().createCompatibleWritableRaster(w, h); | ||
| 72 | IntegerComponentRaster icr = (IntegerComponentRaster) t; | ||
| 73 | Arrays.fill(icr.getDataStorage(), color); | ||
| 74 | // Note - markDirty is probably unnecessary since icr is brand new | ||
| 75 | icr.markDirty(); | ||
| 76 | if (w <= 64 && h <= 64) { | ||
| 77 | savedTile = t; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | return t; | ||
| 82 | } | ||
| 83 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,10099 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2011, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.io.PrintStream; | ||
| 28 | import java.io.PrintWriter; | ||
| 29 | import java.util.Vector; | ||
| 30 | import java.util.Locale; | ||
| 31 | import java.util.EventListener; | ||
| 32 | import java.util.Iterator; | ||
| 33 | import java.util.HashSet; | ||
| 34 | import java.util.Map; | ||
| 35 | import java.util.Set; | ||
| 36 | import java.util.Collections; | ||
| 37 | import java.awt.peer.ComponentPeer; | ||
| 38 | import java.awt.peer.ContainerPeer; | ||
| 39 | import java.awt.peer.LightweightPeer; | ||
| 40 | import java.awt.image.BufferStrategy; | ||
| 41 | import java.awt.image.ImageObserver; | ||
| 42 | import java.awt.image.ImageProducer; | ||
| 43 | import java.awt.image.ColorModel; | ||
| 44 | import java.awt.image.VolatileImage; | ||
| 45 | import java.awt.event.*; | ||
| 46 | import java.io.Serializable; | ||
| 47 | import java.io.ObjectOutputStream; | ||
| 48 | import java.io.ObjectInputStream; | ||
| 49 | import java.io.IOException; | ||
| 50 | import java.beans.PropertyChangeListener; | ||
| 51 | import java.beans.PropertyChangeSupport; | ||
| 52 | import java.beans.Transient; | ||
| 53 | import java.awt.event.InputMethodListener; | ||
| 54 | import java.awt.event.InputMethodEvent; | ||
| 55 | import java.awt.im.InputContext; | ||
| 56 | import java.awt.im.InputMethodRequests; | ||
| 57 | import java.awt.dnd.DropTarget; | ||
| 58 | import java.lang.reflect.InvocationTargetException; | ||
| 59 | import java.lang.reflect.Method; | ||
| 60 | import java.security.AccessController; | ||
| 61 | import java.security.PrivilegedAction; | ||
| 62 | import java.security.AccessControlContext; | ||
| 63 | import javax.accessibility.*; | ||
| 64 | import java.applet.Applet; | ||
| 65 | |||
| 66 | import sun.security.action.GetPropertyAction; | ||
| 67 | import sun.awt.AppContext; | ||
| 68 | import sun.awt.AWTAccessor; | ||
| 69 | import sun.awt.ConstrainableGraphics; | ||
| 70 | import sun.awt.SubRegionShowable; | ||
| 71 | import sun.awt.SunToolkit; | ||
| 72 | import sun.awt.WindowClosingListener; | ||
| 73 | import sun.awt.CausedFocusEvent; | ||
| 74 | import sun.awt.EmbeddedFrame; | ||
| 75 | import sun.awt.dnd.SunDropTargetEvent; | ||
| 76 | import sun.awt.im.CompositionArea; | ||
| 77 | import sun.font.FontManager; | ||
| 78 | import sun.font.FontManagerFactory; | ||
| 79 | import sun.font.SunFontManager; | ||
| 80 | import sun.java2d.SunGraphics2D; | ||
| 81 | import sun.java2d.pipe.Region; | ||
| 82 | import sun.awt.image.VSyncedBSManager; | ||
| 83 | import sun.java2d.pipe.hw.ExtendedBufferCapabilities; | ||
| 84 | import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*; | ||
| 85 | import sun.awt.RequestFocusController; | ||
| 86 | import sun.java2d.SunGraphicsEnvironment; | ||
| 87 | import sun.util.logging.PlatformLogger; | ||
| 88 | |||
| 89 | /** | ||
| 90 | * A <em>component</em> is an object having a graphical representation | ||
| 91 | * that can be displayed on the screen and that can interact with the | ||
| 92 | * user. Examples of components are the buttons, checkboxes, and scrollbars | ||
| 93 | * of a typical graphical user interface. <p> | ||
| 94 | * The <code>Component</code> class is the abstract superclass of | ||
| 95 | * the nonmenu-related Abstract Window Toolkit components. Class | ||
| 96 | * <code>Component</code> can also be extended directly to create a | ||
| 97 | * lightweight component. A lightweight component is a component that is | ||
| 98 | * not associated with a native window. On the contrary, a heavyweight | ||
| 99 | * component is associated with a native window. The {@link #isLightweight()} | ||
| 100 | * method may be used to distinguish between the two kinds of the components. | ||
| 101 | * <p> | ||
| 102 | * Lightweight and heavyweight components may be mixed in a single component | ||
| 103 | * hierarchy. However, for correct operating of such a mixed hierarchy of | ||
| 104 | * components, the whole hierarchy must be valid. When the hierarchy gets | ||
| 105 | * invalidated, like after changing the bounds of components, or | ||
| 106 | * adding/removing components to/from containers, the whole hierarchy must be | ||
| 107 | * validated afterwards by means of the {@link Container#validate()} method | ||
| 108 | * invoked on the top-most invalid container of the hierarchy. | ||
| 109 | * <p> | ||
| 110 | * <h3>Serialization</h3> | ||
| 111 | * It is important to note that only AWT listeners which conform | ||
| 112 | * to the <code>Serializable</code> protocol will be saved when | ||
| 113 | * the object is stored. If an AWT object has listeners that | ||
| 114 | * aren't marked serializable, they will be dropped at | ||
| 115 | * <code>writeObject</code> time. Developers will need, as always, | ||
| 116 | * to consider the implications of making an object serializable. | ||
| 117 | * One situation to watch out for is this: | ||
| 118 | * <pre> | ||
| 119 | * import java.awt.*; | ||
| 120 | * import java.awt.event.*; | ||
| 121 | * import java.io.Serializable; | ||
| 122 | * | ||
| 123 | * class MyApp implements ActionListener, Serializable | ||
| 124 | * { | ||
| 125 | * BigObjectThatShouldNotBeSerializedWithAButton bigOne; | ||
| 126 | * Button aButton = new Button(); | ||
| 127 | * | ||
| 128 | * MyApp() | ||
| 129 | * { | ||
| 130 | * // Oops, now aButton has a listener with a reference | ||
| 131 | * // to bigOne! | ||
| 132 | * aButton.addActionListener(this); | ||
| 133 | * } | ||
| 134 | * | ||
| 135 | * public void actionPerformed(ActionEvent e) | ||
| 136 | * { | ||
| 137 | * System.out.println("Hello There"); | ||
| 138 | * } | ||
| 139 | * } | ||
| 140 | * </pre> | ||
| 141 | * In this example, serializing <code>aButton</code> by itself | ||
| 142 | * will cause <code>MyApp</code> and everything it refers to | ||
| 143 | * to be serialized as well. The problem is that the listener | ||
| 144 | * is serializable by coincidence, not by design. To separate | ||
| 145 | * the decisions about <code>MyApp</code> and the | ||
| 146 | * <code>ActionListener</code> being serializable one can use a | ||
| 147 | * nested class, as in the following example: | ||
| 148 | * <pre> | ||
| 149 | * import java.awt.*; | ||
| 150 | * import java.awt.event.*; | ||
| 151 | * import java.io.Serializable; | ||
| 152 | * | ||
| 153 | * class MyApp java.io.Serializable | ||
| 154 | * { | ||
| 155 | * BigObjectThatShouldNotBeSerializedWithAButton bigOne; | ||
| 156 | * Button aButton = new Button(); | ||
| 157 | * | ||
| 158 | * static class MyActionListener implements ActionListener | ||
| 159 | * { | ||
| 160 | * public void actionPerformed(ActionEvent e) | ||
| 161 | * { | ||
| 162 | * System.out.println("Hello There"); | ||
| 163 | * } | ||
| 164 | * } | ||
| 165 | * | ||
| 166 | * MyApp() | ||
| 167 | * { | ||
| 168 | * aButton.addActionListener(new MyActionListener()); | ||
| 169 | * } | ||
| 170 | * } | ||
| 171 | * </pre> | ||
| 172 | * <p> | ||
| 173 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 174 | * by AWT and Swing, including information on how to write the most | ||
| 175 | * efficient painting code, see | ||
| 176 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 177 | * <p> | ||
| 178 | * For details on the focus subsystem, see | ||
| 179 | * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html"> | ||
| 180 | * How to Use the Focus Subsystem</a>, | ||
| 181 | * a section in <em>The Java Tutorial</em>, and the | ||
| 182 | * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> | ||
| 183 | * for more information. | ||
| 184 | * | ||
| 185 | * @author Arthur van Hoff | ||
| 186 | * @author Sami Shaio | ||
| 187 | */ | ||
| 188 | public abstract class Component implements ImageObserver, MenuContainer, | ||
| 189 | Serializable | ||
| 190 | { | ||
| 191 | |||
| 192 | private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Component"); | ||
| 193 | private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Component"); | ||
| 194 | private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.Component"); | ||
| 195 | private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Component"); | ||
| 196 | |||
| 197 | /** | ||
| 198 | * The peer of the component. The peer implements the component's | ||
| 199 | * behavior. The peer is set when the <code>Component</code> is | ||
| 200 | * added to a container that also is a peer. | ||
| 201 | * @see #addNotify | ||
| 202 | * @see #removeNotify | ||
| 203 | */ | ||
| 204 | transient ComponentPeer peer; | ||
| 205 | |||
| 206 | /** | ||
| 207 | * The parent of the object. It may be <code>null</code> | ||
| 208 | * for top-level components. | ||
| 209 | * @see #getParent | ||
| 210 | */ | ||
| 211 | transient Container parent; | ||
| 212 | |||
| 213 | /** | ||
| 214 | * The <code>AppContext</code> of the component. Applets/Plugin may | ||
| 215 | * change the AppContext. | ||
| 216 | */ | ||
| 217 | transient AppContext appContext; | ||
| 218 | |||
| 219 | /** | ||
| 220 | * The x position of the component in the parent's coordinate system. | ||
| 221 | * | ||
| 222 | * @serial | ||
| 223 | * @see #getLocation | ||
| 224 | */ | ||
| 225 | int x; | ||
| 226 | |||
| 227 | /** | ||
| 228 | * The y position of the component in the parent's coordinate system. | ||
| 229 | * | ||
| 230 | * @serial | ||
| 231 | * @see #getLocation | ||
| 232 | */ | ||
| 233 | int y; | ||
| 234 | |||
| 235 | /** | ||
| 236 | * The width of the component. | ||
| 237 | * | ||
| 238 | * @serial | ||
| 239 | * @see #getSize | ||
| 240 | */ | ||
| 241 | int width; | ||
| 242 | |||
| 243 | /** | ||
| 244 | * The height of the component. | ||
| 245 | * | ||
| 246 | * @serial | ||
| 247 | * @see #getSize | ||
| 248 | */ | ||
| 249 | int height; | ||
| 250 | |||
| 251 | /** | ||
| 252 | * The foreground color for this component. | ||
| 253 | * <code>foreground</code> can be <code>null</code>. | ||
| 254 | * | ||
| 255 | * @serial | ||
| 256 | * @see #getForeground | ||
| 257 | * @see #setForeground | ||
| 258 | */ | ||
| 259 | Color foreground; | ||
| 260 | |||
| 261 | /** | ||
| 262 | * The background color for this component. | ||
| 263 | * <code>background</code> can be <code>null</code>. | ||
| 264 | * | ||
| 265 | * @serial | ||
| 266 | * @see #getBackground | ||
| 267 | * @see #setBackground | ||
| 268 | */ | ||
| 269 | Color background; | ||
| 270 | |||
| 271 | /** | ||
| 272 | * The font used by this component. | ||
| 273 | * The <code>font</code> can be <code>null</code>. | ||
| 274 | * | ||
| 275 | * @serial | ||
| 276 | * @see #getFont | ||
| 277 | * @see #setFont | ||
| 278 | */ | ||
| 279 | Font font; | ||
| 280 | |||
| 281 | /** | ||
| 282 | * The font which the peer is currently using. | ||
| 283 | * (<code>null</code> if no peer exists.) | ||
| 284 | */ | ||
| 285 | Font peerFont; | ||
| 286 | |||
| 287 | /** | ||
| 288 | * The cursor displayed when pointer is over this component. | ||
| 289 | * This value can be <code>null</code>. | ||
| 290 | * | ||
| 291 | * @serial | ||
| 292 | * @see #getCursor | ||
| 293 | * @see #setCursor | ||
| 294 | */ | ||
| 295 | Cursor cursor; | ||
| 296 | |||
| 297 | /** | ||
| 298 | * The locale for the component. | ||
| 299 | * | ||
| 300 | * @serial | ||
| 301 | * @see #getLocale | ||
| 302 | * @see #setLocale | ||
| 303 | */ | ||
| 304 | Locale locale; | ||
| 305 | |||
| 306 | /** | ||
| 307 | * A reference to a <code>GraphicsConfiguration</code> object | ||
| 308 | * used to describe the characteristics of a graphics | ||
| 309 | * destination. | ||
| 310 | * This value can be <code>null</code>. | ||
| 311 | * | ||
| 312 | * @since 1.3 | ||
| 313 | * @serial | ||
| 314 | * @see GraphicsConfiguration | ||
| 315 | * @see #getGraphicsConfiguration | ||
| 316 | */ | ||
| 317 | private transient GraphicsConfiguration graphicsConfig = null; | ||
| 318 | |||
| 319 | /** | ||
| 320 | * A reference to a <code>BufferStrategy</code> object | ||
| 321 | * used to manipulate the buffers on this component. | ||
| 322 | * | ||
| 323 | * @since 1.4 | ||
| 324 | * @see java.awt.image.BufferStrategy | ||
| 325 | * @see #getBufferStrategy() | ||
| 326 | */ | ||
| 327 | transient BufferStrategy bufferStrategy = null; | ||
| 328 | |||
| 329 | /** | ||
| 330 | * True when the object should ignore all repaint events. | ||
| 331 | * | ||
| 332 | * @since 1.4 | ||
| 333 | * @serial | ||
| 334 | * @see #setIgnoreRepaint | ||
| 335 | * @see #getIgnoreRepaint | ||
| 336 | */ | ||
| 337 | boolean ignoreRepaint = false; | ||
| 338 | |||
| 339 | /** | ||
| 340 | * True when the object is visible. An object that is not | ||
| 341 | * visible is not drawn on the screen. | ||
| 342 | * | ||
| 343 | * @serial | ||
| 344 | * @see #isVisible | ||
| 345 | * @see #setVisible | ||
| 346 | */ | ||
| 347 | boolean visible = true; | ||
| 348 | |||
| 349 | /** | ||
| 350 | * True when the object is enabled. An object that is not | ||
| 351 | * enabled does not interact with the user. | ||
| 352 | * | ||
| 353 | * @serial | ||
| 354 | * @see #isEnabled | ||
| 355 | * @see #setEnabled | ||
| 356 | */ | ||
| 357 | boolean enabled = true; | ||
| 358 | |||
| 359 | /** | ||
| 360 | * True when the object is valid. An invalid object needs to | ||
| 361 | * be layed out. This flag is set to false when the object | ||
| 362 | * size is changed. | ||
| 363 | * | ||
| 364 | * @serial | ||
| 365 | * @see #isValid | ||
| 366 | * @see #validate | ||
| 367 | * @see #invalidate | ||
| 368 | */ | ||
| 369 | private volatile boolean valid = false; | ||
| 370 | |||
| 371 | /** | ||
| 372 | * The <code>DropTarget</code> associated with this component. | ||
| 373 | * | ||
| 374 | * @since 1.2 | ||
| 375 | * @serial | ||
| 376 | * @see #setDropTarget | ||
| 377 | * @see #getDropTarget | ||
| 378 | */ | ||
| 379 | DropTarget dropTarget; | ||
| 380 | |||
| 381 | /** | ||
| 382 | * @serial | ||
| 383 | * @see #add | ||
| 384 | */ | ||
| 385 | Vector popups; | ||
| 386 | |||
| 387 | /** | ||
| 388 | * A component's name. | ||
| 389 | * This field can be <code>null</code>. | ||
| 390 | * | ||
| 391 | * @serial | ||
| 392 | * @see #getName | ||
| 393 | * @see #setName(String) | ||
| 394 | */ | ||
| 395 | private String name; | ||
| 396 | |||
| 397 | /** | ||
| 398 | * A bool to determine whether the name has | ||
| 399 | * been set explicitly. <code>nameExplicitlySet</code> will | ||
| 400 | * be false if the name has not been set and | ||
| 401 | * true if it has. | ||
| 402 | * | ||
| 403 | * @serial | ||
| 404 | * @see #getName | ||
| 405 | * @see #setName(String) | ||
| 406 | */ | ||
| 407 | private boolean nameExplicitlySet = false; | ||
| 408 | |||
| 409 | /** | ||
| 410 | * Indicates whether this Component can be focused. | ||
| 411 | * | ||
| 412 | * @serial | ||
| 413 | * @see #setFocusable | ||
| 414 | * @see #isFocusable | ||
| 415 | * @since 1.4 | ||
| 416 | */ | ||
| 417 | private boolean focusable = true; | ||
| 418 | |||
| 419 | private static final int FOCUS_TRAVERSABLE_UNKNOWN = 0; | ||
| 420 | private static final int FOCUS_TRAVERSABLE_DEFAULT = 1; | ||
| 421 | private static final int FOCUS_TRAVERSABLE_SET = 2; | ||
| 422 | |||
| 423 | /** | ||
| 424 | * Tracks whether this Component is relying on default focus travesability. | ||
| 425 | * | ||
| 426 | * @serial | ||
| 427 | * @since 1.4 | ||
| 428 | */ | ||
| 429 | private int isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN; | ||
| 430 | |||
| 431 | /** | ||
| 432 | * The focus traversal keys. These keys will generate focus traversal | ||
| 433 | * behavior for Components for which focus traversal keys are enabled. If a | ||
| 434 | * value of null is specified for a traversal key, this Component inherits | ||
| 435 | * that traversal key from its parent. If all ancestors of this Component | ||
| 436 | * have null specified for that traversal key, then the current | ||
| 437 | * KeyboardFocusManager's default traversal key is used. | ||
| 438 | * | ||
| 439 | * @serial | ||
| 440 | * @see #setFocusTraversalKeys | ||
| 441 | * @see #getFocusTraversalKeys | ||
| 442 | * @since 1.4 | ||
| 443 | */ | ||
| 444 | Set[] focusTraversalKeys; | ||
| 445 | |||
| 446 | private static final String[] focusTraversalKeyPropertyNames = { | ||
| 447 | "forwardFocusTraversalKeys", | ||
| 448 | "backwardFocusTraversalKeys", | ||
| 449 | "upCycleFocusTraversalKeys", | ||
| 450 | "downCycleFocusTraversalKeys" | ||
| 451 | }; | ||
| 452 | |||
| 453 | /** | ||
| 454 | * Indicates whether focus traversal keys are enabled for this Component. | ||
| 455 | * Components for which focus traversal keys are disabled receive key | ||
| 456 | * events for focus traversal keys. Components for which focus traversal | ||
| 457 | * keys are enabled do not see these events; instead, the events are | ||
| 458 | * automatically converted to traversal operations. | ||
| 459 | * | ||
| 460 | * @serial | ||
| 461 | * @see #setFocusTraversalKeysEnabled | ||
| 462 | * @see #getFocusTraversalKeysEnabled | ||
| 463 | * @since 1.4 | ||
| 464 | */ | ||
| 465 | private boolean focusTraversalKeysEnabled = true; | ||
| 466 | |||
| 467 | /** | ||
| 468 | * The locking object for AWT component-tree and layout operations. | ||
| 469 | * | ||
| 470 | * @see #getTreeLock | ||
| 471 | */ | ||
| 472 | static final Object LOCK = new AWTTreeLock(); | ||
| 473 | static class AWTTreeLock {} | ||
| 474 | |||
| 475 | /* | ||
| 476 | * The component's AccessControlContext. | ||
| 477 | */ | ||
| 478 | private transient volatile AccessControlContext acc = | ||
| 479 | AccessController.getContext(); | ||
| 480 | |||
| 481 | /** | ||
| 482 | * Minimum size. | ||
| 483 | * (This field perhaps should have been transient). | ||
| 484 | * | ||
| 485 | * @serial | ||
| 486 | */ | ||
| 487 | Dimension minSize; | ||
| 488 | |||
| 489 | /** | ||
| 490 | * Whether or not setMinimumSize has been invoked with a non-null value. | ||
| 491 | */ | ||
| 492 | boolean minSizeSet; | ||
| 493 | |||
| 494 | /** | ||
| 495 | * Preferred size. | ||
| 496 | * (This field perhaps should have been transient). | ||
| 497 | * | ||
| 498 | * @serial | ||
| 499 | */ | ||
| 500 | Dimension prefSize; | ||
| 501 | |||
| 502 | /** | ||
| 503 | * Whether or not setPreferredSize has been invoked with a non-null value. | ||
| 504 | */ | ||
| 505 | boolean prefSizeSet; | ||
| 506 | |||
| 507 | /** | ||
| 508 | * Maximum size | ||
| 509 | * | ||
| 510 | * @serial | ||
| 511 | */ | ||
| 512 | Dimension maxSize; | ||
| 513 | |||
| 514 | /** | ||
| 515 | * Whether or not setMaximumSize has been invoked with a non-null value. | ||
| 516 | */ | ||
| 517 | boolean maxSizeSet; | ||
| 518 | |||
| 519 | /** | ||
| 520 | * The orientation for this component. | ||
| 521 | * @see #getComponentOrientation | ||
| 522 | * @see #setComponentOrientation | ||
| 523 | */ | ||
| 524 | transient ComponentOrientation componentOrientation | ||
| 525 | = ComponentOrientation.UNKNOWN; | ||
| 526 | |||
| 527 | /** | ||
| 528 | * <code>newEventsOnly</code> will be true if the event is | ||
| 529 | * one of the event types enabled for the component. | ||
| 530 | * It will then allow for normal processing to | ||
| 531 | * continue. If it is false the event is passed | ||
| 532 | * to the component's parent and up the ancestor | ||
| 533 | * tree until the event has been consumed. | ||
| 534 | * | ||
| 535 | * @serial | ||
| 536 | * @see #dispatchEvent | ||
| 537 | */ | ||
| 538 | boolean newEventsOnly = false; | ||
| 539 | transient ComponentListener componentListener; | ||
| 540 | transient FocusListener focusListener; | ||
| 541 | transient HierarchyListener hierarchyListener; | ||
| 542 | transient HierarchyBoundsListener hierarchyBoundsListener; | ||
| 543 | transient KeyListener keyListener; | ||
| 544 | transient MouseListener mouseListener; | ||
| 545 | transient MouseMotionListener mouseMotionListener; | ||
| 546 | transient MouseWheelListener mouseWheelListener; | ||
| 547 | transient InputMethodListener inputMethodListener; | ||
| 548 | |||
| 549 | transient RuntimeException windowClosingException = null; | ||
| 550 | |||
| 551 | /** Internal, constants for serialization */ | ||
| 552 | final static String actionListenerK = "actionL"; | ||
| 553 | final static String adjustmentListenerK = "adjustmentL"; | ||
| 554 | final static String componentListenerK = "componentL"; | ||
| 555 | final static String containerListenerK = "containerL"; | ||
| 556 | final static String focusListenerK = "focusL"; | ||
| 557 | final static String itemListenerK = "itemL"; | ||
| 558 | final static String keyListenerK = "keyL"; | ||
| 559 | final static String mouseListenerK = "mouseL"; | ||
| 560 | final static String mouseMotionListenerK = "mouseMotionL"; | ||
| 561 | final static String mouseWheelListenerK = "mouseWheelL"; | ||
| 562 | final static String textListenerK = "textL"; | ||
| 563 | final static String ownedWindowK = "ownedL"; | ||
| 564 | final static String windowListenerK = "windowL"; | ||
| 565 | final static String inputMethodListenerK = "inputMethodL"; | ||
| 566 | final static String hierarchyListenerK = "hierarchyL"; | ||
| 567 | final static String hierarchyBoundsListenerK = "hierarchyBoundsL"; | ||
| 568 | final static String windowStateListenerK = "windowStateL"; | ||
| 569 | final static String windowFocusListenerK = "windowFocusL"; | ||
| 570 | |||
| 571 | /** | ||
| 572 | * The <code>eventMask</code> is ONLY set by subclasses via | ||
| 573 | * <code>enableEvents</code>. | ||
| 574 | * The mask should NOT be set when listeners are registered | ||
| 575 | * so that we can distinguish the difference between when | ||
| 576 | * listeners request events and subclasses request them. | ||
| 577 | * One bit is used to indicate whether input methods are | ||
| 578 | * enabled; this bit is set by <code>enableInputMethods</code> and is | ||
| 579 | * on by default. | ||
| 580 | * | ||
| 581 | * @serial | ||
| 582 | * @see #enableInputMethods | ||
| 583 | * @see AWTEvent | ||
| 584 | */ | ||
| 585 | long eventMask = AWTEvent.INPUT_METHODS_ENABLED_MASK; | ||
| 586 | |||
| 587 | /** | ||
| 588 | * Static properties for incremental drawing. | ||
| 589 | * @see #imageUpdate | ||
| 590 | */ | ||
| 591 | static boolean isInc; | ||
| 592 | static int incRate; | ||
| 593 | static { | ||
| 594 | /* ensure that the necessary native libraries are loaded */ | ||
| 595 | Toolkit.loadLibraries(); | ||
| 596 | /* initialize JNI field and method ids */ | ||
| 597 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 598 | initIDs(); | ||
| 599 | } | ||
| 600 | |||
| 601 | String s = (String) java.security.AccessController.doPrivileged( | ||
| 602 | new GetPropertyAction("awt.image.incrementaldraw")); | ||
| 603 | isInc = (s == null || s.equals("true")); | ||
| 604 | |||
| 605 | s = (String) java.security.AccessController.doPrivileged( | ||
| 606 | new GetPropertyAction("awt.image.redrawrate")); | ||
| 607 | incRate = (s != null) ? Integer.parseInt(s) : 100; | ||
| 608 | } | ||
| 609 | |||
| 610 | /** | ||
| 611 | * Ease-of-use constant for <code>getAlignmentY()</code>. | ||
| 612 | * Specifies an alignment to the top of the component. | ||
| 613 | * @see #getAlignmentY | ||
| 614 | */ | ||
| 615 | public static final float TOP_ALIGNMENT = 0.0f; | ||
| 616 | |||
| 617 | /** | ||
| 618 | * Ease-of-use constant for <code>getAlignmentY</code> and | ||
| 619 | * <code>getAlignmentX</code>. Specifies an alignment to | ||
| 620 | * the center of the component | ||
| 621 | * @see #getAlignmentX | ||
| 622 | * @see #getAlignmentY | ||
| 623 | */ | ||
| 624 | public static final float CENTER_ALIGNMENT = 0.5f; | ||
| 625 | |||
| 626 | /** | ||
| 627 | * Ease-of-use constant for <code>getAlignmentY</code>. | ||
| 628 | * Specifies an alignment to the bottom of the component. | ||
| 629 | * @see #getAlignmentY | ||
| 630 | */ | ||
| 631 | public static final float BOTTOM_ALIGNMENT = 1.0f; | ||
| 632 | |||
| 633 | /** | ||
| 634 | * Ease-of-use constant for <code>getAlignmentX</code>. | ||
| 635 | * Specifies an alignment to the left side of the component. | ||
| 636 | * @see #getAlignmentX | ||
| 637 | */ | ||
| 638 | public static final float LEFT_ALIGNMENT = 0.0f; | ||
| 639 | |||
| 640 | /** | ||
| 641 | * Ease-of-use constant for <code>getAlignmentX</code>. | ||
| 642 | * Specifies an alignment to the right side of the component. | ||
| 643 | * @see #getAlignmentX | ||
| 644 | */ | ||
| 645 | public static final float RIGHT_ALIGNMENT = 1.0f; | ||
| 646 | |||
| 647 | /* | ||
| 648 | * JDK 1.1 serialVersionUID | ||
| 649 | */ | ||
| 650 | private static final long serialVersionUID = -7644114512714619750L; | ||
| 651 | |||
| 652 | /** | ||
| 653 | * If any <code>PropertyChangeListeners</code> have been registered, | ||
| 654 | * the <code>changeSupport</code> field describes them. | ||
| 655 | * | ||
| 656 | * @serial | ||
| 657 | * @since 1.2 | ||
| 658 | * @see #addPropertyChangeListener | ||
| 659 | * @see #removePropertyChangeListener | ||
| 660 | * @see #firePropertyChange | ||
| 661 | */ | ||
| 662 | private PropertyChangeSupport changeSupport; | ||
| 663 | |||
| 664 | /* | ||
| 665 | * In some cases using "this" as an object to synchronize by | ||
| 666 | * can lead to a deadlock if client code also uses synchronization | ||
| 667 | * by a component object. For every such situation revealed we should | ||
| 668 | * consider possibility of replacing "this" with the package private | ||
| 669 | * objectLock object introduced below. So far there're 2 issues known: | ||
| 670 | * - CR 6708322 (the getName/setName methods); | ||
| 671 | * - CR 6608764 (the PropertyChangeListener machinery). | ||
| 672 | * | ||
| 673 | * Note: this field is considered final, though readObject() prohibits | ||
| 674 | * initializing final fields. | ||
| 675 | */ | ||
| 676 | private transient Object objectLock = new Object(); | ||
| 677 | Object getObjectLock() { | ||
| 678 | return objectLock; | ||
| 679 | } | ||
| 680 | |||
| 681 | /* | ||
| 682 | * Returns the acc this component was constructed with. | ||
| 683 | */ | ||
| 684 | final AccessControlContext getAccessControlContext() { | ||
| 685 | if (acc == null) { | ||
| 686 | throw new SecurityException("Component is missing AccessControlContext"); | ||
| 687 | } | ||
| 688 | return acc; | ||
| 689 | } | ||
| 690 | |||
| 691 | boolean isPacked = false; | ||
| 692 | |||
| 693 | /** | ||
| 694 | * Pseudoparameter for direct Geometry API (setLocation, setBounds setSize | ||
| 695 | * to signal setBounds what's changing. Should be used under TreeLock. | ||
| 696 | * This is only needed due to the inability to change the cross-calling | ||
| 697 | * order of public and deprecated methods. | ||
| 698 | */ | ||
| 699 | private int boundsOp = ComponentPeer.DEFAULT_OPERATION; | ||
| 700 | |||
| 701 | /** | ||
| 702 | * Enumeration of the common ways the baseline of a component can | ||
| 703 | * change as the size changes. The baseline resize behavior is | ||
| 704 | * primarily for layout managers that need to know how the | ||
| 705 | * position of the baseline changes as the component size changes. | ||
| 706 | * In general the baseline resize behavior will be valid for sizes | ||
| 707 | * greater than or equal to the minimum size (the actual minimum | ||
| 708 | * size; not a developer specified minimum size). For sizes | ||
| 709 | * smaller than the minimum size the baseline may change in a way | ||
| 710 | * other than the baseline resize behavior indicates. Similarly, | ||
| 711 | * as the size approaches <code>Integer.MAX_VALUE</code> and/or | ||
| 712 | * <code>Short.MAX_VALUE</code> the baseline may change in a way | ||
| 713 | * other than the baseline resize behavior indicates. | ||
| 714 | * | ||
| 715 | * @see #getBaselineResizeBehavior | ||
| 716 | * @see #getBaseline(int,int) | ||
| 717 | * @since 1.6 | ||
| 718 | */ | ||
| 719 | public enum BaselineResizeBehavior { | ||
| 720 | /** | ||
| 721 | * Indicates the baseline remains fixed relative to the | ||
| 722 | * y-origin. That is, <code>getBaseline</code> returns | ||
| 723 | * the same value regardless of the height or width. For example, a | ||
| 724 | * <code>JLabel</code> containing non-empty text with a | ||
| 725 | * vertical alignment of <code>TOP</code> should have a | ||
| 726 | * baseline type of <code>CONSTANT_ASCENT</code>. | ||
| 727 | */ | ||
| 728 | CONSTANT_ASCENT, | ||
| 729 | |||
| 730 | /** | ||
| 731 | * Indicates the baseline remains fixed relative to the height | ||
| 732 | * and does not change as the width is varied. That is, for | ||
| 733 | * any height H the difference between H and | ||
| 734 | * <code>getBaseline(w, H)</code> is the same. For example, a | ||
| 735 | * <code>JLabel</code> containing non-empty text with a | ||
| 736 | * vertical alignment of <code>BOTTOM</code> should have a | ||
| 737 | * baseline type of <code>CONSTANT_DESCENT</code>. | ||
| 738 | */ | ||
| 739 | CONSTANT_DESCENT, | ||
| 740 | |||
| 741 | /** | ||
| 742 | * Indicates the baseline remains a fixed distance from | ||
| 743 | * the center of the component. That is, for any height H the | ||
| 744 | * difference between <code>getBaseline(w, H)</code> and | ||
| 745 | * <code>H / 2</code> is the same (plus or minus one depending upon | ||
| 746 | * rounding error). | ||
| 747 | * <p> | ||
| 748 | * Because of possible rounding errors it is recommended | ||
| 749 | * you ask for the baseline with two consecutive heights and use | ||
| 750 | * the return value to determine if you need to pad calculations | ||
| 751 | * by 1. The following shows how to calculate the baseline for | ||
| 752 | * any height: | ||
| 753 | * <pre> | ||
| 754 | * Dimension preferredSize = component.getPreferredSize(); | ||
| 755 | * int baseline = getBaseline(preferredSize.width, | ||
| 756 | * preferredSize.height); | ||
| 757 | * int nextBaseline = getBaseline(preferredSize.width, | ||
| 758 | * preferredSize.height + 1); | ||
| 759 | * // Amount to add to height when calculating where baseline | ||
| 760 | * // lands for a particular height: | ||
| 761 | * int padding = 0; | ||
| 762 | * // Where the baseline is relative to the mid point | ||
| 763 | * int baselineOffset = baseline - height / 2; | ||
| 764 | * if (preferredSize.height % 2 == 0 && | ||
| 765 | * baseline != nextBaseline) { | ||
| 766 | * padding = 1; | ||
| 767 | * } | ||
| 768 | * else if (preferredSize.height % 2 == 1 && | ||
| 769 | * baseline == nextBaseline) { | ||
| 770 | * baselineOffset--; | ||
| 771 | * padding = 1; | ||
| 772 | * } | ||
| 773 | * // The following calculates where the baseline lands for | ||
| 774 | * // the height z: | ||
| 775 | * int calculatedBaseline = (z + padding) / 2 + baselineOffset; | ||
| 776 | * </pre> | ||
| 777 | */ | ||
| 778 | CENTER_OFFSET, | ||
| 779 | |||
| 780 | /** | ||
| 781 | * Indicates the baseline resize behavior can not be expressed using | ||
| 782 | * any of the other constants. This may also indicate the baseline | ||
| 783 | * varies with the width of the component. This is also returned | ||
| 784 | * by components that do not have a baseline. | ||
| 785 | */ | ||
| 786 | OTHER | ||
| 787 | } | ||
| 788 | |||
| 789 | /* | ||
| 790 | * The shape set with the applyCompoundShape() method. It uncludes the result | ||
| 791 | * of the HW/LW mixing related shape computation. It may also include | ||
| 792 | * the user-specified shape of the component. | ||
| 793 | * The 'null' value means the component has normal shape (or has no shape at all) | ||
| 794 | * and applyCompoundShape() will skip the following shape identical to normal. | ||
| 795 | */ | ||
| 796 | private transient Region compoundShape = null; | ||
| 797 | |||
| 798 | /* | ||
| 799 | * Represents the shape of this lightweight component to be cut out from | ||
| 800 | * heavyweight components should they intersect. Possible values: | ||
| 801 | * 1. null - consider the shape rectangular | ||
| 802 | * 2. EMPTY_REGION - nothing gets cut out (children still get cut out) | ||
| 803 | * 3. non-empty - this shape gets cut out. | ||
| 804 | */ | ||
| 805 | private transient Region mixingCutoutRegion = null; | ||
| 806 | |||
| 807 | /* | ||
| 808 | * Indicates whether addNotify() is complete | ||
| 809 | * (i.e. the peer is created). | ||
| 810 | */ | ||
| 811 | private transient boolean isAddNotifyComplete = false; | ||
| 812 | |||
| 813 | /** | ||
| 814 | * Should only be used in subclass getBounds to check that part of bounds | ||
| 815 | * is actualy changing | ||
| 816 | */ | ||
| 817 | int getBoundsOp() { | ||
| 818 | assert Thread.holdsLock(getTreeLock()); | ||
| 819 | return boundsOp; | ||
| 820 | } | ||
| 821 | |||
| 822 | void setBoundsOp(int op) { | ||
| 823 | assert Thread.holdsLock(getTreeLock()); | ||
| 824 | if (op == ComponentPeer.RESET_OPERATION) { | ||
| 825 | boundsOp = ComponentPeer.DEFAULT_OPERATION; | ||
| 826 | } else | ||
| 827 | if (boundsOp == ComponentPeer.DEFAULT_OPERATION) { | ||
| 828 | boundsOp = op; | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | // Whether this Component has had the background erase flag | ||
| 833 | // specified via SunToolkit.disableBackgroundErase(). This is | ||
| 834 | // needed in order to make this function work on X11 platforms, | ||
| 835 | // where currently there is no chance to interpose on the creation | ||
| 836 | // of the peer and therefore the call to XSetBackground. | ||
| 837 | transient boolean backgroundEraseDisabled; | ||
| 838 | |||
| 839 | static { | ||
| 840 | AWTAccessor.setComponentAccessor(new AWTAccessor.ComponentAccessor() { | ||
| 841 | public void setBackgroundEraseDisabled(Component comp, boolean disabled) { | ||
| 842 | comp.backgroundEraseDisabled = disabled; | ||
| 843 | } | ||
| 844 | public boolean getBackgroundEraseDisabled(Component comp) { | ||
| 845 | return comp.backgroundEraseDisabled; | ||
| 846 | } | ||
| 847 | public Rectangle getBounds(Component comp) { | ||
| 848 | return new Rectangle(comp.x, comp.y, comp.width, comp.height); | ||
| 849 | } | ||
| 850 | public void setMixingCutoutShape(Component comp, Shape shape) { | ||
| 851 | Region region = shape == null ? null : | ||
| 852 | Region.getInstance(shape, null); | ||
| 853 | |||
| 854 | synchronized (comp.getTreeLock()) { | ||
| 855 | boolean needShowing = false; | ||
| 856 | boolean needHiding = false; | ||
| 857 | |||
| 858 | if (!comp.isNonOpaqueForMixing()) { | ||
| 859 | needHiding = true; | ||
| 860 | } | ||
| 861 | |||
| 862 | comp.mixingCutoutRegion = region; | ||
| 863 | |||
| 864 | if (!comp.isNonOpaqueForMixing()) { | ||
| 865 | needShowing = true; | ||
| 866 | } | ||
| 867 | |||
| 868 | if (comp.isMixingNeeded()) { | ||
| 869 | if (needHiding) { | ||
| 870 | comp.mixOnHiding(comp.isLightweight()); | ||
| 871 | } | ||
| 872 | if (needShowing) { | ||
| 873 | comp.mixOnShowing(); | ||
| 874 | } | ||
| 875 | } | ||
| 876 | } | ||
| 877 | } | ||
| 878 | |||
| 879 | public void setGraphicsConfiguration(Component comp, | ||
| 880 | GraphicsConfiguration gc) | ||
| 881 | { | ||
| 882 | comp.setGraphicsConfiguration(gc); | ||
| 883 | } | ||
| 884 | public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) { | ||
| 885 | return comp.requestFocus(cause); | ||
| 886 | } | ||
| 887 | public boolean canBeFocusOwner(Component comp) { | ||
| 888 | return comp.canBeFocusOwner(); | ||
| 889 | } | ||
| 890 | |||
| 891 | public boolean isVisible(Component comp) { | ||
| 892 | return comp.isVisible_NoClientCode(); | ||
| 893 | } | ||
| 894 | public void setRequestFocusController | ||
| 895 | (RequestFocusController requestController) | ||
| 896 | { | ||
| 897 | Component.setRequestFocusController(requestController); | ||
| 898 | } | ||
| 899 | public AppContext getAppContext(Component comp) { | ||
| 900 | return comp.appContext; | ||
| 901 | } | ||
| 902 | public void setAppContext(Component comp, AppContext appContext) { | ||
| 903 | comp.appContext = appContext; | ||
| 904 | } | ||
| 905 | public Container getParent(Component comp) { | ||
| 906 | return comp.getParent_NoClientCode(); | ||
| 907 | } | ||
| 908 | public void setParent(Component comp, Container parent) { | ||
| 909 | comp.parent = parent; | ||
| 910 | } | ||
| 911 | public void setSize(Component comp, int width, int height) { | ||
| 912 | comp.width = width; | ||
| 913 | comp.height = height; | ||
| 914 | } | ||
| 915 | public Point getLocation(Component comp) { | ||
| 916 | return comp.location_NoClientCode(); | ||
| 917 | } | ||
| 918 | public void setLocation(Component comp, int x, int y) { | ||
| 919 | comp.x = x; | ||
| 920 | comp.y = y; | ||
| 921 | } | ||
| 922 | public boolean isEnabled(Component comp) { | ||
| 923 | return comp.isEnabledImpl(); | ||
| 924 | } | ||
| 925 | public boolean isDisplayable(Component comp) { | ||
| 926 | return comp.peer != null; | ||
| 927 | } | ||
| 928 | public Cursor getCursor(Component comp) { | ||
| 929 | return comp.getCursor_NoClientCode(); | ||
| 930 | } | ||
| 931 | public ComponentPeer getPeer(Component comp) { | ||
| 932 | return comp.peer; | ||
| 933 | } | ||
| 934 | public void setPeer(Component comp, ComponentPeer peer) { | ||
| 935 | comp.peer = peer; | ||
| 936 | } | ||
| 937 | public boolean isLightweight(Component comp) { | ||
| 938 | return (comp.peer instanceof LightweightPeer); | ||
| 939 | } | ||
| 940 | public boolean getIgnoreRepaint(Component comp) { | ||
| 941 | return comp.ignoreRepaint; | ||
| 942 | } | ||
| 943 | public int getWidth(Component comp) { | ||
| 944 | return comp.width; | ||
| 945 | } | ||
| 946 | public int getHeight(Component comp) { | ||
| 947 | return comp.height; | ||
| 948 | } | ||
| 949 | public int getX(Component comp) { | ||
| 950 | return comp.x; | ||
| 951 | } | ||
| 952 | public int getY(Component comp) { | ||
| 953 | return comp.y; | ||
| 954 | } | ||
| 955 | public Color getForeground(Component comp) { | ||
| 956 | return comp.foreground; | ||
| 957 | } | ||
| 958 | public Color getBackground(Component comp) { | ||
| 959 | return comp.background; | ||
| 960 | } | ||
| 961 | public void setBackground(Component comp, Color background) { | ||
| 962 | comp.background = background; | ||
| 963 | } | ||
| 964 | public Font getFont(Component comp) { | ||
| 965 | return comp.getFont_NoClientCode(); | ||
| 966 | } | ||
| 967 | public void processEvent(Component comp, AWTEvent e) { | ||
| 968 | comp.processEvent(e); | ||
| 969 | } | ||
| 970 | |||
| 971 | public AccessControlContext getAccessControlContext(Component comp) { | ||
| 972 | return comp.getAccessControlContext(); | ||
| 973 | } | ||
| 974 | }); | ||
| 975 | } | ||
| 976 | |||
| 977 | /** | ||
| 978 | * Constructs a new component. Class <code>Component</code> can be | ||
| 979 | * extended directly to create a lightweight component that does not | ||
| 980 | * utilize an opaque native window. A lightweight component must be | ||
| 981 | * hosted by a native container somewhere higher up in the component | ||
| 982 | * tree (for example, by a <code>Frame</code> object). | ||
| 983 | */ | ||
| 984 | protected Component() { | ||
| 985 | appContext = AppContext.getAppContext(); | ||
| 986 | } | ||
| 987 | |||
| 988 | void initializeFocusTraversalKeys() { | ||
| 989 | focusTraversalKeys = new Set[3]; | ||
| 990 | } | ||
| 991 | |||
| 992 | /** | ||
| 993 | * Constructs a name for this component. Called by <code>getName</code> | ||
| 994 | * when the name is <code>null</code>. | ||
| 995 | */ | ||
| 996 | String constructComponentName() { | ||
| 997 | return null; // For strict compliance with prior platform versions, a Component | ||
| 998 | // that doesn't set its name should return null from | ||
| 999 | // getName() | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /** | ||
| 1003 | * Gets the name of the component. | ||
| 1004 | * @return this component's name | ||
| 1005 | * @see #setName | ||
| 1006 | * @since JDK1.1 | ||
| 1007 | */ | ||
| 1008 | public String getName() { | ||
| 1009 | if (name == null && !nameExplicitlySet) { | ||
| 1010 | synchronized(getObjectLock()) { | ||
| 1011 | if (name == null && !nameExplicitlySet) | ||
| 1012 | name = constructComponentName(); | ||
| 1013 | } | ||
| 1014 | } | ||
| 1015 | return name; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | /** | ||
| 1019 | * Sets the name of the component to the specified string. | ||
| 1020 | * @param name the string that is to be this | ||
| 1021 | * component's name | ||
| 1022 | * @see #getName | ||
| 1023 | * @since JDK1.1 | ||
| 1024 | */ | ||
| 1025 | public void setName(String name) { | ||
| 1026 | String oldName; | ||
| 1027 | synchronized(getObjectLock()) { | ||
| 1028 | oldName = this.name; | ||
| 1029 | this.name = name; | ||
| 1030 | nameExplicitlySet = true; | ||
| 1031 | } | ||
| 1032 | firePropertyChange("name", oldName, name); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /** | ||
| 1036 | * Gets the parent of this component. | ||
| 1037 | * @return the parent container of this component | ||
| 1038 | * @since JDK1.0 | ||
| 1039 | */ | ||
| 1040 | public Container getParent() { | ||
| 1041 | return getParent_NoClientCode(); | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | // NOTE: This method may be called by privileged threads. | ||
| 1045 | // This functionality is implemented in a package-private method | ||
| 1046 | // to insure that it cannot be overridden by client subclasses. | ||
| 1047 | // DO NOT INVOKE CLIENT CODE ON THIS THREAD! | ||
| 1048 | final Container getParent_NoClientCode() { | ||
| 1049 | return parent; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | // This method is overriden in the Window class to return null, | ||
| 1053 | // because the parent field of the Window object contains | ||
| 1054 | // the owner of the window, not its parent. | ||
| 1055 | Container getContainer() { | ||
| 1056 | return getParent(); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | /** | ||
| 1060 | * @deprecated As of JDK version 1.1, | ||
| 1061 | * programs should not directly manipulate peers; | ||
| 1062 | * replaced by <code>boolean isDisplayable()</code>. | ||
| 1063 | */ | ||
| 1064 | @Deprecated | ||
| 1065 | public ComponentPeer getPeer() { | ||
| 1066 | return peer; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | /** | ||
| 1070 | * Associate a <code>DropTarget</code> with this component. | ||
| 1071 | * The <code>Component</code> will receive drops only if it | ||
| 1072 | * is enabled. | ||
| 1073 | * | ||
| 1074 | * @see #isEnabled | ||
| 1075 | * @param dt The DropTarget | ||
| 1076 | */ | ||
| 1077 | |||
| 1078 | public synchronized void setDropTarget(DropTarget dt) { | ||
| 1079 | if (dt == dropTarget || (dropTarget != null && dropTarget.equals(dt))) | ||
| 1080 | return; | ||
| 1081 | |||
| 1082 | DropTarget old; | ||
| 1083 | |||
| 1084 | if ((old = dropTarget) != null) { | ||
| 1085 | if (peer != null) dropTarget.removeNotify(peer); | ||
| 1086 | |||
| 1087 | DropTarget t = dropTarget; | ||
| 1088 | |||
| 1089 | dropTarget = null; | ||
| 1090 | |||
| 1091 | try { | ||
| 1092 | t.setComponent(null); | ||
| 1093 | } catch (IllegalArgumentException iae) { | ||
| 1094 | // ignore it. | ||
| 1095 | } | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | // if we have a new one, and we have a peer, add it! | ||
| 1099 | |||
| 1100 | if ((dropTarget = dt) != null) { | ||
| 1101 | try { | ||
| 1102 | dropTarget.setComponent(this); | ||
| 1103 | if (peer != null) dropTarget.addNotify(peer); | ||
| 1104 | } catch (IllegalArgumentException iae) { | ||
| 1105 | if (old != null) { | ||
| 1106 | try { | ||
| 1107 | old.setComponent(this); | ||
| 1108 | if (peer != null) dropTarget.addNotify(peer); | ||
| 1109 | } catch (IllegalArgumentException iae1) { | ||
| 1110 | // ignore it! | ||
| 1111 | } | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | /** | ||
| 1118 | * Gets the <code>DropTarget</code> associated with this | ||
| 1119 | * <code>Component</code>. | ||
| 1120 | */ | ||
| 1121 | |||
| 1122 | public synchronized DropTarget getDropTarget() { return dropTarget; } | ||
| 1123 | |||
| 1124 | /** | ||
| 1125 | * Gets the <code>GraphicsConfiguration</code> associated with this | ||
| 1126 | * <code>Component</code>. | ||
| 1127 | * If the <code>Component</code> has not been assigned a specific | ||
| 1128 | * <code>GraphicsConfiguration</code>, | ||
| 1129 | * the <code>GraphicsConfiguration</code> of the | ||
| 1130 | * <code>Component</code> object's top-level container is | ||
| 1131 | * returned. | ||
| 1132 | * If the <code>Component</code> has been created, but not yet added | ||
| 1133 | * to a <code>Container</code>, this method returns <code>null</code>. | ||
| 1134 | * | ||
| 1135 | * @return the <code>GraphicsConfiguration</code> used by this | ||
| 1136 | * <code>Component</code> or <code>null</code> | ||
| 1137 | * @since 1.3 | ||
| 1138 | */ | ||
| 1139 | public GraphicsConfiguration getGraphicsConfiguration() { | ||
| 1140 | synchronized(getTreeLock()) { | ||
| 1141 | return getGraphicsConfiguration_NoClientCode(); | ||
| 1142 | } | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { | ||
| 1146 | return graphicsConfig; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | void setGraphicsConfiguration(GraphicsConfiguration gc) { | ||
| 1150 | synchronized(getTreeLock()) { | ||
| 1151 | if (updateGraphicsData(gc)) { | ||
| 1152 | removeNotify(); | ||
| 1153 | addNotify(); | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | boolean updateGraphicsData(GraphicsConfiguration gc) { | ||
| 1159 | checkTreeLock(); | ||
| 1160 | |||
| 1161 | graphicsConfig = gc; | ||
| 1162 | |||
| 1163 | ComponentPeer peer = getPeer(); | ||
| 1164 | if (peer != null) { | ||
| 1165 | return peer.updateGraphicsData(gc); | ||
| 1166 | } | ||
| 1167 | return false; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | /** | ||
| 1171 | * Checks that this component's <code>GraphicsDevice</code> | ||
| 1172 | * <code>idString</code> matches the string argument. | ||
| 1173 | */ | ||
| 1174 | void checkGD(String stringID) { | ||
| 1175 | if (graphicsConfig != null) { | ||
| 1176 | if (!graphicsConfig.getDevice().getIDstring().equals(stringID)) { | ||
| 1177 | throw new IllegalArgumentException( | ||
| 1178 | "adding a container to a container on a different GraphicsDevice"); | ||
| 1179 | } | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | /** | ||
| 1184 | * Gets this component's locking object (the object that owns the thread | ||
| 1185 | * synchronization monitor) for AWT component-tree and layout | ||
| 1186 | * operations. | ||
| 1187 | * @return this component's locking object | ||
| 1188 | */ | ||
| 1189 | public final Object getTreeLock() { | ||
| 1190 | return LOCK; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | final void checkTreeLock() { | ||
| 1194 | if (!Thread.holdsLock(getTreeLock())) { | ||
| 1195 | throw new IllegalStateException("This function should be called while holding treeLock"); | ||
| 1196 | } | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | /** | ||
| 1200 | * Gets the toolkit of this component. Note that | ||
| 1201 | * the frame that contains a component controls which | ||
| 1202 | * toolkit is used by that component. Therefore if the component | ||
| 1203 | * is moved from one frame to another, the toolkit it uses may change. | ||
| 1204 | * @return the toolkit of this component | ||
| 1205 | * @since JDK1.0 | ||
| 1206 | */ | ||
| 1207 | public Toolkit getToolkit() { | ||
| 1208 | return getToolkitImpl(); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | /* | ||
| 1212 | * This is called by the native code, so client code can't | ||
| 1213 | * be called on the toolkit thread. | ||
| 1214 | */ | ||
| 1215 | final Toolkit getToolkitImpl() { | ||
| 1216 | ComponentPeer peer = this.peer; | ||
| 1217 | if ((peer != null) && ! (peer instanceof LightweightPeer)){ | ||
| 1218 | return peer.getToolkit(); | ||
| 1219 | } | ||
| 1220 | Container parent = this.parent; | ||
| 1221 | if (parent != null) { | ||
| 1222 | return parent.getToolkitImpl(); | ||
| 1223 | } | ||
| 1224 | return Toolkit.getDefaultToolkit(); | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | /** | ||
| 1228 | * Determines whether this component is valid. A component is valid | ||
| 1229 | * when it is correctly sized and positioned within its parent | ||
| 1230 | * container and all its children are also valid. | ||
| 1231 | * In order to account for peers' size requirements, components are invalidated | ||
| 1232 | * before they are first shown on the screen. By the time the parent container | ||
| 1233 | * is fully realized, all its components will be valid. | ||
| 1234 | * @return <code>true</code> if the component is valid, <code>false</code> | ||
| 1235 | * otherwise | ||
| 1236 | * @see #validate | ||
| 1237 | * @see #invalidate | ||
| 1238 | * @since JDK1.0 | ||
| 1239 | */ | ||
| 1240 | public boolean isValid() { | ||
| 1241 | return (peer != null) && valid; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | /** | ||
| 1245 | * Determines whether this component is displayable. A component is | ||
| 1246 | * displayable when it is connected to a native screen resource. | ||
| 1247 | * <p> | ||
| 1248 | * A component is made displayable either when it is added to | ||
| 1249 | * a displayable containment hierarchy or when its containment | ||
| 1250 | * hierarchy is made displayable. | ||
| 1251 | * A containment hierarchy is made displayable when its ancestor | ||
| 1252 | * window is either packed or made visible. | ||
| 1253 | * <p> | ||
| 1254 | * A component is made undisplayable either when it is removed from | ||
| 1255 | * a displayable containment hierarchy or when its containment hierarchy | ||
| 1256 | * is made undisplayable. A containment hierarchy is made | ||
| 1257 | * undisplayable when its ancestor window is disposed. | ||
| 1258 | * | ||
| 1259 | * @return <code>true</code> if the component is displayable, | ||
| 1260 | * <code>false</code> otherwise | ||
| 1261 | * @see Container#add(Component) | ||
| 1262 | * @see Window#pack | ||
| 1263 | * @see Window#show | ||
| 1264 | * @see Container#remove(Component) | ||
| 1265 | * @see Window#dispose | ||
| 1266 | * @since 1.2 | ||
| 1267 | */ | ||
| 1268 | public boolean isDisplayable() { | ||
| 1269 | return getPeer() != null; | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | /** | ||
| 1273 | * Determines whether this component should be visible when its | ||
| 1274 | * parent is visible. Components are | ||
| 1275 | * initially visible, with the exception of top level components such | ||
| 1276 | * as <code>Frame</code> objects. | ||
| 1277 | * @return <code>true</code> if the component is visible, | ||
| 1278 | * <code>false</code> otherwise | ||
| 1279 | * @see #setVisible | ||
| 1280 | * @since JDK1.0 | ||
| 1281 | */ | ||
| 1282 | @Transient | ||
| 1283 | public boolean isVisible() { | ||
| 1284 | return isVisible_NoClientCode(); | ||
| 1285 | } | ||
| 1286 | final boolean isVisible_NoClientCode() { | ||
| 1287 | return visible; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | /** | ||
| 1291 | * Determines whether this component will be displayed on the screen. | ||
| 1292 | * @return <code>true</code> if the component and all of its ancestors | ||
| 1293 | * until a toplevel window or null parent are visible, | ||
| 1294 | * <code>false</code> otherwise | ||
| 1295 | */ | ||
| 1296 | boolean isRecursivelyVisible() { | ||
| 1297 | return visible && (parent == null || parent.isRecursivelyVisible()); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | /** | ||
| 1301 | * Translates absolute coordinates into coordinates in the coordinate | ||
| 1302 | * space of this component. | ||
| 1303 | */ | ||
| 1304 | Point pointRelativeToComponent(Point absolute) { | ||
| 1305 | Point compCoords = getLocationOnScreen(); | ||
| 1306 | return new Point(absolute.x - compCoords.x, | ||
| 1307 | absolute.y - compCoords.y); | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | /** | ||
| 1311 | * Assuming that mouse location is stored in PointerInfo passed | ||
| 1312 | * to this method, it finds a Component that is in the same | ||
| 1313 | * Window as this Component and is located under the mouse pointer. | ||
| 1314 | * If no such Component exists, null is returned. | ||
| 1315 | * NOTE: this method should be called under the protection of | ||
| 1316 | * tree lock, as it is done in Component.getMousePosition() and | ||
| 1317 | * Container.getMousePosition(boolean). | ||
| 1318 | */ | ||
| 1319 | Component findUnderMouseInWindow(PointerInfo pi) { | ||
| 1320 | if (!isShowing()) { | ||
| 1321 | return null; | ||
| 1322 | } | ||
| 1323 | Window win = getContainingWindow(); | ||
| 1324 | if (!Toolkit.getDefaultToolkit().getMouseInfoPeer().isWindowUnderMouse(win)) { | ||
| 1325 | return null; | ||
| 1326 | } | ||
| 1327 | final boolean INCLUDE_DISABLED = true; | ||
| 1328 | Point relativeToWindow = win.pointRelativeToComponent(pi.getLocation()); | ||
| 1329 | Component inTheSameWindow = win.findComponentAt(relativeToWindow.x, | ||
| 1330 | relativeToWindow.y, | ||
| 1331 | INCLUDE_DISABLED); | ||
| 1332 | return inTheSameWindow; | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | /** | ||
| 1336 | * Returns the position of the mouse pointer in this <code>Component</code>'s | ||
| 1337 | * coordinate space if the <code>Component</code> is directly under the mouse | ||
| 1338 | * pointer, otherwise returns <code>null</code>. | ||
| 1339 | * If the <code>Component</code> is not showing on the screen, this method | ||
| 1340 | * returns <code>null</code> even if the mouse pointer is above the area | ||
| 1341 | * where the <code>Component</code> would be displayed. | ||
| 1342 | * If the <code>Component</code> is partially or fully obscured by other | ||
| 1343 | * <code>Component</code>s or native windows, this method returns a non-null | ||
| 1344 | * value only if the mouse pointer is located above the unobscured part of the | ||
| 1345 | * <code>Component</code>. | ||
| 1346 | * <p> | ||
| 1347 | * For <code>Container</code>s it returns a non-null value if the mouse is | ||
| 1348 | * above the <code>Container</code> itself or above any of its descendants. | ||
| 1349 | * Use {@link Container#getMousePosition(boolean)} if you need to exclude children. | ||
| 1350 | * <p> | ||
| 1351 | * Sometimes the exact mouse coordinates are not important, and the only thing | ||
| 1352 | * that matters is whether a specific <code>Component</code> is under the mouse | ||
| 1353 | * pointer. If the return value of this method is <code>null</code>, mouse | ||
| 1354 | * pointer is not directly above the <code>Component</code>. | ||
| 1355 | * | ||
| 1356 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true | ||
| 1357 | * @see #isShowing | ||
| 1358 | * @see Container#getMousePosition | ||
| 1359 | * @return mouse coordinates relative to this <code>Component</code>, or null | ||
| 1360 | * @since 1.5 | ||
| 1361 | */ | ||
| 1362 | public Point getMousePosition() throws HeadlessException { | ||
| 1363 | if (GraphicsEnvironment.isHeadless()) { | ||
| 1364 | throw new HeadlessException(); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged( | ||
| 1368 | new java.security.PrivilegedAction() { | ||
| 1369 | public Object run() { | ||
| 1370 | return MouseInfo.getPointerInfo(); | ||
| 1371 | } | ||
| 1372 | } | ||
| 1373 | ); | ||
| 1374 | |||
| 1375 | synchronized (getTreeLock()) { | ||
| 1376 | Component inTheSameWindow = findUnderMouseInWindow(pi); | ||
| 1377 | if (!isSameOrAncestorOf(inTheSameWindow, true)) { | ||
| 1378 | return null; | ||
| 1379 | } | ||
| 1380 | return pointRelativeToComponent(pi.getLocation()); | ||
| 1381 | } | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | /** | ||
| 1385 | * Overridden in Container. Must be called under TreeLock. | ||
| 1386 | */ | ||
| 1387 | boolean isSameOrAncestorOf(Component comp, boolean allowChildren) { | ||
| 1388 | return comp == this; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | /** | ||
| 1392 | * Determines whether this component is showing on screen. This means | ||
| 1393 | * that the component must be visible, and it must be in a container | ||
| 1394 | * that is visible and showing. | ||
| 1395 | * <p> | ||
| 1396 | * <strong>Note:</strong> sometimes there is no way to detect whether the | ||
| 1397 | * {@code Component} is actually visible to the user. This can happen when: | ||
| 1398 | * <ul> | ||
| 1399 | * <li>the component has been added to a visible {@code ScrollPane} but | ||
| 1400 | * the {@code Component} is not currently in the scroll pane's view port. | ||
| 1401 | * <li>the {@code Component} is obscured by another {@code Component} or | ||
| 1402 | * {@code Container}. | ||
| 1403 | * </ul> | ||
| 1404 | * @return <code>true</code> if the component is showing, | ||
| 1405 | * <code>false</code> otherwise | ||
| 1406 | * @see #setVisible | ||
| 1407 | * @since JDK1.0 | ||
| 1408 | */ | ||
| 1409 | public boolean isShowing() { | ||
| 1410 | if (visible && (peer != null)) { | ||
| 1411 | Container parent = this.parent; | ||
| 1412 | return (parent == null) || parent.isShowing(); | ||
| 1413 | } | ||
| 1414 | return false; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | /** | ||
| 1418 | * Determines whether this component is enabled. An enabled component | ||
| 1419 | * can respond to user input and generate events. Components are | ||
| 1420 | * enabled initially by default. A component may be enabled or disabled by | ||
| 1421 | * calling its <code>setEnabled</code> method. | ||
| 1422 | * @return <code>true</code> if the component is enabled, | ||
| 1423 | * <code>false</code> otherwise | ||
| 1424 | * @see #setEnabled | ||
| 1425 | * @since JDK1.0 | ||
| 1426 | */ | ||
| 1427 | public boolean isEnabled() { | ||
| 1428 | return isEnabledImpl(); | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | /* | ||
| 1432 | * This is called by the native code, so client code can't | ||
| 1433 | * be called on the toolkit thread. | ||
| 1434 | */ | ||
| 1435 | final boolean isEnabledImpl() { | ||
| 1436 | return enabled; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | /** | ||
| 1440 | * Enables or disables this component, depending on the value of the | ||
| 1441 | * parameter <code>b</code>. An enabled component can respond to user | ||
| 1442 | * input and generate events. Components are enabled initially by default. | ||
| 1443 | * | ||
| 1444 | * <p>Note: Disabling a lightweight component does not prevent it from | ||
| 1445 | * receiving MouseEvents. | ||
| 1446 | * <p>Note: Disabling a heavyweight container prevents all components | ||
| 1447 | * in this container from receiving any input events. But disabling a | ||
| 1448 | * lightweight container affects only this container. | ||
| 1449 | * | ||
| 1450 | * @param b If <code>true</code>, this component is | ||
| 1451 | * enabled; otherwise this component is disabled | ||
| 1452 | * @see #isEnabled | ||
| 1453 | * @see #isLightweight | ||
| 1454 | * @since JDK1.1 | ||
| 1455 | */ | ||
| 1456 | public void setEnabled(boolean b) { | ||
| 1457 | enable(b); | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | /** | ||
| 1461 | * @deprecated As of JDK version 1.1, | ||
| 1462 | * replaced by <code>setEnabled(boolean)</code>. | ||
| 1463 | */ | ||
| 1464 | @Deprecated | ||
| 1465 | public void enable() { | ||
| 1466 | if (!enabled) { | ||
| 1467 | synchronized (getTreeLock()) { | ||
| 1468 | enabled = true; | ||
| 1469 | ComponentPeer peer = this.peer; | ||
| 1470 | if (peer != null) { | ||
| 1471 | peer.setEnabled(true); | ||
| 1472 | if (visible) { | ||
| 1473 | updateCursorImmediately(); | ||
| 1474 | } | ||
| 1475 | } | ||
| 1476 | } | ||
| 1477 | if (accessibleContext != null) { | ||
| 1478 | accessibleContext.firePropertyChange( | ||
| 1479 | AccessibleContext.ACCESSIBLE_STATE_PROPERTY, | ||
| 1480 | null, AccessibleState.ENABLED); | ||
| 1481 | } | ||
| 1482 | } | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | /** | ||
| 1486 | * @deprecated As of JDK version 1.1, | ||
| 1487 | * replaced by <code>setEnabled(boolean)</code>. | ||
| 1488 | */ | ||
| 1489 | @Deprecated | ||
| 1490 | public void enable(boolean b) { | ||
| 1491 | if (b) { | ||
| 1492 | enable(); | ||
| 1493 | } else { | ||
| 1494 | disable(); | ||
| 1495 | } | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | /** | ||
| 1499 | * @deprecated As of JDK version 1.1, | ||
| 1500 | * replaced by <code>setEnabled(boolean)</code>. | ||
| 1501 | */ | ||
| 1502 | @Deprecated | ||
| 1503 | public void disable() { | ||
| 1504 | if (enabled) { | ||
| 1505 | KeyboardFocusManager.clearMostRecentFocusOwner(this); | ||
| 1506 | synchronized (getTreeLock()) { | ||
| 1507 | enabled = false; | ||
| 1508 | // A disabled lw container is allowed to contain a focus owner. | ||
| 1509 | if ((isFocusOwner() || (containsFocus() && !isLightweight())) && | ||
| 1510 | KeyboardFocusManager.isAutoFocusTransferEnabled()) | ||
| 1511 | { | ||
| 1512 | // Don't clear the global focus owner. If transferFocus | ||
| 1513 | // fails, we want the focus to stay on the disabled | ||
| 1514 | // Component so that keyboard traversal, et. al. still | ||
| 1515 | // makes sense to the user. | ||
| 1516 | transferFocus(false); | ||
| 1517 | } | ||
| 1518 | ComponentPeer peer = this.peer; | ||
| 1519 | if (peer != null) { | ||
| 1520 | peer.setEnabled(false); | ||
| 1521 | if (visible) { | ||
| 1522 | updateCursorImmediately(); | ||
| 1523 | } | ||
| 1524 | } | ||
| 1525 | } | ||
| 1526 | if (accessibleContext != null) { | ||
| 1527 | accessibleContext.firePropertyChange( | ||
| 1528 | AccessibleContext.ACCESSIBLE_STATE_PROPERTY, | ||
| 1529 | null, AccessibleState.ENABLED); | ||
| 1530 | } | ||
| 1531 | } | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | /** | ||
| 1535 | * Returns true if this component is painted to an offscreen image | ||
| 1536 | * ("buffer") that's copied to the screen later. Component | ||
| 1537 | * subclasses that support double buffering should override this | ||
| 1538 | * method to return true if double buffering is enabled. | ||
| 1539 | * | ||
| 1540 | * @return false by default | ||
| 1541 | */ | ||
| 1542 | public boolean isDoubleBuffered() { | ||
| 1543 | return false; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | /** | ||
| 1547 | * Enables or disables input method support for this component. If input | ||
| 1548 | * method support is enabled and the component also processes key events, | ||
| 1549 | * incoming events are offered to | ||
| 1550 | * the current input method and will only be processed by the component or | ||
| 1551 | * dispatched to its listeners if the input method does not consume them. | ||
| 1552 | * By default, input method support is enabled. | ||
| 1553 | * | ||
| 1554 | * @param enable true to enable, false to disable | ||
| 1555 | * @see #processKeyEvent | ||
| 1556 | * @since 1.2 | ||
| 1557 | */ | ||
| 1558 | public void enableInputMethods(boolean enable) { | ||
| 1559 | if (enable) { | ||
| 1560 | if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) | ||
| 1561 | return; | ||
| 1562 | |||
| 1563 | // If this component already has focus, then activate the | ||
| 1564 | // input method by dispatching a synthesized focus gained | ||
| 1565 | // event. | ||
| 1566 | if (isFocusOwner()) { | ||
| 1567 | InputContext inputContext = getInputContext(); | ||
| 1568 | if (inputContext != null) { | ||
| 1569 | FocusEvent focusGainedEvent = | ||
| 1570 | new FocusEvent(this, FocusEvent.FOCUS_GAINED); | ||
| 1571 | inputContext.dispatchEvent(focusGainedEvent); | ||
| 1572 | } | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | eventMask |= AWTEvent.INPUT_METHODS_ENABLED_MASK; | ||
| 1576 | } else { | ||
| 1577 | if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) { | ||
| 1578 | InputContext inputContext = getInputContext(); | ||
| 1579 | if (inputContext != null) { | ||
| 1580 | inputContext.endComposition(); | ||
| 1581 | inputContext.removeNotify(this); | ||
| 1582 | } | ||
| 1583 | } | ||
| 1584 | eventMask &= ~AWTEvent.INPUT_METHODS_ENABLED_MASK; | ||
| 1585 | } | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | /** | ||
| 1589 | * Shows or hides this component depending on the value of parameter | ||
| 1590 | * <code>b</code>. | ||
| 1591 | * <p> | ||
| 1592 | * This method changes layout-related information, and therefore, | ||
| 1593 | * invalidates the component hierarchy. | ||
| 1594 | * | ||
| 1595 | * @param b if <code>true</code>, shows this component; | ||
| 1596 | * otherwise, hides this component | ||
| 1597 | * @see #isVisible | ||
| 1598 | * @see #invalidate | ||
| 1599 | * @since JDK1.1 | ||
| 1600 | */ | ||
| 1601 | public void setVisible(boolean b) { | ||
| 1602 | show(b); | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | /** | ||
| 1606 | * @deprecated As of JDK version 1.1, | ||
| 1607 | * replaced by <code>setVisible(boolean)</code>. | ||
| 1608 | */ | ||
| 1609 | @Deprecated | ||
| 1610 | public void show() { | ||
| 1611 | if (!visible) { | ||
| 1612 | synchronized (getTreeLock()) { | ||
| 1613 | visible = true; | ||
| 1614 | mixOnShowing(); | ||
| 1615 | ComponentPeer peer = this.peer; | ||
| 1616 | if (peer != null) { | ||
| 1617 | peer.setVisible(true); | ||
| 1618 | createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, | ||
| 1619 | this, parent, | ||
| 1620 | HierarchyEvent.SHOWING_CHANGED, | ||
| 1621 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1622 | if (peer instanceof LightweightPeer) { | ||
| 1623 | repaint(); | ||
| 1624 | } | ||
| 1625 | updateCursorImmediately(); | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | if (componentListener != null || | ||
| 1629 | (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || | ||
| 1630 | Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { | ||
| 1631 | ComponentEvent e = new ComponentEvent(this, | ||
| 1632 | ComponentEvent.COMPONENT_SHOWN); | ||
| 1633 | Toolkit.getEventQueue().postEvent(e); | ||
| 1634 | } | ||
| 1635 | } | ||
| 1636 | Container parent = this.parent; | ||
| 1637 | if (parent != null) { | ||
| 1638 | parent.invalidate(); | ||
| 1639 | } | ||
| 1640 | } | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | /** | ||
| 1644 | * @deprecated As of JDK version 1.1, | ||
| 1645 | * replaced by <code>setVisible(boolean)</code>. | ||
| 1646 | */ | ||
| 1647 | @Deprecated | ||
| 1648 | public void show(boolean b) { | ||
| 1649 | if (b) { | ||
| 1650 | show(); | ||
| 1651 | } else { | ||
| 1652 | hide(); | ||
| 1653 | } | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | boolean containsFocus() { | ||
| 1657 | return isFocusOwner(); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | void clearMostRecentFocusOwnerOnHide() { | ||
| 1661 | KeyboardFocusManager.clearMostRecentFocusOwner(this); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | void clearCurrentFocusCycleRootOnHide() { | ||
| 1665 | /* do nothing */ | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | /** | ||
| 1669 | * @deprecated As of JDK version 1.1, | ||
| 1670 | * replaced by <code>setVisible(boolean)</code>. | ||
| 1671 | */ | ||
| 1672 | @Deprecated | ||
| 1673 | public void hide() { | ||
| 1674 | isPacked = false; | ||
| 1675 | |||
| 1676 | if (visible) { | ||
| 1677 | clearCurrentFocusCycleRootOnHide(); | ||
| 1678 | clearMostRecentFocusOwnerOnHide(); | ||
| 1679 | synchronized (getTreeLock()) { | ||
| 1680 | visible = false; | ||
| 1681 | mixOnHiding(isLightweight()); | ||
| 1682 | if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabled()) { | ||
| 1683 | transferFocus(true); | ||
| 1684 | } | ||
| 1685 | ComponentPeer peer = this.peer; | ||
| 1686 | if (peer != null) { | ||
| 1687 | peer.setVisible(false); | ||
| 1688 | createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, | ||
| 1689 | this, parent, | ||
| 1690 | HierarchyEvent.SHOWING_CHANGED, | ||
| 1691 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1692 | if (peer instanceof LightweightPeer) { | ||
| 1693 | repaint(); | ||
| 1694 | } | ||
| 1695 | updateCursorImmediately(); | ||
| 1696 | } | ||
| 1697 | if (componentListener != null || | ||
| 1698 | (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || | ||
| 1699 | Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { | ||
| 1700 | ComponentEvent e = new ComponentEvent(this, | ||
| 1701 | ComponentEvent.COMPONENT_HIDDEN); | ||
| 1702 | Toolkit.getEventQueue().postEvent(e); | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | Container parent = this.parent; | ||
| 1706 | if (parent != null) { | ||
| 1707 | parent.invalidate(); | ||
| 1708 | } | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | /** | ||
| 1713 | * Gets the foreground color of this component. | ||
| 1714 | * @return this component's foreground color; if this component does | ||
| 1715 | * not have a foreground color, the foreground color of its parent | ||
| 1716 | * is returned | ||
| 1717 | * @see #setForeground | ||
| 1718 | * @since JDK1.0 | ||
| 1719 | * @beaninfo | ||
| 1720 | * bound: true | ||
| 1721 | */ | ||
| 1722 | @Transient | ||
| 1723 | public Color getForeground() { | ||
| 1724 | Color foreground = this.foreground; | ||
| 1725 | if (foreground != null) { | ||
| 1726 | return foreground; | ||
| 1727 | } | ||
| 1728 | Container parent = this.parent; | ||
| 1729 | return (parent != null) ? parent.getForeground() : null; | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | /** | ||
| 1733 | * Sets the foreground color of this component. | ||
| 1734 | * @param c the color to become this component's | ||
| 1735 | * foreground color; if this parameter is <code>null</code> | ||
| 1736 | * then this component will inherit | ||
| 1737 | * the foreground color of its parent | ||
| 1738 | * @see #getForeground | ||
| 1739 | * @since JDK1.0 | ||
| 1740 | */ | ||
| 1741 | public void setForeground(Color c) { | ||
| 1742 | Color oldColor = foreground; | ||
| 1743 | ComponentPeer peer = this.peer; | ||
| 1744 | foreground = c; | ||
| 1745 | if (peer != null) { | ||
| 1746 | c = getForeground(); | ||
| 1747 | if (c != null) { | ||
| 1748 | peer.setForeground(c); | ||
| 1749 | } | ||
| 1750 | } | ||
| 1751 | // This is a bound property, so report the change to | ||
| 1752 | // any registered listeners. (Cheap if there are none.) | ||
| 1753 | firePropertyChange("foreground", oldColor, c); | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | /** | ||
| 1757 | * Returns whether the foreground color has been explicitly set for this | ||
| 1758 | * Component. If this method returns <code>false</code>, this Component is | ||
| 1759 | * inheriting its foreground color from an ancestor. | ||
| 1760 | * | ||
| 1761 | * @return <code>true</code> if the foreground color has been explicitly | ||
| 1762 | * set for this Component; <code>false</code> otherwise. | ||
| 1763 | * @since 1.4 | ||
| 1764 | */ | ||
| 1765 | public boolean isForegroundSet() { | ||
| 1766 | return (foreground != null); | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | /** | ||
| 1770 | * Gets the background color of this component. | ||
| 1771 | * @return this component's background color; if this component does | ||
| 1772 | * not have a background color, | ||
| 1773 | * the background color of its parent is returned | ||
| 1774 | * @see #setBackground | ||
| 1775 | * @since JDK1.0 | ||
| 1776 | */ | ||
| 1777 | @Transient | ||
| 1778 | public Color getBackground() { | ||
| 1779 | Color background = this.background; | ||
| 1780 | if (background != null) { | ||
| 1781 | return background; | ||
| 1782 | } | ||
| 1783 | Container parent = this.parent; | ||
| 1784 | return (parent != null) ? parent.getBackground() : null; | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | /** | ||
| 1788 | * Sets the background color of this component. | ||
| 1789 | * <p> | ||
| 1790 | * The background color affects each component differently and the | ||
| 1791 | * parts of the component that are affected by the background color | ||
| 1792 | * may differ between operating systems. | ||
| 1793 | * | ||
| 1794 | * @param c the color to become this component's color; | ||
| 1795 | * if this parameter is <code>null</code>, then this | ||
| 1796 | * component will inherit the background color of its parent | ||
| 1797 | * @see #getBackground | ||
| 1798 | * @since JDK1.0 | ||
| 1799 | * @beaninfo | ||
| 1800 | * bound: true | ||
| 1801 | */ | ||
| 1802 | public void setBackground(Color c) { | ||
| 1803 | Color oldColor = background; | ||
| 1804 | ComponentPeer peer = this.peer; | ||
| 1805 | background = c; | ||
| 1806 | if (peer != null) { | ||
| 1807 | c = getBackground(); | ||
| 1808 | if (c != null) { | ||
| 1809 | peer.setBackground(c); | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | // This is a bound property, so report the change to | ||
| 1813 | // any registered listeners. (Cheap if there are none.) | ||
| 1814 | firePropertyChange("background", oldColor, c); | ||
| 1815 | } | ||
| 1816 | |||
| 1817 | /** | ||
| 1818 | * Returns whether the background color has been explicitly set for this | ||
| 1819 | * Component. If this method returns <code>false</code>, this Component is | ||
| 1820 | * inheriting its background color from an ancestor. | ||
| 1821 | * | ||
| 1822 | * @return <code>true</code> if the background color has been explicitly | ||
| 1823 | * set for this Component; <code>false</code> otherwise. | ||
| 1824 | * @since 1.4 | ||
| 1825 | */ | ||
| 1826 | public boolean isBackgroundSet() { | ||
| 1827 | return (background != null); | ||
| 1828 | } | ||
| 1829 | |||
| 1830 | /** | ||
| 1831 | * Gets the font of this component. | ||
| 1832 | * @return this component's font; if a font has not been set | ||
| 1833 | * for this component, the font of its parent is returned | ||
| 1834 | * @see #setFont | ||
| 1835 | * @since JDK1.0 | ||
| 1836 | */ | ||
| 1837 | @Transient | ||
| 1838 | public Font getFont() { | ||
| 1839 | return getFont_NoClientCode(); | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | // NOTE: This method may be called by privileged threads. | ||
| 1843 | // This functionality is implemented in a package-private method | ||
| 1844 | // to insure that it cannot be overridden by client subclasses. | ||
| 1845 | // DO NOT INVOKE CLIENT CODE ON THIS THREAD! | ||
| 1846 | final Font getFont_NoClientCode() { | ||
| 1847 | Font font = this.font; | ||
| 1848 | if (font != null) { | ||
| 1849 | return font; | ||
| 1850 | } | ||
| 1851 | Container parent = this.parent; | ||
| 1852 | return (parent != null) ? parent.getFont_NoClientCode() : null; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | /** | ||
| 1856 | * Sets the font of this component. | ||
| 1857 | * <p> | ||
| 1858 | * This method changes layout-related information, and therefore, | ||
| 1859 | * invalidates the component hierarchy. | ||
| 1860 | * | ||
| 1861 | * @param f the font to become this component's font; | ||
| 1862 | * if this parameter is <code>null</code> then this | ||
| 1863 | * component will inherit the font of its parent | ||
| 1864 | * @see #getFont | ||
| 1865 | * @see #invalidate | ||
| 1866 | * @since JDK1.0 | ||
| 1867 | * @beaninfo | ||
| 1868 | * bound: true | ||
| 1869 | */ | ||
| 1870 | public void setFont(Font f) { | ||
| 1871 | Font oldFont, newFont; | ||
| 1872 | synchronized(getTreeLock()) { | ||
| 1873 | synchronized (this) { | ||
| 1874 | oldFont = font; | ||
| 1875 | newFont = font = f; | ||
| 1876 | } | ||
| 1877 | ComponentPeer peer = this.peer; | ||
| 1878 | if (peer != null) { | ||
| 1879 | f = getFont(); | ||
| 1880 | if (f != null) { | ||
| 1881 | peer.setFont(f); | ||
| 1882 | peerFont = f; | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | } | ||
| 1886 | // This is a bound property, so report the change to | ||
| 1887 | // any registered listeners. (Cheap if there are none.) | ||
| 1888 | firePropertyChange("font", oldFont, newFont); | ||
| 1889 | |||
| 1890 | // This could change the preferred size of the Component. | ||
| 1891 | // Fix for 6213660. Should compare old and new fonts and do not | ||
| 1892 | // call invalidate() if they are equal. | ||
| 1893 | if (f != oldFont && (oldFont == null || | ||
| 1894 | !oldFont.equals(f))) { | ||
| 1895 | invalidateIfValid(); | ||
| 1896 | } | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | /** | ||
| 1900 | * Returns whether the font has been explicitly set for this Component. If | ||
| 1901 | * this method returns <code>false</code>, this Component is inheriting its | ||
| 1902 | * font from an ancestor. | ||
| 1903 | * | ||
| 1904 | * @return <code>true</code> if the font has been explicitly set for this | ||
| 1905 | * Component; <code>false</code> otherwise. | ||
| 1906 | * @since 1.4 | ||
| 1907 | */ | ||
| 1908 | public boolean isFontSet() { | ||
| 1909 | return (font != null); | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | /** | ||
| 1913 | * Gets the locale of this component. | ||
| 1914 | * @return this component's locale; if this component does not | ||
| 1915 | * have a locale, the locale of its parent is returned | ||
| 1916 | * @see #setLocale | ||
| 1917 | * @exception IllegalComponentStateException if the <code>Component</code> | ||
| 1918 | * does not have its own locale and has not yet been added to | ||
| 1919 | * a containment hierarchy such that the locale can be determined | ||
| 1920 | * from the containing parent | ||
| 1921 | * @since JDK1.1 | ||
| 1922 | */ | ||
| 1923 | public Locale getLocale() { | ||
| 1924 | Locale locale = this.locale; | ||
| 1925 | if (locale != null) { | ||
| 1926 | return locale; | ||
| 1927 | } | ||
| 1928 | Container parent = this.parent; | ||
| 1929 | |||
| 1930 | if (parent == null) { | ||
| 1931 | throw new IllegalComponentStateException("This component must have a parent in order to determine its locale"); | ||
| 1932 | } else { | ||
| 1933 | return parent.getLocale(); | ||
| 1934 | } | ||
| 1935 | } | ||
| 1936 | |||
| 1937 | /** | ||
| 1938 | * Sets the locale of this component. This is a bound property. | ||
| 1939 | * <p> | ||
| 1940 | * This method changes layout-related information, and therefore, | ||
| 1941 | * invalidates the component hierarchy. | ||
| 1942 | * | ||
| 1943 | * @param l the locale to become this component's locale | ||
| 1944 | * @see #getLocale | ||
| 1945 | * @see #invalidate | ||
| 1946 | * @since JDK1.1 | ||
| 1947 | */ | ||
| 1948 | public void setLocale(Locale l) { | ||
| 1949 | Locale oldValue = locale; | ||
| 1950 | locale = l; | ||
| 1951 | |||
| 1952 | // This is a bound property, so report the change to | ||
| 1953 | // any registered listeners. (Cheap if there are none.) | ||
| 1954 | firePropertyChange("locale", oldValue, l); | ||
| 1955 | |||
| 1956 | // This could change the preferred size of the Component. | ||
| 1957 | invalidateIfValid(); | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | /** | ||
| 1961 | * Gets the instance of <code>ColorModel</code> used to display | ||
| 1962 | * the component on the output device. | ||
| 1963 | * @return the color model used by this component | ||
| 1964 | * @see java.awt.image.ColorModel | ||
| 1965 | * @see java.awt.peer.ComponentPeer#getColorModel() | ||
| 1966 | * @see Toolkit#getColorModel() | ||
| 1967 | * @since JDK1.0 | ||
| 1968 | */ | ||
| 1969 | public ColorModel getColorModel() { | ||
| 1970 | ComponentPeer peer = this.peer; | ||
| 1971 | if ((peer != null) && ! (peer instanceof LightweightPeer)) { | ||
| 1972 | return peer.getColorModel(); | ||
| 1973 | } else if (GraphicsEnvironment.isHeadless()) { | ||
| 1974 | return ColorModel.getRGBdefault(); | ||
| 1975 | } // else | ||
| 1976 | return getToolkit().getColorModel(); | ||
| 1977 | } | ||
| 1978 | |||
| 1979 | /** | ||
| 1980 | * Gets the location of this component in the form of a | ||
| 1981 | * point specifying the component's top-left corner. | ||
| 1982 | * The location will be relative to the parent's coordinate space. | ||
| 1983 | * <p> | ||
| 1984 | * Due to the asynchronous nature of native event handling, this | ||
| 1985 | * method can return outdated values (for instance, after several calls | ||
| 1986 | * of <code>setLocation()</code> in rapid succession). For this | ||
| 1987 | * reason, the recommended method of obtaining a component's position is | ||
| 1988 | * within <code>java.awt.event.ComponentListener.componentMoved()</code>, | ||
| 1989 | * which is called after the operating system has finished moving the | ||
| 1990 | * component. | ||
| 1991 | * </p> | ||
| 1992 | * @return an instance of <code>Point</code> representing | ||
| 1993 | * the top-left corner of the component's bounds in | ||
| 1994 | * the coordinate space of the component's parent | ||
| 1995 | * @see #setLocation | ||
| 1996 | * @see #getLocationOnScreen | ||
| 1997 | * @since JDK1.1 | ||
| 1998 | */ | ||
| 1999 | public Point getLocation() { | ||
| 2000 | return location(); | ||
| 2001 | } | ||
| 2002 | |||
| 2003 | /** | ||
| 2004 | * Gets the location of this component in the form of a point | ||
| 2005 | * specifying the component's top-left corner in the screen's | ||
| 2006 | * coordinate space. | ||
| 2007 | * @return an instance of <code>Point</code> representing | ||
| 2008 | * the top-left corner of the component's bounds in the | ||
| 2009 | * coordinate space of the screen | ||
| 2010 | * @throws <code>IllegalComponentStateException</code> if the | ||
| 2011 | * component is not showing on the screen | ||
| 2012 | * @see #setLocation | ||
| 2013 | * @see #getLocation | ||
| 2014 | */ | ||
| 2015 | public Point getLocationOnScreen() { | ||
| 2016 | synchronized (getTreeLock()) { | ||
| 2017 | return getLocationOnScreen_NoTreeLock(); | ||
| 2018 | } | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | /* | ||
| 2022 | * a package private version of getLocationOnScreen | ||
| 2023 | * used by GlobalCursormanager to update cursor | ||
| 2024 | */ | ||
| 2025 | final Point getLocationOnScreen_NoTreeLock() { | ||
| 2026 | |||
| 2027 | if (peer != null && isShowing()) { | ||
| 2028 | if (peer instanceof LightweightPeer) { | ||
| 2029 | // lightweight component location needs to be translated | ||
| 2030 | // relative to a native component. | ||
| 2031 | Container host = getNativeContainer(); | ||
| 2032 | Point pt = host.peer.getLocationOnScreen(); | ||
| 2033 | for(Component c = this; c != host; c = c.getParent()) { | ||
| 2034 | pt.x += c.x; | ||
| 2035 | pt.y += c.y; | ||
| 2036 | } | ||
| 2037 | return pt; | ||
| 2038 | } else { | ||
| 2039 | Point pt = peer.getLocationOnScreen(); | ||
| 2040 | return pt; | ||
| 2041 | } | ||
| 2042 | } else { | ||
| 2043 | throw new IllegalComponentStateException("component must be showing on the screen to determine its location"); | ||
| 2044 | } | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | |||
| 2048 | /** | ||
| 2049 | * @deprecated As of JDK version 1.1, | ||
| 2050 | * replaced by <code>getLocation()</code>. | ||
| 2051 | */ | ||
| 2052 | @Deprecated | ||
| 2053 | public Point location() { | ||
| 2054 | return location_NoClientCode(); | ||
| 2055 | } | ||
| 2056 | |||
| 2057 | private Point location_NoClientCode() { | ||
| 2058 | return new Point(x, y); | ||
| 2059 | } | ||
| 2060 | |||
| 2061 | /** | ||
| 2062 | * Moves this component to a new location. The top-left corner of | ||
| 2063 | * the new location is specified by the <code>x</code> and <code>y</code> | ||
| 2064 | * parameters in the coordinate space of this component's parent. | ||
| 2065 | * <p> | ||
| 2066 | * This method changes layout-related information, and therefore, | ||
| 2067 | * invalidates the component hierarchy. | ||
| 2068 | * | ||
| 2069 | * @param x the <i>x</i>-coordinate of the new location's | ||
| 2070 | * top-left corner in the parent's coordinate space | ||
| 2071 | * @param y the <i>y</i>-coordinate of the new location's | ||
| 2072 | * top-left corner in the parent's coordinate space | ||
| 2073 | * @see #getLocation | ||
| 2074 | * @see #setBounds | ||
| 2075 | * @see #invalidate | ||
| 2076 | * @since JDK1.1 | ||
| 2077 | */ | ||
| 2078 | public void setLocation(int x, int y) { | ||
| 2079 | move(x, y); | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | /** | ||
| 2083 | * @deprecated As of JDK version 1.1, | ||
| 2084 | * replaced by <code>setLocation(int, int)</code>. | ||
| 2085 | */ | ||
| 2086 | @Deprecated | ||
| 2087 | public void move(int x, int y) { | ||
| 2088 | synchronized(getTreeLock()) { | ||
| 2089 | setBoundsOp(ComponentPeer.SET_LOCATION); | ||
| 2090 | setBounds(x, y, width, height); | ||
| 2091 | } | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | /** | ||
| 2095 | * Moves this component to a new location. The top-left corner of | ||
| 2096 | * the new location is specified by point <code>p</code>. Point | ||
| 2097 | * <code>p</code> is given in the parent's coordinate space. | ||
| 2098 | * <p> | ||
| 2099 | * This method changes layout-related information, and therefore, | ||
| 2100 | * invalidates the component hierarchy. | ||
| 2101 | * | ||
| 2102 | * @param p the point defining the top-left corner | ||
| 2103 | * of the new location, given in the coordinate space of this | ||
| 2104 | * component's parent | ||
| 2105 | * @see #getLocation | ||
| 2106 | * @see #setBounds | ||
| 2107 | * @see #invalidate | ||
| 2108 | * @since JDK1.1 | ||
| 2109 | */ | ||
| 2110 | public void setLocation(Point p) { | ||
| 2111 | setLocation(p.x, p.y); | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | /** | ||
| 2115 | * Returns the size of this component in the form of a | ||
| 2116 | * <code>Dimension</code> object. The <code>height</code> | ||
| 2117 | * field of the <code>Dimension</code> object contains | ||
| 2118 | * this component's height, and the <code>width</code> | ||
| 2119 | * field of the <code>Dimension</code> object contains | ||
| 2120 | * this component's width. | ||
| 2121 | * @return a <code>Dimension</code> object that indicates the | ||
| 2122 | * size of this component | ||
| 2123 | * @see #setSize | ||
| 2124 | * @since JDK1.1 | ||
| 2125 | */ | ||
| 2126 | public Dimension getSize() { | ||
| 2127 | return size(); | ||
| 2128 | } | ||
| 2129 | |||
| 2130 | /** | ||
| 2131 | * @deprecated As of JDK version 1.1, | ||
| 2132 | * replaced by <code>getSize()</code>. | ||
| 2133 | */ | ||
| 2134 | @Deprecated | ||
| 2135 | public Dimension size() { | ||
| 2136 | return new Dimension(width, height); | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | /** | ||
| 2140 | * Resizes this component so that it has width <code>width</code> | ||
| 2141 | * and height <code>height</code>. | ||
| 2142 | * <p> | ||
| 2143 | * This method changes layout-related information, and therefore, | ||
| 2144 | * invalidates the component hierarchy. | ||
| 2145 | * | ||
| 2146 | * @param width the new width of this component in pixels | ||
| 2147 | * @param height the new height of this component in pixels | ||
| 2148 | * @see #getSize | ||
| 2149 | * @see #setBounds | ||
| 2150 | * @see #invalidate | ||
| 2151 | * @since JDK1.1 | ||
| 2152 | */ | ||
| 2153 | public void setSize(int width, int height) { | ||
| 2154 | resize(width, height); | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | /** | ||
| 2158 | * @deprecated As of JDK version 1.1, | ||
| 2159 | * replaced by <code>setSize(int, int)</code>. | ||
| 2160 | */ | ||
| 2161 | @Deprecated | ||
| 2162 | public void resize(int width, int height) { | ||
| 2163 | synchronized(getTreeLock()) { | ||
| 2164 | setBoundsOp(ComponentPeer.SET_SIZE); | ||
| 2165 | setBounds(x, y, width, height); | ||
| 2166 | } | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | /** | ||
| 2170 | * Resizes this component so that it has width <code>d.width</code> | ||
| 2171 | * and height <code>d.height</code>. | ||
| 2172 | * <p> | ||
| 2173 | * This method changes layout-related information, and therefore, | ||
| 2174 | * invalidates the component hierarchy. | ||
| 2175 | * | ||
| 2176 | * @param d the dimension specifying the new size | ||
| 2177 | * of this component | ||
| 2178 | * @throws NullPointerException if {@code d} is {@code null} | ||
| 2179 | * @see #setSize | ||
| 2180 | * @see #setBounds | ||
| 2181 | * @see #invalidate | ||
| 2182 | * @since JDK1.1 | ||
| 2183 | */ | ||
| 2184 | public void setSize(Dimension d) { | ||
| 2185 | resize(d); | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | /** | ||
| 2189 | * @deprecated As of JDK version 1.1, | ||
| 2190 | * replaced by <code>setSize(Dimension)</code>. | ||
| 2191 | */ | ||
| 2192 | @Deprecated | ||
| 2193 | public void resize(Dimension d) { | ||
| 2194 | setSize(d.width, d.height); | ||
| 2195 | } | ||
| 2196 | |||
| 2197 | /** | ||
| 2198 | * Gets the bounds of this component in the form of a | ||
| 2199 | * <code>Rectangle</code> object. The bounds specify this | ||
| 2200 | * component's width, height, and location relative to | ||
| 2201 | * its parent. | ||
| 2202 | * @return a rectangle indicating this component's bounds | ||
| 2203 | * @see #setBounds | ||
| 2204 | * @see #getLocation | ||
| 2205 | * @see #getSize | ||
| 2206 | */ | ||
| 2207 | public Rectangle getBounds() { | ||
| 2208 | return bounds(); | ||
| 2209 | } | ||
| 2210 | |||
| 2211 | /** | ||
| 2212 | * @deprecated As of JDK version 1.1, | ||
| 2213 | * replaced by <code>getBounds()</code>. | ||
| 2214 | */ | ||
| 2215 | @Deprecated | ||
| 2216 | public Rectangle bounds() { | ||
| 2217 | return new Rectangle(x, y, width, height); | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | /** | ||
| 2221 | * Moves and resizes this component. The new location of the top-left | ||
| 2222 | * corner is specified by <code>x</code> and <code>y</code>, and the | ||
| 2223 | * new size is specified by <code>width</code> and <code>height</code>. | ||
| 2224 | * <p> | ||
| 2225 | * This method changes layout-related information, and therefore, | ||
| 2226 | * invalidates the component hierarchy. | ||
| 2227 | * | ||
| 2228 | * @param x the new <i>x</i>-coordinate of this component | ||
| 2229 | * @param y the new <i>y</i>-coordinate of this component | ||
| 2230 | * @param width the new <code>width</code> of this component | ||
| 2231 | * @param height the new <code>height</code> of this | ||
| 2232 | * component | ||
| 2233 | * @see #getBounds | ||
| 2234 | * @see #setLocation(int, int) | ||
| 2235 | * @see #setLocation(Point) | ||
| 2236 | * @see #setSize(int, int) | ||
| 2237 | * @see #setSize(Dimension) | ||
| 2238 | * @see #invalidate | ||
| 2239 | * @since JDK1.1 | ||
| 2240 | */ | ||
| 2241 | public void setBounds(int x, int y, int width, int height) { | ||
| 2242 | reshape(x, y, width, height); | ||
| 2243 | } | ||
| 2244 | |||
| 2245 | /** | ||
| 2246 | * @deprecated As of JDK version 1.1, | ||
| 2247 | * replaced by <code>setBounds(int, int, int, int)</code>. | ||
| 2248 | */ | ||
| 2249 | @Deprecated | ||
| 2250 | public void reshape(int x, int y, int width, int height) { | ||
| 2251 | synchronized (getTreeLock()) { | ||
| 2252 | try { | ||
| 2253 | setBoundsOp(ComponentPeer.SET_BOUNDS); | ||
| 2254 | boolean resized = (this.width != width) || (this.height != height); | ||
| 2255 | boolean moved = (this.x != x) || (this.y != y); | ||
| 2256 | if (!resized && !moved) { | ||
| 2257 | return; | ||
| 2258 | } | ||
| 2259 | int oldX = this.x; | ||
| 2260 | int oldY = this.y; | ||
| 2261 | int oldWidth = this.width; | ||
| 2262 | int oldHeight = this.height; | ||
| 2263 | this.x = x; | ||
| 2264 | this.y = y; | ||
| 2265 | this.width = width; | ||
| 2266 | this.height = height; | ||
| 2267 | |||
| 2268 | if (resized) { | ||
| 2269 | isPacked = false; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | boolean needNotify = true; | ||
| 2273 | mixOnReshaping(); | ||
| 2274 | if (peer != null) { | ||
| 2275 | // LightwightPeer is an empty stub so can skip peer.reshape | ||
| 2276 | if (!(peer instanceof LightweightPeer)) { | ||
| 2277 | reshapeNativePeer(x, y, width, height, getBoundsOp()); | ||
| 2278 | // Check peer actualy changed coordinates | ||
| 2279 | resized = (oldWidth != this.width) || (oldHeight != this.height); | ||
| 2280 | moved = (oldX != this.x) || (oldY != this.y); | ||
| 2281 | // fix for 5025858: do not send ComponentEvents for toplevel | ||
| 2282 | // windows here as it is done from peer or native code when | ||
| 2283 | // the window is really resized or moved, otherwise some | ||
| 2284 | // events may be sent twice | ||
| 2285 | if (this instanceof Window) { | ||
| 2286 | needNotify = false; | ||
| 2287 | } | ||
| 2288 | } | ||
| 2289 | if (resized) { | ||
| 2290 | invalidate(); | ||
| 2291 | } | ||
| 2292 | if (parent != null) { | ||
| 2293 | parent.invalidateIfValid(); | ||
| 2294 | } | ||
| 2295 | } | ||
| 2296 | if (needNotify) { | ||
| 2297 | notifyNewBounds(resized, moved); | ||
| 2298 | } | ||
| 2299 | repaintParentIfNeeded(oldX, oldY, oldWidth, oldHeight); | ||
| 2300 | } finally { | ||
| 2301 | setBoundsOp(ComponentPeer.RESET_OPERATION); | ||
| 2302 | } | ||
| 2303 | } | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | private void repaintParentIfNeeded(int oldX, int oldY, int oldWidth, | ||
| 2307 | int oldHeight) | ||
| 2308 | { | ||
| 2309 | if (parent != null && peer instanceof LightweightPeer && isShowing()) { | ||
| 2310 | // Have the parent redraw the area this component occupied. | ||
| 2311 | parent.repaint(oldX, oldY, oldWidth, oldHeight); | ||
| 2312 | // Have the parent redraw the area this component *now* occupies. | ||
| 2313 | repaint(); | ||
| 2314 | } | ||
| 2315 | } | ||
| 2316 | |||
| 2317 | private void reshapeNativePeer(int x, int y, int width, int height, int op) { | ||
| 2318 | // native peer might be offset by more than direct | ||
| 2319 | // parent since parent might be lightweight. | ||
| 2320 | int nativeX = x; | ||
| 2321 | int nativeY = y; | ||
| 2322 | for (Component c = parent; | ||
| 2323 | (c != null) && (c.peer instanceof LightweightPeer); | ||
| 2324 | c = c.parent) | ||
| 2325 | { | ||
| 2326 | nativeX += c.x; | ||
| 2327 | nativeY += c.y; | ||
| 2328 | } | ||
| 2329 | peer.setBounds(nativeX, nativeY, width, height, op); | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | |||
| 2333 | private void notifyNewBounds(boolean resized, boolean moved) { | ||
| 2334 | if (componentListener != null | ||
| 2335 | || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 | ||
| 2336 | || Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) | ||
| 2337 | { | ||
| 2338 | if (resized) { | ||
| 2339 | ComponentEvent e = new ComponentEvent(this, | ||
| 2340 | ComponentEvent.COMPONENT_RESIZED); | ||
| 2341 | Toolkit.getEventQueue().postEvent(e); | ||
| 2342 | } | ||
| 2343 | if (moved) { | ||
| 2344 | ComponentEvent e = new ComponentEvent(this, | ||
| 2345 | ComponentEvent.COMPONENT_MOVED); | ||
| 2346 | Toolkit.getEventQueue().postEvent(e); | ||
| 2347 | } | ||
| 2348 | } else { | ||
| 2349 | if (this instanceof Container && ((Container)this).countComponents() > 0) { | ||
| 2350 | boolean enabledOnToolkit = | ||
| 2351 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); | ||
| 2352 | if (resized) { | ||
| 2353 | |||
| 2354 | ((Container)this).createChildHierarchyEvents( | ||
| 2355 | HierarchyEvent.ANCESTOR_RESIZED, 0, enabledOnToolkit); | ||
| 2356 | } | ||
| 2357 | if (moved) { | ||
| 2358 | ((Container)this).createChildHierarchyEvents( | ||
| 2359 | HierarchyEvent.ANCESTOR_MOVED, 0, enabledOnToolkit); | ||
| 2360 | } | ||
| 2361 | } | ||
| 2362 | } | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | /** | ||
| 2366 | * Moves and resizes this component to conform to the new | ||
| 2367 | * bounding rectangle <code>r</code>. This component's new | ||
| 2368 | * position is specified by <code>r.x</code> and <code>r.y</code>, | ||
| 2369 | * and its new size is specified by <code>r.width</code> and | ||
| 2370 | * <code>r.height</code> | ||
| 2371 | * <p> | ||
| 2372 | * This method changes layout-related information, and therefore, | ||
| 2373 | * invalidates the component hierarchy. | ||
| 2374 | * | ||
| 2375 | * @param r the new bounding rectangle for this component | ||
| 2376 | * @throws NullPointerException if {@code r} is {@code null} | ||
| 2377 | * @see #getBounds | ||
| 2378 | * @see #setLocation(int, int) | ||
| 2379 | * @see #setLocation(Point) | ||
| 2380 | * @see #setSize(int, int) | ||
| 2381 | * @see #setSize(Dimension) | ||
| 2382 | * @see #invalidate | ||
| 2383 | * @since JDK1.1 | ||
| 2384 | */ | ||
| 2385 | public void setBounds(Rectangle r) { | ||
| 2386 | setBounds(r.x, r.y, r.width, r.height); | ||
| 2387 | } | ||
| 2388 | |||
| 2389 | |||
| 2390 | /** | ||
| 2391 | * Returns the current x coordinate of the components origin. | ||
| 2392 | * This method is preferable to writing | ||
| 2393 | * <code>component.getBounds().x</code>, | ||
| 2394 | * or <code>component.getLocation().x</code> because it doesn't | ||
| 2395 | * cause any heap allocations. | ||
| 2396 | * | ||
| 2397 | * @return the current x coordinate of the components origin | ||
| 2398 | * @since 1.2 | ||
| 2399 | */ | ||
| 2400 | public int getX() { | ||
| 2401 | return x; | ||
| 2402 | } | ||
| 2403 | |||
| 2404 | |||
| 2405 | /** | ||
| 2406 | * Returns the current y coordinate of the components origin. | ||
| 2407 | * This method is preferable to writing | ||
| 2408 | * <code>component.getBounds().y</code>, | ||
| 2409 | * or <code>component.getLocation().y</code> because it | ||
| 2410 | * doesn't cause any heap allocations. | ||
| 2411 | * | ||
| 2412 | * @return the current y coordinate of the components origin | ||
| 2413 | * @since 1.2 | ||
| 2414 | */ | ||
| 2415 | public int getY() { | ||
| 2416 | return y; | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | |||
| 2420 | /** | ||
| 2421 | * Returns the current width of this component. | ||
| 2422 | * This method is preferable to writing | ||
| 2423 | * <code>component.getBounds().width</code>, | ||
| 2424 | * or <code>component.getSize().width</code> because it | ||
| 2425 | * doesn't cause any heap allocations. | ||
| 2426 | * | ||
| 2427 | * @return the current width of this component | ||
| 2428 | * @since 1.2 | ||
| 2429 | */ | ||
| 2430 | public int getWidth() { | ||
| 2431 | return width; | ||
| 2432 | } | ||
| 2433 | |||
| 2434 | |||
| 2435 | /** | ||
| 2436 | * Returns the current height of this component. | ||
| 2437 | * This method is preferable to writing | ||
| 2438 | * <code>component.getBounds().height</code>, | ||
| 2439 | * or <code>component.getSize().height</code> because it | ||
| 2440 | * doesn't cause any heap allocations. | ||
| 2441 | * | ||
| 2442 | * @return the current height of this component | ||
| 2443 | * @since 1.2 | ||
| 2444 | */ | ||
| 2445 | public int getHeight() { | ||
| 2446 | return height; | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | /** | ||
| 2450 | * Stores the bounds of this component into "return value" <b>rv</b> and | ||
| 2451 | * return <b>rv</b>. If rv is <code>null</code> a new | ||
| 2452 | * <code>Rectangle</code> is allocated. | ||
| 2453 | * This version of <code>getBounds</code> is useful if the caller | ||
| 2454 | * wants to avoid allocating a new <code>Rectangle</code> object | ||
| 2455 | * on the heap. | ||
| 2456 | * | ||
| 2457 | * @param rv the return value, modified to the components bounds | ||
| 2458 | * @return rv | ||
| 2459 | */ | ||
| 2460 | public Rectangle getBounds(Rectangle rv) { | ||
| 2461 | if (rv == null) { | ||
| 2462 | return new Rectangle(getX(), getY(), getWidth(), getHeight()); | ||
| 2463 | } | ||
| 2464 | else { | ||
| 2465 | rv.setBounds(getX(), getY(), getWidth(), getHeight()); | ||
| 2466 | return rv; | ||
| 2467 | } | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | /** | ||
| 2471 | * Stores the width/height of this component into "return value" <b>rv</b> | ||
| 2472 | * and return <b>rv</b>. If rv is <code>null</code> a new | ||
| 2473 | * <code>Dimension</code> object is allocated. This version of | ||
| 2474 | * <code>getSize</code> is useful if the caller wants to avoid | ||
| 2475 | * allocating a new <code>Dimension</code> object on the heap. | ||
| 2476 | * | ||
| 2477 | * @param rv the return value, modified to the components size | ||
| 2478 | * @return rv | ||
| 2479 | */ | ||
| 2480 | public Dimension getSize(Dimension rv) { | ||
| 2481 | if (rv == null) { | ||
| 2482 | return new Dimension(getWidth(), getHeight()); | ||
| 2483 | } | ||
| 2484 | else { | ||
| 2485 | rv.setSize(getWidth(), getHeight()); | ||
| 2486 | return rv; | ||
| 2487 | } | ||
| 2488 | } | ||
| 2489 | |||
| 2490 | /** | ||
| 2491 | * Stores the x,y origin of this component into "return value" <b>rv</b> | ||
| 2492 | * and return <b>rv</b>. If rv is <code>null</code> a new | ||
| 2493 | * <code>Point</code> is allocated. | ||
| 2494 | * This version of <code>getLocation</code> is useful if the | ||
| 2495 | * caller wants to avoid allocating a new <code>Point</code> | ||
| 2496 | * object on the heap. | ||
| 2497 | * | ||
| 2498 | * @param rv the return value, modified to the components location | ||
| 2499 | * @return rv | ||
| 2500 | */ | ||
| 2501 | public Point getLocation(Point rv) { | ||
| 2502 | if (rv == null) { | ||
| 2503 | return new Point(getX(), getY()); | ||
| 2504 | } | ||
| 2505 | else { | ||
| 2506 | rv.setLocation(getX(), getY()); | ||
| 2507 | return rv; | ||
| 2508 | } | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | /** | ||
| 2512 | * Returns true if this component is completely opaque, returns | ||
| 2513 | * false by default. | ||
| 2514 | * <p> | ||
| 2515 | * An opaque component paints every pixel within its | ||
| 2516 | * rectangular region. A non-opaque component paints only some of | ||
| 2517 | * its pixels, allowing the pixels underneath it to "show through". | ||
| 2518 | * A component that does not fully paint its pixels therefore | ||
| 2519 | * provides a degree of transparency. | ||
| 2520 | * <p> | ||
| 2521 | * Subclasses that guarantee to always completely paint their | ||
| 2522 | * contents should override this method and return true. | ||
| 2523 | * | ||
| 2524 | * @return true if this component is completely opaque | ||
| 2525 | * @see #isLightweight | ||
| 2526 | * @since 1.2 | ||
| 2527 | */ | ||
| 2528 | public boolean isOpaque() { | ||
| 2529 | if (getPeer() == null) { | ||
| 2530 | return false; | ||
| 2531 | } | ||
| 2532 | else { | ||
| 2533 | return !isLightweight(); | ||
| 2534 | } | ||
| 2535 | } | ||
| 2536 | |||
| 2537 | |||
| 2538 | /** | ||
| 2539 | * A lightweight component doesn't have a native toolkit peer. | ||
| 2540 | * Subclasses of <code>Component</code> and <code>Container</code>, | ||
| 2541 | * other than the ones defined in this package like <code>Button</code> | ||
| 2542 | * or <code>Scrollbar</code>, are lightweight. | ||
| 2543 | * All of the Swing components are lightweights. | ||
| 2544 | * <p> | ||
| 2545 | * This method will always return <code>false</code> if this component | ||
| 2546 | * is not displayable because it is impossible to determine the | ||
| 2547 | * weight of an undisplayable component. | ||
| 2548 | * | ||
| 2549 | * @return true if this component has a lightweight peer; false if | ||
| 2550 | * it has a native peer or no peer | ||
| 2551 | * @see #isDisplayable | ||
| 2552 | * @since 1.2 | ||
| 2553 | */ | ||
| 2554 | public boolean isLightweight() { | ||
| 2555 | return getPeer() instanceof LightweightPeer; | ||
| 2556 | } | ||
| 2557 | |||
| 2558 | |||
| 2559 | /** | ||
| 2560 | * Sets the preferred size of this component to a constant | ||
| 2561 | * value. Subsequent calls to <code>getPreferredSize</code> will always | ||
| 2562 | * return this value. Setting the preferred size to <code>null</code> | ||
| 2563 | * restores the default behavior. | ||
| 2564 | * | ||
| 2565 | * @param preferredSize The new preferred size, or null | ||
| 2566 | * @see #getPreferredSize | ||
| 2567 | * @see #isPreferredSizeSet | ||
| 2568 | * @since 1.5 | ||
| 2569 | */ | ||
| 2570 | public void setPreferredSize(Dimension preferredSize) { | ||
| 2571 | Dimension old; | ||
| 2572 | // If the preferred size was set, use it as the old value, otherwise | ||
| 2573 | // use null to indicate we didn't previously have a set preferred | ||
| 2574 | // size. | ||
| 2575 | if (prefSizeSet) { | ||
| 2576 | old = this.prefSize; | ||
| 2577 | } | ||
| 2578 | else { | ||
| 2579 | old = null; | ||
| 2580 | } | ||
| 2581 | this.prefSize = preferredSize; | ||
| 2582 | prefSizeSet = (preferredSize != null); | ||
| 2583 | firePropertyChange("preferredSize", old, preferredSize); | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | |||
| 2587 | /** | ||
| 2588 | * Returns true if the preferred size has been set to a | ||
| 2589 | * non-<code>null</code> value otherwise returns false. | ||
| 2590 | * | ||
| 2591 | * @return true if <code>setPreferredSize</code> has been invoked | ||
| 2592 | * with a non-null value. | ||
| 2593 | * @since 1.5 | ||
| 2594 | */ | ||
| 2595 | public boolean isPreferredSizeSet() { | ||
| 2596 | return prefSizeSet; | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | |||
| 2600 | /** | ||
| 2601 | * Gets the preferred size of this component. | ||
| 2602 | * @return a dimension object indicating this component's preferred size | ||
| 2603 | * @see #getMinimumSize | ||
| 2604 | * @see LayoutManager | ||
| 2605 | */ | ||
| 2606 | public Dimension getPreferredSize() { | ||
| 2607 | return preferredSize(); | ||
| 2608 | } | ||
| 2609 | |||
| 2610 | |||
| 2611 | /** | ||
| 2612 | * @deprecated As of JDK version 1.1, | ||
| 2613 | * replaced by <code>getPreferredSize()</code>. | ||
| 2614 | */ | ||
| 2615 | @Deprecated | ||
| 2616 | public Dimension preferredSize() { | ||
| 2617 | /* Avoid grabbing the lock if a reasonable cached size value | ||
| 2618 | * is available. | ||
| 2619 | */ | ||
| 2620 | Dimension dim = prefSize; | ||
| 2621 | if (dim == null || !(isPreferredSizeSet() || isValid())) { | ||
| 2622 | synchronized (getTreeLock()) { | ||
| 2623 | prefSize = (peer != null) ? | ||
| 2624 | peer.getPreferredSize() : | ||
| 2625 | getMinimumSize(); | ||
| 2626 | dim = prefSize; | ||
| 2627 | } | ||
| 2628 | } | ||
| 2629 | return new Dimension(dim); | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | /** | ||
| 2633 | * Sets the minimum size of this component to a constant | ||
| 2634 | * value. Subsequent calls to <code>getMinimumSize</code> will always | ||
| 2635 | * return this value. Setting the minimum size to <code>null</code> | ||
| 2636 | * restores the default behavior. | ||
| 2637 | * | ||
| 2638 | * @param minimumSize the new minimum size of this component | ||
| 2639 | * @see #getMinimumSize | ||
| 2640 | * @see #isMinimumSizeSet | ||
| 2641 | * @since 1.5 | ||
| 2642 | */ | ||
| 2643 | public void setMinimumSize(Dimension minimumSize) { | ||
| 2644 | Dimension old; | ||
| 2645 | // If the minimum size was set, use it as the old value, otherwise | ||
| 2646 | // use null to indicate we didn't previously have a set minimum | ||
| 2647 | // size. | ||
| 2648 | if (minSizeSet) { | ||
| 2649 | old = this.minSize; | ||
| 2650 | } | ||
| 2651 | else { | ||
| 2652 | old = null; | ||
| 2653 | } | ||
| 2654 | this.minSize = minimumSize; | ||
| 2655 | minSizeSet = (minimumSize != null); | ||
| 2656 | firePropertyChange("minimumSize", old, minimumSize); | ||
| 2657 | } | ||
| 2658 | |||
| 2659 | /** | ||
| 2660 | * Returns whether or not <code>setMinimumSize</code> has been | ||
| 2661 | * invoked with a non-null value. | ||
| 2662 | * | ||
| 2663 | * @return true if <code>setMinimumSize</code> has been invoked with a | ||
| 2664 | * non-null value. | ||
| 2665 | * @since 1.5 | ||
| 2666 | */ | ||
| 2667 | public boolean isMinimumSizeSet() { | ||
| 2668 | return minSizeSet; | ||
| 2669 | } | ||
| 2670 | |||
| 2671 | /** | ||
| 2672 | * Gets the mininimum size of this component. | ||
| 2673 | * @return a dimension object indicating this component's minimum size | ||
| 2674 | * @see #getPreferredSize | ||
| 2675 | * @see LayoutManager | ||
| 2676 | */ | ||
| 2677 | public Dimension getMinimumSize() { | ||
| 2678 | return minimumSize(); | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | /** | ||
| 2682 | * @deprecated As of JDK version 1.1, | ||
| 2683 | * replaced by <code>getMinimumSize()</code>. | ||
| 2684 | */ | ||
| 2685 | @Deprecated | ||
| 2686 | public Dimension minimumSize() { | ||
| 2687 | /* Avoid grabbing the lock if a reasonable cached size value | ||
| 2688 | * is available. | ||
| 2689 | */ | ||
| 2690 | Dimension dim = minSize; | ||
| 2691 | if (dim == null || !(isMinimumSizeSet() || isValid())) { | ||
| 2692 | synchronized (getTreeLock()) { | ||
| 2693 | minSize = (peer != null) ? | ||
| 2694 | peer.getMinimumSize() : | ||
| 2695 | size(); | ||
| 2696 | dim = minSize; | ||
| 2697 | } | ||
| 2698 | } | ||
| 2699 | return new Dimension(dim); | ||
| 2700 | } | ||
| 2701 | |||
| 2702 | /** | ||
| 2703 | * Sets the maximum size of this component to a constant | ||
| 2704 | * value. Subsequent calls to <code>getMaximumSize</code> will always | ||
| 2705 | * return this value. Setting the maximum size to <code>null</code> | ||
| 2706 | * restores the default behavior. | ||
| 2707 | * | ||
| 2708 | * @param maximumSize a <code>Dimension</code> containing the | ||
| 2709 | * desired maximum allowable size | ||
| 2710 | * @see #getMaximumSize | ||
| 2711 | * @see #isMaximumSizeSet | ||
| 2712 | * @since 1.5 | ||
| 2713 | */ | ||
| 2714 | public void setMaximumSize(Dimension maximumSize) { | ||
| 2715 | // If the maximum size was set, use it as the old value, otherwise | ||
| 2716 | // use null to indicate we didn't previously have a set maximum | ||
| 2717 | // size. | ||
| 2718 | Dimension old; | ||
| 2719 | if (maxSizeSet) { | ||
| 2720 | old = this.maxSize; | ||
| 2721 | } | ||
| 2722 | else { | ||
| 2723 | old = null; | ||
| 2724 | } | ||
| 2725 | this.maxSize = maximumSize; | ||
| 2726 | maxSizeSet = (maximumSize != null); | ||
| 2727 | firePropertyChange("maximumSize", old, maximumSize); | ||
| 2728 | } | ||
| 2729 | |||
| 2730 | /** | ||
| 2731 | * Returns true if the maximum size has been set to a non-<code>null</code> | ||
| 2732 | * value otherwise returns false. | ||
| 2733 | * | ||
| 2734 | * @return true if <code>maximumSize</code> is non-<code>null</code>, | ||
| 2735 | * false otherwise | ||
| 2736 | * @since 1.5 | ||
| 2737 | */ | ||
| 2738 | public boolean isMaximumSizeSet() { | ||
| 2739 | return maxSizeSet; | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | /** | ||
| 2743 | * Gets the maximum size of this component. | ||
| 2744 | * @return a dimension object indicating this component's maximum size | ||
| 2745 | * @see #getMinimumSize | ||
| 2746 | * @see #getPreferredSize | ||
| 2747 | * @see LayoutManager | ||
| 2748 | */ | ||
| 2749 | public Dimension getMaximumSize() { | ||
| 2750 | if (isMaximumSizeSet()) { | ||
| 2751 | return new Dimension(maxSize); | ||
| 2752 | } | ||
| 2753 | return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | /** | ||
| 2757 | * Returns the alignment along the x axis. This specifies how | ||
| 2758 | * the component would like to be aligned relative to other | ||
| 2759 | * components. The value should be a number between 0 and 1 | ||
| 2760 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 2761 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 2762 | */ | ||
| 2763 | public float getAlignmentX() { | ||
| 2764 | return CENTER_ALIGNMENT; | ||
| 2765 | } | ||
| 2766 | |||
| 2767 | /** | ||
| 2768 | * Returns the alignment along the y axis. This specifies how | ||
| 2769 | * the component would like to be aligned relative to other | ||
| 2770 | * components. The value should be a number between 0 and 1 | ||
| 2771 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 2772 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 2773 | */ | ||
| 2774 | public float getAlignmentY() { | ||
| 2775 | return CENTER_ALIGNMENT; | ||
| 2776 | } | ||
| 2777 | |||
| 2778 | /** | ||
| 2779 | * Returns the baseline. The baseline is measured from the top of | ||
| 2780 | * the component. This method is primarily meant for | ||
| 2781 | * <code>LayoutManager</code>s to align components along their | ||
| 2782 | * baseline. A return value less than 0 indicates this component | ||
| 2783 | * does not have a reasonable baseline and that | ||
| 2784 | * <code>LayoutManager</code>s should not align this component on | ||
| 2785 | * its baseline. | ||
| 2786 | * <p> | ||
| 2787 | * The default implementation returns -1. Subclasses that support | ||
| 2788 | * baseline should override appropriately. If a value >= 0 is | ||
| 2789 | * returned, then the component has a valid baseline for any | ||
| 2790 | * size >= the minimum size and <code>getBaselineResizeBehavior</code> | ||
| 2791 | * can be used to determine how the baseline changes with size. | ||
| 2792 | * | ||
| 2793 | * @param width the width to get the baseline for | ||
| 2794 | * @param height the height to get the baseline for | ||
| 2795 | * @return the baseline or < 0 indicating there is no reasonable | ||
| 2796 | * baseline | ||
| 2797 | * @throws IllegalArgumentException if width or height is < 0 | ||
| 2798 | * @see #getBaselineResizeBehavior | ||
| 2799 | * @see java.awt.FontMetrics | ||
| 2800 | * @since 1.6 | ||
| 2801 | */ | ||
| 2802 | public int getBaseline(int width, int height) { | ||
| 2803 | if (width < 0 || height < 0) { | ||
| 2804 | throw new IllegalArgumentException( | ||
| 2805 | "Width and height must be >= 0"); | ||
| 2806 | } | ||
| 2807 | return -1; | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | /** | ||
| 2811 | * Returns an enum indicating how the baseline of the component | ||
| 2812 | * changes as the size changes. This method is primarily meant for | ||
| 2813 | * layout managers and GUI builders. | ||
| 2814 | * <p> | ||
| 2815 | * The default implementation returns | ||
| 2816 | * <code>BaselineResizeBehavior.OTHER</code>. Subclasses that have a | ||
| 2817 | * baseline should override appropriately. Subclasses should | ||
| 2818 | * never return <code>null</code>; if the baseline can not be | ||
| 2819 | * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers | ||
| 2820 | * should first ask for the baseline using | ||
| 2821 | * <code>getBaseline</code> and if a value >= 0 is returned use | ||
| 2822 | * this method. It is acceptable for this method to return a | ||
| 2823 | * value other than <code>BaselineResizeBehavior.OTHER</code> even if | ||
| 2824 | * <code>getBaseline</code> returns a value less than 0. | ||
| 2825 | * | ||
| 2826 | * @return an enum indicating how the baseline changes as the component | ||
| 2827 | * size changes | ||
| 2828 | * @see #getBaseline(int, int) | ||
| 2829 | * @since 1.6 | ||
| 2830 | */ | ||
| 2831 | public BaselineResizeBehavior getBaselineResizeBehavior() { | ||
| 2832 | return BaselineResizeBehavior.OTHER; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | /** | ||
| 2836 | * Prompts the layout manager to lay out this component. This is | ||
| 2837 | * usually called when the component (more specifically, container) | ||
| 2838 | * is validated. | ||
| 2839 | * @see #validate | ||
| 2840 | * @see LayoutManager | ||
| 2841 | */ | ||
| 2842 | public void doLayout() { | ||
| 2843 | layout(); | ||
| 2844 | } | ||
| 2845 | |||
| 2846 | /** | ||
| 2847 | * @deprecated As of JDK version 1.1, | ||
| 2848 | * replaced by <code>doLayout()</code>. | ||
| 2849 | */ | ||
| 2850 | @Deprecated | ||
| 2851 | public void layout() { | ||
| 2852 | } | ||
| 2853 | |||
| 2854 | /** | ||
| 2855 | * Validates this component. | ||
| 2856 | * <p> | ||
| 2857 | * The meaning of the term <i>validating</i> is defined by the ancestors of | ||
| 2858 | * this class. See {@link Container#validate} for more details. | ||
| 2859 | * | ||
| 2860 | * @see #invalidate | ||
| 2861 | * @see #doLayout() | ||
| 2862 | * @see LayoutManager | ||
| 2863 | * @see Container#validate | ||
| 2864 | * @since JDK1.0 | ||
| 2865 | */ | ||
| 2866 | public void validate() { | ||
| 2867 | synchronized (getTreeLock()) { | ||
| 2868 | ComponentPeer peer = this.peer; | ||
| 2869 | boolean wasValid = isValid(); | ||
| 2870 | if (!wasValid && peer != null) { | ||
| 2871 | Font newfont = getFont(); | ||
| 2872 | Font oldfont = peerFont; | ||
| 2873 | if (newfont != oldfont && (oldfont == null | ||
| 2874 | || !oldfont.equals(newfont))) { | ||
| 2875 | peer.setFont(newfont); | ||
| 2876 | peerFont = newfont; | ||
| 2877 | } | ||
| 2878 | peer.layout(); | ||
| 2879 | } | ||
| 2880 | valid = true; | ||
| 2881 | if (!wasValid) { | ||
| 2882 | mixOnValidating(); | ||
| 2883 | } | ||
| 2884 | } | ||
| 2885 | } | ||
| 2886 | |||
| 2887 | /** | ||
| 2888 | * Invalidates this component and its ancestors. | ||
| 2889 | * <p> | ||
| 2890 | * By default, all the ancestors of the component up to the top-most | ||
| 2891 | * container of the hierarchy are marked invalid. If the {@code | ||
| 2892 | * java.awt.smartInvalidate} system property is set to {@code true}, | ||
| 2893 | * invalidation stops on the nearest validate root of this component. | ||
| 2894 | * Marking a container <i>invalid</i> indicates that the container needs to | ||
| 2895 | * be laid out. | ||
| 2896 | * <p> | ||
| 2897 | * This method is called automatically when any layout-related information | ||
| 2898 | * changes (e.g. setting the bounds of the component, or adding the | ||
| 2899 | * component to a container). | ||
| 2900 | * <p> | ||
| 2901 | * This method might be called often, so it should work fast. | ||
| 2902 | * | ||
| 2903 | * @see #validate | ||
| 2904 | * @see #doLayout | ||
| 2905 | * @see LayoutManager | ||
| 2906 | * @see java.awt.Container#isValidateRoot | ||
| 2907 | * @since JDK1.0 | ||
| 2908 | */ | ||
| 2909 | public void invalidate() { | ||
| 2910 | synchronized (getTreeLock()) { | ||
| 2911 | /* Nullify cached layout and size information. | ||
| 2912 | * For efficiency, propagate invalidate() upwards only if | ||
| 2913 | * some other component hasn't already done so first. | ||
| 2914 | */ | ||
| 2915 | valid = false; | ||
| 2916 | if (!isPreferredSizeSet()) { | ||
| 2917 | prefSize = null; | ||
| 2918 | } | ||
| 2919 | if (!isMinimumSizeSet()) { | ||
| 2920 | minSize = null; | ||
| 2921 | } | ||
| 2922 | if (!isMaximumSizeSet()) { | ||
| 2923 | maxSize = null; | ||
| 2924 | } | ||
| 2925 | invalidateParent(); | ||
| 2926 | } | ||
| 2927 | } | ||
| 2928 | |||
| 2929 | /** | ||
| 2930 | * Invalidates the parent of this component if any. | ||
| 2931 | * | ||
| 2932 | * This method MUST BE invoked under the TreeLock. | ||
| 2933 | */ | ||
| 2934 | void invalidateParent() { | ||
| 2935 | if (parent != null) { | ||
| 2936 | parent.invalidateIfValid(); | ||
| 2937 | } | ||
| 2938 | } | ||
| 2939 | |||
| 2940 | /** Invalidates the component unless it is already invalid. | ||
| 2941 | */ | ||
| 2942 | final void invalidateIfValid() { | ||
| 2943 | if (isValid()) { | ||
| 2944 | invalidate(); | ||
| 2945 | } | ||
| 2946 | } | ||
| 2947 | |||
| 2948 | /** | ||
| 2949 | * Revalidates the component hierarchy up to the nearest validate root. | ||
| 2950 | * <p> | ||
| 2951 | * This method first invalidates the component hierarchy starting from this | ||
| 2952 | * component up to the nearest validate root. Afterwards, the component | ||
| 2953 | * hierarchy is validated starting from the nearest validate root. | ||
| 2954 | * <p> | ||
| 2955 | * This is a convenience method supposed to help application developers | ||
| 2956 | * avoid looking for validate roots manually. Basically, it's equivalent to | ||
| 2957 | * first calling the {@link #invalidate()} method on this component, and | ||
| 2958 | * then calling the {@link #validate()} method on the nearest validate | ||
| 2959 | * root. | ||
| 2960 | * | ||
| 2961 | * @see Container#isValidateRoot | ||
| 2962 | * @since 1.7 | ||
| 2963 | */ | ||
| 2964 | public void revalidate() { | ||
| 2965 | synchronized (getTreeLock()) { | ||
| 2966 | invalidate(); | ||
| 2967 | |||
| 2968 | Container root = getContainer(); | ||
| 2969 | if (root == null) { | ||
| 2970 | // There's no parents. Just validate itself. | ||
| 2971 | validate(); | ||
| 2972 | } else { | ||
| 2973 | while (!root.isValidateRoot()) { | ||
| 2974 | if (root.getContainer() == null) { | ||
| 2975 | // If there's no validate roots, we'll validate the | ||
| 2976 | // topmost container | ||
| 2977 | break; | ||
| 2978 | } | ||
| 2979 | |||
| 2980 | root = root.getContainer(); | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | root.validate(); | ||
| 2984 | } | ||
| 2985 | } | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | /** | ||
| 2989 | * Creates a graphics context for this component. This method will | ||
| 2990 | * return <code>null</code> if this component is currently not | ||
| 2991 | * displayable. | ||
| 2992 | * @return a graphics context for this component, or <code>null</code> | ||
| 2993 | * if it has none | ||
| 2994 | * @see #paint | ||
| 2995 | * @since JDK1.0 | ||
| 2996 | */ | ||
| 2997 | public Graphics getGraphics() { | ||
| 2998 | if (peer instanceof LightweightPeer) { | ||
| 2999 | // This is for a lightweight component, need to | ||
| 3000 | // translate coordinate spaces and clip relative | ||
| 3001 | // to the parent. | ||
| 3002 | if (parent == null) return null; | ||
| 3003 | Graphics g = parent.getGraphics(); | ||
| 3004 | if (g == null) return null; | ||
| 3005 | if (g instanceof ConstrainableGraphics) { | ||
| 3006 | ((ConstrainableGraphics) g).constrain(x, y, width, height); | ||
| 3007 | } else { | ||
| 3008 | g.translate(x,y); | ||
| 3009 | g.setClip(0, 0, width, height); | ||
| 3010 | } | ||
| 3011 | g.setFont(getFont()); | ||
| 3012 | return g; | ||
| 3013 | } else { | ||
| 3014 | ComponentPeer peer = this.peer; | ||
| 3015 | return (peer != null) ? peer.getGraphics() : null; | ||
| 3016 | } | ||
| 3017 | } | ||
| 3018 | |||
| 3019 | final Graphics getGraphics_NoClientCode() { | ||
| 3020 | ComponentPeer peer = this.peer; | ||
| 3021 | if (peer instanceof LightweightPeer) { | ||
| 3022 | // This is for a lightweight component, need to | ||
| 3023 | // translate coordinate spaces and clip relative | ||
| 3024 | // to the parent. | ||
| 3025 | Container parent = this.parent; | ||
| 3026 | if (parent == null) return null; | ||
| 3027 | Graphics g = parent.getGraphics_NoClientCode(); | ||
| 3028 | if (g == null) return null; | ||
| 3029 | if (g instanceof ConstrainableGraphics) { | ||
| 3030 | ((ConstrainableGraphics) g).constrain(x, y, width, height); | ||
| 3031 | } else { | ||
| 3032 | g.translate(x,y); | ||
| 3033 | g.setClip(0, 0, width, height); | ||
| 3034 | } | ||
| 3035 | g.setFont(getFont_NoClientCode()); | ||
| 3036 | return g; | ||
| 3037 | } else { | ||
| 3038 | return (peer != null) ? peer.getGraphics() : null; | ||
| 3039 | } | ||
| 3040 | } | ||
| 3041 | |||
| 3042 | /** | ||
| 3043 | * Gets the font metrics for the specified font. | ||
| 3044 | * Warning: Since Font metrics are affected by the | ||
| 3045 | * {@link java.awt.font.FontRenderContext FontRenderContext} and | ||
| 3046 | * this method does not provide one, it can return only metrics for | ||
| 3047 | * the default render context which may not match that used when | ||
| 3048 | * rendering on the Component if {@link Graphics2D} functionality is being | ||
| 3049 | * used. Instead metrics can be obtained at rendering time by calling | ||
| 3050 | * {@link Graphics#getFontMetrics()} or text measurement APIs on the | ||
| 3051 | * {@link Font Font} class. | ||
| 3052 | * @param font the font for which font metrics is to be | ||
| 3053 | * obtained | ||
| 3054 | * @return the font metrics for <code>font</code> | ||
| 3055 | * @see #getFont | ||
| 3056 | * @see #getPeer | ||
| 3057 | * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) | ||
| 3058 | * @see Toolkit#getFontMetrics(Font) | ||
| 3059 | * @since JDK1.0 | ||
| 3060 | */ | ||
| 3061 | public FontMetrics getFontMetrics(Font font) { | ||
| 3062 | // This is an unsupported hack, but left in for a customer. | ||
| 3063 | // Do not remove. | ||
| 3064 | FontManager fm = FontManagerFactory.getInstance(); | ||
| 3065 | if (fm instanceof SunFontManager | ||
| 3066 | && ((SunFontManager) fm).usePlatformFontMetrics()) { | ||
| 3067 | |||
| 3068 | if (peer != null && | ||
| 3069 | !(peer instanceof LightweightPeer)) { | ||
| 3070 | return peer.getFontMetrics(font); | ||
| 3071 | } | ||
| 3072 | } | ||
| 3073 | return sun.font.FontDesignMetrics.getMetrics(font); | ||
| 3074 | } | ||
| 3075 | |||
| 3076 | /** | ||
| 3077 | * Sets the cursor image to the specified cursor. This cursor | ||
| 3078 | * image is displayed when the <code>contains</code> method for | ||
| 3079 | * this component returns true for the current cursor location, and | ||
| 3080 | * this Component is visible, displayable, and enabled. Setting the | ||
| 3081 | * cursor of a <code>Container</code> causes that cursor to be displayed | ||
| 3082 | * within all of the container's subcomponents, except for those | ||
| 3083 | * that have a non-<code>null</code> cursor. | ||
| 3084 | * <p> | ||
| 3085 | * The method may have no visual effect if the Java platform | ||
| 3086 | * implementation and/or the native system do not support | ||
| 3087 | * changing the mouse cursor shape. | ||
| 3088 | * @param cursor One of the constants defined | ||
| 3089 | * by the <code>Cursor</code> class; | ||
| 3090 | * if this parameter is <code>null</code> | ||
| 3091 | * then this component will inherit | ||
| 3092 | * the cursor of its parent | ||
| 3093 | * @see #isEnabled | ||
| 3094 | * @see #isShowing | ||
| 3095 | * @see #getCursor | ||
| 3096 | * @see #contains | ||
| 3097 | * @see Toolkit#createCustomCursor | ||
| 3098 | * @see Cursor | ||
| 3099 | * @since JDK1.1 | ||
| 3100 | */ | ||
| 3101 | public void setCursor(Cursor cursor) { | ||
| 3102 | this.cursor = cursor; | ||
| 3103 | updateCursorImmediately(); | ||
| 3104 | } | ||
| 3105 | |||
| 3106 | /** | ||
| 3107 | * Updates the cursor. May not be invoked from the native | ||
| 3108 | * message pump. | ||
| 3109 | */ | ||
| 3110 | final void updateCursorImmediately() { | ||
| 3111 | if (peer instanceof LightweightPeer) { | ||
| 3112 | Container nativeContainer = getNativeContainer(); | ||
| 3113 | |||
| 3114 | if (nativeContainer == null) return; | ||
| 3115 | |||
| 3116 | ComponentPeer cPeer = nativeContainer.getPeer(); | ||
| 3117 | |||
| 3118 | if (cPeer != null) { | ||
| 3119 | cPeer.updateCursorImmediately(); | ||
| 3120 | } | ||
| 3121 | } else if (peer != null) { | ||
| 3122 | peer.updateCursorImmediately(); | ||
| 3123 | } | ||
| 3124 | } | ||
| 3125 | |||
| 3126 | /** | ||
| 3127 | * Gets the cursor set in the component. If the component does | ||
| 3128 | * not have a cursor set, the cursor of its parent is returned. | ||
| 3129 | * If no cursor is set in the entire hierarchy, | ||
| 3130 | * <code>Cursor.DEFAULT_CURSOR</code> is returned. | ||
| 3131 | * @see #setCursor | ||
| 3132 | * @since JDK1.1 | ||
| 3133 | */ | ||
| 3134 | public Cursor getCursor() { | ||
| 3135 | return getCursor_NoClientCode(); | ||
| 3136 | } | ||
| 3137 | |||
| 3138 | final Cursor getCursor_NoClientCode() { | ||
| 3139 | Cursor cursor = this.cursor; | ||
| 3140 | if (cursor != null) { | ||
| 3141 | return cursor; | ||
| 3142 | } | ||
| 3143 | Container parent = this.parent; | ||
| 3144 | if (parent != null) { | ||
| 3145 | return parent.getCursor_NoClientCode(); | ||
| 3146 | } else { | ||
| 3147 | return Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); | ||
| 3148 | } | ||
| 3149 | } | ||
| 3150 | |||
| 3151 | /** | ||
| 3152 | * Returns whether the cursor has been explicitly set for this Component. | ||
| 3153 | * If this method returns <code>false</code>, this Component is inheriting | ||
| 3154 | * its cursor from an ancestor. | ||
| 3155 | * | ||
| 3156 | * @return <code>true</code> if the cursor has been explicitly set for this | ||
| 3157 | * Component; <code>false</code> otherwise. | ||
| 3158 | * @since 1.4 | ||
| 3159 | */ | ||
| 3160 | public boolean isCursorSet() { | ||
| 3161 | return (cursor != null); | ||
| 3162 | } | ||
| 3163 | |||
| 3164 | /** | ||
| 3165 | * Paints this component. | ||
| 3166 | * <p> | ||
| 3167 | * This method is called when the contents of the component should | ||
| 3168 | * be painted; such as when the component is first being shown or | ||
| 3169 | * is damaged and in need of repair. The clip rectangle in the | ||
| 3170 | * <code>Graphics</code> parameter is set to the area | ||
| 3171 | * which needs to be painted. | ||
| 3172 | * Subclasses of <code>Component</code> that override this | ||
| 3173 | * method need not call <code>super.paint(g)</code>. | ||
| 3174 | * <p> | ||
| 3175 | * For performance reasons, <code>Component</code>s with zero width | ||
| 3176 | * or height aren't considered to need painting when they are first shown, | ||
| 3177 | * and also aren't considered to need repair. | ||
| 3178 | * <p> | ||
| 3179 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3180 | * by AWT and Swing, including information on how to write the most | ||
| 3181 | * efficient painting code, see | ||
| 3182 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3183 | * | ||
| 3184 | * @param g the graphics context to use for painting | ||
| 3185 | * @see #update | ||
| 3186 | * @since JDK1.0 | ||
| 3187 | */ | ||
| 3188 | public void paint(Graphics g) { | ||
| 3189 | } | ||
| 3190 | |||
| 3191 | /** | ||
| 3192 | * Updates this component. | ||
| 3193 | * <p> | ||
| 3194 | * If this component is not a lightweight component, the | ||
| 3195 | * AWT calls the <code>update</code> method in response to | ||
| 3196 | * a call to <code>repaint</code>. You can assume that | ||
| 3197 | * the background is not cleared. | ||
| 3198 | * <p> | ||
| 3199 | * The <code>update</code> method of <code>Component</code> | ||
| 3200 | * calls this component's <code>paint</code> method to redraw | ||
| 3201 | * this component. This method is commonly overridden by subclasses | ||
| 3202 | * which need to do additional work in response to a call to | ||
| 3203 | * <code>repaint</code>. | ||
| 3204 | * Subclasses of Component that override this method should either | ||
| 3205 | * call <code>super.update(g)</code>, or call <code>paint(g)</code> | ||
| 3206 | * directly from their <code>update</code> method. | ||
| 3207 | * <p> | ||
| 3208 | * The origin of the graphics context, its | ||
| 3209 | * (<code>0</code>, <code>0</code>) coordinate point, is the | ||
| 3210 | * top-left corner of this component. The clipping region of the | ||
| 3211 | * graphics context is the bounding rectangle of this component. | ||
| 3212 | * | ||
| 3213 | * <p> | ||
| 3214 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3215 | * by AWT and Swing, including information on how to write the most | ||
| 3216 | * efficient painting code, see | ||
| 3217 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3218 | * | ||
| 3219 | * @param g the specified context to use for updating | ||
| 3220 | * @see #paint | ||
| 3221 | * @see #repaint() | ||
| 3222 | * @since JDK1.0 | ||
| 3223 | */ | ||
| 3224 | public void update(Graphics g) { | ||
| 3225 | paint(g); | ||
| 3226 | } | ||
| 3227 | |||
| 3228 | /** | ||
| 3229 | * Paints this component and all of its subcomponents. | ||
| 3230 | * <p> | ||
| 3231 | * The origin of the graphics context, its | ||
| 3232 | * (<code>0</code>, <code>0</code>) coordinate point, is the | ||
| 3233 | * top-left corner of this component. The clipping region of the | ||
| 3234 | * graphics context is the bounding rectangle of this component. | ||
| 3235 | * | ||
| 3236 | * @param g the graphics context to use for painting | ||
| 3237 | * @see #paint | ||
| 3238 | * @since JDK1.0 | ||
| 3239 | */ | ||
| 3240 | public void paintAll(Graphics g) { | ||
| 3241 | if (isShowing()) { | ||
| 3242 | GraphicsCallback.PeerPaintCallback.getInstance(). | ||
| 3243 | runOneComponent(this, new Rectangle(0, 0, width, height), | ||
| 3244 | g, g.getClip(), | ||
| 3245 | GraphicsCallback.LIGHTWEIGHTS | | ||
| 3246 | GraphicsCallback.HEAVYWEIGHTS); | ||
| 3247 | } | ||
| 3248 | } | ||
| 3249 | |||
| 3250 | /** | ||
| 3251 | * Simulates the peer callbacks into java.awt for painting of | ||
| 3252 | * lightweight Components. | ||
| 3253 | * @param g the graphics context to use for painting | ||
| 3254 | * @see #paintAll | ||
| 3255 | */ | ||
| 3256 | void lightweightPaint(Graphics g) { | ||
| 3257 | paint(g); | ||
| 3258 | } | ||
| 3259 | |||
| 3260 | /** | ||
| 3261 | * Paints all the heavyweight subcomponents. | ||
| 3262 | */ | ||
| 3263 | void paintHeavyweightComponents(Graphics g) { | ||
| 3264 | } | ||
| 3265 | |||
| 3266 | /** | ||
| 3267 | * Repaints this component. | ||
| 3268 | * <p> | ||
| 3269 | * If this component is a lightweight component, this method | ||
| 3270 | * causes a call to this component's <code>paint</code> | ||
| 3271 | * method as soon as possible. Otherwise, this method causes | ||
| 3272 | * a call to this component's <code>update</code> method as soon | ||
| 3273 | * as possible. | ||
| 3274 | * <p> | ||
| 3275 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3276 | * by AWT and Swing, including information on how to write the most | ||
| 3277 | * efficient painting code, see | ||
| 3278 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3279 | |||
| 3280 | * | ||
| 3281 | * @see #update(Graphics) | ||
| 3282 | * @since JDK1.0 | ||
| 3283 | */ | ||
| 3284 | public void repaint() { | ||
| 3285 | repaint(0, 0, 0, width, height); | ||
| 3286 | } | ||
| 3287 | |||
| 3288 | /** | ||
| 3289 | * Repaints the component. If this component is a lightweight | ||
| 3290 | * component, this results in a call to <code>paint</code> | ||
| 3291 | * within <code>tm</code> milliseconds. | ||
| 3292 | * <p> | ||
| 3293 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3294 | * by AWT and Swing, including information on how to write the most | ||
| 3295 | * efficient painting code, see | ||
| 3296 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3297 | * | ||
| 3298 | * @param tm maximum time in milliseconds before update | ||
| 3299 | * @see #paint | ||
| 3300 | * @see #update(Graphics) | ||
| 3301 | * @since JDK1.0 | ||
| 3302 | */ | ||
| 3303 | public void repaint(long tm) { | ||
| 3304 | repaint(tm, 0, 0, width, height); | ||
| 3305 | } | ||
| 3306 | |||
| 3307 | /** | ||
| 3308 | * Repaints the specified rectangle of this component. | ||
| 3309 | * <p> | ||
| 3310 | * If this component is a lightweight component, this method | ||
| 3311 | * causes a call to this component's <code>paint</code> method | ||
| 3312 | * as soon as possible. Otherwise, this method causes a call to | ||
| 3313 | * this component's <code>update</code> method as soon as possible. | ||
| 3314 | * <p> | ||
| 3315 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3316 | * by AWT and Swing, including information on how to write the most | ||
| 3317 | * efficient painting code, see | ||
| 3318 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3319 | * | ||
| 3320 | * @param x the <i>x</i> coordinate | ||
| 3321 | * @param y the <i>y</i> coordinate | ||
| 3322 | * @param width the width | ||
| 3323 | * @param height the height | ||
| 3324 | * @see #update(Graphics) | ||
| 3325 | * @since JDK1.0 | ||
| 3326 | */ | ||
| 3327 | public void repaint(int x, int y, int width, int height) { | ||
| 3328 | repaint(0, x, y, width, height); | ||
| 3329 | } | ||
| 3330 | |||
| 3331 | /** | ||
| 3332 | * Repaints the specified rectangle of this component within | ||
| 3333 | * <code>tm</code> milliseconds. | ||
| 3334 | * <p> | ||
| 3335 | * If this component is a lightweight component, this method causes | ||
| 3336 | * a call to this component's <code>paint</code> method. | ||
| 3337 | * Otherwise, this method causes a call to this component's | ||
| 3338 | * <code>update</code> method. | ||
| 3339 | * <p> | ||
| 3340 | * <b>Note</b>: For more information on the paint mechanisms utilitized | ||
| 3341 | * by AWT and Swing, including information on how to write the most | ||
| 3342 | * efficient painting code, see | ||
| 3343 | * <a href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">Painting in AWT and Swing</a>. | ||
| 3344 | * | ||
| 3345 | * @param tm maximum time in milliseconds before update | ||
| 3346 | * @param x the <i>x</i> coordinate | ||
| 3347 | * @param y the <i>y</i> coordinate | ||
| 3348 | * @param width the width | ||
| 3349 | * @param height the height | ||
| 3350 | * @see #update(Graphics) | ||
| 3351 | * @since JDK1.0 | ||
| 3352 | */ | ||
| 3353 | public void repaint(long tm, int x, int y, int width, int height) { | ||
| 3354 | if (this.peer instanceof LightweightPeer) { | ||
| 3355 | // Needs to be translated to parent coordinates since | ||
| 3356 | // a parent native container provides the actual repaint | ||
| 3357 | // services. Additionally, the request is restricted to | ||
| 3358 | // the bounds of the component. | ||
| 3359 | if (parent != null) { | ||
| 3360 | if (x < 0) { | ||
| 3361 | width += x; | ||
| 3362 | x = 0; | ||
| 3363 | } | ||
| 3364 | if (y < 0) { | ||
| 3365 | height += y; | ||
| 3366 | y = 0; | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | int pwidth = (width > this.width) ? this.width : width; | ||
| 3370 | int pheight = (height > this.height) ? this.height : height; | ||
| 3371 | |||
| 3372 | if (pwidth <= 0 || pheight <= 0) { | ||
| 3373 | return; | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | int px = this.x + x; | ||
| 3377 | int py = this.y + y; | ||
| 3378 | parent.repaint(tm, px, py, pwidth, pheight); | ||
| 3379 | } | ||
| 3380 | } else { | ||
| 3381 | if (isVisible() && (this.peer != null) && | ||
| 3382 | (width > 0) && (height > 0)) { | ||
| 3383 | PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE, | ||
| 3384 | new Rectangle(x, y, width, height)); | ||
| 3385 | Toolkit.getEventQueue().postEvent(e); | ||
| 3386 | } | ||
| 3387 | } | ||
| 3388 | } | ||
| 3389 | |||
| 3390 | /** | ||
| 3391 | * Prints this component. Applications should override this method | ||
| 3392 | * for components that must do special processing before being | ||
| 3393 | * printed or should be printed differently than they are painted. | ||
| 3394 | * <p> | ||
| 3395 | * The default implementation of this method calls the | ||
| 3396 | * <code>paint</code> method. | ||
| 3397 | * <p> | ||
| 3398 | * The origin of the graphics context, its | ||
| 3399 | * (<code>0</code>, <code>0</code>) coordinate point, is the | ||
| 3400 | * top-left corner of this component. The clipping region of the | ||
| 3401 | * graphics context is the bounding rectangle of this component. | ||
| 3402 | * @param g the graphics context to use for printing | ||
| 3403 | * @see #paint(Graphics) | ||
| 3404 | * @since JDK1.0 | ||
| 3405 | */ | ||
| 3406 | public void print(Graphics g) { | ||
| 3407 | paint(g); | ||
| 3408 | } | ||
| 3409 | |||
| 3410 | /** | ||
| 3411 | * Prints this component and all of its subcomponents. | ||
| 3412 | * <p> | ||
| 3413 | * The origin of the graphics context, its | ||
| 3414 | * (<code>0</code>, <code>0</code>) coordinate point, is the | ||
| 3415 | * top-left corner of this component. The clipping region of the | ||
| 3416 | * graphics context is the bounding rectangle of this component. | ||
| 3417 | * @param g the graphics context to use for printing | ||
| 3418 | * @see #print(Graphics) | ||
| 3419 | * @since JDK1.0 | ||
| 3420 | */ | ||
| 3421 | public void printAll(Graphics g) { | ||
| 3422 | if (isShowing()) { | ||
| 3423 | GraphicsCallback.PeerPrintCallback.getInstance(). | ||
| 3424 | runOneComponent(this, new Rectangle(0, 0, width, height), | ||
| 3425 | g, g.getClip(), | ||
| 3426 | GraphicsCallback.LIGHTWEIGHTS | | ||
| 3427 | GraphicsCallback.HEAVYWEIGHTS); | ||
| 3428 | } | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | /** | ||
| 3432 | * Simulates the peer callbacks into java.awt for printing of | ||
| 3433 | * lightweight Components. | ||
| 3434 | * @param g the graphics context to use for printing | ||
| 3435 | * @see #printAll | ||
| 3436 | */ | ||
| 3437 | void lightweightPrint(Graphics g) { | ||
| 3438 | print(g); | ||
| 3439 | } | ||
| 3440 | |||
| 3441 | /** | ||
| 3442 | * Prints all the heavyweight subcomponents. | ||
| 3443 | */ | ||
| 3444 | void printHeavyweightComponents(Graphics g) { | ||
| 3445 | } | ||
| 3446 | |||
| 3447 | private Insets getInsets_NoClientCode() { | ||
| 3448 | ComponentPeer peer = this.peer; | ||
| 3449 | if (peer instanceof ContainerPeer) { | ||
| 3450 | return (Insets)((ContainerPeer)peer).getInsets().clone(); | ||
| 3451 | } | ||
| 3452 | return new Insets(0, 0, 0, 0); | ||
| 3453 | } | ||
| 3454 | |||
| 3455 | /** | ||
| 3456 | * Repaints the component when the image has changed. | ||
| 3457 | * This <code>imageUpdate</code> method of an <code>ImageObserver</code> | ||
| 3458 | * is called when more information about an | ||
| 3459 | * image which had been previously requested using an asynchronous | ||
| 3460 | * routine such as the <code>drawImage</code> method of | ||
| 3461 | * <code>Graphics</code> becomes available. | ||
| 3462 | * See the definition of <code>imageUpdate</code> for | ||
| 3463 | * more information on this method and its arguments. | ||
| 3464 | * <p> | ||
| 3465 | * The <code>imageUpdate</code> method of <code>Component</code> | ||
| 3466 | * incrementally draws an image on the component as more of the bits | ||
| 3467 | * of the image are available. | ||
| 3468 | * <p> | ||
| 3469 | * If the system property <code>awt.image.incrementaldraw</code> | ||
| 3470 | * is missing or has the value <code>true</code>, the image is | ||
| 3471 | * incrementally drawn. If the system property has any other value, | ||
| 3472 | * then the image is not drawn until it has been completely loaded. | ||
| 3473 | * <p> | ||
| 3474 | * Also, if incremental drawing is in effect, the value of the | ||
| 3475 | * system property <code>awt.image.redrawrate</code> is interpreted | ||
| 3476 | * as an integer to give the maximum redraw rate, in milliseconds. If | ||
| 3477 | * the system property is missing or cannot be interpreted as an | ||
| 3478 | * integer, the redraw rate is once every 100ms. | ||
| 3479 | * <p> | ||
| 3480 | * The interpretation of the <code>x</code>, <code>y</code>, | ||
| 3481 | * <code>width</code>, and <code>height</code> arguments depends on | ||
| 3482 | * the value of the <code>infoflags</code> argument. | ||
| 3483 | * | ||
| 3484 | * @param img the image being observed | ||
| 3485 | * @param infoflags see <code>imageUpdate</code> for more information | ||
| 3486 | * @param x the <i>x</i> coordinate | ||
| 3487 | * @param y the <i>y</i> coordinate | ||
| 3488 | * @param w the width | ||
| 3489 | * @param h the height | ||
| 3490 | * @return <code>false</code> if the infoflags indicate that the | ||
| 3491 | * image is completely loaded; <code>true</code> otherwise. | ||
| 3492 | * | ||
| 3493 | * @see java.awt.image.ImageObserver | ||
| 3494 | * @see Graphics#drawImage(Image, int, int, Color, java.awt.image.ImageObserver) | ||
| 3495 | * @see Graphics#drawImage(Image, int, int, java.awt.image.ImageObserver) | ||
| 3496 | * @see Graphics#drawImage(Image, int, int, int, int, Color, java.awt.image.ImageObserver) | ||
| 3497 | * @see Graphics#drawImage(Image, int, int, int, int, java.awt.image.ImageObserver) | ||
| 3498 | * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) | ||
| 3499 | * @since JDK1.0 | ||
| 3500 | */ | ||
| 3501 | public boolean imageUpdate(Image img, int infoflags, | ||
| 3502 | int x, int y, int w, int h) { | ||
| 3503 | int rate = -1; | ||
| 3504 | if ((infoflags & (FRAMEBITS|ALLBITS)) != 0) { | ||
| 3505 | rate = 0; | ||
| 3506 | } else if ((infoflags & SOMEBITS) != 0) { | ||
| 3507 | if (isInc) { | ||
| 3508 | rate = incRate; | ||
| 3509 | if (rate < 0) { | ||
| 3510 | rate = 0; | ||
| 3511 | } | ||
| 3512 | } | ||
| 3513 | } | ||
| 3514 | if (rate >= 0) { | ||
| 3515 | repaint(rate, 0, 0, width, height); | ||
| 3516 | } | ||
| 3517 | return (infoflags & (ALLBITS|ABORT)) == 0; | ||
| 3518 | } | ||
| 3519 | |||
| 3520 | /** | ||
| 3521 | * Creates an image from the specified image producer. | ||
| 3522 | * @param producer the image producer | ||
| 3523 | * @return the image produced | ||
| 3524 | * @since JDK1.0 | ||
| 3525 | */ | ||
| 3526 | public Image createImage(ImageProducer producer) { | ||
| 3527 | ComponentPeer peer = this.peer; | ||
| 3528 | if ((peer != null) && ! (peer instanceof LightweightPeer)) { | ||
| 3529 | return peer.createImage(producer); | ||
| 3530 | } | ||
| 3531 | return getToolkit().createImage(producer); | ||
| 3532 | } | ||
| 3533 | |||
| 3534 | /** | ||
| 3535 | * Creates an off-screen drawable image | ||
| 3536 | * to be used for double buffering. | ||
| 3537 | * @param width the specified width | ||
| 3538 | * @param height the specified height | ||
| 3539 | * @return an off-screen drawable image, which can be used for double | ||
| 3540 | * buffering. The return value may be <code>null</code> if the | ||
| 3541 | * component is not displayable. This will always happen if | ||
| 3542 | * <code>GraphicsEnvironment.isHeadless()</code> returns | ||
| 3543 | * <code>true</code>. | ||
| 3544 | * @see #isDisplayable | ||
| 3545 | * @see GraphicsEnvironment#isHeadless | ||
| 3546 | * @since JDK1.0 | ||
| 3547 | */ | ||
| 3548 | public Image createImage(int width, int height) { | ||
| 3549 | ComponentPeer peer = this.peer; | ||
| 3550 | if (peer instanceof LightweightPeer) { | ||
| 3551 | if (parent != null) { return parent.createImage(width, height); } | ||
| 3552 | else { return null;} | ||
| 3553 | } else { | ||
| 3554 | return (peer != null) ? peer.createImage(width, height) : null; | ||
| 3555 | } | ||
| 3556 | } | ||
| 3557 | |||
| 3558 | /** | ||
| 3559 | * Creates a volatile off-screen drawable image | ||
| 3560 | * to be used for double buffering. | ||
| 3561 | * @param width the specified width. | ||
| 3562 | * @param height the specified height. | ||
| 3563 | * @return an off-screen drawable image, which can be used for double | ||
| 3564 | * buffering. The return value may be <code>null</code> if the | ||
| 3565 | * component is not displayable. This will always happen if | ||
| 3566 | * <code>GraphicsEnvironment.isHeadless()</code> returns | ||
| 3567 | * <code>true</code>. | ||
| 3568 | * @see java.awt.image.VolatileImage | ||
| 3569 | * @see #isDisplayable | ||
| 3570 | * @see GraphicsEnvironment#isHeadless | ||
| 3571 | * @since 1.4 | ||
| 3572 | */ | ||
| 3573 | public VolatileImage createVolatileImage(int width, int height) { | ||
| 3574 | ComponentPeer peer = this.peer; | ||
| 3575 | if (peer instanceof LightweightPeer) { | ||
| 3576 | if (parent != null) { | ||
| 3577 | return parent.createVolatileImage(width, height); | ||
| 3578 | } | ||
| 3579 | else { return null;} | ||
| 3580 | } else { | ||
| 3581 | return (peer != null) ? | ||
| 3582 | peer.createVolatileImage(width, height) : null; | ||
| 3583 | } | ||
| 3584 | } | ||
| 3585 | |||
| 3586 | /** | ||
| 3587 | * Creates a volatile off-screen drawable image, with the given capabilities. | ||
| 3588 | * The contents of this image may be lost at any time due | ||
| 3589 | * to operating system issues, so the image must be managed | ||
| 3590 | * via the <code>VolatileImage</code> interface. | ||
| 3591 | * @param width the specified width. | ||
| 3592 | * @param height the specified height. | ||
| 3593 | * @param caps the image capabilities | ||
| 3594 | * @exception AWTException if an image with the specified capabilities cannot | ||
| 3595 | * be created | ||
| 3596 | * @return a VolatileImage object, which can be used | ||
| 3597 | * to manage surface contents loss and capabilities. | ||
| 3598 | * @see java.awt.image.VolatileImage | ||
| 3599 | * @since 1.4 | ||
| 3600 | */ | ||
| 3601 | public VolatileImage createVolatileImage(int width, int height, | ||
| 3602 | ImageCapabilities caps) throws AWTException { | ||
| 3603 | // REMIND : check caps | ||
| 3604 | return createVolatileImage(width, height); | ||
| 3605 | } | ||
| 3606 | |||
| 3607 | /** | ||
| 3608 | * Prepares an image for rendering on this component. The image | ||
| 3609 | * data is downloaded asynchronously in another thread and the | ||
| 3610 | * appropriate screen representation of the image is generated. | ||
| 3611 | * @param image the <code>Image</code> for which to | ||
| 3612 | * prepare a screen representation | ||
| 3613 | * @param observer the <code>ImageObserver</code> object | ||
| 3614 | * to be notified as the image is being prepared | ||
| 3615 | * @return <code>true</code> if the image has already been fully | ||
| 3616 | * prepared; <code>false</code> otherwise | ||
| 3617 | * @since JDK1.0 | ||
| 3618 | */ | ||
| 3619 | public boolean prepareImage(Image image, ImageObserver observer) { | ||
| 3620 | return prepareImage(image, -1, -1, observer); | ||
| 3621 | } | ||
| 3622 | |||
| 3623 | /** | ||
| 3624 | * Prepares an image for rendering on this component at the | ||
| 3625 | * specified width and height. | ||
| 3626 | * <p> | ||
| 3627 | * The image data is downloaded asynchronously in another thread, | ||
| 3628 | * and an appropriately scaled screen representation of the image is | ||
| 3629 | * generated. | ||
| 3630 | * @param image the instance of <code>Image</code> | ||
| 3631 | * for which to prepare a screen representation | ||
| 3632 | * @param width the width of the desired screen representation | ||
| 3633 | * @param height the height of the desired screen representation | ||
| 3634 | * @param observer the <code>ImageObserver</code> object | ||
| 3635 | * to be notified as the image is being prepared | ||
| 3636 | * @return <code>true</code> if the image has already been fully | ||
| 3637 | * prepared; <code>false</code> otherwise | ||
| 3638 | * @see java.awt.image.ImageObserver | ||
| 3639 | * @since JDK1.0 | ||
| 3640 | */ | ||
| 3641 | public boolean prepareImage(Image image, int width, int height, | ||
| 3642 | ImageObserver observer) { | ||
| 3643 | ComponentPeer peer = this.peer; | ||
| 3644 | if (peer instanceof LightweightPeer) { | ||
| 3645 | return (parent != null) | ||
| 3646 | ? parent.prepareImage(image, width, height, observer) | ||
| 3647 | : getToolkit().prepareImage(image, width, height, observer); | ||
| 3648 | } else { | ||
| 3649 | return (peer != null) | ||
| 3650 | ? peer.prepareImage(image, width, height, observer) | ||
| 3651 | : getToolkit().prepareImage(image, width, height, observer); | ||
| 3652 | } | ||
| 3653 | } | ||
| 3654 | |||
| 3655 | /** | ||
| 3656 | * Returns the status of the construction of a screen representation | ||
| 3657 | * of the specified image. | ||
| 3658 | * <p> | ||
| 3659 | * This method does not cause the image to begin loading. An | ||
| 3660 | * application must use the <code>prepareImage</code> method | ||
| 3661 | * to force the loading of an image. | ||
| 3662 | * <p> | ||
| 3663 | * Information on the flags returned by this method can be found | ||
| 3664 | * with the discussion of the <code>ImageObserver</code> interface. | ||
| 3665 | * @param image the <code>Image</code> object whose status | ||
| 3666 | * is being checked | ||
| 3667 | * @param observer the <code>ImageObserver</code> | ||
| 3668 | * object to be notified as the image is being prepared | ||
| 3669 | * @return the bitwise inclusive <b>OR</b> of | ||
| 3670 | * <code>ImageObserver</code> flags indicating what | ||
| 3671 | * information about the image is currently available | ||
| 3672 | * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) | ||
| 3673 | * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) | ||
| 3674 | * @see java.awt.image.ImageObserver | ||
| 3675 | * @since JDK1.0 | ||
| 3676 | */ | ||
| 3677 | public int checkImage(Image image, ImageObserver observer) { | ||
| 3678 | return checkImage(image, -1, -1, observer); | ||
| 3679 | } | ||
| 3680 | |||
| 3681 | /** | ||
| 3682 | * Returns the status of the construction of a screen representation | ||
| 3683 | * of the specified image. | ||
| 3684 | * <p> | ||
| 3685 | * This method does not cause the image to begin loading. An | ||
| 3686 | * application must use the <code>prepareImage</code> method | ||
| 3687 | * to force the loading of an image. | ||
| 3688 | * <p> | ||
| 3689 | * The <code>checkImage</code> method of <code>Component</code> | ||
| 3690 | * calls its peer's <code>checkImage</code> method to calculate | ||
| 3691 | * the flags. If this component does not yet have a peer, the | ||
| 3692 | * component's toolkit's <code>checkImage</code> method is called | ||
| 3693 | * instead. | ||
| 3694 | * <p> | ||
| 3695 | * Information on the flags returned by this method can be found | ||
| 3696 | * with the discussion of the <code>ImageObserver</code> interface. | ||
| 3697 | * @param image the <code>Image</code> object whose status | ||
| 3698 | * is being checked | ||
| 3699 | * @param width the width of the scaled version | ||
| 3700 | * whose status is to be checked | ||
| 3701 | * @param height the height of the scaled version | ||
| 3702 | * whose status is to be checked | ||
| 3703 | * @param observer the <code>ImageObserver</code> object | ||
| 3704 | * to be notified as the image is being prepared | ||
| 3705 | * @return the bitwise inclusive <b>OR</b> of | ||
| 3706 | * <code>ImageObserver</code> flags indicating what | ||
| 3707 | * information about the image is currently available | ||
| 3708 | * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) | ||
| 3709 | * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) | ||
| 3710 | * @see java.awt.image.ImageObserver | ||
| 3711 | * @since JDK1.0 | ||
| 3712 | */ | ||
| 3713 | public int checkImage(Image image, int width, int height, | ||
| 3714 | ImageObserver observer) { | ||
| 3715 | ComponentPeer peer = this.peer; | ||
| 3716 | if (peer instanceof LightweightPeer) { | ||
| 3717 | return (parent != null) | ||
| 3718 | ? parent.checkImage(image, width, height, observer) | ||
| 3719 | : getToolkit().checkImage(image, width, height, observer); | ||
| 3720 | } else { | ||
| 3721 | return (peer != null) | ||
| 3722 | ? peer.checkImage(image, width, height, observer) | ||
| 3723 | : getToolkit().checkImage(image, width, height, observer); | ||
| 3724 | } | ||
| 3725 | } | ||
| 3726 | |||
| 3727 | /** | ||
| 3728 | * Creates a new strategy for multi-buffering on this component. | ||
| 3729 | * Multi-buffering is useful for rendering performance. This method | ||
| 3730 | * attempts to create the best strategy available with the number of | ||
| 3731 | * buffers supplied. It will always create a <code>BufferStrategy</code> | ||
| 3732 | * with that number of buffers. | ||
| 3733 | * A page-flipping strategy is attempted first, then a blitting strategy | ||
| 3734 | * using accelerated buffers. Finally, an unaccelerated blitting | ||
| 3735 | * strategy is used. | ||
| 3736 | * <p> | ||
| 3737 | * Each time this method is called, | ||
| 3738 | * the existing buffer strategy for this component is discarded. | ||
| 3739 | * @param numBuffers number of buffers to create, including the front buffer | ||
| 3740 | * @exception IllegalArgumentException if numBuffers is less than 1. | ||
| 3741 | * @exception IllegalStateException if the component is not displayable | ||
| 3742 | * @see #isDisplayable | ||
| 3743 | * @see Window#getBufferStrategy() | ||
| 3744 | * @see Canvas#getBufferStrategy() | ||
| 3745 | * @since 1.4 | ||
| 3746 | */ | ||
| 3747 | void createBufferStrategy(int numBuffers) { | ||
| 3748 | BufferCapabilities bufferCaps; | ||
| 3749 | if (numBuffers > 1) { | ||
| 3750 | // Try to create a page-flipping strategy | ||
| 3751 | bufferCaps = new BufferCapabilities(new ImageCapabilities(true), | ||
| 3752 | new ImageCapabilities(true), | ||
| 3753 | BufferCapabilities.FlipContents.UNDEFINED); | ||
| 3754 | try { | ||
| 3755 | createBufferStrategy(numBuffers, bufferCaps); | ||
| 3756 | return; // Success | ||
| 3757 | } catch (AWTException e) { | ||
| 3758 | // Failed | ||
| 3759 | } | ||
| 3760 | } | ||
| 3761 | // Try a blitting (but still accelerated) strategy | ||
| 3762 | bufferCaps = new BufferCapabilities(new ImageCapabilities(true), | ||
| 3763 | new ImageCapabilities(true), | ||
| 3764 | null); | ||
| 3765 | try { | ||
| 3766 | createBufferStrategy(numBuffers, bufferCaps); | ||
| 3767 | return; // Success | ||
| 3768 | } catch (AWTException e) { | ||
| 3769 | // Failed | ||
| 3770 | } | ||
| 3771 | // Try an unaccelerated blitting strategy | ||
| 3772 | bufferCaps = new BufferCapabilities(new ImageCapabilities(false), | ||
| 3773 | new ImageCapabilities(false), | ||
| 3774 | null); | ||
| 3775 | try { | ||
| 3776 | createBufferStrategy(numBuffers, bufferCaps); | ||
| 3777 | return; // Success | ||
| 3778 | } catch (AWTException e) { | ||
| 3779 | // Failed | ||
| 3780 | } | ||
| 3781 | // Code should never reach here (an unaccelerated blitting | ||
| 3782 | // strategy should always work) | ||
| 3783 | throw new InternalError("Could not create a buffer strategy"); | ||
| 3784 | } | ||
| 3785 | |||
| 3786 | /** | ||
| 3787 | * Creates a new strategy for multi-buffering on this component with the | ||
| 3788 | * required buffer capabilities. This is useful, for example, if only | ||
| 3789 | * accelerated memory or page flipping is desired (as specified by the | ||
| 3790 | * buffer capabilities). | ||
| 3791 | * <p> | ||
| 3792 | * Each time this method | ||
| 3793 | * is called, <code>dispose</code> will be invoked on the existing | ||
| 3794 | * <code>BufferStrategy</code>. | ||
| 3795 | * @param numBuffers number of buffers to create | ||
| 3796 | * @param caps the required capabilities for creating the buffer strategy; | ||
| 3797 | * cannot be <code>null</code> | ||
| 3798 | * @exception AWTException if the capabilities supplied could not be | ||
| 3799 | * supported or met; this may happen, for example, if there is not enough | ||
| 3800 | * accelerated memory currently available, or if page flipping is specified | ||
| 3801 | * but not possible. | ||
| 3802 | * @exception IllegalArgumentException if numBuffers is less than 1, or if | ||
| 3803 | * caps is <code>null</code> | ||
| 3804 | * @see Window#getBufferStrategy() | ||
| 3805 | * @see Canvas#getBufferStrategy() | ||
| 3806 | * @since 1.4 | ||
| 3807 | */ | ||
| 3808 | void createBufferStrategy(int numBuffers, | ||
| 3809 | BufferCapabilities caps) throws AWTException { | ||
| 3810 | // Check arguments | ||
| 3811 | if (numBuffers < 1) { | ||
| 3812 | throw new IllegalArgumentException( | ||
| 3813 | "Number of buffers must be at least 1"); | ||
| 3814 | } | ||
| 3815 | if (caps == null) { | ||
| 3816 | throw new IllegalArgumentException("No capabilities specified"); | ||
| 3817 | } | ||
| 3818 | // Destroy old buffers | ||
| 3819 | if (bufferStrategy != null) { | ||
| 3820 | bufferStrategy.dispose(); | ||
| 3821 | } | ||
| 3822 | if (numBuffers == 1) { | ||
| 3823 | bufferStrategy = new SingleBufferStrategy(caps); | ||
| 3824 | } else { | ||
| 3825 | SunGraphicsEnvironment sge = (SunGraphicsEnvironment) | ||
| 3826 | GraphicsEnvironment.getLocalGraphicsEnvironment(); | ||
| 3827 | if (!caps.isPageFlipping() && sge.isFlipStrategyPreferred(peer)) { | ||
| 3828 | caps = new ProxyCapabilities(caps); | ||
| 3829 | } | ||
| 3830 | // assert numBuffers > 1; | ||
| 3831 | if (caps.isPageFlipping()) { | ||
| 3832 | bufferStrategy = new FlipSubRegionBufferStrategy(numBuffers, caps); | ||
| 3833 | } else { | ||
| 3834 | bufferStrategy = new BltSubRegionBufferStrategy(numBuffers, caps); | ||
| 3835 | } | ||
| 3836 | } | ||
| 3837 | } | ||
| 3838 | |||
| 3839 | /** | ||
| 3840 | * This is a proxy capabilities class used when a FlipBufferStrategy | ||
| 3841 | * is created instead of the requested Blit strategy. | ||
| 3842 | * | ||
| 3843 | * @see sun.awt.SunGraphicsEnvironment#isFlipStrategyPreferred(ComponentPeer) | ||
| 3844 | */ | ||
| 3845 | private class ProxyCapabilities extends ExtendedBufferCapabilities { | ||
| 3846 | private BufferCapabilities orig; | ||
| 3847 | private ProxyCapabilities(BufferCapabilities orig) { | ||
| 3848 | super(orig.getFrontBufferCapabilities(), | ||
| 3849 | orig.getBackBufferCapabilities(), | ||
| 3850 | orig.getFlipContents() == | ||
| 3851 | BufferCapabilities.FlipContents.BACKGROUND ? | ||
| 3852 | BufferCapabilities.FlipContents.BACKGROUND : | ||
| 3853 | BufferCapabilities.FlipContents.COPIED); | ||
| 3854 | this.orig = orig; | ||
| 3855 | } | ||
| 3856 | } | ||
| 3857 | |||
| 3858 | /** | ||
| 3859 | * @return the buffer strategy used by this component | ||
| 3860 | * @see Window#createBufferStrategy | ||
| 3861 | * @see Canvas#createBufferStrategy | ||
| 3862 | * @since 1.4 | ||
| 3863 | */ | ||
| 3864 | BufferStrategy getBufferStrategy() { | ||
| 3865 | return bufferStrategy; | ||
| 3866 | } | ||
| 3867 | |||
| 3868 | /** | ||
| 3869 | * @return the back buffer currently used by this component's | ||
| 3870 | * BufferStrategy. If there is no BufferStrategy or no | ||
| 3871 | * back buffer, this method returns null. | ||
| 3872 | */ | ||
| 3873 | Image getBackBuffer() { | ||
| 3874 | if (bufferStrategy != null) { | ||
| 3875 | if (bufferStrategy instanceof BltBufferStrategy) { | ||
| 3876 | BltBufferStrategy bltBS = (BltBufferStrategy)bufferStrategy; | ||
| 3877 | return bltBS.getBackBuffer(); | ||
| 3878 | } else if (bufferStrategy instanceof FlipBufferStrategy) { | ||
| 3879 | FlipBufferStrategy flipBS = (FlipBufferStrategy)bufferStrategy; | ||
| 3880 | return flipBS.getBackBuffer(); | ||
| 3881 | } | ||
| 3882 | } | ||
| 3883 | return null; | ||
| 3884 | } | ||
| 3885 | |||
| 3886 | /** | ||
| 3887 | * Inner class for flipping buffers on a component. That component must | ||
| 3888 | * be a <code>Canvas</code> or <code>Window</code>. | ||
| 3889 | * @see Canvas | ||
| 3890 | * @see Window | ||
| 3891 | * @see java.awt.image.BufferStrategy | ||
| 3892 | * @author Michael Martak | ||
| 3893 | * @since 1.4 | ||
| 3894 | */ | ||
| 3895 | protected class FlipBufferStrategy extends BufferStrategy { | ||
| 3896 | /** | ||
| 3897 | * The number of buffers | ||
| 3898 | */ | ||
| 3899 | protected int numBuffers; // = 0 | ||
| 3900 | /** | ||
| 3901 | * The buffering capabilities | ||
| 3902 | */ | ||
| 3903 | protected BufferCapabilities caps; // = null | ||
| 3904 | /** | ||
| 3905 | * The drawing buffer | ||
| 3906 | */ | ||
| 3907 | protected Image drawBuffer; // = null | ||
| 3908 | /** | ||
| 3909 | * The drawing buffer as a volatile image | ||
| 3910 | */ | ||
| 3911 | protected VolatileImage drawVBuffer; // = null | ||
| 3912 | /** | ||
| 3913 | * Whether or not the drawing buffer has been recently restored from | ||
| 3914 | * a lost state. | ||
| 3915 | */ | ||
| 3916 | protected boolean validatedContents; // = false | ||
| 3917 | /** | ||
| 3918 | * Size of the back buffers. (Note: these fields were added in 6.0 | ||
| 3919 | * but kept package-private to avoid exposing them in the spec. | ||
| 3920 | * None of these fields/methods really should have been marked | ||
| 3921 | * protected when they were introduced in 1.4, but now we just have | ||
| 3922 | * to live with that decision.) | ||
| 3923 | */ | ||
| 3924 | int width; | ||
| 3925 | int height; | ||
| 3926 | |||
| 3927 | /** | ||
| 3928 | * Creates a new flipping buffer strategy for this component. | ||
| 3929 | * The component must be a <code>Canvas</code> or <code>Window</code>. | ||
| 3930 | * @see Canvas | ||
| 3931 | * @see Window | ||
| 3932 | * @param numBuffers the number of buffers | ||
| 3933 | * @param caps the capabilities of the buffers | ||
| 3934 | * @exception AWTException if the capabilities supplied could not be | ||
| 3935 | * supported or met | ||
| 3936 | * @exception ClassCastException if the component is not a canvas or | ||
| 3937 | * window. | ||
| 3938 | * @exception IllegalStateException if the component has no peer | ||
| 3939 | * @exception IllegalArgumentException if {@code numBuffers} is less than two, | ||
| 3940 | * or if {@code BufferCapabilities.isPageFlipping} is not | ||
| 3941 | * {@code true}. | ||
| 3942 | * @see #createBuffers(int, BufferCapabilities) | ||
| 3943 | */ | ||
| 3944 | protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps) | ||
| 3945 | throws AWTException | ||
| 3946 | { | ||
| 3947 | if (!(Component.this instanceof Window) && | ||
| 3948 | !(Component.this instanceof Canvas)) | ||
| 3949 | { | ||
| 3950 | throw new ClassCastException( | ||
| 3951 | "Component must be a Canvas or Window"); | ||
| 3952 | } | ||
| 3953 | this.numBuffers = numBuffers; | ||
| 3954 | this.caps = caps; | ||
| 3955 | createBuffers(numBuffers, caps); | ||
| 3956 | } | ||
| 3957 | |||
| 3958 | /** | ||
| 3959 | * Creates one or more complex, flipping buffers with the given | ||
| 3960 | * capabilities. | ||
| 3961 | * @param numBuffers number of buffers to create; must be greater than | ||
| 3962 | * one | ||
| 3963 | * @param caps the capabilities of the buffers. | ||
| 3964 | * <code>BufferCapabilities.isPageFlipping</code> must be | ||
| 3965 | * <code>true</code>. | ||
| 3966 | * @exception AWTException if the capabilities supplied could not be | ||
| 3967 | * supported or met | ||
| 3968 | * @exception IllegalStateException if the component has no peer | ||
| 3969 | * @exception IllegalArgumentException if numBuffers is less than two, | ||
| 3970 | * or if <code>BufferCapabilities.isPageFlipping</code> is not | ||
| 3971 | * <code>true</code>. | ||
| 3972 | * @see java.awt.BufferCapabilities#isPageFlipping() | ||
| 3973 | */ | ||
| 3974 | protected void createBuffers(int numBuffers, BufferCapabilities caps) | ||
| 3975 | throws AWTException | ||
| 3976 | { | ||
| 3977 | if (numBuffers < 2) { | ||
| 3978 | throw new IllegalArgumentException( | ||
| 3979 | "Number of buffers cannot be less than two"); | ||
| 3980 | } else if (peer == null) { | ||
| 3981 | throw new IllegalStateException( | ||
| 3982 | "Component must have a valid peer"); | ||
| 3983 | } else if (caps == null || !caps.isPageFlipping()) { | ||
| 3984 | throw new IllegalArgumentException( | ||
| 3985 | "Page flipping capabilities must be specified"); | ||
| 3986 | } | ||
| 3987 | |||
| 3988 | // save the current bounds | ||
| 3989 | width = getWidth(); | ||
| 3990 | height = getHeight(); | ||
| 3991 | |||
| 3992 | if (drawBuffer != null) { | ||
| 3993 | // dispose the existing backbuffers | ||
| 3994 | drawBuffer = null; | ||
| 3995 | drawVBuffer = null; | ||
| 3996 | destroyBuffers(); | ||
| 3997 | // ... then recreate the backbuffers | ||
| 3998 | } | ||
| 3999 | |||
| 4000 | if (caps instanceof ExtendedBufferCapabilities) { | ||
| 4001 | ExtendedBufferCapabilities ebc = | ||
| 4002 | (ExtendedBufferCapabilities)caps; | ||
| 4003 | if (ebc.getVSync() == VSYNC_ON) { | ||
| 4004 | // if this buffer strategy is not allowed to be v-synced, | ||
| 4005 | // change the caps that we pass to the peer but keep on | ||
| 4006 | // trying to create v-synced buffers; | ||
| 4007 | // do not throw IAE here in case it is disallowed, see | ||
| 4008 | // ExtendedBufferCapabilities for more info | ||
| 4009 | if (!VSyncedBSManager.vsyncAllowed(this)) { | ||
| 4010 | caps = ebc.derive(VSYNC_DEFAULT); | ||
| 4011 | } | ||
| 4012 | } | ||
| 4013 | } | ||
| 4014 | |||
| 4015 | peer.createBuffers(numBuffers, caps); | ||
| 4016 | updateInternalBuffers(); | ||
| 4017 | } | ||
| 4018 | |||
| 4019 | /** | ||
| 4020 | * Updates internal buffers (both volatile and non-volatile) | ||
| 4021 | * by requesting the back-buffer from the peer. | ||
| 4022 | */ | ||
| 4023 | private void updateInternalBuffers() { | ||
| 4024 | // get the images associated with the draw buffer | ||
| 4025 | drawBuffer = getBackBuffer(); | ||
| 4026 | if (drawBuffer instanceof VolatileImage) { | ||
| 4027 | drawVBuffer = (VolatileImage)drawBuffer; | ||
| 4028 | } else { | ||
| 4029 | drawVBuffer = null; | ||
| 4030 | } | ||
| 4031 | } | ||
| 4032 | |||
| 4033 | /** | ||
| 4034 | * @return direct access to the back buffer, as an image. | ||
| 4035 | * @exception IllegalStateException if the buffers have not yet | ||
| 4036 | * been created | ||
| 4037 | */ | ||
| 4038 | protected Image getBackBuffer() { | ||
| 4039 | if (peer != null) { | ||
| 4040 | return peer.getBackBuffer(); | ||
| 4041 | } else { | ||
| 4042 | throw new IllegalStateException( | ||
| 4043 | "Component must have a valid peer"); | ||
| 4044 | } | ||
| 4045 | } | ||
| 4046 | |||
| 4047 | /** | ||
| 4048 | * Flipping moves the contents of the back buffer to the front buffer, | ||
| 4049 | * either by copying or by moving the video pointer. | ||
| 4050 | * @param flipAction an integer value describing the flipping action | ||
| 4051 | * for the contents of the back buffer. This should be one of the | ||
| 4052 | * values of the <code>BufferCapabilities.FlipContents</code> | ||
| 4053 | * property. | ||
| 4054 | * @exception IllegalStateException if the buffers have not yet | ||
| 4055 | * been created | ||
| 4056 | * @see java.awt.BufferCapabilities#getFlipContents() | ||
| 4057 | */ | ||
| 4058 | protected void flip(BufferCapabilities.FlipContents flipAction) { | ||
| 4059 | if (peer != null) { | ||
| 4060 | Image backBuffer = getBackBuffer(); | ||
| 4061 | if (backBuffer != null) { | ||
| 4062 | peer.flip(0, 0, | ||
| 4063 | backBuffer.getWidth(null), | ||
| 4064 | backBuffer.getHeight(null), flipAction); | ||
| 4065 | } | ||
| 4066 | } else { | ||
| 4067 | throw new IllegalStateException( | ||
| 4068 | "Component must have a valid peer"); | ||
| 4069 | } | ||
| 4070 | } | ||
| 4071 | |||
| 4072 | void flipSubRegion(int x1, int y1, int x2, int y2, | ||
| 4073 | BufferCapabilities.FlipContents flipAction) | ||
| 4074 | { | ||
| 4075 | if (peer != null) { | ||
| 4076 | peer.flip(x1, y1, x2, y2, flipAction); | ||
| 4077 | } else { | ||
| 4078 | throw new IllegalStateException( | ||
| 4079 | "Component must have a valid peer"); | ||
| 4080 | } | ||
| 4081 | } | ||
| 4082 | |||
| 4083 | /** | ||
| 4084 | * Destroys the buffers created through this object | ||
| 4085 | */ | ||
| 4086 | protected void destroyBuffers() { | ||
| 4087 | VSyncedBSManager.releaseVsync(this); | ||
| 4088 | if (peer != null) { | ||
| 4089 | peer.destroyBuffers(); | ||
| 4090 | } else { | ||
| 4091 | throw new IllegalStateException( | ||
| 4092 | "Component must have a valid peer"); | ||
| 4093 | } | ||
| 4094 | } | ||
| 4095 | |||
| 4096 | /** | ||
| 4097 | * @return the buffering capabilities of this strategy | ||
| 4098 | */ | ||
| 4099 | public BufferCapabilities getCapabilities() { | ||
| 4100 | if (caps instanceof ProxyCapabilities) { | ||
| 4101 | return ((ProxyCapabilities)caps).orig; | ||
| 4102 | } else { | ||
| 4103 | return caps; | ||
| 4104 | } | ||
| 4105 | } | ||
| 4106 | |||
| 4107 | /** | ||
| 4108 | * @return the graphics on the drawing buffer. This method may not | ||
| 4109 | * be synchronized for performance reasons; use of this method by multiple | ||
| 4110 | * threads should be handled at the application level. Disposal of the | ||
| 4111 | * graphics object must be handled by the application. | ||
| 4112 | */ | ||
| 4113 | public Graphics getDrawGraphics() { | ||
| 4114 | revalidate(); | ||
| 4115 | return drawBuffer.getGraphics(); | ||
| 4116 | } | ||
| 4117 | |||
| 4118 | /** | ||
| 4119 | * Restore the drawing buffer if it has been lost | ||
| 4120 | */ | ||
| 4121 | protected void revalidate() { | ||
| 4122 | revalidate(true); | ||
| 4123 | } | ||
| 4124 | |||
| 4125 | void revalidate(boolean checkSize) { | ||
| 4126 | validatedContents = false; | ||
| 4127 | |||
| 4128 | if (checkSize && (getWidth() != width || getHeight() != height)) { | ||
| 4129 | // component has been resized; recreate the backbuffers | ||
| 4130 | try { | ||
| 4131 | createBuffers(numBuffers, caps); | ||
| 4132 | } catch (AWTException e) { | ||
| 4133 | // shouldn't be possible | ||
| 4134 | } | ||
| 4135 | validatedContents = true; | ||
| 4136 | } | ||
| 4137 | |||
| 4138 | // get the buffers from the peer every time since they | ||
| 4139 | // might have been replaced in response to a display change event | ||
| 4140 | updateInternalBuffers(); | ||
| 4141 | |||
| 4142 | // now validate the backbuffer | ||
| 4143 | if (drawVBuffer != null) { | ||
| 4144 | GraphicsConfiguration gc = | ||
| 4145 | getGraphicsConfiguration_NoClientCode(); | ||
| 4146 | int returnCode = drawVBuffer.validate(gc); | ||
| 4147 | if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { | ||
| 4148 | try { | ||
| 4149 | createBuffers(numBuffers, caps); | ||
| 4150 | } catch (AWTException e) { | ||
| 4151 | // shouldn't be possible | ||
| 4152 | } | ||
| 4153 | if (drawVBuffer != null) { | ||
| 4154 | // backbuffers were recreated, so validate again | ||
| 4155 | drawVBuffer.validate(gc); | ||
| 4156 | } | ||
| 4157 | validatedContents = true; | ||
| 4158 | } else if (returnCode == VolatileImage.IMAGE_RESTORED) { | ||
| 4159 | validatedContents = true; | ||
| 4160 | } | ||
| 4161 | } | ||
| 4162 | } | ||
| 4163 | |||
| 4164 | /** | ||
| 4165 | * @return whether the drawing buffer was lost since the last call to | ||
| 4166 | * <code>getDrawGraphics</code> | ||
| 4167 | */ | ||
| 4168 | public boolean contentsLost() { | ||
| 4169 | if (drawVBuffer == null) { | ||
| 4170 | return false; | ||
| 4171 | } | ||
| 4172 | return drawVBuffer.contentsLost(); | ||
| 4173 | } | ||
| 4174 | |||
| 4175 | /** | ||
| 4176 | * @return whether the drawing buffer was recently restored from a lost | ||
| 4177 | * state and reinitialized to the default background color (white) | ||
| 4178 | */ | ||
| 4179 | public boolean contentsRestored() { | ||
| 4180 | return validatedContents; | ||
| 4181 | } | ||
| 4182 | |||
| 4183 | /** | ||
| 4184 | * Makes the next available buffer visible by either blitting or | ||
| 4185 | * flipping. | ||
| 4186 | */ | ||
| 4187 | public void show() { | ||
| 4188 | flip(caps.getFlipContents()); | ||
| 4189 | } | ||
| 4190 | |||
| 4191 | /** | ||
| 4192 | * Makes specified region of the the next available buffer visible | ||
| 4193 | * by either blitting or flipping. | ||
| 4194 | */ | ||
| 4195 | void showSubRegion(int x1, int y1, int x2, int y2) { | ||
| 4196 | flipSubRegion(x1, y1, x2, y2, caps.getFlipContents()); | ||
| 4197 | } | ||
| 4198 | |||
| 4199 | /** | ||
| 4200 | * {@inheritDoc} | ||
| 4201 | * @since 1.6 | ||
| 4202 | */ | ||
| 4203 | public void dispose() { | ||
| 4204 | if (Component.this.bufferStrategy == this) { | ||
| 4205 | Component.this.bufferStrategy = null; | ||
| 4206 | if (peer != null) { | ||
| 4207 | destroyBuffers(); | ||
| 4208 | } | ||
| 4209 | } | ||
| 4210 | } | ||
| 4211 | |||
| 4212 | } // Inner class FlipBufferStrategy | ||
| 4213 | |||
| 4214 | /** | ||
| 4215 | * Inner class for blitting offscreen surfaces to a component. | ||
| 4216 | * | ||
| 4217 | * @author Michael Martak | ||
| 4218 | * @since 1.4 | ||
| 4219 | */ | ||
| 4220 | protected class BltBufferStrategy extends BufferStrategy { | ||
| 4221 | |||
| 4222 | /** | ||
| 4223 | * The buffering capabilities | ||
| 4224 | */ | ||
| 4225 | protected BufferCapabilities caps; // = null | ||
| 4226 | /** | ||
| 4227 | * The back buffers | ||
| 4228 | */ | ||
| 4229 | protected VolatileImage[] backBuffers; // = null | ||
| 4230 | /** | ||
| 4231 | * Whether or not the drawing buffer has been recently restored from | ||
| 4232 | * a lost state. | ||
| 4233 | */ | ||
| 4234 | protected boolean validatedContents; // = false | ||
| 4235 | /** | ||
| 4236 | * Size of the back buffers | ||
| 4237 | */ | ||
| 4238 | protected int width; | ||
| 4239 | protected int height; | ||
| 4240 | |||
| 4241 | /** | ||
| 4242 | * Insets for the hosting Component. The size of the back buffer | ||
| 4243 | * is constrained by these. | ||
| 4244 | */ | ||
| 4245 | private Insets insets; | ||
| 4246 | |||
| 4247 | /** | ||
| 4248 | * Creates a new blt buffer strategy around a component | ||
| 4249 | * @param numBuffers number of buffers to create, including the | ||
| 4250 | * front buffer | ||
| 4251 | * @param caps the capabilities of the buffers | ||
| 4252 | */ | ||
| 4253 | protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) { | ||
| 4254 | this.caps = caps; | ||
| 4255 | createBackBuffers(numBuffers - 1); | ||
| 4256 | } | ||
| 4257 | |||
| 4258 | /** | ||
| 4259 | * {@inheritDoc} | ||
| 4260 | * @since 1.6 | ||
| 4261 | */ | ||
| 4262 | public void dispose() { | ||
| 4263 | if (backBuffers != null) { | ||
| 4264 | for (int counter = backBuffers.length - 1; counter >= 0; | ||
| 4265 | counter--) { | ||
| 4266 | if (backBuffers[counter] != null) { | ||
| 4267 | backBuffers[counter].flush(); | ||
| 4268 | backBuffers[counter] = null; | ||
| 4269 | } | ||
| 4270 | } | ||
| 4271 | } | ||
| 4272 | if (Component.this.bufferStrategy == this) { | ||
| 4273 | Component.this.bufferStrategy = null; | ||
| 4274 | } | ||
| 4275 | } | ||
| 4276 | |||
| 4277 | /** | ||
| 4278 | * Creates the back buffers | ||
| 4279 | */ | ||
| 4280 | protected void createBackBuffers(int numBuffers) { | ||
| 4281 | if (numBuffers == 0) { | ||
| 4282 | backBuffers = null; | ||
| 4283 | } else { | ||
| 4284 | // save the current bounds | ||
| 4285 | width = getWidth(); | ||
| 4286 | height = getHeight(); | ||
| 4287 | insets = getInsets_NoClientCode(); | ||
| 4288 | int iWidth = width - insets.left - insets.right; | ||
| 4289 | int iHeight = height - insets.top - insets.bottom; | ||
| 4290 | |||
| 4291 | // It is possible for the component's width and/or height | ||
| 4292 | // to be 0 here. Force the size of the backbuffers to | ||
| 4293 | // be > 0 so that creating the image won't fail. | ||
| 4294 | iWidth = Math.max(1, iWidth); | ||
| 4295 | iHeight = Math.max(1, iHeight); | ||
| 4296 | if (backBuffers == null) { | ||
| 4297 | backBuffers = new VolatileImage[numBuffers]; | ||
| 4298 | } else { | ||
| 4299 | // flush any existing backbuffers | ||
| 4300 | for (int i = 0; i < numBuffers; i++) { | ||
| 4301 | if (backBuffers[i] != null) { | ||
| 4302 | backBuffers[i].flush(); | ||
| 4303 | backBuffers[i] = null; | ||
| 4304 | } | ||
| 4305 | } | ||
| 4306 | } | ||
| 4307 | |||
| 4308 | // create the backbuffers | ||
| 4309 | for (int i = 0; i < numBuffers; i++) { | ||
| 4310 | backBuffers[i] = createVolatileImage(iWidth, iHeight); | ||
| 4311 | } | ||
| 4312 | } | ||
| 4313 | } | ||
| 4314 | |||
| 4315 | /** | ||
| 4316 | * @return the buffering capabilities of this strategy | ||
| 4317 | */ | ||
| 4318 | public BufferCapabilities getCapabilities() { | ||
| 4319 | return caps; | ||
| 4320 | } | ||
| 4321 | |||
| 4322 | /** | ||
| 4323 | * @return the draw graphics | ||
| 4324 | */ | ||
| 4325 | public Graphics getDrawGraphics() { | ||
| 4326 | revalidate(); | ||
| 4327 | Image backBuffer = getBackBuffer(); | ||
| 4328 | if (backBuffer == null) { | ||
| 4329 | return getGraphics(); | ||
| 4330 | } | ||
| 4331 | SunGraphics2D g = (SunGraphics2D)backBuffer.getGraphics(); | ||
| 4332 | g.constrain(-insets.left, -insets.top, | ||
| 4333 | backBuffer.getWidth(null) + insets.left, | ||
| 4334 | backBuffer.getHeight(null) + insets.top); | ||
| 4335 | return g; | ||
| 4336 | } | ||
| 4337 | |||
| 4338 | /** | ||
| 4339 | * @return direct access to the back buffer, as an image. | ||
| 4340 | * If there is no back buffer, returns null. | ||
| 4341 | */ | ||
| 4342 | Image getBackBuffer() { | ||
| 4343 | if (backBuffers != null) { | ||
| 4344 | return backBuffers[backBuffers.length - 1]; | ||
| 4345 | } else { | ||
| 4346 | return null; | ||
| 4347 | } | ||
| 4348 | } | ||
| 4349 | |||
| 4350 | /** | ||
| 4351 | * Makes the next available buffer visible. | ||
| 4352 | */ | ||
| 4353 | public void show() { | ||
| 4354 | showSubRegion(insets.left, insets.top, | ||
| 4355 | width - insets.right, | ||
| 4356 | height - insets.bottom); | ||
| 4357 | } | ||
| 4358 | |||
| 4359 | /** | ||
| 4360 | * Package-private method to present a specific rectangular area | ||
| 4361 | * of this buffer. This class currently shows only the entire | ||
| 4362 | * buffer, by calling showSubRegion() with the full dimensions of | ||
| 4363 | * the buffer. Subclasses (e.g., BltSubRegionBufferStrategy | ||
| 4364 | * and FlipSubRegionBufferStrategy) may have region-specific show | ||
| 4365 | * methods that call this method with actual sub regions of the | ||
| 4366 | * buffer. | ||
| 4367 | */ | ||
| 4368 | void showSubRegion(int x1, int y1, int x2, int y2) { | ||
| 4369 | if (backBuffers == null) { | ||
| 4370 | return; | ||
| 4371 | } | ||
| 4372 | // Adjust location to be relative to client area. | ||
| 4373 | x1 -= insets.left; | ||
| 4374 | x2 -= insets.left; | ||
| 4375 | y1 -= insets.top; | ||
| 4376 | y2 -= insets.top; | ||
| 4377 | Graphics g = getGraphics_NoClientCode(); | ||
| 4378 | if (g == null) { | ||
| 4379 | // Not showing, bail | ||
| 4380 | return; | ||
| 4381 | } | ||
| 4382 | try { | ||
| 4383 | // First image copy is in terms of Frame's coordinates, need | ||
| 4384 | // to translate to client area. | ||
| 4385 | g.translate(insets.left, insets.top); | ||
| 4386 | for (int i = 0; i < backBuffers.length; i++) { | ||
| 4387 | g.drawImage(backBuffers[i], | ||
| 4388 | x1, y1, x2, y2, | ||
| 4389 | x1, y1, x2, y2, | ||
| 4390 | null); | ||
| 4391 | g.dispose(); | ||
| 4392 | g = null; | ||
| 4393 | g = backBuffers[i].getGraphics(); | ||
| 4394 | } | ||
| 4395 | } finally { | ||
| 4396 | if (g != null) { | ||
| 4397 | g.dispose(); | ||
| 4398 | } | ||
| 4399 | } | ||
| 4400 | } | ||
| 4401 | |||
| 4402 | /** | ||
| 4403 | * Restore the drawing buffer if it has been lost | ||
| 4404 | */ | ||
| 4405 | protected void revalidate() { | ||
| 4406 | revalidate(true); | ||
| 4407 | } | ||
| 4408 | |||
| 4409 | void revalidate(boolean checkSize) { | ||
| 4410 | validatedContents = false; | ||
| 4411 | |||
| 4412 | if (backBuffers == null) { | ||
| 4413 | return; | ||
| 4414 | } | ||
| 4415 | |||
| 4416 | if (checkSize) { | ||
| 4417 | Insets insets = getInsets_NoClientCode(); | ||
| 4418 | if (getWidth() != width || getHeight() != height || | ||
| 4419 | !insets.equals(this.insets)) { | ||
| 4420 | // component has been resized; recreate the backbuffers | ||
| 4421 | createBackBuffers(backBuffers.length); | ||
| 4422 | validatedContents = true; | ||
| 4423 | } | ||
| 4424 | } | ||
| 4425 | |||
| 4426 | // now validate the backbuffer | ||
| 4427 | GraphicsConfiguration gc = getGraphicsConfiguration_NoClientCode(); | ||
| 4428 | int returnCode = | ||
| 4429 | backBuffers[backBuffers.length - 1].validate(gc); | ||
| 4430 | if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { | ||
| 4431 | if (checkSize) { | ||
| 4432 | createBackBuffers(backBuffers.length); | ||
| 4433 | // backbuffers were recreated, so validate again | ||
| 4434 | backBuffers[backBuffers.length - 1].validate(gc); | ||
| 4435 | } | ||
| 4436 | // else case means we're called from Swing on the toolkit | ||
| 4437 | // thread, don't recreate buffers as that'll deadlock | ||
| 4438 | // (creating VolatileImages invokes getting GraphicsConfig | ||
| 4439 | // which grabs treelock). | ||
| 4440 | validatedContents = true; | ||
| 4441 | } else if (returnCode == VolatileImage.IMAGE_RESTORED) { | ||
| 4442 | validatedContents = true; | ||
| 4443 | } | ||
| 4444 | } | ||
| 4445 | |||
| 4446 | /** | ||
| 4447 | * @return whether the drawing buffer was lost since the last call to | ||
| 4448 | * <code>getDrawGraphics</code> | ||
| 4449 | */ | ||
| 4450 | public boolean contentsLost() { | ||
| 4451 | if (backBuffers == null) { | ||
| 4452 | return false; | ||
| 4453 | } else { | ||
| 4454 | return backBuffers[backBuffers.length - 1].contentsLost(); | ||
| 4455 | } | ||
| 4456 | } | ||
| 4457 | |||
| 4458 | /** | ||
| 4459 | * @return whether the drawing buffer was recently restored from a lost | ||
| 4460 | * state and reinitialized to the default background color (white) | ||
| 4461 | */ | ||
| 4462 | public boolean contentsRestored() { | ||
| 4463 | return validatedContents; | ||
| 4464 | } | ||
| 4465 | } // Inner class BltBufferStrategy | ||
| 4466 | |||
| 4467 | /** | ||
| 4468 | * Private class to perform sub-region flipping. | ||
| 4469 | */ | ||
| 4470 | private class FlipSubRegionBufferStrategy extends FlipBufferStrategy | ||
| 4471 | implements SubRegionShowable | ||
| 4472 | { | ||
| 4473 | |||
| 4474 | protected FlipSubRegionBufferStrategy(int numBuffers, | ||
| 4475 | BufferCapabilities caps) | ||
| 4476 | throws AWTException | ||
| 4477 | { | ||
| 4478 | super(numBuffers, caps); | ||
| 4479 | } | ||
| 4480 | |||
| 4481 | public void show(int x1, int y1, int x2, int y2) { | ||
| 4482 | showSubRegion(x1, y1, x2, y2); | ||
| 4483 | } | ||
| 4484 | |||
| 4485 | // This is invoked by Swing on the toolkit thread. | ||
| 4486 | public boolean showIfNotLost(int x1, int y1, int x2, int y2) { | ||
| 4487 | if (!contentsLost()) { | ||
| 4488 | showSubRegion(x1, y1, x2, y2); | ||
| 4489 | return !contentsLost(); | ||
| 4490 | } | ||
| 4491 | return false; | ||
| 4492 | } | ||
| 4493 | } | ||
| 4494 | |||
| 4495 | /** | ||
| 4496 | * Private class to perform sub-region blitting. Swing will use | ||
| 4497 | * this subclass via the SubRegionShowable interface in order to | ||
| 4498 | * copy only the area changed during a repaint. | ||
| 4499 | * @see javax.swing.BufferStrategyPaintManager | ||
| 4500 | */ | ||
| 4501 | private class BltSubRegionBufferStrategy extends BltBufferStrategy | ||
| 4502 | implements SubRegionShowable | ||
| 4503 | { | ||
| 4504 | |||
| 4505 | protected BltSubRegionBufferStrategy(int numBuffers, | ||
| 4506 | BufferCapabilities caps) | ||
| 4507 | { | ||
| 4508 | super(numBuffers, caps); | ||
| 4509 | } | ||
| 4510 | |||
| 4511 | public void show(int x1, int y1, int x2, int y2) { | ||
| 4512 | showSubRegion(x1, y1, x2, y2); | ||
| 4513 | } | ||
| 4514 | |||
| 4515 | // This method is called by Swing on the toolkit thread. | ||
| 4516 | public boolean showIfNotLost(int x1, int y1, int x2, int y2) { | ||
| 4517 | if (!contentsLost()) { | ||
| 4518 | showSubRegion(x1, y1, x2, y2); | ||
| 4519 | return !contentsLost(); | ||
| 4520 | } | ||
| 4521 | return false; | ||
| 4522 | } | ||
| 4523 | } | ||
| 4524 | |||
| 4525 | /** | ||
| 4526 | * Inner class for flipping buffers on a component. That component must | ||
| 4527 | * be a <code>Canvas</code> or <code>Window</code>. | ||
| 4528 | * @see Canvas | ||
| 4529 | * @see Window | ||
| 4530 | * @see java.awt.image.BufferStrategy | ||
| 4531 | * @author Michael Martak | ||
| 4532 | * @since 1.4 | ||
| 4533 | */ | ||
| 4534 | private class SingleBufferStrategy extends BufferStrategy { | ||
| 4535 | |||
| 4536 | private BufferCapabilities caps; | ||
| 4537 | |||
| 4538 | public SingleBufferStrategy(BufferCapabilities caps) { | ||
| 4539 | this.caps = caps; | ||
| 4540 | } | ||
| 4541 | public BufferCapabilities getCapabilities() { | ||
| 4542 | return caps; | ||
| 4543 | } | ||
| 4544 | public Graphics getDrawGraphics() { | ||
| 4545 | return getGraphics(); | ||
| 4546 | } | ||
| 4547 | public boolean contentsLost() { | ||
| 4548 | return false; | ||
| 4549 | } | ||
| 4550 | public boolean contentsRestored() { | ||
| 4551 | return false; | ||
| 4552 | } | ||
| 4553 | public void show() { | ||
| 4554 | // Do nothing | ||
| 4555 | } | ||
| 4556 | } // Inner class SingleBufferStrategy | ||
| 4557 | |||
| 4558 | /** | ||
| 4559 | * Sets whether or not paint messages received from the operating system | ||
| 4560 | * should be ignored. This does not affect paint events generated in | ||
| 4561 | * software by the AWT, unless they are an immediate response to an | ||
| 4562 | * OS-level paint message. | ||
| 4563 | * <p> | ||
| 4564 | * This is useful, for example, if running under full-screen mode and | ||
| 4565 | * better performance is desired, or if page-flipping is used as the | ||
| 4566 | * buffer strategy. | ||
| 4567 | * | ||
| 4568 | * @since 1.4 | ||
| 4569 | * @see #getIgnoreRepaint | ||
| 4570 | * @see Canvas#createBufferStrategy | ||
| 4571 | * @see Window#createBufferStrategy | ||
| 4572 | * @see java.awt.image.BufferStrategy | ||
| 4573 | * @see GraphicsDevice#setFullScreenWindow | ||
| 4574 | */ | ||
| 4575 | public void setIgnoreRepaint(boolean ignoreRepaint) { | ||
| 4576 | this.ignoreRepaint = ignoreRepaint; | ||
| 4577 | } | ||
| 4578 | |||
| 4579 | /** | ||
| 4580 | * @return whether or not paint messages received from the operating system | ||
| 4581 | * should be ignored. | ||
| 4582 | * | ||
| 4583 | * @since 1.4 | ||
| 4584 | * @see #setIgnoreRepaint | ||
| 4585 | */ | ||
| 4586 | public boolean getIgnoreRepaint() { | ||
| 4587 | return ignoreRepaint; | ||
| 4588 | } | ||
| 4589 | |||
| 4590 | /** | ||
| 4591 | * Checks whether this component "contains" the specified point, | ||
| 4592 | * where <code>x</code> and <code>y</code> are defined to be | ||
| 4593 | * relative to the coordinate system of this component. | ||
| 4594 | * @param x the <i>x</i> coordinate of the point | ||
| 4595 | * @param y the <i>y</i> coordinate of the point | ||
| 4596 | * @see #getComponentAt(int, int) | ||
| 4597 | * @since JDK1.1 | ||
| 4598 | */ | ||
| 4599 | public boolean contains(int x, int y) { | ||
| 4600 | return inside(x, y); | ||
| 4601 | } | ||
| 4602 | |||
| 4603 | /** | ||
| 4604 | * @deprecated As of JDK version 1.1, | ||
| 4605 | * replaced by contains(int, int). | ||
| 4606 | */ | ||
| 4607 | @Deprecated | ||
| 4608 | public boolean inside(int x, int y) { | ||
| 4609 | return (x >= 0) && (x < width) && (y >= 0) && (y < height); | ||
| 4610 | } | ||
| 4611 | |||
| 4612 | /** | ||
| 4613 | * Checks whether this component "contains" the specified point, | ||
| 4614 | * where the point's <i>x</i> and <i>y</i> coordinates are defined | ||
| 4615 | * to be relative to the coordinate system of this component. | ||
| 4616 | * @param p the point | ||
| 4617 | * @throws NullPointerException if {@code p} is {@code null} | ||
| 4618 | * @see #getComponentAt(Point) | ||
| 4619 | * @since JDK1.1 | ||
| 4620 | */ | ||
| 4621 | public boolean contains(Point p) { | ||
| 4622 | return contains(p.x, p.y); | ||
| 4623 | } | ||
| 4624 | |||
| 4625 | /** | ||
| 4626 | * Determines if this component or one of its immediate | ||
| 4627 | * subcomponents contains the (<i>x</i>, <i>y</i>) location, | ||
| 4628 | * and if so, returns the containing component. This method only | ||
| 4629 | * looks one level deep. If the point (<i>x</i>, <i>y</i>) is | ||
| 4630 | * inside a subcomponent that itself has subcomponents, it does not | ||
| 4631 | * go looking down the subcomponent tree. | ||
| 4632 | * <p> | ||
| 4633 | * The <code>locate</code> method of <code>Component</code> simply | ||
| 4634 | * returns the component itself if the (<i>x</i>, <i>y</i>) | ||
| 4635 | * coordinate location is inside its bounding box, and <code>null</code> | ||
| 4636 | * otherwise. | ||
| 4637 | * @param x the <i>x</i> coordinate | ||
| 4638 | * @param y the <i>y</i> coordinate | ||
| 4639 | * @return the component or subcomponent that contains the | ||
| 4640 | * (<i>x</i>, <i>y</i>) location; | ||
| 4641 | * <code>null</code> if the location | ||
| 4642 | * is outside this component | ||
| 4643 | * @see #contains(int, int) | ||
| 4644 | * @since JDK1.0 | ||
| 4645 | */ | ||
| 4646 | public Component getComponentAt(int x, int y) { | ||
| 4647 | return locate(x, y); | ||
| 4648 | } | ||
| 4649 | |||
| 4650 | /** | ||
| 4651 | * @deprecated As of JDK version 1.1, | ||
| 4652 | * replaced by getComponentAt(int, int). | ||
| 4653 | */ | ||
| 4654 | @Deprecated | ||
| 4655 | public Component locate(int x, int y) { | ||
| 4656 | return contains(x, y) ? this : null; | ||
| 4657 | } | ||
| 4658 | |||
| 4659 | /** | ||
| 4660 | * Returns the component or subcomponent that contains the | ||
| 4661 | * specified point. | ||
| 4662 | * @param p the point | ||
| 4663 | * @see java.awt.Component#contains | ||
| 4664 | * @since JDK1.1 | ||
| 4665 | */ | ||
| 4666 | public Component getComponentAt(Point p) { | ||
| 4667 | return getComponentAt(p.x, p.y); | ||
| 4668 | } | ||
| 4669 | |||
| 4670 | /** | ||
| 4671 | * @deprecated As of JDK version 1.1, | ||
| 4672 | * replaced by <code>dispatchEvent(AWTEvent e)</code>. | ||
| 4673 | */ | ||
| 4674 | @Deprecated | ||
| 4675 | public void deliverEvent(Event e) { | ||
| 4676 | postEvent(e); | ||
| 4677 | } | ||
| 4678 | |||
| 4679 | /** | ||
| 4680 | * Dispatches an event to this component or one of its sub components. | ||
| 4681 | * Calls <code>processEvent</code> before returning for 1.1-style | ||
| 4682 | * events which have been enabled for the <code>Component</code>. | ||
| 4683 | * @param e the event | ||
| 4684 | */ | ||
| 4685 | public final void dispatchEvent(AWTEvent e) { | ||
| 4686 | dispatchEventImpl(e); | ||
| 4687 | } | ||
| 4688 | |||
| 4689 | void dispatchEventImpl(AWTEvent e) { | ||
| 4690 | int id = e.getID(); | ||
| 4691 | |||
| 4692 | // Check that this component belongs to this app-context | ||
| 4693 | AppContext compContext = appContext; | ||
| 4694 | if (compContext != null && !compContext.equals(AppContext.getAppContext())) { | ||
| 4695 | if (eventLog.isLoggable(PlatformLogger.FINE)) { | ||
| 4696 | eventLog.fine("Event " + e + " is being dispatched on the wrong AppContext"); | ||
| 4697 | } | ||
| 4698 | } | ||
| 4699 | |||
| 4700 | if (eventLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4701 | eventLog.finest("{0}", e); | ||
| 4702 | } | ||
| 4703 | |||
| 4704 | /* | ||
| 4705 | * 0. Set timestamp and modifiers of current event. | ||
| 4706 | */ | ||
| 4707 | EventQueue.setCurrentEventAndMostRecentTime(e); | ||
| 4708 | |||
| 4709 | /* | ||
| 4710 | * 1. Pre-dispatchers. Do any necessary retargeting/reordering here | ||
| 4711 | * before we notify AWTEventListeners. | ||
| 4712 | */ | ||
| 4713 | |||
| 4714 | if (e instanceof SunDropTargetEvent) { | ||
| 4715 | ((SunDropTargetEvent)e).dispatch(); | ||
| 4716 | return; | ||
| 4717 | } | ||
| 4718 | |||
| 4719 | if (!e.focusManagerIsDispatching) { | ||
| 4720 | // Invoke the private focus retargeting method which provides | ||
| 4721 | // lightweight Component support | ||
| 4722 | if (e.isPosted) { | ||
| 4723 | e = KeyboardFocusManager.retargetFocusEvent(e); | ||
| 4724 | e.isPosted = true; | ||
| 4725 | } | ||
| 4726 | |||
| 4727 | // Now, with the event properly targeted to a lightweight | ||
| 4728 | // descendant if necessary, invoke the public focus retargeting | ||
| 4729 | // and dispatching function | ||
| 4730 | if (KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 4731 | dispatchEvent(e)) | ||
| 4732 | { | ||
| 4733 | return; | ||
| 4734 | } | ||
| 4735 | } | ||
| 4736 | if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4737 | focusLog.finest("" + e); | ||
| 4738 | } | ||
| 4739 | // MouseWheel may need to be retargeted here so that | ||
| 4740 | // AWTEventListener sees the event go to the correct | ||
| 4741 | // Component. If the MouseWheelEvent needs to go to an ancestor, | ||
| 4742 | // the event is dispatched to the ancestor, and dispatching here | ||
| 4743 | // stops. | ||
| 4744 | if (id == MouseEvent.MOUSE_WHEEL && | ||
| 4745 | (!eventTypeEnabled(id)) && | ||
| 4746 | (peer != null && !peer.handlesWheelScrolling()) && | ||
| 4747 | (dispatchMouseWheelToAncestor((MouseWheelEvent)e))) | ||
| 4748 | { | ||
| 4749 | return; | ||
| 4750 | } | ||
| 4751 | |||
| 4752 | /* | ||
| 4753 | * 2. Allow the Toolkit to pass this to AWTEventListeners. | ||
| 4754 | */ | ||
| 4755 | Toolkit toolkit = Toolkit.getDefaultToolkit(); | ||
| 4756 | toolkit.notifyAWTEventListeners(e); | ||
| 4757 | |||
| 4758 | |||
| 4759 | /* | ||
| 4760 | * 3. If no one has consumed a key event, allow the | ||
| 4761 | * KeyboardFocusManager to process it. | ||
| 4762 | */ | ||
| 4763 | if (!e.isConsumed()) { | ||
| 4764 | if (e instanceof java.awt.event.KeyEvent) { | ||
| 4765 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 4766 | processKeyEvent(this, (KeyEvent)e); | ||
| 4767 | if (e.isConsumed()) { | ||
| 4768 | return; | ||
| 4769 | } | ||
| 4770 | } | ||
| 4771 | } | ||
| 4772 | |||
| 4773 | /* | ||
| 4774 | * 4. Allow input methods to process the event | ||
| 4775 | */ | ||
| 4776 | if (areInputMethodsEnabled()) { | ||
| 4777 | // We need to pass on InputMethodEvents since some host | ||
| 4778 | // input method adapters send them through the Java | ||
| 4779 | // event queue instead of directly to the component, | ||
| 4780 | // and the input context also handles the Java composition window | ||
| 4781 | if(((e instanceof InputMethodEvent) && !(this instanceof CompositionArea)) | ||
| 4782 | || | ||
| 4783 | // Otherwise, we only pass on input and focus events, because | ||
| 4784 | // a) input methods shouldn't know about semantic or component-level events | ||
| 4785 | // b) passing on the events takes time | ||
| 4786 | // c) isConsumed() is always true for semantic events. | ||
| 4787 | (e instanceof InputEvent) || (e instanceof FocusEvent)) { | ||
| 4788 | InputContext inputContext = getInputContext(); | ||
| 4789 | |||
| 4790 | |||
| 4791 | if (inputContext != null) { | ||
| 4792 | inputContext.dispatchEvent(e); | ||
| 4793 | if (e.isConsumed()) { | ||
| 4794 | if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4795 | focusLog.finest("3579: Skipping " + e); | ||
| 4796 | } | ||
| 4797 | return; | ||
| 4798 | } | ||
| 4799 | } | ||
| 4800 | } | ||
| 4801 | } else { | ||
| 4802 | // When non-clients get focus, we need to explicitly disable the native | ||
| 4803 | // input method. The native input method is actually not disabled when | ||
| 4804 | // the active/passive/peered clients loose focus. | ||
| 4805 | if (id == FocusEvent.FOCUS_GAINED) { | ||
| 4806 | InputContext inputContext = getInputContext(); | ||
| 4807 | if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) { | ||
| 4808 | ((sun.awt.im.InputContext)inputContext).disableNativeIM(); | ||
| 4809 | } | ||
| 4810 | } | ||
| 4811 | } | ||
| 4812 | |||
| 4813 | |||
| 4814 | /* | ||
| 4815 | * 5. Pre-process any special events before delivery | ||
| 4816 | */ | ||
| 4817 | switch(id) { | ||
| 4818 | // Handling of the PAINT and UPDATE events is now done in the | ||
| 4819 | // peer's handleEvent() method so the background can be cleared | ||
| 4820 | // selectively for non-native components on Windows only. | ||
| 4821 | // - Fred.Ecks@Eng.sun.com, 5-8-98 | ||
| 4822 | |||
| 4823 | case KeyEvent.KEY_PRESSED: | ||
| 4824 | case KeyEvent.KEY_RELEASED: | ||
| 4825 | Container p = (Container)((this instanceof Container) ? this : parent); | ||
| 4826 | if (p != null) { | ||
| 4827 | p.preProcessKeyEvent((KeyEvent)e); | ||
| 4828 | if (e.isConsumed()) { | ||
| 4829 | if (focusLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4830 | focusLog.finest("Pre-process consumed event"); | ||
| 4831 | } | ||
| 4832 | return; | ||
| 4833 | } | ||
| 4834 | } | ||
| 4835 | break; | ||
| 4836 | |||
| 4837 | case WindowEvent.WINDOW_CLOSING: | ||
| 4838 | if (toolkit instanceof WindowClosingListener) { | ||
| 4839 | windowClosingException = ((WindowClosingListener) | ||
| 4840 | toolkit).windowClosingNotify((WindowEvent)e); | ||
| 4841 | if (checkWindowClosingException()) { | ||
| 4842 | return; | ||
| 4843 | } | ||
| 4844 | } | ||
| 4845 | break; | ||
| 4846 | |||
| 4847 | default: | ||
| 4848 | break; | ||
| 4849 | } | ||
| 4850 | |||
| 4851 | /* | ||
| 4852 | * 6. Deliver event for normal processing | ||
| 4853 | */ | ||
| 4854 | if (newEventsOnly) { | ||
| 4855 | // Filtering needs to really be moved to happen at a lower | ||
| 4856 | // level in order to get maximum performance gain; it is | ||
| 4857 | // here temporarily to ensure the API spec is honored. | ||
| 4858 | // | ||
| 4859 | if (eventEnabled(e)) { | ||
| 4860 | processEvent(e); | ||
| 4861 | } | ||
| 4862 | } else if (id == MouseEvent.MOUSE_WHEEL) { | ||
| 4863 | // newEventsOnly will be false for a listenerless ScrollPane, but | ||
| 4864 | // MouseWheelEvents still need to be dispatched to it so scrolling | ||
| 4865 | // can be done. | ||
| 4866 | autoProcessMouseWheel((MouseWheelEvent)e); | ||
| 4867 | } else if (!(e instanceof MouseEvent && !postsOldMouseEvents())) { | ||
| 4868 | // | ||
| 4869 | // backward compatibility | ||
| 4870 | // | ||
| 4871 | Event olde = e.convertToOld(); | ||
| 4872 | if (olde != null) { | ||
| 4873 | int key = olde.key; | ||
| 4874 | int modifiers = olde.modifiers; | ||
| 4875 | |||
| 4876 | postEvent(olde); | ||
| 4877 | if (olde.isConsumed()) { | ||
| 4878 | e.consume(); | ||
| 4879 | } | ||
| 4880 | // if target changed key or modifier values, copy them | ||
| 4881 | // back to original event | ||
| 4882 | // | ||
| 4883 | switch(olde.id) { | ||
| 4884 | case Event.KEY_PRESS: | ||
| 4885 | case Event.KEY_RELEASE: | ||
| 4886 | case Event.KEY_ACTION: | ||
| 4887 | case Event.KEY_ACTION_RELEASE: | ||
| 4888 | if (olde.key != key) { | ||
| 4889 | ((KeyEvent)e).setKeyChar(olde.getKeyEventChar()); | ||
| 4890 | } | ||
| 4891 | if (olde.modifiers != modifiers) { | ||
| 4892 | ((KeyEvent)e).setModifiers(olde.modifiers); | ||
| 4893 | } | ||
| 4894 | break; | ||
| 4895 | default: | ||
| 4896 | break; | ||
| 4897 | } | ||
| 4898 | } | ||
| 4899 | } | ||
| 4900 | |||
| 4901 | /* | ||
| 4902 | * 8. Special handling for 4061116 : Hook for browser to close modal | ||
| 4903 | * dialogs. | ||
| 4904 | */ | ||
| 4905 | if (id == WindowEvent.WINDOW_CLOSING && !e.isConsumed()) { | ||
| 4906 | if (toolkit instanceof WindowClosingListener) { | ||
| 4907 | windowClosingException = | ||
| 4908 | ((WindowClosingListener)toolkit). | ||
| 4909 | windowClosingDelivered((WindowEvent)e); | ||
| 4910 | if (checkWindowClosingException()) { | ||
| 4911 | return; | ||
| 4912 | } | ||
| 4913 | } | ||
| 4914 | } | ||
| 4915 | |||
| 4916 | /* | ||
| 4917 | * 9. Allow the peer to process the event. | ||
| 4918 | * Except KeyEvents, they will be processed by peer after | ||
| 4919 | * all KeyEventPostProcessors | ||
| 4920 | * (see DefaultKeyboardFocusManager.dispatchKeyEvent()) | ||
| 4921 | */ | ||
| 4922 | if (!(e instanceof KeyEvent)) { | ||
| 4923 | ComponentPeer tpeer = peer; | ||
| 4924 | if (e instanceof FocusEvent && (tpeer == null || tpeer instanceof LightweightPeer)) { | ||
| 4925 | // if focus owner is lightweight then its native container | ||
| 4926 | // processes event | ||
| 4927 | Component source = (Component)e.getSource(); | ||
| 4928 | if (source != null) { | ||
| 4929 | Container target = source.getNativeContainer(); | ||
| 4930 | if (target != null) { | ||
| 4931 | tpeer = target.getPeer(); | ||
| 4932 | } | ||
| 4933 | } | ||
| 4934 | } | ||
| 4935 | if (tpeer != null) { | ||
| 4936 | tpeer.handleEvent(e); | ||
| 4937 | } | ||
| 4938 | } | ||
| 4939 | } // dispatchEventImpl() | ||
| 4940 | |||
| 4941 | /* | ||
| 4942 | * If newEventsOnly is false, method is called so that ScrollPane can | ||
| 4943 | * override it and handle common-case mouse wheel scrolling. NOP | ||
| 4944 | * for Component. | ||
| 4945 | */ | ||
| 4946 | void autoProcessMouseWheel(MouseWheelEvent e) {} | ||
| 4947 | |||
| 4948 | /* | ||
| 4949 | * Dispatch given MouseWheelEvent to the first ancestor for which | ||
| 4950 | * MouseWheelEvents are enabled. | ||
| 4951 | * | ||
| 4952 | * Returns whether or not event was dispatched to an ancestor | ||
| 4953 | */ | ||
| 4954 | boolean dispatchMouseWheelToAncestor(MouseWheelEvent e) { | ||
| 4955 | int newX, newY; | ||
| 4956 | newX = e.getX() + getX(); // Coordinates take into account at least | ||
| 4957 | newY = e.getY() + getY(); // the cursor's position relative to this | ||
| 4958 | // Component (e.getX()), and this Component's | ||
| 4959 | // position relative to its parent. | ||
| 4960 | MouseWheelEvent newMWE; | ||
| 4961 | |||
| 4962 | if (eventLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4963 | eventLog.finest("dispatchMouseWheelToAncestor"); | ||
| 4964 | eventLog.finest("orig event src is of " + e.getSource().getClass()); | ||
| 4965 | } | ||
| 4966 | |||
| 4967 | /* parent field for Window refers to the owning Window. | ||
| 4968 | * MouseWheelEvents should NOT be propagated into owning Windows | ||
| 4969 | */ | ||
| 4970 | synchronized (getTreeLock()) { | ||
| 4971 | Container anc = getParent(); | ||
| 4972 | while (anc != null && !anc.eventEnabled(e)) { | ||
| 4973 | // fix coordinates to be relative to new event source | ||
| 4974 | newX += anc.getX(); | ||
| 4975 | newY += anc.getY(); | ||
| 4976 | |||
| 4977 | if (!(anc instanceof Window)) { | ||
| 4978 | anc = anc.getParent(); | ||
| 4979 | } | ||
| 4980 | else { | ||
| 4981 | break; | ||
| 4982 | } | ||
| 4983 | } | ||
| 4984 | |||
| 4985 | if (eventLog.isLoggable(PlatformLogger.FINEST)) { | ||
| 4986 | eventLog.finest("new event src is " + anc.getClass()); | ||
| 4987 | } | ||
| 4988 | |||
| 4989 | if (anc != null && anc.eventEnabled(e)) { | ||
| 4990 | // Change event to be from new source, with new x,y | ||
| 4991 | // For now, just create a new event - yucky | ||
| 4992 | |||
| 4993 | newMWE = new MouseWheelEvent(anc, // new source | ||
| 4994 | e.getID(), | ||
| 4995 | e.getWhen(), | ||
| 4996 | e.getModifiers(), | ||
| 4997 | newX, // x relative to new source | ||
| 4998 | newY, // y relative to new source | ||
| 4999 | e.getXOnScreen(), | ||
5100 more lines aren’t shown here.
Binary file not shown.
| @@ -0,0 +1,202 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2006, 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 | /* | ||
| 27 | * (C) Copyright IBM Corp. 1998 - All Rights Reserved | ||
| 28 | * | ||
| 29 | * The original version of this source code and documentation is copyrighted | ||
| 30 | * and owned by IBM, Inc. These materials are provided under terms of a | ||
| 31 | * License Agreement between IBM and Sun. This technology is protected by | ||
| 32 | * multiple US and International patents. This notice and attribution to IBM | ||
| 33 | * may not be removed. | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | package java.awt; | ||
| 38 | |||
| 39 | import java.util.Locale; | ||
| 40 | import java.util.ResourceBundle; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * The ComponentOrientation class encapsulates the language-sensitive | ||
| 44 | * orientation that is to be used to order the elements of a component | ||
| 45 | * or of text. It is used to reflect the differences in this ordering | ||
| 46 | * between Western alphabets, Middle Eastern (such as Hebrew), and Far | ||
| 47 | * Eastern (such as Japanese). | ||
| 48 | * <p> | ||
| 49 | * Fundamentally, this governs items (such as characters) which are laid out | ||
| 50 | * in lines, with the lines then laid out in a block. This also applies | ||
| 51 | * to items in a widget: for example, in a check box where the box is | ||
| 52 | * positioned relative to the text. | ||
| 53 | * <p> | ||
| 54 | * There are four different orientations used in modern languages | ||
| 55 | * as in the following table.<br> | ||
| 56 | * <pre> | ||
| 57 | * LT RT TL TR | ||
| 58 | * A B C C B A A D G G D A | ||
| 59 | * D E F F E D B E H H E B | ||
| 60 | * G H I I H G C F I I F C | ||
| 61 | * </pre><br> | ||
| 62 | * (In the header, the two-letter abbreviation represents the item direction | ||
| 63 | * in the first letter, and the line direction in the second. For example, | ||
| 64 | * LT means "items left-to-right, lines top-to-bottom", | ||
| 65 | * TL means "items top-to-bottom, lines left-to-right", and so on.) | ||
| 66 | * <p> | ||
| 67 | * The orientations are: | ||
| 68 | * <ul> | ||
| 69 | * <li>LT - Western Europe (optional for Japanese, Chinese, Korean) | ||
| 70 | * <li>RT - Middle East (Arabic, Hebrew) | ||
| 71 | * <li>TR - Japanese, Chinese, Korean | ||
| 72 | * <li>TL - Mongolian | ||
| 73 | * </ul> | ||
| 74 | * Components whose view and controller code depends on orientation | ||
| 75 | * should use the <code>isLeftToRight()</code> and | ||
| 76 | * <code>isHorizontal()</code> methods to | ||
| 77 | * determine their behavior. They should not include switch-like | ||
| 78 | * code that keys off of the constants, such as: | ||
| 79 | * <pre> | ||
| 80 | * if (orientation == LEFT_TO_RIGHT) { | ||
| 81 | * ... | ||
| 82 | * } else if (orientation == RIGHT_TO_LEFT) { | ||
| 83 | * ... | ||
| 84 | * } else { | ||
| 85 | * // Oops | ||
| 86 | * } | ||
| 87 | * </pre> | ||
| 88 | * This is unsafe, since more constants may be added in the future and | ||
| 89 | * since it is not guaranteed that orientation objects will be unique. | ||
| 90 | */ | ||
| 91 | public final class ComponentOrientation implements java.io.Serializable | ||
| 92 | { | ||
| 93 | /* | ||
| 94 | * serialVersionUID | ||
| 95 | */ | ||
| 96 | private static final long serialVersionUID = -4113291392143563828L; | ||
| 97 | |||
| 98 | // Internal constants used in the implementation | ||
| 99 | private static final int UNK_BIT = 1; | ||
| 100 | private static final int HORIZ_BIT = 2; | ||
| 101 | private static final int LTR_BIT = 4; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Items run left to right and lines flow top to bottom | ||
| 105 | * Examples: English, French. | ||
| 106 | */ | ||
| 107 | public static final ComponentOrientation LEFT_TO_RIGHT = | ||
| 108 | new ComponentOrientation(HORIZ_BIT|LTR_BIT); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Items run right to left and lines flow top to bottom | ||
| 112 | * Examples: Arabic, Hebrew. | ||
| 113 | */ | ||
| 114 | public static final ComponentOrientation RIGHT_TO_LEFT = | ||
| 115 | new ComponentOrientation(HORIZ_BIT); | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Indicates that a component's orientation has not been set. | ||
| 119 | * To preserve the behavior of existing applications, | ||
| 120 | * isLeftToRight will return true for this value. | ||
| 121 | */ | ||
| 122 | public static final ComponentOrientation UNKNOWN = | ||
| 123 | new ComponentOrientation(HORIZ_BIT|LTR_BIT|UNK_BIT); | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Are lines horizontal? | ||
| 127 | * This will return true for horizontal, left-to-right writing | ||
| 128 | * systems such as Roman. | ||
| 129 | */ | ||
| 130 | public boolean isHorizontal() { | ||
| 131 | return (orientation & HORIZ_BIT) != 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * HorizontalLines: Do items run left-to-right?<br> | ||
| 136 | * Vertical Lines: Do lines run left-to-right?<br> | ||
| 137 | * This will return true for horizontal, left-to-right writing | ||
| 138 | * systems such as Roman. | ||
| 139 | */ | ||
| 140 | public boolean isLeftToRight() { | ||
| 141 | return (orientation & LTR_BIT) != 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | /** | ||
| 145 | * Returns the orientation that is appropriate for the given locale. | ||
| 146 | * @param locale the specified locale | ||
| 147 | */ | ||
| 148 | public static ComponentOrientation getOrientation(Locale locale) { | ||
| 149 | // A more flexible implementation would consult a ResourceBundle | ||
| 150 | // to find the appropriate orientation. Until pluggable locales | ||
| 151 | // are introduced however, the flexiblity isn't really needed. | ||
| 152 | // So we choose efficiency instead. | ||
| 153 | String lang = locale.getLanguage(); | ||
| 154 | if( "iw".equals(lang) || "ar".equals(lang) | ||
| 155 | || "fa".equals(lang) || "ur".equals(lang) ) | ||
| 156 | { | ||
| 157 | return RIGHT_TO_LEFT; | ||
| 158 | } else { | ||
| 159 | return LEFT_TO_RIGHT; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Returns the orientation appropriate for the given ResourceBundle's | ||
| 165 | * localization. Three approaches are tried, in the following order: | ||
| 166 | * <ol> | ||
| 167 | * <li>Retrieve a ComponentOrientation object from the ResourceBundle | ||
| 168 | * using the string "Orientation" as the key. | ||
| 169 | * <li>Use the ResourceBundle.getLocale to determine the bundle's | ||
| 170 | * locale, then return the orientation for that locale. | ||
| 171 | * <li>Return the default locale's orientation. | ||
| 172 | * </ol> | ||
| 173 | * | ||
| 174 | * @deprecated As of J2SE 1.4, use {@link #getOrientation(java.util.Locale)}. | ||
| 175 | */ | ||
| 176 | @Deprecated | ||
| 177 | public static ComponentOrientation getOrientation(ResourceBundle bdl) | ||
| 178 | { | ||
| 179 | ComponentOrientation result = null; | ||
| 180 | |||
| 181 | try { | ||
| 182 | result = (ComponentOrientation)bdl.getObject("Orientation"); | ||
| 183 | } | ||
| 184 | catch (Exception e) { | ||
| 185 | } | ||
| 186 | |||
| 187 | if (result == null) { | ||
| 188 | result = getOrientation(bdl.getLocale()); | ||
| 189 | } | ||
| 190 | if (result == null) { | ||
| 191 | result = getOrientation(Locale.getDefault()); | ||
| 192 | } | ||
| 193 | return result; | ||
| 194 | } | ||
| 195 | |||
| 196 | private int orientation; | ||
| 197 | |||
| 198 | private ComponentOrientation(int value) | ||
| 199 | { | ||
| 200 | orientation = value; | ||
| 201 | } | ||
| 202 | } | ||
Binary file not shown.
| @@ -0,0 +1,86 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 1998, 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 java.awt; | ||
| 27 | |||
| 28 | import java.awt.image.ColorModel; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The <code>Composite</code> interface, along with | ||
| 32 | * {@link CompositeContext}, defines the methods to compose a draw | ||
| 33 | * primitive with the underlying graphics area. | ||
| 34 | * After the <code>Composite</code> is set in the | ||
| 35 | * {@link Graphics2D} context, it combines a shape, text, or an image | ||
| 36 | * being rendered with the colors that have already been rendered | ||
| 37 | * according to pre-defined rules. The classes | ||
| 38 | * implementing this interface provide the rules and a method to create | ||
| 39 | * the context for a particular operation. | ||
| 40 | * <code>CompositeContext</code> is an environment used by the | ||
| 41 | * compositing operation, which is created by the <code>Graphics2D</code> | ||
| 42 | * prior to the start of the operation. <code>CompositeContext</code> | ||
| 43 | * contains private information and resources needed for a compositing | ||
| 44 | * operation. When the <code>CompositeContext</code> is no longer needed, | ||
| 45 | * the <code>Graphics2D</code> object disposes of it in order to reclaim | ||
| 46 | * resources allocated for the operation. | ||
| 47 | * <p> | ||
| 48 | * Instances of classes implementing <code>Composite</code> must be | ||
| 49 | * immutable because the <code>Graphics2D</code> does not clone | ||
| 50 | * these objects when they are set as an attribute with the | ||
| 51 | * <code>setComposite</code> method or when the <code>Graphics2D</code> | ||
| 52 | * object is cloned. This is to avoid undefined rendering behavior of | ||
| 53 | * <code>Graphics2D</code>, resulting from the modification of | ||
| 54 | * the <code>Composite</code> object after it has been set in the | ||
| 55 | * <code>Graphics2D</code> context. | ||
| 56 | * <p> | ||
| 57 | * Since this interface must expose the contents of pixels on the | ||
| 58 | * target device or image to potentially arbitrary code, the use of | ||
| 59 | * custom objects which implement this interface when rendering directly | ||
| 60 | * to a screen device is governed by the <code>readDisplayPixels</code> | ||
| 61 | * {@link AWTPermission}. The permission check will occur when such | ||
| 62 | * a custom object is passed to the <code>setComposite</code> method | ||
| 63 | * of a <code>Graphics2D</code> retrieved from a {@link Component}. | ||
| 64 | * @see AlphaComposite | ||
| 65 | * @see CompositeContext | ||
| 66 | * @see Graphics2D#setComposite | ||
| 67 | */ | ||
| 68 | public interface Composite { | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Creates a context containing state that is used to perform | ||
| 72 | * the compositing operation. In a multi-threaded environment, | ||
| 73 | * several contexts can exist simultaneously for a single | ||
| 74 | * <code>Composite</code> object. | ||
| 75 | * @param srcColorModel the {@link ColorModel} of the source | ||
| 76 | * @param dstColorModel the <code>ColorModel</code> of the destination | ||
| 77 | * @param hints the hint that the context object uses to choose between | ||
| 78 | * rendering alternatives | ||
| 79 | * @return the <code>CompositeContext</code> object used to perform the | ||
| 80 | * compositing operation. | ||
| 81 | */ | ||
| 82 | public CompositeContext createContext(ColorModel srcColorModel, | ||
| 83 | ColorModel dstColorModel, | ||
| 84 | RenderingHints hints); | ||
| 85 | |||
| 86 | } | ||
Binary file not shown.
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 1998, 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 java.awt; | ||
| 27 | |||
| 28 | import java.awt.image.Raster; | ||
| 29 | import java.awt.image.WritableRaster; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * The <code>CompositeContext</code> interface defines the encapsulated | ||
| 33 | * and optimized environment for a compositing operation. | ||
| 34 | * <code>CompositeContext</code> objects maintain state for | ||
| 35 | * compositing operations. In a multi-threaded environment, several | ||
| 36 | * contexts can exist simultaneously for a single {@link Composite} | ||
| 37 | * object. | ||
| 38 | * @see Composite | ||
| 39 | */ | ||
| 40 | |||
| 41 | public interface CompositeContext { | ||
| 42 | /** | ||
| 43 | * Releases resources allocated for a context. | ||
| 44 | */ | ||
| 45 | public void dispose(); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Composes the two source {@link Raster} objects and | ||
| 49 | * places the result in the destination | ||
| 50 | * {@link WritableRaster}. Note that the destination | ||
| 51 | * can be the same object as either the first or second | ||
| 52 | * source. Note that <code>dstIn</code> and | ||
| 53 | * <code>dstOut</code> must be compatible with the | ||
| 54 | * <code>dstColorModel</code> passed to the | ||
| 55 | * {@link Composite#createContext(java.awt.image.ColorModel, java.awt.image.ColorModel, java.awt.RenderingHints) createContext} | ||
| 56 | * method of the <code>Composite</code> interface. | ||
| 57 | * @param src the first source for the compositing operation | ||
| 58 | * @param dstIn the second source for the compositing operation | ||
| 59 | * @param dstOut the <code>WritableRaster</code> into which the | ||
| 60 | * result of the operation is stored | ||
| 61 | * @see Composite | ||
| 62 | */ | ||
| 63 | public void compose(Raster src, | ||
| 64 | Raster dstIn, | ||
| 65 | WritableRaster dstOut); | ||
| 66 | |||
| 67 | |||
| 68 | } | ||
Binary file not shown.
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 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 java.awt; | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Conditional is used by the EventDispatchThread's message pumps to | ||
| 30 | * determine if a given pump should continue to run, or should instead exit | ||
| 31 | * and yield control to the parent pump. | ||
| 32 | * | ||
| 33 | * @author David Mendenhall | ||
| 34 | */ | ||
| 35 | interface Conditional { | ||
| 36 | boolean evaluate(); | ||
| 37 | } | ||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,4904 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1995, 2010, 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 | package java.awt; | ||
| 26 | |||
| 27 | import java.awt.dnd.DropTarget; | ||
| 28 | |||
| 29 | import java.awt.event.*; | ||
| 30 | |||
| 31 | import java.awt.peer.ContainerPeer; | ||
| 32 | import java.awt.peer.ComponentPeer; | ||
| 33 | import java.awt.peer.LightweightPeer; | ||
| 34 | |||
| 35 | import java.beans.PropertyChangeListener; | ||
| 36 | |||
| 37 | import java.io.IOException; | ||
| 38 | import java.io.ObjectInputStream; | ||
| 39 | import java.io.ObjectOutputStream; | ||
| 40 | import java.io.ObjectStreamField; | ||
| 41 | import java.io.PrintStream; | ||
| 42 | import java.io.PrintWriter; | ||
| 43 | |||
| 44 | import java.security.AccessController; | ||
| 45 | |||
| 46 | import java.util.Arrays; | ||
| 47 | import java.util.EventListener; | ||
| 48 | import java.util.HashSet; | ||
| 49 | import java.util.Set; | ||
| 50 | |||
| 51 | import javax.accessibility.*; | ||
| 52 | |||
| 53 | import sun.util.logging.PlatformLogger; | ||
| 54 | |||
| 55 | import sun.awt.AppContext; | ||
| 56 | import sun.awt.AWTAccessor; | ||
| 57 | import sun.awt.CausedFocusEvent; | ||
| 58 | import sun.awt.PeerEvent; | ||
| 59 | import sun.awt.SunToolkit; | ||
| 60 | |||
| 61 | import sun.awt.dnd.SunDropTargetEvent; | ||
| 62 | |||
| 63 | import sun.java2d.pipe.Region; | ||
| 64 | |||
| 65 | import sun.security.action.GetBooleanAction; | ||
| 66 | |||
| 67 | /** | ||
| 68 | * A generic Abstract Window Toolkit(AWT) container object is a component | ||
| 69 | * that can contain other AWT components. | ||
| 70 | * <p> | ||
| 71 | * Components added to a container are tracked in a list. The order | ||
| 72 | * of the list will define the components' front-to-back stacking order | ||
| 73 | * within the container. If no index is specified when adding a | ||
| 74 | * component to a container, it will be added to the end of the list | ||
| 75 | * (and hence to the bottom of the stacking order). | ||
| 76 | * <p> | ||
| 77 | * <b>Note</b>: For details on the focus subsystem, see | ||
| 78 | * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html"> | ||
| 79 | * How to Use the Focus Subsystem</a>, | ||
| 80 | * a section in <em>The Java Tutorial</em>, and the | ||
| 81 | * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> | ||
| 82 | * for more information. | ||
| 83 | * | ||
| 84 | * @author Arthur van Hoff | ||
| 85 | * @author Sami Shaio | ||
| 86 | * @see #add(java.awt.Component, int) | ||
| 87 | * @see #getComponent(int) | ||
| 88 | * @see LayoutManager | ||
| 89 | * @since JDK1.0 | ||
| 90 | */ | ||
| 91 | public class Container extends Component { | ||
| 92 | |||
| 93 | private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container"); | ||
| 94 | private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container"); | ||
| 95 | |||
| 96 | private static final Component[] EMPTY_ARRAY = new Component[0]; | ||
| 97 | |||
| 98 | /** | ||
| 99 | * The components in this container. | ||
| 100 | * @see #add | ||
| 101 | * @see #getComponents | ||
| 102 | */ | ||
| 103 | private java.util.List<Component> component = new java.util.ArrayList<Component>(); | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Layout manager for this container. | ||
| 107 | * @see #doLayout | ||
| 108 | * @see #setLayout | ||
| 109 | * @see #getLayout | ||
| 110 | */ | ||
| 111 | LayoutManager layoutMgr; | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Event router for lightweight components. If this container | ||
| 115 | * is native, this dispatcher takes care of forwarding and | ||
| 116 | * retargeting the events to lightweight components contained | ||
| 117 | * (if any). | ||
| 118 | */ | ||
| 119 | private LightweightDispatcher dispatcher; | ||
| 120 | |||
| 121 | /** | ||
| 122 | * The focus traversal policy that will manage keyboard traversal of this | ||
| 123 | * Container's children, if this Container is a focus cycle root. If the | ||
| 124 | * value is null, this Container inherits its policy from its focus-cycle- | ||
| 125 | * root ancestor. If all such ancestors of this Container have null | ||
| 126 | * policies, then the current KeyboardFocusManager's default policy is | ||
| 127 | * used. If the value is non-null, this policy will be inherited by all | ||
| 128 | * focus-cycle-root children that have no keyboard-traversal policy of | ||
| 129 | * their own (as will, recursively, their focus-cycle-root children). | ||
| 130 | * <p> | ||
| 131 | * If this Container is not a focus cycle root, the value will be | ||
| 132 | * remembered, but will not be used or inherited by this or any other | ||
| 133 | * Containers until this Container is made a focus cycle root. | ||
| 134 | * | ||
| 135 | * @see #setFocusTraversalPolicy | ||
| 136 | * @see #getFocusTraversalPolicy | ||
| 137 | * @since 1.4 | ||
| 138 | */ | ||
| 139 | private transient FocusTraversalPolicy focusTraversalPolicy; | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Indicates whether this Component is the root of a focus traversal cycle. | ||
| 143 | * Once focus enters a traversal cycle, typically it cannot leave it via | ||
| 144 | * focus traversal unless one of the up- or down-cycle keys is pressed. | ||
| 145 | * Normal traversal is limited to this Container, and all of this | ||
| 146 | * Container's descendants that are not descendants of inferior focus cycle | ||
| 147 | * roots. | ||
| 148 | * | ||
| 149 | * @see #setFocusCycleRoot | ||
| 150 | * @see #isFocusCycleRoot | ||
| 151 | * @since 1.4 | ||
| 152 | */ | ||
| 153 | private boolean focusCycleRoot = false; | ||
| 154 | |||
| 155 | |||
| 156 | /** | ||
| 157 | * Stores the value of focusTraversalPolicyProvider property. | ||
| 158 | * @since 1.5 | ||
| 159 | * @see #setFocusTraversalPolicyProvider | ||
| 160 | */ | ||
| 161 | private boolean focusTraversalPolicyProvider; | ||
| 162 | |||
| 163 | // keeps track of the threads that are printing this component | ||
| 164 | private transient Set printingThreads; | ||
| 165 | // True if there is at least one thread that's printing this component | ||
| 166 | private transient boolean printing = false; | ||
| 167 | |||
| 168 | transient ContainerListener containerListener; | ||
| 169 | |||
| 170 | /* HierarchyListener and HierarchyBoundsListener support */ | ||
| 171 | transient int listeningChildren; | ||
| 172 | transient int listeningBoundsChildren; | ||
| 173 | transient int descendantsCount; | ||
| 174 | |||
| 175 | /* Non-opaque window support -- see Window.setLayersOpaque */ | ||
| 176 | transient Color preserveBackgroundColor = null; | ||
| 177 | |||
| 178 | /** | ||
| 179 | * JDK 1.1 serialVersionUID | ||
| 180 | */ | ||
| 181 | private static final long serialVersionUID = 4613797578919906343L; | ||
| 182 | |||
| 183 | /** | ||
| 184 | * A constant which toggles one of the controllable behaviors | ||
| 185 | * of <code>getMouseEventTarget</code>. It is used to specify whether | ||
| 186 | * the method can return the Container on which it is originally called | ||
| 187 | * in case if none of its children are the current mouse event targets. | ||
| 188 | * | ||
| 189 | * @see #getMouseEventTarget(int, int, boolean, boolean, boolean) | ||
| 190 | */ | ||
| 191 | static final boolean INCLUDE_SELF = true; | ||
| 192 | |||
| 193 | /** | ||
| 194 | * A constant which toggles one of the controllable behaviors | ||
| 195 | * of <code>getMouseEventTarget</code>. It is used to specify whether | ||
| 196 | * the method should search only lightweight components. | ||
| 197 | * | ||
| 198 | * @see #getMouseEventTarget(int, int, boolean, boolean, boolean) | ||
| 199 | */ | ||
| 200 | static final boolean SEARCH_HEAVYWEIGHTS = true; | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Number of HW or LW components in this container (including | ||
| 204 | * all descendant containers). | ||
| 205 | */ | ||
| 206 | private transient int numOfHWComponents = 0; | ||
| 207 | private transient int numOfLWComponents = 0; | ||
| 208 | |||
| 209 | private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container"); | ||
| 210 | |||
| 211 | /** | ||
| 212 | * @serialField ncomponents int | ||
| 213 | * The number of components in this container. | ||
| 214 | * This value can be null. | ||
| 215 | * @serialField component Component[] | ||
| 216 | * The components in this container. | ||
| 217 | * @serialField layoutMgr LayoutManager | ||
| 218 | * Layout manager for this container. | ||
| 219 | * @serialField dispatcher LightweightDispatcher | ||
| 220 | * Event router for lightweight components. If this container | ||
| 221 | * is native, this dispatcher takes care of forwarding and | ||
| 222 | * retargeting the events to lightweight components contained | ||
| 223 | * (if any). | ||
| 224 | * @serialField maxSize Dimension | ||
| 225 | * Maximum size of this Container. | ||
| 226 | * @serialField focusCycleRoot boolean | ||
| 227 | * Indicates whether this Component is the root of a focus traversal cycle. | ||
| 228 | * Once focus enters a traversal cycle, typically it cannot leave it via | ||
| 229 | * focus traversal unless one of the up- or down-cycle keys is pressed. | ||
| 230 | * Normal traversal is limited to this Container, and all of this | ||
| 231 | * Container's descendants that are not descendants of inferior focus cycle | ||
| 232 | * roots. | ||
| 233 | * @serialField containerSerializedDataVersion int | ||
| 234 | * Container Serial Data Version. | ||
| 235 | * @serialField focusTraversalPolicyProvider boolean | ||
| 236 | * Stores the value of focusTraversalPolicyProvider property. | ||
| 237 | */ | ||
| 238 | private static final ObjectStreamField[] serialPersistentFields = { | ||
| 239 | new ObjectStreamField("ncomponents", Integer.TYPE), | ||
| 240 | new ObjectStreamField("component", Component[].class), | ||
| 241 | new ObjectStreamField("layoutMgr", LayoutManager.class), | ||
| 242 | new ObjectStreamField("dispatcher", LightweightDispatcher.class), | ||
| 243 | new ObjectStreamField("maxSize", Dimension.class), | ||
| 244 | new ObjectStreamField("focusCycleRoot", Boolean.TYPE), | ||
| 245 | new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE), | ||
| 246 | new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE), | ||
| 247 | }; | ||
| 248 | |||
| 249 | static { | ||
| 250 | /* ensure that the necessary native libraries are loaded */ | ||
| 251 | Toolkit.loadLibraries(); | ||
| 252 | if (!GraphicsEnvironment.isHeadless()) { | ||
| 253 | initIDs(); | ||
| 254 | } | ||
| 255 | |||
| 256 | AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() { | ||
| 257 | @Override | ||
| 258 | public void validateUnconditionally(Container cont) { | ||
| 259 | cont.validateUnconditionally(); | ||
| 260 | } | ||
| 261 | }); | ||
| 262 | } | ||
| 263 | |||
| 264 | /** | ||
| 265 | * Initialize JNI field and method IDs for fields that may be | ||
| 266 | called from C. | ||
| 267 | */ | ||
| 268 | private static native void initIDs(); | ||
| 269 | |||
| 270 | /** | ||
| 271 | * Constructs a new Container. Containers can be extended directly, | ||
| 272 | * but are lightweight in this case and must be contained by a parent | ||
| 273 | * somewhere higher up in the component tree that is native. | ||
| 274 | * (such as Frame for example). | ||
| 275 | */ | ||
| 276 | public Container() { | ||
| 277 | } | ||
| 278 | |||
| 279 | void initializeFocusTraversalKeys() { | ||
| 280 | focusTraversalKeys = new Set[4]; | ||
| 281 | } | ||
| 282 | |||
| 283 | /** | ||
| 284 | * Gets the number of components in this panel. | ||
| 285 | * <p> | ||
| 286 | * Note: This method should be called under AWT tree lock. | ||
| 287 | * | ||
| 288 | * @return the number of components in this panel. | ||
| 289 | * @see #getComponent | ||
| 290 | * @since JDK1.1 | ||
| 291 | * @see Component#getTreeLock() | ||
| 292 | */ | ||
| 293 | public int getComponentCount() { | ||
| 294 | return countComponents(); | ||
| 295 | } | ||
| 296 | |||
| 297 | /** | ||
| 298 | * @deprecated As of JDK version 1.1, | ||
| 299 | * replaced by getComponentCount(). | ||
| 300 | */ | ||
| 301 | @Deprecated | ||
| 302 | public int countComponents() { | ||
| 303 | // This method is not synchronized under AWT tree lock. | ||
| 304 | // Instead, the calling code is responsible for the | ||
| 305 | // synchronization. See 6784816 for details. | ||
| 306 | return component.size(); | ||
| 307 | } | ||
| 308 | |||
| 309 | /** | ||
| 310 | * Gets the nth component in this container. | ||
| 311 | * <p> | ||
| 312 | * Note: This method should be called under AWT tree lock. | ||
| 313 | * | ||
| 314 | * @param n the index of the component to get. | ||
| 315 | * @return the n<sup>th</sup> component in this container. | ||
| 316 | * @exception ArrayIndexOutOfBoundsException | ||
| 317 | * if the n<sup>th</sup> value does not exist. | ||
| 318 | * @see Component#getTreeLock() | ||
| 319 | */ | ||
| 320 | public Component getComponent(int n) { | ||
| 321 | // This method is not synchronized under AWT tree lock. | ||
| 322 | // Instead, the calling code is responsible for the | ||
| 323 | // synchronization. See 6784816 for details. | ||
| 324 | try { | ||
| 325 | return component.get(n); | ||
| 326 | } catch (IndexOutOfBoundsException z) { | ||
| 327 | throw new ArrayIndexOutOfBoundsException("No such child: " + n); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | /** | ||
| 332 | * Gets all the components in this container. | ||
| 333 | * <p> | ||
| 334 | * Note: This method should be called under AWT tree lock. | ||
| 335 | * | ||
| 336 | * @return an array of all the components in this container. | ||
| 337 | * @see Component#getTreeLock() | ||
| 338 | */ | ||
| 339 | public Component[] getComponents() { | ||
| 340 | // This method is not synchronized under AWT tree lock. | ||
| 341 | // Instead, the calling code is responsible for the | ||
| 342 | // synchronization. See 6784816 for details. | ||
| 343 | return getComponents_NoClientCode(); | ||
| 344 | } | ||
| 345 | |||
| 346 | // NOTE: This method may be called by privileged threads. | ||
| 347 | // This functionality is implemented in a package-private method | ||
| 348 | // to insure that it cannot be overridden by client subclasses. | ||
| 349 | // DO NOT INVOKE CLIENT CODE ON THIS THREAD! | ||
| 350 | final Component[] getComponents_NoClientCode() { | ||
| 351 | return component.toArray(EMPTY_ARRAY); | ||
| 352 | } | ||
| 353 | |||
| 354 | /* | ||
| 355 | * Wrapper for getComponents() method with a proper synchronization. | ||
| 356 | */ | ||
| 357 | Component[] getComponentsSync() { | ||
| 358 | synchronized (getTreeLock()) { | ||
| 359 | return getComponents(); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Determines the insets of this container, which indicate the size | ||
| 365 | * of the container's border. | ||
| 366 | * <p> | ||
| 367 | * A <code>Frame</code> object, for example, has a top inset that | ||
| 368 | * corresponds to the height of the frame's title bar. | ||
| 369 | * @return the insets of this container. | ||
| 370 | * @see Insets | ||
| 371 | * @see LayoutManager | ||
| 372 | * @since JDK1.1 | ||
| 373 | */ | ||
| 374 | public Insets getInsets() { | ||
| 375 | return insets(); | ||
| 376 | } | ||
| 377 | |||
| 378 | /** | ||
| 379 | * @deprecated As of JDK version 1.1, | ||
| 380 | * replaced by <code>getInsets()</code>. | ||
| 381 | */ | ||
| 382 | @Deprecated | ||
| 383 | public Insets insets() { | ||
| 384 | ComponentPeer peer = this.peer; | ||
| 385 | if (peer instanceof ContainerPeer) { | ||
| 386 | ContainerPeer cpeer = (ContainerPeer)peer; | ||
| 387 | return (Insets)cpeer.getInsets().clone(); | ||
| 388 | } | ||
| 389 | return new Insets(0, 0, 0, 0); | ||
| 390 | } | ||
| 391 | |||
| 392 | /** | ||
| 393 | * Appends the specified component to the end of this container. | ||
| 394 | * This is a convenience method for {@link #addImpl}. | ||
| 395 | * <p> | ||
| 396 | * This method changes layout-related information, and therefore, | ||
| 397 | * invalidates the component hierarchy. If the container has already been | ||
| 398 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 399 | * display the added component. | ||
| 400 | * | ||
| 401 | * @param comp the component to be added | ||
| 402 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 403 | * @see #addImpl | ||
| 404 | * @see #invalidate | ||
| 405 | * @see #validate | ||
| 406 | * @see javax.swing.JComponent#revalidate() | ||
| 407 | * @return the component argument | ||
| 408 | */ | ||
| 409 | public Component add(Component comp) { | ||
| 410 | addImpl(comp, null, -1); | ||
| 411 | return comp; | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Adds the specified component to this container. | ||
| 416 | * This is a convenience method for {@link #addImpl}. | ||
| 417 | * <p> | ||
| 418 | * This method is obsolete as of 1.1. Please use the | ||
| 419 | * method <code>add(Component, Object)</code> instead. | ||
| 420 | * <p> | ||
| 421 | * This method changes layout-related information, and therefore, | ||
| 422 | * invalidates the component hierarchy. If the container has already been | ||
| 423 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 424 | * display the added component. | ||
| 425 | * | ||
| 426 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 427 | * @see #add(Component, Object) | ||
| 428 | * @see #invalidate | ||
| 429 | */ | ||
| 430 | public Component add(String name, Component comp) { | ||
| 431 | addImpl(comp, name, -1); | ||
| 432 | return comp; | ||
| 433 | } | ||
| 434 | |||
| 435 | /** | ||
| 436 | * Adds the specified component to this container at the given | ||
| 437 | * position. | ||
| 438 | * This is a convenience method for {@link #addImpl}. | ||
| 439 | * <p> | ||
| 440 | * This method changes layout-related information, and therefore, | ||
| 441 | * invalidates the component hierarchy. If the container has already been | ||
| 442 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 443 | * display the added component. | ||
| 444 | * | ||
| 445 | * | ||
| 446 | * @param comp the component to be added | ||
| 447 | * @param index the position at which to insert the component, | ||
| 448 | * or <code>-1</code> to append the component to the end | ||
| 449 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 450 | * @exception IllegalArgumentException if {@code index} is invalid (see | ||
| 451 | * {@link #addImpl} for details) | ||
| 452 | * @return the component <code>comp</code> | ||
| 453 | * @see #addImpl | ||
| 454 | * @see #remove | ||
| 455 | * @see #invalidate | ||
| 456 | * @see #validate | ||
| 457 | * @see javax.swing.JComponent#revalidate() | ||
| 458 | */ | ||
| 459 | public Component add(Component comp, int index) { | ||
| 460 | addImpl(comp, null, index); | ||
| 461 | return comp; | ||
| 462 | } | ||
| 463 | |||
| 464 | /** | ||
| 465 | * Checks that the component | ||
| 466 | * isn't supposed to be added into itself. | ||
| 467 | */ | ||
| 468 | private void checkAddToSelf(Component comp){ | ||
| 469 | if (comp instanceof Container) { | ||
| 470 | for (Container cn = this; cn != null; cn=cn.parent) { | ||
| 471 | if (cn == comp) { | ||
| 472 | throw new IllegalArgumentException("adding container's parent to itself"); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * Checks that the component is not a Window instance. | ||
| 480 | */ | ||
| 481 | private void checkNotAWindow(Component comp){ | ||
| 482 | if (comp instanceof Window) { | ||
| 483 | throw new IllegalArgumentException("adding a window to a container"); | ||
| 484 | } | ||
| 485 | } | ||
| 486 | |||
| 487 | /** | ||
| 488 | * Checks that the component comp can be added to this container | ||
| 489 | * Checks : index in bounds of container's size, | ||
| 490 | * comp is not one of this container's parents, | ||
| 491 | * and comp is not a window. | ||
| 492 | * Comp and container must be on the same GraphicsDevice. | ||
| 493 | * if comp is container, all sub-components must be on | ||
| 494 | * same GraphicsDevice. | ||
| 495 | * | ||
| 496 | * @since 1.5 | ||
| 497 | */ | ||
| 498 | private void checkAdding(Component comp, int index) { | ||
| 499 | checkTreeLock(); | ||
| 500 | |||
| 501 | GraphicsConfiguration thisGC = getGraphicsConfiguration(); | ||
| 502 | |||
| 503 | if (index > component.size() || index < 0) { | ||
| 504 | throw new IllegalArgumentException("illegal component position"); | ||
| 505 | } | ||
| 506 | if (comp.parent == this) { | ||
| 507 | if (index == component.size()) { | ||
| 508 | throw new IllegalArgumentException("illegal component position " + | ||
| 509 | index + " should be less then " + component.size()); | ||
| 510 | } | ||
| 511 | } | ||
| 512 | checkAddToSelf(comp); | ||
| 513 | checkNotAWindow(comp); | ||
| 514 | |||
| 515 | Window thisTopLevel = getContainingWindow(); | ||
| 516 | Window compTopLevel = comp.getContainingWindow(); | ||
| 517 | if (thisTopLevel != compTopLevel) { | ||
| 518 | throw new IllegalArgumentException("component and container should be in the same top-level window"); | ||
| 519 | } | ||
| 520 | if (thisGC != null) { | ||
| 521 | comp.checkGD(thisGC.getDevice().getIDstring()); | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | /** | ||
| 526 | * Removes component comp from this container without making unneccessary changes | ||
| 527 | * and generating unneccessary events. This function intended to perform optimized | ||
| 528 | * remove, for example, if newParent and current parent are the same it just changes | ||
| 529 | * index without calling removeNotify. | ||
| 530 | * Note: Should be called while holding treeLock | ||
| 531 | * Returns whether removeNotify was invoked | ||
| 532 | * @since: 1.5 | ||
| 533 | */ | ||
| 534 | private boolean removeDelicately(Component comp, Container newParent, int newIndex) { | ||
| 535 | checkTreeLock(); | ||
| 536 | |||
| 537 | int index = getComponentZOrder(comp); | ||
| 538 | boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent); | ||
| 539 | if (needRemoveNotify) { | ||
| 540 | comp.removeNotify(); | ||
| 541 | } | ||
| 542 | if (newParent != this) { | ||
| 543 | if (layoutMgr != null) { | ||
| 544 | layoutMgr.removeLayoutComponent(comp); | ||
| 545 | } | ||
| 546 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 547 | -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 548 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 549 | -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 550 | adjustDescendants(-(comp.countHierarchyMembers())); | ||
| 551 | |||
| 552 | comp.parent = null; | ||
| 553 | if (needRemoveNotify) { | ||
| 554 | comp.setGraphicsConfiguration(null); | ||
| 555 | } | ||
| 556 | component.remove(index); | ||
| 557 | |||
| 558 | invalidateIfValid(); | ||
| 559 | } else { | ||
| 560 | // We should remove component and then | ||
| 561 | // add it by the newIndex without newIndex decrement if even we shift components to the left | ||
| 562 | // after remove. Consult the rules below: | ||
| 563 | // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452 | ||
| 564 | // 4->2: 012345 -> 014235 | ||
| 565 | component.remove(index); | ||
| 566 | component.add(newIndex, comp); | ||
| 567 | } | ||
| 568 | if (comp.parent == null) { // was actually removed | ||
| 569 | if (containerListener != null || | ||
| 570 | (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 571 | Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { | ||
| 572 | ContainerEvent e = new ContainerEvent(this, | ||
| 573 | ContainerEvent.COMPONENT_REMOVED, | ||
| 574 | comp); | ||
| 575 | dispatchEvent(e); | ||
| 576 | |||
| 577 | } | ||
| 578 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, | ||
| 579 | this, HierarchyEvent.PARENT_CHANGED, | ||
| 580 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 581 | if (peer != null && layoutMgr == null && isVisible()) { | ||
| 582 | updateCursorImmediately(); | ||
| 583 | } | ||
| 584 | } | ||
| 585 | return needRemoveNotify; | ||
| 586 | } | ||
| 587 | |||
| 588 | /** | ||
| 589 | * Checks whether this container can contain component which is focus owner. | ||
| 590 | * Verifies that container is enable and showing, and if it is focus cycle root | ||
| 591 | * its FTP allows component to be focus owner | ||
| 592 | * @since 1.5 | ||
| 593 | */ | ||
| 594 | boolean canContainFocusOwner(Component focusOwnerCandidate) { | ||
| 595 | if (!(isEnabled() && isDisplayable() | ||
| 596 | && isVisible() && isFocusable())) | ||
| 597 | { | ||
| 598 | return false; | ||
| 599 | } | ||
| 600 | if (isFocusCycleRoot()) { | ||
| 601 | FocusTraversalPolicy policy = getFocusTraversalPolicy(); | ||
| 602 | if (policy instanceof DefaultFocusTraversalPolicy) { | ||
| 603 | if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) { | ||
| 604 | return false; | ||
| 605 | } | ||
| 606 | } | ||
| 607 | } | ||
| 608 | synchronized(getTreeLock()) { | ||
| 609 | if (parent != null) { | ||
| 610 | return parent.canContainFocusOwner(focusOwnerCandidate); | ||
| 611 | } | ||
| 612 | } | ||
| 613 | return true; | ||
| 614 | } | ||
| 615 | |||
| 616 | /** | ||
| 617 | * Checks whether or not this container has heavyweight children. | ||
| 618 | * Note: Should be called while holding tree lock | ||
| 619 | * @return true if there is at least one heavyweight children in a container, false otherwise | ||
| 620 | * @since 1.5 | ||
| 621 | */ | ||
| 622 | final boolean hasHeavyweightDescendants() { | ||
| 623 | checkTreeLock(); | ||
| 624 | return numOfHWComponents > 0; | ||
| 625 | } | ||
| 626 | |||
| 627 | /** | ||
| 628 | * Checks whether or not this container has lightweight children. | ||
| 629 | * Note: Should be called while holding tree lock | ||
| 630 | * @return true if there is at least one lightweight children in a container, false otherwise | ||
| 631 | * @since 1.7 | ||
| 632 | */ | ||
| 633 | final boolean hasLightweightDescendants() { | ||
| 634 | checkTreeLock(); | ||
| 635 | return numOfLWComponents > 0; | ||
| 636 | } | ||
| 637 | |||
| 638 | /** | ||
| 639 | * Returns closest heavyweight component to this container. If this container is heavyweight | ||
| 640 | * returns this. | ||
| 641 | * @since 1.5 | ||
| 642 | */ | ||
| 643 | Container getHeavyweightContainer() { | ||
| 644 | checkTreeLock(); | ||
| 645 | if (peer != null && !(peer instanceof LightweightPeer)) { | ||
| 646 | return this; | ||
| 647 | } else { | ||
| 648 | return getNativeContainer(); | ||
| 649 | } | ||
| 650 | } | ||
| 651 | |||
| 652 | /** | ||
| 653 | * Detects whether or not remove from current parent and adding to new parent requires call of | ||
| 654 | * removeNotify on the component. Since removeNotify destroys native window this might (not) | ||
| 655 | * be required. For example, if new container and old containers are the same we don't need to | ||
| 656 | * destroy native window. | ||
| 657 | * @since: 1.5 | ||
| 658 | */ | ||
| 659 | private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) { | ||
| 660 | if (oldContainer == null) { // Component didn't have parent - no removeNotify | ||
| 661 | return false; | ||
| 662 | } | ||
| 663 | if (comp.peer == null) { // Component didn't have peer - no removeNotify | ||
| 664 | return false; | ||
| 665 | } | ||
| 666 | if (newContainer.peer == null) { | ||
| 667 | // Component has peer but new Container doesn't - call removeNotify | ||
| 668 | return true; | ||
| 669 | } | ||
| 670 | |||
| 671 | // If component is lightweight non-Container or lightweight Container with all but heavyweight | ||
| 672 | // children there is no need to call remove notify | ||
| 673 | if (comp.isLightweight()) { | ||
| 674 | boolean isContainer = comp instanceof Container; | ||
| 675 | |||
| 676 | if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) { | ||
| 677 | return false; | ||
| 678 | } | ||
| 679 | } | ||
| 680 | |||
| 681 | // If this point is reached, then the comp is either a HW or a LW container with HW descendants. | ||
| 682 | |||
| 683 | // All three components have peers, check for peer change | ||
| 684 | Container newNativeContainer = oldContainer.getHeavyweightContainer(); | ||
| 685 | Container oldNativeContainer = newContainer.getHeavyweightContainer(); | ||
| 686 | if (newNativeContainer != oldNativeContainer) { | ||
| 687 | // Native containers change - check whether or not current platform supports | ||
| 688 | // changing of widget hierarchy on native level without recreation. | ||
| 689 | // The current implementation forbids reparenting of LW containers with HW descendants | ||
| 690 | // into another native container w/o destroying the peers. Actually such an operation | ||
| 691 | // is quite rare. If we ever need to save the peers, we'll have to slightly change the | ||
| 692 | // addDelicately() method in order to handle such LW containers recursively, reparenting | ||
| 693 | // each HW descendant independently. | ||
| 694 | return !comp.peer.isReparentSupported(); | ||
| 695 | } else { | ||
| 696 | return false; | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | /** | ||
| 701 | * Moves the specified component to the specified z-order index in | ||
| 702 | * the container. The z-order determines the order that components | ||
| 703 | * are painted; the component with the highest z-order paints first | ||
| 704 | * and the component with the lowest z-order paints last. | ||
| 705 | * Where components overlap, the component with the lower | ||
| 706 | * z-order paints over the component with the higher z-order. | ||
| 707 | * <p> | ||
| 708 | * If the component is a child of some other container, it is | ||
| 709 | * removed from that container before being added to this container. | ||
| 710 | * The important difference between this method and | ||
| 711 | * <code>java.awt.Container.add(Component, int)</code> is that this method | ||
| 712 | * doesn't call <code>removeNotify</code> on the component while | ||
| 713 | * removing it from its previous container unless necessary and when | ||
| 714 | * allowed by the underlying native windowing system. This way, if the | ||
| 715 | * component has the keyboard focus, it maintains the focus when | ||
| 716 | * moved to the new position. | ||
| 717 | * <p> | ||
| 718 | * This property is guaranteed to apply only to lightweight | ||
| 719 | * non-<code>Container</code> components. | ||
| 720 | * <p> | ||
| 721 | * This method changes layout-related information, and therefore, | ||
| 722 | * invalidates the component hierarchy. | ||
| 723 | * <p> | ||
| 724 | * <b>Note</b>: Not all platforms support changing the z-order of | ||
| 725 | * heavyweight components from one container into another without | ||
| 726 | * the call to <code>removeNotify</code>. There is no way to detect | ||
| 727 | * whether a platform supports this, so developers shouldn't make | ||
| 728 | * any assumptions. | ||
| 729 | * | ||
| 730 | * @param comp the component to be moved | ||
| 731 | * @param index the position in the container's list to | ||
| 732 | * insert the component, where <code>getComponentCount()</code> | ||
| 733 | * appends to the end | ||
| 734 | * @exception NullPointerException if <code>comp</code> is | ||
| 735 | * <code>null</code> | ||
| 736 | * @exception IllegalArgumentException if <code>comp</code> is one of the | ||
| 737 | * container's parents | ||
| 738 | * @exception IllegalArgumentException if <code>index</code> is not in | ||
| 739 | * the range <code>[0, getComponentCount()]</code> for moving | ||
| 740 | * between containers, or not in the range | ||
| 741 | * <code>[0, getComponentCount()-1]</code> for moving inside | ||
| 742 | * a container | ||
| 743 | * @exception IllegalArgumentException if adding a container to itself | ||
| 744 | * @exception IllegalArgumentException if adding a <code>Window</code> | ||
| 745 | * to a container | ||
| 746 | * @see #getComponentZOrder(java.awt.Component) | ||
| 747 | * @see #invalidate | ||
| 748 | * @since 1.5 | ||
| 749 | */ | ||
| 750 | public void setComponentZOrder(Component comp, int index) { | ||
| 751 | synchronized (getTreeLock()) { | ||
| 752 | // Store parent because remove will clear it | ||
| 753 | Container curParent = comp.parent; | ||
| 754 | int oldZindex = getComponentZOrder(comp); | ||
| 755 | |||
| 756 | if (curParent == this && index == oldZindex) { | ||
| 757 | return; | ||
| 758 | } | ||
| 759 | checkAdding(comp, index); | ||
| 760 | |||
| 761 | boolean peerRecreated = (curParent != null) ? | ||
| 762 | curParent.removeDelicately(comp, this, index) : false; | ||
| 763 | |||
| 764 | addDelicately(comp, curParent, index); | ||
| 765 | |||
| 766 | // If the oldZindex == -1, the component gets inserted, | ||
| 767 | // rather than it changes its z-order. | ||
| 768 | if (!peerRecreated && oldZindex != -1) { | ||
| 769 | // The new 'index' cannot be == -1. | ||
| 770 | // It gets checked at the checkAdding() method. | ||
| 771 | // Therefore both oldZIndex and index denote | ||
| 772 | // some existing positions at this point and | ||
| 773 | // this is actually a Z-order changing. | ||
| 774 | comp.mixOnZOrderChanging(oldZindex, index); | ||
| 775 | } | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 779 | /** | ||
| 780 | * Traverses the tree of components and reparents children heavyweight component | ||
| 781 | * to new heavyweight parent. | ||
| 782 | * @since 1.5 | ||
| 783 | */ | ||
| 784 | private void reparentTraverse(ContainerPeer parentPeer, Container child) { | ||
| 785 | checkTreeLock(); | ||
| 786 | |||
| 787 | for (int i = 0; i < child.getComponentCount(); i++) { | ||
| 788 | Component comp = child.getComponent(i); | ||
| 789 | if (comp.isLightweight()) { | ||
| 790 | // If components is lightweight check if it is container | ||
| 791 | // If it is container it might contain heavyweight children we need to reparent | ||
| 792 | if (comp instanceof Container) { | ||
| 793 | reparentTraverse(parentPeer, (Container)comp); | ||
| 794 | } | ||
| 795 | } else { | ||
| 796 | // Q: Need to update NativeInLightFixer? | ||
| 797 | comp.getPeer().reparent(parentPeer); | ||
| 798 | } | ||
| 799 | } | ||
| 800 | } | ||
| 801 | |||
| 802 | /** | ||
| 803 | * Reparents child component peer to this container peer. | ||
| 804 | * Container must be heavyweight. | ||
| 805 | * @since 1.5 | ||
| 806 | */ | ||
| 807 | private void reparentChild(Component comp) { | ||
| 808 | checkTreeLock(); | ||
| 809 | if (comp == null) { | ||
| 810 | return; | ||
| 811 | } | ||
| 812 | if (comp.isLightweight()) { | ||
| 813 | // If component is lightweight container we need to reparent all its explicit heavyweight children | ||
| 814 | if (comp instanceof Container) { | ||
| 815 | // Traverse component's tree till depth-first until encountering heavyweight component | ||
| 816 | reparentTraverse((ContainerPeer)getPeer(), (Container)comp); | ||
| 817 | } | ||
| 818 | } else { | ||
| 819 | comp.getPeer().reparent((ContainerPeer)getPeer()); | ||
| 820 | } | ||
| 821 | } | ||
| 822 | |||
| 823 | /** | ||
| 824 | * Adds component to this container. Tries to minimize side effects of this adding - | ||
| 825 | * doesn't call remove notify if it is not required. | ||
| 826 | * @since 1.5 | ||
| 827 | */ | ||
| 828 | private void addDelicately(Component comp, Container curParent, int index) { | ||
| 829 | checkTreeLock(); | ||
| 830 | |||
| 831 | // Check if moving between containers | ||
| 832 | if (curParent != this) { | ||
| 833 | //index == -1 means add to the end. | ||
| 834 | if (index == -1) { | ||
| 835 | component.add(comp); | ||
| 836 | } else { | ||
| 837 | component.add(index, comp); | ||
| 838 | } | ||
| 839 | comp.parent = this; | ||
| 840 | comp.setGraphicsConfiguration(getGraphicsConfiguration()); | ||
| 841 | |||
| 842 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 843 | comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 844 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 845 | comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 846 | adjustDescendants(comp.countHierarchyMembers()); | ||
| 847 | } else { | ||
| 848 | if (index < component.size()) { | ||
| 849 | component.set(index, comp); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | invalidateIfValid(); | ||
| 854 | if (peer != null) { | ||
| 855 | if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one | ||
| 856 | comp.addNotify(); | ||
| 857 | } else { // Both container and child have peers, it means child peer should be reparented. | ||
| 858 | // In both cases we need to reparent native widgets. | ||
| 859 | Container newNativeContainer = getHeavyweightContainer(); | ||
| 860 | Container oldNativeContainer = curParent.getHeavyweightContainer(); | ||
| 861 | if (oldNativeContainer != newNativeContainer) { | ||
| 862 | // Native container changed - need to reparent native widgets | ||
| 863 | newNativeContainer.reparentChild(comp); | ||
| 864 | } | ||
| 865 | comp.updateZOrder(); | ||
| 866 | |||
| 867 | if (!comp.isLightweight() && isLightweight()) { | ||
| 868 | // If component is heavyweight and one of the containers is lightweight | ||
| 869 | // the location of the component should be fixed. | ||
| 870 | comp.relocateComponent(); | ||
| 871 | } | ||
| 872 | } | ||
| 873 | } | ||
| 874 | if (curParent != this) { | ||
| 875 | /* Notify the layout manager of the added component. */ | ||
| 876 | if (layoutMgr != null) { | ||
| 877 | if (layoutMgr instanceof LayoutManager2) { | ||
| 878 | ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null); | ||
| 879 | } else { | ||
| 880 | layoutMgr.addLayoutComponent(null, comp); | ||
| 881 | } | ||
| 882 | } | ||
| 883 | if (containerListener != null || | ||
| 884 | (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 885 | Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { | ||
| 886 | ContainerEvent e = new ContainerEvent(this, | ||
| 887 | ContainerEvent.COMPONENT_ADDED, | ||
| 888 | comp); | ||
| 889 | dispatchEvent(e); | ||
| 890 | } | ||
| 891 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, | ||
| 892 | this, HierarchyEvent.PARENT_CHANGED, | ||
| 893 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 894 | |||
| 895 | // If component is focus owner or parent container of focus owner check that after reparenting | ||
| 896 | // focus owner moved out if new container prohibit this kind of focus owner. | ||
| 897 | if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) { | ||
| 898 | comp.transferFocus(); | ||
| 899 | } else if (comp instanceof Container) { | ||
| 900 | Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); | ||
| 901 | if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) { | ||
| 902 | focusOwner.transferFocus(); | ||
| 903 | } | ||
| 904 | } | ||
| 905 | } else { | ||
| 906 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, | ||
| 907 | this, HierarchyEvent.HIERARCHY_CHANGED, | ||
| 908 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 909 | } | ||
| 910 | |||
| 911 | if (peer != null && layoutMgr == null && isVisible()) { | ||
| 912 | updateCursorImmediately(); | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | /** | ||
| 917 | * Returns the z-order index of the component inside the container. | ||
| 918 | * The higher a component is in the z-order hierarchy, the lower | ||
| 919 | * its index. The component with the lowest z-order index is | ||
| 920 | * painted last, above all other child components. | ||
| 921 | * | ||
| 922 | * @param comp the component being queried | ||
| 923 | * @return the z-order index of the component; otherwise | ||
| 924 | * returns -1 if the component is <code>null</code> | ||
| 925 | * or doesn't belong to the container | ||
| 926 | * @see #setComponentZOrder(java.awt.Component, int) | ||
| 927 | * @since 1.5 | ||
| 928 | */ | ||
| 929 | public int getComponentZOrder(Component comp) { | ||
| 930 | if (comp == null) { | ||
| 931 | return -1; | ||
| 932 | } | ||
| 933 | synchronized(getTreeLock()) { | ||
| 934 | // Quick check - container should be immediate parent of the component | ||
| 935 | if (comp.parent != this) { | ||
| 936 | return -1; | ||
| 937 | } | ||
| 938 | return component.indexOf(comp); | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | /** | ||
| 943 | * Adds the specified component to the end of this container. | ||
| 944 | * Also notifies the layout manager to add the component to | ||
| 945 | * this container's layout using the specified constraints object. | ||
| 946 | * This is a convenience method for {@link #addImpl}. | ||
| 947 | * <p> | ||
| 948 | * This method changes layout-related information, and therefore, | ||
| 949 | * invalidates the component hierarchy. If the container has already been | ||
| 950 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 951 | * display the added component. | ||
| 952 | * | ||
| 953 | * | ||
| 954 | * @param comp the component to be added | ||
| 955 | * @param constraints an object expressing | ||
| 956 | * layout contraints for this component | ||
| 957 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 958 | * @see #addImpl | ||
| 959 | * @see #invalidate | ||
| 960 | * @see #validate | ||
| 961 | * @see javax.swing.JComponent#revalidate() | ||
| 962 | * @see LayoutManager | ||
| 963 | * @since JDK1.1 | ||
| 964 | */ | ||
| 965 | public void add(Component comp, Object constraints) { | ||
| 966 | addImpl(comp, constraints, -1); | ||
| 967 | } | ||
| 968 | |||
| 969 | /** | ||
| 970 | * Adds the specified component to this container with the specified | ||
| 971 | * constraints at the specified index. Also notifies the layout | ||
| 972 | * manager to add the component to the this container's layout using | ||
| 973 | * the specified constraints object. | ||
| 974 | * This is a convenience method for {@link #addImpl}. | ||
| 975 | * <p> | ||
| 976 | * This method changes layout-related information, and therefore, | ||
| 977 | * invalidates the component hierarchy. If the container has already been | ||
| 978 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 979 | * display the added component. | ||
| 980 | * | ||
| 981 | * | ||
| 982 | * @param comp the component to be added | ||
| 983 | * @param constraints an object expressing layout contraints for this | ||
| 984 | * @param index the position in the container's list at which to insert | ||
| 985 | * the component; <code>-1</code> means insert at the end | ||
| 986 | * component | ||
| 987 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 988 | * @exception IllegalArgumentException if {@code index} is invalid (see | ||
| 989 | * {@link #addImpl} for details) | ||
| 990 | * @see #addImpl | ||
| 991 | * @see #invalidate | ||
| 992 | * @see #validate | ||
| 993 | * @see javax.swing.JComponent#revalidate() | ||
| 994 | * @see #remove | ||
| 995 | * @see LayoutManager | ||
| 996 | */ | ||
| 997 | public void add(Component comp, Object constraints, int index) { | ||
| 998 | addImpl(comp, constraints, index); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | /** | ||
| 1002 | * Adds the specified component to this container at the specified | ||
| 1003 | * index. This method also notifies the layout manager to add | ||
| 1004 | * the component to this container's layout using the specified | ||
| 1005 | * constraints object via the <code>addLayoutComponent</code> | ||
| 1006 | * method. | ||
| 1007 | * <p> | ||
| 1008 | * The constraints are | ||
| 1009 | * defined by the particular layout manager being used. For | ||
| 1010 | * example, the <code>BorderLayout</code> class defines five | ||
| 1011 | * constraints: <code>BorderLayout.NORTH</code>, | ||
| 1012 | * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>, | ||
| 1013 | * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>. | ||
| 1014 | * <p> | ||
| 1015 | * The <code>GridBagLayout</code> class requires a | ||
| 1016 | * <code>GridBagConstraints</code> object. Failure to pass | ||
| 1017 | * the correct type of constraints object results in an | ||
| 1018 | * <code>IllegalArgumentException</code>. | ||
| 1019 | * <p> | ||
| 1020 | * If the current layout manager implements {@code LayoutManager2}, then | ||
| 1021 | * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on | ||
| 1022 | * it. If the current layout manager does not implement | ||
| 1023 | * {@code LayoutManager2}, and constraints is a {@code String}, then | ||
| 1024 | * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it. | ||
| 1025 | * <p> | ||
| 1026 | * If the component is not an ancestor of this container and has a non-null | ||
| 1027 | * parent, it is removed from its current parent before it is added to this | ||
| 1028 | * container. | ||
| 1029 | * <p> | ||
| 1030 | * This is the method to override if a program needs to track | ||
| 1031 | * every add request to a container as all other add methods defer | ||
| 1032 | * to this one. An overriding method should | ||
| 1033 | * usually include a call to the superclass's version of the method: | ||
| 1034 | * <p> | ||
| 1035 | * <blockquote> | ||
| 1036 | * <code>super.addImpl(comp, constraints, index)</code> | ||
| 1037 | * </blockquote> | ||
| 1038 | * <p> | ||
| 1039 | * This method changes layout-related information, and therefore, | ||
| 1040 | * invalidates the component hierarchy. If the container has already been | ||
| 1041 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 1042 | * display the added component. | ||
| 1043 | * | ||
| 1044 | * @param comp the component to be added | ||
| 1045 | * @param constraints an object expressing layout constraints | ||
| 1046 | * for this component | ||
| 1047 | * @param index the position in the container's list at which to | ||
| 1048 | * insert the component, where <code>-1</code> | ||
| 1049 | * means append to the end | ||
| 1050 | * @exception IllegalArgumentException if {@code index} is invalid; | ||
| 1051 | * if {@code comp} is a child of this container, the valid | ||
| 1052 | * range is {@code [-1, getComponentCount()-1]}; if component is | ||
| 1053 | * not a child of this container, the valid range is | ||
| 1054 | * {@code [-1, getComponentCount()]} | ||
| 1055 | * | ||
| 1056 | * @exception IllegalArgumentException if {@code comp} is an ancestor of | ||
| 1057 | * this container | ||
| 1058 | * @exception IllegalArgumentException if adding a window to a container | ||
| 1059 | * @exception NullPointerException if {@code comp} is {@code null} | ||
| 1060 | * @see #add(Component) | ||
| 1061 | * @see #add(Component, int) | ||
| 1062 | * @see #add(Component, java.lang.Object) | ||
| 1063 | * @see #invalidate | ||
| 1064 | * @see LayoutManager | ||
| 1065 | * @see LayoutManager2 | ||
| 1066 | * @since JDK1.1 | ||
| 1067 | */ | ||
| 1068 | protected void addImpl(Component comp, Object constraints, int index) { | ||
| 1069 | synchronized (getTreeLock()) { | ||
| 1070 | /* Check for correct arguments: index in bounds, | ||
| 1071 | * comp cannot be one of this container's parents, | ||
| 1072 | * and comp cannot be a window. | ||
| 1073 | * comp and container must be on the same GraphicsDevice. | ||
| 1074 | * if comp is container, all sub-components must be on | ||
| 1075 | * same GraphicsDevice. | ||
| 1076 | */ | ||
| 1077 | GraphicsConfiguration thisGC = this.getGraphicsConfiguration(); | ||
| 1078 | |||
| 1079 | if (index > component.size() || (index < 0 && index != -1)) { | ||
| 1080 | throw new IllegalArgumentException( | ||
| 1081 | "illegal component position"); | ||
| 1082 | } | ||
| 1083 | checkAddToSelf(comp); | ||
| 1084 | checkNotAWindow(comp); | ||
| 1085 | if (thisGC != null) { | ||
| 1086 | comp.checkGD(thisGC.getDevice().getIDstring()); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | /* Reparent the component and tidy up the tree's state. */ | ||
| 1090 | if (comp.parent != null) { | ||
| 1091 | comp.parent.remove(comp); | ||
| 1092 | if (index > component.size()) { | ||
| 1093 | throw new IllegalArgumentException("illegal component position"); | ||
| 1094 | } | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | //index == -1 means add to the end. | ||
| 1098 | if (index == -1) { | ||
| 1099 | component.add(comp); | ||
| 1100 | } else { | ||
| 1101 | component.add(index, comp); | ||
| 1102 | } | ||
| 1103 | comp.parent = this; | ||
| 1104 | comp.setGraphicsConfiguration(thisGC); | ||
| 1105 | |||
| 1106 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 1107 | comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1108 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 1109 | comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 1110 | adjustDescendants(comp.countHierarchyMembers()); | ||
| 1111 | |||
| 1112 | invalidateIfValid(); | ||
| 1113 | if (peer != null) { | ||
| 1114 | comp.addNotify(); | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | /* Notify the layout manager of the added component. */ | ||
| 1118 | if (layoutMgr != null) { | ||
| 1119 | if (layoutMgr instanceof LayoutManager2) { | ||
| 1120 | ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints); | ||
| 1121 | } else if (constraints instanceof String) { | ||
| 1122 | layoutMgr.addLayoutComponent((String)constraints, comp); | ||
| 1123 | } | ||
| 1124 | } | ||
| 1125 | if (containerListener != null || | ||
| 1126 | (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 1127 | Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { | ||
| 1128 | ContainerEvent e = new ContainerEvent(this, | ||
| 1129 | ContainerEvent.COMPONENT_ADDED, | ||
| 1130 | comp); | ||
| 1131 | dispatchEvent(e); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, | ||
| 1135 | this, HierarchyEvent.PARENT_CHANGED, | ||
| 1136 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1137 | if (peer != null && layoutMgr == null && isVisible()) { | ||
| 1138 | updateCursorImmediately(); | ||
| 1139 | } | ||
| 1140 | } | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | @Override | ||
| 1144 | boolean updateGraphicsData(GraphicsConfiguration gc) { | ||
| 1145 | checkTreeLock(); | ||
| 1146 | |||
| 1147 | boolean ret = super.updateGraphicsData(gc); | ||
| 1148 | |||
| 1149 | for (Component comp : component) { | ||
| 1150 | if (comp != null) { | ||
| 1151 | ret |= comp.updateGraphicsData(gc); | ||
| 1152 | } | ||
| 1153 | } | ||
| 1154 | return ret; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | /** | ||
| 1158 | * Checks that all Components that this Container contains are on | ||
| 1159 | * the same GraphicsDevice as this Container. If not, throws an | ||
| 1160 | * IllegalArgumentException. | ||
| 1161 | */ | ||
| 1162 | void checkGD(String stringID) { | ||
| 1163 | for (Component comp : component) { | ||
| 1164 | if (comp != null) { | ||
| 1165 | comp.checkGD(stringID); | ||
| 1166 | } | ||
| 1167 | } | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | /** | ||
| 1171 | * Removes the component, specified by <code>index</code>, | ||
| 1172 | * from this container. | ||
| 1173 | * This method also notifies the layout manager to remove the | ||
| 1174 | * component from this container's layout via the | ||
| 1175 | * <code>removeLayoutComponent</code> method. | ||
| 1176 | * <p> | ||
| 1177 | * This method changes layout-related information, and therefore, | ||
| 1178 | * invalidates the component hierarchy. If the container has already been | ||
| 1179 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 1180 | * reflect the changes. | ||
| 1181 | * | ||
| 1182 | * | ||
| 1183 | * @param index the index of the component to be removed | ||
| 1184 | * @throws ArrayIndexOutOfBoundsException if {@code index} is not in | ||
| 1185 | * range {@code [0, getComponentCount()-1]} | ||
| 1186 | * @see #add | ||
| 1187 | * @see #invalidate | ||
| 1188 | * @see #validate | ||
| 1189 | * @see #getComponentCount | ||
| 1190 | * @since JDK1.1 | ||
| 1191 | */ | ||
| 1192 | public void remove(int index) { | ||
| 1193 | synchronized (getTreeLock()) { | ||
| 1194 | if (index < 0 || index >= component.size()) { | ||
| 1195 | throw new ArrayIndexOutOfBoundsException(index); | ||
| 1196 | } | ||
| 1197 | Component comp = component.get(index); | ||
| 1198 | if (peer != null) { | ||
| 1199 | comp.removeNotify(); | ||
| 1200 | } | ||
| 1201 | if (layoutMgr != null) { | ||
| 1202 | layoutMgr.removeLayoutComponent(comp); | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 1206 | -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1207 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 1208 | -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 1209 | adjustDescendants(-(comp.countHierarchyMembers())); | ||
| 1210 | |||
| 1211 | comp.parent = null; | ||
| 1212 | component.remove(index); | ||
| 1213 | comp.setGraphicsConfiguration(null); | ||
| 1214 | |||
| 1215 | invalidateIfValid(); | ||
| 1216 | if (containerListener != null || | ||
| 1217 | (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 1218 | Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { | ||
| 1219 | ContainerEvent e = new ContainerEvent(this, | ||
| 1220 | ContainerEvent.COMPONENT_REMOVED, | ||
| 1221 | comp); | ||
| 1222 | dispatchEvent(e); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, | ||
| 1226 | this, HierarchyEvent.PARENT_CHANGED, | ||
| 1227 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1228 | if (peer != null && layoutMgr == null && isVisible()) { | ||
| 1229 | updateCursorImmediately(); | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | /** | ||
| 1235 | * Removes the specified component from this container. | ||
| 1236 | * This method also notifies the layout manager to remove the | ||
| 1237 | * component from this container's layout via the | ||
| 1238 | * <code>removeLayoutComponent</code> method. | ||
| 1239 | * <p> | ||
| 1240 | * This method changes layout-related information, and therefore, | ||
| 1241 | * invalidates the component hierarchy. If the container has already been | ||
| 1242 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 1243 | * reflect the changes. | ||
| 1244 | * | ||
| 1245 | * @param comp the component to be removed | ||
| 1246 | * @throws NullPointerException if {@code comp} is {@code null} | ||
| 1247 | * @see #add | ||
| 1248 | * @see #invalidate | ||
| 1249 | * @see #validate | ||
| 1250 | * @see #remove(int) | ||
| 1251 | */ | ||
| 1252 | public void remove(Component comp) { | ||
| 1253 | synchronized (getTreeLock()) { | ||
| 1254 | if (comp.parent == this) { | ||
| 1255 | int index = component.indexOf(comp); | ||
| 1256 | if (index >= 0) { | ||
| 1257 | remove(index); | ||
| 1258 | } | ||
| 1259 | } | ||
| 1260 | } | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | /** | ||
| 1264 | * Removes all the components from this container. | ||
| 1265 | * This method also notifies the layout manager to remove the | ||
| 1266 | * components from this container's layout via the | ||
| 1267 | * <code>removeLayoutComponent</code> method. | ||
| 1268 | * <p> | ||
| 1269 | * This method changes layout-related information, and therefore, | ||
| 1270 | * invalidates the component hierarchy. If the container has already been | ||
| 1271 | * displayed, the hierarchy must be validated thereafter in order to | ||
| 1272 | * reflect the changes. | ||
| 1273 | * | ||
| 1274 | * @see #add | ||
| 1275 | * @see #remove | ||
| 1276 | * @see #invalidate | ||
| 1277 | */ | ||
| 1278 | public void removeAll() { | ||
| 1279 | synchronized (getTreeLock()) { | ||
| 1280 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 1281 | -listeningChildren); | ||
| 1282 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 1283 | -listeningBoundsChildren); | ||
| 1284 | adjustDescendants(-descendantsCount); | ||
| 1285 | |||
| 1286 | while (!component.isEmpty()) { | ||
| 1287 | Component comp = component.remove(component.size()-1); | ||
| 1288 | |||
| 1289 | if (peer != null) { | ||
| 1290 | comp.removeNotify(); | ||
| 1291 | } | ||
| 1292 | if (layoutMgr != null) { | ||
| 1293 | layoutMgr.removeLayoutComponent(comp); | ||
| 1294 | } | ||
| 1295 | comp.parent = null; | ||
| 1296 | comp.setGraphicsConfiguration(null); | ||
| 1297 | if (containerListener != null || | ||
| 1298 | (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 1299 | Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { | ||
| 1300 | ContainerEvent e = new ContainerEvent(this, | ||
| 1301 | ContainerEvent.COMPONENT_REMOVED, | ||
| 1302 | comp); | ||
| 1303 | dispatchEvent(e); | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, | ||
| 1307 | comp, this, | ||
| 1308 | HierarchyEvent.PARENT_CHANGED, | ||
| 1309 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 1310 | } | ||
| 1311 | if (peer != null && layoutMgr == null && isVisible()) { | ||
| 1312 | updateCursorImmediately(); | ||
| 1313 | } | ||
| 1314 | invalidateIfValid(); | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | // Should only be called while holding tree lock | ||
| 1319 | int numListening(long mask) { | ||
| 1320 | int superListening = super.numListening(mask); | ||
| 1321 | |||
| 1322 | if (mask == AWTEvent.HIERARCHY_EVENT_MASK) { | ||
| 1323 | if (eventLog.isLoggable(PlatformLogger.FINE)) { | ||
| 1324 | // Verify listeningChildren is correct | ||
| 1325 | int sum = 0; | ||
| 1326 | for (Component comp : component) { | ||
| 1327 | sum += comp.numListening(mask); | ||
| 1328 | } | ||
| 1329 | if (listeningChildren != sum) { | ||
| 1330 | eventLog.fine("Assertion (listeningChildren == sum) failed"); | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | return listeningChildren + superListening; | ||
| 1334 | } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) { | ||
| 1335 | if (eventLog.isLoggable(PlatformLogger.FINE)) { | ||
| 1336 | // Verify listeningBoundsChildren is correct | ||
| 1337 | int sum = 0; | ||
| 1338 | for (Component comp : component) { | ||
| 1339 | sum += comp.numListening(mask); | ||
| 1340 | } | ||
| 1341 | if (listeningBoundsChildren != sum) { | ||
| 1342 | eventLog.fine("Assertion (listeningBoundsChildren == sum) failed"); | ||
| 1343 | } | ||
| 1344 | } | ||
| 1345 | return listeningBoundsChildren + superListening; | ||
| 1346 | } else { | ||
| 1347 | // assert false; | ||
| 1348 | if (eventLog.isLoggable(PlatformLogger.FINE)) { | ||
| 1349 | eventLog.fine("This code must never be reached"); | ||
| 1350 | } | ||
| 1351 | return superListening; | ||
| 1352 | } | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | // Should only be called while holding tree lock | ||
| 1356 | void adjustListeningChildren(long mask, int num) { | ||
| 1357 | if (eventLog.isLoggable(PlatformLogger.FINE)) { | ||
| 1358 | boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK || | ||
| 1359 | mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK || | ||
| 1360 | mask == (AWTEvent.HIERARCHY_EVENT_MASK | | ||
| 1361 | AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 1362 | if (!toAssert) { | ||
| 1363 | eventLog.fine("Assertion failed"); | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | if (num == 0) | ||
| 1368 | return; | ||
| 1369 | |||
| 1370 | if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) { | ||
| 1371 | listeningChildren += num; | ||
| 1372 | } | ||
| 1373 | if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) { | ||
| 1374 | listeningBoundsChildren += num; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | adjustListeningChildrenOnParent(mask, num); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | // Should only be called while holding tree lock | ||
| 1381 | void adjustDescendants(int num) { | ||
| 1382 | if (num == 0) | ||
| 1383 | return; | ||
| 1384 | |||
| 1385 | descendantsCount += num; | ||
| 1386 | adjustDecendantsOnParent(num); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | // Should only be called while holding tree lock | ||
| 1390 | void adjustDecendantsOnParent(int num) { | ||
| 1391 | if (parent != null) { | ||
| 1392 | parent.adjustDescendants(num); | ||
| 1393 | } | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | // Should only be called while holding tree lock | ||
| 1397 | int countHierarchyMembers() { | ||
| 1398 | if (log.isLoggable(PlatformLogger.FINE)) { | ||
| 1399 | // Verify descendantsCount is correct | ||
| 1400 | int sum = 0; | ||
| 1401 | for (Component comp : component) { | ||
| 1402 | sum += comp.countHierarchyMembers(); | ||
| 1403 | } | ||
| 1404 | if (descendantsCount != sum) { | ||
| 1405 | log.fine("Assertion (descendantsCount == sum) failed"); | ||
| 1406 | } | ||
| 1407 | } | ||
| 1408 | return descendantsCount + 1; | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | private int getListenersCount(int id, boolean enabledOnToolkit) { | ||
| 1412 | checkTreeLock(); | ||
| 1413 | if (enabledOnToolkit) { | ||
| 1414 | return descendantsCount; | ||
| 1415 | } | ||
| 1416 | switch (id) { | ||
| 1417 | case HierarchyEvent.HIERARCHY_CHANGED: | ||
| 1418 | return listeningChildren; | ||
| 1419 | case HierarchyEvent.ANCESTOR_MOVED: | ||
| 1420 | case HierarchyEvent.ANCESTOR_RESIZED: | ||
| 1421 | return listeningBoundsChildren; | ||
| 1422 | default: | ||
| 1423 | return 0; | ||
| 1424 | } | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | final int createHierarchyEvents(int id, Component changed, | ||
| 1428 | Container changedParent, long changeFlags, boolean enabledOnToolkit) | ||
| 1429 | { | ||
| 1430 | checkTreeLock(); | ||
| 1431 | int listeners = getListenersCount(id, enabledOnToolkit); | ||
| 1432 | |||
| 1433 | for (int count = listeners, i = 0; count > 0; i++) { | ||
| 1434 | count -= component.get(i).createHierarchyEvents(id, changed, | ||
| 1435 | changedParent, changeFlags, enabledOnToolkit); | ||
| 1436 | } | ||
| 1437 | return listeners + | ||
| 1438 | super.createHierarchyEvents(id, changed, changedParent, | ||
| 1439 | changeFlags, enabledOnToolkit); | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | final void createChildHierarchyEvents(int id, long changeFlags, | ||
| 1443 | boolean enabledOnToolkit) | ||
| 1444 | { | ||
| 1445 | checkTreeLock(); | ||
| 1446 | if (component.isEmpty()) { | ||
| 1447 | return; | ||
| 1448 | } | ||
| 1449 | int listeners = getListenersCount(id, enabledOnToolkit); | ||
| 1450 | |||
| 1451 | for (int count = listeners, i = 0; count > 0; i++) { | ||
| 1452 | count -= component.get(i).createHierarchyEvents(id, this, parent, | ||
| 1453 | changeFlags, enabledOnToolkit); | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | /** | ||
| 1458 | * Gets the layout manager for this container. | ||
| 1459 | * @see #doLayout | ||
| 1460 | * @see #setLayout | ||
| 1461 | */ | ||
| 1462 | public LayoutManager getLayout() { | ||
| 1463 | return layoutMgr; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | /** | ||
| 1467 | * Sets the layout manager for this container. | ||
| 1468 | * <p> | ||
| 1469 | * This method changes layout-related information, and therefore, | ||
| 1470 | * invalidates the component hierarchy. | ||
| 1471 | * | ||
| 1472 | * @param mgr the specified layout manager | ||
| 1473 | * @see #doLayout | ||
| 1474 | * @see #getLayout | ||
| 1475 | * @see #invalidate | ||
| 1476 | */ | ||
| 1477 | public void setLayout(LayoutManager mgr) { | ||
| 1478 | layoutMgr = mgr; | ||
| 1479 | invalidateIfValid(); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | /** | ||
| 1483 | * Causes this container to lay out its components. Most programs | ||
| 1484 | * should not call this method directly, but should invoke | ||
| 1485 | * the <code>validate</code> method instead. | ||
| 1486 | * @see LayoutManager#layoutContainer | ||
| 1487 | * @see #setLayout | ||
| 1488 | * @see #validate | ||
| 1489 | * @since JDK1.1 | ||
| 1490 | */ | ||
| 1491 | public void doLayout() { | ||
| 1492 | layout(); | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | /** | ||
| 1496 | * @deprecated As of JDK version 1.1, | ||
| 1497 | * replaced by <code>doLayout()</code>. | ||
| 1498 | */ | ||
| 1499 | @Deprecated | ||
| 1500 | public void layout() { | ||
| 1501 | LayoutManager layoutMgr = this.layoutMgr; | ||
| 1502 | if (layoutMgr != null) { | ||
| 1503 | layoutMgr.layoutContainer(this); | ||
| 1504 | } | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | /** | ||
| 1508 | * Indicates if this container is a <i>validate root</i>. | ||
| 1509 | * <p> | ||
| 1510 | * Layout-related changes, such as bounds of the validate root descendants, | ||
| 1511 | * do not affect the layout of the validate root parent. This peculiarity | ||
| 1512 | * enables the {@code invalidate()} method to stop invalidating the | ||
| 1513 | * component hierarchy when the method encounters a validate root. However, | ||
| 1514 | * to preserve backward compatibility this new optimized behavior is | ||
| 1515 | * enabled only when the {@code java.awt.smartInvalidate} system property | ||
| 1516 | * value is set to {@code true}. | ||
| 1517 | * <p> | ||
| 1518 | * If a component hierarchy contains validate roots and the new optimized | ||
| 1519 | * {@code invalidate()} behavior is enabled, the {@code validate()} method | ||
| 1520 | * must be invoked on the validate root of a previously invalidated | ||
| 1521 | * component to restore the validity of the hierarchy later. Otherwise, | ||
| 1522 | * calling the {@code validate()} method on the top-level container (such | ||
| 1523 | * as a {@code Frame} object) should be used to restore the validity of the | ||
| 1524 | * component hierarchy. | ||
| 1525 | * <p> | ||
| 1526 | * The {@code Window} class and the {@code Applet} class are the validate | ||
| 1527 | * roots in AWT. Swing introduces more validate roots. | ||
| 1528 | * | ||
| 1529 | * @return whether this container is a validate root | ||
| 1530 | * @see #invalidate | ||
| 1531 | * @see java.awt.Component#invalidate | ||
| 1532 | * @see javax.swing.JComponent#isValidateRoot | ||
| 1533 | * @see javax.swing.JComponent#revalidate | ||
| 1534 | * @since 1.7 | ||
| 1535 | */ | ||
| 1536 | public boolean isValidateRoot() { | ||
| 1537 | return false; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | private static final boolean isJavaAwtSmartInvalidate; | ||
| 1541 | static { | ||
| 1542 | // Don't lazy-read because every app uses invalidate() | ||
| 1543 | isJavaAwtSmartInvalidate = AccessController.doPrivileged( | ||
| 1544 | new GetBooleanAction("java.awt.smartInvalidate")); | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | /** | ||
| 1548 | * Invalidates the parent of the container unless the container | ||
| 1549 | * is a validate root. | ||
| 1550 | */ | ||
| 1551 | @Override | ||
| 1552 | void invalidateParent() { | ||
| 1553 | if (!isJavaAwtSmartInvalidate || !isValidateRoot()) { | ||
| 1554 | super.invalidateParent(); | ||
| 1555 | } | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | /** | ||
| 1559 | * Invalidates the container. | ||
| 1560 | * <p> | ||
| 1561 | * If the {@code LayoutManager} installed on this container is an instance | ||
| 1562 | * of the {@code LayoutManager2} interface, then | ||
| 1563 | * the {@link LayoutManager2#invalidateLayout(Container)} method is invoked | ||
| 1564 | * on it supplying this {@code Container} as the argument. | ||
| 1565 | * <p> | ||
| 1566 | * Afterwards this method marks this container invalid, and invalidates its | ||
| 1567 | * ancestors. See the {@link Component#invalidate} method for more details. | ||
| 1568 | * | ||
| 1569 | * @see #validate | ||
| 1570 | * @see #layout | ||
| 1571 | * @see LayoutManager2 | ||
| 1572 | */ | ||
| 1573 | @Override | ||
| 1574 | public void invalidate() { | ||
| 1575 | LayoutManager layoutMgr = this.layoutMgr; | ||
| 1576 | if (layoutMgr instanceof LayoutManager2) { | ||
| 1577 | LayoutManager2 lm = (LayoutManager2) layoutMgr; | ||
| 1578 | lm.invalidateLayout(this); | ||
| 1579 | } | ||
| 1580 | super.invalidate(); | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | /** | ||
| 1584 | * Validates this container and all of its subcomponents. | ||
| 1585 | * <p> | ||
| 1586 | * Validating a container means laying out its subcomponents. | ||
| 1587 | * Layout-related changes, such as setting the bounds of a component, or | ||
| 1588 | * adding a component to the container, invalidate the container | ||
| 1589 | * automatically. Note that the ancestors of the container may be | ||
| 1590 | * invalidated also (see {@link Component#invalidate} for details.) | ||
| 1591 | * Therefore, to restore the validity of the hierarchy, the {@code | ||
| 1592 | * validate()} method should be invoked on the top-most invalid | ||
| 1593 | * container of the hierarchy. | ||
| 1594 | * <p> | ||
| 1595 | * Validating the container may be a quite time-consuming operation. For | ||
| 1596 | * performance reasons a developer may postpone the validation of the | ||
| 1597 | * hierarchy till a set of layout-related operations completes, e.g. after | ||
| 1598 | * adding all the children to the container. | ||
| 1599 | * <p> | ||
| 1600 | * If this {@code Container} is not valid, this method invokes | ||
| 1601 | * the {@code validateTree} method and marks this {@code Container} | ||
| 1602 | * as valid. Otherwise, no action is performed. | ||
| 1603 | * | ||
| 1604 | * @see #add(java.awt.Component) | ||
| 1605 | * @see #invalidate | ||
| 1606 | * @see Container#isValidateRoot | ||
| 1607 | * @see javax.swing.JComponent#revalidate() | ||
| 1608 | * @see #validateTree | ||
| 1609 | */ | ||
| 1610 | public void validate() { | ||
| 1611 | boolean updateCur = false; | ||
| 1612 | synchronized (getTreeLock()) { | ||
| 1613 | if ((!isValid() || descendUnconditionallyWhenValidating) | ||
| 1614 | && peer != null) | ||
| 1615 | { | ||
| 1616 | ContainerPeer p = null; | ||
| 1617 | if (peer instanceof ContainerPeer) { | ||
| 1618 | p = (ContainerPeer) peer; | ||
| 1619 | } | ||
| 1620 | if (p != null) { | ||
| 1621 | p.beginValidate(); | ||
| 1622 | } | ||
| 1623 | validateTree(); | ||
| 1624 | if (p != null) { | ||
| 1625 | p.endValidate(); | ||
| 1626 | // Avoid updating cursor if this is an internal call. | ||
| 1627 | // See validateUnconditionally() for details. | ||
| 1628 | if (!descendUnconditionallyWhenValidating) { | ||
| 1629 | updateCur = isVisible(); | ||
| 1630 | } | ||
| 1631 | } | ||
| 1632 | } | ||
| 1633 | } | ||
| 1634 | if (updateCur) { | ||
| 1635 | updateCursorImmediately(); | ||
| 1636 | } | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | /** | ||
| 1640 | * Indicates whether valid containers should also traverse their | ||
| 1641 | * children and call the validateTree() method on them. | ||
| 1642 | * | ||
| 1643 | * Synchronization: TreeLock. | ||
| 1644 | * | ||
| 1645 | * The field is allowed to be static as long as the TreeLock itself is | ||
| 1646 | * static. | ||
| 1647 | * | ||
| 1648 | * @see #validateUnconditionally() | ||
| 1649 | */ | ||
| 1650 | private static boolean descendUnconditionallyWhenValidating = false; | ||
| 1651 | |||
| 1652 | /** | ||
| 1653 | * Unconditionally validate the component hierarchy. | ||
| 1654 | */ | ||
| 1655 | final void validateUnconditionally() { | ||
| 1656 | boolean updateCur = false; | ||
| 1657 | synchronized (getTreeLock()) { | ||
| 1658 | descendUnconditionallyWhenValidating = true; | ||
| 1659 | |||
| 1660 | validate(); | ||
| 1661 | if (peer instanceof ContainerPeer) { | ||
| 1662 | updateCur = isVisible(); | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | descendUnconditionallyWhenValidating = false; | ||
| 1666 | } | ||
| 1667 | if (updateCur) { | ||
| 1668 | updateCursorImmediately(); | ||
| 1669 | } | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | /** | ||
| 1673 | * Recursively descends the container tree and recomputes the | ||
| 1674 | * layout for any subtrees marked as needing it (those marked as | ||
| 1675 | * invalid). Synchronization should be provided by the method | ||
| 1676 | * that calls this one: <code>validate</code>. | ||
| 1677 | * | ||
| 1678 | * @see #doLayout | ||
| 1679 | * @see #validate | ||
| 1680 | */ | ||
| 1681 | protected void validateTree() { | ||
| 1682 | checkTreeLock(); | ||
| 1683 | if (!isValid() || descendUnconditionallyWhenValidating) { | ||
| 1684 | if (peer instanceof ContainerPeer) { | ||
| 1685 | ((ContainerPeer)peer).beginLayout(); | ||
| 1686 | } | ||
| 1687 | if (!isValid()) { | ||
| 1688 | doLayout(); | ||
| 1689 | } | ||
| 1690 | for (int i = 0; i < component.size(); i++) { | ||
| 1691 | Component comp = component.get(i); | ||
| 1692 | if ( (comp instanceof Container) | ||
| 1693 | && !(comp instanceof Window) | ||
| 1694 | && (!comp.isValid() || | ||
| 1695 | descendUnconditionallyWhenValidating)) | ||
| 1696 | { | ||
| 1697 | ((Container)comp).validateTree(); | ||
| 1698 | } else { | ||
| 1699 | comp.validate(); | ||
| 1700 | } | ||
| 1701 | } | ||
| 1702 | if (peer instanceof ContainerPeer) { | ||
| 1703 | ((ContainerPeer)peer).endLayout(); | ||
| 1704 | } | ||
| 1705 | } | ||
| 1706 | super.validate(); | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | /** | ||
| 1710 | * Recursively descends the container tree and invalidates all | ||
| 1711 | * contained components. | ||
| 1712 | */ | ||
| 1713 | void invalidateTree() { | ||
| 1714 | synchronized (getTreeLock()) { | ||
| 1715 | for (int i = 0; i < component.size(); i++) { | ||
| 1716 | Component comp = component.get(i); | ||
| 1717 | if (comp instanceof Container) { | ||
| 1718 | ((Container)comp).invalidateTree(); | ||
| 1719 | } | ||
| 1720 | else { | ||
| 1721 | comp.invalidateIfValid(); | ||
| 1722 | } | ||
| 1723 | } | ||
| 1724 | invalidateIfValid(); | ||
| 1725 | } | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | /** | ||
| 1729 | * Sets the font of this container. | ||
| 1730 | * <p> | ||
| 1731 | * This method changes layout-related information, and therefore, | ||
| 1732 | * invalidates the component hierarchy. | ||
| 1733 | * | ||
| 1734 | * @param f The font to become this container's font. | ||
| 1735 | * @see Component#getFont | ||
| 1736 | * @see #invalidate | ||
| 1737 | * @since JDK1.0 | ||
| 1738 | */ | ||
| 1739 | public void setFont(Font f) { | ||
| 1740 | boolean shouldinvalidate = false; | ||
| 1741 | |||
| 1742 | Font oldfont = getFont(); | ||
| 1743 | super.setFont(f); | ||
| 1744 | Font newfont = getFont(); | ||
| 1745 | if (newfont != oldfont && (oldfont == null || | ||
| 1746 | !oldfont.equals(newfont))) { | ||
| 1747 | invalidateTree(); | ||
| 1748 | } | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | /** | ||
| 1752 | * Returns the preferred size of this container. If the preferred size has | ||
| 1753 | * not been set explicitly by {@link Component#setPreferredSize(Dimension)} | ||
| 1754 | * and this {@code Container} has a {@code non-null} {@link LayoutManager}, | ||
| 1755 | * then {@link LayoutManager#preferredLayoutSize(Container)} | ||
| 1756 | * is used to calculate the preferred size. | ||
| 1757 | * | ||
| 1758 | * <p>Note: some implementations may cache the value returned from the | ||
| 1759 | * {@code LayoutManager}. Implementations that cache need not invoke | ||
| 1760 | * {@code preferredLayoutSize} on the {@code LayoutManager} every time | ||
| 1761 | * this method is invoked, rather the {@code LayoutManager} will only | ||
| 1762 | * be queried after the {@code Container} becomes invalid. | ||
| 1763 | * | ||
| 1764 | * @return an instance of <code>Dimension</code> that represents | ||
| 1765 | * the preferred size of this container. | ||
| 1766 | * @see #getMinimumSize | ||
| 1767 | * @see #getMaximumSize | ||
| 1768 | * @see #getLayout | ||
| 1769 | * @see LayoutManager#preferredLayoutSize(Container) | ||
| 1770 | * @see Component#getPreferredSize | ||
| 1771 | */ | ||
| 1772 | public Dimension getPreferredSize() { | ||
| 1773 | return preferredSize(); | ||
| 1774 | } | ||
| 1775 | |||
| 1776 | /** | ||
| 1777 | * @deprecated As of JDK version 1.1, | ||
| 1778 | * replaced by <code>getPreferredSize()</code>. | ||
| 1779 | */ | ||
| 1780 | @Deprecated | ||
| 1781 | public Dimension preferredSize() { | ||
| 1782 | /* Avoid grabbing the lock if a reasonable cached size value | ||
| 1783 | * is available. | ||
| 1784 | */ | ||
| 1785 | Dimension dim = prefSize; | ||
| 1786 | if (dim == null || !(isPreferredSizeSet() || isValid())) { | ||
| 1787 | synchronized (getTreeLock()) { | ||
| 1788 | prefSize = (layoutMgr != null) ? | ||
| 1789 | layoutMgr.preferredLayoutSize(this) : | ||
| 1790 | super.preferredSize(); | ||
| 1791 | dim = prefSize; | ||
| 1792 | } | ||
| 1793 | } | ||
| 1794 | if (dim != null){ | ||
| 1795 | return new Dimension(dim); | ||
| 1796 | } | ||
| 1797 | else{ | ||
| 1798 | return dim; | ||
| 1799 | } | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | /** | ||
| 1803 | * Returns the minimum size of this container. If the minimum size has | ||
| 1804 | * not been set explicitly by {@link Component#setMinimumSize(Dimension)} | ||
| 1805 | * and this {@code Container} has a {@code non-null} {@link LayoutManager}, | ||
| 1806 | * then {@link LayoutManager#minimumLayoutSize(Container)} | ||
| 1807 | * is used to calculate the minimum size. | ||
| 1808 | * | ||
| 1809 | * <p>Note: some implementations may cache the value returned from the | ||
| 1810 | * {@code LayoutManager}. Implementations that cache need not invoke | ||
| 1811 | * {@code minimumLayoutSize} on the {@code LayoutManager} every time | ||
| 1812 | * this method is invoked, rather the {@code LayoutManager} will only | ||
| 1813 | * be queried after the {@code Container} becomes invalid. | ||
| 1814 | * | ||
| 1815 | * @return an instance of <code>Dimension</code> that represents | ||
| 1816 | * the minimum size of this container. | ||
| 1817 | * @see #getPreferredSize | ||
| 1818 | * @see #getMaximumSize | ||
| 1819 | * @see #getLayout | ||
| 1820 | * @see LayoutManager#minimumLayoutSize(Container) | ||
| 1821 | * @see Component#getMinimumSize | ||
| 1822 | * @since JDK1.1 | ||
| 1823 | */ | ||
| 1824 | public Dimension getMinimumSize() { | ||
| 1825 | return minimumSize(); | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | /** | ||
| 1829 | * @deprecated As of JDK version 1.1, | ||
| 1830 | * replaced by <code>getMinimumSize()</code>. | ||
| 1831 | */ | ||
| 1832 | @Deprecated | ||
| 1833 | public Dimension minimumSize() { | ||
| 1834 | /* Avoid grabbing the lock if a reasonable cached size value | ||
| 1835 | * is available. | ||
| 1836 | */ | ||
| 1837 | Dimension dim = minSize; | ||
| 1838 | if (dim == null || !(isMinimumSizeSet() || isValid())) { | ||
| 1839 | synchronized (getTreeLock()) { | ||
| 1840 | minSize = (layoutMgr != null) ? | ||
| 1841 | layoutMgr.minimumLayoutSize(this) : | ||
| 1842 | super.minimumSize(); | ||
| 1843 | dim = minSize; | ||
| 1844 | } | ||
| 1845 | } | ||
| 1846 | if (dim != null){ | ||
| 1847 | return new Dimension(dim); | ||
| 1848 | } | ||
| 1849 | else{ | ||
| 1850 | return dim; | ||
| 1851 | } | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | /** | ||
| 1855 | * Returns the maximum size of this container. If the maximum size has | ||
| 1856 | * not been set explicitly by {@link Component#setMaximumSize(Dimension)} | ||
| 1857 | * and the {@link LayoutManager} installed on this {@code Container} | ||
| 1858 | * is an instance of {@link LayoutManager2}, then | ||
| 1859 | * {@link LayoutManager2#maximumLayoutSize(Container)} | ||
| 1860 | * is used to calculate the maximum size. | ||
| 1861 | * | ||
| 1862 | * <p>Note: some implementations may cache the value returned from the | ||
| 1863 | * {@code LayoutManager2}. Implementations that cache need not invoke | ||
| 1864 | * {@code maximumLayoutSize} on the {@code LayoutManager2} every time | ||
| 1865 | * this method is invoked, rather the {@code LayoutManager2} will only | ||
| 1866 | * be queried after the {@code Container} becomes invalid. | ||
| 1867 | * | ||
| 1868 | * @return an instance of <code>Dimension</code> that represents | ||
| 1869 | * the maximum size of this container. | ||
| 1870 | * @see #getPreferredSize | ||
| 1871 | * @see #getMinimumSize | ||
| 1872 | * @see #getLayout | ||
| 1873 | * @see LayoutManager2#maximumLayoutSize(Container) | ||
| 1874 | * @see Component#getMaximumSize | ||
| 1875 | */ | ||
| 1876 | public Dimension getMaximumSize() { | ||
| 1877 | /* Avoid grabbing the lock if a reasonable cached size value | ||
| 1878 | * is available. | ||
| 1879 | */ | ||
| 1880 | Dimension dim = maxSize; | ||
| 1881 | if (dim == null || !(isMaximumSizeSet() || isValid())) { | ||
| 1882 | synchronized (getTreeLock()) { | ||
| 1883 | if (layoutMgr instanceof LayoutManager2) { | ||
| 1884 | LayoutManager2 lm = (LayoutManager2) layoutMgr; | ||
| 1885 | maxSize = lm.maximumLayoutSize(this); | ||
| 1886 | } else { | ||
| 1887 | maxSize = super.getMaximumSize(); | ||
| 1888 | } | ||
| 1889 | dim = maxSize; | ||
| 1890 | } | ||
| 1891 | } | ||
| 1892 | if (dim != null){ | ||
| 1893 | return new Dimension(dim); | ||
| 1894 | } | ||
| 1895 | else{ | ||
| 1896 | return dim; | ||
| 1897 | } | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | /** | ||
| 1901 | * Returns the alignment along the x axis. This specifies how | ||
| 1902 | * the component would like to be aligned relative to other | ||
| 1903 | * components. The value should be a number between 0 and 1 | ||
| 1904 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 1905 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 1906 | */ | ||
| 1907 | public float getAlignmentX() { | ||
| 1908 | float xAlign; | ||
| 1909 | if (layoutMgr instanceof LayoutManager2) { | ||
| 1910 | synchronized (getTreeLock()) { | ||
| 1911 | LayoutManager2 lm = (LayoutManager2) layoutMgr; | ||
| 1912 | xAlign = lm.getLayoutAlignmentX(this); | ||
| 1913 | } | ||
| 1914 | } else { | ||
| 1915 | xAlign = super.getAlignmentX(); | ||
| 1916 | } | ||
| 1917 | return xAlign; | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | /** | ||
| 1921 | * Returns the alignment along the y axis. This specifies how | ||
| 1922 | * the component would like to be aligned relative to other | ||
| 1923 | * components. The value should be a number between 0 and 1 | ||
| 1924 | * where 0 represents alignment along the origin, 1 is aligned | ||
| 1925 | * the furthest away from the origin, 0.5 is centered, etc. | ||
| 1926 | */ | ||
| 1927 | public float getAlignmentY() { | ||
| 1928 | float yAlign; | ||
| 1929 | if (layoutMgr instanceof LayoutManager2) { | ||
| 1930 | synchronized (getTreeLock()) { | ||
| 1931 | LayoutManager2 lm = (LayoutManager2) layoutMgr; | ||
| 1932 | yAlign = lm.getLayoutAlignmentY(this); | ||
| 1933 | } | ||
| 1934 | } else { | ||
| 1935 | yAlign = super.getAlignmentY(); | ||
| 1936 | } | ||
| 1937 | return yAlign; | ||
| 1938 | } | ||
| 1939 | |||
| 1940 | /** | ||
| 1941 | * Paints the container. This forwards the paint to any lightweight | ||
| 1942 | * components that are children of this container. If this method is | ||
| 1943 | * reimplemented, super.paint(g) should be called so that lightweight | ||
| 1944 | * components are properly rendered. If a child component is entirely | ||
| 1945 | * clipped by the current clipping setting in g, paint() will not be | ||
| 1946 | * forwarded to that child. | ||
| 1947 | * | ||
| 1948 | * @param g the specified Graphics window | ||
| 1949 | * @see Component#update(Graphics) | ||
| 1950 | */ | ||
| 1951 | public void paint(Graphics g) { | ||
| 1952 | if (isShowing()) { | ||
| 1953 | synchronized (this) { | ||
| 1954 | if (printing) { | ||
| 1955 | if (printingThreads.contains(Thread.currentThread())) { | ||
| 1956 | return; | ||
| 1957 | } | ||
| 1958 | } | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | // The container is showing on screen and | ||
| 1962 | // this paint() is not called from print(). | ||
| 1963 | // Paint self and forward the paint to lightweight subcomponents. | ||
| 1964 | |||
| 1965 | // super.paint(); -- Don't bother, since it's a NOP. | ||
| 1966 | |||
| 1967 | GraphicsCallback.PaintCallback.getInstance(). | ||
| 1968 | runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS); | ||
| 1969 | } | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | /** | ||
| 1973 | * Updates the container. This forwards the update to any lightweight | ||
| 1974 | * components that are children of this container. If this method is | ||
| 1975 | * reimplemented, super.update(g) should be called so that lightweight | ||
| 1976 | * components are properly rendered. If a child component is entirely | ||
| 1977 | * clipped by the current clipping setting in g, update() will not be | ||
| 1978 | * forwarded to that child. | ||
| 1979 | * | ||
| 1980 | * @param g the specified Graphics window | ||
| 1981 | * @see Component#update(Graphics) | ||
| 1982 | */ | ||
| 1983 | public void update(Graphics g) { | ||
| 1984 | if (isShowing()) { | ||
| 1985 | if (! (peer instanceof LightweightPeer)) { | ||
| 1986 | g.clearRect(0, 0, width, height); | ||
| 1987 | } | ||
| 1988 | paint(g); | ||
| 1989 | } | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | /** | ||
| 1993 | * Prints the container. This forwards the print to any lightweight | ||
| 1994 | * components that are children of this container. If this method is | ||
| 1995 | * reimplemented, super.print(g) should be called so that lightweight | ||
| 1996 | * components are properly rendered. If a child component is entirely | ||
| 1997 | * clipped by the current clipping setting in g, print() will not be | ||
| 1998 | * forwarded to that child. | ||
| 1999 | * | ||
| 2000 | * @param g the specified Graphics window | ||
| 2001 | * @see Component#update(Graphics) | ||
| 2002 | */ | ||
| 2003 | public void print(Graphics g) { | ||
| 2004 | if (isShowing()) { | ||
| 2005 | Thread t = Thread.currentThread(); | ||
| 2006 | try { | ||
| 2007 | synchronized (this) { | ||
| 2008 | if (printingThreads == null) { | ||
| 2009 | printingThreads = new HashSet(); | ||
| 2010 | } | ||
| 2011 | printingThreads.add(t); | ||
| 2012 | printing = true; | ||
| 2013 | } | ||
| 2014 | super.print(g); // By default, Component.print() calls paint() | ||
| 2015 | } finally { | ||
| 2016 | synchronized (this) { | ||
| 2017 | printingThreads.remove(t); | ||
| 2018 | printing = !printingThreads.isEmpty(); | ||
| 2019 | } | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | GraphicsCallback.PrintCallback.getInstance(). | ||
| 2023 | runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS); | ||
| 2024 | } | ||
| 2025 | } | ||
| 2026 | |||
| 2027 | /** | ||
| 2028 | * Paints each of the components in this container. | ||
| 2029 | * @param g the graphics context. | ||
| 2030 | * @see Component#paint | ||
| 2031 | * @see Component#paintAll | ||
| 2032 | */ | ||
| 2033 | public void paintComponents(Graphics g) { | ||
| 2034 | if (isShowing()) { | ||
| 2035 | GraphicsCallback.PaintAllCallback.getInstance(). | ||
| 2036 | runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES); | ||
| 2037 | } | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | /** | ||
| 2041 | * Simulates the peer callbacks into java.awt for printing of | ||
| 2042 | * lightweight Containers. | ||
| 2043 | * @param g the graphics context to use for printing. | ||
| 2044 | * @see Component#printAll | ||
| 2045 | * @see #printComponents | ||
| 2046 | */ | ||
| 2047 | void lightweightPaint(Graphics g) { | ||
| 2048 | super.lightweightPaint(g); | ||
| 2049 | paintHeavyweightComponents(g); | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | /** | ||
| 2053 | * Prints all the heavyweight subcomponents. | ||
| 2054 | */ | ||
| 2055 | void paintHeavyweightComponents(Graphics g) { | ||
| 2056 | if (isShowing()) { | ||
| 2057 | GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance(). | ||
| 2058 | runComponents(getComponentsSync(), g, | ||
| 2059 | GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS); | ||
| 2060 | } | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | /** | ||
| 2064 | * Prints each of the components in this container. | ||
| 2065 | * @param g the graphics context. | ||
| 2066 | * @see Component#print | ||
| 2067 | * @see Component#printAll | ||
| 2068 | */ | ||
| 2069 | public void printComponents(Graphics g) { | ||
| 2070 | if (isShowing()) { | ||
| 2071 | GraphicsCallback.PrintAllCallback.getInstance(). | ||
| 2072 | runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES); | ||
| 2073 | } | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | /** | ||
| 2077 | * Simulates the peer callbacks into java.awt for printing of | ||
| 2078 | * lightweight Containers. | ||
| 2079 | * @param g the graphics context to use for printing. | ||
| 2080 | * @see Component#printAll | ||
| 2081 | * @see #printComponents | ||
| 2082 | */ | ||
| 2083 | void lightweightPrint(Graphics g) { | ||
| 2084 | super.lightweightPrint(g); | ||
| 2085 | printHeavyweightComponents(g); | ||
| 2086 | } | ||
| 2087 | |||
| 2088 | /** | ||
| 2089 | * Prints all the heavyweight subcomponents. | ||
| 2090 | */ | ||
| 2091 | void printHeavyweightComponents(Graphics g) { | ||
| 2092 | if (isShowing()) { | ||
| 2093 | GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance(). | ||
| 2094 | runComponents(getComponentsSync(), g, | ||
| 2095 | GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS); | ||
| 2096 | } | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | /** | ||
| 2100 | * Adds the specified container listener to receive container events | ||
| 2101 | * from this container. | ||
| 2102 | * If l is null, no exception is thrown and no action is performed. | ||
| 2103 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 2104 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 2105 | * | ||
| 2106 | * @param l the container listener | ||
| 2107 | * | ||
| 2108 | * @see #removeContainerListener | ||
| 2109 | * @see #getContainerListeners | ||
| 2110 | */ | ||
| 2111 | public synchronized void addContainerListener(ContainerListener l) { | ||
| 2112 | if (l == null) { | ||
| 2113 | return; | ||
| 2114 | } | ||
| 2115 | containerListener = AWTEventMulticaster.add(containerListener, l); | ||
| 2116 | newEventsOnly = true; | ||
| 2117 | } | ||
| 2118 | |||
| 2119 | /** | ||
| 2120 | * Removes the specified container listener so it no longer receives | ||
| 2121 | * container events from this container. | ||
| 2122 | * If l is null, no exception is thrown and no action is performed. | ||
| 2123 | * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" | ||
| 2124 | * >AWT Threading Issues</a> for details on AWT's threading model. | ||
| 2125 | * | ||
| 2126 | * @param l the container listener | ||
| 2127 | * | ||
| 2128 | * @see #addContainerListener | ||
| 2129 | * @see #getContainerListeners | ||
| 2130 | */ | ||
| 2131 | public synchronized void removeContainerListener(ContainerListener l) { | ||
| 2132 | if (l == null) { | ||
| 2133 | return; | ||
| 2134 | } | ||
| 2135 | containerListener = AWTEventMulticaster.remove(containerListener, l); | ||
| 2136 | } | ||
| 2137 | |||
| 2138 | /** | ||
| 2139 | * Returns an array of all the container listeners | ||
| 2140 | * registered on this container. | ||
| 2141 | * | ||
| 2142 | * @return all of this container's <code>ContainerListener</code>s | ||
| 2143 | * or an empty array if no container | ||
| 2144 | * listeners are currently registered | ||
| 2145 | * | ||
| 2146 | * @see #addContainerListener | ||
| 2147 | * @see #removeContainerListener | ||
| 2148 | * @since 1.4 | ||
| 2149 | */ | ||
| 2150 | public synchronized ContainerListener[] getContainerListeners() { | ||
| 2151 | return (ContainerListener[]) (getListeners(ContainerListener.class)); | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | /** | ||
| 2155 | * Returns an array of all the objects currently registered | ||
| 2156 | * as <code><em>Foo</em>Listener</code>s | ||
| 2157 | * upon this <code>Container</code>. | ||
| 2158 | * <code><em>Foo</em>Listener</code>s are registered using the | ||
| 2159 | * <code>add<em>Foo</em>Listener</code> method. | ||
| 2160 | * | ||
| 2161 | * <p> | ||
| 2162 | * You can specify the <code>listenerType</code> argument | ||
| 2163 | * with a class literal, such as | ||
| 2164 | * <code><em>Foo</em>Listener.class</code>. | ||
| 2165 | * For example, you can query a | ||
| 2166 | * <code>Container</code> <code>c</code> | ||
| 2167 | * for its container listeners with the following code: | ||
| 2168 | * | ||
| 2169 | * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre> | ||
| 2170 | * | ||
| 2171 | * If no such listeners exist, this method returns an empty array. | ||
| 2172 | * | ||
| 2173 | * @param listenerType the type of listeners requested; this parameter | ||
| 2174 | * should specify an interface that descends from | ||
| 2175 | * <code>java.util.EventListener</code> | ||
| 2176 | * @return an array of all objects registered as | ||
| 2177 | * <code><em>Foo</em>Listener</code>s on this container, | ||
| 2178 | * or an empty array if no such listeners have been added | ||
| 2179 | * @exception ClassCastException if <code>listenerType</code> | ||
| 2180 | * doesn't specify a class or interface that implements | ||
| 2181 | * <code>java.util.EventListener</code> | ||
| 2182 | * @exception NullPointerException if {@code listenerType} is {@code null} | ||
| 2183 | * | ||
| 2184 | * @see #getContainerListeners | ||
| 2185 | * | ||
| 2186 | * @since 1.3 | ||
| 2187 | */ | ||
| 2188 | public <T extends EventListener> T[] getListeners(Class<T> listenerType) { | ||
| 2189 | EventListener l = null; | ||
| 2190 | if (listenerType == ContainerListener.class) { | ||
| 2191 | l = containerListener; | ||
| 2192 | } else { | ||
| 2193 | return super.getListeners(listenerType); | ||
| 2194 | } | ||
| 2195 | return AWTEventMulticaster.getListeners(l, listenerType); | ||
| 2196 | } | ||
| 2197 | |||
| 2198 | // REMIND: remove when filtering is done at lower level | ||
| 2199 | boolean eventEnabled(AWTEvent e) { | ||
| 2200 | int id = e.getID(); | ||
| 2201 | |||
| 2202 | if (id == ContainerEvent.COMPONENT_ADDED || | ||
| 2203 | id == ContainerEvent.COMPONENT_REMOVED) { | ||
| 2204 | if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || | ||
| 2205 | containerListener != null) { | ||
| 2206 | return true; | ||
| 2207 | } | ||
| 2208 | return false; | ||
| 2209 | } | ||
| 2210 | return super.eventEnabled(e); | ||
| 2211 | } | ||
| 2212 | |||
| 2213 | /** | ||
| 2214 | * Processes events on this container. If the event is a | ||
| 2215 | * <code>ContainerEvent</code>, it invokes the | ||
| 2216 | * <code>processContainerEvent</code> method, else it invokes | ||
| 2217 | * its superclass's <code>processEvent</code>. | ||
| 2218 | * <p>Note that if the event parameter is <code>null</code> | ||
| 2219 | * the behavior is unspecified and may result in an | ||
| 2220 | * exception. | ||
| 2221 | * | ||
| 2222 | * @param e the event | ||
| 2223 | */ | ||
| 2224 | protected void processEvent(AWTEvent e) { | ||
| 2225 | if (e instanceof ContainerEvent) { | ||
| 2226 | processContainerEvent((ContainerEvent)e); | ||
| 2227 | return; | ||
| 2228 | } | ||
| 2229 | super.processEvent(e); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | /** | ||
| 2233 | * Processes container events occurring on this container by | ||
| 2234 | * dispatching them to any registered ContainerListener objects. | ||
| 2235 | * NOTE: This method will not be called unless container events | ||
| 2236 | * are enabled for this component; this happens when one of the | ||
| 2237 | * following occurs: | ||
| 2238 | * <ul> | ||
| 2239 | * <li>A ContainerListener object is registered via | ||
| 2240 | * <code>addContainerListener</code> | ||
| 2241 | * <li>Container events are enabled via <code>enableEvents</code> | ||
| 2242 | * </ul> | ||
| 2243 | * <p>Note that if the event parameter is <code>null</code> | ||
| 2244 | * the behavior is unspecified and may result in an | ||
| 2245 | * exception. | ||
| 2246 | * | ||
| 2247 | * @param e the container event | ||
| 2248 | * @see Component#enableEvents | ||
| 2249 | */ | ||
| 2250 | protected void processContainerEvent(ContainerEvent e) { | ||
| 2251 | ContainerListener listener = containerListener; | ||
| 2252 | if (listener != null) { | ||
| 2253 | switch(e.getID()) { | ||
| 2254 | case ContainerEvent.COMPONENT_ADDED: | ||
| 2255 | listener.componentAdded(e); | ||
| 2256 | break; | ||
| 2257 | case ContainerEvent.COMPONENT_REMOVED: | ||
| 2258 | listener.componentRemoved(e); | ||
| 2259 | break; | ||
| 2260 | } | ||
| 2261 | } | ||
| 2262 | } | ||
| 2263 | |||
| 2264 | /* | ||
| 2265 | * Dispatches an event to this component or one of its sub components. | ||
| 2266 | * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to | ||
| 2267 | * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this | ||
| 2268 | * here instead of in processComponentEvent because ComponentEvents | ||
| 2269 | * may not be enabled for this Container. | ||
| 2270 | * @param e the event | ||
| 2271 | */ | ||
| 2272 | void dispatchEventImpl(AWTEvent e) { | ||
| 2273 | if ((dispatcher != null) && dispatcher.dispatchEvent(e)) { | ||
| 2274 | // event was sent to a lightweight component. The | ||
| 2275 | // native-produced event sent to the native container | ||
| 2276 | // must be properly disposed of by the peer, so it | ||
| 2277 | // gets forwarded. If the native host has been removed | ||
| 2278 | // as a result of the sending the lightweight event, | ||
| 2279 | // the peer reference will be null. | ||
| 2280 | e.consume(); | ||
| 2281 | if (peer != null) { | ||
| 2282 | peer.handleEvent(e); | ||
| 2283 | } | ||
| 2284 | return; | ||
| 2285 | } | ||
| 2286 | |||
| 2287 | super.dispatchEventImpl(e); | ||
| 2288 | |||
| 2289 | synchronized (getTreeLock()) { | ||
| 2290 | switch (e.getID()) { | ||
| 2291 | case ComponentEvent.COMPONENT_RESIZED: | ||
| 2292 | createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0, | ||
| 2293 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 2294 | break; | ||
| 2295 | case ComponentEvent.COMPONENT_MOVED: | ||
| 2296 | createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0, | ||
| 2297 | Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 2298 | break; | ||
| 2299 | default: | ||
| 2300 | break; | ||
| 2301 | } | ||
| 2302 | } | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | /* | ||
| 2306 | * Dispatches an event to this component, without trying to forward | ||
| 2307 | * it to any subcomponents | ||
| 2308 | * @param e the event | ||
| 2309 | */ | ||
| 2310 | void dispatchEventToSelf(AWTEvent e) { | ||
| 2311 | super.dispatchEventImpl(e); | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | /** | ||
| 2315 | * Fetchs the top-most (deepest) lightweight component that is interested | ||
| 2316 | * in receiving mouse events. | ||
| 2317 | */ | ||
| 2318 | Component getMouseEventTarget(int x, int y, boolean includeSelf) { | ||
| 2319 | return getMouseEventTarget(x, y, includeSelf, | ||
| 2320 | MouseEventTargetFilter.FILTER, | ||
| 2321 | !SEARCH_HEAVYWEIGHTS); | ||
| 2322 | } | ||
| 2323 | |||
| 2324 | /** | ||
| 2325 | * Fetches the top-most (deepest) component to receive SunDropTargetEvents. | ||
| 2326 | */ | ||
| 2327 | Component getDropTargetEventTarget(int x, int y, boolean includeSelf) { | ||
| 2328 | return getMouseEventTarget(x, y, includeSelf, | ||
| 2329 | DropTargetEventTargetFilter.FILTER, | ||
| 2330 | SEARCH_HEAVYWEIGHTS); | ||
| 2331 | } | ||
| 2332 | |||
| 2333 | /** | ||
| 2334 | * A private version of getMouseEventTarget which has two additional | ||
| 2335 | * controllable behaviors. This method searches for the top-most | ||
| 2336 | * descendant of this container that contains the given coordinates | ||
| 2337 | * and is accepted by the given filter. The search will be constrained to | ||
| 2338 | * lightweight descendants if the last argument is <code>false</code>. | ||
| 2339 | * | ||
| 2340 | * @param filter EventTargetFilter instance to determine whether the | ||
| 2341 | * given component is a valid target for this event. | ||
| 2342 | * @param searchHeavyweights if <code>false</code>, the method | ||
| 2343 | * will bypass heavyweight components during the search. | ||
| 2344 | */ | ||
| 2345 | private Component getMouseEventTarget(int x, int y, boolean includeSelf, | ||
| 2346 | EventTargetFilter filter, | ||
| 2347 | boolean searchHeavyweights) { | ||
| 2348 | Component comp = null; | ||
| 2349 | if (searchHeavyweights) { | ||
| 2350 | comp = getMouseEventTargetImpl(x, y, includeSelf, filter, | ||
| 2351 | SEARCH_HEAVYWEIGHTS, | ||
| 2352 | searchHeavyweights); | ||
| 2353 | } | ||
| 2354 | |||
| 2355 | if (comp == null || comp == this) { | ||
| 2356 | comp = getMouseEventTargetImpl(x, y, includeSelf, filter, | ||
| 2357 | !SEARCH_HEAVYWEIGHTS, | ||
| 2358 | searchHeavyweights); | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | return comp; | ||
| 2362 | } | ||
| 2363 | |||
| 2364 | /** | ||
| 2365 | * A private version of getMouseEventTarget which has three additional | ||
| 2366 | * controllable behaviors. This method searches for the top-most | ||
| 2367 | * descendant of this container that contains the given coordinates | ||
| 2368 | * and is accepted by the given filter. The search will be constrained to | ||
| 2369 | * descendants of only lightweight children or only heavyweight children | ||
| 2370 | * of this container depending on searchHeavyweightChildren. The search will | ||
| 2371 | * be constrained to only lightweight descendants of the searched children | ||
| 2372 | * of this container if searchHeavyweightDescendants is <code>false</code>. | ||
| 2373 | * | ||
| 2374 | * @param filter EventTargetFilter instance to determine whether the | ||
| 2375 | * selected component is a valid target for this event. | ||
| 2376 | * @param searchHeavyweightChildren if <code>true</code>, the method | ||
| 2377 | * will bypass immediate lightweight children during the search. | ||
| 2378 | * If <code>false</code>, the methods will bypass immediate | ||
| 2379 | * heavyweight children during the search. | ||
| 2380 | * @param searchHeavyweightDescendants if <code>false</code>, the method | ||
| 2381 | * will bypass heavyweight descendants which are not immediate | ||
| 2382 | * children during the search. If <code>true</code>, the method | ||
| 2383 | * will traverse both lightweight and heavyweight descendants during | ||
| 2384 | * the search. | ||
| 2385 | */ | ||
| 2386 | private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf, | ||
| 2387 | EventTargetFilter filter, | ||
| 2388 | boolean searchHeavyweightChildren, | ||
| 2389 | boolean searchHeavyweightDescendants) { | ||
| 2390 | synchronized (getTreeLock()) { | ||
| 2391 | |||
| 2392 | for (int i = 0; i < component.size(); i++) { | ||
| 2393 | Component comp = component.get(i); | ||
| 2394 | if (comp != null && comp.visible && | ||
| 2395 | ((!searchHeavyweightChildren && | ||
| 2396 | comp.peer instanceof LightweightPeer) || | ||
| 2397 | (searchHeavyweightChildren && | ||
| 2398 | !(comp.peer instanceof LightweightPeer))) && | ||
| 2399 | comp.contains(x - comp.x, y - comp.y)) { | ||
| 2400 | |||
| 2401 | // found a component that intersects the point, see if there | ||
| 2402 | // is a deeper possibility. | ||
| 2403 | if (comp instanceof Container) { | ||
| 2404 | Container child = (Container) comp; | ||
| 2405 | Component deeper = child.getMouseEventTarget( | ||
| 2406 | x - child.x, | ||
| 2407 | y - child.y, | ||
| 2408 | includeSelf, | ||
| 2409 | filter, | ||
| 2410 | searchHeavyweightDescendants); | ||
| 2411 | if (deeper != null) { | ||
| 2412 | return deeper; | ||
| 2413 | } | ||
| 2414 | } else { | ||
| 2415 | if (filter.accept(comp)) { | ||
| 2416 | // there isn't a deeper target, but this component | ||
| 2417 | // is a target | ||
| 2418 | return comp; | ||
| 2419 | } | ||
| 2420 | } | ||
| 2421 | } | ||
| 2422 | } | ||
| 2423 | |||
| 2424 | boolean isPeerOK; | ||
| 2425 | boolean isMouseOverMe; | ||
| 2426 | |||
| 2427 | isPeerOK = (peer instanceof LightweightPeer) || includeSelf; | ||
| 2428 | isMouseOverMe = contains(x,y); | ||
| 2429 | |||
| 2430 | // didn't find a child target, return this component if it's | ||
| 2431 | // a possible target | ||
| 2432 | if (isMouseOverMe && isPeerOK && filter.accept(this)) { | ||
| 2433 | return this; | ||
| 2434 | } | ||
| 2435 | // no possible target | ||
| 2436 | return null; | ||
| 2437 | } | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | static interface EventTargetFilter { | ||
| 2441 | boolean accept(final Component comp); | ||
| 2442 | } | ||
| 2443 | |||
| 2444 | static class MouseEventTargetFilter implements EventTargetFilter { | ||
| 2445 | static final EventTargetFilter FILTER = new MouseEventTargetFilter(); | ||
| 2446 | |||
| 2447 | private MouseEventTargetFilter() {} | ||
| 2448 | |||
| 2449 | public boolean accept(final Component comp) { | ||
| 2450 | return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 | ||
| 2451 | || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 | ||
| 2452 | || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 | ||
| 2453 | || comp.mouseListener != null | ||
| 2454 | || comp.mouseMotionListener != null | ||
| 2455 | || comp.mouseWheelListener != null; | ||
| 2456 | } | ||
| 2457 | } | ||
| 2458 | |||
| 2459 | static class DropTargetEventTargetFilter implements EventTargetFilter { | ||
| 2460 | static final EventTargetFilter FILTER = new DropTargetEventTargetFilter(); | ||
| 2461 | |||
| 2462 | private DropTargetEventTargetFilter() {} | ||
| 2463 | |||
| 2464 | public boolean accept(final Component comp) { | ||
| 2465 | DropTarget dt = comp.getDropTarget(); | ||
| 2466 | return dt != null && dt.isActive(); | ||
| 2467 | } | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | /** | ||
| 2471 | * This is called by lightweight components that want the containing | ||
| 2472 | * windowed parent to enable some kind of events on their behalf. | ||
| 2473 | * This is needed for events that are normally only dispatched to | ||
| 2474 | * windows to be accepted so that they can be forwarded downward to | ||
| 2475 | * the lightweight component that has enabled them. | ||
| 2476 | */ | ||
| 2477 | void proxyEnableEvents(long events) { | ||
| 2478 | if (peer instanceof LightweightPeer) { | ||
| 2479 | // this container is lightweight.... continue sending it | ||
| 2480 | // upward. | ||
| 2481 | if (parent != null) { | ||
| 2482 | parent.proxyEnableEvents(events); | ||
| 2483 | } | ||
| 2484 | } else { | ||
| 2485 | // This is a native container, so it needs to host | ||
| 2486 | // one of it's children. If this function is called before | ||
| 2487 | // a peer has been created we don't yet have a dispatcher | ||
| 2488 | // because it has not yet been determined if this instance | ||
| 2489 | // is lightweight. | ||
| 2490 | if (dispatcher != null) { | ||
| 2491 | dispatcher.enableEvents(events); | ||
| 2492 | } | ||
| 2493 | } | ||
| 2494 | } | ||
| 2495 | |||
| 2496 | /** | ||
| 2497 | * @deprecated As of JDK version 1.1, | ||
| 2498 | * replaced by <code>dispatchEvent(AWTEvent e)</code> | ||
| 2499 | */ | ||
| 2500 | @Deprecated | ||
| 2501 | public void deliverEvent(Event e) { | ||
| 2502 | Component comp = getComponentAt(e.x, e.y); | ||
| 2503 | if ((comp != null) && (comp != this)) { | ||
| 2504 | e.translate(-comp.x, -comp.y); | ||
| 2505 | comp.deliverEvent(e); | ||
| 2506 | } else { | ||
| 2507 | postEvent(e); | ||
| 2508 | } | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | /** | ||
| 2512 | * Locates the component that contains the x,y position. The | ||
| 2513 | * top-most child component is returned in the case where there | ||
| 2514 | * is overlap in the components. This is determined by finding | ||
| 2515 | * the component closest to the index 0 that claims to contain | ||
| 2516 | * the given point via Component.contains(), except that Components | ||
| 2517 | * which have native peers take precedence over those which do not | ||
| 2518 | * (i.e., lightweight Components). | ||
| 2519 | * | ||
| 2520 | * @param x the <i>x</i> coordinate | ||
| 2521 | * @param y the <i>y</i> coordinate | ||
| 2522 | * @return null if the component does not contain the position. | ||
| 2523 | * If there is no child component at the requested point and the | ||
| 2524 | * point is within the bounds of the container the container itself | ||
| 2525 | * is returned; otherwise the top-most child is returned. | ||
| 2526 | * @see Component#contains | ||
| 2527 | * @since JDK1.1 | ||
| 2528 | */ | ||
| 2529 | public Component getComponentAt(int x, int y) { | ||
| 2530 | return locate(x, y); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | /** | ||
| 2534 | * @deprecated As of JDK version 1.1, | ||
| 2535 | * replaced by <code>getComponentAt(int, int)</code>. | ||
| 2536 | */ | ||
| 2537 | @Deprecated | ||
| 2538 | public Component locate(int x, int y) { | ||
| 2539 | if (!contains(x, y)) { | ||
| 2540 | return null; | ||
| 2541 | } | ||
| 2542 | synchronized (getTreeLock()) { | ||
| 2543 | // Two passes: see comment in sun.awt.SunGraphicsCallback | ||
| 2544 | for (int i = 0; i < component.size(); i++) { | ||
| 2545 | Component comp = component.get(i); | ||
| 2546 | if (comp != null && | ||
| 2547 | !(comp.peer instanceof LightweightPeer)) { | ||
| 2548 | if (comp.contains(x - comp.x, y - comp.y)) { | ||
| 2549 | return comp; | ||
| 2550 | } | ||
| 2551 | } | ||
| 2552 | } | ||
| 2553 | for (int i = 0; i < component.size(); i++) { | ||
| 2554 | Component comp = component.get(i); | ||
| 2555 | if (comp != null && | ||
| 2556 | comp.peer instanceof LightweightPeer) { | ||
| 2557 | if (comp.contains(x - comp.x, y - comp.y)) { | ||
| 2558 | return comp; | ||
| 2559 | } | ||
| 2560 | } | ||
| 2561 | } | ||
| 2562 | } | ||
| 2563 | return this; | ||
| 2564 | } | ||
| 2565 | |||
| 2566 | /** | ||
| 2567 | * Gets the component that contains the specified point. | ||
| 2568 | * @param p the point. | ||
| 2569 | * @return returns the component that contains the point, | ||
| 2570 | * or <code>null</code> if the component does | ||
| 2571 | * not contain the point. | ||
| 2572 | * @see Component#contains | ||
| 2573 | * @since JDK1.1 | ||
| 2574 | */ | ||
| 2575 | public Component getComponentAt(Point p) { | ||
| 2576 | return getComponentAt(p.x, p.y); | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | /** | ||
| 2580 | * Returns the position of the mouse pointer in this <code>Container</code>'s | ||
| 2581 | * coordinate space if the <code>Container</code> is under the mouse pointer, | ||
| 2582 | * otherwise returns <code>null</code>. | ||
| 2583 | * This method is similar to {@link Component#getMousePosition()} with the exception | ||
| 2584 | * that it can take the <code>Container</code>'s children into account. | ||
| 2585 | * If <code>allowChildren</code> is <code>false</code>, this method will return | ||
| 2586 | * a non-null value only if the mouse pointer is above the <code>Container</code> | ||
| 2587 | * directly, not above the part obscured by children. | ||
| 2588 | * If <code>allowChildren</code> is <code>true</code>, this method returns | ||
| 2589 | * a non-null value if the mouse pointer is above <code>Container</code> or any | ||
| 2590 | * of its descendants. | ||
| 2591 | * | ||
| 2592 | * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true | ||
| 2593 | * @param allowChildren true if children should be taken into account | ||
| 2594 | * @see Component#getMousePosition | ||
| 2595 | * @return mouse coordinates relative to this <code>Component</code>, or null | ||
| 2596 | * @since 1.5 | ||
| 2597 | */ | ||
| 2598 | public Point getMousePosition(boolean allowChildren) throws HeadlessException { | ||
| 2599 | if (GraphicsEnvironment.isHeadless()) { | ||
| 2600 | throw new HeadlessException(); | ||
| 2601 | } | ||
| 2602 | PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged( | ||
| 2603 | new java.security.PrivilegedAction() { | ||
| 2604 | public Object run() { | ||
| 2605 | return MouseInfo.getPointerInfo(); | ||
| 2606 | } | ||
| 2607 | } | ||
| 2608 | ); | ||
| 2609 | synchronized (getTreeLock()) { | ||
| 2610 | Component inTheSameWindow = findUnderMouseInWindow(pi); | ||
| 2611 | if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) { | ||
| 2612 | return pointRelativeToComponent(pi.getLocation()); | ||
| 2613 | } | ||
| 2614 | return null; | ||
| 2615 | } | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | boolean isSameOrAncestorOf(Component comp, boolean allowChildren) { | ||
| 2619 | return this == comp || (allowChildren && isParentOf(comp)); | ||
| 2620 | } | ||
| 2621 | |||
| 2622 | /** | ||
| 2623 | * Locates the visible child component that contains the specified | ||
| 2624 | * position. The top-most child component is returned in the case | ||
| 2625 | * where there is overlap in the components. If the containing child | ||
| 2626 | * component is a Container, this method will continue searching for | ||
| 2627 | * the deepest nested child component. Components which are not | ||
| 2628 | * visible are ignored during the search.<p> | ||
| 2629 | * | ||
| 2630 | * The findComponentAt method is different from getComponentAt in | ||
| 2631 | * that getComponentAt only searches the Container's immediate | ||
| 2632 | * children; if the containing component is a Container, | ||
| 2633 | * findComponentAt will search that child to find a nested component. | ||
| 2634 | * | ||
| 2635 | * @param x the <i>x</i> coordinate | ||
| 2636 | * @param y the <i>y</i> coordinate | ||
| 2637 | * @return null if the component does not contain the position. | ||
| 2638 | * If there is no child component at the requested point and the | ||
| 2639 | * point is within the bounds of the container the container itself | ||
| 2640 | * is returned. | ||
| 2641 | * @see Component#contains | ||
| 2642 | * @see #getComponentAt | ||
| 2643 | * @since 1.2 | ||
| 2644 | */ | ||
| 2645 | public Component findComponentAt(int x, int y) { | ||
| 2646 | return findComponentAt(x, y, true); | ||
| 2647 | } | ||
| 2648 | |||
| 2649 | /** | ||
| 2650 | * Private version of findComponentAt which has a controllable | ||
| 2651 | * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled | ||
| 2652 | * Components during the search. This behavior is used by the | ||
| 2653 | * lightweight cursor support in sun.awt.GlobalCursorManager. | ||
| 2654 | * The cursor code calls this function directly via native code. | ||
| 2655 | * | ||
| 2656 | * The addition of this feature is temporary, pending the | ||
| 2657 | * adoption of new, public API which exports this feature. | ||
| 2658 | */ | ||
| 2659 | final Component findComponentAt(int x, int y, boolean ignoreEnabled) { | ||
| 2660 | synchronized (getTreeLock()) { | ||
| 2661 | if (isRecursivelyVisible()){ | ||
| 2662 | return findComponentAtImpl(x, y, ignoreEnabled); | ||
| 2663 | } | ||
| 2664 | } | ||
| 2665 | return null; | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){ | ||
| 2669 | checkTreeLock(); | ||
| 2670 | |||
| 2671 | if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) { | ||
| 2672 | return null; | ||
| 2673 | } | ||
| 2674 | |||
| 2675 | // Two passes: see comment in sun.awt.SunGraphicsCallback | ||
| 2676 | for (int i = 0; i < component.size(); i++) { | ||
| 2677 | Component comp = component.get(i); | ||
| 2678 | if (comp != null && | ||
| 2679 | !(comp.peer instanceof LightweightPeer)) { | ||
| 2680 | if (comp instanceof Container) { | ||
| 2681 | comp = ((Container)comp).findComponentAtImpl(x - comp.x, | ||
| 2682 | y - comp.y, | ||
| 2683 | ignoreEnabled); | ||
| 2684 | } else { | ||
| 2685 | comp = comp.locate(x - comp.x, y - comp.y); | ||
| 2686 | } | ||
| 2687 | if (comp != null && comp.visible && | ||
| 2688 | (ignoreEnabled || comp.enabled)) | ||
| 2689 | { | ||
| 2690 | return comp; | ||
| 2691 | } | ||
| 2692 | } | ||
| 2693 | } | ||
| 2694 | for (int i = 0; i < component.size(); i++) { | ||
| 2695 | Component comp = component.get(i); | ||
| 2696 | if (comp != null && | ||
| 2697 | comp.peer instanceof LightweightPeer) { | ||
| 2698 | if (comp instanceof Container) { | ||
| 2699 | comp = ((Container)comp).findComponentAtImpl(x - comp.x, | ||
| 2700 | y - comp.y, | ||
| 2701 | ignoreEnabled); | ||
| 2702 | } else { | ||
| 2703 | comp = comp.locate(x - comp.x, y - comp.y); | ||
| 2704 | } | ||
| 2705 | if (comp != null && comp.visible && | ||
| 2706 | (ignoreEnabled || comp.enabled)) | ||
| 2707 | { | ||
| 2708 | return comp; | ||
| 2709 | } | ||
| 2710 | } | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | return this; | ||
| 2714 | } | ||
| 2715 | |||
| 2716 | /** | ||
| 2717 | * Locates the visible child component that contains the specified | ||
| 2718 | * point. The top-most child component is returned in the case | ||
| 2719 | * where there is overlap in the components. If the containing child | ||
| 2720 | * component is a Container, this method will continue searching for | ||
| 2721 | * the deepest nested child component. Components which are not | ||
| 2722 | * visible are ignored during the search.<p> | ||
| 2723 | * | ||
| 2724 | * The findComponentAt method is different from getComponentAt in | ||
| 2725 | * that getComponentAt only searches the Container's immediate | ||
| 2726 | * children; if the containing component is a Container, | ||
| 2727 | * findComponentAt will search that child to find a nested component. | ||
| 2728 | * | ||
| 2729 | * @param p the point. | ||
| 2730 | * @return null if the component does not contain the position. | ||
| 2731 | * If there is no child component at the requested point and the | ||
| 2732 | * point is within the bounds of the container the container itself | ||
| 2733 | * is returned. | ||
| 2734 | * @throws NullPointerException if {@code p} is {@code null} | ||
| 2735 | * @see Component#contains | ||
| 2736 | * @see #getComponentAt | ||
| 2737 | * @since 1.2 | ||
| 2738 | */ | ||
| 2739 | public Component findComponentAt(Point p) { | ||
| 2740 | return findComponentAt(p.x, p.y); | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | /** | ||
| 2744 | * Makes this Container displayable by connecting it to | ||
| 2745 | * a native screen resource. Making a container displayable will | ||
| 2746 | * cause all of its children to be made displayable. | ||
| 2747 | * This method is called internally by the toolkit and should | ||
| 2748 | * not be called directly by programs. | ||
| 2749 | * @see Component#isDisplayable | ||
| 2750 | * @see #removeNotify | ||
| 2751 | */ | ||
| 2752 | public void addNotify() { | ||
| 2753 | synchronized (getTreeLock()) { | ||
| 2754 | // addNotify() on the children may cause proxy event enabling | ||
| 2755 | // on this instance, so we first call super.addNotify() and | ||
| 2756 | // possibly create an lightweight event dispatcher before calling | ||
| 2757 | // addNotify() on the children which may be lightweight. | ||
| 2758 | super.addNotify(); | ||
| 2759 | if (! (peer instanceof LightweightPeer)) { | ||
| 2760 | dispatcher = new LightweightDispatcher(this); | ||
| 2761 | } | ||
| 2762 | |||
| 2763 | // We shouldn't use iterator because of the Swing menu | ||
| 2764 | // implementation specifics: | ||
| 2765 | // the menu is being assigned as a child to JLayeredPane | ||
| 2766 | // instead of particular component so always affect | ||
| 2767 | // collection of component if menu is becoming shown or hidden. | ||
| 2768 | for (int i = 0; i < component.size(); i++) { | ||
| 2769 | component.get(i).addNotify(); | ||
| 2770 | } | ||
| 2771 | } | ||
| 2772 | } | ||
| 2773 | |||
| 2774 | /** | ||
| 2775 | * Makes this Container undisplayable by removing its connection | ||
| 2776 | * to its native screen resource. Making a container undisplayable | ||
| 2777 | * will cause all of its children to be made undisplayable. | ||
| 2778 | * This method is called by the toolkit internally and should | ||
| 2779 | * not be called directly by programs. | ||
| 2780 | * @see Component#isDisplayable | ||
| 2781 | * @see #addNotify | ||
| 2782 | */ | ||
| 2783 | public void removeNotify() { | ||
| 2784 | synchronized (getTreeLock()) { | ||
| 2785 | // We shouldn't use iterator because of the Swing menu | ||
| 2786 | // implementation specifics: | ||
| 2787 | // the menu is being assigned as a child to JLayeredPane | ||
| 2788 | // instead of particular component so always affect | ||
| 2789 | // collection of component if menu is becoming shown or hidden. | ||
| 2790 | for (int i = component.size()-1 ; i >= 0 ; i--) { | ||
| 2791 | Component comp = component.get(i); | ||
| 2792 | if (comp != null) { | ||
| 2793 | // Fix for 6607170. | ||
| 2794 | // We want to suppress focus change on disposal | ||
| 2795 | // of the focused component. But because of focus | ||
| 2796 | // is asynchronous, we should suppress focus change | ||
| 2797 | // on every component in case it receives native focus | ||
| 2798 | // in the process of disposal. | ||
| 2799 | comp.setAutoFocusTransferOnDisposal(false); | ||
| 2800 | comp.removeNotify(); | ||
| 2801 | comp.setAutoFocusTransferOnDisposal(true); | ||
| 2802 | } | ||
| 2803 | } | ||
| 2804 | // If some of the children had focus before disposal then it still has. | ||
| 2805 | // Auto-transfer focus to the next (or previous) component if auto-transfer | ||
| 2806 | // is enabled. | ||
| 2807 | if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { | ||
| 2808 | if (!transferFocus(false)) { | ||
| 2809 | transferFocusBackward(true); | ||
| 2810 | } | ||
| 2811 | } | ||
| 2812 | if ( dispatcher != null ) { | ||
| 2813 | dispatcher.dispose(); | ||
| 2814 | dispatcher = null; | ||
| 2815 | } | ||
| 2816 | super.removeNotify(); | ||
| 2817 | } | ||
| 2818 | } | ||
| 2819 | |||
| 2820 | /** | ||
| 2821 | * Checks if the component is contained in the component hierarchy of | ||
| 2822 | * this container. | ||
| 2823 | * @param c the component | ||
| 2824 | * @return <code>true</code> if it is an ancestor; | ||
| 2825 | * <code>false</code> otherwise. | ||
| 2826 | * @since JDK1.1 | ||
| 2827 | */ | ||
| 2828 | public boolean isAncestorOf(Component c) { | ||
| 2829 | Container p; | ||
| 2830 | if (c == null || ((p = c.getParent()) == null)) { | ||
| 2831 | return false; | ||
| 2832 | } | ||
| 2833 | while (p != null) { | ||
| 2834 | if (p == this) { | ||
| 2835 | return true; | ||
| 2836 | } | ||
| 2837 | p = p.getParent(); | ||
| 2838 | } | ||
| 2839 | return false; | ||
| 2840 | } | ||
| 2841 | |||
| 2842 | /* | ||
| 2843 | * The following code was added to support modal JInternalFrames | ||
| 2844 | * Unfortunately this code has to be added here so that we can get access to | ||
| 2845 | * some private AWT classes like SequencedEvent. | ||
| 2846 | * | ||
| 2847 | * The native container of the LW component has this field set | ||
| 2848 | * to tell it that it should block Mouse events for all LW | ||
| 2849 | * children except for the modal component. | ||
| 2850 | * | ||
| 2851 | * In the case of nested Modal components, we store the previous | ||
| 2852 | * modal component in the new modal components value of modalComp; | ||
| 2853 | */ | ||
| 2854 | |||
| 2855 | transient Component modalComp; | ||
| 2856 | transient AppContext modalAppContext; | ||
| 2857 | |||
| 2858 | private void startLWModal() { | ||
| 2859 | // Store the app context on which this component is being shown. | ||
| 2860 | // Event dispatch thread of this app context will be sleeping until | ||
| 2861 | // we wake it by any event from hideAndDisposeHandler(). | ||
| 2862 | modalAppContext = AppContext.getAppContext(); | ||
| 2863 | |||
| 2864 | // keep the KeyEvents from being dispatched | ||
| 2865 | // until the focus has been transfered | ||
| 2866 | long time = Toolkit.getEventQueue().getMostRecentEventTime(); | ||
| 2867 | Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null; | ||
| 2868 | if (predictedFocusOwner != null) { | ||
| 2869 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 2870 | enqueueKeyEvents(time, predictedFocusOwner); | ||
| 2871 | } | ||
| 2872 | // We have two mechanisms for blocking: 1. If we're on the | ||
| 2873 | // EventDispatchThread, start a new event pump. 2. If we're | ||
| 2874 | // on any other thread, call wait() on the treelock. | ||
| 2875 | final Container nativeContainer; | ||
| 2876 | synchronized (getTreeLock()) { | ||
| 2877 | nativeContainer = getHeavyweightContainer(); | ||
| 2878 | if (nativeContainer.modalComp != null) { | ||
| 2879 | this.modalComp = nativeContainer.modalComp; | ||
| 2880 | nativeContainer.modalComp = this; | ||
| 2881 | return; | ||
| 2882 | } | ||
| 2883 | else { | ||
| 2884 | nativeContainer.modalComp = this; | ||
| 2885 | } | ||
| 2886 | } | ||
| 2887 | |||
| 2888 | Runnable pumpEventsForHierarchy = new Runnable() { | ||
| 2889 | public void run() { | ||
| 2890 | EventDispatchThread dispatchThread = | ||
| 2891 | (EventDispatchThread)Thread.currentThread(); | ||
| 2892 | dispatchThread.pumpEventsForHierarchy( | ||
| 2893 | new Conditional() { | ||
| 2894 | public boolean evaluate() { | ||
| 2895 | return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ; | ||
| 2896 | } | ||
| 2897 | }, Container.this); | ||
| 2898 | } | ||
| 2899 | }; | ||
| 2900 | |||
| 2901 | if (EventQueue.isDispatchThread()) { | ||
| 2902 | SequencedEvent currentSequencedEvent = | ||
| 2903 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 2904 | getCurrentSequencedEvent(); | ||
| 2905 | if (currentSequencedEvent != null) { | ||
| 2906 | currentSequencedEvent.dispose(); | ||
| 2907 | } | ||
| 2908 | |||
| 2909 | pumpEventsForHierarchy.run(); | ||
| 2910 | } else { | ||
| 2911 | synchronized (getTreeLock()) { | ||
| 2912 | Toolkit.getEventQueue(). | ||
| 2913 | postEvent(new PeerEvent(this, | ||
| 2914 | pumpEventsForHierarchy, | ||
| 2915 | PeerEvent.PRIORITY_EVENT)); | ||
| 2916 | while ((windowClosingException == null) && | ||
| 2917 | (nativeContainer.modalComp != null)) | ||
| 2918 | { | ||
| 2919 | try { | ||
| 2920 | getTreeLock().wait(); | ||
| 2921 | } catch (InterruptedException e) { | ||
| 2922 | break; | ||
| 2923 | } | ||
| 2924 | } | ||
| 2925 | } | ||
| 2926 | } | ||
| 2927 | if (windowClosingException != null) { | ||
| 2928 | windowClosingException.fillInStackTrace(); | ||
| 2929 | throw windowClosingException; | ||
| 2930 | } | ||
| 2931 | if (predictedFocusOwner != null) { | ||
| 2932 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 2933 | dequeueKeyEvents(time, predictedFocusOwner); | ||
| 2934 | } | ||
| 2935 | } | ||
| 2936 | |||
| 2937 | private void stopLWModal() { | ||
| 2938 | synchronized (getTreeLock()) { | ||
| 2939 | if (modalAppContext != null) { | ||
| 2940 | Container nativeContainer = getHeavyweightContainer(); | ||
| 2941 | if(nativeContainer != null) { | ||
| 2942 | if (this.modalComp != null) { | ||
| 2943 | nativeContainer.modalComp = this.modalComp; | ||
| 2944 | this.modalComp = null; | ||
| 2945 | return; | ||
| 2946 | } | ||
| 2947 | else { | ||
| 2948 | nativeContainer.modalComp = null; | ||
| 2949 | } | ||
| 2950 | } | ||
| 2951 | // Wake up event dispatch thread on which the dialog was | ||
| 2952 | // initially shown | ||
| 2953 | SunToolkit.postEvent(modalAppContext, | ||
| 2954 | new PeerEvent(this, | ||
| 2955 | new WakingRunnable(), | ||
| 2956 | PeerEvent.PRIORITY_EVENT)); | ||
| 2957 | } | ||
| 2958 | EventQueue.invokeLater(new WakingRunnable()); | ||
| 2959 | getTreeLock().notifyAll(); | ||
| 2960 | } | ||
| 2961 | } | ||
| 2962 | |||
| 2963 | final static class WakingRunnable implements Runnable { | ||
| 2964 | public void run() { | ||
| 2965 | } | ||
| 2966 | } | ||
| 2967 | |||
| 2968 | /* End of JOptionPane support code */ | ||
| 2969 | |||
| 2970 | /** | ||
| 2971 | * Returns a string representing the state of this <code>Container</code>. | ||
| 2972 | * This method is intended to be used only for debugging purposes, and the | ||
| 2973 | * content and format of the returned string may vary between | ||
| 2974 | * implementations. The returned string may be empty but may not be | ||
| 2975 | * <code>null</code>. | ||
| 2976 | * | ||
| 2977 | * @return the parameter string of this container | ||
| 2978 | */ | ||
| 2979 | protected String paramString() { | ||
| 2980 | String str = super.paramString(); | ||
| 2981 | LayoutManager layoutMgr = this.layoutMgr; | ||
| 2982 | if (layoutMgr != null) { | ||
| 2983 | str += ",layout=" + layoutMgr.getClass().getName(); | ||
| 2984 | } | ||
| 2985 | return str; | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | /** | ||
| 2989 | * Prints a listing of this container to the specified output | ||
| 2990 | * stream. The listing starts at the specified indentation. | ||
| 2991 | * <p> | ||
| 2992 | * The immediate children of the container are printed with | ||
| 2993 | * an indentation of <code>indent+1</code>. The children | ||
| 2994 | * of those children are printed at <code>indent+2</code> | ||
| 2995 | * and so on. | ||
| 2996 | * | ||
| 2997 | * @param out a print stream | ||
| 2998 | * @param indent the number of spaces to indent | ||
| 2999 | * @throws NullPointerException if {@code out} is {@code null} | ||
| 3000 | * @see Component#list(java.io.PrintStream, int) | ||
| 3001 | * @since JDK1.0 | ||
| 3002 | */ | ||
| 3003 | public void list(PrintStream out, int indent) { | ||
| 3004 | super.list(out, indent); | ||
| 3005 | synchronized(getTreeLock()) { | ||
| 3006 | for (int i = 0; i < component.size(); i++) { | ||
| 3007 | Component comp = component.get(i); | ||
| 3008 | if (comp != null) { | ||
| 3009 | comp.list(out, indent+1); | ||
| 3010 | } | ||
| 3011 | } | ||
| 3012 | } | ||
| 3013 | } | ||
| 3014 | |||
| 3015 | /** | ||
| 3016 | * Prints out a list, starting at the specified indentation, | ||
| 3017 | * to the specified print writer. | ||
| 3018 | * <p> | ||
| 3019 | * The immediate children of the container are printed with | ||
| 3020 | * an indentation of <code>indent+1</code>. The children | ||
| 3021 | * of those children are printed at <code>indent+2</code> | ||
| 3022 | * and so on. | ||
| 3023 | * | ||
| 3024 | * @param out a print writer | ||
| 3025 | * @param indent the number of spaces to indent | ||
| 3026 | * @throws NullPointerException if {@code out} is {@code null} | ||
| 3027 | * @see Component#list(java.io.PrintWriter, int) | ||
| 3028 | * @since JDK1.1 | ||
| 3029 | */ | ||
| 3030 | public void list(PrintWriter out, int indent) { | ||
| 3031 | super.list(out, indent); | ||
| 3032 | synchronized(getTreeLock()) { | ||
| 3033 | for (int i = 0; i < component.size(); i++) { | ||
| 3034 | Component comp = component.get(i); | ||
| 3035 | if (comp != null) { | ||
| 3036 | comp.list(out, indent+1); | ||
| 3037 | } | ||
| 3038 | } | ||
| 3039 | } | ||
| 3040 | } | ||
| 3041 | |||
| 3042 | /** | ||
| 3043 | * Sets the focus traversal keys for a given traversal operation for this | ||
| 3044 | * Container. | ||
| 3045 | * <p> | ||
| 3046 | * The default values for a Container's focus traversal keys are | ||
| 3047 | * implementation-dependent. Sun recommends that all implementations for a | ||
| 3048 | * particular native platform use the same default values. The | ||
| 3049 | * recommendations for Windows and Unix are listed below. These | ||
| 3050 | * recommendations are used in the Sun AWT implementations. | ||
| 3051 | * | ||
| 3052 | * <table border=1 summary="Recommended default values for a Container's focus traversal keys"> | ||
| 3053 | * <tr> | ||
| 3054 | * <th>Identifier</th> | ||
| 3055 | * <th>Meaning</th> | ||
| 3056 | * <th>Default</th> | ||
| 3057 | * </tr> | ||
| 3058 | * <tr> | ||
| 3059 | * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td> | ||
| 3060 | * <td>Normal forward keyboard traversal</td> | ||
| 3061 | * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td> | ||
| 3062 | * </tr> | ||
| 3063 | * <tr> | ||
| 3064 | * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td> | ||
| 3065 | * <td>Normal reverse keyboard traversal</td> | ||
| 3066 | * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td> | ||
| 3067 | * </tr> | ||
| 3068 | * <tr> | ||
| 3069 | * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td> | ||
| 3070 | * <td>Go up one focus traversal cycle</td> | ||
| 3071 | * <td>none</td> | ||
| 3072 | * </tr> | ||
| 3073 | * <tr> | ||
| 3074 | * <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td> | ||
| 3075 | * <td>Go down one focus traversal cycle</td> | ||
| 3076 | * <td>none</td> | ||
| 3077 | * </tr> | ||
| 3078 | * </table> | ||
| 3079 | * | ||
| 3080 | * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is | ||
| 3081 | * recommended. | ||
| 3082 | * <p> | ||
| 3083 | * Using the AWTKeyStroke API, client code can specify on which of two | ||
| 3084 | * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal | ||
| 3085 | * operation will occur. Regardless of which KeyEvent is specified, | ||
| 3086 | * however, all KeyEvents related to the focus traversal key, including the | ||
| 3087 | * associated KEY_TYPED event, will be consumed, and will not be dispatched | ||
| 3088 | * to any Container. It is a runtime error to specify a KEY_TYPED event as | ||
| 3089 | * mapping to a focus traversal operation, or to map the same event to | ||
| 3090 | * multiple default focus traversal operations. | ||
| 3091 | * <p> | ||
| 3092 | * If a value of null is specified for the Set, this Container inherits the | ||
| 3093 | * Set from its parent. If all ancestors of this Container have null | ||
| 3094 | * specified for the Set, then the current KeyboardFocusManager's default | ||
| 3095 | * Set is used. | ||
| 3096 | * | ||
| 3097 | * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3098 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3099 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3100 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3101 | * @param keystrokes the Set of AWTKeyStroke for the specified operation | ||
| 3102 | * @see #getFocusTraversalKeys | ||
| 3103 | * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS | ||
| 3104 | * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS | ||
| 3105 | * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS | ||
| 3106 | * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3107 | * @throws IllegalArgumentException if id is not one of | ||
| 3108 | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3109 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3110 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3111 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes | ||
| 3112 | * contains null, or if any Object in keystrokes is not an | ||
| 3113 | * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, | ||
| 3114 | * or if any keystroke already maps to another focus traversal | ||
| 3115 | * operation for this Container | ||
| 3116 | * @since 1.4 | ||
| 3117 | * @beaninfo | ||
| 3118 | * bound: true | ||
| 3119 | */ | ||
| 3120 | public void setFocusTraversalKeys(int id, | ||
| 3121 | Set<? extends AWTKeyStroke> keystrokes) | ||
| 3122 | { | ||
| 3123 | if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { | ||
| 3124 | throw new IllegalArgumentException("invalid focus traversal key identifier"); | ||
| 3125 | } | ||
| 3126 | |||
| 3127 | // Don't call super.setFocusTraversalKey. The Component parameter check | ||
| 3128 | // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do. | ||
| 3129 | setFocusTraversalKeys_NoIDCheck(id, keystrokes); | ||
| 3130 | } | ||
| 3131 | |||
| 3132 | /** | ||
| 3133 | * Returns the Set of focus traversal keys for a given traversal operation | ||
| 3134 | * for this Container. (See | ||
| 3135 | * <code>setFocusTraversalKeys</code> for a full description of each key.) | ||
| 3136 | * <p> | ||
| 3137 | * If a Set of traversal keys has not been explicitly defined for this | ||
| 3138 | * Container, then this Container's parent's Set is returned. If no Set | ||
| 3139 | * has been explicitly defined for any of this Container's ancestors, then | ||
| 3140 | * the current KeyboardFocusManager's default Set is returned. | ||
| 3141 | * | ||
| 3142 | * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3143 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3144 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3145 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3146 | * @return the Set of AWTKeyStrokes for the specified operation. The Set | ||
| 3147 | * will be unmodifiable, and may be empty. null will never be | ||
| 3148 | * returned. | ||
| 3149 | * @see #setFocusTraversalKeys | ||
| 3150 | * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS | ||
| 3151 | * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS | ||
| 3152 | * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS | ||
| 3153 | * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3154 | * @throws IllegalArgumentException if id is not one of | ||
| 3155 | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3156 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3157 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3158 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3159 | * @since 1.4 | ||
| 3160 | */ | ||
| 3161 | public Set<AWTKeyStroke> getFocusTraversalKeys(int id) { | ||
| 3162 | if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { | ||
| 3163 | throw new IllegalArgumentException("invalid focus traversal key identifier"); | ||
| 3164 | } | ||
| 3165 | |||
| 3166 | // Don't call super.getFocusTraversalKey. The Component parameter check | ||
| 3167 | // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do. | ||
| 3168 | return getFocusTraversalKeys_NoIDCheck(id); | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | /** | ||
| 3172 | * Returns whether the Set of focus traversal keys for the given focus | ||
| 3173 | * traversal operation has been explicitly defined for this Container. If | ||
| 3174 | * this method returns <code>false</code>, this Container is inheriting the | ||
| 3175 | * Set from an ancestor, or from the current KeyboardFocusManager. | ||
| 3176 | * | ||
| 3177 | * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3178 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3179 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3180 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3181 | * @return <code>true</code> if the the Set of focus traversal keys for the | ||
| 3182 | * given focus traversal operation has been explicitly defined for | ||
| 3183 | * this Component; <code>false</code> otherwise. | ||
| 3184 | * @throws IllegalArgumentException if id is not one of | ||
| 3185 | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | ||
| 3186 | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | ||
| 3187 | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or | ||
| 3188 | * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3189 | * @since 1.4 | ||
| 3190 | */ | ||
| 3191 | public boolean areFocusTraversalKeysSet(int id) { | ||
| 3192 | if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { | ||
| 3193 | throw new IllegalArgumentException("invalid focus traversal key identifier"); | ||
| 3194 | } | ||
| 3195 | |||
| 3196 | return (focusTraversalKeys != null && focusTraversalKeys[id] != null); | ||
| 3197 | } | ||
| 3198 | |||
| 3199 | /** | ||
| 3200 | * Returns whether the specified Container is the focus cycle root of this | ||
| 3201 | * Container's focus traversal cycle. Each focus traversal cycle has only | ||
| 3202 | * a single focus cycle root and each Container which is not a focus cycle | ||
| 3203 | * root belongs to only a single focus traversal cycle. Containers which | ||
| 3204 | * are focus cycle roots belong to two cycles: one rooted at the Container | ||
| 3205 | * itself, and one rooted at the Container's nearest focus-cycle-root | ||
| 3206 | * ancestor. This method will return <code>true</code> for both such | ||
| 3207 | * Containers in this case. | ||
| 3208 | * | ||
| 3209 | * @param container the Container to be tested | ||
| 3210 | * @return <code>true</code> if the specified Container is a focus-cycle- | ||
| 3211 | * root of this Container; <code>false</code> otherwise | ||
| 3212 | * @see #isFocusCycleRoot() | ||
| 3213 | * @since 1.4 | ||
| 3214 | */ | ||
| 3215 | public boolean isFocusCycleRoot(Container container) { | ||
| 3216 | if (isFocusCycleRoot() && container == this) { | ||
| 3217 | return true; | ||
| 3218 | } else { | ||
| 3219 | return super.isFocusCycleRoot(container); | ||
| 3220 | } | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | private Container findTraversalRoot() { | ||
| 3224 | // I potentially have two roots, myself and my root parent | ||
| 3225 | // If I am the current root, then use me | ||
| 3226 | // If none of my parents are roots, then use me | ||
| 3227 | // If my root parent is the current root, then use my root parent | ||
| 3228 | // If neither I nor my root parent is the current root, then | ||
| 3229 | // use my root parent (a guess) | ||
| 3230 | |||
| 3231 | Container currentFocusCycleRoot = KeyboardFocusManager. | ||
| 3232 | getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot(); | ||
| 3233 | Container root; | ||
| 3234 | |||
| 3235 | if (currentFocusCycleRoot == this) { | ||
| 3236 | root = this; | ||
| 3237 | } else { | ||
| 3238 | root = getFocusCycleRootAncestor(); | ||
| 3239 | if (root == null) { | ||
| 3240 | root = this; | ||
| 3241 | } | ||
| 3242 | } | ||
| 3243 | |||
| 3244 | if (root != currentFocusCycleRoot) { | ||
| 3245 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 3246 | setGlobalCurrentFocusCycleRoot(root); | ||
| 3247 | } | ||
| 3248 | return root; | ||
| 3249 | } | ||
| 3250 | |||
| 3251 | final boolean containsFocus() { | ||
| 3252 | final Component focusOwner = KeyboardFocusManager. | ||
| 3253 | getCurrentKeyboardFocusManager().getFocusOwner(); | ||
| 3254 | return isParentOf(focusOwner); | ||
| 3255 | } | ||
| 3256 | |||
| 3257 | /** | ||
| 3258 | * Check if this component is the child of this container or its children. | ||
| 3259 | * Note: this function acquires treeLock | ||
| 3260 | * Note: this function traverses children tree only in one Window. | ||
| 3261 | * @param comp a component in test, must not be null | ||
| 3262 | */ | ||
| 3263 | private boolean isParentOf(Component comp) { | ||
| 3264 | synchronized(getTreeLock()) { | ||
| 3265 | while (comp != null && comp != this && !(comp instanceof Window)) { | ||
| 3266 | comp = comp.getParent(); | ||
| 3267 | } | ||
| 3268 | return (comp == this); | ||
| 3269 | } | ||
| 3270 | } | ||
| 3271 | |||
| 3272 | void clearMostRecentFocusOwnerOnHide() { | ||
| 3273 | boolean reset = false; | ||
| 3274 | Window window = null; | ||
| 3275 | |||
| 3276 | synchronized (getTreeLock()) { | ||
| 3277 | window = getContainingWindow(); | ||
| 3278 | if (window != null) { | ||
| 3279 | Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window); | ||
| 3280 | reset = ((comp == this) || isParentOf(comp)); | ||
| 3281 | // This synchronized should always be the second in a pair | ||
| 3282 | // (tree lock, KeyboardFocusManager.class) | ||
| 3283 | synchronized(KeyboardFocusManager.class) { | ||
| 3284 | Component storedComp = window.getTemporaryLostComponent(); | ||
| 3285 | if (isParentOf(storedComp) || storedComp == this) { | ||
| 3286 | window.setTemporaryLostComponent(null); | ||
| 3287 | } | ||
| 3288 | } | ||
| 3289 | } | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | if (reset) { | ||
| 3293 | KeyboardFocusManager.setMostRecentFocusOwner(window, null); | ||
| 3294 | } | ||
| 3295 | } | ||
| 3296 | |||
| 3297 | void clearCurrentFocusCycleRootOnHide() { | ||
| 3298 | KeyboardFocusManager kfm = | ||
| 3299 | KeyboardFocusManager.getCurrentKeyboardFocusManager(); | ||
| 3300 | Container cont = kfm.getCurrentFocusCycleRoot(); | ||
| 3301 | |||
| 3302 | if (cont == this || isParentOf(cont)) { | ||
| 3303 | kfm.setGlobalCurrentFocusCycleRoot(null); | ||
| 3304 | } | ||
| 3305 | } | ||
| 3306 | |||
| 3307 | final Container getTraversalRoot() { | ||
| 3308 | if (isFocusCycleRoot()) { | ||
| 3309 | return findTraversalRoot(); | ||
| 3310 | } | ||
| 3311 | |||
| 3312 | return super.getTraversalRoot(); | ||
| 3313 | } | ||
| 3314 | |||
| 3315 | /** | ||
| 3316 | * Sets the focus traversal policy that will manage keyboard traversal of | ||
| 3317 | * this Container's children, if this Container is a focus cycle root. If | ||
| 3318 | * the argument is null, this Container inherits its policy from its focus- | ||
| 3319 | * cycle-root ancestor. If the argument is non-null, this policy will be | ||
| 3320 | * inherited by all focus-cycle-root children that have no keyboard- | ||
| 3321 | * traversal policy of their own (as will, recursively, their focus-cycle- | ||
| 3322 | * root children). | ||
| 3323 | * <p> | ||
| 3324 | * If this Container is not a focus cycle root, the policy will be | ||
| 3325 | * remembered, but will not be used or inherited by this or any other | ||
| 3326 | * Containers until this Container is made a focus cycle root. | ||
| 3327 | * | ||
| 3328 | * @param policy the new focus traversal policy for this Container | ||
| 3329 | * @see #getFocusTraversalPolicy | ||
| 3330 | * @see #setFocusCycleRoot | ||
| 3331 | * @see #isFocusCycleRoot | ||
| 3332 | * @since 1.4 | ||
| 3333 | * @beaninfo | ||
| 3334 | * bound: true | ||
| 3335 | */ | ||
| 3336 | public void setFocusTraversalPolicy(FocusTraversalPolicy policy) { | ||
| 3337 | FocusTraversalPolicy oldPolicy; | ||
| 3338 | synchronized (this) { | ||
| 3339 | oldPolicy = this.focusTraversalPolicy; | ||
| 3340 | this.focusTraversalPolicy = policy; | ||
| 3341 | } | ||
| 3342 | firePropertyChange("focusTraversalPolicy", oldPolicy, policy); | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | /** | ||
| 3346 | * Returns the focus traversal policy that will manage keyboard traversal | ||
| 3347 | * of this Container's children, or null if this Container is not a focus | ||
| 3348 | * cycle root. If no traversal policy has been explicitly set for this | ||
| 3349 | * Container, then this Container's focus-cycle-root ancestor's policy is | ||
| 3350 | * returned. | ||
| 3351 | * | ||
| 3352 | * @return this Container's focus traversal policy, or null if this | ||
| 3353 | * Container is not a focus cycle root. | ||
| 3354 | * @see #setFocusTraversalPolicy | ||
| 3355 | * @see #setFocusCycleRoot | ||
| 3356 | * @see #isFocusCycleRoot | ||
| 3357 | * @since 1.4 | ||
| 3358 | */ | ||
| 3359 | public FocusTraversalPolicy getFocusTraversalPolicy() { | ||
| 3360 | if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) { | ||
| 3361 | return null; | ||
| 3362 | } | ||
| 3363 | |||
| 3364 | FocusTraversalPolicy policy = this.focusTraversalPolicy; | ||
| 3365 | if (policy != null) { | ||
| 3366 | return policy; | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | Container rootAncestor = getFocusCycleRootAncestor(); | ||
| 3370 | if (rootAncestor != null) { | ||
| 3371 | return rootAncestor.getFocusTraversalPolicy(); | ||
| 3372 | } else { | ||
| 3373 | return KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 3374 | getDefaultFocusTraversalPolicy(); | ||
| 3375 | } | ||
| 3376 | } | ||
| 3377 | |||
| 3378 | /** | ||
| 3379 | * Returns whether the focus traversal policy has been explicitly set for | ||
| 3380 | * this Container. If this method returns <code>false</code>, this | ||
| 3381 | * Container will inherit its focus traversal policy from an ancestor. | ||
| 3382 | * | ||
| 3383 | * @return <code>true</code> if the focus traversal policy has been | ||
| 3384 | * explicitly set for this Container; <code>false</code> otherwise. | ||
| 3385 | * @since 1.4 | ||
| 3386 | */ | ||
| 3387 | public boolean isFocusTraversalPolicySet() { | ||
| 3388 | return (focusTraversalPolicy != null); | ||
| 3389 | } | ||
| 3390 | |||
| 3391 | /** | ||
| 3392 | * Sets whether this Container is the root of a focus traversal cycle. Once | ||
| 3393 | * focus enters a traversal cycle, typically it cannot leave it via focus | ||
| 3394 | * traversal unless one of the up- or down-cycle keys is pressed. Normal | ||
| 3395 | * traversal is limited to this Container, and all of this Container's | ||
| 3396 | * descendants that are not descendants of inferior focus cycle roots. Note | ||
| 3397 | * that a FocusTraversalPolicy may bend these restrictions, however. For | ||
| 3398 | * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle | ||
| 3399 | * traversal. | ||
| 3400 | * <p> | ||
| 3401 | * The alternative way to specify the traversal order of this Container's | ||
| 3402 | * children is to make this Container a | ||
| 3403 | * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>. | ||
| 3404 | * | ||
| 3405 | * @param focusCycleRoot indicates whether this Container is the root of a | ||
| 3406 | * focus traversal cycle | ||
| 3407 | * @see #isFocusCycleRoot() | ||
| 3408 | * @see #setFocusTraversalPolicy | ||
| 3409 | * @see #getFocusTraversalPolicy | ||
| 3410 | * @see ContainerOrderFocusTraversalPolicy | ||
| 3411 | * @see #setFocusTraversalPolicyProvider | ||
| 3412 | * @since 1.4 | ||
| 3413 | * @beaninfo | ||
| 3414 | * bound: true | ||
| 3415 | */ | ||
| 3416 | public void setFocusCycleRoot(boolean focusCycleRoot) { | ||
| 3417 | boolean oldFocusCycleRoot; | ||
| 3418 | synchronized (this) { | ||
| 3419 | oldFocusCycleRoot = this.focusCycleRoot; | ||
| 3420 | this.focusCycleRoot = focusCycleRoot; | ||
| 3421 | } | ||
| 3422 | firePropertyChange("focusCycleRoot", oldFocusCycleRoot, | ||
| 3423 | focusCycleRoot); | ||
| 3424 | } | ||
| 3425 | |||
| 3426 | /** | ||
| 3427 | * Returns whether this Container is the root of a focus traversal cycle. | ||
| 3428 | * Once focus enters a traversal cycle, typically it cannot leave it via | ||
| 3429 | * focus traversal unless one of the up- or down-cycle keys is pressed. | ||
| 3430 | * Normal traversal is limited to this Container, and all of this | ||
| 3431 | * Container's descendants that are not descendants of inferior focus | ||
| 3432 | * cycle roots. Note that a FocusTraversalPolicy may bend these | ||
| 3433 | * restrictions, however. For example, ContainerOrderFocusTraversalPolicy | ||
| 3434 | * supports implicit down-cycle traversal. | ||
| 3435 | * | ||
| 3436 | * @return whether this Container is the root of a focus traversal cycle | ||
| 3437 | * @see #setFocusCycleRoot | ||
| 3438 | * @see #setFocusTraversalPolicy | ||
| 3439 | * @see #getFocusTraversalPolicy | ||
| 3440 | * @see ContainerOrderFocusTraversalPolicy | ||
| 3441 | * @since 1.4 | ||
| 3442 | */ | ||
| 3443 | public boolean isFocusCycleRoot() { | ||
| 3444 | return focusCycleRoot; | ||
| 3445 | } | ||
| 3446 | |||
| 3447 | /** | ||
| 3448 | * Sets whether this container will be used to provide focus | ||
| 3449 | * traversal policy. Container with this property as | ||
| 3450 | * <code>true</code> will be used to acquire focus traversal policy | ||
| 3451 | * instead of closest focus cycle root ancestor. | ||
| 3452 | * @param provider indicates whether this container will be used to | ||
| 3453 | * provide focus traversal policy | ||
| 3454 | * @see #setFocusTraversalPolicy | ||
| 3455 | * @see #getFocusTraversalPolicy | ||
| 3456 | * @see #isFocusTraversalPolicyProvider | ||
| 3457 | * @since 1.5 | ||
| 3458 | * @beaninfo | ||
| 3459 | * bound: true | ||
| 3460 | */ | ||
| 3461 | public final void setFocusTraversalPolicyProvider(boolean provider) { | ||
| 3462 | boolean oldProvider; | ||
| 3463 | synchronized(this) { | ||
| 3464 | oldProvider = focusTraversalPolicyProvider; | ||
| 3465 | focusTraversalPolicyProvider = provider; | ||
| 3466 | } | ||
| 3467 | firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider); | ||
| 3468 | } | ||
| 3469 | |||
| 3470 | /** | ||
| 3471 | * Returns whether this container provides focus traversal | ||
| 3472 | * policy. If this property is set to <code>true</code> then when | ||
| 3473 | * keyboard focus manager searches container hierarchy for focus | ||
| 3474 | * traversal policy and encounters this container before any other | ||
| 3475 | * container with this property as true or focus cycle roots then | ||
| 3476 | * its focus traversal policy will be used instead of focus cycle | ||
| 3477 | * root's policy. | ||
| 3478 | * @see #setFocusTraversalPolicy | ||
| 3479 | * @see #getFocusTraversalPolicy | ||
| 3480 | * @see #setFocusCycleRoot | ||
| 3481 | * @see #setFocusTraversalPolicyProvider | ||
| 3482 | * @return <code>true</code> if this container provides focus traversal | ||
| 3483 | * policy, <code>false</code> otherwise | ||
| 3484 | * @since 1.5 | ||
| 3485 | * @beaninfo | ||
| 3486 | * bound: true | ||
| 3487 | */ | ||
| 3488 | public final boolean isFocusTraversalPolicyProvider() { | ||
| 3489 | return focusTraversalPolicyProvider; | ||
| 3490 | } | ||
| 3491 | |||
| 3492 | /** | ||
| 3493 | * Transfers the focus down one focus traversal cycle. If this Container is | ||
| 3494 | * a focus cycle root, then the focus owner is set to this Container's | ||
| 3495 | * default Component to focus, and the current focus cycle root is set to | ||
| 3496 | * this Container. If this Container is not a focus cycle root, then no | ||
| 3497 | * focus traversal operation occurs. | ||
| 3498 | * | ||
| 3499 | * @see Component#requestFocus() | ||
| 3500 | * @see #isFocusCycleRoot | ||
| 3501 | * @see #setFocusCycleRoot | ||
| 3502 | * @since 1.4 | ||
| 3503 | */ | ||
| 3504 | public void transferFocusDownCycle() { | ||
| 3505 | if (isFocusCycleRoot()) { | ||
| 3506 | KeyboardFocusManager.getCurrentKeyboardFocusManager(). | ||
| 3507 | setGlobalCurrentFocusCycleRoot(this); | ||
| 3508 | Component toFocus = getFocusTraversalPolicy(). | ||
| 3509 | getDefaultComponent(this); | ||
| 3510 | if (toFocus != null) { | ||
| 3511 | toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN); | ||
| 3512 | } | ||
| 3513 | } | ||
| 3514 | } | ||
| 3515 | |||
| 3516 | void preProcessKeyEvent(KeyEvent e) { | ||
| 3517 | Container parent = this.parent; | ||
| 3518 | if (parent != null) { | ||
| 3519 | parent.preProcessKeyEvent(e); | ||
| 3520 | } | ||
| 3521 | } | ||
| 3522 | |||
| 3523 | void postProcessKeyEvent(KeyEvent e) { | ||
| 3524 | Container parent = this.parent; | ||
| 3525 | if (parent != null) { | ||
| 3526 | parent.postProcessKeyEvent(e); | ||
| 3527 | } | ||
| 3528 | } | ||
| 3529 | |||
| 3530 | boolean postsOldMouseEvents() { | ||
| 3531 | return true; | ||
| 3532 | } | ||
| 3533 | |||
| 3534 | /** | ||
| 3535 | * Sets the <code>ComponentOrientation</code> property of this container | ||
| 3536 | * and all components contained within it. | ||
| 3537 | * <p> | ||
| 3538 | * This method changes layout-related information, and therefore, | ||
| 3539 | * invalidates the component hierarchy. | ||
| 3540 | * | ||
| 3541 | * @param o the new component orientation of this container and | ||
| 3542 | * the components contained within it. | ||
| 3543 | * @exception NullPointerException if <code>orientation</code> is null. | ||
| 3544 | * @see Component#setComponentOrientation | ||
| 3545 | * @see Component#getComponentOrientation | ||
| 3546 | * @see #invalidate | ||
| 3547 | * @since 1.4 | ||
| 3548 | */ | ||
| 3549 | public void applyComponentOrientation(ComponentOrientation o) { | ||
| 3550 | super.applyComponentOrientation(o); | ||
| 3551 | synchronized (getTreeLock()) { | ||
| 3552 | for (int i = 0; i < component.size(); i++) { | ||
| 3553 | Component comp = component.get(i); | ||
| 3554 | comp.applyComponentOrientation(o); | ||
| 3555 | } | ||
| 3556 | } | ||
| 3557 | } | ||
| 3558 | |||
| 3559 | /** | ||
| 3560 | * Adds a PropertyChangeListener to the listener list. The listener is | ||
| 3561 | * registered for all bound properties of this class, including the | ||
| 3562 | * following: | ||
| 3563 | * <ul> | ||
| 3564 | * <li>this Container's font ("font")</li> | ||
| 3565 | * <li>this Container's background color ("background")</li> | ||
| 3566 | * <li>this Container's foreground color ("foreground")</li> | ||
| 3567 | * <li>this Container's focusability ("focusable")</li> | ||
| 3568 | * <li>this Container's focus traversal keys enabled state | ||
| 3569 | * ("focusTraversalKeysEnabled")</li> | ||
| 3570 | * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS | ||
| 3571 | * ("forwardFocusTraversalKeys")</li> | ||
| 3572 | * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS | ||
| 3573 | * ("backwardFocusTraversalKeys")</li> | ||
| 3574 | * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS | ||
| 3575 | * ("upCycleFocusTraversalKeys")</li> | ||
| 3576 | * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3577 | * ("downCycleFocusTraversalKeys")</li> | ||
| 3578 | * <li>this Container's focus traversal policy ("focusTraversalPolicy") | ||
| 3579 | * </li> | ||
| 3580 | * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li> | ||
| 3581 | * </ul> | ||
| 3582 | * Note that if this Container is inheriting a bound property, then no | ||
| 3583 | * event will be fired in response to a change in the inherited property. | ||
| 3584 | * <p> | ||
| 3585 | * If listener is null, no exception is thrown and no action is performed. | ||
| 3586 | * | ||
| 3587 | * @param listener the PropertyChangeListener to be added | ||
| 3588 | * | ||
| 3589 | * @see Component#removePropertyChangeListener | ||
| 3590 | * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) | ||
| 3591 | */ | ||
| 3592 | public void addPropertyChangeListener(PropertyChangeListener listener) { | ||
| 3593 | super.addPropertyChangeListener(listener); | ||
| 3594 | } | ||
| 3595 | |||
| 3596 | /** | ||
| 3597 | * Adds a PropertyChangeListener to the listener list for a specific | ||
| 3598 | * property. The specified property may be user-defined, or one of the | ||
| 3599 | * following defaults: | ||
| 3600 | * <ul> | ||
| 3601 | * <li>this Container's font ("font")</li> | ||
| 3602 | * <li>this Container's background color ("background")</li> | ||
| 3603 | * <li>this Container's foreground color ("foreground")</li> | ||
| 3604 | * <li>this Container's focusability ("focusable")</li> | ||
| 3605 | * <li>this Container's focus traversal keys enabled state | ||
| 3606 | * ("focusTraversalKeysEnabled")</li> | ||
| 3607 | * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS | ||
| 3608 | * ("forwardFocusTraversalKeys")</li> | ||
| 3609 | * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS | ||
| 3610 | * ("backwardFocusTraversalKeys")</li> | ||
| 3611 | * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS | ||
| 3612 | * ("upCycleFocusTraversalKeys")</li> | ||
| 3613 | * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS | ||
| 3614 | * ("downCycleFocusTraversalKeys")</li> | ||
| 3615 | * <li>this Container's focus traversal policy ("focusTraversalPolicy") | ||
| 3616 | * </li> | ||
| 3617 | * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li> | ||
| 3618 | * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li> | ||
| 3619 | * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li> | ||
| 3620 | * </ul> | ||
| 3621 | * Note that if this Container is inheriting a bound property, then no | ||
| 3622 | * event will be fired in response to a change in the inherited property. | ||
| 3623 | * <p> | ||
| 3624 | * If listener is null, no exception is thrown and no action is performed. | ||
| 3625 | * | ||
| 3626 | * @param propertyName one of the property names listed above | ||
| 3627 | * @param listener the PropertyChangeListener to be added | ||
| 3628 | * | ||
| 3629 | * @see #addPropertyChangeListener(java.beans.PropertyChangeListener) | ||
| 3630 | * @see Component#removePropertyChangeListener | ||
| 3631 | */ | ||
| 3632 | public void addPropertyChangeListener(String propertyName, | ||
| 3633 | PropertyChangeListener listener) { | ||
| 3634 | super.addPropertyChangeListener(propertyName, listener); | ||
| 3635 | } | ||
| 3636 | |||
| 3637 | // Serialization support. A Container is responsible for restoring the | ||
| 3638 | // parent fields of its component children. | ||
| 3639 | |||
| 3640 | /** | ||
| 3641 | * Container Serial Data Version. | ||
| 3642 | */ | ||
| 3643 | private int containerSerializedDataVersion = 1; | ||
| 3644 | |||
| 3645 | /** | ||
| 3646 | * Serializes this <code>Container</code> to the specified | ||
| 3647 | * <code>ObjectOutputStream</code>. | ||
| 3648 | * <ul> | ||
| 3649 | * <li>Writes default serializable fields to the stream.</li> | ||
| 3650 | * <li>Writes a list of serializable ContainerListener(s) as optional | ||
| 3651 | * data. The non-serializable ContainerListner(s) are detected and | ||
| 3652 | * no attempt is made to serialize them.</li> | ||
| 3653 | * <li>Write this Container's FocusTraversalPolicy if and only if it | ||
| 3654 | * is Serializable; otherwise, <code>null</code> is written.</li> | ||
| 3655 | * </ul> | ||
| 3656 | * | ||
| 3657 | * @param s the <code>ObjectOutputStream</code> to write | ||
| 3658 | * @serialData <code>null</code> terminated sequence of 0 or more pairs; | ||
| 3659 | * the pair consists of a <code>String</code> and <code>Object</code>; | ||
| 3660 | * the <code>String</code> indicates the type of object and | ||
| 3661 | * is one of the following: | ||
| 3662 | * <code>containerListenerK</code> indicating an | ||
| 3663 | * <code>ContainerListener</code> object; | ||
| 3664 | * the <code>Container</code>'s <code>FocusTraversalPolicy</code>, | ||
| 3665 | * or <code>null</code> | ||
| 3666 | * | ||
| 3667 | * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener) | ||
| 3668 | * @see Container#containerListenerK | ||
| 3669 | * @see #readObject(ObjectInputStream) | ||
| 3670 | */ | ||
| 3671 | private void writeObject(ObjectOutputStream s) throws IOException { | ||
| 3672 | ObjectOutputStream.PutField f = s.putFields(); | ||
| 3673 | f.put("ncomponents", component.size()); | ||
| 3674 | f.put("component", getComponentsSync()); | ||
| 3675 | f.put("layoutMgr", layoutMgr); | ||
| 3676 | f.put("dispatcher", dispatcher); | ||
| 3677 | f.put("maxSize", maxSize); | ||
| 3678 | f.put("focusCycleRoot", focusCycleRoot); | ||
| 3679 | f.put("containerSerializedDataVersion", containerSerializedDataVersion); | ||
| 3680 | f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider); | ||
| 3681 | s.writeFields(); | ||
| 3682 | |||
| 3683 | AWTEventMulticaster.save(s, containerListenerK, containerListener); | ||
| 3684 | s.writeObject(null); | ||
| 3685 | |||
| 3686 | if (focusTraversalPolicy instanceof java.io.Serializable) { | ||
| 3687 | s.writeObject(focusTraversalPolicy); | ||
| 3688 | } else { | ||
| 3689 | s.writeObject(null); | ||
| 3690 | } | ||
| 3691 | } | ||
| 3692 | |||
| 3693 | /** | ||
| 3694 | * Deserializes this <code>Container</code> from the specified | ||
| 3695 | * <code>ObjectInputStream</code>. | ||
| 3696 | * <ul> | ||
| 3697 | * <li>Reads default serializable fields from the stream.</li> | ||
| 3698 | * <li>Reads a list of serializable ContainerListener(s) as optional | ||
| 3699 | * data. If the list is null, no Listeners are installed.</li> | ||
| 3700 | * <li>Reads this Container's FocusTraversalPolicy, which may be null, | ||
| 3701 | * as optional data.</li> | ||
| 3702 | * </ul> | ||
| 3703 | * | ||
| 3704 | * @param s the <code>ObjectInputStream</code> to read | ||
| 3705 | * @serial | ||
| 3706 | * @see #addContainerListener | ||
| 3707 | * @see #writeObject(ObjectOutputStream) | ||
| 3708 | */ | ||
| 3709 | private void readObject(ObjectInputStream s) | ||
| 3710 | throws ClassNotFoundException, IOException | ||
| 3711 | { | ||
| 3712 | ObjectInputStream.GetField f = s.readFields(); | ||
| 3713 | Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY); | ||
| 3714 | int ncomponents = (Integer) f.get("ncomponents", 0); | ||
| 3715 | component = new java.util.ArrayList<Component>(ncomponents); | ||
| 3716 | for (int i = 0; i < ncomponents; ++i) { | ||
| 3717 | component.add(tmpComponent[i]); | ||
| 3718 | } | ||
| 3719 | layoutMgr = (LayoutManager)f.get("layoutMgr", null); | ||
| 3720 | dispatcher = (LightweightDispatcher)f.get("dispatcher", null); | ||
| 3721 | // Old stream. Doesn't contain maxSize among Component's fields. | ||
| 3722 | if (maxSize == null) { | ||
| 3723 | maxSize = (Dimension)f.get("maxSize", null); | ||
| 3724 | } | ||
| 3725 | focusCycleRoot = f.get("focusCycleRoot", false); | ||
| 3726 | containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1); | ||
| 3727 | focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false); | ||
| 3728 | java.util.List<Component> component = this.component; | ||
| 3729 | for(Component comp : component) { | ||
| 3730 | comp.parent = this; | ||
| 3731 | adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, | ||
| 3732 | comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); | ||
| 3733 | adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | ||
| 3734 | comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); | ||
| 3735 | adjustDescendants(comp.countHierarchyMembers()); | ||
| 3736 | } | ||
| 3737 | |||
| 3738 | Object keyOrNull; | ||
| 3739 | while(null != (keyOrNull = s.readObject())) { | ||
| 3740 | String key = ((String)keyOrNull).intern(); | ||
| 3741 | |||
| 3742 | if (containerListenerK == key) { | ||
| 3743 | addContainerListener((ContainerListener)(s.readObject())); | ||
| 3744 | } else { | ||
| 3745 | // skip value for unrecognized key | ||
| 3746 | s.readObject(); | ||
| 3747 | } | ||
| 3748 | } | ||
| 3749 | |||
| 3750 | try { | ||
| 3751 | Object policy = s.readObject(); | ||
| 3752 | if (policy instanceof FocusTraversalPolicy) { | ||
| 3753 | focusTraversalPolicy = (FocusTraversalPolicy)policy; | ||
| 3754 | } | ||
| 3755 | } catch (java.io.OptionalDataException e) { | ||
| 3756 | // JDK 1.1/1.2/1.3 instances will not have this optional data. | ||
| 3757 | // e.eof will be true to indicate that there is no more data | ||
| 3758 | // available for this object. If e.eof is not true, throw the | ||
| 3759 | // exception as it might have been caused by reasons unrelated to | ||
| 3760 | // focusTraversalPolicy. | ||
| 3761 | |||
| 3762 | if (!e.eof) { | ||
| 3763 | throw e; | ||
| 3764 | } | ||
| 3765 | } | ||
| 3766 | } | ||
| 3767 | |||
| 3768 | /* | ||
| 3769 | * --- Accessibility Support --- | ||
| 3770 | */ | ||
| 3771 | |||
| 3772 | /** | ||
| 3773 | * Inner class of Container used to provide default support for | ||
| 3774 | * accessibility. This class is not meant to be used directly by | ||
| 3775 | * application developers, but is instead meant only to be | ||
| 3776 | * subclassed by container developers. | ||
| 3777 | * <p> | ||
| 3778 | * The class used to obtain the accessible role for this object, | ||
| 3779 | * as well as implementing many of the methods in the | ||
1125 more lines aren’t shown here.
Binary file not shown.
This diff is large: its 581 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 464 lines aren’t shown here.
Binary file not shown.
This diff is large: its 129 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1359 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 485 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1681 lines aren’t shown here.
Binary file not shown.
This diff is large: its 240 lines aren’t shown here.
Binary file not shown.
This diff is large: its 157 lines aren’t shown here.
Binary file not shown.
This diff is large: its 880 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 309 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 62 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1279 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 582 lines aren’t shown here.
Binary file not shown.
This diff is large: its 697 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 176 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2653 lines aren’t shown here.
Binary file not shown.
This diff is large: its 52 lines aren’t shown here.
Binary file not shown.
This diff is large: its 643 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1324 lines aren’t shown here.
Binary file not shown.
This diff is large: its 279 lines aren’t shown here.
Binary file not shown.
This diff is large: its 296 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1257 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1235 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 147 lines aren’t shown here.
Binary file not shown.
This diff is large: its 112 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 455 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 582 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 453 lines aren’t shown here.
Binary file not shown.
This diff is large: its 664 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 2229 lines aren’t shown here.
Binary file not shown.
This diff is large: its 88 lines aren’t shown here.
Binary file not shown.
This diff is large: its 482 lines aren’t shown here.
Binary file not shown.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 354 lines aren’t shown here.
Binary file not shown.
This diff is large: its 82 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 189 lines aren’t shown here.
Binary file not shown.
This diff is large: its 66 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1066 lines aren’t shown here.
Binary file not shown.
This diff is large: its 91 lines aren’t shown here.
Binary file not shown.
This diff is large: its 94 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 3066 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 361 lines aren’t shown here.
Binary file not shown.
This diff is large: its 84 lines aren’t shown here.
Binary file not shown.
This diff is large: its 88 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 385 lines aren’t shown here.
Binary file not shown.
This diff is large: its 166 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1950 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 950 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 623 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 501 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1062 lines aren’t shown here.
Binary file not shown.
This diff is large: its 44 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 920 lines aren’t shown here.
Binary file not shown.
This diff is large: its 209 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 217 lines aren’t shown here.
Binary file not shown.
This diff is large: its 136 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 312 lines aren’t shown here.
Binary file not shown.
This diff is large: its 725 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1379 lines aren’t shown here.
Binary file not shown.
This diff is large: its 109 lines aren’t shown here.
Binary file not shown.
This diff is large: its 82 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 134 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 235 lines aren’t shown here.
Binary file not shown.
This diff is large: its 85 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 678 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 241 lines aren’t shown here.
Binary file not shown.
This diff is large: its 42 lines aren’t shown here.
Binary file not shown.
This diff is large: its 81 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 647 lines aren’t shown here.
Binary file not shown.
This diff is large: its 450 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1217 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1301 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 594 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 850 lines aren’t shown here.
Binary file not shown.
This diff is large: its 446 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1338 lines aren’t shown here.
Binary file not shown.
This diff is large: its 148 lines aren’t shown here.
Binary file not shown.
This diff is large: its 92 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 214 lines aren’t shown here.
Binary file not shown.
This diff is large: its 415 lines aren’t shown here.
Binary file not shown.
This diff is large: its 401 lines aren’t shown here.
Binary file not shown.
This diff is large: its 69 lines aren’t shown here.
Binary file not shown.
This diff is large: its 544 lines aren’t shown here.
Binary file not shown.
This diff is large: its 505 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 715 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1232 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 762 lines aren’t shown here.
Binary file not shown.
This diff is large: its 152 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 828 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2609 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 781 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 303 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 4089 lines aren’t shown here.
Binary file not shown.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
This diff is large: its 612 lines aren’t shown here.
Binary file not shown.
This diff is large: its 617 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2074 lines aren’t shown here.
Binary file not shown.
This diff is large: its 151 lines aren’t shown here.
Binary file not shown.
This diff is large: its 283 lines aren’t shown here.
Binary file not shown.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 355 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1382 lines aren’t shown here.
Binary file not shown.
This diff is large: its 52 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 76 lines aren’t shown here.
Binary file not shown.
This diff is large: its 83 lines aren’t shown here.
Binary file not shown.
This diff is large: its 394 lines aren’t shown here.
Binary file not shown.
This diff is large: its 405 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 141 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1300 lines aren’t shown here.
Binary file not shown.
This diff is large: its 74 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
Binary file not shown.
This diff is large: its 81 lines aren’t shown here.
Binary file not shown.
This diff is large: its 84 lines aren’t shown here.
Binary file not shown.
This diff is large: its 232 lines aren’t shown here.
Binary file not shown.
This diff is large: its 385 lines aren’t shown here.
Binary file not shown.
This diff is large: its 65 lines aren’t shown here.
Binary file not shown.
This diff is large: its 467 lines aren’t shown here.
Binary file not shown.
This diff is large: its 923 lines aren’t shown here.
Binary file not shown.
This diff is large: its 143 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 635 lines aren’t shown here.
Binary file not shown.
This diff is large: its 329 lines aren’t shown here.
Binary file not shown.
This diff is large: its 169 lines aren’t shown here.
Binary file not shown.
This diff is large: its 186 lines aren’t shown here.
Binary file not shown.
This diff is large: its 127 lines aren’t shown here.
Binary file not shown.
This diff is large: its 62 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 859 lines aren’t shown here.
Binary file not shown.
This diff is large: its 110 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 421 lines aren’t shown here.
Binary file not shown.
This diff is large: its 244 lines aren’t shown here.
Binary file not shown.
This diff is large: its 301 lines aren’t shown here.
Binary file not shown.
This diff is large: its 82 lines aren’t shown here.
Binary file not shown.
This diff is large: its 153 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 209 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
Binary file not shown.
This diff is large: its 72 lines aren’t shown here.
Binary file not shown.
This diff is large: its 112 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 190 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 274 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 1368 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 473 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 3 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 82 lines aren’t shown here.
Binary file not shown.
This diff is large: its 289 lines aren’t shown here.
Binary file not shown.
This diff is large: its 53 lines aren’t shown here.
Binary file not shown.
This diff is large: its 290 lines aren’t shown here.
Binary file not shown.
This diff is large: its 44 lines aren’t shown here.
Binary file not shown.
This diff is large: its 73 lines aren’t shown here.
Binary file not shown.
This diff is large: its 166 lines aren’t shown here.
Binary file not shown.
This diff is large: its 75 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 160 lines aren’t shown here.
Binary file not shown.
This diff is large: its 67 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 250 lines aren’t shown here.
Binary file not shown.
This diff is large: its 62 lines aren’t shown here.
Binary file not shown.
This diff is large: its 62 lines aren’t shown here.
Binary file not shown.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 338 lines aren’t shown here.
Binary file not shown.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 528 lines aren’t shown here.
Binary file not shown.
This diff is large: its 417 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 352 lines aren’t shown here.
Binary file not shown.
This diff is large: its 203 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1670 lines aren’t shown here.
Binary file not shown.
This diff is large: its 74 lines aren’t shown here.
Binary file not shown.
This diff is large: its 114 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1172 lines aren’t shown here.
Binary file not shown.
This diff is large: its 85 lines aren’t shown here.
Binary file not shown.
This diff is large: its 72 lines aren’t shown here.
Binary file not shown.
This diff is large: its 76 lines aren’t shown here.
Binary file not shown.
This diff is large: its 448 lines aren’t shown here.
Binary file not shown.
This diff is large: its 59 lines aren’t shown here.
Binary file not shown.
This diff is large: its 60 lines aren’t shown here.
Binary file not shown.
This diff is large: its 140 lines aren’t shown here.
Binary file not shown.
This diff is large: its 114 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 118 lines aren’t shown here.
Binary file not shown.
This diff is large: its 429 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 104 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
This diff is large: its 194 lines aren’t shown here.
Binary file not shown.
This diff is large: its 359 lines aren’t shown here.
Binary file not shown.
This diff is large: its 213 lines aren’t shown here.
Binary file not shown.
This diff is large: its 325 lines aren’t shown here.
Binary file not shown.
This diff is large: its 612 lines aren’t shown here.
Binary file not shown.
This diff is large: its 222 lines aren’t shown here.
Binary file not shown.
This diff is large: its 228 lines aren’t shown here.
Binary file not shown.
This diff is large: its 85 lines aren’t shown here.
Binary file not shown.
This diff is large: its 534 lines aren’t shown here.
Binary file not shown.
This diff is large: its 144 lines aren’t shown here.
Binary file not shown.
This diff is large: its 107 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1508 lines aren’t shown here.
Binary file not shown.
This diff is large: its 433 lines aren’t shown here.
Binary file not shown.
This diff is large: its 257 lines aren’t shown here.
Binary file not shown.
This diff is large: its 493 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1118 lines aren’t shown here.
Binary file not shown.
This diff is large: its 248 lines aren’t shown here.
Binary file not shown.
This diff is large: its 241 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 2754 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1438 lines aren’t shown here.
Binary file not shown.
This diff is large: its 760 lines aren’t shown here.
Binary file not shown.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
Binary file not shown.
This diff is large: its 3924 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1475 lines aren’t shown here.
Binary file not shown.
This diff is large: its 313 lines aren’t shown here.
Binary file not shown.
This diff is large: its 745 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1576 lines aren’t shown here.
Binary file not shown.
This diff is large: its 157 lines aren’t shown here.
Binary file not shown.
This diff is large: its 115 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 465 lines aren’t shown here.
Binary file not shown.
This diff is large: its 190 lines aren’t shown here.
Binary file not shown.
This diff is large: its 396 lines aren’t shown here.
Binary file not shown.
This diff is large: its 128 lines aren’t shown here.
Binary file not shown.
This diff is large: its 57 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1129 lines aren’t shown here.
Binary file not shown.
This diff is large: its 149 lines aren’t shown here.
Binary file not shown.
This diff is large: its 47 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 2596 lines aren’t shown here.
Binary file not shown.
This diff is large: its 216 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 429 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 1402 lines aren’t shown here.
Binary file not shown.
This diff is large: its 153 lines aren’t shown here.
Binary file not shown.
This diff is large: its 157 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 931 lines aren’t shown here.
Binary file not shown.
This diff is large: its 398 lines aren’t shown here.
Binary file not shown.
This diff is large: its 190 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This diff is large: its 682 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
Binary file not shown.
This diff is large: its 340 lines aren’t shown here.
Binary file not shown.
This diff is large: its 196 lines aren’t shown here.
Binary file not shown.
This diff is large: its 209 lines aren’t shown here.
Binary file not shown.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 383 lines aren’t shown here.
Binary file not shown.
This diff is large: its 141 lines aren’t shown here.
Binary file not shown.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
Binary file not shown.
This diff is large: its 561 lines aren’t shown here.
Binary file not shown.
This diff is large: its 282 lines aren’t shown here.
Binary file not shown.
This diff is large: its 290 lines aren’t shown here.
Binary file not shown.
This diff is large: its 850 lines aren’t shown here.
Binary file not shown.
This diff is large: its 206 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1610 lines aren’t shown here.
Binary file not shown.
This diff is large: its 418 lines aren’t shown here.
Binary file not shown.
This diff is large: its 137 lines aren’t shown here.
Binary file not shown.
This diff is large: its 211 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1110 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1960 lines aren’t shown here.
Binary file not shown.
This diff is large: its 2949 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1213 lines aren’t shown here.
Binary file not shown.
This diff is large: its 348 lines aren’t shown here.
Binary file not shown.
This diff is large: its 194 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 542 lines aren’t shown here.
Binary file not shown.
This diff is large: its 287 lines aren’t shown here.
Binary file not shown.
This diff is large: its 404 lines aren’t shown here.
Binary file not shown.
This diff is large: its 407 lines aren’t shown here.
Binary file not shown.
This diff is large: its 285 lines aren’t shown here.
Binary file not shown.
This diff is large: its 284 lines aren’t shown here.
Binary file not shown.
This diff is large: its 319 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1417 lines aren’t shown here.
Binary file not shown.
This diff is large: its 210 lines aren’t shown here.
Binary file not shown.
This diff is large: its 227 lines aren’t shown here.
Binary file not shown.
This diff is large: its 259 lines aren’t shown here.
Binary file not shown.
This diff is large: its 171 lines aren’t shown here.
Binary file not shown.
This diff is large: its 113 lines aren’t shown here.
Binary file not shown.
This diff is large: its 46 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1535 lines aren’t shown here.
Binary file not shown.
This diff is large: its 154 lines aren’t shown here.
Binary file not shown.
This diff is large: its 568 lines aren’t shown here.
Binary file not shown.
This diff is large: its 110 lines aren’t shown here.
Binary file not shown.
This diff is large: its 572 lines aren’t shown here.
Binary file not shown.
This diff is large: its 700 lines aren’t shown here.
Binary file not shown.
This diff is large: its 487 lines aren’t shown here.
Binary file not shown.
This diff is large: its 673 lines aren’t shown here.
Binary file not shown.
This diff is large: its 172 lines aren’t shown here.
Binary file not shown.
This diff is large: its 293 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1778 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
This diff is large: its 108 lines aren’t shown here.
Binary file not shown.
This diff is large: its 218 lines aren’t shown here.
Binary file not shown.
This diff is large: its 256 lines aren’t shown here.
Binary file not shown.
This diff is large: its 667 lines aren’t shown here.
Binary file not shown.
This diff is large: its 1508 lines aren’t shown here.
Binary file not shown.
This diff is large: its 205 lines aren’t shown here.
Binary file not shown.
This diff is large: its 802 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 343 lines aren’t shown here.
Binary file not shown.
This diff is large: its 742 lines aren’t shown here.
Binary file not shown.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
This diff is large: its 144 lines aren’t shown here.
Binary file not shown.
This diff is large: its 726 lines aren’t shown here.
Binary file not shown.
This diff is large: its 273 lines aren’t shown here.
Binary file not shown.
This diff is large: its 199 lines aren’t shown here.
Binary file not shown.
This diff is large: its 351 lines aren’t shown here.
Binary file not shown.
This diff is large: its 220 lines aren’t shown here.
Binary file not shown.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 145 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
This diff is large: its 50 lines aren’t shown here.
Binary file not shown.
This diff is large: its 72 lines aren’t shown here.
Binary file not shown.
This diff is large: its 77 lines aren’t shown here.
Binary file not shown.
This diff is large: its 556 lines aren’t shown here.
Binary file not shown.
This diff is large: its 80 lines aren’t shown here.
Binary file not shown.
This diff is large: its 108 lines aren’t shown here.
Binary file not shown.
This diff is large: its 71 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 40 lines aren’t shown here.
Binary file not shown.
This diff is large: its 129 lines aren’t shown here.
Binary file not shown.
This diff is large: its 73 lines aren’t shown here.
Binary file not shown.
This diff is large: its 61 lines aren’t shown here.
Binary file not shown.
This diff is large: its 45 lines aren’t shown here.
Binary file not shown.
This diff is large: its 139 lines aren’t shown here.
Binary file not shown.
This diff is large: its 68 lines aren’t shown here.
Binary file not shown.
This diff is large: its 58 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 66 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 40 lines aren’t shown here.
Binary file not shown.
This diff is large: its 51 lines aren’t shown here.
Binary file not shown.
This diff is large: its 125 lines aren’t shown here.
Binary file not shown.
This diff is large: its 98 lines aren’t shown here.
Binary file not shown.
This diff is large: its 70 lines aren’t shown here.
Binary file not shown.
This diff is large: its 46 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
This diff is large: its 122 lines aren’t shown here.
Binary file not shown.
This diff is large: its 75 lines aren’t shown here.
Binary file not shown.
This diff is large: its 81 lines aren’t shown here.
Binary file not shown.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 222 lines aren’t shown here.
Binary file not shown.
This diff is large: its 364 lines aren’t shown here.
Binary file not shown.
This diff is large: its 84 lines aren’t shown here.
Binary file not shown.
This diff is large: its 210 lines aren’t shown here.
Binary file not shown.
This diff is large: its 144 lines aren’t shown here.
Binary file not shown.
This diff is large: its 56 lines aren’t shown here.
Binary file not shown.
This diff is large: its 54 lines aren’t shown here.
Binary file not shown.
This diff is large: its 48 lines aren’t shown here.
Binary file not shown.
This diff is large: its 89 lines aren’t shown here.
Binary file not shown.
Binary file not shown.
This diff is large: its 620 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.