Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/javax/swing/JComponent.java
+++ new/src/share/classes/javax/swing/JComponent.java
1 1 /*
2 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25 package javax.swing;
26 26
27 27
28 28 import java.util.HashSet;
29 29 import java.util.Hashtable;
30 30 import java.util.Dictionary;
31 31 import java.util.Enumeration;
32 32 import java.util.Locale;
33 33 import java.util.Vector;
34 34 import java.util.EventListener;
35 35 import java.util.Set;
36 36 import java.util.Map;
37 37 import java.util.HashMap;
38 38
39 39 import java.awt.*;
40 40 import java.awt.event.*;
41 41 import java.awt.image.VolatileImage;
42 42 import java.awt.Graphics2D;
43 43 import java.awt.peer.LightweightPeer;
44 44 import java.awt.dnd.DropTarget;
45 45 import java.awt.font.FontRenderContext;
46 46 import java.beans.PropertyChangeListener;
47 47 import java.beans.VetoableChangeListener;
48 48 import java.beans.VetoableChangeSupport;
49 49 import java.beans.Transient;
50 50
51 51 import java.applet.Applet;
52 52
53 53 import java.io.Serializable;
54 54 import java.io.ObjectOutputStream;
55 55 import java.io.ObjectInputStream;
56 56 import java.io.IOException;
57 57 import java.io.ObjectInputValidation;
58 58 import java.io.InvalidObjectException;
59 59 import java.util.concurrent.atomic.AtomicBoolean;
60 60
61 61 import javax.swing.border.*;
62 62 import javax.swing.event.*;
63 63 import javax.swing.plaf.*;
64 64 import static javax.swing.ClientPropertyKey.*;
65 65 import javax.accessibility.*;
66 66
67 67 import sun.awt.SunToolkit;
68 68 import sun.swing.SwingUtilities2;
69 69 import sun.swing.UIClientPropertyKey;
70 70
71 71 /**
72 72 * The base class for all Swing components except top-level containers.
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
73 73 * To use a component that inherits from <code>JComponent</code>,
74 74 * you must place the component in a containment hierarchy
75 75 * whose root is a top-level Swing container.
76 76 * Top-level Swing containers --
77 77 * such as <code>JFrame</code>, <code>JDialog</code>,
78 78 * and <code>JApplet</code> --
79 79 * are specialized components
80 80 * that provide a place for other Swing components to paint themselves.
81 81 * For an explanation of containment hierarchies, see
82 82 * <a
83 - href="http://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html">Swing Components and the Containment Hierarchy</a>,
83 + href="https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html">Swing Components and the Containment Hierarchy</a>,
84 84 * a section in <em>The Java Tutorial</em>.
85 85 *
86 86 * <p>
87 87 * The <code>JComponent</code> class provides:
88 88 * <ul>
89 89 * <li>The base class for both standard and custom components
90 90 * that use the Swing architecture.
91 91 * <li>A "pluggable look and feel" (L&F) that can be specified by the
92 92 * programmer or (optionally) selected by the user at runtime.
93 93 * The look and feel for each component is provided by a
94 94 * <em>UI delegate</em> -- an object that descends from
95 95 * {@link javax.swing.plaf.ComponentUI}.
96 96 * See <a
97 - * href="http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html">How
97 + * href="https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html">How
98 98 * to Set the Look and Feel</a>
99 99 * in <em>The Java Tutorial</em>
100 100 * for more information.
101 101 * <li>Comprehensive keystroke handling.
102 102 * See the document <a
103 - * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html">How to Use Key Bindings</a>,
103 + * href="https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html">How to Use Key Bindings</a>,
104 104 * an article in <em>The Java Tutorial</em>,
105 105 * for more information.
106 106 * <li>Support for tool tips --
107 107 * short descriptions that pop up when the cursor lingers
108 108 * over a component.
109 109 * See <a
110 - * href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How
110 + * href="https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How
111 111 * to Use Tool Tips</a>
112 112 * in <em>The Java Tutorial</em>
113 113 * for more information.
114 114 * <li>Support for accessibility.
115 115 * <code>JComponent</code> contains all of the methods in the
116 116 * <code>Accessible</code> interface,
117 117 * but it doesn't actually implement the interface. That is the
118 118 * responsibility of the individual classes
119 119 * that extend <code>JComponent</code>.
120 120 * <li>Support for component-specific properties.
121 121 * With the {@link #putClientProperty}
122 122 * and {@link #getClientProperty} methods,
123 123 * you can associate name-object pairs
124 124 * with any object that descends from <code>JComponent</code>.
125 125 * <li>An infrastructure for painting
126 126 * that includes double buffering and support for borders.
127 127 * For more information see <a
128 128 * href="http://www.oracle.com/technetwork/java/painting-140037.html#swing">Painting</a> and
129 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.htmll">How
129 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/border.htmll">How
130 130 * to Use Borders</a>,
131 131 * both of which are sections in <em>The Java Tutorial</em>.
132 132 * </ul>
133 133 * For more information on these subjects, see the
134 134 * <a href="package-summary.html#package_description">Swing package description</a>
135 135 * and <em>The Java Tutorial</em> section
136 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
136 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
137 137 * <p>
138 138 * <code>JComponent</code> and its subclasses document default values
139 139 * for certain properties. For example, <code>JTable</code> documents the
140 140 * default row height as 16. Each <code>JComponent</code> subclass
141 141 * that has a <code>ComponentUI</code> will create the
142 142 * <code>ComponentUI</code> as part of its constructor. In order
143 143 * to provide a particular look and feel each
144 144 * <code>ComponentUI</code> may set properties back on the
145 145 * <code>JComponent</code> that created it. For example, a custom
146 146 * look and feel may require <code>JTable</code>s to have a row
147 147 * height of 24. The documented defaults are the value of a property
148 148 * BEFORE the <code>ComponentUI</code> has been installed. If you
149 149 * need a specific value for a particular property you should
150 150 * explicitly set it.
151 151 * <p>
152 152 * In release 1.4, the focus subsystem was rearchitected.
153 153 * For more information, see
154 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
154 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
155 155 * How to Use the Focus Subsystem</a>,
156 156 * a section in <em>The Java Tutorial</em>.
157 157 * <p>
158 158 * <strong>Warning:</strong> Swing is not thread safe. For more
159 159 * information see <a
160 160 * href="package-summary.html#threading">Swing's Threading
161 161 * Policy</a>.
162 162 * <p>
163 163 * <strong>Warning:</strong>
164 164 * Serialized objects of this class will not be compatible with
165 165 * future Swing releases. The current serialization support is
166 166 * appropriate for short term storage or RMI between applications running
167 167 * the same version of Swing. As of 1.4, support for long term storage
168 168 * of all JavaBeans™
169 169 * has been added to the <code>java.beans</code> package.
170 170 * Please see {@link java.beans.XMLEncoder}.
171 171 *
172 172 * @see KeyStroke
173 173 * @see Action
174 174 * @see #setBorder
175 175 * @see #registerKeyboardAction
176 176 * @see JOptionPane
177 177 * @see #setDebugGraphicsOptions
178 178 * @see #setToolTipText
179 179 * @see #setAutoscrolls
180 180 *
181 181 * @author Hans Muller
182 182 * @author Arnaud Weber
183 183 */
184 184 public abstract class JComponent extends Container implements Serializable,
185 185 TransferHandler.HasGetTransferHandler
186 186 {
187 187 /**
188 188 * @see #getUIClassID
189 189 * @see #writeObject
190 190 */
191 191 private static final String uiClassID = "ComponentUI";
192 192
193 193 /**
194 194 * @see #readObject
195 195 */
196 196 private static final Hashtable<ObjectInputStream, ReadObjectCallback> readObjectCallbacks =
197 197 new Hashtable<ObjectInputStream, ReadObjectCallback>(1);
198 198
199 199 /**
200 200 * Keys to use for forward focus traversal when the JComponent is
201 201 * managing focus.
202 202 */
203 203 private static Set<KeyStroke> managingFocusForwardTraversalKeys;
204 204
205 205 /**
206 206 * Keys to use for backward focus traversal when the JComponent is
207 207 * managing focus.
208 208 */
209 209 private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
210 210
211 211 // Following are the possible return values from getObscuredState.
212 212 private static final int NOT_OBSCURED = 0;
213 213 private static final int PARTIALLY_OBSCURED = 1;
214 214 private static final int COMPLETELY_OBSCURED = 2;
215 215
216 216 /**
217 217 * Set to true when DebugGraphics has been loaded.
218 218 */
219 219 static boolean DEBUG_GRAPHICS_LOADED;
220 220
221 221 /**
222 222 * Key used to look up a value from the AppContext to determine the
223 223 * JComponent the InputVerifier is running for. That is, if
224 224 * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it
225 225 * indicates the EDT is calling into the InputVerifier from the
226 226 * returned component.
227 227 */
228 228 private static final Object INPUT_VERIFIER_SOURCE_KEY =
229 229 new StringBuilder("InputVerifierSourceKey");
230 230
231 231 /* The following fields support set methods for the corresponding
232 232 * java.awt.Component properties.
233 233 */
234 234 private boolean isAlignmentXSet;
235 235 private float alignmentX;
236 236 private boolean isAlignmentYSet;
237 237 private float alignmentY;
238 238
239 239 /**
240 240 * Backing store for JComponent properties and listeners
241 241 */
242 242
243 243 /** The look and feel delegate for this component. */
244 244 protected transient ComponentUI ui;
245 245 /** A list of event listeners for this component. */
246 246 protected EventListenerList listenerList = new EventListenerList();
247 247
248 248 private transient ArrayTable clientProperties;
249 249 private VetoableChangeSupport vetoableChangeSupport;
250 250 /**
251 251 * Whether or not autoscroll has been enabled.
252 252 */
253 253 private boolean autoscrolls;
254 254 private Border border;
255 255 private int flags;
256 256
257 257 /* Input verifier for this component */
258 258 private InputVerifier inputVerifier = null;
259 259
260 260 private boolean verifyInputWhenFocusTarget = true;
261 261
262 262 /**
263 263 * Set in <code>_paintImmediately</code>.
264 264 * Will indicate the child that initiated the painting operation.
265 265 * If <code>paintingChild</code> is opaque, no need to paint
266 266 * any child components after <code>paintingChild</code>.
267 267 * Test used in <code>paintChildren</code>.
268 268 */
269 269 transient Component paintingChild;
270 270
271 271 /**
272 272 * Constant used for <code>registerKeyboardAction</code> that
273 273 * means that the command should be invoked when
274 274 * the component has the focus.
275 275 */
276 276 public static final int WHEN_FOCUSED = 0;
277 277
278 278 /**
279 279 * Constant used for <code>registerKeyboardAction</code> that
280 280 * means that the command should be invoked when the receiving
281 281 * component is an ancestor of the focused component or is
282 282 * itself the focused component.
283 283 */
284 284 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
285 285
286 286 /**
287 287 * Constant used for <code>registerKeyboardAction</code> that
288 288 * means that the command should be invoked when
289 289 * the receiving component is in the window that has the focus
290 290 * or is itself the focused component.
291 291 */
292 292 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
293 293
294 294 /**
295 295 * Constant used by some of the APIs to mean that no condition is defined.
296 296 */
297 297 public static final int UNDEFINED_CONDITION = -1;
298 298
299 299 /**
300 300 * The key used by <code>JComponent</code> to access keyboard bindings.
301 301 */
302 302 private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
303 303
304 304 /**
305 305 * An array of <code>KeyStroke</code>s used for
306 306 * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed
307 307 * in the client properties under this string.
308 308 */
309 309 private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow";
310 310
311 311 /**
312 312 * The comment to display when the cursor is over the component,
313 313 * also known as a "value tip", "flyover help", or "flyover label".
314 314 */
315 315 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
316 316
317 317 private static final String NEXT_FOCUS = "nextFocus";
318 318
319 319 /**
320 320 * <code>JPopupMenu</code> assigned to this component
321 321 * and all of its children
322 322 */
323 323 private JPopupMenu popupMenu;
324 324
325 325 /** Private flags **/
326 326 private static final int IS_DOUBLE_BUFFERED = 0;
327 327 private static final int ANCESTOR_USING_BUFFER = 1;
328 328 private static final int IS_PAINTING_TILE = 2;
329 329 private static final int IS_OPAQUE = 3;
330 330 private static final int KEY_EVENTS_ENABLED = 4;
331 331 private static final int FOCUS_INPUTMAP_CREATED = 5;
332 332 private static final int ANCESTOR_INPUTMAP_CREATED = 6;
333 333 private static final int WIF_INPUTMAP_CREATED = 7;
334 334 private static final int ACTIONMAP_CREATED = 8;
335 335 private static final int CREATED_DOUBLE_BUFFER = 9;
336 336 // bit 10 is free
337 337 private static final int IS_PRINTING = 11;
338 338 private static final int IS_PRINTING_ALL = 12;
339 339 private static final int IS_REPAINTING = 13;
340 340 /** Bits 14-21 are used to handle nested writeObject calls. **/
341 341 private static final int WRITE_OBJ_COUNTER_FIRST = 14;
342 342 private static final int RESERVED_1 = 15;
343 343 private static final int RESERVED_2 = 16;
344 344 private static final int RESERVED_3 = 17;
345 345 private static final int RESERVED_4 = 18;
346 346 private static final int RESERVED_5 = 19;
347 347 private static final int RESERVED_6 = 20;
348 348 private static final int WRITE_OBJ_COUNTER_LAST = 21;
349 349
350 350 private static final int REQUEST_FOCUS_DISABLED = 22;
351 351 private static final int INHERITS_POPUP_MENU = 23;
352 352 private static final int OPAQUE_SET = 24;
353 353 private static final int AUTOSCROLLS_SET = 25;
354 354 private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26;
355 355 private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27;
356 356
357 357 private transient AtomicBoolean revalidateRunnableScheduled = new AtomicBoolean(false);
358 358
359 359 /**
360 360 * Temporary rectangles.
361 361 */
362 362 private static java.util.List<Rectangle> tempRectangles = new java.util.ArrayList<Rectangle>(11);
363 363
364 364 /** Used for <code>WHEN_FOCUSED</code> bindings. */
365 365 private InputMap focusInputMap;
366 366 /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */
367 367 private InputMap ancestorInputMap;
368 368 /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */
369 369 private ComponentInputMap windowInputMap;
370 370
371 371 /** ActionMap. */
372 372 private ActionMap actionMap;
373 373
374 374 /** Key used to store the default locale in an AppContext **/
375 375 private static final String defaultLocale = "JComponent.defaultLocale";
376 376
377 377 private static Component componentObtainingGraphicsFrom;
378 378 private static Object componentObtainingGraphicsFromLock = new
379 379 StringBuilder("componentObtainingGraphicsFrom");
380 380
381 381 /**
382 382 * AA text hints.
383 383 */
384 384 transient private Object aaTextInfo;
385 385
386 386 static Graphics safelyGetGraphics(Component c) {
387 387 return safelyGetGraphics(c, SwingUtilities.getRoot(c));
388 388 }
389 389
390 390 static Graphics safelyGetGraphics(Component c, Component root) {
391 391 synchronized(componentObtainingGraphicsFromLock) {
392 392 componentObtainingGraphicsFrom = root;
393 393 Graphics g = c.getGraphics();
394 394 componentObtainingGraphicsFrom = null;
395 395 return g;
396 396 }
397 397 }
398 398
399 399 static void getGraphicsInvoked(Component root) {
400 400 if (!JComponent.isComponentObtainingGraphicsFrom(root)) {
401 401 JRootPane rootPane = ((RootPaneContainer)root).getRootPane();
402 402 if (rootPane != null) {
403 403 rootPane.disableTrueDoubleBuffering();
404 404 }
405 405 }
406 406 }
407 407
408 408
409 409 /**
410 410 * Returns true if {@code c} is the component the graphics is being
411 411 * requested of. This is intended for use when getGraphics is invoked.
412 412 */
413 413 private static boolean isComponentObtainingGraphicsFrom(Component c) {
414 414 synchronized(componentObtainingGraphicsFromLock) {
415 415 return (componentObtainingGraphicsFrom == c);
416 416 }
417 417 }
418 418
419 419 /**
420 420 * Returns the Set of <code>KeyStroke</code>s to use if the component
421 421 * is managing focus for forward focus traversal.
422 422 */
423 423 static Set<KeyStroke> getManagingFocusForwardTraversalKeys() {
424 424 synchronized(JComponent.class) {
425 425 if (managingFocusForwardTraversalKeys == null) {
426 426 managingFocusForwardTraversalKeys = new HashSet<KeyStroke>(1);
427 427 managingFocusForwardTraversalKeys.add(
428 428 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
429 429 InputEvent.CTRL_MASK));
430 430 }
431 431 }
432 432 return managingFocusForwardTraversalKeys;
433 433 }
434 434
435 435 /**
436 436 * Returns the Set of <code>KeyStroke</code>s to use if the component
437 437 * is managing focus for backward focus traversal.
438 438 */
439 439 static Set<KeyStroke> getManagingFocusBackwardTraversalKeys() {
440 440 synchronized(JComponent.class) {
441 441 if (managingFocusBackwardTraversalKeys == null) {
442 442 managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>(1);
443 443 managingFocusBackwardTraversalKeys.add(
444 444 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
445 445 InputEvent.SHIFT_MASK |
446 446 InputEvent.CTRL_MASK));
447 447 }
448 448 }
449 449 return managingFocusBackwardTraversalKeys;
450 450 }
451 451
452 452 private static Rectangle fetchRectangle() {
453 453 synchronized(tempRectangles) {
454 454 Rectangle rect;
455 455 int size = tempRectangles.size();
456 456 if (size > 0) {
457 457 rect = tempRectangles.remove(size - 1);
458 458 }
459 459 else {
460 460 rect = new Rectangle(0, 0, 0, 0);
461 461 }
462 462 return rect;
463 463 }
464 464 }
465 465
466 466 private static void recycleRectangle(Rectangle rect) {
467 467 synchronized(tempRectangles) {
468 468 tempRectangles.add(rect);
469 469 }
470 470 }
471 471
472 472 /**
473 473 * Sets whether or not <code>getComponentPopupMenu</code> should delegate
474 474 * to the parent if this component does not have a <code>JPopupMenu</code>
475 475 * assigned to it.
476 476 * <p>
477 477 * The default value for this is false, but some <code>JComponent</code>
478 478 * subclasses that are implemented as a number of <code>JComponent</code>s
479 479 * may set this to true.
480 480 * <p>
481 481 * This is a bound property.
482 482 *
483 483 * @param value whether or not the JPopupMenu is inherited
484 484 * @see #setComponentPopupMenu
485 485 * @beaninfo
486 486 * bound: true
487 487 * description: Whether or not the JPopupMenu is inherited
488 488 * @since 1.5
489 489 */
490 490 public void setInheritsPopupMenu(boolean value) {
491 491 boolean oldValue = getFlag(INHERITS_POPUP_MENU);
492 492 setFlag(INHERITS_POPUP_MENU, value);
493 493 firePropertyChange("inheritsPopupMenu", oldValue, value);
494 494 }
495 495
496 496 /**
497 497 * Returns true if the JPopupMenu should be inherited from the parent.
498 498 *
499 499 * @see #setComponentPopupMenu
500 500 * @since 1.5
501 501 */
502 502 public boolean getInheritsPopupMenu() {
503 503 return getFlag(INHERITS_POPUP_MENU);
504 504 }
505 505
506 506 /**
507 507 * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>.
508 508 * The UI is responsible for registering bindings and adding the necessary
509 509 * listeners such that the <code>JPopupMenu</code> will be shown at
510 510 * the appropriate time. When the <code>JPopupMenu</code> is shown
511 511 * depends upon the look and feel: some may show it on a mouse event,
512 512 * some may enable a key binding.
513 513 * <p>
514 514 * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code>
515 515 * returns true, then <code>getComponentPopupMenu</code> will be delegated
516 516 * to the parent. This provides for a way to make all child components
517 517 * inherit the popupmenu of the parent.
518 518 * <p>
519 519 * This is a bound property.
520 520 *
521 521 * @param popup - the popup that will be assigned to this component
522 522 * may be null
523 523 * @see #getComponentPopupMenu
524 524 * @beaninfo
525 525 * bound: true
526 526 * preferred: true
527 527 * description: Popup to show
528 528 * @since 1.5
529 529 */
530 530 public void setComponentPopupMenu(JPopupMenu popup) {
531 531 if(popup != null) {
532 532 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
533 533 }
534 534 JPopupMenu oldPopup = this.popupMenu;
535 535 this.popupMenu = popup;
536 536 firePropertyChange("componentPopupMenu", oldPopup, popup);
537 537 }
538 538
539 539 /**
540 540 * Returns <code>JPopupMenu</code> that assigned for this component.
541 541 * If this component does not have a <code>JPopupMenu</code> assigned
542 542 * to it and <code>getInheritsPopupMenu</code> is true, this
543 543 * will return <code>getParent().getComponentPopupMenu()</code> (assuming
544 544 * the parent is valid.)
545 545 *
546 546 * @return <code>JPopupMenu</code> assigned for this component
547 547 * or <code>null</code> if no popup assigned
548 548 * @see #setComponentPopupMenu
549 549 * @since 1.5
550 550 */
551 551 public JPopupMenu getComponentPopupMenu() {
552 552
553 553 if(!getInheritsPopupMenu()) {
554 554 return popupMenu;
555 555 }
556 556
557 557 if(popupMenu == null) {
558 558 // Search parents for its popup
559 559 Container parent = getParent();
560 560 while (parent != null) {
561 561 if(parent instanceof JComponent) {
562 562 return ((JComponent)parent).getComponentPopupMenu();
563 563 }
564 564 if(parent instanceof Window ||
565 565 parent instanceof Applet) {
566 566 // Reached toplevel, break and return null
567 567 break;
568 568 }
569 569 parent = parent.getParent();
570 570 }
571 571 return null;
572 572 }
573 573
574 574 return popupMenu;
575 575 }
576 576
577 577 /**
578 578 * Default <code>JComponent</code> constructor. This constructor does
579 579 * very little initialization beyond calling the <code>Container</code>
580 580 * constructor. For example, the initial layout manager is
581 581 * <code>null</code>. It does, however, set the component's locale
582 582 * property to the value returned by
583 583 * <code>JComponent.getDefaultLocale</code>.
584 584 *
585 585 * @see #getDefaultLocale
586 586 */
587 587 public JComponent() {
588 588 super();
589 589 // We enable key events on all JComponents so that accessibility
590 590 // bindings will work everywhere. This is a partial fix to BugID
591 591 // 4282211.
592 592 enableEvents(AWTEvent.KEY_EVENT_MASK);
593 593 if (isManagingFocus()) {
594 594 LookAndFeel.installProperty(this,
595 595 "focusTraversalKeysForward",
596 596 getManagingFocusForwardTraversalKeys());
597 597 LookAndFeel.installProperty(this,
598 598 "focusTraversalKeysBackward",
599 599 getManagingFocusBackwardTraversalKeys());
600 600 }
601 601
602 602 super.setLocale( JComponent.getDefaultLocale() );
603 603 }
604 604
605 605
606 606 /**
607 607 * Resets the UI property to a value from the current look and feel.
608 608 * <code>JComponent</code> subclasses must override this method
609 609 * like this:
610 610 * <pre>
611 611 * public void updateUI() {
612 612 * setUI((SliderUI)UIManager.getUI(this);
613 613 * }
614 614 * </pre>
615 615 *
616 616 * @see #setUI
617 617 * @see UIManager#getLookAndFeel
618 618 * @see UIManager#getUI
619 619 */
620 620 public void updateUI() {}
621 621
622 622
623 623 /**
624 624 * Sets the look and feel delegate for this component.
625 625 * <code>JComponent</code> subclasses generally override this method
626 626 * to narrow the argument type. For example, in <code>JSlider</code>:
627 627 * <pre>
628 628 * public void setUI(SliderUI newUI) {
629 629 * super.setUI(newUI);
630 630 * }
631 631 * </pre>
632 632 * <p>
633 633 * Additionally <code>JComponent</code> subclasses must provide a
634 634 * <code>getUI</code> method that returns the correct type. For example:
635 635 * <pre>
636 636 * public SliderUI getUI() {
637 637 * return (SliderUI)ui;
638 638 * }
639 639 * </pre>
640 640 *
641 641 * @param newUI the new UI delegate
642 642 * @see #updateUI
643 643 * @see UIManager#getLookAndFeel
644 644 * @see UIManager#getUI
645 645 * @beaninfo
646 646 * bound: true
647 647 * hidden: true
648 648 * attribute: visualUpdate true
649 649 * description: The component's look and feel delegate.
650 650 */
651 651 protected void setUI(ComponentUI newUI) {
652 652 /* We do not check that the UI instance is different
653 653 * before allowing the switch in order to enable the
654 654 * same UI instance *with different default settings*
655 655 * to be installed.
656 656 */
657 657
658 658 uninstallUIAndProperties();
659 659
660 660 // aaText shouldn't persist between look and feels, reset it.
661 661 aaTextInfo =
662 662 UIManager.getDefaults().get(SwingUtilities2.AA_TEXT_PROPERTY_KEY);
663 663 ComponentUI oldUI = ui;
664 664 ui = newUI;
665 665 if (ui != null) {
666 666 ui.installUI(this);
667 667 }
668 668
669 669 firePropertyChange("UI", oldUI, newUI);
670 670 revalidate();
671 671 repaint();
672 672 }
673 673
674 674 /**
675 675 * Uninstalls the UI, if any, and any client properties designated
676 676 * as being specific to the installed UI - instances of
677 677 * {@code UIClientPropertyKey}.
678 678 */
679 679 private void uninstallUIAndProperties() {
680 680 if (ui != null) {
681 681 ui.uninstallUI(this);
682 682 //clean UIClientPropertyKeys from client properties
683 683 if (clientProperties != null) {
684 684 synchronized(clientProperties) {
685 685 Object[] clientPropertyKeys =
686 686 clientProperties.getKeys(null);
687 687 if (clientPropertyKeys != null) {
688 688 for (Object key : clientPropertyKeys) {
689 689 if (key instanceof UIClientPropertyKey) {
690 690 putClientProperty(key, null);
691 691 }
692 692 }
693 693 }
694 694 }
695 695 }
696 696 }
697 697 }
698 698
699 699 /**
700 700 * Returns the <code>UIDefaults</code> key used to
701 701 * look up the name of the <code>swing.plaf.ComponentUI</code>
702 702 * class that defines the look and feel
703 703 * for this component. Most applications will never need to
704 704 * call this method. Subclasses of <code>JComponent</code> that support
705 705 * pluggable look and feel should override this method to
706 706 * return a <code>UIDefaults</code> key that maps to the
707 707 * <code>ComponentUI</code> subclass that defines their look and feel.
708 708 *
709 709 * @return the <code>UIDefaults</code> key for a
710 710 * <code>ComponentUI</code> subclass
711 711 * @see UIDefaults#getUI
712 712 * @beaninfo
713 713 * expert: true
714 714 * description: UIClassID
715 715 */
716 716 public String getUIClassID() {
717 717 return uiClassID;
718 718 }
719 719
720 720
721 721 /**
722 722 * Returns the graphics object used to paint this component.
723 723 * If <code>DebugGraphics</code> is turned on we create a new
724 724 * <code>DebugGraphics</code> object if necessary.
725 725 * Otherwise we just configure the
726 726 * specified graphics object's foreground and font.
727 727 *
728 728 * @param g the original <code>Graphics</code> object
729 729 * @return a <code>Graphics</code> object configured for this component
730 730 */
731 731 protected Graphics getComponentGraphics(Graphics g) {
732 732 Graphics componentGraphics = g;
733 733 if (ui != null && DEBUG_GRAPHICS_LOADED) {
734 734 if ((DebugGraphics.debugComponentCount() != 0) &&
735 735 (shouldDebugGraphics() != 0) &&
736 736 !(g instanceof DebugGraphics)) {
737 737 componentGraphics = new DebugGraphics(g,this);
738 738 }
739 739 }
740 740 componentGraphics.setColor(getForeground());
741 741 componentGraphics.setFont(getFont());
742 742
743 743 return componentGraphics;
744 744 }
745 745
746 746
747 747 /**
748 748 * Calls the UI delegate's paint method, if the UI delegate
749 749 * is non-<code>null</code>. We pass the delegate a copy of the
750 750 * <code>Graphics</code> object to protect the rest of the
751 751 * paint code from irrevocable changes
752 752 * (for example, <code>Graphics.translate</code>).
753 753 * <p>
754 754 * If you override this in a subclass you should not make permanent
755 755 * changes to the passed in <code>Graphics</code>. For example, you
756 756 * should not alter the clip <code>Rectangle</code> or modify the
757 757 * transform. If you need to do these operations you may find it
758 758 * easier to create a new <code>Graphics</code> from the passed in
759 759 * <code>Graphics</code> and manipulate it. Further, if you do not
760 760 * invoker super's implementation you must honor the opaque property,
761 761 * that is
762 762 * if this component is opaque, you must completely fill in the background
763 763 * in a non-opaque color. If you do not honor the opaque property you
764 764 * will likely see visual artifacts.
765 765 * <p>
766 766 * The passed in <code>Graphics</code> object might
767 767 * have a transform other than the identify transform
768 768 * installed on it. In this case, you might get
769 769 * unexpected results if you cumulatively apply
770 770 * another transform.
771 771 *
772 772 * @param g the <code>Graphics</code> object to protect
773 773 * @see #paint
774 774 * @see ComponentUI
775 775 */
776 776 protected void paintComponent(Graphics g) {
777 777 if (ui != null) {
778 778 Graphics scratchGraphics = (g == null) ? null : g.create();
779 779 try {
780 780 ui.update(scratchGraphics, this);
781 781 }
782 782 finally {
783 783 scratchGraphics.dispose();
784 784 }
785 785 }
786 786 }
787 787
788 788 /**
789 789 * Paints this component's children.
790 790 * If <code>shouldUseBuffer</code> is true,
791 791 * no component ancestor has a buffer and
792 792 * the component children can use a buffer if they have one.
793 793 * Otherwise, one ancestor has a buffer currently in use and children
794 794 * should not use a buffer to paint.
795 795 * @param g the <code>Graphics</code> context in which to paint
796 796 * @see #paint
797 797 * @see java.awt.Container#paint
798 798 */
799 799 protected void paintChildren(Graphics g) {
800 800 Graphics sg = g;
801 801
802 802 synchronized(getTreeLock()) {
803 803 int i = getComponentCount() - 1;
804 804 if (i < 0) {
805 805 return;
806 806 }
807 807 // If we are only to paint to a specific child, determine
808 808 // its index.
809 809 if (paintingChild != null &&
810 810 (paintingChild instanceof JComponent) &&
811 811 paintingChild.isOpaque()) {
812 812 for (; i >= 0; i--) {
813 813 if (getComponent(i) == paintingChild){
814 814 break;
815 815 }
816 816 }
817 817 }
818 818 Rectangle tmpRect = fetchRectangle();
819 819 boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
820 820 checkIfChildObscuredBySibling());
821 821 Rectangle clipBounds = null;
822 822 if (checkSiblings) {
823 823 clipBounds = sg.getClipBounds();
824 824 if (clipBounds == null) {
825 825 clipBounds = new Rectangle(0, 0, getWidth(),
826 826 getHeight());
827 827 }
828 828 }
829 829 boolean printing = getFlag(IS_PRINTING);
830 830 final Window window = SwingUtilities.getWindowAncestor(this);
831 831 final boolean isWindowOpaque = window == null || window.isOpaque();
832 832 for (; i >= 0 ; i--) {
833 833 Component comp = getComponent(i);
834 834 if (comp == null) {
835 835 continue;
836 836 }
837 837
838 838 final boolean isJComponent = comp instanceof JComponent;
839 839
840 840 // Enable painting of heavyweights in non-opaque windows.
841 841 // See 6884960
842 842 if ((!isWindowOpaque || isJComponent ||
843 843 isLightweightComponent(comp)) && comp.isVisible())
844 844 {
845 845 Rectangle cr;
846 846
847 847 cr = comp.getBounds(tmpRect);
848 848
849 849 boolean hitClip = g.hitClip(cr.x, cr.y, cr.width,
850 850 cr.height);
851 851
852 852 if (hitClip) {
853 853 if (checkSiblings && i > 0) {
854 854 int x = cr.x;
855 855 int y = cr.y;
856 856 int width = cr.width;
857 857 int height = cr.height;
858 858 SwingUtilities.computeIntersection
859 859 (clipBounds.x, clipBounds.y,
860 860 clipBounds.width, clipBounds.height, cr);
861 861
862 862 if(getObscuredState(i, cr.x, cr.y, cr.width,
863 863 cr.height) == COMPLETELY_OBSCURED) {
864 864 continue;
865 865 }
866 866 cr.x = x;
867 867 cr.y = y;
868 868 cr.width = width;
869 869 cr.height = height;
870 870 }
871 871 Graphics cg = sg.create(cr.x, cr.y, cr.width,
872 872 cr.height);
873 873 cg.setColor(comp.getForeground());
874 874 cg.setFont(comp.getFont());
875 875 boolean shouldSetFlagBack = false;
876 876 try {
877 877 if(isJComponent) {
878 878 if(getFlag(ANCESTOR_USING_BUFFER)) {
879 879 ((JComponent)comp).setFlag(
880 880 ANCESTOR_USING_BUFFER,true);
881 881 shouldSetFlagBack = true;
882 882 }
883 883 if(getFlag(IS_PAINTING_TILE)) {
884 884 ((JComponent)comp).setFlag(
885 885 IS_PAINTING_TILE,true);
886 886 shouldSetFlagBack = true;
887 887 }
888 888 if(!printing) {
889 889 comp.paint(cg);
890 890 }
891 891 else {
892 892 if (!getFlag(IS_PRINTING_ALL)) {
893 893 comp.print(cg);
894 894 }
895 895 else {
896 896 comp.printAll(cg);
897 897 }
898 898 }
899 899 } else {
900 900 // The component is either lightweight, or
901 901 // heavyweight in a non-opaque window
902 902 if (!printing) {
903 903 comp.paint(cg);
904 904 }
905 905 else {
906 906 if (!getFlag(IS_PRINTING_ALL)) {
907 907 comp.print(cg);
908 908 }
909 909 else {
910 910 comp.printAll(cg);
911 911 }
912 912 }
913 913 }
914 914 } finally {
915 915 cg.dispose();
916 916 if(shouldSetFlagBack) {
917 917 ((JComponent)comp).setFlag(
918 918 ANCESTOR_USING_BUFFER,false);
919 919 ((JComponent)comp).setFlag(
920 920 IS_PAINTING_TILE,false);
921 921 }
922 922 }
923 923 }
924 924 }
925 925
926 926 }
927 927 recycleRectangle(tmpRect);
928 928 }
929 929 }
930 930
931 931 /**
932 932 * Paints the component's border.
933 933 * <p>
934 934 * If you override this in a subclass you should not make permanent
935 935 * changes to the passed in <code>Graphics</code>. For example, you
936 936 * should not alter the clip <code>Rectangle</code> or modify the
937 937 * transform. If you need to do these operations you may find it
938 938 * easier to create a new <code>Graphics</code> from the passed in
939 939 * <code>Graphics</code> and manipulate it.
940 940 *
941 941 * @param g the <code>Graphics</code> context in which to paint
942 942 *
943 943 * @see #paint
944 944 * @see #setBorder
945 945 */
946 946 protected void paintBorder(Graphics g) {
947 947 Border border = getBorder();
948 948 if (border != null) {
949 949 border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
950 950 }
951 951 }
952 952
953 953
954 954 /**
955 955 * Calls <code>paint</code>. Doesn't clear the background but see
956 956 * <code>ComponentUI.update</code>, which is called by
957 957 * <code>paintComponent</code>.
958 958 *
959 959 * @param g the <code>Graphics</code> context in which to paint
960 960 * @see #paint
961 961 * @see #paintComponent
962 962 * @see javax.swing.plaf.ComponentUI
963 963 */
964 964 public void update(Graphics g) {
965 965 paint(g);
966 966 }
967 967
968 968
969 969 /**
970 970 * Invoked by Swing to draw components.
971 971 * Applications should not invoke <code>paint</code> directly,
972 972 * but should instead use the <code>repaint</code> method to
973 973 * schedule the component for redrawing.
974 974 * <p>
975 975 * This method actually delegates the work of painting to three
976 976 * protected methods: <code>paintComponent</code>,
977 977 * <code>paintBorder</code>,
978 978 * and <code>paintChildren</code>. They're called in the order
979 979 * listed to ensure that children appear on top of component itself.
980 980 * Generally speaking, the component and its children should not
981 981 * paint in the insets area allocated to the border. Subclasses can
982 982 * just override this method, as always. A subclass that just
983 983 * wants to specialize the UI (look and feel) delegate's
984 984 * <code>paint</code> method should just override
985 985 * <code>paintComponent</code>.
986 986 *
987 987 * @param g the <code>Graphics</code> context in which to paint
988 988 * @see #paintComponent
989 989 * @see #paintBorder
990 990 * @see #paintChildren
991 991 * @see #getComponentGraphics
992 992 * @see #repaint
993 993 */
994 994 public void paint(Graphics g) {
995 995 boolean shouldClearPaintFlags = false;
996 996
997 997 if ((getWidth() <= 0) || (getHeight() <= 0)) {
998 998 return;
999 999 }
1000 1000
1001 1001 Graphics componentGraphics = getComponentGraphics(g);
1002 1002 Graphics co = componentGraphics.create();
1003 1003 try {
1004 1004 RepaintManager repaintManager = RepaintManager.currentManager(this);
1005 1005 Rectangle clipRect = co.getClipBounds();
1006 1006 int clipX;
1007 1007 int clipY;
1008 1008 int clipW;
1009 1009 int clipH;
1010 1010 if (clipRect == null) {
1011 1011 clipX = clipY = 0;
1012 1012 clipW = getWidth();
1013 1013 clipH = getHeight();
1014 1014 }
1015 1015 else {
1016 1016 clipX = clipRect.x;
1017 1017 clipY = clipRect.y;
1018 1018 clipW = clipRect.width;
1019 1019 clipH = clipRect.height;
1020 1020 }
1021 1021
1022 1022 if(clipW > getWidth()) {
1023 1023 clipW = getWidth();
1024 1024 }
1025 1025 if(clipH > getHeight()) {
1026 1026 clipH = getHeight();
1027 1027 }
1028 1028
1029 1029 if(getParent() != null && !(getParent() instanceof JComponent)) {
1030 1030 adjustPaintFlags();
1031 1031 shouldClearPaintFlags = true;
1032 1032 }
1033 1033
1034 1034 int bw,bh;
1035 1035 boolean printing = getFlag(IS_PRINTING);
1036 1036 if (!printing && repaintManager.isDoubleBufferingEnabled() &&
1037 1037 !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
1038 1038 (getFlag(IS_REPAINTING) || repaintManager.isPainting()))
1039 1039 {
1040 1040 repaintManager.beginPaint();
1041 1041 try {
1042 1042 repaintManager.paint(this, this, co, clipX, clipY, clipW,
1043 1043 clipH);
1044 1044 } finally {
1045 1045 repaintManager.endPaint();
1046 1046 }
1047 1047 }
1048 1048 else {
1049 1049 // Will ocassionaly happen in 1.2, especially when printing.
1050 1050 if (clipRect == null) {
1051 1051 co.setClip(clipX, clipY, clipW, clipH);
1052 1052 }
1053 1053
1054 1054 if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
1055 1055 if (!printing) {
1056 1056 paintComponent(co);
1057 1057 paintBorder(co);
1058 1058 }
1059 1059 else {
1060 1060 printComponent(co);
1061 1061 printBorder(co);
1062 1062 }
1063 1063 }
1064 1064 if (!printing) {
1065 1065 paintChildren(co);
1066 1066 }
1067 1067 else {
1068 1068 printChildren(co);
1069 1069 }
1070 1070 }
1071 1071 } finally {
1072 1072 co.dispose();
1073 1073 if(shouldClearPaintFlags) {
1074 1074 setFlag(ANCESTOR_USING_BUFFER,false);
1075 1075 setFlag(IS_PAINTING_TILE,false);
1076 1076 setFlag(IS_PRINTING,false);
1077 1077 setFlag(IS_PRINTING_ALL,false);
1078 1078 }
1079 1079 }
1080 1080 }
1081 1081
1082 1082 // paint forcing use of the double buffer. This is used for historical
1083 1083 // reasons: JViewport, when scrolling, previously directly invoked paint
1084 1084 // while turning off double buffering at the RepaintManager level, this
1085 1085 // codes simulates that.
1086 1086 void paintForceDoubleBuffered(Graphics g) {
1087 1087 RepaintManager rm = RepaintManager.currentManager(this);
1088 1088 Rectangle clip = g.getClipBounds();
1089 1089 rm.beginPaint();
1090 1090 setFlag(IS_REPAINTING, true);
1091 1091 try {
1092 1092 rm.paint(this, this, g, clip.x, clip.y, clip.width, clip.height);
1093 1093 } finally {
1094 1094 rm.endPaint();
1095 1095 setFlag(IS_REPAINTING, false);
1096 1096 }
1097 1097 }
1098 1098
1099 1099 /**
1100 1100 * Returns true if this component, or any of its ancestors, are in
1101 1101 * the processing of painting.
1102 1102 */
1103 1103 boolean isPainting() {
1104 1104 Container component = this;
1105 1105 while (component != null) {
1106 1106 if (component instanceof JComponent &&
1107 1107 ((JComponent)component).getFlag(ANCESTOR_USING_BUFFER)) {
1108 1108 return true;
1109 1109 }
1110 1110 component = component.getParent();
1111 1111 }
1112 1112 return false;
1113 1113 }
1114 1114
1115 1115 private void adjustPaintFlags() {
1116 1116 JComponent jparent;
1117 1117 Container parent;
1118 1118 for(parent = getParent() ; parent != null ; parent =
1119 1119 parent.getParent()) {
1120 1120 if(parent instanceof JComponent) {
1121 1121 jparent = (JComponent) parent;
1122 1122 if(jparent.getFlag(ANCESTOR_USING_BUFFER))
1123 1123 setFlag(ANCESTOR_USING_BUFFER, true);
1124 1124 if(jparent.getFlag(IS_PAINTING_TILE))
1125 1125 setFlag(IS_PAINTING_TILE, true);
1126 1126 if(jparent.getFlag(IS_PRINTING))
1127 1127 setFlag(IS_PRINTING, true);
1128 1128 if(jparent.getFlag(IS_PRINTING_ALL))
1129 1129 setFlag(IS_PRINTING_ALL, true);
1130 1130 break;
1131 1131 }
1132 1132 }
1133 1133 }
1134 1134
1135 1135 /**
1136 1136 * Invoke this method to print the component. This method invokes
1137 1137 * <code>print</code> on the component.
1138 1138 *
1139 1139 * @param g the <code>Graphics</code> context in which to paint
1140 1140 * @see #print
1141 1141 * @see #printComponent
1142 1142 * @see #printBorder
1143 1143 * @see #printChildren
1144 1144 */
1145 1145 public void printAll(Graphics g) {
1146 1146 setFlag(IS_PRINTING_ALL, true);
1147 1147 try {
1148 1148 print(g);
1149 1149 }
1150 1150 finally {
1151 1151 setFlag(IS_PRINTING_ALL, false);
1152 1152 }
1153 1153 }
1154 1154
1155 1155 /**
1156 1156 * Invoke this method to print the component to the specified
1157 1157 * <code>Graphics</code>. This method will result in invocations
1158 1158 * of <code>printComponent</code>, <code>printBorder</code> and
1159 1159 * <code>printChildren</code>. It is recommended that you override
1160 1160 * one of the previously mentioned methods rather than this one if
1161 1161 * your intention is to customize the way printing looks. However,
1162 1162 * it can be useful to override this method should you want to prepare
1163 1163 * state before invoking the superclass behavior. As an example,
1164 1164 * if you wanted to change the component's background color before
1165 1165 * printing, you could do the following:
1166 1166 * <pre>
1167 1167 * public void print(Graphics g) {
1168 1168 * Color orig = getBackground();
1169 1169 * setBackground(Color.WHITE);
1170 1170 *
1171 1171 * // wrap in try/finally so that we always restore the state
1172 1172 * try {
1173 1173 * super.print(g);
1174 1174 * } finally {
1175 1175 * setBackground(orig);
1176 1176 * }
1177 1177 * }
1178 1178 * </pre>
1179 1179 * <p>
1180 1180 * Alternatively, or for components that delegate painting to other objects,
1181 1181 * you can query during painting whether or not the component is in the
1182 1182 * midst of a print operation. The <code>isPaintingForPrint</code> method provides
1183 1183 * this ability and its return value will be changed by this method: to
1184 1184 * <code>true</code> immediately before rendering and to <code>false</code>
1185 1185 * immediately after. With each change a property change event is fired on
1186 1186 * this component with the name <code>"paintingForPrint"</code>.
1187 1187 * <p>
1188 1188 * This method sets the component's state such that the double buffer
1189 1189 * will not be used: painting will be done directly on the passed in
1190 1190 * <code>Graphics</code>.
1191 1191 *
1192 1192 * @param g the <code>Graphics</code> context in which to paint
1193 1193 * @see #printComponent
1194 1194 * @see #printBorder
1195 1195 * @see #printChildren
1196 1196 * @see #isPaintingForPrint
1197 1197 */
1198 1198 public void print(Graphics g) {
1199 1199 setFlag(IS_PRINTING, true);
1200 1200 firePropertyChange("paintingForPrint", false, true);
1201 1201 try {
1202 1202 paint(g);
1203 1203 }
1204 1204 finally {
1205 1205 setFlag(IS_PRINTING, false);
1206 1206 firePropertyChange("paintingForPrint", true, false);
1207 1207 }
1208 1208 }
1209 1209
1210 1210 /**
1211 1211 * This is invoked during a printing operation. This is implemented to
1212 1212 * invoke <code>paintComponent</code> on the component. Override this
1213 1213 * if you wish to add special painting behavior when printing.
1214 1214 *
1215 1215 * @param g the <code>Graphics</code> context in which to paint
1216 1216 * @see #print
1217 1217 * @since 1.3
1218 1218 */
1219 1219 protected void printComponent(Graphics g) {
1220 1220 paintComponent(g);
1221 1221 }
1222 1222
1223 1223 /**
1224 1224 * Prints this component's children. This is implemented to invoke
1225 1225 * <code>paintChildren</code> on the component. Override this if you
1226 1226 * wish to print the children differently than painting.
1227 1227 *
1228 1228 * @param g the <code>Graphics</code> context in which to paint
1229 1229 * @see #print
1230 1230 * @since 1.3
1231 1231 */
1232 1232 protected void printChildren(Graphics g) {
1233 1233 paintChildren(g);
1234 1234 }
1235 1235
1236 1236 /**
1237 1237 * Prints the component's border. This is implemented to invoke
1238 1238 * <code>paintBorder</code> on the component. Override this if you
1239 1239 * wish to print the border differently that it is painted.
1240 1240 *
1241 1241 * @param g the <code>Graphics</code> context in which to paint
1242 1242 * @see #print
1243 1243 * @since 1.3
1244 1244 */
1245 1245 protected void printBorder(Graphics g) {
1246 1246 paintBorder(g);
1247 1247 }
1248 1248
1249 1249 /**
1250 1250 * Returns true if the component is currently painting a tile.
1251 1251 * If this method returns true, paint will be called again for another
1252 1252 * tile. This method returns false if you are not painting a tile or
1253 1253 * if the last tile is painted.
1254 1254 * Use this method to keep some state you might need between tiles.
1255 1255 *
1256 1256 * @return true if the component is currently painting a tile,
1257 1257 * false otherwise
1258 1258 */
1259 1259 public boolean isPaintingTile() {
1260 1260 return getFlag(IS_PAINTING_TILE);
1261 1261 }
1262 1262
1263 1263 /**
1264 1264 * Returns <code>true</code> if the current painting operation on this
1265 1265 * component is part of a <code>print</code> operation. This method is
1266 1266 * useful when you want to customize what you print versus what you show
1267 1267 * on the screen.
1268 1268 * <p>
1269 1269 * You can detect changes in the value of this property by listening for
1270 1270 * property change events on this component with name
1271 1271 * <code>"paintingForPrint"</code>.
1272 1272 * <p>
1273 1273 * Note: This method provides complimentary functionality to that provided
1274 1274 * by other high level Swing printing APIs. However, it deals strictly with
1275 1275 * painting and should not be confused as providing information on higher
1276 1276 * level print processes. For example, a {@link javax.swing.JTable#print()}
1277 1277 * operation doesn't necessarily result in a continuous rendering of the
1278 1278 * full component, and the return value of this method can change multiple
1279 1279 * times during that operation. It is even possible for the component to be
1280 1280 * painted to the screen while the printing process is ongoing. In such a
1281 1281 * case, the return value of this method is <code>true</code> when, and only
1282 1282 * when, the table is being painted as part of the printing process.
1283 1283 *
1284 1284 * @return true if the current painting operation on this component
1285 1285 * is part of a print operation
↓ open down ↓ |
1121 lines elided |
↑ open up ↑ |
1286 1286 * @see #print
1287 1287 * @since 1.6
1288 1288 */
1289 1289 public final boolean isPaintingForPrint() {
1290 1290 return getFlag(IS_PRINTING);
1291 1291 }
1292 1292
1293 1293 /**
1294 1294 * In release 1.4, the focus subsystem was rearchitected.
1295 1295 * For more information, see
1296 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1296 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1297 1297 * How to Use the Focus Subsystem</a>,
1298 1298 * a section in <em>The Java Tutorial</em>.
1299 1299 * <p>
1300 1300 * Changes this <code>JComponent</code>'s focus traversal keys to
1301 1301 * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents
1302 1302 * <code>SortingFocusTraversalPolicy</code> from considering descendants
1303 1303 * of this JComponent when computing a focus traversal cycle.
1304 1304 *
1305 1305 * @see java.awt.Component#setFocusTraversalKeys
1306 1306 * @see SortingFocusTraversalPolicy
1307 1307 * @deprecated As of 1.4, replaced by
1308 1308 * <code>Component.setFocusTraversalKeys(int, Set)</code> and
1309 1309 * <code>Container.setFocusCycleRoot(boolean)</code>.
1310 1310 */
1311 1311 @Deprecated
1312 1312 public boolean isManagingFocus() {
1313 1313 return false;
1314 1314 }
1315 1315
1316 1316 private void registerNextFocusableComponent() {
1317 1317 registerNextFocusableComponent(getNextFocusableComponent());
1318 1318 }
1319 1319
1320 1320 private void registerNextFocusableComponent(Component
1321 1321 nextFocusableComponent) {
1322 1322 if (nextFocusableComponent == null) {
1323 1323 return;
1324 1324 }
1325 1325
1326 1326 Container nearestRoot =
1327 1327 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1328 1328 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1329 1329 if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) {
1330 1330 policy = new LegacyGlueFocusTraversalPolicy(policy);
1331 1331 nearestRoot.setFocusTraversalPolicy(policy);
1332 1332 }
1333 1333 ((LegacyGlueFocusTraversalPolicy)policy).
1334 1334 setNextFocusableComponent(this, nextFocusableComponent);
1335 1335 }
1336 1336
1337 1337 private void deregisterNextFocusableComponent() {
1338 1338 Component nextFocusableComponent = getNextFocusableComponent();
1339 1339 if (nextFocusableComponent == null) {
1340 1340 return;
1341 1341 }
1342 1342
1343 1343 Container nearestRoot =
1344 1344 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1345 1345 if (nearestRoot == null) {
1346 1346 return;
1347 1347 }
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
1348 1348 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1349 1349 if (policy instanceof LegacyGlueFocusTraversalPolicy) {
1350 1350 ((LegacyGlueFocusTraversalPolicy)policy).
1351 1351 unsetNextFocusableComponent(this, nextFocusableComponent);
1352 1352 }
1353 1353 }
1354 1354
1355 1355 /**
1356 1356 * In release 1.4, the focus subsystem was rearchitected.
1357 1357 * For more information, see
1358 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1358 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1359 1359 * How to Use the Focus Subsystem</a>,
1360 1360 * a section in <em>The Java Tutorial</em>.
1361 1361 * <p>
1362 1362 * Overrides the default <code>FocusTraversalPolicy</code> for this
1363 1363 * <code>JComponent</code>'s focus traversal cycle by unconditionally
1364 1364 * setting the specified <code>Component</code> as the next
1365 1365 * <code>Component</code> in the cycle, and this <code>JComponent</code>
1366 1366 * as the specified <code>Component</code>'s previous
1367 1367 * <code>Component</code> in the cycle.
1368 1368 *
1369 1369 * @param aComponent the <code>Component</code> that should follow this
1370 1370 * <code>JComponent</code> in the focus traversal cycle
1371 1371 *
1372 1372 * @see #getNextFocusableComponent
1373 1373 * @see java.awt.FocusTraversalPolicy
1374 1374 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>
1375 1375 */
1376 1376 @Deprecated
1377 1377 public void setNextFocusableComponent(Component aComponent) {
1378 1378 boolean displayable = isDisplayable();
1379 1379 if (displayable) {
1380 1380 deregisterNextFocusableComponent();
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1381 1381 }
1382 1382 putClientProperty(NEXT_FOCUS, aComponent);
1383 1383 if (displayable) {
1384 1384 registerNextFocusableComponent(aComponent);
1385 1385 }
1386 1386 }
1387 1387
1388 1388 /**
1389 1389 * In release 1.4, the focus subsystem was rearchitected.
1390 1390 * For more information, see
1391 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1391 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1392 1392 * How to Use the Focus Subsystem</a>,
1393 1393 * a section in <em>The Java Tutorial</em>.
1394 1394 * <p>
1395 1395 * Returns the <code>Component</code> set by a prior call to
1396 1396 * <code>setNextFocusableComponent(Component)</code> on this
1397 1397 * <code>JComponent</code>.
1398 1398 *
1399 1399 * @return the <code>Component</code> that will follow this
1400 1400 * <code>JComponent</code> in the focus traversal cycle, or
1401 1401 * <code>null</code> if none has been explicitly specified
1402 1402 *
1403 1403 * @see #setNextFocusableComponent
1404 1404 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
1405 1405 */
1406 1406 @Deprecated
1407 1407 public Component getNextFocusableComponent() {
1408 1408 return (Component)getClientProperty(NEXT_FOCUS);
1409 1409 }
1410 1410
1411 1411 /**
1412 1412 * Provides a hint as to whether or not this <code>JComponent</code>
1413 1413 * should get focus. This is only a hint, and it is up to consumers that
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1414 1414 * are requesting focus to honor this property. This is typically honored
1415 1415 * for mouse operations, but not keyboard operations. For example, look
1416 1416 * and feels could verify this property is true before requesting focus
1417 1417 * during a mouse operation. This would often times be used if you did
1418 1418 * not want a mouse press on a <code>JComponent</code> to steal focus,
1419 1419 * but did want the <code>JComponent</code> to be traversable via the
1420 1420 * keyboard. If you do not want this <code>JComponent</code> focusable at
1421 1421 * all, use the <code>setFocusable</code> method instead.
1422 1422 * <p>
1423 1423 * Please see
1424 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1424 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1425 1425 * How to Use the Focus Subsystem</a>,
1426 1426 * a section in <em>The Java Tutorial</em>,
1427 1427 * for more information.
1428 1428 *
1429 1429 * @param requestFocusEnabled indicates whether you want this
1430 1430 * <code>JComponent</code> to be focusable or not
1431 1431 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
1432 1432 * @see java.awt.Component#setFocusable
1433 1433 */
1434 1434 public void setRequestFocusEnabled(boolean requestFocusEnabled) {
1435 1435 setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled);
1436 1436 }
1437 1437
1438 1438 /**
1439 1439 * Returns <code>true</code> if this <code>JComponent</code> should
1440 1440 * get focus; otherwise returns <code>false</code>.
1441 1441 * <p>
1442 1442 * Please see
1443 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1443 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1444 1444 * How to Use the Focus Subsystem</a>,
1445 1445 * a section in <em>The Java Tutorial</em>,
1446 1446 * for more information.
1447 1447 *
1448 1448 * @return <code>true</code> if this component should get focus,
1449 1449 * otherwise returns <code>false</code>
1450 1450 * @see #setRequestFocusEnabled
1451 1451 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus
1452 1452 * Specification</a>
1453 1453 * @see java.awt.Component#isFocusable
1454 1454 */
1455 1455 public boolean isRequestFocusEnabled() {
1456 1456 return !getFlag(REQUEST_FOCUS_DISABLED);
1457 1457 }
1458 1458
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1459 1459 /**
1460 1460 * Requests that this <code>Component</code> gets the input focus.
1461 1461 * Refer to {@link java.awt.Component#requestFocus()
1462 1462 * Component.requestFocus()} for a complete description of
1463 1463 * this method.
1464 1464 * <p>
1465 1465 * Note that the use of this method is discouraged because
1466 1466 * its behavior is platform dependent. Instead we recommend the
1467 1467 * use of {@link #requestFocusInWindow() requestFocusInWindow()}.
1468 1468 * If you would like more information on focus, see
1469 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1469 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1470 1470 * How to Use the Focus Subsystem</a>,
1471 1471 * a section in <em>The Java Tutorial</em>.
1472 1472 *
1473 1473 * @see java.awt.Component#requestFocusInWindow()
1474 1474 * @see java.awt.Component#requestFocusInWindow(boolean)
1475 1475 * @since 1.4
1476 1476 */
1477 1477 public void requestFocus() {
1478 1478 super.requestFocus();
1479 1479 }
1480 1480
1481 1481 /**
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1482 1482 * Requests that this <code>Component</code> gets the input focus.
1483 1483 * Refer to {@link java.awt.Component#requestFocus(boolean)
1484 1484 * Component.requestFocus(boolean)} for a complete description of
1485 1485 * this method.
1486 1486 * <p>
1487 1487 * Note that the use of this method is discouraged because
1488 1488 * its behavior is platform dependent. Instead we recommend the
1489 1489 * use of {@link #requestFocusInWindow(boolean)
1490 1490 * requestFocusInWindow(boolean)}.
1491 1491 * If you would like more information on focus, see
1492 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1492 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1493 1493 * How to Use the Focus Subsystem</a>,
1494 1494 * a section in <em>The Java Tutorial</em>.
1495 1495 *
1496 1496 * @param temporary boolean indicating if the focus change is temporary
1497 1497 * @return <code>false</code> if the focus change request is guaranteed to
1498 1498 * fail; <code>true</code> if it is likely to succeed
1499 1499 * @see java.awt.Component#requestFocusInWindow()
1500 1500 * @see java.awt.Component#requestFocusInWindow(boolean)
1501 1501 * @since 1.4
1502 1502 */
1503 1503 public boolean requestFocus(boolean temporary) {
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
1504 1504 return super.requestFocus(temporary);
1505 1505 }
1506 1506
1507 1507 /**
1508 1508 * Requests that this <code>Component</code> gets the input focus.
1509 1509 * Refer to {@link java.awt.Component#requestFocusInWindow()
1510 1510 * Component.requestFocusInWindow()} for a complete description of
1511 1511 * this method.
1512 1512 * <p>
1513 1513 * If you would like more information on focus, see
1514 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1514 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1515 1515 * How to Use the Focus Subsystem</a>,
1516 1516 * a section in <em>The Java Tutorial</em>.
1517 1517 *
1518 1518 * @return <code>false</code> if the focus change request is guaranteed to
1519 1519 * fail; <code>true</code> if it is likely to succeed
1520 1520 * @see java.awt.Component#requestFocusInWindow()
1521 1521 * @see java.awt.Component#requestFocusInWindow(boolean)
1522 1522 * @since 1.4
1523 1523 */
1524 1524 public boolean requestFocusInWindow() {
1525 1525 return super.requestFocusInWindow();
1526 1526 }
1527 1527
1528 1528 /**
1529 1529 * Requests that this <code>Component</code> gets the input focus.
1530 1530 * Refer to {@link java.awt.Component#requestFocusInWindow(boolean)
1531 1531 * Component.requestFocusInWindow(boolean)} for a complete description of
1532 1532 * this method.
1533 1533 * <p>
1534 1534 * If you would like more information on focus, see
1535 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1535 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1536 1536 * How to Use the Focus Subsystem</a>,
1537 1537 * a section in <em>The Java Tutorial</em>.
1538 1538 *
1539 1539 * @param temporary boolean indicating if the focus change is temporary
1540 1540 * @return <code>false</code> if the focus change request is guaranteed to
1541 1541 * fail; <code>true</code> if it is likely to succeed
1542 1542 * @see java.awt.Component#requestFocusInWindow()
1543 1543 * @see java.awt.Component#requestFocusInWindow(boolean)
1544 1544 * @since 1.4
1545 1545 */
1546 1546 protected boolean requestFocusInWindow(boolean temporary) {
1547 1547 return super.requestFocusInWindow(temporary);
1548 1548 }
1549 1549
1550 1550 /**
1551 1551 * Requests that this Component get the input focus, and that this
1552 1552 * Component's top-level ancestor become the focused Window. This component
1553 1553 * must be displayable, visible, and focusable for the request to be
1554 1554 * granted.
1555 1555 * <p>
1556 1556 * This method is intended for use by focus implementations. Client code
1557 1557 * should not use this method; instead, it should use
1558 1558 * <code>requestFocusInWindow()</code>.
1559 1559 *
1560 1560 * @see #requestFocusInWindow()
1561 1561 */
1562 1562 public void grabFocus() {
1563 1563 requestFocus();
1564 1564 }
1565 1565
1566 1566 /**
1567 1567 * Sets the value to indicate whether input verifier for the
1568 1568 * current focus owner will be called before this component requests
1569 1569 * focus. The default is true. Set to false on components such as a
1570 1570 * Cancel button or a scrollbar, which should activate even if the
1571 1571 * input in the current focus owner is not "passed" by the input
1572 1572 * verifier for that component.
1573 1573 *
1574 1574 * @param verifyInputWhenFocusTarget value for the
1575 1575 * <code>verifyInputWhenFocusTarget</code> property
1576 1576 * @see InputVerifier
1577 1577 * @see #setInputVerifier
1578 1578 * @see #getInputVerifier
1579 1579 * @see #getVerifyInputWhenFocusTarget
1580 1580 *
1581 1581 * @since 1.3
1582 1582 * @beaninfo
1583 1583 * bound: true
1584 1584 * description: Whether the Component verifies input before accepting
1585 1585 * focus.
1586 1586 */
1587 1587 public void setVerifyInputWhenFocusTarget(boolean
1588 1588 verifyInputWhenFocusTarget) {
1589 1589 boolean oldVerifyInputWhenFocusTarget =
1590 1590 this.verifyInputWhenFocusTarget;
1591 1591 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
1592 1592 firePropertyChange("verifyInputWhenFocusTarget",
1593 1593 oldVerifyInputWhenFocusTarget,
1594 1594 verifyInputWhenFocusTarget);
1595 1595 }
1596 1596
1597 1597 /**
1598 1598 * Returns the value that indicates whether the input verifier for the
1599 1599 * current focus owner will be called before this component requests
1600 1600 * focus.
1601 1601 *
1602 1602 * @return value of the <code>verifyInputWhenFocusTarget</code> property
1603 1603 *
1604 1604 * @see InputVerifier
1605 1605 * @see #setInputVerifier
1606 1606 * @see #getInputVerifier
1607 1607 * @see #setVerifyInputWhenFocusTarget
1608 1608 *
1609 1609 * @since 1.3
1610 1610 */
1611 1611 public boolean getVerifyInputWhenFocusTarget() {
1612 1612 return verifyInputWhenFocusTarget;
1613 1613 }
1614 1614
1615 1615
1616 1616 /**
1617 1617 * Gets the <code>FontMetrics</code> for the specified <code>Font</code>.
1618 1618 *
1619 1619 * @param font the font for which font metrics is to be
1620 1620 * obtained
1621 1621 * @return the font metrics for <code>font</code>
1622 1622 * @throws NullPointerException if <code>font</code> is null
1623 1623 * @since 1.5
1624 1624 */
1625 1625 public FontMetrics getFontMetrics(Font font) {
1626 1626 return SwingUtilities2.getFontMetrics(this, font);
1627 1627 }
1628 1628
1629 1629
1630 1630 /**
1631 1631 * Sets the preferred size of this component.
1632 1632 * If <code>preferredSize</code> is <code>null</code>, the UI will
1633 1633 * be asked for the preferred size.
1634 1634 * @beaninfo
1635 1635 * preferred: true
1636 1636 * bound: true
1637 1637 * description: The preferred size of the component.
1638 1638 */
1639 1639 public void setPreferredSize(Dimension preferredSize) {
1640 1640 super.setPreferredSize(preferredSize);
1641 1641 }
1642 1642
1643 1643
1644 1644 /**
1645 1645 * If the <code>preferredSize</code> has been set to a
1646 1646 * non-<code>null</code> value just returns it.
1647 1647 * If the UI delegate's <code>getPreferredSize</code>
1648 1648 * method returns a non <code>null</code> value then return that;
1649 1649 * otherwise defer to the component's layout manager.
1650 1650 *
1651 1651 * @return the value of the <code>preferredSize</code> property
1652 1652 * @see #setPreferredSize
1653 1653 * @see ComponentUI
1654 1654 */
1655 1655 @Transient
1656 1656 public Dimension getPreferredSize() {
1657 1657 if (isPreferredSizeSet()) {
1658 1658 return super.getPreferredSize();
1659 1659 }
1660 1660 Dimension size = null;
1661 1661 if (ui != null) {
1662 1662 size = ui.getPreferredSize(this);
1663 1663 }
1664 1664 return (size != null) ? size : super.getPreferredSize();
1665 1665 }
1666 1666
1667 1667
1668 1668 /**
1669 1669 * Sets the maximum size of this component to a constant
1670 1670 * value. Subsequent calls to <code>getMaximumSize</code> will always
1671 1671 * return this value; the component's UI will not be asked
1672 1672 * to compute it. Setting the maximum size to <code>null</code>
1673 1673 * restores the default behavior.
1674 1674 *
1675 1675 * @param maximumSize a <code>Dimension</code> containing the
1676 1676 * desired maximum allowable size
1677 1677 * @see #getMaximumSize
1678 1678 * @beaninfo
1679 1679 * bound: true
1680 1680 * description: The maximum size of the component.
1681 1681 */
1682 1682 public void setMaximumSize(Dimension maximumSize) {
1683 1683 super.setMaximumSize(maximumSize);
1684 1684 }
1685 1685
1686 1686
1687 1687 /**
1688 1688 * If the maximum size has been set to a non-<code>null</code> value
1689 1689 * just returns it. If the UI delegate's <code>getMaximumSize</code>
1690 1690 * method returns a non-<code>null</code> value then return that;
1691 1691 * otherwise defer to the component's layout manager.
1692 1692 *
1693 1693 * @return the value of the <code>maximumSize</code> property
1694 1694 * @see #setMaximumSize
1695 1695 * @see ComponentUI
1696 1696 */
1697 1697 @Transient
1698 1698 public Dimension getMaximumSize() {
1699 1699 if (isMaximumSizeSet()) {
1700 1700 return super.getMaximumSize();
1701 1701 }
1702 1702 Dimension size = null;
1703 1703 if (ui != null) {
1704 1704 size = ui.getMaximumSize(this);
1705 1705 }
1706 1706 return (size != null) ? size : super.getMaximumSize();
1707 1707 }
1708 1708
1709 1709
1710 1710 /**
1711 1711 * Sets the minimum size of this component to a constant
1712 1712 * value. Subsequent calls to <code>getMinimumSize</code> will always
1713 1713 * return this value; the component's UI will not be asked
1714 1714 * to compute it. Setting the minimum size to <code>null</code>
1715 1715 * restores the default behavior.
1716 1716 *
1717 1717 * @param minimumSize the new minimum size of this component
1718 1718 * @see #getMinimumSize
1719 1719 * @beaninfo
1720 1720 * bound: true
1721 1721 * description: The minimum size of the component.
1722 1722 */
1723 1723 public void setMinimumSize(Dimension minimumSize) {
1724 1724 super.setMinimumSize(minimumSize);
1725 1725 }
1726 1726
1727 1727 /**
1728 1728 * If the minimum size has been set to a non-<code>null</code> value
1729 1729 * just returns it. If the UI delegate's <code>getMinimumSize</code>
1730 1730 * method returns a non-<code>null</code> value then return that; otherwise
1731 1731 * defer to the component's layout manager.
1732 1732 *
1733 1733 * @return the value of the <code>minimumSize</code> property
1734 1734 * @see #setMinimumSize
1735 1735 * @see ComponentUI
1736 1736 */
1737 1737 @Transient
1738 1738 public Dimension getMinimumSize() {
1739 1739 if (isMinimumSizeSet()) {
1740 1740 return super.getMinimumSize();
1741 1741 }
1742 1742 Dimension size = null;
1743 1743 if (ui != null) {
1744 1744 size = ui.getMinimumSize(this);
1745 1745 }
1746 1746 return (size != null) ? size : super.getMinimumSize();
1747 1747 }
1748 1748
1749 1749 /**
1750 1750 * Gives the UI delegate an opportunity to define the precise
1751 1751 * shape of this component for the sake of mouse processing.
1752 1752 *
1753 1753 * @return true if this component logically contains x,y
1754 1754 * @see java.awt.Component#contains(int, int)
1755 1755 * @see ComponentUI
1756 1756 */
1757 1757 public boolean contains(int x, int y) {
1758 1758 return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
1759 1759 }
1760 1760
1761 1761 /**
1762 1762 * Sets the border of this component. The <code>Border</code> object is
1763 1763 * responsible for defining the insets for the component
1764 1764 * (overriding any insets set directly on the component) and
1765 1765 * for optionally rendering any border decorations within the
1766 1766 * bounds of those insets. Borders should be used (rather
1767 1767 * than insets) for creating both decorative and non-decorative
1768 1768 * (such as margins and padding) regions for a swing component.
1769 1769 * Compound borders can be used to nest multiple borders within a
1770 1770 * single component.
1771 1771 * <p>
1772 1772 * Although technically you can set the border on any object
1773 1773 * that inherits from <code>JComponent</code>, the look and
1774 1774 * feel implementation of many standard Swing components
1775 1775 * doesn't work well with user-set borders. In general,
1776 1776 * when you want to set a border on a standard Swing
1777 1777 * component other than <code>JPanel</code> or <code>JLabel</code>,
1778 1778 * we recommend that you put the component in a <code>JPanel</code>
1779 1779 * and set the border on the <code>JPanel</code>.
1780 1780 * <p>
1781 1781 * This is a bound property.
1782 1782 *
1783 1783 * @param border the border to be rendered for this component
1784 1784 * @see Border
1785 1785 * @see CompoundBorder
1786 1786 * @beaninfo
1787 1787 * bound: true
1788 1788 * preferred: true
1789 1789 * attribute: visualUpdate true
1790 1790 * description: The component's border.
1791 1791 */
1792 1792 public void setBorder(Border border) {
1793 1793 Border oldBorder = this.border;
1794 1794
1795 1795 this.border = border;
1796 1796 firePropertyChange("border", oldBorder, border);
1797 1797 if (border != oldBorder) {
1798 1798 if (border == null || oldBorder == null ||
1799 1799 !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
1800 1800 revalidate();
1801 1801 }
1802 1802 repaint();
1803 1803 }
1804 1804 }
1805 1805
1806 1806 /**
1807 1807 * Returns the border of this component or <code>null</code> if no
1808 1808 * border is currently set.
1809 1809 *
1810 1810 * @return the border object for this component
1811 1811 * @see #setBorder
1812 1812 */
1813 1813 public Border getBorder() {
1814 1814 return border;
1815 1815 }
1816 1816
1817 1817 /**
1818 1818 * If a border has been set on this component, returns the
1819 1819 * border's insets; otherwise calls <code>super.getInsets</code>.
1820 1820 *
1821 1821 * @return the value of the insets property
1822 1822 * @see #setBorder
1823 1823 */
1824 1824 public Insets getInsets() {
1825 1825 if (border != null) {
1826 1826 return border.getBorderInsets(this);
1827 1827 }
1828 1828 return super.getInsets();
1829 1829 }
1830 1830
1831 1831 /**
1832 1832 * Returns an <code>Insets</code> object containing this component's inset
1833 1833 * values. The passed-in <code>Insets</code> object will be reused
1834 1834 * if possible.
1835 1835 * Calling methods cannot assume that the same object will be returned,
1836 1836 * however. All existing values within this object are overwritten.
1837 1837 * If <code>insets</code> is null, this will allocate a new one.
1838 1838 *
1839 1839 * @param insets the <code>Insets</code> object, which can be reused
1840 1840 * @return the <code>Insets</code> object
1841 1841 * @see #getInsets
1842 1842 * @beaninfo
1843 1843 * expert: true
1844 1844 */
1845 1845 public Insets getInsets(Insets insets) {
1846 1846 if (insets == null) {
1847 1847 insets = new Insets(0, 0, 0, 0);
1848 1848 }
1849 1849 if (border != null) {
1850 1850 if (border instanceof AbstractBorder) {
1851 1851 return ((AbstractBorder)border).getBorderInsets(this, insets);
1852 1852 } else {
1853 1853 // Can't reuse border insets because the Border interface
1854 1854 // can't be enhanced.
1855 1855 return border.getBorderInsets(this);
1856 1856 }
1857 1857 } else {
1858 1858 // super.getInsets() always returns an Insets object with
1859 1859 // all of its value zeroed. No need for a new object here.
1860 1860 insets.left = insets.top = insets.right = insets.bottom = 0;
1861 1861 return insets;
1862 1862 }
1863 1863 }
1864 1864
1865 1865 /**
1866 1866 * Overrides <code>Container.getAlignmentY</code> to return
1867 1867 * the horizontal alignment.
1868 1868 *
1869 1869 * @return the value of the <code>alignmentY</code> property
1870 1870 * @see #setAlignmentY
1871 1871 * @see java.awt.Component#getAlignmentY
1872 1872 */
1873 1873 public float getAlignmentY() {
1874 1874 if (isAlignmentYSet) {
1875 1875 return alignmentY;
1876 1876 }
1877 1877 return super.getAlignmentY();
1878 1878 }
1879 1879
1880 1880 /**
1881 1881 * Sets the the horizontal alignment.
1882 1882 *
1883 1883 * @param alignmentY the new horizontal alignment
1884 1884 * @see #getAlignmentY
1885 1885 * @beaninfo
1886 1886 * description: The preferred vertical alignment of the component.
1887 1887 */
1888 1888 public void setAlignmentY(float alignmentY) {
1889 1889 this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY;
1890 1890 isAlignmentYSet = true;
1891 1891 }
1892 1892
1893 1893
1894 1894 /**
1895 1895 * Overrides <code>Container.getAlignmentX</code> to return
1896 1896 * the vertical alignment.
1897 1897 *
1898 1898 * @return the value of the <code>alignmentX</code> property
1899 1899 * @see #setAlignmentX
1900 1900 * @see java.awt.Component#getAlignmentX
1901 1901 */
1902 1902 public float getAlignmentX() {
1903 1903 if (isAlignmentXSet) {
1904 1904 return alignmentX;
1905 1905 }
1906 1906 return super.getAlignmentX();
1907 1907 }
1908 1908
1909 1909 /**
1910 1910 * Sets the the vertical alignment.
1911 1911 *
1912 1912 * @param alignmentX the new vertical alignment
1913 1913 * @see #getAlignmentX
1914 1914 * @beaninfo
1915 1915 * description: The preferred horizontal alignment of the component.
1916 1916 */
1917 1917 public void setAlignmentX(float alignmentX) {
1918 1918 this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX;
1919 1919 isAlignmentXSet = true;
1920 1920 }
1921 1921
1922 1922 /**
1923 1923 * Sets the input verifier for this component.
1924 1924 *
1925 1925 * @param inputVerifier the new input verifier
1926 1926 * @since 1.3
1927 1927 * @see InputVerifier
1928 1928 * @beaninfo
1929 1929 * bound: true
1930 1930 * description: The component's input verifier.
1931 1931 */
1932 1932 public void setInputVerifier(InputVerifier inputVerifier) {
1933 1933 InputVerifier oldInputVerifier = (InputVerifier)getClientProperty(
1934 1934 JComponent_INPUT_VERIFIER);
1935 1935 putClientProperty(JComponent_INPUT_VERIFIER, inputVerifier);
1936 1936 firePropertyChange("inputVerifier", oldInputVerifier, inputVerifier);
1937 1937 }
1938 1938
1939 1939 /**
1940 1940 * Returns the input verifier for this component.
1941 1941 *
1942 1942 * @return the <code>inputVerifier</code> property
1943 1943 * @since 1.3
1944 1944 * @see InputVerifier
1945 1945 */
1946 1946 public InputVerifier getInputVerifier() {
1947 1947 return (InputVerifier)getClientProperty(JComponent_INPUT_VERIFIER);
1948 1948 }
1949 1949
1950 1950 /**
1951 1951 * Returns this component's graphics context, which lets you draw
1952 1952 * on a component. Use this method to get a <code>Graphics</code> object and
1953 1953 * then invoke operations on that object to draw on the component.
1954 1954 * @return this components graphics context
1955 1955 */
1956 1956 public Graphics getGraphics() {
1957 1957 if (DEBUG_GRAPHICS_LOADED && shouldDebugGraphics() != 0) {
1958 1958 DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
1959 1959 this);
1960 1960 return graphics;
1961 1961 }
1962 1962 return super.getGraphics();
1963 1963 }
1964 1964
1965 1965
1966 1966 /** Enables or disables diagnostic information about every graphics
1967 1967 * operation performed within the component or one of its children.
1968 1968 *
1969 1969 * @param debugOptions determines how the component should display
1970 1970 * the information; one of the following options:
1971 1971 * <ul>
1972 1972 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1973 1973 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1974 1974 * times.
1975 1975 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1976 1976 * <code>ExternalWindow</code> that displays the operations
1977 1977 * performed on the View's offscreen buffer.
1978 1978 * <li>DebugGraphics.NONE_OPTION disables debugging.
1979 1979 * <li>A value of 0 causes no changes to the debugging options.
1980 1980 * </ul>
1981 1981 * <code>debugOptions</code> is bitwise OR'd into the current value
1982 1982 *
1983 1983 * @beaninfo
1984 1984 * preferred: true
1985 1985 * enum: NONE_OPTION DebugGraphics.NONE_OPTION
1986 1986 * LOG_OPTION DebugGraphics.LOG_OPTION
1987 1987 * FLASH_OPTION DebugGraphics.FLASH_OPTION
1988 1988 * BUFFERED_OPTION DebugGraphics.BUFFERED_OPTION
1989 1989 * description: Diagnostic options for graphics operations.
1990 1990 */
1991 1991 public void setDebugGraphicsOptions(int debugOptions) {
1992 1992 DebugGraphics.setDebugOptions(this, debugOptions);
1993 1993 }
1994 1994
1995 1995 /** Returns the state of graphics debugging.
1996 1996 *
1997 1997 * @return a bitwise OR'd flag of zero or more of the following options:
1998 1998 * <ul>
1999 1999 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
2000 2000 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
2001 2001 * times.
2002 2002 * <li>DebugGraphics.BUFFERED_OPTION - creates an
2003 2003 * <code>ExternalWindow</code> that displays the operations
2004 2004 * performed on the View's offscreen buffer.
2005 2005 * <li>DebugGraphics.NONE_OPTION disables debugging.
2006 2006 * <li>A value of 0 causes no changes to the debugging options.
2007 2007 * </ul>
2008 2008 * @see #setDebugGraphicsOptions
2009 2009 */
2010 2010 public int getDebugGraphicsOptions() {
2011 2011 return DebugGraphics.getDebugOptions(this);
2012 2012 }
2013 2013
2014 2014
2015 2015 /**
2016 2016 * Returns true if debug information is enabled for this
2017 2017 * <code>JComponent</code> or one of its parents.
2018 2018 */
2019 2019 int shouldDebugGraphics() {
2020 2020 return DebugGraphics.shouldComponentDebug(this);
2021 2021 }
2022 2022
2023 2023 /**
2024 2024 * This method is now obsolete, please use a combination of
2025 2025 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2026 2026 * similar behavior. For example, to bind the <code>KeyStroke</code>
2027 2027 * <code>aKeyStroke</code> to the <code>Action</code> <code>anAction</code>
2028 2028 * now use:
2029 2029 * <pre>
2030 2030 * component.getInputMap().put(aKeyStroke, aCommand);
2031 2031 * component.getActionMap().put(aCommmand, anAction);
2032 2032 * </pre>
2033 2033 * The above assumes you want the binding to be applicable for
2034 2034 * <code>WHEN_FOCUSED</code>. To register bindings for other focus
2035 2035 * states use the <code>getInputMap</code> method that takes an integer.
2036 2036 * <p>
2037 2037 * Register a new keyboard action.
2038 2038 * <code>anAction</code> will be invoked if a key event matching
2039 2039 * <code>aKeyStroke</code> occurs and <code>aCondition</code> is verified.
2040 2040 * The <code>KeyStroke</code> object defines a
2041 2041 * particular combination of a keyboard key and one or more modifiers
2042 2042 * (alt, shift, ctrl, meta).
2043 2043 * <p>
2044 2044 * The <code>aCommand</code> will be set in the delivered event if
2045 2045 * specified.
2046 2046 * <p>
2047 2047 * The <code>aCondition</code> can be one of:
2048 2048 * <blockquote>
2049 2049 * <DL>
2050 2050 * <DT>WHEN_FOCUSED
2051 2051 * <DD>The action will be invoked only when the keystroke occurs
2052 2052 * while the component has the focus.
2053 2053 * <DT>WHEN_IN_FOCUSED_WINDOW
2054 2054 * <DD>The action will be invoked when the keystroke occurs while
2055 2055 * the component has the focus or if the component is in the
2056 2056 * window that has the focus. Note that the component need not
2057 2057 * be an immediate descendent of the window -- it can be
2058 2058 * anywhere in the window's containment hierarchy. In other
2059 2059 * words, whenever <em>any</em> component in the window has the focus,
2060 2060 * the action registered with this component is invoked.
2061 2061 * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2062 2062 * <DD>The action will be invoked when the keystroke occurs while the
2063 2063 * component has the focus or if the component is an ancestor of
2064 2064 * the component that has the focus.
2065 2065 * </DL>
2066 2066 * </blockquote>
2067 2067 * <p>
2068 2068 * The combination of keystrokes and conditions lets you define high
2069 2069 * level (semantic) action events for a specified keystroke+modifier
2070 2070 * combination (using the KeyStroke class) and direct to a parent or
2071 2071 * child of a component that has the focus, or to the component itself.
2072 2072 * In other words, in any hierarchical structure of components, an
2073 2073 * arbitrary key-combination can be immediately directed to the
2074 2074 * appropriate component in the hierarchy, and cause a specific method
2075 2075 * to be invoked (usually by way of adapter objects).
2076 2076 * <p>
2077 2077 * If an action has already been registered for the receiving
2078 2078 * container, with the same charCode and the same modifiers,
2079 2079 * <code>anAction</code> will replace the action.
2080 2080 *
2081 2081 * @param anAction the <code>Action</code> to be registered
2082 2082 * @param aCommand the command to be set in the delivered event
2083 2083 * @param aKeyStroke the <code>KeyStroke</code> to bind to the action
2084 2084 * @param aCondition the condition that needs to be met, see above
2085 2085 * @see KeyStroke
2086 2086 */
2087 2087 public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
2088 2088
2089 2089 InputMap inputMap = getInputMap(aCondition, true);
2090 2090
2091 2091 if (inputMap != null) {
2092 2092 ActionMap actionMap = getActionMap(true);
2093 2093 ActionStandin action = new ActionStandin(anAction, aCommand);
2094 2094 inputMap.put(aKeyStroke, action);
2095 2095 if (actionMap != null) {
2096 2096 actionMap.put(action, action);
2097 2097 }
2098 2098 }
2099 2099 }
2100 2100
2101 2101 /**
2102 2102 * Registers any bound <code>WHEN_IN_FOCUSED_WINDOW</code> actions with
2103 2103 * the <code>KeyboardManager</code>. If <code>onlyIfNew</code>
2104 2104 * is true only actions that haven't been registered are pushed
2105 2105 * to the <code>KeyboardManager</code>;
2106 2106 * otherwise all actions are pushed to the <code>KeyboardManager</code>.
2107 2107 *
2108 2108 * @param onlyIfNew if true, only actions that haven't been registered
2109 2109 * are pushed to the <code>KeyboardManager</code>
2110 2110 */
2111 2111 private void registerWithKeyboardManager(boolean onlyIfNew) {
2112 2112 InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2113 2113 KeyStroke[] strokes;
2114 2114 Hashtable<KeyStroke, KeyStroke> registered =
2115 2115 (Hashtable<KeyStroke, KeyStroke>)getClientProperty
2116 2116 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2117 2117
2118 2118 if (inputMap != null) {
2119 2119 // Push any new KeyStrokes to the KeyboardManager.
2120 2120 strokes = inputMap.allKeys();
2121 2121 if (strokes != null) {
2122 2122 for (int counter = strokes.length - 1; counter >= 0;
2123 2123 counter--) {
2124 2124 if (!onlyIfNew || registered == null ||
2125 2125 registered.get(strokes[counter]) == null) {
2126 2126 registerWithKeyboardManager(strokes[counter]);
2127 2127 }
2128 2128 if (registered != null) {
2129 2129 registered.remove(strokes[counter]);
2130 2130 }
2131 2131 }
2132 2132 }
2133 2133 }
2134 2134 else {
2135 2135 strokes = null;
2136 2136 }
2137 2137 // Remove any old ones.
2138 2138 if (registered != null && registered.size() > 0) {
2139 2139 Enumeration<KeyStroke> keys = registered.keys();
2140 2140
2141 2141 while (keys.hasMoreElements()) {
2142 2142 KeyStroke ks = keys.nextElement();
2143 2143 unregisterWithKeyboardManager(ks);
2144 2144 }
2145 2145 registered.clear();
2146 2146 }
2147 2147 // Updated the registered Hashtable.
2148 2148 if (strokes != null && strokes.length > 0) {
2149 2149 if (registered == null) {
2150 2150 registered = new Hashtable<KeyStroke, KeyStroke>(strokes.length);
2151 2151 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, registered);
2152 2152 }
2153 2153 for (int counter = strokes.length - 1; counter >= 0; counter--) {
2154 2154 registered.put(strokes[counter], strokes[counter]);
2155 2155 }
2156 2156 }
2157 2157 else {
2158 2158 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2159 2159 }
2160 2160 }
2161 2161
2162 2162 /**
2163 2163 * Unregisters all the previously registered
2164 2164 * <code>WHEN_IN_FOCUSED_WINDOW</code> <code>KeyStroke</code> bindings.
2165 2165 */
2166 2166 private void unregisterWithKeyboardManager() {
2167 2167 Hashtable<KeyStroke, KeyStroke> registered =
2168 2168 (Hashtable<KeyStroke, KeyStroke>)getClientProperty
2169 2169 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2170 2170
2171 2171 if (registered != null && registered.size() > 0) {
2172 2172 Enumeration<KeyStroke> keys = registered.keys();
2173 2173
2174 2174 while (keys.hasMoreElements()) {
2175 2175 KeyStroke ks = keys.nextElement();
2176 2176 unregisterWithKeyboardManager(ks);
2177 2177 }
2178 2178 }
2179 2179 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2180 2180 }
2181 2181
2182 2182 /**
2183 2183 * Invoked from <code>ComponentInputMap</code> when its bindings change.
2184 2184 * If <code>inputMap</code> is the current <code>windowInputMap</code>
2185 2185 * (or a parent of the window <code>InputMap</code>)
2186 2186 * the <code>KeyboardManager</code> is notified of the new bindings.
2187 2187 *
2188 2188 * @param inputMap the map containing the new bindings
2189 2189 */
2190 2190 void componentInputMapChanged(ComponentInputMap inputMap) {
2191 2191 InputMap km = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2192 2192
2193 2193 while (km != inputMap && km != null) {
2194 2194 km = km.getParent();
2195 2195 }
2196 2196 if (km != null) {
2197 2197 registerWithKeyboardManager(false);
2198 2198 }
2199 2199 }
2200 2200
2201 2201 private void registerWithKeyboardManager(KeyStroke aKeyStroke) {
2202 2202 KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke,this);
2203 2203 }
2204 2204
2205 2205 private void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
2206 2206 KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke,
2207 2207 this);
2208 2208 }
2209 2209
2210 2210 /**
2211 2211 * This method is now obsolete, please use a combination of
2212 2212 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2213 2213 * similar behavior.
2214 2214 */
2215 2215 public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
2216 2216 registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
2217 2217 }
2218 2218
2219 2219 /**
2220 2220 * This method is now obsolete. To unregister an existing binding
2221 2221 * you can either remove the binding from the
2222 2222 * <code>ActionMap/InputMap</code>, or place a dummy binding the
2223 2223 * <code>InputMap</code>. Removing the binding from the
2224 2224 * <code>InputMap</code> allows bindings in parent <code>InputMap</code>s
2225 2225 * to be active, whereas putting a dummy binding in the
2226 2226 * <code>InputMap</code> effectively disables
2227 2227 * the binding from ever happening.
2228 2228 * <p>
2229 2229 * Unregisters a keyboard action.
2230 2230 * This will remove the binding from the <code>ActionMap</code>
2231 2231 * (if it exists) as well as the <code>InputMap</code>s.
2232 2232 */
2233 2233 public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
2234 2234 ActionMap am = getActionMap(false);
2235 2235 for (int counter = 0; counter < 3; counter++) {
2236 2236 InputMap km = getInputMap(counter, false);
2237 2237 if (km != null) {
2238 2238 Object actionID = km.get(aKeyStroke);
2239 2239
2240 2240 if (am != null && actionID != null) {
2241 2241 am.remove(actionID);
2242 2242 }
2243 2243 km.remove(aKeyStroke);
2244 2244 }
2245 2245 }
2246 2246 }
2247 2247
2248 2248 /**
2249 2249 * Returns the <code>KeyStrokes</code> that will initiate
2250 2250 * registered actions.
2251 2251 *
2252 2252 * @return an array of <code>KeyStroke</code> objects
2253 2253 * @see #registerKeyboardAction
2254 2254 */
2255 2255 public KeyStroke[] getRegisteredKeyStrokes() {
2256 2256 int[] counts = new int[3];
2257 2257 KeyStroke[][] strokes = new KeyStroke[3][];
2258 2258
2259 2259 for (int counter = 0; counter < 3; counter++) {
2260 2260 InputMap km = getInputMap(counter, false);
2261 2261 strokes[counter] = (km != null) ? km.allKeys() : null;
2262 2262 counts[counter] = (strokes[counter] != null) ?
2263 2263 strokes[counter].length : 0;
2264 2264 }
2265 2265 KeyStroke[] retValue = new KeyStroke[counts[0] + counts[1] +
2266 2266 counts[2]];
2267 2267 for (int counter = 0, last = 0; counter < 3; counter++) {
2268 2268 if (counts[counter] > 0) {
2269 2269 System.arraycopy(strokes[counter], 0, retValue, last,
2270 2270 counts[counter]);
2271 2271 last += counts[counter];
2272 2272 }
2273 2273 }
2274 2274 return retValue;
2275 2275 }
2276 2276
2277 2277 /**
2278 2278 * Returns the condition that determines whether a registered action
2279 2279 * occurs in response to the specified keystroke.
2280 2280 * <p>
2281 2281 * For Java 2 platform v1.3, a <code>KeyStroke</code> can be associated
2282 2282 * with more than one condition.
2283 2283 * For example, 'a' could be bound for the two
2284 2284 * conditions <code>WHEN_FOCUSED</code> and
2285 2285 * <code>WHEN_IN_FOCUSED_WINDOW</code> condition.
2286 2286 *
2287 2287 * @return the action-keystroke condition
2288 2288 */
2289 2289 public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
2290 2290 for (int counter = 0; counter < 3; counter++) {
2291 2291 InputMap inputMap = getInputMap(counter, false);
2292 2292 if (inputMap != null && inputMap.get(aKeyStroke) != null) {
2293 2293 return counter;
2294 2294 }
2295 2295 }
2296 2296 return UNDEFINED_CONDITION;
2297 2297 }
2298 2298
2299 2299 /**
2300 2300 * Returns the object that will perform the action registered for a
2301 2301 * given keystroke.
2302 2302 *
2303 2303 * @return the <code>ActionListener</code>
2304 2304 * object invoked when the keystroke occurs
2305 2305 */
2306 2306 public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
2307 2307 ActionMap am = getActionMap(false);
2308 2308
2309 2309 if (am == null) {
2310 2310 return null;
2311 2311 }
2312 2312 for (int counter = 0; counter < 3; counter++) {
2313 2313 InputMap inputMap = getInputMap(counter, false);
2314 2314 if (inputMap != null) {
2315 2315 Object actionBinding = inputMap.get(aKeyStroke);
2316 2316
2317 2317 if (actionBinding != null) {
2318 2318 Action action = am.get(actionBinding);
2319 2319 if (action instanceof ActionStandin) {
2320 2320 return ((ActionStandin)action).actionListener;
2321 2321 }
2322 2322 return action;
2323 2323 }
2324 2324 }
2325 2325 }
2326 2326 return null;
2327 2327 }
2328 2328
2329 2329 /**
2330 2330 * Unregisters all the bindings in the first tier <code>InputMaps</code>
2331 2331 * and <code>ActionMap</code>. This has the effect of removing any
2332 2332 * local bindings, and allowing the bindings defined in parent
2333 2333 * <code>InputMap/ActionMaps</code>
2334 2334 * (the UI is usually defined in the second tier) to persist.
2335 2335 */
2336 2336 public void resetKeyboardActions() {
2337 2337 // Keys
2338 2338 for (int counter = 0; counter < 3; counter++) {
2339 2339 InputMap inputMap = getInputMap(counter, false);
2340 2340
2341 2341 if (inputMap != null) {
2342 2342 inputMap.clear();
2343 2343 }
2344 2344 }
2345 2345
2346 2346 // Actions
2347 2347 ActionMap am = getActionMap(false);
2348 2348
2349 2349 if (am != null) {
2350 2350 am.clear();
2351 2351 }
2352 2352 }
2353 2353
2354 2354 /**
2355 2355 * Sets the <code>InputMap</code> to use under the condition
2356 2356 * <code>condition</code> to
2357 2357 * <code>map</code>. A <code>null</code> value implies you
2358 2358 * do not want any bindings to be used, even from the UI. This will
2359 2359 * not reinstall the UI <code>InputMap</code> (if there was one).
2360 2360 * <code>condition</code> has one of the following values:
2361 2361 * <ul>
2362 2362 * <li><code>WHEN_IN_FOCUSED_WINDOW</code>
2363 2363 * <li><code>WHEN_FOCUSED</code>
2364 2364 * <li><code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code>
2365 2365 * </ul>
2366 2366 * If <code>condition</code> is <code>WHEN_IN_FOCUSED_WINDOW</code>
2367 2367 * and <code>map</code> is not a <code>ComponentInputMap</code>, an
2368 2368 * <code>IllegalArgumentException</code> will be thrown.
2369 2369 * Similarly, if <code>condition</code> is not one of the values
2370 2370 * listed, an <code>IllegalArgumentException</code> will be thrown.
2371 2371 *
2372 2372 * @param condition one of the values listed above
2373 2373 * @param map the <code>InputMap</code> to use for the given condition
2374 2374 * @exception IllegalArgumentException if <code>condition</code> is
2375 2375 * <code>WHEN_IN_FOCUSED_WINDOW</code> and <code>map</code>
2376 2376 * is not an instance of <code>ComponentInputMap</code>; or
2377 2377 * if <code>condition</code> is not one of the legal values
2378 2378 * specified above
2379 2379 * @since 1.3
2380 2380 */
2381 2381 public final void setInputMap(int condition, InputMap map) {
2382 2382 switch (condition) {
2383 2383 case WHEN_IN_FOCUSED_WINDOW:
2384 2384 if (map != null && !(map instanceof ComponentInputMap)) {
2385 2385 throw new IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW InputMaps must be of type ComponentInputMap");
2386 2386 }
2387 2387 windowInputMap = (ComponentInputMap)map;
2388 2388 setFlag(WIF_INPUTMAP_CREATED, true);
2389 2389 registerWithKeyboardManager(false);
2390 2390 break;
2391 2391 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2392 2392 ancestorInputMap = map;
2393 2393 setFlag(ANCESTOR_INPUTMAP_CREATED, true);
2394 2394 break;
2395 2395 case WHEN_FOCUSED:
2396 2396 focusInputMap = map;
2397 2397 setFlag(FOCUS_INPUTMAP_CREATED, true);
2398 2398 break;
2399 2399 default:
2400 2400 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2401 2401 }
2402 2402 }
2403 2403
2404 2404 /**
2405 2405 * Returns the <code>InputMap</code> that is used during
2406 2406 * <code>condition</code>.
2407 2407 *
2408 2408 * @param condition one of WHEN_IN_FOCUSED_WINDOW, WHEN_FOCUSED,
2409 2409 * WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2410 2410 * @return the <code>InputMap</code> for the specified
2411 2411 * <code>condition</code>
2412 2412 * @since 1.3
2413 2413 */
2414 2414 public final InputMap getInputMap(int condition) {
2415 2415 return getInputMap(condition, true);
2416 2416 }
2417 2417
2418 2418 /**
2419 2419 * Returns the <code>InputMap</code> that is used when the
2420 2420 * component has focus.
2421 2421 * This is convenience method for <code>getInputMap(WHEN_FOCUSED)</code>.
2422 2422 *
2423 2423 * @return the <code>InputMap</code> used when the component has focus
2424 2424 * @since 1.3
2425 2425 */
2426 2426 public final InputMap getInputMap() {
2427 2427 return getInputMap(WHEN_FOCUSED, true);
2428 2428 }
2429 2429
2430 2430 /**
2431 2431 * Sets the <code>ActionMap</code> to <code>am</code>. This does not set
2432 2432 * the parent of the <code>am</code> to be the <code>ActionMap</code>
2433 2433 * from the UI (if there was one), it is up to the caller to have done this.
2434 2434 *
2435 2435 * @param am the new <code>ActionMap</code>
2436 2436 * @since 1.3
2437 2437 */
2438 2438 public final void setActionMap(ActionMap am) {
2439 2439 actionMap = am;
2440 2440 setFlag(ACTIONMAP_CREATED, true);
2441 2441 }
2442 2442
2443 2443 /**
2444 2444 * Returns the <code>ActionMap</code> used to determine what
2445 2445 * <code>Action</code> to fire for particular <code>KeyStroke</code>
2446 2446 * binding. The returned <code>ActionMap</code>, unless otherwise
2447 2447 * set, will have the <code>ActionMap</code> from the UI set as the parent.
2448 2448 *
2449 2449 * @return the <code>ActionMap</code> containing the key/action bindings
2450 2450 * @since 1.3
2451 2451 */
2452 2452 public final ActionMap getActionMap() {
2453 2453 return getActionMap(true);
2454 2454 }
2455 2455
2456 2456 /**
2457 2457 * Returns the <code>InputMap</code> to use for condition
2458 2458 * <code>condition</code>. If the <code>InputMap</code> hasn't
2459 2459 * been created, and <code>create</code> is
2460 2460 * true, it will be created.
2461 2461 *
2462 2462 * @param condition one of the following values:
2463 2463 * <ul>
2464 2464 * <li>JComponent.FOCUS_INPUTMAP_CREATED
2465 2465 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2466 2466 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2467 2467 * </ul>
2468 2468 * @param create if true, create the <code>InputMap</code> if it
2469 2469 * is not already created
2470 2470 * @return the <code>InputMap</code> for the given <code>condition</code>;
2471 2471 * if <code>create</code> is false and the <code>InputMap</code>
2472 2472 * hasn't been created, returns <code>null</code>
2473 2473 * @exception IllegalArgumentException if <code>condition</code>
2474 2474 * is not one of the legal values listed above
2475 2475 */
2476 2476 final InputMap getInputMap(int condition, boolean create) {
2477 2477 switch (condition) {
2478 2478 case WHEN_FOCUSED:
2479 2479 if (getFlag(FOCUS_INPUTMAP_CREATED)) {
2480 2480 return focusInputMap;
2481 2481 }
2482 2482 // Hasn't been created yet.
2483 2483 if (create) {
2484 2484 InputMap km = new InputMap();
2485 2485 setInputMap(condition, km);
2486 2486 return km;
2487 2487 }
2488 2488 break;
2489 2489 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2490 2490 if (getFlag(ANCESTOR_INPUTMAP_CREATED)) {
2491 2491 return ancestorInputMap;
2492 2492 }
2493 2493 // Hasn't been created yet.
2494 2494 if (create) {
2495 2495 InputMap km = new InputMap();
2496 2496 setInputMap(condition, km);
2497 2497 return km;
2498 2498 }
2499 2499 break;
2500 2500 case WHEN_IN_FOCUSED_WINDOW:
2501 2501 if (getFlag(WIF_INPUTMAP_CREATED)) {
2502 2502 return windowInputMap;
2503 2503 }
2504 2504 // Hasn't been created yet.
2505 2505 if (create) {
2506 2506 ComponentInputMap km = new ComponentInputMap(this);
2507 2507 setInputMap(condition, km);
2508 2508 return km;
2509 2509 }
2510 2510 break;
2511 2511 default:
2512 2512 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2513 2513 }
2514 2514 return null;
2515 2515 }
2516 2516
2517 2517 /**
2518 2518 * Finds and returns the appropriate <code>ActionMap</code>.
2519 2519 *
2520 2520 * @param create if true, create the <code>ActionMap</code> if it
2521 2521 * is not already created
2522 2522 * @return the <code>ActionMap</code> for this component; if the
2523 2523 * <code>create</code> flag is false and there is no
2524 2524 * current <code>ActionMap</code>, returns <code>null</code>
2525 2525 */
2526 2526 final ActionMap getActionMap(boolean create) {
2527 2527 if (getFlag(ACTIONMAP_CREATED)) {
2528 2528 return actionMap;
2529 2529 }
2530 2530 // Hasn't been created.
2531 2531 if (create) {
2532 2532 ActionMap am = new ActionMap();
2533 2533 setActionMap(am);
2534 2534 return am;
2535 2535 }
2536 2536 return null;
2537 2537 }
2538 2538
2539 2539 /**
2540 2540 * Returns the baseline. The baseline is measured from the top of
2541 2541 * the component. This method is primarily meant for
2542 2542 * <code>LayoutManager</code>s to align components along their
2543 2543 * baseline. A return value less than 0 indicates this component
2544 2544 * does not have a reasonable baseline and that
2545 2545 * <code>LayoutManager</code>s should not align this component on
2546 2546 * its baseline.
2547 2547 * <p>
2548 2548 * This method calls into the <code>ComponentUI</code> method of the
2549 2549 * same name. If this component does not have a <code>ComponentUI</code>
2550 2550 * -1 will be returned. If a value >= 0 is
2551 2551 * returned, then the component has a valid baseline for any
2552 2552 * size >= the minimum size and <code>getBaselineResizeBehavior</code>
2553 2553 * can be used to determine how the baseline changes with size.
2554 2554 *
2555 2555 * @throws IllegalArgumentException {@inheritDoc}
2556 2556 * @see #getBaselineResizeBehavior
2557 2557 * @see java.awt.FontMetrics
2558 2558 * @since 1.6
2559 2559 */
2560 2560 public int getBaseline(int width, int height) {
2561 2561 // check size.
2562 2562 super.getBaseline(width, height);
2563 2563 if (ui != null) {
2564 2564 return ui.getBaseline(this, width, height);
2565 2565 }
2566 2566 return -1;
2567 2567 }
2568 2568
2569 2569 /**
2570 2570 * Returns an enum indicating how the baseline of the component
2571 2571 * changes as the size changes. This method is primarily meant for
2572 2572 * layout managers and GUI builders.
2573 2573 * <p>
2574 2574 * This method calls into the <code>ComponentUI</code> method of
2575 2575 * the same name. If this component does not have a
2576 2576 * <code>ComponentUI</code>
2577 2577 * <code>BaselineResizeBehavior.OTHER</code> will be
2578 2578 * returned. Subclasses should
2579 2579 * never return <code>null</code>; if the baseline can not be
2580 2580 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers
2581 2581 * should first ask for the baseline using
2582 2582 * <code>getBaseline</code> and if a value >= 0 is returned use
2583 2583 * this method. It is acceptable for this method to return a
2584 2584 * value other than <code>BaselineResizeBehavior.OTHER</code> even if
2585 2585 * <code>getBaseline</code> returns a value less than 0.
2586 2586 *
2587 2587 * @see #getBaseline(int, int)
2588 2588 * @since 1.6
2589 2589 */
↓ open down ↓ |
1044 lines elided |
↑ open up ↑ |
2590 2590 public BaselineResizeBehavior getBaselineResizeBehavior() {
2591 2591 if (ui != null) {
2592 2592 return ui.getBaselineResizeBehavior(this);
2593 2593 }
2594 2594 return BaselineResizeBehavior.OTHER;
2595 2595 }
2596 2596
2597 2597 /**
2598 2598 * In release 1.4, the focus subsystem was rearchitected.
2599 2599 * For more information, see
2600 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
2600 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
2601 2601 * How to Use the Focus Subsystem</a>,
2602 2602 * a section in <em>The Java Tutorial</em>.
2603 2603 * <p>
2604 2604 * Requests focus on this <code>JComponent</code>'s
2605 2605 * <code>FocusTraversalPolicy</code>'s default <code>Component</code>.
2606 2606 * If this <code>JComponent</code> is a focus cycle root, then its
2607 2607 * <code>FocusTraversalPolicy</code> is used. Otherwise, the
2608 2608 * <code>FocusTraversalPolicy</code> of this <code>JComponent</code>'s
2609 2609 * focus-cycle-root ancestor is used.
2610 2610 *
2611 2611 * @see java.awt.FocusTraversalPolicy#getDefaultComponent
2612 2612 * @deprecated As of 1.4, replaced by
2613 2613 * <code>FocusTraversalPolicy.getDefaultComponent(Container).requestFocus()</code>
2614 2614 */
2615 2615 @Deprecated
2616 2616 public boolean requestDefaultFocus() {
2617 2617 Container nearestRoot =
2618 2618 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
2619 2619 if (nearestRoot == null) {
2620 2620 return false;
2621 2621 }
2622 2622 Component comp = nearestRoot.getFocusTraversalPolicy().
2623 2623 getDefaultComponent(nearestRoot);
2624 2624 if (comp != null) {
2625 2625 comp.requestFocus();
2626 2626 return true;
2627 2627 } else {
2628 2628 return false;
2629 2629 }
2630 2630 }
2631 2631
2632 2632 /**
2633 2633 * Makes the component visible or invisible.
2634 2634 * Overrides <code>Component.setVisible</code>.
2635 2635 *
2636 2636 * @param aFlag true to make the component visible; false to
2637 2637 * make it invisible
2638 2638 *
2639 2639 * @beaninfo
2640 2640 * attribute: visualUpdate true
2641 2641 */
2642 2642 public void setVisible(boolean aFlag) {
2643 2643 if (aFlag != isVisible()) {
2644 2644 super.setVisible(aFlag);
2645 2645 if (aFlag) {
2646 2646 Container parent = getParent();
2647 2647 if (parent != null) {
2648 2648 Rectangle r = getBounds();
2649 2649 parent.repaint(r.x, r.y, r.width, r.height);
2650 2650 }
2651 2651 revalidate();
2652 2652 }
2653 2653 }
2654 2654 }
2655 2655
2656 2656 /**
2657 2657 * Sets whether or not this component is enabled.
2658 2658 * A component that is enabled may respond to user input,
2659 2659 * while a component that is not enabled cannot respond to
2660 2660 * user input. Some components may alter their visual
2661 2661 * representation when they are disabled in order to
2662 2662 * provide feedback to the user that they cannot take input.
2663 2663 * <p>Note: Disabling a component does not disable its children.
2664 2664 *
2665 2665 * <p>Note: Disabling a lightweight component does not prevent it from
2666 2666 * receiving MouseEvents.
2667 2667 *
2668 2668 * @param enabled true if this component should be enabled, false otherwise
2669 2669 * @see java.awt.Component#isEnabled
2670 2670 * @see java.awt.Component#isLightweight
2671 2671 *
2672 2672 * @beaninfo
2673 2673 * preferred: true
2674 2674 * bound: true
2675 2675 * attribute: visualUpdate true
2676 2676 * description: The enabled state of the component.
2677 2677 */
2678 2678 public void setEnabled(boolean enabled) {
2679 2679 boolean oldEnabled = isEnabled();
2680 2680 super.setEnabled(enabled);
2681 2681 firePropertyChange("enabled", oldEnabled, enabled);
2682 2682 if (enabled != oldEnabled) {
2683 2683 repaint();
2684 2684 }
2685 2685 }
2686 2686
2687 2687 /**
2688 2688 * Sets the foreground color of this component. It is up to the
2689 2689 * look and feel to honor this property, some may choose to ignore
2690 2690 * it.
2691 2691 *
2692 2692 * @param fg the desired foreground <code>Color</code>
2693 2693 * @see java.awt.Component#getForeground
2694 2694 *
2695 2695 * @beaninfo
2696 2696 * preferred: true
2697 2697 * bound: true
2698 2698 * attribute: visualUpdate true
2699 2699 * description: The foreground color of the component.
2700 2700 */
2701 2701 public void setForeground(Color fg) {
2702 2702 Color oldFg = getForeground();
2703 2703 super.setForeground(fg);
2704 2704 if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) {
2705 2705 // foreground already bound in AWT1.2
2706 2706 repaint();
2707 2707 }
2708 2708 }
2709 2709
2710 2710 /**
2711 2711 * Sets the background color of this component. The background
2712 2712 * color is used only if the component is opaque, and only
2713 2713 * by subclasses of <code>JComponent</code> or
2714 2714 * <code>ComponentUI</code> implementations. Direct subclasses of
2715 2715 * <code>JComponent</code> must override
2716 2716 * <code>paintComponent</code> to honor this property.
2717 2717 * <p>
2718 2718 * It is up to the look and feel to honor this property, some may
2719 2719 * choose to ignore it.
2720 2720 *
2721 2721 * @param bg the desired background <code>Color</code>
2722 2722 * @see java.awt.Component#getBackground
2723 2723 * @see #setOpaque
2724 2724 *
2725 2725 * @beaninfo
2726 2726 * preferred: true
2727 2727 * bound: true
2728 2728 * attribute: visualUpdate true
2729 2729 * description: The background color of the component.
2730 2730 */
2731 2731 public void setBackground(Color bg) {
2732 2732 Color oldBg = getBackground();
2733 2733 super.setBackground(bg);
2734 2734 if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg.equals(oldBg))) {
2735 2735 // background already bound in AWT1.2
2736 2736 repaint();
2737 2737 }
2738 2738 }
2739 2739
2740 2740 /**
2741 2741 * Sets the font for this component.
2742 2742 *
2743 2743 * @param font the desired <code>Font</code> for this component
2744 2744 * @see java.awt.Component#getFont
2745 2745 *
2746 2746 * @beaninfo
2747 2747 * preferred: true
2748 2748 * bound: true
2749 2749 * attribute: visualUpdate true
2750 2750 * description: The font for the component.
2751 2751 */
2752 2752 public void setFont(Font font) {
2753 2753 Font oldFont = getFont();
2754 2754 super.setFont(font);
2755 2755 // font already bound in AWT1.2
2756 2756 if (font != oldFont) {
2757 2757 revalidate();
2758 2758 repaint();
2759 2759 }
2760 2760 }
2761 2761
2762 2762 /**
2763 2763 * Returns the default locale used to initialize each JComponent's
2764 2764 * locale property upon creation.
2765 2765 *
2766 2766 * The default locale has "AppContext" scope so that applets (and
2767 2767 * potentially multiple lightweight applications running in a single VM)
2768 2768 * can have their own setting. An applet can safely alter its default
2769 2769 * locale because it will have no affect on other applets (or the browser).
2770 2770 *
2771 2771 * @return the default <code>Locale</code>.
2772 2772 * @see #setDefaultLocale
2773 2773 * @see java.awt.Component#getLocale
2774 2774 * @see #setLocale
2775 2775 * @since 1.4
2776 2776 */
2777 2777 static public Locale getDefaultLocale() {
2778 2778 Locale l = (Locale) SwingUtilities.appContextGet(defaultLocale);
2779 2779 if( l == null ) {
2780 2780 //REMIND(bcb) choosing the default value is more complicated
2781 2781 //than this.
2782 2782 l = Locale.getDefault();
2783 2783 JComponent.setDefaultLocale( l );
2784 2784 }
2785 2785 return l;
2786 2786 }
2787 2787
2788 2788
2789 2789 /**
2790 2790 * Sets the default locale used to initialize each JComponent's locale
2791 2791 * property upon creation. The initial value is the VM's default locale.
2792 2792 *
2793 2793 * The default locale has "AppContext" scope so that applets (and
2794 2794 * potentially multiple lightweight applications running in a single VM)
2795 2795 * can have their own setting. An applet can safely alter its default
2796 2796 * locale because it will have no affect on other applets (or the browser).
2797 2797 *
2798 2798 * @param l the desired default <code>Locale</code> for new components.
2799 2799 * @see #getDefaultLocale
2800 2800 * @see java.awt.Component#getLocale
2801 2801 * @see #setLocale
2802 2802 * @since 1.4
2803 2803 */
2804 2804 static public void setDefaultLocale( Locale l ) {
2805 2805 SwingUtilities.appContextPut(defaultLocale, l);
2806 2806 }
2807 2807
2808 2808
2809 2809 /**
2810 2810 * Processes any key events that the component itself
2811 2811 * recognizes. This is called after the focus
2812 2812 * manager and any interested listeners have been
2813 2813 * given a chance to steal away the event. This
2814 2814 * method is called only if the event has not
2815 2815 * yet been consumed. This method is called prior
2816 2816 * to the keyboard UI logic.
2817 2817 * <p>
2818 2818 * This method is implemented to do nothing. Subclasses would
2819 2819 * normally override this method if they process some
2820 2820 * key events themselves. If the event is processed,
2821 2821 * it should be consumed.
2822 2822 */
2823 2823 protected void processComponentKeyEvent(KeyEvent e) {
2824 2824 }
2825 2825
2826 2826 /** Overrides <code>processKeyEvent</code> to process events. **/
2827 2827 protected void processKeyEvent(KeyEvent e) {
2828 2828 boolean result;
2829 2829 boolean shouldProcessKey;
2830 2830
2831 2831 // This gives the key event listeners a crack at the event
2832 2832 super.processKeyEvent(e);
2833 2833
2834 2834 // give the component itself a crack at the event
2835 2835 if (! e.isConsumed()) {
2836 2836 processComponentKeyEvent(e);
2837 2837 }
2838 2838
2839 2839 shouldProcessKey = KeyboardState.shouldProcess(e);
2840 2840
2841 2841 if(e.isConsumed()) {
2842 2842 return;
2843 2843 }
2844 2844
2845 2845 if (shouldProcessKey && processKeyBindings(e, e.getID() ==
2846 2846 KeyEvent.KEY_PRESSED)) {
2847 2847 e.consume();
2848 2848 }
2849 2849 }
2850 2850
2851 2851 /**
2852 2852 * Invoked to process the key bindings for <code>ks</code> as the result
2853 2853 * of the <code>KeyEvent</code> <code>e</code>. This obtains
2854 2854 * the appropriate <code>InputMap</code>,
2855 2855 * gets the binding, gets the action from the <code>ActionMap</code>,
2856 2856 * and then (if the action is found and the component
2857 2857 * is enabled) invokes <code>notifyAction</code> to notify the action.
2858 2858 *
2859 2859 * @param ks the <code>KeyStroke</code> queried
2860 2860 * @param e the <code>KeyEvent</code>
2861 2861 * @param condition one of the following values:
2862 2862 * <ul>
2863 2863 * <li>JComponent.WHEN_FOCUSED
2864 2864 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2865 2865 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2866 2866 * </ul>
2867 2867 * @param pressed true if the key is pressed
2868 2868 * @return true if there was a binding to an action, and the action
2869 2869 * was enabled
2870 2870 *
2871 2871 * @since 1.3
2872 2872 */
2873 2873 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
2874 2874 int condition, boolean pressed) {
2875 2875 InputMap map = getInputMap(condition, false);
2876 2876 ActionMap am = getActionMap(false);
2877 2877
2878 2878 if(map != null && am != null && isEnabled()) {
2879 2879 Object binding = map.get(ks);
2880 2880 Action action = (binding == null) ? null : am.get(binding);
2881 2881 if (action != null) {
2882 2882 return SwingUtilities.notifyAction(action, ks, e, this,
2883 2883 e.getModifiers());
2884 2884 }
2885 2885 }
2886 2886 return false;
2887 2887 }
2888 2888
2889 2889 /**
2890 2890 * This is invoked as the result of a <code>KeyEvent</code>
2891 2891 * that was not consumed by the <code>FocusManager</code>,
2892 2892 * <code>KeyListeners</code>, or the component. It will first try
2893 2893 * <code>WHEN_FOCUSED</code> bindings,
2894 2894 * then <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings,
2895 2895 * and finally <code>WHEN_IN_FOCUSED_WINDOW</code> bindings.
2896 2896 *
2897 2897 * @param e the unconsumed <code>KeyEvent</code>
2898 2898 * @param pressed true if the key is pressed
2899 2899 * @return true if there is a key binding for <code>e</code>
2900 2900 */
2901 2901 boolean processKeyBindings(KeyEvent e, boolean pressed) {
2902 2902 if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) {
2903 2903 return false;
2904 2904 }
2905 2905 // Get the KeyStroke
2906 2906 // There may be two keystrokes associated with a low-level key event;
2907 2907 // in this case a keystroke made of an extended key code has a priority.
2908 2908 KeyStroke ks;
2909 2909 KeyStroke ksE = null;
2910 2910
2911 2911 if (e.getID() == KeyEvent.KEY_TYPED) {
2912 2912 ks = KeyStroke.getKeyStroke(e.getKeyChar());
2913 2913 }
2914 2914 else {
2915 2915 ks = KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
2916 2916 (pressed ? false:true));
2917 2917 if (e.getKeyCode() != e.getExtendedKeyCode()) {
2918 2918 ksE = KeyStroke.getKeyStroke(e.getExtendedKeyCode(),e.getModifiers(),
2919 2919 (pressed ? false:true));
2920 2920 }
2921 2921 }
2922 2922
2923 2923 // Do we have a key binding for e?
2924 2924 // If we have a binding by an extended code, use it.
2925 2925 // If not, check for regular code binding.
2926 2926 if(ksE != null && processKeyBinding(ksE, e, WHEN_FOCUSED, pressed)) {
2927 2927 return true;
2928 2928 }
2929 2929 if(processKeyBinding(ks, e, WHEN_FOCUSED, pressed))
2930 2930 return true;
2931 2931
2932 2932 /* We have no key binding. Let's try the path from our parent to the
2933 2933 * window excluded. We store the path components so we can avoid
2934 2934 * asking the same component twice.
2935 2935 */
2936 2936 Container parent = this;
2937 2937 while (parent != null && !(parent instanceof Window) &&
2938 2938 !(parent instanceof Applet)) {
2939 2939 if(parent instanceof JComponent) {
2940 2940 if(ksE != null && ((JComponent)parent).processKeyBinding(ksE, e,
2941 2941 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2942 2942 return true;
2943 2943 if(((JComponent)parent).processKeyBinding(ks, e,
2944 2944 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2945 2945 return true;
2946 2946 }
2947 2947 // This is done so that the children of a JInternalFrame are
2948 2948 // given precedence for WHEN_IN_FOCUSED_WINDOW bindings before
2949 2949 // other components WHEN_IN_FOCUSED_WINDOW bindings. This also gives
2950 2950 // more precedence to the WHEN_IN_FOCUSED_WINDOW bindings of the
2951 2951 // JInternalFrame's children vs the
2952 2952 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT bindings of the parents.
2953 2953 // maybe generalize from JInternalFrame (like isFocusCycleRoot).
2954 2954 if ((parent instanceof JInternalFrame) &&
2955 2955 JComponent.processKeyBindingsForAllComponents(e,parent,pressed)){
2956 2956 return true;
2957 2957 }
2958 2958 parent = parent.getParent();
2959 2959 }
2960 2960
2961 2961 /* No components between the focused component and the window is
2962 2962 * actually interested by the key event. Let's try the other
2963 2963 * JComponent in this window.
2964 2964 */
2965 2965 if(parent != null) {
2966 2966 return JComponent.processKeyBindingsForAllComponents(e,parent,pressed);
2967 2967 }
2968 2968 return false;
2969 2969 }
2970 2970
2971 2971 static boolean processKeyBindingsForAllComponents(KeyEvent e,
2972 2972 Container container, boolean pressed) {
2973 2973 while (true) {
2974 2974 if (KeyboardManager.getCurrentManager().fireKeyboardAction(
2975 2975 e, pressed, container)) {
2976 2976 return true;
2977 2977 }
2978 2978 if (container instanceof Popup.HeavyWeightWindow) {
2979 2979 container = ((Window)container).getOwner();
2980 2980 }
↓ open down ↓ |
370 lines elided |
↑ open up ↑ |
2981 2981 else {
2982 2982 return false;
2983 2983 }
2984 2984 }
2985 2985 }
2986 2986
2987 2987 /**
2988 2988 * Registers the text to display in a tool tip.
2989 2989 * The text displays when the cursor lingers over the component.
2990 2990 * <p>
2991 - * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How to Use Tool Tips</a>
2991 + * See <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How to Use Tool Tips</a>
2992 2992 * in <em>The Java Tutorial</em>
2993 2993 * for further documentation.
2994 2994 *
2995 2995 * @param text the string to display; if the text is <code>null</code>,
2996 2996 * the tool tip is turned off for this component
2997 2997 * @see #TOOL_TIP_TEXT_KEY
2998 2998 * @beaninfo
2999 2999 * preferred: true
3000 3000 * description: The text to display in a tool tip.
3001 3001 */
3002 3002 public void setToolTipText(String text) {
3003 3003 String oldText = getToolTipText();
3004 3004 putClientProperty(TOOL_TIP_TEXT_KEY, text);
3005 3005 ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
3006 3006 if (text != null) {
3007 3007 if (oldText == null) {
3008 3008 toolTipManager.registerComponent(this);
3009 3009 }
3010 3010 } else {
3011 3011 toolTipManager.unregisterComponent(this);
3012 3012 }
3013 3013 }
3014 3014
3015 3015 /**
3016 3016 * Returns the tooltip string that has been set with
3017 3017 * <code>setToolTipText</code>.
3018 3018 *
3019 3019 * @return the text of the tool tip
3020 3020 * @see #TOOL_TIP_TEXT_KEY
3021 3021 */
3022 3022 public String getToolTipText() {
3023 3023 return (String)getClientProperty(TOOL_TIP_TEXT_KEY);
3024 3024 }
3025 3025
3026 3026
3027 3027 /**
3028 3028 * Returns the string to be used as the tooltip for <i>event</i>.
3029 3029 * By default this returns any string set using
3030 3030 * <code>setToolTipText</code>. If a component provides
3031 3031 * more extensive API to support differing tooltips at different locations,
3032 3032 * this method should be overridden.
3033 3033 */
3034 3034 public String getToolTipText(MouseEvent event) {
3035 3035 return getToolTipText();
3036 3036 }
3037 3037
3038 3038 /**
3039 3039 * Returns the tooltip location in this component's coordinate system.
3040 3040 * If <code>null</code> is returned, Swing will choose a location.
3041 3041 * The default implementation returns <code>null</code>.
3042 3042 *
3043 3043 * @param event the <code>MouseEvent</code> that caused the
3044 3044 * <code>ToolTipManager</code> to show the tooltip
3045 3045 * @return always returns <code>null</code>
3046 3046 */
3047 3047 public Point getToolTipLocation(MouseEvent event) {
3048 3048 return null;
3049 3049 }
3050 3050
3051 3051 /**
3052 3052 * Returns the preferred location to display the popup menu in this
3053 3053 * component's coordinate system. It is up to the look and feel to
3054 3054 * honor this property, some may choose to ignore it.
3055 3055 * If {@code null}, the look and feel will choose a suitable location.
3056 3056 *
3057 3057 * @param event the {@code MouseEvent} that triggered the popup to be
3058 3058 * shown, or {@code null} if the popup is not being shown as the
3059 3059 * result of a mouse event
3060 3060 * @return location to display the {@code JPopupMenu}, or {@code null}
3061 3061 * @since 1.5
3062 3062 */
3063 3063 public Point getPopupLocation(MouseEvent event) {
3064 3064 return null;
3065 3065 }
3066 3066
3067 3067
3068 3068 /**
3069 3069 * Returns the instance of <code>JToolTip</code> that should be used
3070 3070 * to display the tooltip.
3071 3071 * Components typically would not override this method,
3072 3072 * but it can be used to
3073 3073 * cause different tooltips to be displayed differently.
3074 3074 *
3075 3075 * @return the <code>JToolTip</code> used to display this toolTip
3076 3076 */
3077 3077 public JToolTip createToolTip() {
3078 3078 JToolTip tip = new JToolTip();
3079 3079 tip.setComponent(this);
3080 3080 return tip;
3081 3081 }
3082 3082
3083 3083 /**
3084 3084 * Forwards the <code>scrollRectToVisible()</code> message to the
3085 3085 * <code>JComponent</code>'s parent. Components that can service
3086 3086 * the request, such as <code>JViewport</code>,
3087 3087 * override this method and perform the scrolling.
3088 3088 *
3089 3089 * @param aRect the visible <code>Rectangle</code>
3090 3090 * @see JViewport
3091 3091 */
3092 3092 public void scrollRectToVisible(Rectangle aRect) {
3093 3093 Container parent;
3094 3094 int dx = getX(), dy = getY();
3095 3095
3096 3096 for (parent = getParent();
3097 3097 !(parent == null) &&
3098 3098 !(parent instanceof JComponent) &&
3099 3099 !(parent instanceof CellRendererPane);
3100 3100 parent = parent.getParent()) {
3101 3101 Rectangle bounds = parent.getBounds();
3102 3102
3103 3103 dx += bounds.x;
3104 3104 dy += bounds.y;
3105 3105 }
3106 3106
3107 3107 if (!(parent == null) && !(parent instanceof CellRendererPane)) {
3108 3108 aRect.x += dx;
3109 3109 aRect.y += dy;
3110 3110
3111 3111 ((JComponent)parent).scrollRectToVisible(aRect);
3112 3112 aRect.x -= dx;
3113 3113 aRect.y -= dy;
3114 3114 }
3115 3115 }
3116 3116
3117 3117 /**
3118 3118 * Sets the <code>autoscrolls</code> property.
3119 3119 * If <code>true</code> mouse dragged events will be
3120 3120 * synthetically generated when the mouse is dragged
3121 3121 * outside of the component's bounds and mouse motion
3122 3122 * has paused (while the button continues to be held
3123 3123 * down). The synthetic events make it appear that the
3124 3124 * drag gesture has resumed in the direction established when
3125 3125 * the component's boundary was crossed. Components that
3126 3126 * support autoscrolling must handle <code>mouseDragged</code>
3127 3127 * events by calling <code>scrollRectToVisible</code> with a
3128 3128 * rectangle that contains the mouse event's location. All of
3129 3129 * the Swing components that support item selection and are
3130 3130 * typically displayed in a <code>JScrollPane</code>
3131 3131 * (<code>JTable</code>, <code>JList</code>, <code>JTree</code>,
3132 3132 * <code>JTextArea</code>, and <code>JEditorPane</code>)
3133 3133 * already handle mouse dragged events in this way. To enable
3134 3134 * autoscrolling in any other component, add a mouse motion
3135 3135 * listener that calls <code>scrollRectToVisible</code>.
3136 3136 * For example, given a <code>JPanel</code>, <code>myPanel</code>:
3137 3137 * <pre>
3138 3138 * MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() {
3139 3139 * public void mouseDragged(MouseEvent e) {
3140 3140 * Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
3141 3141 * ((JPanel)e.getSource()).scrollRectToVisible(r);
3142 3142 * }
3143 3143 * };
3144 3144 * myPanel.addMouseMotionListener(doScrollRectToVisible);
3145 3145 * </pre>
3146 3146 * The default value of the <code>autoScrolls</code>
3147 3147 * property is <code>false</code>.
3148 3148 *
3149 3149 * @param autoscrolls if true, synthetic mouse dragged events
3150 3150 * are generated when the mouse is dragged outside of a component's
3151 3151 * bounds and the mouse button continues to be held down; otherwise
3152 3152 * false
3153 3153 * @see #getAutoscrolls
3154 3154 * @see JViewport
3155 3155 * @see JScrollPane
3156 3156 *
3157 3157 * @beaninfo
3158 3158 * expert: true
3159 3159 * description: Determines if this component automatically scrolls its contents when dragged.
3160 3160 */
3161 3161 public void setAutoscrolls(boolean autoscrolls) {
3162 3162 setFlag(AUTOSCROLLS_SET, true);
3163 3163 if (this.autoscrolls != autoscrolls) {
3164 3164 this.autoscrolls = autoscrolls;
3165 3165 if (autoscrolls) {
3166 3166 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
3167 3167 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
3168 3168 }
3169 3169 else {
3170 3170 Autoscroller.stop(this);
3171 3171 }
3172 3172 }
3173 3173 }
3174 3174
3175 3175 /**
3176 3176 * Gets the <code>autoscrolls</code> property.
3177 3177 *
3178 3178 * @return the value of the <code>autoscrolls</code> property
3179 3179 * @see JViewport
3180 3180 * @see #setAutoscrolls
3181 3181 */
3182 3182 public boolean getAutoscrolls() {
3183 3183 return autoscrolls;
3184 3184 }
3185 3185
3186 3186 /**
3187 3187 * Sets the {@code TransferHandler}, which provides support for transfer
3188 3188 * of data into and out of this component via cut/copy/paste and drag
3189 3189 * and drop. This may be {@code null} if the component does not support
3190 3190 * data transfer operations.
3191 3191 * <p>
3192 3192 * If the new {@code TransferHandler} is not {@code null}, this method
3193 3193 * also installs a <b>new</b> {@code DropTarget} on the component to
3194 3194 * activate drop handling through the {@code TransferHandler} and activate
3195 3195 * any built-in support (such as calculating and displaying potential drop
3196 3196 * locations). If you do not wish for this component to respond in any way
3197 3197 * to drops, you can disable drop support entirely either by removing the
3198 3198 * drop target ({@code setDropTarget(null)}) or by de-activating it
3199 3199 * ({@code getDropTaget().setActive(false)}).
3200 3200 * <p>
↓ open down ↓ |
199 lines elided |
↑ open up ↑ |
3201 3201 * If the new {@code TransferHandler} is {@code null}, this method removes
3202 3202 * the drop target.
3203 3203 * <p>
3204 3204 * Under two circumstances, this method does not modify the drop target:
3205 3205 * First, if the existing drop target on this component was explicitly
3206 3206 * set by the developer to a {@code non-null} value. Second, if the
3207 3207 * system property {@code suppressSwingDropSupport} is {@code true}. The
3208 3208 * default value for the system property is {@code false}.
3209 3209 * <p>
3210 3210 * Please see
3211 - * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
3211 + * <a href="https://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
3212 3212 * How to Use Drag and Drop and Data Transfer</a>,
3213 3213 * a section in <em>The Java Tutorial</em>, for more information.
3214 3214 *
3215 3215 * @param newHandler the new {@code TransferHandler}
3216 3216 *
3217 3217 * @see TransferHandler
3218 3218 * @see #getTransferHandler
3219 3219 * @since 1.4
3220 3220 * @beaninfo
3221 3221 * bound: true
3222 3222 * hidden: true
3223 3223 * description: Mechanism for transfer of data to and from the component
3224 3224 */
3225 3225 public void setTransferHandler(TransferHandler newHandler) {
3226 3226 TransferHandler oldHandler = (TransferHandler)getClientProperty(
3227 3227 JComponent_TRANSFER_HANDLER);
3228 3228 putClientProperty(JComponent_TRANSFER_HANDLER, newHandler);
3229 3229
3230 3230 SwingUtilities.installSwingDropTargetAsNecessary(this, newHandler);
3231 3231 firePropertyChange("transferHandler", oldHandler, newHandler);
3232 3232 }
3233 3233
3234 3234 /**
3235 3235 * Gets the <code>transferHandler</code> property.
3236 3236 *
3237 3237 * @return the value of the <code>transferHandler</code> property
3238 3238 *
3239 3239 * @see TransferHandler
3240 3240 * @see #setTransferHandler
3241 3241 * @since 1.4
3242 3242 */
3243 3243 public TransferHandler getTransferHandler() {
3244 3244 return (TransferHandler)getClientProperty(JComponent_TRANSFER_HANDLER);
3245 3245 }
3246 3246
3247 3247 /**
3248 3248 * Calculates a custom drop location for this type of component,
3249 3249 * representing where a drop at the given point should insert data.
3250 3250 * <code>null</code> is returned if this component doesn't calculate
3251 3251 * custom drop locations. In this case, <code>TransferHandler</code>
3252 3252 * will provide a default <code>DropLocation</code> containing just
3253 3253 * the point.
3254 3254 *
3255 3255 * @param p the point to calculate a drop location for
3256 3256 * @return the drop location, or <code>null</code>
3257 3257 */
3258 3258 TransferHandler.DropLocation dropLocationForPoint(Point p) {
3259 3259 return null;
3260 3260 }
3261 3261
3262 3262 /**
3263 3263 * Called to set or clear the drop location during a DnD operation.
3264 3264 * In some cases, the component may need to use its internal selection
3265 3265 * temporarily to indicate the drop location. To help facilitate this,
3266 3266 * this method returns and accepts as a parameter a state object.
3267 3267 * This state object can be used to store, and later restore, the selection
3268 3268 * state. Whatever this method returns will be passed back to it in
3269 3269 * future calls, as the state parameter. If it wants the DnD system to
3270 3270 * continue storing the same state, it must pass it back every time.
3271 3271 * Here's how this is used:
3272 3272 * <p>
3273 3273 * Let's say that on the first call to this method the component decides
3274 3274 * to save some state (because it is about to use the selection to show
3275 3275 * a drop index). It can return a state object to the caller encapsulating
3276 3276 * any saved selection state. On a second call, let's say the drop location
3277 3277 * is being changed to something else. The component doesn't need to
3278 3278 * restore anything yet, so it simply passes back the same state object
3279 3279 * to have the DnD system continue storing it. Finally, let's say this
3280 3280 * method is messaged with <code>null</code>. This means DnD
3281 3281 * is finished with this component for now, meaning it should restore
3282 3282 * state. At this point, it can use the state parameter to restore
3283 3283 * said state, and of course return <code>null</code> since there's
3284 3284 * no longer anything to store.
3285 3285 *
3286 3286 * @param location the drop location (as calculated by
3287 3287 * <code>dropLocationForPoint</code>) or <code>null</code>
3288 3288 * if there's no longer a valid drop location
3289 3289 * @param state the state object saved earlier for this component,
3290 3290 * or <code>null</code>
3291 3291 * @param forDrop whether or not the method is being called because an
3292 3292 * actual drop occurred
3293 3293 * @return any saved state for this component, or <code>null</code> if none
3294 3294 */
3295 3295 Object setDropLocation(TransferHandler.DropLocation location,
3296 3296 Object state,
3297 3297 boolean forDrop) {
3298 3298
3299 3299 return null;
3300 3300 }
3301 3301
3302 3302 /**
3303 3303 * Called to indicate to this component that DnD is done.
3304 3304 * Needed by <code>JTree</code>.
3305 3305 */
3306 3306 void dndDone() {
3307 3307 }
3308 3308
3309 3309 /**
3310 3310 * Processes mouse events occurring on this component by
3311 3311 * dispatching them to any registered
3312 3312 * <code>MouseListener</code> objects, refer to
3313 3313 * {@link java.awt.Component#processMouseEvent(MouseEvent)}
3314 3314 * for a complete description of this method.
3315 3315 *
3316 3316 * @param e the mouse event
3317 3317 * @see java.awt.Component#processMouseEvent
3318 3318 * @since 1.5
3319 3319 */
3320 3320 protected void processMouseEvent(MouseEvent e) {
3321 3321 if (autoscrolls && e.getID() == MouseEvent.MOUSE_RELEASED) {
3322 3322 Autoscroller.stop(this);
3323 3323 }
3324 3324 super.processMouseEvent(e);
3325 3325 }
3326 3326
3327 3327 /**
3328 3328 * Processes mouse motion events, such as MouseEvent.MOUSE_DRAGGED.
3329 3329 *
3330 3330 * @param e the <code>MouseEvent</code>
3331 3331 * @see MouseEvent
3332 3332 */
3333 3333 protected void processMouseMotionEvent(MouseEvent e) {
3334 3334 boolean dispatch = true;
3335 3335 if (autoscrolls && e.getID() == MouseEvent.MOUSE_DRAGGED) {
3336 3336 // We don't want to do the drags when the mouse moves if we're
3337 3337 // autoscrolling. It makes it feel spastic.
3338 3338 dispatch = !Autoscroller.isRunning(this);
3339 3339 Autoscroller.processMouseDragged(e);
3340 3340 }
3341 3341 if (dispatch) {
3342 3342 super.processMouseMotionEvent(e);
3343 3343 }
3344 3344 }
3345 3345
3346 3346 // Inner classes can't get at this method from a super class
3347 3347 void superProcessMouseMotionEvent(MouseEvent e) {
3348 3348 super.processMouseMotionEvent(e);
3349 3349 }
3350 3350
3351 3351 /**
3352 3352 * This is invoked by the <code>RepaintManager</code> if
3353 3353 * <code>createImage</code> is called on the component.
3354 3354 *
3355 3355 * @param newValue true if the double buffer image was created from this component
3356 3356 */
3357 3357 void setCreatedDoubleBuffer(boolean newValue) {
3358 3358 setFlag(CREATED_DOUBLE_BUFFER, newValue);
3359 3359 }
3360 3360
3361 3361 /**
3362 3362 * Returns true if the <code>RepaintManager</code>
3363 3363 * created the double buffer image from the component.
3364 3364 *
3365 3365 * @return true if this component had a double buffer image, false otherwise
3366 3366 */
3367 3367 boolean getCreatedDoubleBuffer() {
3368 3368 return getFlag(CREATED_DOUBLE_BUFFER);
3369 3369 }
3370 3370
3371 3371 /**
3372 3372 * <code>ActionStandin</code> is used as a standin for
3373 3373 * <code>ActionListeners</code> that are
3374 3374 * added via <code>registerKeyboardAction</code>.
3375 3375 */
3376 3376 final class ActionStandin implements Action {
3377 3377 private final ActionListener actionListener;
3378 3378 private final String command;
3379 3379 // This will be non-null if actionListener is an Action.
3380 3380 private final Action action;
3381 3381
3382 3382 ActionStandin(ActionListener actionListener, String command) {
3383 3383 this.actionListener = actionListener;
3384 3384 if (actionListener instanceof Action) {
3385 3385 this.action = (Action)actionListener;
3386 3386 }
3387 3387 else {
3388 3388 this.action = null;
3389 3389 }
3390 3390 this.command = command;
3391 3391 }
3392 3392
3393 3393 public Object getValue(String key) {
3394 3394 if (key != null) {
3395 3395 if (key.equals(Action.ACTION_COMMAND_KEY)) {
3396 3396 return command;
3397 3397 }
3398 3398 if (action != null) {
3399 3399 return action.getValue(key);
3400 3400 }
3401 3401 if (key.equals(NAME)) {
3402 3402 return "ActionStandin";
3403 3403 }
3404 3404 }
3405 3405 return null;
3406 3406 }
3407 3407
3408 3408 public boolean isEnabled() {
3409 3409 if (actionListener == null) {
3410 3410 // This keeps the old semantics where
3411 3411 // registerKeyboardAction(null) would essentialy remove
3412 3412 // the binding. We don't remove the binding from the
3413 3413 // InputMap as that would still allow parent InputMaps
3414 3414 // bindings to be accessed.
3415 3415 return false;
3416 3416 }
3417 3417 if (action == null) {
3418 3418 return true;
3419 3419 }
3420 3420 return action.isEnabled();
3421 3421 }
3422 3422
3423 3423 public void actionPerformed(ActionEvent ae) {
3424 3424 if (actionListener != null) {
3425 3425 actionListener.actionPerformed(ae);
3426 3426 }
3427 3427 }
3428 3428
3429 3429 // We don't allow any values to be added.
3430 3430 public void putValue(String key, Object value) {}
3431 3431
3432 3432 // Does nothing, our enabledness is determiend from our asociated
3433 3433 // action.
3434 3434 public void setEnabled(boolean b) { }
3435 3435
3436 3436 public void addPropertyChangeListener
3437 3437 (PropertyChangeListener listener) {}
3438 3438 public void removePropertyChangeListener
3439 3439 (PropertyChangeListener listener) {}
3440 3440 }
3441 3441
3442 3442
3443 3443 // This class is used by the KeyboardState class to provide a single
3444 3444 // instance that can be stored in the AppContext.
3445 3445 static final class IntVector {
3446 3446 int array[] = null;
3447 3447 int count = 0;
3448 3448 int capacity = 0;
3449 3449
3450 3450 int size() {
3451 3451 return count;
3452 3452 }
3453 3453
3454 3454 int elementAt(int index) {
3455 3455 return array[index];
3456 3456 }
3457 3457
3458 3458 void addElement(int value) {
3459 3459 if (count == capacity) {
3460 3460 capacity = (capacity + 2) * 2;
3461 3461 int[] newarray = new int[capacity];
3462 3462 if (count > 0) {
3463 3463 System.arraycopy(array, 0, newarray, 0, count);
3464 3464 }
3465 3465 array = newarray;
3466 3466 }
3467 3467 array[count++] = value;
3468 3468 }
3469 3469
3470 3470 void setElementAt(int value, int index) {
3471 3471 array[index] = value;
3472 3472 }
3473 3473 }
3474 3474
3475 3475 @SuppressWarnings("serial")
3476 3476 static class KeyboardState implements Serializable {
3477 3477 private static final Object keyCodesKey =
3478 3478 JComponent.KeyboardState.class;
3479 3479
3480 3480 // Get the array of key codes from the AppContext.
3481 3481 static IntVector getKeyCodeArray() {
3482 3482 IntVector iv =
3483 3483 (IntVector)SwingUtilities.appContextGet(keyCodesKey);
3484 3484 if (iv == null) {
3485 3485 iv = new IntVector();
3486 3486 SwingUtilities.appContextPut(keyCodesKey, iv);
3487 3487 }
3488 3488 return iv;
3489 3489 }
3490 3490
3491 3491 static void registerKeyPressed(int keyCode) {
3492 3492 IntVector kca = getKeyCodeArray();
3493 3493 int count = kca.size();
3494 3494 int i;
3495 3495 for(i=0;i<count;i++) {
3496 3496 if(kca.elementAt(i) == -1){
3497 3497 kca.setElementAt(keyCode, i);
3498 3498 return;
3499 3499 }
3500 3500 }
3501 3501 kca.addElement(keyCode);
3502 3502 }
3503 3503
3504 3504 static void registerKeyReleased(int keyCode) {
3505 3505 IntVector kca = getKeyCodeArray();
3506 3506 int count = kca.size();
3507 3507 int i;
3508 3508 for(i=0;i<count;i++) {
3509 3509 if(kca.elementAt(i) == keyCode) {
3510 3510 kca.setElementAt(-1, i);
3511 3511 return;
3512 3512 }
3513 3513 }
3514 3514 }
3515 3515
3516 3516 static boolean keyIsPressed(int keyCode) {
3517 3517 IntVector kca = getKeyCodeArray();
3518 3518 int count = kca.size();
3519 3519 int i;
3520 3520 for(i=0;i<count;i++) {
3521 3521 if(kca.elementAt(i) == keyCode) {
3522 3522 return true;
3523 3523 }
3524 3524 }
3525 3525 return false;
3526 3526 }
3527 3527
3528 3528 /**
3529 3529 * Updates internal state of the KeyboardState and returns true
3530 3530 * if the event should be processed further.
3531 3531 */
3532 3532 static boolean shouldProcess(KeyEvent e) {
3533 3533 switch (e.getID()) {
3534 3534 case KeyEvent.KEY_PRESSED:
3535 3535 if (!keyIsPressed(e.getKeyCode())) {
3536 3536 registerKeyPressed(e.getKeyCode());
3537 3537 }
3538 3538 return true;
3539 3539 case KeyEvent.KEY_RELEASED:
3540 3540 // We are forced to process VK_PRINTSCREEN separately because
3541 3541 // the Windows doesn't generate the key pressed event for
3542 3542 // printscreen and it block the processing of key release
3543 3543 // event for printscreen.
3544 3544 if (keyIsPressed(e.getKeyCode()) || e.getKeyCode()==KeyEvent.VK_PRINTSCREEN) {
3545 3545 registerKeyReleased(e.getKeyCode());
3546 3546 return true;
3547 3547 }
3548 3548 return false;
3549 3549 case KeyEvent.KEY_TYPED:
3550 3550 return true;
3551 3551 default:
3552 3552 // Not a known KeyEvent type, bail.
3553 3553 return false;
3554 3554 }
3555 3555 }
3556 3556 }
3557 3557
3558 3558 static final sun.awt.RequestFocusController focusController =
3559 3559 new sun.awt.RequestFocusController() {
3560 3560 public boolean acceptRequestFocus(Component from, Component to,
3561 3561 boolean temporary, boolean focusedWindowChangeAllowed,
3562 3562 sun.awt.CausedFocusEvent.Cause cause)
3563 3563 {
3564 3564 if ((to == null) || !(to instanceof JComponent)) {
3565 3565 return true;
3566 3566 }
3567 3567
3568 3568 if ((from == null) || !(from instanceof JComponent)) {
3569 3569 return true;
3570 3570 }
3571 3571
3572 3572 JComponent target = (JComponent) to;
3573 3573 if (!target.getVerifyInputWhenFocusTarget()) {
3574 3574 return true;
3575 3575 }
3576 3576
3577 3577 JComponent jFocusOwner = (JComponent)from;
3578 3578 InputVerifier iv = jFocusOwner.getInputVerifier();
3579 3579
3580 3580 if (iv == null) {
3581 3581 return true;
3582 3582 } else {
3583 3583 Object currentSource = SwingUtilities.appContextGet(
3584 3584 INPUT_VERIFIER_SOURCE_KEY);
3585 3585 if (currentSource == jFocusOwner) {
3586 3586 // We're currently calling into the InputVerifier
3587 3587 // for this component, so allow the focus change.
3588 3588 return true;
3589 3589 }
3590 3590 SwingUtilities.appContextPut(INPUT_VERIFIER_SOURCE_KEY,
3591 3591 jFocusOwner);
3592 3592 try {
3593 3593 return iv.shouldYieldFocus(jFocusOwner);
3594 3594 } finally {
3595 3595 if (currentSource != null) {
3596 3596 // We're already in the InputVerifier for
3597 3597 // currentSource. By resetting the currentSource
3598 3598 // we ensure that if the InputVerifier for
3599 3599 // currentSource does a requestFocus, we don't
3600 3600 // try and run the InputVerifier again.
3601 3601 SwingUtilities.appContextPut(
3602 3602 INPUT_VERIFIER_SOURCE_KEY, currentSource);
3603 3603 } else {
3604 3604 SwingUtilities.appContextRemove(
3605 3605 INPUT_VERIFIER_SOURCE_KEY);
3606 3606 }
3607 3607 }
3608 3608 }
3609 3609 }
3610 3610 };
3611 3611
3612 3612 /*
3613 3613 * --- Accessibility Support ---
3614 3614 */
3615 3615
3616 3616 /**
3617 3617 * @deprecated As of JDK version 1.1,
3618 3618 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3619 3619 */
3620 3620 @Deprecated
3621 3621 public void enable() {
3622 3622 if (isEnabled() != true) {
3623 3623 super.enable();
3624 3624 if (accessibleContext != null) {
3625 3625 accessibleContext.firePropertyChange(
3626 3626 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3627 3627 null, AccessibleState.ENABLED);
3628 3628 }
3629 3629 }
3630 3630 }
3631 3631
3632 3632 /**
3633 3633 * @deprecated As of JDK version 1.1,
3634 3634 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3635 3635 */
3636 3636 @Deprecated
3637 3637 public void disable() {
3638 3638 if (isEnabled() != false) {
3639 3639 super.disable();
3640 3640 if (accessibleContext != null) {
3641 3641 accessibleContext.firePropertyChange(
3642 3642 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3643 3643 AccessibleState.ENABLED, null);
3644 3644 }
3645 3645 }
3646 3646 }
3647 3647
3648 3648 /**
3649 3649 * Inner class of JComponent used to provide default support for
3650 3650 * accessibility. This class is not meant to be used directly by
3651 3651 * application developers, but is instead meant only to be
3652 3652 * subclassed by component developers.
3653 3653 * <p>
3654 3654 * <strong>Warning:</strong>
3655 3655 * Serialized objects of this class will not be compatible with
3656 3656 * future Swing releases. The current serialization support is
3657 3657 * appropriate for short term storage or RMI between applications running
3658 3658 * the same version of Swing. As of 1.4, support for long term storage
3659 3659 * of all JavaBeans™
3660 3660 * has been added to the <code>java.beans</code> package.
3661 3661 * Please see {@link java.beans.XMLEncoder}.
3662 3662 */
3663 3663 public abstract class AccessibleJComponent extends AccessibleAWTContainer
3664 3664 implements AccessibleExtendedComponent
3665 3665 {
3666 3666 /**
3667 3667 * Though the class is abstract, this should be called by
3668 3668 * all sub-classes.
3669 3669 */
3670 3670 protected AccessibleJComponent() {
3671 3671 super();
3672 3672 }
3673 3673
3674 3674 /**
3675 3675 * Number of PropertyChangeListener objects registered. It's used
3676 3676 * to add/remove ContainerListener and FocusListener to track
3677 3677 * target JComponent's state
3678 3678 */
3679 3679 private volatile transient int propertyListenersCount = 0;
3680 3680
3681 3681 /**
3682 3682 * This field duplicates the function of the accessibleAWTFocusHandler field
3683 3683 * in java.awt.Component.AccessibleAWTComponent, so it has been deprecated.
3684 3684 */
3685 3685 @Deprecated
3686 3686 protected FocusListener accessibleFocusHandler = null;
3687 3687
3688 3688 /**
3689 3689 * Fire PropertyChange listener, if one is registered,
3690 3690 * when children added/removed.
3691 3691 */
3692 3692 protected class AccessibleContainerHandler
3693 3693 implements ContainerListener {
3694 3694 public void componentAdded(ContainerEvent e) {
3695 3695 Component c = e.getChild();
3696 3696 if (c != null && c instanceof Accessible) {
3697 3697 AccessibleJComponent.this.firePropertyChange(
3698 3698 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3699 3699 null, c.getAccessibleContext());
3700 3700 }
3701 3701 }
3702 3702 public void componentRemoved(ContainerEvent e) {
3703 3703 Component c = e.getChild();
3704 3704 if (c != null && c instanceof Accessible) {
3705 3705 AccessibleJComponent.this.firePropertyChange(
3706 3706 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3707 3707 c.getAccessibleContext(), null);
3708 3708 }
3709 3709 }
3710 3710 }
3711 3711
3712 3712 /**
3713 3713 * Fire PropertyChange listener, if one is registered,
3714 3714 * when focus events happen
3715 3715 * @since 1.3
3716 3716 */
3717 3717 protected class AccessibleFocusHandler implements FocusListener {
3718 3718 public void focusGained(FocusEvent event) {
3719 3719 if (accessibleContext != null) {
3720 3720 accessibleContext.firePropertyChange(
3721 3721 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3722 3722 null, AccessibleState.FOCUSED);
3723 3723 }
3724 3724 }
3725 3725 public void focusLost(FocusEvent event) {
3726 3726 if (accessibleContext != null) {
3727 3727 accessibleContext.firePropertyChange(
3728 3728 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3729 3729 AccessibleState.FOCUSED, null);
3730 3730 }
3731 3731 }
3732 3732 } // inner class AccessibleFocusHandler
3733 3733
3734 3734
3735 3735 /**
3736 3736 * Adds a PropertyChangeListener to the listener list.
3737 3737 *
3738 3738 * @param listener the PropertyChangeListener to be added
3739 3739 */
3740 3740 public void addPropertyChangeListener(PropertyChangeListener listener) {
3741 3741 if (accessibleContainerHandler == null) {
3742 3742 accessibleContainerHandler = new AccessibleContainerHandler();
3743 3743 }
3744 3744 if (propertyListenersCount++ == 0) {
3745 3745 JComponent.this.addContainerListener(accessibleContainerHandler);
3746 3746 }
3747 3747 super.addPropertyChangeListener(listener);
3748 3748 }
3749 3749
3750 3750 /**
3751 3751 * Removes a PropertyChangeListener from the listener list.
3752 3752 * This removes a PropertyChangeListener that was registered
3753 3753 * for all properties.
3754 3754 *
3755 3755 * @param listener the PropertyChangeListener to be removed
3756 3756 */
3757 3757 public void removePropertyChangeListener(PropertyChangeListener listener) {
3758 3758 if (--propertyListenersCount == 0) {
3759 3759 JComponent.this.removeContainerListener(accessibleContainerHandler);
3760 3760 }
3761 3761 super.removePropertyChangeListener(listener);
3762 3762 }
3763 3763
3764 3764
3765 3765
3766 3766 /**
3767 3767 * Recursively search through the border hierarchy (if it exists)
3768 3768 * for a TitledBorder with a non-null title. This does a depth
3769 3769 * first search on first the inside borders then the outside borders.
3770 3770 * The assumption is that titles make really pretty inside borders
3771 3771 * but not very pretty outside borders in compound border situations.
3772 3772 * It's rather arbitrary, but hopefully decent UI programmers will
3773 3773 * not create multiple titled borders for the same component.
3774 3774 */
3775 3775 protected String getBorderTitle(Border b) {
3776 3776 String s;
3777 3777 if (b instanceof TitledBorder) {
3778 3778 return ((TitledBorder) b).getTitle();
3779 3779 } else if (b instanceof CompoundBorder) {
3780 3780 s = getBorderTitle(((CompoundBorder) b).getInsideBorder());
3781 3781 if (s == null) {
3782 3782 s = getBorderTitle(((CompoundBorder) b).getOutsideBorder());
3783 3783 }
3784 3784 return s;
3785 3785 } else {
3786 3786 return null;
3787 3787 }
3788 3788 }
3789 3789
3790 3790 // AccessibleContext methods
3791 3791 //
3792 3792 /**
3793 3793 * Gets the accessible name of this object. This should almost never
3794 3794 * return java.awt.Component.getName(), as that generally isn't
3795 3795 * a localized name, and doesn't have meaning for the user. If the
3796 3796 * object is fundamentally a text object (such as a menu item), the
3797 3797 * accessible name should be the text of the object (for example,
3798 3798 * "save").
3799 3799 * If the object has a tooltip, the tooltip text may also be an
3800 3800 * appropriate String to return.
3801 3801 *
3802 3802 * @return the localized name of the object -- can be null if this
3803 3803 * object does not have a name
3804 3804 * @see AccessibleContext#setAccessibleName
3805 3805 */
3806 3806 public String getAccessibleName() {
3807 3807 String name = accessibleName;
3808 3808
3809 3809 // fallback to the client name property
3810 3810 //
3811 3811 if (name == null) {
3812 3812 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
3813 3813 }
3814 3814
3815 3815 // fallback to the titled border if it exists
3816 3816 //
3817 3817 if (name == null) {
3818 3818 name = getBorderTitle(getBorder());
3819 3819 }
3820 3820
3821 3821 // fallback to the label labeling us if it exists
3822 3822 //
3823 3823 if (name == null) {
3824 3824 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3825 3825 if (o instanceof Accessible) {
3826 3826 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3827 3827 if (ac != null) {
3828 3828 name = ac.getAccessibleName();
3829 3829 }
3830 3830 }
3831 3831 }
3832 3832 return name;
3833 3833 }
3834 3834
3835 3835 /**
3836 3836 * Gets the accessible description of this object. This should be
3837 3837 * a concise, localized description of what this object is - what
3838 3838 * is its meaning to the user. If the object has a tooltip, the
3839 3839 * tooltip text may be an appropriate string to return, assuming
3840 3840 * it contains a concise description of the object (instead of just
3841 3841 * the name of the object - for example a "Save" icon on a toolbar that
3842 3842 * had "save" as the tooltip text shouldn't return the tooltip
3843 3843 * text as the description, but something like "Saves the current
3844 3844 * text document" instead).
3845 3845 *
3846 3846 * @return the localized description of the object -- can be null if
3847 3847 * this object does not have a description
3848 3848 * @see AccessibleContext#setAccessibleDescription
3849 3849 */
3850 3850 public String getAccessibleDescription() {
3851 3851 String description = accessibleDescription;
3852 3852
3853 3853 // fallback to the client description property
3854 3854 //
3855 3855 if (description == null) {
3856 3856 description = (String)getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY);
3857 3857 }
3858 3858
3859 3859 // fallback to the tool tip text if it exists
3860 3860 //
3861 3861 if (description == null) {
3862 3862 try {
3863 3863 description = getToolTipText();
3864 3864 } catch (Exception e) {
3865 3865 // Just in case the subclass overrode the
3866 3866 // getToolTipText method and actually
3867 3867 // requires a MouseEvent.
3868 3868 // [[[FIXME: WDW - we probably should require this
3869 3869 // method to take a MouseEvent and just pass it on
3870 3870 // to getToolTipText. The swing-feedback traffic
3871 3871 // leads me to believe getToolTipText might change,
3872 3872 // though, so I was hesitant to make this change at
3873 3873 // this time.]]]
3874 3874 }
3875 3875 }
3876 3876
3877 3877 // fallback to the label labeling us if it exists
3878 3878 //
3879 3879 if (description == null) {
3880 3880 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3881 3881 if (o instanceof Accessible) {
3882 3882 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3883 3883 if (ac != null) {
3884 3884 description = ac.getAccessibleDescription();
3885 3885 }
3886 3886 }
3887 3887 }
3888 3888
3889 3889 return description;
3890 3890 }
3891 3891
3892 3892 /**
3893 3893 * Gets the role of this object.
3894 3894 *
3895 3895 * @return an instance of AccessibleRole describing the role of the
3896 3896 * object
3897 3897 * @see AccessibleRole
3898 3898 */
3899 3899 public AccessibleRole getAccessibleRole() {
3900 3900 return AccessibleRole.SWING_COMPONENT;
3901 3901 }
3902 3902
3903 3903 /**
3904 3904 * Gets the state of this object.
3905 3905 *
3906 3906 * @return an instance of AccessibleStateSet containing the current
3907 3907 * state set of the object
3908 3908 * @see AccessibleState
3909 3909 */
3910 3910 public AccessibleStateSet getAccessibleStateSet() {
3911 3911 AccessibleStateSet states = super.getAccessibleStateSet();
3912 3912 if (JComponent.this.isOpaque()) {
3913 3913 states.add(AccessibleState.OPAQUE);
3914 3914 }
3915 3915 return states;
3916 3916 }
3917 3917
3918 3918 /**
3919 3919 * Returns the number of accessible children in the object. If all
3920 3920 * of the children of this object implement Accessible, than this
3921 3921 * method should return the number of children of this object.
3922 3922 *
3923 3923 * @return the number of accessible children in the object.
3924 3924 */
3925 3925 public int getAccessibleChildrenCount() {
3926 3926 return super.getAccessibleChildrenCount();
3927 3927 }
3928 3928
3929 3929 /**
3930 3930 * Returns the nth Accessible child of the object.
3931 3931 *
3932 3932 * @param i zero-based index of child
3933 3933 * @return the nth Accessible child of the object
3934 3934 */
3935 3935 public Accessible getAccessibleChild(int i) {
3936 3936 return super.getAccessibleChild(i);
3937 3937 }
3938 3938
3939 3939 // ----- AccessibleExtendedComponent
3940 3940
3941 3941 /**
3942 3942 * Returns the AccessibleExtendedComponent
3943 3943 *
3944 3944 * @return the AccessibleExtendedComponent
3945 3945 */
3946 3946 AccessibleExtendedComponent getAccessibleExtendedComponent() {
3947 3947 return this;
3948 3948 }
3949 3949
3950 3950 /**
3951 3951 * Returns the tool tip text
3952 3952 *
3953 3953 * @return the tool tip text, if supported, of the object;
3954 3954 * otherwise, null
3955 3955 * @since 1.4
3956 3956 */
3957 3957 public String getToolTipText() {
3958 3958 return JComponent.this.getToolTipText();
3959 3959 }
3960 3960
3961 3961 /**
3962 3962 * Returns the titled border text
3963 3963 *
3964 3964 * @return the titled border text, if supported, of the object;
3965 3965 * otherwise, null
3966 3966 * @since 1.4
3967 3967 */
3968 3968 public String getTitledBorderText() {
3969 3969 Border border = JComponent.this.getBorder();
3970 3970 if (border instanceof TitledBorder) {
3971 3971 return ((TitledBorder)border).getTitle();
3972 3972 } else {
3973 3973 return null;
3974 3974 }
3975 3975 }
3976 3976
3977 3977 /**
3978 3978 * Returns key bindings associated with this object
3979 3979 *
3980 3980 * @return the key bindings, if supported, of the object;
3981 3981 * otherwise, null
3982 3982 * @see AccessibleKeyBinding
3983 3983 * @since 1.4
3984 3984 */
3985 3985 public AccessibleKeyBinding getAccessibleKeyBinding() {
3986 3986 // Try to get the linked label's mnemonic if it exists
3987 3987 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3988 3988 if (o instanceof Accessible){
3989 3989 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3990 3990 if (ac != null){
3991 3991 AccessibleComponent comp = ac.getAccessibleComponent();
3992 3992 if (! (comp instanceof AccessibleExtendedComponent))
3993 3993 return null;
3994 3994 return ((AccessibleExtendedComponent)comp).getAccessibleKeyBinding();
3995 3995 }
3996 3996 }
3997 3997 return null;
3998 3998 }
3999 3999 } // inner class AccessibleJComponent
4000 4000
4001 4001
4002 4002 /**
4003 4003 * Returns an <code>ArrayTable</code> used for
4004 4004 * key/value "client properties" for this component. If the
4005 4005 * <code>clientProperties</code> table doesn't exist, an empty one
4006 4006 * will be created.
4007 4007 *
4008 4008 * @return an ArrayTable
4009 4009 * @see #putClientProperty
4010 4010 * @see #getClientProperty
4011 4011 */
4012 4012 private ArrayTable getClientProperties() {
4013 4013 if (clientProperties == null) {
4014 4014 clientProperties = new ArrayTable();
4015 4015 }
4016 4016 return clientProperties;
4017 4017 }
4018 4018
4019 4019
4020 4020 /**
4021 4021 * Returns the value of the property with the specified key. Only
4022 4022 * properties added with <code>putClientProperty</code> will return
4023 4023 * a non-<code>null</code> value.
4024 4024 *
4025 4025 * @param key the being queried
4026 4026 * @return the value of this property or <code>null</code>
4027 4027 * @see #putClientProperty
4028 4028 */
4029 4029 public final Object getClientProperty(Object key) {
4030 4030 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) {
4031 4031 return aaTextInfo;
4032 4032 } else if (key == SwingUtilities2.COMPONENT_UI_PROPERTY_KEY) {
4033 4033 return ui;
4034 4034 }
4035 4035 if(clientProperties == null) {
4036 4036 return null;
4037 4037 } else {
4038 4038 synchronized(clientProperties) {
4039 4039 return clientProperties.get(key);
4040 4040 }
4041 4041 }
4042 4042 }
4043 4043
4044 4044 /**
4045 4045 * Adds an arbitrary key/value "client property" to this component.
4046 4046 * <p>
4047 4047 * The <code>get/putClientProperty</code> methods provide access to
4048 4048 * a small per-instance hashtable. Callers can use get/putClientProperty
4049 4049 * to annotate components that were created by another module.
4050 4050 * For example, a
4051 4051 * layout manager might store per child constraints this way. For example:
4052 4052 * <pre>
4053 4053 * componentA.putClientProperty("to the left of", componentB);
4054 4054 * </pre>
4055 4055 * If value is <code>null</code> this method will remove the property.
4056 4056 * Changes to client properties are reported with
4057 4057 * <code>PropertyChange</code> events.
4058 4058 * The name of the property (for the sake of PropertyChange
4059 4059 * events) is <code>key.toString()</code>.
4060 4060 * <p>
4061 4061 * The <code>clientProperty</code> dictionary is not intended to
4062 4062 * support large
4063 4063 * scale extensions to JComponent nor should be it considered an
4064 4064 * alternative to subclassing when designing a new component.
4065 4065 *
4066 4066 * @param key the new client property key
4067 4067 * @param value the new client property value; if <code>null</code>
4068 4068 * this method will remove the property
4069 4069 * @see #getClientProperty
4070 4070 * @see #addPropertyChangeListener
4071 4071 */
4072 4072 public final void putClientProperty(Object key, Object value) {
4073 4073 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) {
4074 4074 aaTextInfo = value;
4075 4075 return;
4076 4076 }
4077 4077 if (value == null && clientProperties == null) {
4078 4078 // Both the value and ArrayTable are null, implying we don't
4079 4079 // have to do anything.
4080 4080 return;
4081 4081 }
4082 4082 ArrayTable clientProperties = getClientProperties();
4083 4083 Object oldValue;
4084 4084 synchronized(clientProperties) {
4085 4085 oldValue = clientProperties.get(key);
4086 4086 if (value != null) {
4087 4087 clientProperties.put(key, value);
4088 4088 } else if (oldValue != null) {
4089 4089 clientProperties.remove(key);
4090 4090 } else {
4091 4091 // old == new == null
4092 4092 return;
4093 4093 }
4094 4094 }
4095 4095 clientPropertyChanged(key, oldValue, value);
4096 4096 firePropertyChange(key.toString(), oldValue, value);
4097 4097 }
4098 4098
4099 4099 // Invoked from putClientProperty. This is provided for subclasses
4100 4100 // in Swing.
4101 4101 void clientPropertyChanged(Object key, Object oldValue,
4102 4102 Object newValue) {
4103 4103 }
4104 4104
4105 4105
4106 4106 /*
4107 4107 * Sets the property with the specified name to the specified value if
4108 4108 * the property has not already been set by the client program.
4109 4109 * This method is used primarily to set UI defaults for properties
4110 4110 * with primitive types, where the values cannot be marked with
4111 4111 * UIResource.
4112 4112 * @see LookAndFeel#installProperty
4113 4113 * @param propertyName String containing the name of the property
4114 4114 * @param value Object containing the property value
4115 4115 */
4116 4116 void setUIProperty(String propertyName, Object value) {
4117 4117 if (propertyName == "opaque") {
4118 4118 if (!getFlag(OPAQUE_SET)) {
4119 4119 setOpaque(((Boolean)value).booleanValue());
4120 4120 setFlag(OPAQUE_SET, false);
4121 4121 }
4122 4122 } else if (propertyName == "autoscrolls") {
4123 4123 if (!getFlag(AUTOSCROLLS_SET)) {
4124 4124 setAutoscrolls(((Boolean)value).booleanValue());
4125 4125 setFlag(AUTOSCROLLS_SET, false);
4126 4126 }
4127 4127 } else if (propertyName == "focusTraversalKeysForward") {
4128 4128 if (!getFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET)) {
4129 4129 super.setFocusTraversalKeys(KeyboardFocusManager.
4130 4130 FORWARD_TRAVERSAL_KEYS,
4131 4131 (Set<AWTKeyStroke>)value);
4132 4132 }
4133 4133 } else if (propertyName == "focusTraversalKeysBackward") {
4134 4134 if (!getFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET)) {
4135 4135 super.setFocusTraversalKeys(KeyboardFocusManager.
4136 4136 BACKWARD_TRAVERSAL_KEYS,
4137 4137 (Set<AWTKeyStroke>)value);
4138 4138 }
4139 4139 } else {
4140 4140 throw new IllegalArgumentException("property \""+
4141 4141 propertyName+ "\" cannot be set using this method");
4142 4142 }
4143 4143 }
4144 4144
4145 4145
4146 4146 /**
4147 4147 * Sets the focus traversal keys for a given traversal operation for this
4148 4148 * Component.
4149 4149 * Refer to
4150 4150 * {@link java.awt.Component#setFocusTraversalKeys}
4151 4151 * for a complete description of this method.
4152 4152 * <p>
4153 4153 * This method may throw a {@code ClassCastException} if any {@code Object}
4154 4154 * in {@code keystrokes} is not an {@code AWTKeyStroke}.
4155 4155 *
4156 4156 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4157 4157 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4158 4158 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
4159 4159 * @param keystrokes the Set of AWTKeyStroke for the specified operation
4160 4160 * @see java.awt.KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4161 4161 * @see java.awt.KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4162 4162 * @see java.awt.KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4163 4163 * @throws IllegalArgumentException if id is not one of
4164 4164 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4165 4165 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4166 4166 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes
4167 4167 * contains null, or if any keystroke represents a KEY_TYPED event,
4168 4168 * or if any keystroke already maps to another focus traversal
4169 4169 * operation for this Component
4170 4170 * @since 1.5
4171 4171 * @beaninfo
4172 4172 * bound: true
4173 4173 */
4174 4174 public void
4175 4175 setFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes)
4176 4176 {
4177 4177 if (id == KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS) {
4178 4178 setFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET,true);
4179 4179 } else if (id == KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS) {
4180 4180 setFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET,true);
4181 4181 }
4182 4182 super.setFocusTraversalKeys(id,keystrokes);
4183 4183 }
4184 4184
4185 4185 /* --- Transitional java.awt.Component Support ---
4186 4186 * The methods and fields in this section will migrate to
4187 4187 * java.awt.Component in the next JDK release.
4188 4188 */
4189 4189
4190 4190 /**
4191 4191 * Returns true if this component is lightweight, that is, if it doesn't
4192 4192 * have a native window system peer.
4193 4193 *
4194 4194 * @return true if this component is lightweight
4195 4195 */
4196 4196 @SuppressWarnings("deprecation")
4197 4197 public static boolean isLightweightComponent(Component c) {
4198 4198 return c.getPeer() instanceof LightweightPeer;
4199 4199 }
4200 4200
4201 4201
4202 4202 /**
4203 4203 * @deprecated As of JDK 5,
4204 4204 * replaced by <code>Component.setBounds(int, int, int, int)</code>.
4205 4205 * <p>
4206 4206 * Moves and resizes this component.
4207 4207 *
4208 4208 * @param x the new horizontal location
4209 4209 * @param y the new vertical location
4210 4210 * @param w the new width
4211 4211 * @param h the new height
4212 4212 * @see java.awt.Component#setBounds
4213 4213 */
4214 4214 @Deprecated
4215 4215 public void reshape(int x, int y, int w, int h) {
4216 4216 super.reshape(x, y, w, h);
4217 4217 }
4218 4218
4219 4219
4220 4220 /**
4221 4221 * Stores the bounds of this component into "return value"
4222 4222 * <code>rv</code> and returns <code>rv</code>.
4223 4223 * If <code>rv</code> is <code>null</code> a new <code>Rectangle</code>
4224 4224 * is allocated. This version of <code>getBounds</code> is useful
4225 4225 * if the caller wants to avoid allocating a new <code>Rectangle</code>
4226 4226 * object on the heap.
4227 4227 *
4228 4228 * @param rv the return value, modified to the component's bounds
4229 4229 * @return <code>rv</code>; if <code>rv</code> is <code>null</code>
4230 4230 * return a newly created <code>Rectangle</code> with this
4231 4231 * component's bounds
4232 4232 */
4233 4233 public Rectangle getBounds(Rectangle rv) {
4234 4234 if (rv == null) {
4235 4235 return new Rectangle(getX(), getY(), getWidth(), getHeight());
4236 4236 }
4237 4237 else {
4238 4238 rv.setBounds(getX(), getY(), getWidth(), getHeight());
4239 4239 return rv;
4240 4240 }
4241 4241 }
4242 4242
4243 4243
4244 4244 /**
4245 4245 * Stores the width/height of this component into "return value"
4246 4246 * <code>rv</code> and returns <code>rv</code>.
4247 4247 * If <code>rv</code> is <code>null</code> a new <code>Dimension</code>
4248 4248 * object is allocated. This version of <code>getSize</code>
4249 4249 * is useful if the caller wants to avoid allocating a new
4250 4250 * <code>Dimension</code> object on the heap.
4251 4251 *
4252 4252 * @param rv the return value, modified to the component's size
4253 4253 * @return <code>rv</code>
4254 4254 */
4255 4255 public Dimension getSize(Dimension rv) {
4256 4256 if (rv == null) {
4257 4257 return new Dimension(getWidth(), getHeight());
4258 4258 }
4259 4259 else {
4260 4260 rv.setSize(getWidth(), getHeight());
4261 4261 return rv;
4262 4262 }
4263 4263 }
4264 4264
4265 4265
4266 4266 /**
4267 4267 * Stores the x,y origin of this component into "return value"
4268 4268 * <code>rv</code> and returns <code>rv</code>.
4269 4269 * If <code>rv</code> is <code>null</code> a new <code>Point</code>
4270 4270 * is allocated. This version of <code>getLocation</code> is useful
4271 4271 * if the caller wants to avoid allocating a new <code>Point</code>
4272 4272 * object on the heap.
4273 4273 *
4274 4274 * @param rv the return value, modified to the component's location
4275 4275 * @return <code>rv</code>
4276 4276 */
4277 4277 public Point getLocation(Point rv) {
4278 4278 if (rv == null) {
4279 4279 return new Point(getX(), getY());
4280 4280 }
4281 4281 else {
4282 4282 rv.setLocation(getX(), getY());
4283 4283 return rv;
4284 4284 }
4285 4285 }
4286 4286
4287 4287
4288 4288 /**
4289 4289 * Returns the current x coordinate of the component's origin.
4290 4290 * This method is preferable to writing
4291 4291 * <code>component.getBounds().x</code>, or
4292 4292 * <code>component.getLocation().x</code> because it doesn't cause any
4293 4293 * heap allocations.
4294 4294 *
4295 4295 * @return the current x coordinate of the component's origin
4296 4296 */
4297 4297 public int getX() { return super.getX(); }
4298 4298
4299 4299
4300 4300 /**
4301 4301 * Returns the current y coordinate of the component's origin.
4302 4302 * This method is preferable to writing
4303 4303 * <code>component.getBounds().y</code>, or
4304 4304 * <code>component.getLocation().y</code> because it doesn't cause any
4305 4305 * heap allocations.
4306 4306 *
4307 4307 * @return the current y coordinate of the component's origin
4308 4308 */
4309 4309 public int getY() { return super.getY(); }
4310 4310
4311 4311
4312 4312 /**
4313 4313 * Returns the current width of this component.
4314 4314 * This method is preferable to writing
4315 4315 * <code>component.getBounds().width</code>, or
4316 4316 * <code>component.getSize().width</code> because it doesn't cause any
4317 4317 * heap allocations.
4318 4318 *
4319 4319 * @return the current width of this component
4320 4320 */
4321 4321 public int getWidth() { return super.getWidth(); }
4322 4322
4323 4323
4324 4324 /**
4325 4325 * Returns the current height of this component.
4326 4326 * This method is preferable to writing
4327 4327 * <code>component.getBounds().height</code>, or
4328 4328 * <code>component.getSize().height</code> because it doesn't cause any
4329 4329 * heap allocations.
4330 4330 *
4331 4331 * @return the current height of this component
4332 4332 */
4333 4333 public int getHeight() { return super.getHeight(); }
4334 4334
4335 4335 /**
4336 4336 * Returns true if this component is completely opaque.
4337 4337 * <p>
4338 4338 * An opaque component paints every pixel within its
4339 4339 * rectangular bounds. A non-opaque component paints only a subset of
4340 4340 * its pixels or none at all, allowing the pixels underneath it to
4341 4341 * "show through". Therefore, a component that does not fully paint
4342 4342 * its pixels provides a degree of transparency.
4343 4343 * <p>
4344 4344 * Subclasses that guarantee to always completely paint their contents
4345 4345 * should override this method and return true.
4346 4346 *
4347 4347 * @return true if this component is completely opaque
4348 4348 * @see #setOpaque
4349 4349 */
4350 4350 public boolean isOpaque() {
4351 4351 return getFlag(IS_OPAQUE);
4352 4352 }
4353 4353
4354 4354 /**
4355 4355 * If true the component paints every pixel within its bounds.
4356 4356 * Otherwise, the component may not paint some or all of its
4357 4357 * pixels, allowing the underlying pixels to show through.
4358 4358 * <p>
4359 4359 * The default value of this property is false for <code>JComponent</code>.
4360 4360 * However, the default value for this property on most standard
4361 4361 * <code>JComponent</code> subclasses (such as <code>JButton</code> and
4362 4362 * <code>JTree</code>) is look-and-feel dependent.
4363 4363 *
4364 4364 * @param isOpaque true if this component should be opaque
4365 4365 * @see #isOpaque
4366 4366 * @beaninfo
4367 4367 * bound: true
4368 4368 * expert: true
4369 4369 * description: The component's opacity
4370 4370 */
4371 4371 public void setOpaque(boolean isOpaque) {
4372 4372 boolean oldValue = getFlag(IS_OPAQUE);
4373 4373 setFlag(IS_OPAQUE, isOpaque);
4374 4374 setFlag(OPAQUE_SET, true);
4375 4375 firePropertyChange("opaque", oldValue, isOpaque);
4376 4376 }
4377 4377
4378 4378
4379 4379 /**
4380 4380 * If the specified rectangle is completely obscured by any of this
4381 4381 * component's opaque children then returns true. Only direct children
4382 4382 * are considered, more distant descendants are ignored. A
4383 4383 * <code>JComponent</code> is opaque if
4384 4384 * <code>JComponent.isOpaque()</code> returns true, other lightweight
4385 4385 * components are always considered transparent, and heavyweight components
4386 4386 * are always considered opaque.
4387 4387 *
4388 4388 * @param x x value of specified rectangle
4389 4389 * @param y y value of specified rectangle
4390 4390 * @param width width of specified rectangle
4391 4391 * @param height height of specified rectangle
4392 4392 * @return true if the specified rectangle is obscured by an opaque child
4393 4393 */
4394 4394 boolean rectangleIsObscured(int x,int y,int width,int height)
4395 4395 {
4396 4396 int numChildren = getComponentCount();
4397 4397
4398 4398 for(int i = 0; i < numChildren; i++) {
4399 4399 Component child = getComponent(i);
4400 4400 int cx, cy, cw, ch;
4401 4401
4402 4402 cx = child.getX();
4403 4403 cy = child.getY();
4404 4404 cw = child.getWidth();
4405 4405 ch = child.getHeight();
4406 4406
4407 4407 if (x >= cx && (x + width) <= (cx + cw) &&
4408 4408 y >= cy && (y + height) <= (cy + ch) && child.isVisible()) {
4409 4409
4410 4410 if(child instanceof JComponent) {
4411 4411 // System.out.println("A) checking opaque: " + ((JComponent)child).isOpaque() + " " + child);
4412 4412 // System.out.print("B) ");
4413 4413 // Thread.dumpStack();
4414 4414 return child.isOpaque();
4415 4415 } else {
4416 4416 /** Sometimes a heavy weight can have a bound larger than its peer size
4417 4417 * so we should always draw under heavy weights
4418 4418 */
4419 4419 return false;
4420 4420 }
4421 4421 }
4422 4422 }
4423 4423
4424 4424 return false;
4425 4425 }
4426 4426
4427 4427
4428 4428 /**
4429 4429 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4430 4430 * intersection of the visible rectangles for the component <code>c</code>
4431 4431 * and all of its ancestors. The return value is stored in
4432 4432 * <code>visibleRect</code>.
4433 4433 *
4434 4434 * @param c the component
4435 4435 * @param visibleRect a <code>Rectangle</code> computed as the
4436 4436 * intersection of all visible rectangles for the component
4437 4437 * <code>c</code> and all of its ancestors -- this is the
4438 4438 * return value for this method
4439 4439 * @see #getVisibleRect
4440 4440 */
4441 4441 static final void computeVisibleRect(Component c, Rectangle visibleRect) {
4442 4442 Container p = c.getParent();
4443 4443 Rectangle bounds = c.getBounds();
4444 4444
4445 4445 if (p == null || p instanceof Window || p instanceof Applet) {
4446 4446 visibleRect.setBounds(0, 0, bounds.width, bounds.height);
4447 4447 } else {
4448 4448 computeVisibleRect(p, visibleRect);
4449 4449 visibleRect.x -= bounds.x;
4450 4450 visibleRect.y -= bounds.y;
4451 4451 SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect);
4452 4452 }
4453 4453 }
4454 4454
4455 4455
4456 4456 /**
4457 4457 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4458 4458 * intersection of the visible rectangles for this component
4459 4459 * and all of its ancestors. The return value is stored in
4460 4460 * <code>visibleRect</code>.
4461 4461 *
4462 4462 * @param visibleRect a <code>Rectangle</code> computed as the
4463 4463 * intersection of all visible rectangles for this
4464 4464 * component and all of its ancestors -- this is the return
4465 4465 * value for this method
4466 4466 * @see #getVisibleRect
4467 4467 */
4468 4468 public void computeVisibleRect(Rectangle visibleRect) {
4469 4469 computeVisibleRect(this, visibleRect);
4470 4470 }
4471 4471
4472 4472
4473 4473 /**
4474 4474 * Returns the <code>Component</code>'s "visible rectangle" - the
4475 4475 * intersection of this component's visible rectangle,
4476 4476 * <code>new Rectangle(0, 0, getWidth(), getHeight())</code>,
4477 4477 * and all of its ancestors' visible rectangles.
4478 4478 *
4479 4479 * @return the visible rectangle
4480 4480 */
4481 4481 public Rectangle getVisibleRect() {
4482 4482 Rectangle visibleRect = new Rectangle();
4483 4483
4484 4484 computeVisibleRect(visibleRect);
4485 4485 return visibleRect;
4486 4486 }
4487 4487
4488 4488 /**
4489 4489 * Support for reporting bound property changes for boolean properties.
4490 4490 * This method can be called when a bound property has changed and it will
4491 4491 * send the appropriate PropertyChangeEvent to any registered
4492 4492 * PropertyChangeListeners.
4493 4493 *
4494 4494 * @param propertyName the property whose value has changed
4495 4495 * @param oldValue the property's previous value
4496 4496 * @param newValue the property's new value
4497 4497 */
4498 4498 public void firePropertyChange(String propertyName,
4499 4499 boolean oldValue, boolean newValue) {
4500 4500 super.firePropertyChange(propertyName, oldValue, newValue);
4501 4501 }
4502 4502
4503 4503
4504 4504 /**
4505 4505 * Support for reporting bound property changes for integer properties.
4506 4506 * This method can be called when a bound property has changed and it will
4507 4507 * send the appropriate PropertyChangeEvent to any registered
4508 4508 * PropertyChangeListeners.
4509 4509 *
4510 4510 * @param propertyName the property whose value has changed
4511 4511 * @param oldValue the property's previous value
4512 4512 * @param newValue the property's new value
4513 4513 */
4514 4514 public void firePropertyChange(String propertyName,
4515 4515 int oldValue, int newValue) {
4516 4516 super.firePropertyChange(propertyName, oldValue, newValue);
4517 4517 }
4518 4518
4519 4519 // XXX This method is implemented as a workaround to a JLS issue with ambiguous
4520 4520 // methods. This should be removed once 4758654 is resolved.
4521 4521 public void firePropertyChange(String propertyName, char oldValue, char newValue) {
4522 4522 super.firePropertyChange(propertyName, oldValue, newValue);
4523 4523 }
4524 4524
4525 4525 /**
4526 4526 * Supports reporting constrained property changes.
4527 4527 * This method can be called when a constrained property has changed
4528 4528 * and it will send the appropriate <code>PropertyChangeEvent</code>
4529 4529 * to any registered <code>VetoableChangeListeners</code>.
4530 4530 *
4531 4531 * @param propertyName the name of the property that was listened on
4532 4532 * @param oldValue the old value of the property
4533 4533 * @param newValue the new value of the property
4534 4534 * @exception java.beans.PropertyVetoException when the attempt to set the
4535 4535 * property is vetoed by the component
4536 4536 */
4537 4537 protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
4538 4538 throws java.beans.PropertyVetoException
4539 4539 {
4540 4540 if (vetoableChangeSupport == null) {
4541 4541 return;
4542 4542 }
4543 4543 vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
4544 4544 }
4545 4545
4546 4546
4547 4547 /**
4548 4548 * Adds a <code>VetoableChangeListener</code> to the listener list.
4549 4549 * The listener is registered for all properties.
4550 4550 *
4551 4551 * @param listener the <code>VetoableChangeListener</code> to be added
4552 4552 */
4553 4553 public synchronized void addVetoableChangeListener(VetoableChangeListener listener) {
4554 4554 if (vetoableChangeSupport == null) {
4555 4555 vetoableChangeSupport = new java.beans.VetoableChangeSupport(this);
4556 4556 }
4557 4557 vetoableChangeSupport.addVetoableChangeListener(listener);
4558 4558 }
4559 4559
4560 4560
4561 4561 /**
4562 4562 * Removes a <code>VetoableChangeListener</code> from the listener list.
4563 4563 * This removes a <code>VetoableChangeListener</code> that was registered
4564 4564 * for all properties.
4565 4565 *
4566 4566 * @param listener the <code>VetoableChangeListener</code> to be removed
4567 4567 */
4568 4568 public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) {
4569 4569 if (vetoableChangeSupport == null) {
4570 4570 return;
4571 4571 }
4572 4572 vetoableChangeSupport.removeVetoableChangeListener(listener);
4573 4573 }
4574 4574
4575 4575
4576 4576 /**
4577 4577 * Returns an array of all the vetoable change listeners
4578 4578 * registered on this component.
4579 4579 *
4580 4580 * @return all of the component's <code>VetoableChangeListener</code>s
4581 4581 * or an empty
4582 4582 * array if no vetoable change listeners are currently registered
4583 4583 *
4584 4584 * @see #addVetoableChangeListener
4585 4585 * @see #removeVetoableChangeListener
4586 4586 *
4587 4587 * @since 1.4
4588 4588 */
4589 4589 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
4590 4590 if (vetoableChangeSupport == null) {
4591 4591 return new VetoableChangeListener[0];
4592 4592 }
4593 4593 return vetoableChangeSupport.getVetoableChangeListeners();
4594 4594 }
4595 4595
4596 4596
4597 4597 /**
4598 4598 * Returns the top-level ancestor of this component (either the
4599 4599 * containing <code>Window</code> or <code>Applet</code>),
4600 4600 * or <code>null</code> if this component has not
4601 4601 * been added to any container.
4602 4602 *
4603 4603 * @return the top-level <code>Container</code> that this component is in,
4604 4604 * or <code>null</code> if not in any container
4605 4605 */
4606 4606 public Container getTopLevelAncestor() {
4607 4607 for(Container p = this; p != null; p = p.getParent()) {
4608 4608 if(p instanceof Window || p instanceof Applet) {
4609 4609 return p;
4610 4610 }
4611 4611 }
4612 4612 return null;
4613 4613 }
4614 4614
4615 4615 private AncestorNotifier getAncestorNotifier() {
4616 4616 return (AncestorNotifier)
4617 4617 getClientProperty(JComponent_ANCESTOR_NOTIFIER);
4618 4618 }
4619 4619
4620 4620 /**
4621 4621 * Registers <code>listener</code> so that it will receive
4622 4622 * <code>AncestorEvents</code> when it or any of its ancestors
4623 4623 * move or are made visible or invisible.
4624 4624 * Events are also sent when the component or its ancestors are added
4625 4625 * or removed from the containment hierarchy.
4626 4626 *
4627 4627 * @param listener the <code>AncestorListener</code> to register
4628 4628 * @see AncestorEvent
4629 4629 */
4630 4630 public void addAncestorListener(AncestorListener listener) {
4631 4631 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4632 4632 if (ancestorNotifier == null) {
4633 4633 ancestorNotifier = new AncestorNotifier(this);
4634 4634 putClientProperty(JComponent_ANCESTOR_NOTIFIER,
4635 4635 ancestorNotifier);
4636 4636 }
4637 4637 ancestorNotifier.addAncestorListener(listener);
4638 4638 }
4639 4639
4640 4640 /**
4641 4641 * Unregisters <code>listener</code> so that it will no longer receive
4642 4642 * <code>AncestorEvents</code>.
4643 4643 *
4644 4644 * @param listener the <code>AncestorListener</code> to be removed
4645 4645 * @see #addAncestorListener
4646 4646 */
4647 4647 public void removeAncestorListener(AncestorListener listener) {
4648 4648 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4649 4649 if (ancestorNotifier == null) {
4650 4650 return;
4651 4651 }
4652 4652 ancestorNotifier.removeAncestorListener(listener);
4653 4653 if (ancestorNotifier.listenerList.getListenerList().length == 0) {
4654 4654 ancestorNotifier.removeAllListeners();
4655 4655 putClientProperty(JComponent_ANCESTOR_NOTIFIER, null);
4656 4656 }
4657 4657 }
4658 4658
4659 4659 /**
4660 4660 * Returns an array of all the ancestor listeners
4661 4661 * registered on this component.
4662 4662 *
4663 4663 * @return all of the component's <code>AncestorListener</code>s
4664 4664 * or an empty
4665 4665 * array if no ancestor listeners are currently registered
4666 4666 *
4667 4667 * @see #addAncestorListener
4668 4668 * @see #removeAncestorListener
4669 4669 *
4670 4670 * @since 1.4
4671 4671 */
4672 4672 public AncestorListener[] getAncestorListeners() {
4673 4673 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4674 4674 if (ancestorNotifier == null) {
4675 4675 return new AncestorListener[0];
4676 4676 }
4677 4677 return ancestorNotifier.getAncestorListeners();
4678 4678 }
4679 4679
4680 4680 /**
4681 4681 * Returns an array of all the objects currently registered
4682 4682 * as <code><em>Foo</em>Listener</code>s
4683 4683 * upon this <code>JComponent</code>.
4684 4684 * <code><em>Foo</em>Listener</code>s are registered using the
4685 4685 * <code>add<em>Foo</em>Listener</code> method.
4686 4686 *
4687 4687 * <p>
4688 4688 *
4689 4689 * You can specify the <code>listenerType</code> argument
4690 4690 * with a class literal,
4691 4691 * such as
4692 4692 * <code><em>Foo</em>Listener.class</code>.
4693 4693 * For example, you can query a
4694 4694 * <code>JComponent</code> <code>c</code>
4695 4695 * for its mouse listeners with the following code:
4696 4696 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
4697 4697 * If no such listeners exist, this method returns an empty array.
4698 4698 *
4699 4699 * @param listenerType the type of listeners requested; this parameter
4700 4700 * should specify an interface that descends from
4701 4701 * <code>java.util.EventListener</code>
4702 4702 * @return an array of all objects registered as
4703 4703 * <code><em>Foo</em>Listener</code>s on this component,
4704 4704 * or an empty array if no such
4705 4705 * listeners have been added
4706 4706 * @exception ClassCastException if <code>listenerType</code>
4707 4707 * doesn't specify a class or interface that implements
4708 4708 * <code>java.util.EventListener</code>
4709 4709 *
4710 4710 * @since 1.3
4711 4711 *
4712 4712 * @see #getVetoableChangeListeners
4713 4713 * @see #getAncestorListeners
4714 4714 */
4715 4715 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
4716 4716 T[] result;
4717 4717 if (listenerType == AncestorListener.class) {
4718 4718 // AncestorListeners are handled by the AncestorNotifier
4719 4719 result = (T[])getAncestorListeners();
4720 4720 }
4721 4721 else if (listenerType == VetoableChangeListener.class) {
4722 4722 // VetoableChangeListeners are handled by VetoableChangeSupport
4723 4723 result = (T[])getVetoableChangeListeners();
4724 4724 }
4725 4725 else if (listenerType == PropertyChangeListener.class) {
4726 4726 // PropertyChangeListeners are handled by PropertyChangeSupport
4727 4727 result = (T[])getPropertyChangeListeners();
4728 4728 }
4729 4729 else {
4730 4730 result = listenerList.getListeners(listenerType);
4731 4731 }
4732 4732
4733 4733 if (result.length == 0) {
4734 4734 return super.getListeners(listenerType);
4735 4735 }
4736 4736 return result;
4737 4737 }
4738 4738
4739 4739 /**
4740 4740 * Notifies this component that it now has a parent component.
4741 4741 * When this method is invoked, the chain of parent components is
4742 4742 * set up with <code>KeyboardAction</code> event listeners.
4743 4743 * This method is called by the toolkit internally and should
4744 4744 * not be called directly by programs.
4745 4745 *
4746 4746 * @see #registerKeyboardAction
4747 4747 */
4748 4748 public void addNotify() {
4749 4749 super.addNotify();
4750 4750 firePropertyChange("ancestor", null, getParent());
4751 4751
4752 4752 registerWithKeyboardManager(false);
4753 4753 registerNextFocusableComponent();
4754 4754 }
4755 4755
4756 4756
4757 4757 /**
4758 4758 * Notifies this component that it no longer has a parent component.
4759 4759 * When this method is invoked, any <code>KeyboardAction</code>s
4760 4760 * set up in the the chain of parent components are removed.
4761 4761 * This method is called by the toolkit internally and should
4762 4762 * not be called directly by programs.
4763 4763 *
4764 4764 * @see #registerKeyboardAction
4765 4765 */
4766 4766 public void removeNotify() {
4767 4767 super.removeNotify();
4768 4768 // This isn't strictly correct. The event shouldn't be
4769 4769 // fired until *after* the parent is set to null. But
4770 4770 // we only get notified before that happens
4771 4771 firePropertyChange("ancestor", getParent(), null);
4772 4772
4773 4773 unregisterWithKeyboardManager();
4774 4774 deregisterNextFocusableComponent();
4775 4775
4776 4776 if (getCreatedDoubleBuffer()) {
4777 4777 RepaintManager.currentManager(this).resetDoubleBuffer();
4778 4778 setCreatedDoubleBuffer(false);
4779 4779 }
4780 4780 if (autoscrolls) {
4781 4781 Autoscroller.stop(this);
4782 4782 }
4783 4783 }
4784 4784
4785 4785
4786 4786 /**
4787 4787 * Adds the specified region to the dirty region list if the component
4788 4788 * is showing. The component will be repainted after all of the
4789 4789 * currently pending events have been dispatched.
4790 4790 *
4791 4791 * @param tm this parameter is not used
4792 4792 * @param x the x value of the dirty region
4793 4793 * @param y the y value of the dirty region
4794 4794 * @param width the width of the dirty region
4795 4795 * @param height the height of the dirty region
4796 4796 * @see #isPaintingOrigin()
4797 4797 * @see java.awt.Component#isShowing
4798 4798 * @see RepaintManager#addDirtyRegion
4799 4799 */
4800 4800 public void repaint(long tm, int x, int y, int width, int height) {
4801 4801 RepaintManager.currentManager(SunToolkit.targetToAppContext(this))
4802 4802 .addDirtyRegion(this, x, y, width, height);
4803 4803 }
4804 4804
4805 4805
4806 4806 /**
4807 4807 * Adds the specified region to the dirty region list if the component
4808 4808 * is showing. The component will be repainted after all of the
4809 4809 * currently pending events have been dispatched.
4810 4810 *
4811 4811 * @param r a <code>Rectangle</code> containing the dirty region
4812 4812 * @see #isPaintingOrigin()
4813 4813 * @see java.awt.Component#isShowing
4814 4814 * @see RepaintManager#addDirtyRegion
4815 4815 */
4816 4816 public void repaint(Rectangle r) {
4817 4817 repaint(0,r.x,r.y,r.width,r.height);
4818 4818 }
4819 4819
4820 4820
4821 4821 /**
4822 4822 * Supports deferred automatic layout.
4823 4823 * <p>
4824 4824 * Calls <code>invalidate</code> and then adds this component's
4825 4825 * <code>validateRoot</code> to a list of components that need to be
4826 4826 * validated. Validation will occur after all currently pending
4827 4827 * events have been dispatched. In other words after this method
4828 4828 * is called, the first validateRoot (if any) found when walking
4829 4829 * up the containment hierarchy of this component will be validated.
4830 4830 * By default, <code>JRootPane</code>, <code>JScrollPane</code>,
4831 4831 * and <code>JTextField</code> return true
4832 4832 * from <code>isValidateRoot</code>.
4833 4833 * <p>
4834 4834 * This method will automatically be called on this component
4835 4835 * when a property value changes such that size, location, or
4836 4836 * internal layout of this component has been affected. This automatic
4837 4837 * updating differs from the AWT because programs generally no
4838 4838 * longer need to invoke <code>validate</code> to get the contents of the
4839 4839 * GUI to update.
4840 4840 *
4841 4841 * @see java.awt.Component#invalidate
4842 4842 * @see java.awt.Container#validate
4843 4843 * @see #isValidateRoot
4844 4844 * @see RepaintManager#addInvalidComponent
4845 4845 */
4846 4846 public void revalidate() {
4847 4847 if (getParent() == null) {
4848 4848 // Note: We don't bother invalidating here as once added
4849 4849 // to a valid parent invalidate will be invoked (addImpl
4850 4850 // invokes addNotify which will invoke invalidate on the
4851 4851 // new Component). Also, if we do add a check to isValid
4852 4852 // here it can potentially be called before the constructor
4853 4853 // which was causing some people grief.
4854 4854 return;
4855 4855 }
4856 4856 if (SunToolkit.isDispatchThreadForAppContext(this)) {
4857 4857 invalidate();
4858 4858 RepaintManager.currentManager(this).addInvalidComponent(this);
4859 4859 }
4860 4860 else {
4861 4861 // To avoid a flood of Runnables when constructing GUIs off
4862 4862 // the EDT, a flag is maintained as to whether or not
4863 4863 // a Runnable has been scheduled.
4864 4864 if (revalidateRunnableScheduled.getAndSet(true)) {
4865 4865 return;
4866 4866 }
4867 4867 SunToolkit.executeOnEventHandlerThread(this, () -> {
4868 4868 revalidateRunnableScheduled.set(false);
4869 4869 revalidate();
4870 4870 });
4871 4871 }
4872 4872 }
4873 4873
4874 4874 /**
4875 4875 * If this method returns true, <code>revalidate</code> calls by
4876 4876 * descendants of this component will cause the entire tree
4877 4877 * beginning with this root to be validated.
4878 4878 * Returns false by default. <code>JScrollPane</code> overrides
4879 4879 * this method and returns true.
4880 4880 *
4881 4881 * @return always returns false
4882 4882 * @see #revalidate
4883 4883 * @see java.awt.Component#invalidate
4884 4884 * @see java.awt.Container#validate
4885 4885 * @see java.awt.Container#isValidateRoot
4886 4886 */
4887 4887 @Override
4888 4888 public boolean isValidateRoot() {
4889 4889 return false;
4890 4890 }
4891 4891
4892 4892
4893 4893 /**
4894 4894 * Returns true if this component tiles its children -- that is, if
4895 4895 * it can guarantee that the children will not overlap. The
4896 4896 * repainting system is substantially more efficient in this
4897 4897 * common case. <code>JComponent</code> subclasses that can't make this
4898 4898 * guarantee, such as <code>JLayeredPane</code>,
4899 4899 * should override this method to return false.
4900 4900 *
4901 4901 * @return always returns true
4902 4902 */
4903 4903 public boolean isOptimizedDrawingEnabled() {
4904 4904 return true;
4905 4905 }
4906 4906
4907 4907 /**
4908 4908 * Returns {@code true} if a paint triggered on a child component should cause
4909 4909 * painting to originate from this Component, or one of its ancestors.
4910 4910 * <p>
4911 4911 * Calling {@link #repaint} or {@link #paintImmediately(int, int, int, int)}
4912 4912 * on a Swing component will result in calling
4913 4913 * the {@link JComponent#paintImmediately(int, int, int, int)} method of
4914 4914 * the first ancestor which {@code isPaintingOrigin()} returns {@code true}, if there are any.
4915 4915 * <p>
4916 4916 * {@code JComponent} subclasses that need to be painted when any of their
4917 4917 * children are repainted should override this method to return {@code true}.
4918 4918 *
4919 4919 * @return always returns {@code false}
4920 4920 *
4921 4921 * @see #paintImmediately(int, int, int, int)
4922 4922 */
4923 4923 protected boolean isPaintingOrigin() {
4924 4924 return false;
4925 4925 }
4926 4926
4927 4927 /**
4928 4928 * Paints the specified region in this component and all of its
4929 4929 * descendants that overlap the region, immediately.
4930 4930 * <p>
4931 4931 * It's rarely necessary to call this method. In most cases it's
4932 4932 * more efficient to call repaint, which defers the actual painting
4933 4933 * and can collapse redundant requests into a single paint call.
4934 4934 * This method is useful if one needs to update the display while
4935 4935 * the current event is being dispatched.
4936 4936 * <p>
4937 4937 * This method is to be overridden when the dirty region needs to be changed
4938 4938 * for components that are painting origins.
4939 4939 *
4940 4940 * @param x the x value of the region to be painted
4941 4941 * @param y the y value of the region to be painted
4942 4942 * @param w the width of the region to be painted
4943 4943 * @param h the height of the region to be painted
4944 4944 * @see #repaint
4945 4945 * @see #isPaintingOrigin()
4946 4946 */
4947 4947 public void paintImmediately(int x,int y,int w, int h) {
4948 4948 Component c = this;
4949 4949 Component parent;
4950 4950
4951 4951 if(!isShowing()) {
4952 4952 return;
4953 4953 }
4954 4954
4955 4955 JComponent paintingOigin = SwingUtilities.getPaintingOrigin(this);
4956 4956 if (paintingOigin != null) {
4957 4957 Rectangle rectangle = SwingUtilities.convertRectangle(
4958 4958 c, new Rectangle(x, y, w, h), paintingOigin);
4959 4959 paintingOigin.paintImmediately(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
4960 4960 return;
4961 4961 }
4962 4962
4963 4963 while(!c.isOpaque()) {
4964 4964 parent = c.getParent();
4965 4965 if(parent != null) {
4966 4966 x += c.getX();
4967 4967 y += c.getY();
4968 4968 c = parent;
4969 4969 } else {
4970 4970 break;
4971 4971 }
4972 4972
4973 4973 if(!(c instanceof JComponent)) {
4974 4974 break;
4975 4975 }
4976 4976 }
4977 4977 if(c instanceof JComponent) {
4978 4978 ((JComponent)c)._paintImmediately(x,y,w,h);
4979 4979 } else {
4980 4980 c.repaint(x,y,w,h);
4981 4981 }
4982 4982 }
4983 4983
4984 4984 /**
4985 4985 * Paints the specified region now.
4986 4986 *
4987 4987 * @param r a <code>Rectangle</code> containing the region to be painted
4988 4988 */
4989 4989 public void paintImmediately(Rectangle r) {
4990 4990 paintImmediately(r.x,r.y,r.width,r.height);
4991 4991 }
4992 4992
4993 4993 /**
4994 4994 * Returns whether this component should be guaranteed to be on top.
4995 4995 * For example, it would make no sense for <code>Menu</code>s to pop up
4996 4996 * under another component, so they would always return true.
4997 4997 * Most components will want to return false, hence that is the default.
4998 4998 *
4999 4999 * @return always returns false
5000 5000 */
5001 5001 // package private
5002 5002 boolean alwaysOnTop() {
5003 5003 return false;
5004 5004 }
5005 5005
5006 5006 void setPaintingChild(Component paintingChild) {
5007 5007 this.paintingChild = paintingChild;
5008 5008 }
5009 5009
5010 5010 void _paintImmediately(int x, int y, int w, int h) {
5011 5011 Graphics g;
5012 5012 Container c;
5013 5013 Rectangle b;
5014 5014
5015 5015 int tmpX, tmpY, tmpWidth, tmpHeight;
5016 5016 int offsetX=0,offsetY=0;
5017 5017
5018 5018 boolean hasBuffer = false;
5019 5019
5020 5020 JComponent bufferedComponent = null;
5021 5021 JComponent paintingComponent = this;
5022 5022
5023 5023 RepaintManager repaintManager = RepaintManager.currentManager(this);
5024 5024 // parent Container's up to Window or Applet. First container is
5025 5025 // the direct parent. Note that in testing it was faster to
5026 5026 // alloc a new Vector vs keeping a stack of them around, and gc
5027 5027 // seemed to have a minimal effect on this.
5028 5028 java.util.List<Component> path = new java.util.ArrayList<Component>(7);
5029 5029 int pIndex = -1;
5030 5030 int pCount = 0;
5031 5031
5032 5032 tmpX = tmpY = tmpWidth = tmpHeight = 0;
5033 5033
5034 5034 Rectangle paintImmediatelyClip = fetchRectangle();
5035 5035 paintImmediatelyClip.x = x;
5036 5036 paintImmediatelyClip.y = y;
5037 5037 paintImmediatelyClip.width = w;
5038 5038 paintImmediatelyClip.height = h;
5039 5039
5040 5040
5041 5041 // System.out.println("1) ************* in _paintImmediately for " + this);
5042 5042
5043 5043 boolean ontop = alwaysOnTop() && isOpaque();
5044 5044 if (ontop) {
5045 5045 SwingUtilities.computeIntersection(0, 0, getWidth(), getHeight(),
5046 5046 paintImmediatelyClip);
5047 5047 if (paintImmediatelyClip.width == 0) {
5048 5048 recycleRectangle(paintImmediatelyClip);
5049 5049 return;
5050 5050 }
5051 5051 }
5052 5052 Component child;
5053 5053 for (c = this, child = null;
5054 5054 c != null && !(c instanceof Window) && !(c instanceof Applet);
5055 5055 child = c, c = c.getParent()) {
5056 5056 JComponent jc = (c instanceof JComponent) ? (JComponent)c :
5057 5057 null;
5058 5058 path.add(c);
5059 5059 if(!ontop && jc != null && !jc.isOptimizedDrawingEnabled()) {
5060 5060 boolean resetPC;
5061 5061
5062 5062 // Children of c may overlap, three possible cases for the
5063 5063 // painting region:
5064 5064 // . Completely obscured by an opaque sibling, in which
5065 5065 // case there is no need to paint.
5066 5066 // . Partially obscured by a sibling: need to start
5067 5067 // painting from c.
5068 5068 // . Otherwise we aren't obscured and thus don't need to
5069 5069 // start painting from parent.
5070 5070 if (c != this) {
5071 5071 if (jc.isPaintingOrigin()) {
5072 5072 resetPC = true;
5073 5073 }
5074 5074 else {
5075 5075 Component[] children = c.getComponents();
5076 5076 int i = 0;
5077 5077 for (; i<children.length; i++) {
5078 5078 if (children[i] == child) break;
5079 5079 }
5080 5080 switch (jc.getObscuredState(i,
5081 5081 paintImmediatelyClip.x,
5082 5082 paintImmediatelyClip.y,
5083 5083 paintImmediatelyClip.width,
5084 5084 paintImmediatelyClip.height)) {
5085 5085 case NOT_OBSCURED:
5086 5086 resetPC = false;
5087 5087 break;
5088 5088 case COMPLETELY_OBSCURED:
5089 5089 recycleRectangle(paintImmediatelyClip);
5090 5090 return;
5091 5091 default:
5092 5092 resetPC = true;
5093 5093 break;
5094 5094 }
5095 5095 }
5096 5096 }
5097 5097 else {
5098 5098 resetPC = false;
5099 5099 }
5100 5100
5101 5101 if (resetPC) {
5102 5102 // Get rid of any buffer since we draw from here and
5103 5103 // we might draw something larger
5104 5104 paintingComponent = jc;
5105 5105 pIndex = pCount;
5106 5106 offsetX = offsetY = 0;
5107 5107 hasBuffer = false;
5108 5108 }
5109 5109 }
5110 5110 pCount++;
5111 5111
5112 5112 // look to see if the parent (and therefor this component)
5113 5113 // is double buffered
5114 5114 if(repaintManager.isDoubleBufferingEnabled() && jc != null &&
5115 5115 jc.isDoubleBuffered()) {
5116 5116 hasBuffer = true;
5117 5117 bufferedComponent = jc;
5118 5118 }
5119 5119
5120 5120 // if we aren't on top, include the parent's clip
5121 5121 if (!ontop) {
5122 5122 int bx = c.getX();
5123 5123 int by = c.getY();
5124 5124 tmpWidth = c.getWidth();
5125 5125 tmpHeight = c.getHeight();
5126 5126 SwingUtilities.computeIntersection(tmpX,tmpY,tmpWidth,tmpHeight,paintImmediatelyClip);
5127 5127 paintImmediatelyClip.x += bx;
5128 5128 paintImmediatelyClip.y += by;
5129 5129 offsetX += bx;
5130 5130 offsetY += by;
5131 5131 }
5132 5132 }
5133 5133
5134 5134 // If the clip width or height is negative, don't bother painting
5135 5135 if(c == null || c.getPeer() == null ||
5136 5136 paintImmediatelyClip.width <= 0 ||
5137 5137 paintImmediatelyClip.height <= 0) {
5138 5138 recycleRectangle(paintImmediatelyClip);
5139 5139 return;
5140 5140 }
5141 5141
5142 5142 paintingComponent.setFlag(IS_REPAINTING, true);
5143 5143
5144 5144 paintImmediatelyClip.x -= offsetX;
5145 5145 paintImmediatelyClip.y -= offsetY;
5146 5146
5147 5147 // Notify the Components that are going to be painted of the
5148 5148 // child component to paint to.
5149 5149 if(paintingComponent != this) {
5150 5150 Component comp;
5151 5151 int i = pIndex;
5152 5152 for(; i > 0 ; i--) {
5153 5153 comp = path.get(i);
5154 5154 if(comp instanceof JComponent) {
5155 5155 ((JComponent)comp).setPaintingChild(path.get(i-1));
5156 5156 }
5157 5157 }
5158 5158 }
5159 5159 try {
5160 5160 if ((g = safelyGetGraphics(paintingComponent, c)) != null) {
5161 5161 try {
5162 5162 if (hasBuffer) {
5163 5163 RepaintManager rm = RepaintManager.currentManager(
5164 5164 bufferedComponent);
5165 5165 rm.beginPaint();
5166 5166 try {
5167 5167 rm.paint(paintingComponent, bufferedComponent, g,
5168 5168 paintImmediatelyClip.x,
5169 5169 paintImmediatelyClip.y,
5170 5170 paintImmediatelyClip.width,
5171 5171 paintImmediatelyClip.height);
5172 5172 } finally {
5173 5173 rm.endPaint();
5174 5174 }
5175 5175 } else {
5176 5176 g.setClip(paintImmediatelyClip.x, paintImmediatelyClip.y,
5177 5177 paintImmediatelyClip.width, paintImmediatelyClip.height);
5178 5178 paintingComponent.paint(g);
5179 5179 }
5180 5180 } finally {
5181 5181 g.dispose();
5182 5182 }
5183 5183 }
5184 5184 }
5185 5185 finally {
5186 5186 // Reset the painting child for the parent components.
5187 5187 if(paintingComponent != this) {
5188 5188 Component comp;
5189 5189 int i = pIndex;
5190 5190 for(; i > 0 ; i--) {
5191 5191 comp = path.get(i);
5192 5192 if(comp instanceof JComponent) {
5193 5193 ((JComponent)comp).setPaintingChild(null);
5194 5194 }
5195 5195 }
5196 5196 }
5197 5197 paintingComponent.setFlag(IS_REPAINTING, false);
5198 5198 }
5199 5199 recycleRectangle(paintImmediatelyClip);
5200 5200 }
5201 5201
5202 5202 /**
5203 5203 * Paints to the specified graphics. This does not set the clip and it
5204 5204 * does not adjust the Graphics in anyway, callers must do that first.
5205 5205 * This method is package-private for RepaintManager.PaintManager and
5206 5206 * its subclasses to call, it is NOT intended for general use outside
5207 5207 * of that.
5208 5208 */
5209 5209 void paintToOffscreen(Graphics g, int x, int y, int w, int h, int maxX,
5210 5210 int maxY) {
5211 5211 try {
5212 5212 setFlag(ANCESTOR_USING_BUFFER, true);
5213 5213 if ((y + h) < maxY || (x + w) < maxX) {
5214 5214 setFlag(IS_PAINTING_TILE, true);
5215 5215 }
5216 5216 if (getFlag(IS_REPAINTING)) {
5217 5217 // Called from paintImmediately (RepaintManager) to fill
5218 5218 // repaint request
5219 5219 paint(g);
5220 5220 } else {
5221 5221 // Called from paint() (AWT) to repair damage
5222 5222 if(!rectangleIsObscured(x, y, w, h)) {
5223 5223 paintComponent(g);
5224 5224 paintBorder(g);
5225 5225 }
5226 5226 paintChildren(g);
5227 5227 }
5228 5228 } finally {
5229 5229 setFlag(ANCESTOR_USING_BUFFER, false);
5230 5230 setFlag(IS_PAINTING_TILE, false);
5231 5231 }
5232 5232 }
5233 5233
5234 5234 /**
5235 5235 * Returns whether or not the region of the specified component is
5236 5236 * obscured by a sibling.
5237 5237 *
5238 5238 * @return NOT_OBSCURED if non of the siblings above the Component obscure
5239 5239 * it, COMPLETELY_OBSCURED if one of the siblings completely
5240 5240 * obscures the Component or PARTIALLY_OBSCURED if the Component is
5241 5241 * only partially obscured.
5242 5242 */
5243 5243 private int getObscuredState(int compIndex, int x, int y, int width,
5244 5244 int height) {
5245 5245 int retValue = NOT_OBSCURED;
5246 5246 Rectangle tmpRect = fetchRectangle();
5247 5247
5248 5248 for (int i = compIndex - 1 ; i >= 0 ; i--) {
5249 5249 Component sibling = getComponent(i);
5250 5250 if (!sibling.isVisible()) {
5251 5251 continue;
5252 5252 }
5253 5253 Rectangle siblingRect;
5254 5254 boolean opaque;
5255 5255 if (sibling instanceof JComponent) {
5256 5256 opaque = sibling.isOpaque();
5257 5257 if (!opaque) {
5258 5258 if (retValue == PARTIALLY_OBSCURED) {
5259 5259 continue;
5260 5260 }
5261 5261 }
5262 5262 }
5263 5263 else {
5264 5264 opaque = true;
5265 5265 }
5266 5266 siblingRect = sibling.getBounds(tmpRect);
5267 5267 if (opaque && x >= siblingRect.x && (x + width) <=
5268 5268 (siblingRect.x + siblingRect.width) &&
5269 5269 y >= siblingRect.y && (y + height) <=
5270 5270 (siblingRect.y + siblingRect.height)) {
5271 5271 recycleRectangle(tmpRect);
5272 5272 return COMPLETELY_OBSCURED;
5273 5273 }
5274 5274 else if (retValue == NOT_OBSCURED &&
5275 5275 !((x + width <= siblingRect.x) ||
5276 5276 (y + height <= siblingRect.y) ||
5277 5277 (x >= siblingRect.x + siblingRect.width) ||
5278 5278 (y >= siblingRect.y + siblingRect.height))) {
5279 5279 retValue = PARTIALLY_OBSCURED;
5280 5280 }
5281 5281 }
5282 5282 recycleRectangle(tmpRect);
5283 5283 return retValue;
5284 5284 }
5285 5285
5286 5286 /**
5287 5287 * Returns true, which implies that before checking if a child should
5288 5288 * be painted it is first check that the child is not obscured by another
5289 5289 * sibling. This is only checked if <code>isOptimizedDrawingEnabled</code>
5290 5290 * returns false.
5291 5291 *
5292 5292 * @return always returns true
5293 5293 */
5294 5294 boolean checkIfChildObscuredBySibling() {
5295 5295 return true;
5296 5296 }
5297 5297
5298 5298
5299 5299 private void setFlag(int aFlag, boolean aValue) {
5300 5300 if(aValue) {
5301 5301 flags |= (1 << aFlag);
5302 5302 } else {
5303 5303 flags &= ~(1 << aFlag);
5304 5304 }
5305 5305 }
5306 5306 private boolean getFlag(int aFlag) {
5307 5307 int mask = (1 << aFlag);
5308 5308 return ((flags & mask) == mask);
5309 5309 }
5310 5310 // These functions must be static so that they can be called from
5311 5311 // subclasses inside the package, but whose inheritance hierarhcy includes
5312 5312 // classes outside of the package below JComponent (e.g., JTextArea).
5313 5313 static void setWriteObjCounter(JComponent comp, byte count) {
5314 5314 comp.flags = (comp.flags & ~(0xFF << WRITE_OBJ_COUNTER_FIRST)) |
5315 5315 (count << WRITE_OBJ_COUNTER_FIRST);
5316 5316 }
5317 5317 static byte getWriteObjCounter(JComponent comp) {
5318 5318 return (byte)((comp.flags >> WRITE_OBJ_COUNTER_FIRST) & 0xFF);
5319 5319 }
5320 5320
5321 5321 /** Buffering **/
5322 5322
5323 5323 /**
5324 5324 * Sets whether this component should use a buffer to paint.
5325 5325 * If set to true, all the drawing from this component will be done
5326 5326 * in an offscreen painting buffer. The offscreen painting buffer will
5327 5327 * the be copied onto the screen.
5328 5328 * If a <code>Component</code> is buffered and one of its ancestor
5329 5329 * is also buffered, the ancestor buffer will be used.
5330 5330 *
5331 5331 * @param aFlag if true, set this component to be double buffered
5332 5332 */
5333 5333 public void setDoubleBuffered(boolean aFlag) {
5334 5334 setFlag(IS_DOUBLE_BUFFERED,aFlag);
5335 5335 }
5336 5336
5337 5337 /**
5338 5338 * Returns whether this component should use a buffer to paint.
5339 5339 *
5340 5340 * @return true if this component is double buffered, otherwise false
5341 5341 */
5342 5342 public boolean isDoubleBuffered() {
5343 5343 return getFlag(IS_DOUBLE_BUFFERED);
5344 5344 }
5345 5345
5346 5346 /**
5347 5347 * Returns the <code>JRootPane</code> ancestor for this component.
5348 5348 *
5349 5349 * @return the <code>JRootPane</code> that contains this component,
5350 5350 * or <code>null</code> if no <code>JRootPane</code> is found
5351 5351 */
5352 5352 public JRootPane getRootPane() {
5353 5353 return SwingUtilities.getRootPane(this);
5354 5354 }
5355 5355
5356 5356
5357 5357 /** Serialization **/
5358 5358
5359 5359 /**
5360 5360 * This is called from Component by way of reflection. Do NOT change
5361 5361 * the name unless you change the code in Component as well.
5362 5362 */
5363 5363 void compWriteObjectNotify() {
5364 5364 byte count = JComponent.getWriteObjCounter(this);
5365 5365 JComponent.setWriteObjCounter(this, (byte)(count + 1));
5366 5366 if (count != 0) {
5367 5367 return;
5368 5368 }
5369 5369
5370 5370 uninstallUIAndProperties();
5371 5371
5372 5372 /* JTableHeader is in a separate package, which prevents it from
5373 5373 * being able to override this package-private method the way the
5374 5374 * other components can. We don't want to make this method protected
5375 5375 * because it would introduce public-api for a less-than-desirable
5376 5376 * serialization scheme, so we compromise with this 'instanceof' hack
5377 5377 * for now.
5378 5378 */
5379 5379 if (getToolTipText() != null ||
5380 5380 this instanceof javax.swing.table.JTableHeader) {
5381 5381 ToolTipManager.sharedInstance().unregisterComponent(JComponent.this);
5382 5382 }
5383 5383 }
5384 5384
5385 5385 /**
5386 5386 * This object is the <code>ObjectInputStream</code> callback
5387 5387 * that's called after a complete graph of objects (including at least
5388 5388 * one <code>JComponent</code>) has been read.
5389 5389 * It sets the UI property of each Swing component
5390 5390 * that was read to the current default with <code>updateUI</code>.
5391 5391 * <p>
5392 5392 * As each component is read in we keep track of the current set of
5393 5393 * root components here, in the roots vector. Note that there's only one
5394 5394 * <code>ReadObjectCallback</code> per <code>ObjectInputStream</code>,
5395 5395 * they're stored in the static <code>readObjectCallbacks</code>
5396 5396 * hashtable.
5397 5397 *
5398 5398 * @see java.io.ObjectInputStream#registerValidation
5399 5399 * @see SwingUtilities#updateComponentTreeUI
5400 5400 */
5401 5401 private class ReadObjectCallback implements ObjectInputValidation
5402 5402 {
5403 5403 private final Vector<JComponent> roots = new Vector<JComponent>(1);
5404 5404 private final ObjectInputStream inputStream;
5405 5405
5406 5406 ReadObjectCallback(ObjectInputStream s) throws Exception {
5407 5407 inputStream = s;
5408 5408 s.registerValidation(this, 0);
5409 5409 }
5410 5410
5411 5411 /**
5412 5412 * This is the method that's called after the entire graph
5413 5413 * of objects has been read in. It initializes
5414 5414 * the UI property of all of the copmonents with
5415 5415 * <code>SwingUtilities.updateComponentTreeUI</code>.
5416 5416 */
5417 5417 public void validateObject() throws InvalidObjectException {
5418 5418 try {
5419 5419 for (JComponent root : roots) {
5420 5420 SwingUtilities.updateComponentTreeUI(root);
5421 5421 }
5422 5422 }
5423 5423 finally {
5424 5424 readObjectCallbacks.remove(inputStream);
5425 5425 }
5426 5426 }
5427 5427
5428 5428 /**
5429 5429 * If <code>c</code> isn't a descendant of a component we've already
5430 5430 * seen, then add it to the roots <code>Vector</code>.
5431 5431 *
5432 5432 * @param c the <code>JComponent</code> to add
5433 5433 */
5434 5434 private void registerComponent(JComponent c)
5435 5435 {
5436 5436 /* If the Component c is a descendant of one of the
5437 5437 * existing roots (or it IS an existing root), we're done.
5438 5438 */
5439 5439 for (JComponent root : roots) {
5440 5440 for(Component p = c; p != null; p = p.getParent()) {
5441 5441 if (p == root) {
5442 5442 return;
5443 5443 }
5444 5444 }
5445 5445 }
5446 5446
5447 5447 /* Otherwise: if Component c is an ancestor of any of the
5448 5448 * existing roots then remove them and add c (the "new root")
5449 5449 * to the roots vector.
5450 5450 */
5451 5451 for(int i = 0; i < roots.size(); i++) {
5452 5452 JComponent root = roots.elementAt(i);
5453 5453 for(Component p = root.getParent(); p != null; p = p.getParent()) {
5454 5454 if (p == c) {
5455 5455 roots.removeElementAt(i--); // !!
5456 5456 break;
5457 5457 }
5458 5458 }
5459 5459 }
5460 5460
5461 5461 roots.addElement(c);
5462 5462 }
5463 5463 }
5464 5464
5465 5465
5466 5466 /**
5467 5467 * We use the <code>ObjectInputStream</code> "registerValidation"
5468 5468 * callback to update the UI for the entire tree of components
5469 5469 * after they've all been read in.
5470 5470 *
5471 5471 * @param s the <code>ObjectInputStream</code> from which to read
5472 5472 */
5473 5473 private void readObject(ObjectInputStream s)
5474 5474 throws IOException, ClassNotFoundException
5475 5475 {
5476 5476 s.defaultReadObject();
5477 5477
5478 5478 /* If there's no ReadObjectCallback for this stream yet, that is, if
5479 5479 * this is the first call to JComponent.readObject() for this
5480 5480 * graph of objects, then create a callback and stash it
5481 5481 * in the readObjectCallbacks table. Note that the ReadObjectCallback
5482 5482 * constructor takes care of calling s.registerValidation().
5483 5483 */
5484 5484 ReadObjectCallback cb = readObjectCallbacks.get(s);
5485 5485 if (cb == null) {
5486 5486 try {
5487 5487 readObjectCallbacks.put(s, cb = new ReadObjectCallback(s));
5488 5488 }
5489 5489 catch (Exception e) {
5490 5490 throw new IOException(e.toString());
5491 5491 }
5492 5492 }
5493 5493 cb.registerComponent(this);
5494 5494
5495 5495 // Read back the client properties.
5496 5496 int cpCount = s.readInt();
5497 5497 if (cpCount > 0) {
5498 5498 clientProperties = new ArrayTable();
5499 5499 for (int counter = 0; counter < cpCount; counter++) {
5500 5500 clientProperties.put(s.readObject(),
5501 5501 s.readObject());
5502 5502 }
5503 5503 }
5504 5504 if (getToolTipText() != null) {
5505 5505 ToolTipManager.sharedInstance().registerComponent(this);
5506 5506 }
5507 5507 setWriteObjCounter(this, (byte)0);
5508 5508 revalidateRunnableScheduled = new AtomicBoolean(false);
5509 5509 }
5510 5510
5511 5511
5512 5512 /**
5513 5513 * Before writing a <code>JComponent</code> to an
5514 5514 * <code>ObjectOutputStream</code> we temporarily uninstall its UI.
5515 5515 * This is tricky to do because we want to uninstall
5516 5516 * the UI before any of the <code>JComponent</code>'s children
5517 5517 * (or its <code>LayoutManager</code> etc.) are written,
5518 5518 * and we don't want to restore the UI until the most derived
5519 5519 * <code>JComponent</code> subclass has been been stored.
5520 5520 *
5521 5521 * @param s the <code>ObjectOutputStream</code> in which to write
5522 5522 */
5523 5523 private void writeObject(ObjectOutputStream s) throws IOException {
5524 5524 s.defaultWriteObject();
5525 5525 if (getUIClassID().equals(uiClassID)) {
5526 5526 byte count = JComponent.getWriteObjCounter(this);
5527 5527 JComponent.setWriteObjCounter(this, --count);
5528 5528 if (count == 0 && ui != null) {
5529 5529 ui.installUI(this);
5530 5530 }
5531 5531 }
5532 5532 ArrayTable.writeArrayTable(s, clientProperties);
5533 5533 }
5534 5534
5535 5535
5536 5536 /**
5537 5537 * Returns a string representation of this <code>JComponent</code>.
5538 5538 * This method
5539 5539 * is intended to be used only for debugging purposes, and the
5540 5540 * content and format of the returned string may vary between
5541 5541 * implementations. The returned string may be empty but may not
5542 5542 * be <code>null</code>.
5543 5543 *
5544 5544 * @return a string representation of this <code>JComponent</code>
5545 5545 */
5546 5546 protected String paramString() {
5547 5547 String preferredSizeString = (isPreferredSizeSet() ?
5548 5548 getPreferredSize().toString() : "");
5549 5549 String minimumSizeString = (isMinimumSizeSet() ?
5550 5550 getMinimumSize().toString() : "");
5551 5551 String maximumSizeString = (isMaximumSizeSet() ?
5552 5552 getMaximumSize().toString() : "");
5553 5553 String borderString = (border == null ? ""
5554 5554 : (border == this ? "this" : border.toString()));
5555 5555
5556 5556 return super.paramString() +
5557 5557 ",alignmentX=" + alignmentX +
5558 5558 ",alignmentY=" + alignmentY +
5559 5559 ",border=" + borderString +
5560 5560 ",flags=" + flags + // should beef this up a bit
5561 5561 ",maximumSize=" + maximumSizeString +
5562 5562 ",minimumSize=" + minimumSizeString +
5563 5563 ",preferredSize=" + preferredSizeString;
5564 5564 }
5565 5565
5566 5566 /**
5567 5567 * {@inheritDoc}
5568 5568 */
5569 5569 @Override
5570 5570 @Deprecated
5571 5571 public void hide() {
5572 5572 boolean showing = isShowing();
5573 5573 super.hide();
5574 5574 if (showing) {
5575 5575 Container parent = getParent();
5576 5576 if (parent != null) {
5577 5577 Rectangle r = getBounds();
5578 5578 parent.repaint(r.x, r.y, r.width, r.height);
5579 5579 }
5580 5580 revalidate();
5581 5581 }
5582 5582 }
5583 5583
5584 5584 }
↓ open down ↓ |
2363 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX