Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/javax/swing/JMenuItem.java
+++ new/src/share/classes/javax/swing/JMenuItem.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 import java.util.EventListener;
28 28 import java.awt.*;
29 29 import java.awt.event.*;
30 30 import java.awt.image.*;
31 31
32 32 import java.beans.PropertyChangeEvent;
33 33 import java.beans.PropertyChangeListener;
34 34
35 35 import java.io.Serializable;
36 36 import java.io.ObjectOutputStream;
37 37 import java.io.ObjectInputStream;
38 38 import java.io.IOException;
39 39
40 40 import javax.swing.plaf.*;
41 41 import javax.swing.plaf.basic.*;
42 42 import javax.swing.event.*;
43 43 import javax.accessibility.*;
44 44
45 45 /**
46 46 * An implementation of an item in a menu. A menu item is essentially a button
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
47 47 * sitting in a list. When the user selects the "button", the action
48 48 * associated with the menu item is performed. A <code>JMenuItem</code>
49 49 * contained in a <code>JPopupMenu</code> performs exactly that function.
50 50 * <p>
51 51 * Menu items can be configured, and to some degree controlled, by
52 52 * <code><a href="Action.html">Action</a></code>s. Using an
53 53 * <code>Action</code> with a menu item has many benefits beyond directly
54 54 * configuring a menu item. Refer to <a href="Action.html#buttonActions">
55 55 * Swing Components Supporting <code>Action</code></a> for more
56 56 * details, and you can find more information in <a
57 - * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
57 + * href="https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html">How
58 58 * to Use Actions</a>, a section in <em>The Java Tutorial</em>.
59 59 * <p>
60 60 * For further documentation and for examples, see
61 61 * <a
62 - href="http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html">How to Use Menus</a>
62 + href="https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html">How to Use Menus</a>
63 63 * in <em>The Java Tutorial.</em>
64 64 * <p>
65 65 * <strong>Warning:</strong> Swing is not thread safe. For more
66 66 * information see <a
67 67 * href="package-summary.html#threading">Swing's Threading
68 68 * Policy</a>.
69 69 * <p>
70 70 * <strong>Warning:</strong>
71 71 * Serialized objects of this class will not be compatible with
72 72 * future Swing releases. The current serialization support is
73 73 * appropriate for short term storage or RMI between applications running
74 74 * the same version of Swing. As of 1.4, support for long term storage
75 75 * of all JavaBeans™
76 76 * has been added to the <code>java.beans</code> package.
77 77 * Please see {@link java.beans.XMLEncoder}.
78 78 *
79 79 * @beaninfo
80 80 * attribute: isContainer false
81 81 * description: An item which can be selected in a menu.
82 82 *
83 83 * @author Georges Saab
84 84 * @author David Karlton
85 85 * @see JPopupMenu
86 86 * @see JMenu
87 87 * @see JCheckBoxMenuItem
88 88 * @see JRadioButtonMenuItem
89 89 */
90 90 @SuppressWarnings("serial")
91 91 public class JMenuItem extends AbstractButton implements Accessible,MenuElement {
92 92
93 93 /**
94 94 * @see #getUIClassID
95 95 * @see #readObject
96 96 */
97 97 private static final String uiClassID = "MenuItemUI";
98 98
99 99 /* diagnostic aids -- should be false for production builds. */
100 100 private static final boolean TRACE = false; // trace creates and disposes
101 101 private static final boolean VERBOSE = false; // show reuse hits/misses
102 102 private static final boolean DEBUG = false; // show bad params, misc.
103 103
104 104 private boolean isMouseDragged = false;
105 105
106 106 /**
107 107 * Creates a <code>JMenuItem</code> with no set text or icon.
108 108 */
109 109 public JMenuItem() {
110 110 this(null, (Icon)null);
111 111 }
112 112
113 113 /**
114 114 * Creates a <code>JMenuItem</code> with the specified icon.
115 115 *
116 116 * @param icon the icon of the <code>JMenuItem</code>
117 117 */
118 118 public JMenuItem(Icon icon) {
119 119 this(null, icon);
120 120 }
121 121
122 122 /**
123 123 * Creates a <code>JMenuItem</code> with the specified text.
124 124 *
125 125 * @param text the text of the <code>JMenuItem</code>
126 126 */
127 127 public JMenuItem(String text) {
128 128 this(text, (Icon)null);
129 129 }
130 130
131 131 /**
132 132 * Creates a menu item whose properties are taken from the
133 133 * specified <code>Action</code>.
134 134 *
135 135 * @param a the action of the <code>JMenuItem</code>
136 136 * @since 1.3
137 137 */
138 138 public JMenuItem(Action a) {
139 139 this();
140 140 setAction(a);
141 141 }
142 142
143 143 /**
144 144 * Creates a <code>JMenuItem</code> with the specified text and icon.
145 145 *
146 146 * @param text the text of the <code>JMenuItem</code>
147 147 * @param icon the icon of the <code>JMenuItem</code>
148 148 */
149 149 public JMenuItem(String text, Icon icon) {
150 150 setModel(new DefaultButtonModel());
151 151 init(text, icon);
152 152 initFocusability();
153 153 }
154 154
155 155 /**
156 156 * Creates a <code>JMenuItem</code> with the specified text and
157 157 * keyboard mnemonic.
158 158 *
159 159 * @param text the text of the <code>JMenuItem</code>
160 160 * @param mnemonic the keyboard mnemonic for the <code>JMenuItem</code>
161 161 */
162 162 public JMenuItem(String text, int mnemonic) {
163 163 setModel(new DefaultButtonModel());
164 164 init(text, null);
165 165 setMnemonic(mnemonic);
166 166 initFocusability();
167 167 }
168 168
169 169 /**
170 170 * {@inheritDoc}
171 171 */
172 172 public void setModel(ButtonModel newModel) {
173 173 super.setModel(newModel);
174 174 if(newModel instanceof DefaultButtonModel) {
175 175 ((DefaultButtonModel)newModel).setMenuItem(true);
176 176 }
177 177 }
178 178
179 179 /**
180 180 * Inititalizes the focusability of the the <code>JMenuItem</code>.
181 181 * <code>JMenuItem</code>'s are focusable, but subclasses may
182 182 * want to be, this provides them the opportunity to override this
183 183 * and invoke something else, or nothing at all. Refer to
184 184 * {@link javax.swing.JMenu#initFocusability} for the motivation of
185 185 * this.
186 186 */
187 187 void initFocusability() {
188 188 setFocusable(false);
189 189 }
190 190
191 191 /**
192 192 * Initializes the menu item with the specified text and icon.
193 193 *
194 194 * @param text the text of the <code>JMenuItem</code>
195 195 * @param icon the icon of the <code>JMenuItem</code>
196 196 */
197 197 protected void init(String text, Icon icon) {
198 198 if(text != null) {
199 199 setText(text);
200 200 }
201 201
202 202 if(icon != null) {
203 203 setIcon(icon);
204 204 }
205 205
206 206 // Listen for Focus events
207 207 addFocusListener(new MenuItemFocusListener());
208 208 setUIProperty("borderPainted", Boolean.FALSE);
209 209 setFocusPainted(false);
210 210 setHorizontalTextPosition(JButton.TRAILING);
211 211 setHorizontalAlignment(JButton.LEADING);
212 212 updateUI();
213 213 }
214 214
215 215 private static class MenuItemFocusListener implements FocusListener,
216 216 Serializable {
217 217 public void focusGained(FocusEvent event) {}
218 218 public void focusLost(FocusEvent event) {
219 219 // When focus is lost, repaint if
220 220 // the focus information is painted
221 221 JMenuItem mi = (JMenuItem)event.getSource();
222 222 if(mi.isFocusPainted()) {
223 223 mi.repaint();
224 224 }
225 225 }
226 226 }
227 227
228 228
229 229 /**
230 230 * Sets the look and feel object that renders this component.
231 231 *
232 232 * @param ui the <code>JMenuItemUI</code> L&F object
233 233 * @see UIDefaults#getUI
234 234 * @beaninfo
235 235 * bound: true
236 236 * hidden: true
237 237 * attribute: visualUpdate true
238 238 * description: The UI object that implements the Component's LookAndFeel.
239 239 */
240 240 public void setUI(MenuItemUI ui) {
241 241 super.setUI(ui);
242 242 }
243 243
244 244 /**
245 245 * Resets the UI property with a value from the current look and feel.
246 246 *
247 247 * @see JComponent#updateUI
248 248 */
249 249 public void updateUI() {
250 250 setUI((MenuItemUI)UIManager.getUI(this));
251 251 }
252 252
253 253
254 254 /**
255 255 * Returns the suffix used to construct the name of the L&F class used to
256 256 * render this component.
257 257 *
258 258 * @return the string "MenuItemUI"
259 259 * @see JComponent#getUIClassID
260 260 * @see UIDefaults#getUI
261 261 */
262 262 public String getUIClassID() {
263 263 return uiClassID;
264 264 }
265 265
266 266
267 267 /**
268 268 * Identifies the menu item as "armed". If the mouse button is
269 269 * released while it is over this item, the menu's action event
270 270 * will fire. If the mouse button is released elsewhere, the
271 271 * event will not fire and the menu item will be disarmed.
272 272 *
273 273 * @param b true to arm the menu item so it can be selected
274 274 * @beaninfo
275 275 * description: Mouse release will fire an action event
276 276 * hidden: true
277 277 */
278 278 public void setArmed(boolean b) {
279 279 ButtonModel model = getModel();
280 280
281 281 boolean oldValue = model.isArmed();
282 282 if(model.isArmed() != b) {
283 283 model.setArmed(b);
284 284 }
285 285 }
286 286
287 287 /**
288 288 * Returns whether the menu item is "armed".
289 289 *
290 290 * @return true if the menu item is armed, and it can be selected
291 291 * @see #setArmed
292 292 */
293 293 public boolean isArmed() {
294 294 ButtonModel model = getModel();
295 295 return model.isArmed();
296 296 }
297 297
298 298 /**
299 299 * Enables or disables the menu item.
300 300 *
301 301 * @param b true to enable the item
302 302 * @beaninfo
303 303 * description: Does the component react to user interaction
304 304 * bound: true
305 305 * preferred: true
306 306 */
307 307 public void setEnabled(boolean b) {
308 308 // Make sure we aren't armed!
309 309 if (!b && !UIManager.getBoolean("MenuItem.disabledAreNavigable")) {
310 310 setArmed(false);
311 311 }
312 312 super.setEnabled(b);
313 313 }
314 314
315 315
316 316 /**
317 317 * Returns true since <code>Menu</code>s, by definition,
318 318 * should always be on top of all other windows. If the menu is
319 319 * in an internal frame false is returned due to the rollover effect
320 320 * for windows laf where the menu is not always on top.
321 321 */
322 322 // package private
323 323 boolean alwaysOnTop() {
324 324 // Fix for bug #4482165
325 325 if (SwingUtilities.getAncestorOfClass(JInternalFrame.class, this) !=
326 326 null) {
327 327 return false;
328 328 }
329 329 return true;
330 330 }
331 331
332 332
333 333 /* The keystroke which acts as the menu item's accelerator
334 334 */
335 335 private KeyStroke accelerator;
336 336
337 337 /**
338 338 * Sets the key combination which invokes the menu item's
339 339 * action listeners without navigating the menu hierarchy. It is the
340 340 * UI's responsibility to install the correct action. Note that
341 341 * when the keyboard accelerator is typed, it will work whether or
342 342 * not the menu is currently displayed.
343 343 *
344 344 * @param keyStroke the <code>KeyStroke</code> which will
345 345 * serve as an accelerator
346 346 * @beaninfo
347 347 * description: The keystroke combination which will invoke the
348 348 * JMenuItem's actionlisteners without navigating the
349 349 * menu hierarchy
350 350 * bound: true
351 351 * preferred: true
352 352 */
353 353 public void setAccelerator(KeyStroke keyStroke) {
354 354 KeyStroke oldAccelerator = accelerator;
355 355 this.accelerator = keyStroke;
356 356 repaint();
357 357 revalidate();
358 358 firePropertyChange("accelerator", oldAccelerator, accelerator);
359 359 }
360 360
361 361 /**
362 362 * Returns the <code>KeyStroke</code> which serves as an accelerator
363 363 * for the menu item.
364 364 * @return a <code>KeyStroke</code> object identifying the
365 365 * accelerator key
366 366 */
367 367 public KeyStroke getAccelerator() {
368 368 return this.accelerator;
369 369 }
370 370
371 371 /**
372 372 * {@inheritDoc}
373 373 *
374 374 * @since 1.3
375 375 */
376 376 protected void configurePropertiesFromAction(Action a) {
377 377 super.configurePropertiesFromAction(a);
378 378 configureAcceleratorFromAction(a);
379 379 }
380 380
381 381 void setIconFromAction(Action a) {
382 382 Icon icon = null;
383 383 if (a != null) {
384 384 icon = (Icon)a.getValue(Action.SMALL_ICON);
385 385 }
386 386 setIcon(icon);
387 387 }
388 388
389 389 void largeIconChanged(Action a) {
390 390 }
391 391
392 392 void smallIconChanged(Action a) {
393 393 setIconFromAction(a);
394 394 }
395 395
396 396 void configureAcceleratorFromAction(Action a) {
397 397 KeyStroke ks = (a==null) ? null :
398 398 (KeyStroke)a.getValue(Action.ACCELERATOR_KEY);
399 399 setAccelerator(ks);
400 400 }
401 401
402 402 /**
403 403 * {@inheritDoc}
404 404 * @since 1.6
405 405 */
406 406 protected void actionPropertyChanged(Action action, String propertyName) {
407 407 if (propertyName == Action.ACCELERATOR_KEY) {
408 408 configureAcceleratorFromAction(action);
409 409 }
410 410 else {
411 411 super.actionPropertyChanged(action, propertyName);
412 412 }
413 413 }
414 414
415 415 /**
416 416 * Processes a mouse event forwarded from the
417 417 * <code>MenuSelectionManager</code> and changes the menu
418 418 * selection, if necessary, by using the
419 419 * <code>MenuSelectionManager</code>'s API.
420 420 * <p>
421 421 * Note: you do not have to forward the event to sub-components.
422 422 * This is done automatically by the <code>MenuSelectionManager</code>.
423 423 *
424 424 * @param e a <code>MouseEvent</code>
425 425 * @param path the <code>MenuElement</code> path array
426 426 * @param manager the <code>MenuSelectionManager</code>
427 427 */
428 428 public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
429 429 processMenuDragMouseEvent(
430 430 new MenuDragMouseEvent(e.getComponent(), e.getID(),
431 431 e.getWhen(),
432 432 e.getModifiers(), e.getX(), e.getY(),
433 433 e.getXOnScreen(), e.getYOnScreen(),
434 434 e.getClickCount(), e.isPopupTrigger(),
435 435 path, manager));
436 436 }
437 437
438 438
439 439 /**
440 440 * Processes a key event forwarded from the
441 441 * <code>MenuSelectionManager</code> and changes the menu selection,
442 442 * if necessary, by using <code>MenuSelectionManager</code>'s API.
443 443 * <p>
444 444 * Note: you do not have to forward the event to sub-components.
445 445 * This is done automatically by the <code>MenuSelectionManager</code>.
446 446 *
447 447 * @param e a <code>KeyEvent</code>
448 448 * @param path the <code>MenuElement</code> path array
449 449 * @param manager the <code>MenuSelectionManager</code>
450 450 */
451 451 public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
452 452 if (DEBUG) {
453 453 System.out.println("in JMenuItem.processKeyEvent/3 for " + getText() +
454 454 " " + KeyStroke.getKeyStrokeForEvent(e));
455 455 }
456 456 MenuKeyEvent mke = new MenuKeyEvent(e.getComponent(), e.getID(),
457 457 e.getWhen(), e.getModifiers(),
458 458 e.getKeyCode(), e.getKeyChar(),
459 459 path, manager);
460 460 processMenuKeyEvent(mke);
461 461
462 462 if (mke.isConsumed()) {
463 463 e.consume();
464 464 }
465 465 }
466 466
467 467
468 468
469 469 /**
470 470 * Handles mouse drag in a menu.
471 471 *
472 472 * @param e a <code>MenuDragMouseEvent</code> object
473 473 */
474 474 public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
475 475 switch (e.getID()) {
476 476 case MouseEvent.MOUSE_ENTERED:
477 477 isMouseDragged = false; fireMenuDragMouseEntered(e); break;
478 478 case MouseEvent.MOUSE_EXITED:
479 479 isMouseDragged = false; fireMenuDragMouseExited(e); break;
480 480 case MouseEvent.MOUSE_DRAGGED:
481 481 isMouseDragged = true; fireMenuDragMouseDragged(e); break;
482 482 case MouseEvent.MOUSE_RELEASED:
483 483 if(isMouseDragged) fireMenuDragMouseReleased(e); break;
484 484 default:
485 485 break;
486 486 }
487 487 }
488 488
489 489 /**
490 490 * Handles a keystroke in a menu.
491 491 *
492 492 * @param e a <code>MenuKeyEvent</code> object
493 493 */
494 494 public void processMenuKeyEvent(MenuKeyEvent e) {
495 495 if (DEBUG) {
496 496 System.out.println("in JMenuItem.processMenuKeyEvent for " + getText()+
497 497 " " + KeyStroke.getKeyStrokeForEvent(e));
498 498 }
499 499 switch (e.getID()) {
500 500 case KeyEvent.KEY_PRESSED:
501 501 fireMenuKeyPressed(e); break;
502 502 case KeyEvent.KEY_RELEASED:
503 503 fireMenuKeyReleased(e); break;
504 504 case KeyEvent.KEY_TYPED:
505 505 fireMenuKeyTyped(e); break;
506 506 default:
507 507 break;
508 508 }
509 509 }
510 510
511 511 /**
512 512 * Notifies all listeners that have registered interest for
513 513 * notification on this event type.
514 514 *
515 515 * @param event a <code>MenuMouseDragEvent</code>
516 516 * @see EventListenerList
517 517 */
518 518 protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
519 519 // Guaranteed to return a non-null array
520 520 Object[] listeners = listenerList.getListenerList();
521 521 // Process the listeners last to first, notifying
522 522 // those that are interested in this event
523 523 for (int i = listeners.length-2; i>=0; i-=2) {
524 524 if (listeners[i]==MenuDragMouseListener.class) {
525 525 // Lazily create the event:
526 526 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
527 527 }
528 528 }
529 529 }
530 530
531 531 /**
532 532 * Notifies all listeners that have registered interest for
533 533 * notification on this event type.
534 534 *
535 535 * @param event a <code>MenuDragMouseEvent</code>
536 536 * @see EventListenerList
537 537 */
538 538 protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
539 539 // Guaranteed to return a non-null array
540 540 Object[] listeners = listenerList.getListenerList();
541 541 // Process the listeners last to first, notifying
542 542 // those that are interested in this event
543 543 for (int i = listeners.length-2; i>=0; i-=2) {
544 544 if (listeners[i]==MenuDragMouseListener.class) {
545 545 // Lazily create the event:
546 546 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
547 547 }
548 548 }
549 549 }
550 550
551 551 /**
552 552 * Notifies all listeners that have registered interest for
553 553 * notification on this event type.
554 554 *
555 555 * @param event a <code>MenuDragMouseEvent</code>
556 556 * @see EventListenerList
557 557 */
558 558 protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
559 559 // Guaranteed to return a non-null array
560 560 Object[] listeners = listenerList.getListenerList();
561 561 // Process the listeners last to first, notifying
562 562 // those that are interested in this event
563 563 for (int i = listeners.length-2; i>=0; i-=2) {
564 564 if (listeners[i]==MenuDragMouseListener.class) {
565 565 // Lazily create the event:
566 566 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
567 567 }
568 568 }
569 569 }
570 570
571 571 /**
572 572 * Notifies all listeners that have registered interest for
573 573 * notification on this event type.
574 574 *
575 575 * @param event a <code>MenuDragMouseEvent</code>
576 576 * @see EventListenerList
577 577 */
578 578 protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
579 579 // Guaranteed to return a non-null array
580 580 Object[] listeners = listenerList.getListenerList();
581 581 // Process the listeners last to first, notifying
582 582 // those that are interested in this event
583 583 for (int i = listeners.length-2; i>=0; i-=2) {
584 584 if (listeners[i]==MenuDragMouseListener.class) {
585 585 // Lazily create the event:
586 586 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
587 587 }
588 588 }
589 589 }
590 590
591 591 /**
592 592 * Notifies all listeners that have registered interest for
593 593 * notification on this event type.
594 594 *
595 595 * @param event a <code>MenuKeyEvent</code>
596 596 * @see EventListenerList
597 597 */
598 598 protected void fireMenuKeyPressed(MenuKeyEvent event) {
599 599 if (DEBUG) {
600 600 System.out.println("in JMenuItem.fireMenuKeyPressed for " + getText()+
601 601 " " + KeyStroke.getKeyStrokeForEvent(event));
602 602 }
603 603 // Guaranteed to return a non-null array
604 604 Object[] listeners = listenerList.getListenerList();
605 605 // Process the listeners last to first, notifying
606 606 // those that are interested in this event
607 607 for (int i = listeners.length-2; i>=0; i-=2) {
608 608 if (listeners[i]==MenuKeyListener.class) {
609 609 // Lazily create the event:
610 610 ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
611 611 }
612 612 }
613 613 }
614 614
615 615 /**
616 616 * Notifies all listeners that have registered interest for
617 617 * notification on this event type.
618 618 *
619 619 * @param event a <code>MenuKeyEvent</code>
620 620 * @see EventListenerList
621 621 */
622 622 protected void fireMenuKeyReleased(MenuKeyEvent event) {
623 623 if (DEBUG) {
624 624 System.out.println("in JMenuItem.fireMenuKeyReleased for " + getText()+
625 625 " " + KeyStroke.getKeyStrokeForEvent(event));
626 626 }
627 627 // Guaranteed to return a non-null array
628 628 Object[] listeners = listenerList.getListenerList();
629 629 // Process the listeners last to first, notifying
630 630 // those that are interested in this event
631 631 for (int i = listeners.length-2; i>=0; i-=2) {
632 632 if (listeners[i]==MenuKeyListener.class) {
633 633 // Lazily create the event:
634 634 ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
635 635 }
636 636 }
637 637 }
638 638
639 639 /**
640 640 * Notifies all listeners that have registered interest for
641 641 * notification on this event type.
642 642 *
643 643 * @param event a <code>MenuKeyEvent</code>
644 644 * @see EventListenerList
645 645 */
646 646 protected void fireMenuKeyTyped(MenuKeyEvent event) {
647 647 if (DEBUG) {
648 648 System.out.println("in JMenuItem.fireMenuKeyTyped for " + getText()+
649 649 " " + KeyStroke.getKeyStrokeForEvent(event));
650 650 }
651 651 // Guaranteed to return a non-null array
652 652 Object[] listeners = listenerList.getListenerList();
653 653 // Process the listeners last to first, notifying
654 654 // those that are interested in this event
655 655 for (int i = listeners.length-2; i>=0; i-=2) {
656 656 if (listeners[i]==MenuKeyListener.class) {
657 657 // Lazily create the event:
658 658 ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
659 659 }
660 660 }
661 661 }
662 662
663 663 /**
664 664 * Called by the <code>MenuSelectionManager</code> when the
665 665 * <code>MenuElement</code> is selected or unselected.
666 666 *
667 667 * @param isIncluded true if this menu item is on the part of the menu
668 668 * path that changed, false if this menu is part of the
669 669 * a menu path that changed, but this particular part of
670 670 * that path is still the same
671 671 * @see MenuSelectionManager#setSelectedPath(MenuElement[])
672 672 */
673 673 public void menuSelectionChanged(boolean isIncluded) {
674 674 setArmed(isIncluded);
675 675 }
676 676
677 677 /**
678 678 * This method returns an array containing the sub-menu
679 679 * components for this menu component.
680 680 *
681 681 * @return an array of <code>MenuElement</code>s
682 682 */
683 683 public MenuElement[] getSubElements() {
684 684 return new MenuElement[0];
685 685 }
686 686
687 687 /**
688 688 * Returns the <code>java.awt.Component</code> used to paint
689 689 * this object. The returned component will be used to convert
690 690 * events and detect if an event is inside a menu component.
691 691 *
692 692 * @return the <code>Component</code> that paints this menu item
693 693 */
694 694 public Component getComponent() {
695 695 return this;
696 696 }
697 697
698 698 /**
699 699 * Adds a <code>MenuDragMouseListener</code> to the menu item.
700 700 *
701 701 * @param l the <code>MenuDragMouseListener</code> to be added
702 702 */
703 703 public void addMenuDragMouseListener(MenuDragMouseListener l) {
704 704 listenerList.add(MenuDragMouseListener.class, l);
705 705 }
706 706
707 707 /**
708 708 * Removes a <code>MenuDragMouseListener</code> from the menu item.
709 709 *
710 710 * @param l the <code>MenuDragMouseListener</code> to be removed
711 711 */
712 712 public void removeMenuDragMouseListener(MenuDragMouseListener l) {
713 713 listenerList.remove(MenuDragMouseListener.class, l);
714 714 }
715 715
716 716 /**
717 717 * Returns an array of all the <code>MenuDragMouseListener</code>s added
718 718 * to this JMenuItem with addMenuDragMouseListener().
719 719 *
720 720 * @return all of the <code>MenuDragMouseListener</code>s added or an empty
721 721 * array if no listeners have been added
722 722 * @since 1.4
723 723 */
724 724 public MenuDragMouseListener[] getMenuDragMouseListeners() {
725 725 return listenerList.getListeners(MenuDragMouseListener.class);
726 726 }
727 727
728 728 /**
729 729 * Adds a <code>MenuKeyListener</code> to the menu item.
730 730 *
731 731 * @param l the <code>MenuKeyListener</code> to be added
732 732 */
733 733 public void addMenuKeyListener(MenuKeyListener l) {
734 734 listenerList.add(MenuKeyListener.class, l);
735 735 }
736 736
737 737 /**
738 738 * Removes a <code>MenuKeyListener</code> from the menu item.
739 739 *
740 740 * @param l the <code>MenuKeyListener</code> to be removed
741 741 */
742 742 public void removeMenuKeyListener(MenuKeyListener l) {
743 743 listenerList.remove(MenuKeyListener.class, l);
744 744 }
745 745
746 746 /**
747 747 * Returns an array of all the <code>MenuKeyListener</code>s added
748 748 * to this JMenuItem with addMenuKeyListener().
749 749 *
750 750 * @return all of the <code>MenuKeyListener</code>s added or an empty
751 751 * array if no listeners have been added
752 752 * @since 1.4
753 753 */
754 754 public MenuKeyListener[] getMenuKeyListeners() {
755 755 return listenerList.getListeners(MenuKeyListener.class);
756 756 }
757 757
758 758 /**
759 759 * See JComponent.readObject() for information about serialization
760 760 * in Swing.
761 761 */
762 762 private void readObject(ObjectInputStream s)
763 763 throws IOException, ClassNotFoundException
764 764 {
765 765 s.defaultReadObject();
766 766 if (getUIClassID().equals(uiClassID)) {
767 767 updateUI();
768 768 }
769 769 }
770 770
771 771 private void writeObject(ObjectOutputStream s) throws IOException {
772 772 s.defaultWriteObject();
773 773 if (getUIClassID().equals(uiClassID)) {
774 774 byte count = JComponent.getWriteObjCounter(this);
775 775 JComponent.setWriteObjCounter(this, --count);
776 776 if (count == 0 && ui != null) {
777 777 ui.installUI(this);
778 778 }
779 779 }
780 780 }
781 781
782 782
783 783 /**
784 784 * Returns a string representation of this <code>JMenuItem</code>.
785 785 * This method is intended to be used only for debugging purposes,
786 786 * and the content and format of the returned string may vary between
787 787 * implementations. The returned string may be empty but may not
788 788 * be <code>null</code>.
789 789 *
790 790 * @return a string representation of this <code>JMenuItem</code>
791 791 */
792 792 protected String paramString() {
793 793 return super.paramString();
794 794 }
795 795
796 796 /////////////////
797 797 // Accessibility support
798 798 ////////////////
799 799
800 800 /**
801 801 * Returns the <code>AccessibleContext</code> associated with this
802 802 * <code>JMenuItem</code>. For <code>JMenuItem</code>s,
803 803 * the <code>AccessibleContext</code> takes the form of an
804 804 * <code>AccessibleJMenuItem</code>.
805 805 * A new AccessibleJMenuItme instance is created if necessary.
806 806 *
807 807 * @return an <code>AccessibleJMenuItem</code> that serves as the
808 808 * <code>AccessibleContext</code> of this <code>JMenuItem</code>
809 809 */
810 810 public AccessibleContext getAccessibleContext() {
811 811 if (accessibleContext == null) {
812 812 accessibleContext = new AccessibleJMenuItem();
813 813 }
814 814 return accessibleContext;
815 815 }
816 816
817 817
818 818 /**
819 819 * This class implements accessibility support for the
820 820 * <code>JMenuItem</code> class. It provides an implementation of the
821 821 * Java Accessibility API appropriate to menu item user-interface
822 822 * elements.
823 823 * <p>
824 824 * <strong>Warning:</strong>
825 825 * Serialized objects of this class will not be compatible with
826 826 * future Swing releases. The current serialization support is
827 827 * appropriate for short term storage or RMI between applications running
828 828 * the same version of Swing. As of 1.4, support for long term storage
829 829 * of all JavaBeans™
830 830 * has been added to the <code>java.beans</code> package.
831 831 * Please see {@link java.beans.XMLEncoder}.
832 832 */
833 833 @SuppressWarnings("serial")
834 834 protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
835 835
836 836 private boolean isArmed = false;
837 837 private boolean hasFocus = false;
838 838 private boolean isPressed = false;
839 839 private boolean isSelected = false;
840 840
841 841 AccessibleJMenuItem() {
842 842 super();
843 843 JMenuItem.this.addChangeListener(this);
844 844 }
845 845
846 846 /**
847 847 * Get the role of this object.
848 848 *
849 849 * @return an instance of AccessibleRole describing the role of the
850 850 * object
851 851 */
852 852 public AccessibleRole getAccessibleRole() {
853 853 return AccessibleRole.MENU_ITEM;
854 854 }
855 855
856 856 private void fireAccessibilityFocusedEvent(JMenuItem toCheck) {
857 857 MenuElement [] path =
858 858 MenuSelectionManager.defaultManager().getSelectedPath();
859 859 if (path.length > 0) {
860 860 Object menuItem = path[path.length - 1];
861 861 if (toCheck == menuItem) {
862 862 firePropertyChange(
863 863 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
864 864 null, AccessibleState.FOCUSED);
865 865 }
866 866 }
867 867 }
868 868
869 869 /**
870 870 * Supports the change listener interface and fires property changes.
871 871 */
872 872 public void stateChanged(ChangeEvent e) {
873 873 firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
874 874 Boolean.valueOf(false), Boolean.valueOf(true));
875 875 if (JMenuItem.this.getModel().isArmed()) {
876 876 if (!isArmed) {
877 877 isArmed = true;
878 878 firePropertyChange(
879 879 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
880 880 null, AccessibleState.ARMED);
881 881 // Fix for 4848220 moved here to avoid major memory leak
882 882 // Here we will fire the event in case of JMenuItem
883 883 // See bug 4910323 for details [zav]
884 884 fireAccessibilityFocusedEvent(JMenuItem.this);
885 885 }
886 886 } else {
887 887 if (isArmed) {
888 888 isArmed = false;
889 889 firePropertyChange(
890 890 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
891 891 AccessibleState.ARMED, null);
892 892 }
893 893 }
894 894 if (JMenuItem.this.isFocusOwner()) {
895 895 if (!hasFocus) {
896 896 hasFocus = true;
897 897 firePropertyChange(
898 898 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
899 899 null, AccessibleState.FOCUSED);
900 900 }
901 901 } else {
902 902 if (hasFocus) {
903 903 hasFocus = false;
904 904 firePropertyChange(
905 905 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
906 906 AccessibleState.FOCUSED, null);
907 907 }
908 908 }
909 909 if (JMenuItem.this.getModel().isPressed()) {
910 910 if (!isPressed) {
911 911 isPressed = true;
912 912 firePropertyChange(
913 913 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
914 914 null, AccessibleState.PRESSED);
915 915 }
916 916 } else {
917 917 if (isPressed) {
918 918 isPressed = false;
919 919 firePropertyChange(
920 920 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
921 921 AccessibleState.PRESSED, null);
922 922 }
923 923 }
924 924 if (JMenuItem.this.getModel().isSelected()) {
925 925 if (!isSelected) {
926 926 isSelected = true;
927 927 firePropertyChange(
928 928 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
929 929 null, AccessibleState.CHECKED);
930 930
931 931 // Fix for 4848220 moved here to avoid major memory leak
932 932 // Here we will fire the event in case of JMenu
933 933 // See bug 4910323 for details [zav]
934 934 fireAccessibilityFocusedEvent(JMenuItem.this);
935 935 }
936 936 } else {
937 937 if (isSelected) {
938 938 isSelected = false;
939 939 firePropertyChange(
940 940 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
941 941 AccessibleState.CHECKED, null);
942 942 }
943 943 }
944 944
945 945 }
946 946 } // inner class AccessibleJMenuItem
947 947
948 948
949 949 }
↓ open down ↓ |
877 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX