21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.swing.plaf.basic;
27
28 import javax.accessibility.AccessibleContext;
29 import javax.swing.*;
30 import javax.swing.border.Border;
31 import javax.swing.border.LineBorder;
32 import javax.swing.event.*;
33 import java.awt.*;
34 import java.awt.event.*;
35 import java.beans.PropertyChangeListener;
36 import java.beans.PropertyChangeEvent;
37 import java.io.Serializable;
38
39
40 /**
41 * This is a basic implementation of the <code>ComboPopup</code> interface.
42 *
43 * This class represents the ui for the popup portion of the combo box.
44 * <p>
45 * All event handling is handled by listener classes created with the
46 * <code>createxxxListener()</code> methods and internal classes.
47 * You can change the behavior of this class by overriding the
48 * <code>createxxxListener()</code> methods and supplying your own
49 * event listeners or subclassing from the ones supplied in this class.
50 * <p>
51 * <strong>Warning:</strong>
52 * Serialized objects of this class will not be compatible with
53 * future Swing releases. The current serialization support is
54 * appropriate for short term storage or RMI between applications running
55 * the same version of Swing. As of 1.4, support for long term storage
56 * of all JavaBeans™
57 * has been added to the <code>java.beans</code> package.
58 * Please see {@link java.beans.XMLEncoder}.
59 *
60 * @author Tom Santos
61 * @author Mark Davidson
62 */
63 @SuppressWarnings("serial") // Same-version serialization only
64 public class BasicComboPopup extends JPopupMenu implements ComboPopup {
65 // An empty ListMode, this is used when the UI changes to allow
66 // the JList to be gc'ed.
67 private static class EmptyListModelClass implements ListModel<Object>, Serializable {
68 public int getSize() { return 0; }
69 public Object getElementAt(int index) { return null; }
70 public void addListDataListener(ListDataListener l) {}
71 public void removeListDataListener(ListDataListener l) {}
72 };
73
74 static final ListModel<Object> EmptyListModel = new EmptyListModelClass();
75
76 private static Border LIST_BORDER = new LineBorder(Color.BLACK, 1);
77
245 if ( selection[i] == this ) {
246 manager.clearSelectedPath();
247 break;
248 }
249 }
250 if (selection.length > 0) {
251 comboBox.repaint();
252 }
253 }
254
255 /**
256 * Implementation of ComboPopup.getList().
257 */
258 public JList<Object> getList() {
259 return list;
260 }
261
262 /**
263 * Implementation of ComboPopup.getMouseListener().
264 *
265 * @return a <code>MouseListener</code> or null
266 * @see ComboPopup#getMouseListener
267 */
268 public MouseListener getMouseListener() {
269 if (mouseListener == null) {
270 mouseListener = createMouseListener();
271 }
272 return mouseListener;
273 }
274
275 /**
276 * Implementation of ComboPopup.getMouseMotionListener().
277 *
278 * @return a <code>MouseMotionListener</code> or null
279 * @see ComboPopup#getMouseMotionListener
280 */
281 public MouseMotionListener getMouseMotionListener() {
282 if (mouseMotionListener == null) {
283 mouseMotionListener = createMouseMotionListener();
284 }
285 return mouseMotionListener;
286 }
287
288 /**
289 * Implementation of ComboPopup.getKeyListener().
290 *
291 * @return a <code>KeyListener</code> or null
292 * @see ComboPopup#getKeyListener
293 */
294 public KeyListener getKeyListener() {
295 if (keyListener == null) {
296 keyListener = createKeyListener();
297 }
298 return keyListener;
299 }
300
301 /**
302 * Called when the UI is uninstalling. Since this popup isn't in the component
303 * tree, it won't get it's uninstallUI() called. It removes the listeners that
304 * were added in addComboBoxListeners().
305 */
306 public void uninstallingUI() {
307 if (propertyChangeListener != null) {
308 comboBox.removePropertyChangeListener( propertyChangeListener );
309 }
310 if (itemListener != null) {
311 comboBox.removeItemListener( itemListener );
385 }
386
387 protected void firePopupMenuWillBecomeInvisible() {
388 super.firePopupMenuWillBecomeInvisible();
389 comboBox.firePopupMenuWillBecomeInvisible();
390 }
391
392 protected void firePopupMenuCanceled() {
393 super.firePopupMenuCanceled();
394 comboBox.firePopupMenuCanceled();
395 }
396
397 /**
398 * Creates a listener
399 * that will watch for mouse-press and release events on the combo box.
400 *
401 * <strong>Warning:</strong>
402 * When overriding this method, make sure to maintain the existing
403 * behavior.
404 *
405 * @return a <code>MouseListener</code> which will be added to
406 * the combo box or null
407 */
408 protected MouseListener createMouseListener() {
409 return getHandler();
410 }
411
412 /**
413 * Creates the mouse motion listener which will be added to the combo
414 * box.
415 *
416 * <strong>Warning:</strong>
417 * When overriding this method, make sure to maintain the existing
418 * behavior.
419 *
420 * @return a <code>MouseMotionListener</code> which will be added to
421 * the combo box or null
422 */
423 protected MouseMotionListener createMouseMotionListener() {
424 return getHandler();
425 }
426
427 /**
428 * Creates the key listener that will be added to the combo box. If
429 * this method returns null then it will not be added to the combo box.
430 *
431 * @return a <code>KeyListener</code> or null
432 */
433 protected KeyListener createKeyListener() {
434 return null;
435 }
436
437 /**
438 * Creates a list selection listener that watches for selection changes in
439 * the popup's list. If this method returns null then it will not
440 * be added to the popup list.
441 *
442 * @return an instance of a <code>ListSelectionListener</code> or null
443 */
444 protected ListSelectionListener createListSelectionListener() {
445 return null;
446 }
447
448 /**
449 * Creates a list data listener which will be added to the
450 * <code>ComboBoxModel</code>. If this method returns null then
451 * it will not be added to the combo box model.
452 *
453 * @return an instance of a <code>ListDataListener</code> or null
454 */
455 protected ListDataListener createListDataListener() {
456 return null;
457 }
458
459 /**
460 * Creates a mouse listener that watches for mouse events in
461 * the popup's list. If this method returns null then it will
462 * not be added to the combo box.
463 *
464 * @return an instance of a <code>MouseListener</code> or null
465 */
466 protected MouseListener createListMouseListener() {
467 return getHandler();
468 }
469
470 /**
471 * Creates a mouse motion listener that watches for mouse motion
472 * events in the popup's list. If this method returns null then it will
473 * not be added to the combo box.
474 *
475 * @return an instance of a <code>MouseMotionListener</code> or null
476 */
477 protected MouseMotionListener createListMouseMotionListener() {
478 return getHandler();
479 }
480
481 /**
482 * Creates a <code>PropertyChangeListener</code> which will be added to
483 * the combo box. If this method returns null then it will not
484 * be added to the combo box.
485 *
486 * @return an instance of a <code>PropertyChangeListener</code> or null
487 */
488 protected PropertyChangeListener createPropertyChangeListener() {
489 return getHandler();
490 }
491
492 /**
493 * Creates an <code>ItemListener</code> which will be added to the
494 * combo box. If this method returns null then it will not
495 * be added to the combo box.
496 * <p>
497 * Subclasses may override this method to return instances of their own
498 * ItemEvent handlers.
499 *
500 * @return an instance of an <code>ItemListener</code> or null
501 */
502 protected ItemListener createItemListener() {
503 return getHandler();
504 }
505
506 private Handler getHandler() {
507 if (handler == null) {
508 handler = new Handler();
509 }
510 return handler;
511 }
512
513 /**
514 * Creates the JList used in the popup to display
515 * the items in the combo box model. This method is called when the UI class
516 * is created.
517 *
518 * @return a <code>JList</code> used to display the combo box items
519 */
520 protected JList<Object> createList() {
521 return new JList<Object>( comboBox.getModel() ) {
522 public void processMouseEvent(MouseEvent e) {
523 if (BasicGraphicsUtils.isMenuShortcutKeyDown(e)) {
524 // Fix for 4234053. Filter out the Control Key from the list.
525 // ie., don't allow CTRL key deselection.
526 Toolkit toolkit = Toolkit.getDefaultToolkit();
527 e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(),
528 e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(),
529 e.getX(), e.getY(),
530 e.getXOnScreen(), e.getYOnScreen(),
531 e.getClickCount(),
532 e.isPopupTrigger(),
533 MouseEvent.NOBUTTON);
534 }
535 super.processMouseEvent(e);
536 }
537 };
538 }
641 scrollerMouseWheelListener = null;
642 }
643 }
644
645 /**
646 * This method adds the necessary listeners to the JComboBox.
647 */
648 protected void installComboBoxListeners() {
649 if ((propertyChangeListener = createPropertyChangeListener()) != null) {
650 comboBox.addPropertyChangeListener(propertyChangeListener);
651 }
652 if ((itemListener = createItemListener()) != null) {
653 comboBox.addItemListener(itemListener);
654 }
655 installComboBoxModelListeners(comboBox.getModel());
656 }
657
658 /**
659 * Installs the listeners on the combo box model. Any listeners installed
660 * on the combo box model should be removed in
661 * <code>uninstallComboBoxModelListeners</code>.
662 *
663 * @param model The combo box model to install listeners
664 * @see #uninstallComboBoxModelListeners
665 */
666 protected void installComboBoxModelListeners( ComboBoxModel<?> model ) {
667 if (model != null && (listDataListener = createListDataListener()) != null) {
668 model.addListDataListener(listDataListener);
669 }
670 }
671
672 /**
673 * Registers keyboard actions.
674 */
675 protected void installKeyboardActions() {
676
677 /* XXX - shouldn't call this method. take it out for testing.
678 ActionListener action = new ActionListener() {
679 public void actionPerformed(ActionEvent e){
680 }
681 };
755 * BasicComboBoxUI ActionMap/InputMap methods.
756 */
757 public class InvocationKeyHandler extends KeyAdapter {
758 public void keyReleased( KeyEvent e ) {}
759 }
760
761 /**
762 * As of Java 2 platform v 1.4, this class is now obsolete, doesn't do anything, and
763 * is only included for backwards API compatibility. Do not call or
764 * override.
765 */
766 protected class ListSelectionHandler implements ListSelectionListener {
767 public void valueChanged( ListSelectionEvent e ) {}
768 }
769
770 /**
771 * As of 1.4, this class is now obsolete, doesn't do anything, and
772 * is only included for backwards API compatibility. Do not call or
773 * override.
774 * <p>
775 * The functionality has been migrated into <code>ItemHandler</code>.
776 *
777 * @see #createItemListener
778 */
779 public class ListDataHandler implements ListDataListener {
780 public void contentsChanged( ListDataEvent e ) {}
781
782 public void intervalAdded( ListDataEvent e ) {
783 }
784
785 public void intervalRemoved( ListDataEvent e ) {
786 }
787 }
788
789 /**
790 * This listener hides the popup when the mouse is released in the list.
791 */
792 protected class ListMouseHandler extends MouseAdapter {
793 public void mousePressed( MouseEvent e ) {
794 }
795 public void mouseReleased(MouseEvent anEvent) {
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.swing.plaf.basic;
27
28 import javax.accessibility.AccessibleContext;
29 import javax.swing.*;
30 import javax.swing.border.Border;
31 import javax.swing.border.LineBorder;
32 import javax.swing.event.*;
33 import java.awt.*;
34 import java.awt.event.*;
35 import java.beans.PropertyChangeListener;
36 import java.beans.PropertyChangeEvent;
37 import java.io.Serializable;
38
39
40 /**
41 * This is a basic implementation of the {@code ComboPopup} interface.
42 *
43 * This class represents the ui for the popup portion of the combo box.
44 * <p>
45 * All event handling is handled by listener classes created with the
46 * {@code createxxxListener()} methods and internal classes.
47 * You can change the behavior of this class by overriding the
48 * {@code createxxxListener()} methods and supplying your own
49 * event listeners or subclassing from the ones supplied in this class.
50 * <p>
51 * <strong>Warning:</strong>
52 * Serialized objects of this class will not be compatible with
53 * future Swing releases. The current serialization support is
54 * appropriate for short term storage or RMI between applications running
55 * the same version of Swing. As of 1.4, support for long term storage
56 * of all JavaBeans™
57 * has been added to the {@code java.beans} package.
58 * Please see {@link java.beans.XMLEncoder}.
59 *
60 * @author Tom Santos
61 * @author Mark Davidson
62 */
63 @SuppressWarnings("serial") // Same-version serialization only
64 public class BasicComboPopup extends JPopupMenu implements ComboPopup {
65 // An empty ListMode, this is used when the UI changes to allow
66 // the JList to be gc'ed.
67 private static class EmptyListModelClass implements ListModel<Object>, Serializable {
68 public int getSize() { return 0; }
69 public Object getElementAt(int index) { return null; }
70 public void addListDataListener(ListDataListener l) {}
71 public void removeListDataListener(ListDataListener l) {}
72 };
73
74 static final ListModel<Object> EmptyListModel = new EmptyListModelClass();
75
76 private static Border LIST_BORDER = new LineBorder(Color.BLACK, 1);
77
245 if ( selection[i] == this ) {
246 manager.clearSelectedPath();
247 break;
248 }
249 }
250 if (selection.length > 0) {
251 comboBox.repaint();
252 }
253 }
254
255 /**
256 * Implementation of ComboPopup.getList().
257 */
258 public JList<Object> getList() {
259 return list;
260 }
261
262 /**
263 * Implementation of ComboPopup.getMouseListener().
264 *
265 * @return a {@code MouseListener} or null
266 * @see ComboPopup#getMouseListener
267 */
268 public MouseListener getMouseListener() {
269 if (mouseListener == null) {
270 mouseListener = createMouseListener();
271 }
272 return mouseListener;
273 }
274
275 /**
276 * Implementation of ComboPopup.getMouseMotionListener().
277 *
278 * @return a {@code MouseMotionListener} or null
279 * @see ComboPopup#getMouseMotionListener
280 */
281 public MouseMotionListener getMouseMotionListener() {
282 if (mouseMotionListener == null) {
283 mouseMotionListener = createMouseMotionListener();
284 }
285 return mouseMotionListener;
286 }
287
288 /**
289 * Implementation of ComboPopup.getKeyListener().
290 *
291 * @return a {@code KeyListener} or null
292 * @see ComboPopup#getKeyListener
293 */
294 public KeyListener getKeyListener() {
295 if (keyListener == null) {
296 keyListener = createKeyListener();
297 }
298 return keyListener;
299 }
300
301 /**
302 * Called when the UI is uninstalling. Since this popup isn't in the component
303 * tree, it won't get it's uninstallUI() called. It removes the listeners that
304 * were added in addComboBoxListeners().
305 */
306 public void uninstallingUI() {
307 if (propertyChangeListener != null) {
308 comboBox.removePropertyChangeListener( propertyChangeListener );
309 }
310 if (itemListener != null) {
311 comboBox.removeItemListener( itemListener );
385 }
386
387 protected void firePopupMenuWillBecomeInvisible() {
388 super.firePopupMenuWillBecomeInvisible();
389 comboBox.firePopupMenuWillBecomeInvisible();
390 }
391
392 protected void firePopupMenuCanceled() {
393 super.firePopupMenuCanceled();
394 comboBox.firePopupMenuCanceled();
395 }
396
397 /**
398 * Creates a listener
399 * that will watch for mouse-press and release events on the combo box.
400 *
401 * <strong>Warning:</strong>
402 * When overriding this method, make sure to maintain the existing
403 * behavior.
404 *
405 * @return a {@code MouseListener} which will be added to
406 * the combo box or null
407 */
408 protected MouseListener createMouseListener() {
409 return getHandler();
410 }
411
412 /**
413 * Creates the mouse motion listener which will be added to the combo
414 * box.
415 *
416 * <strong>Warning:</strong>
417 * When overriding this method, make sure to maintain the existing
418 * behavior.
419 *
420 * @return a {@code MouseMotionListener} which will be added to
421 * the combo box or null
422 */
423 protected MouseMotionListener createMouseMotionListener() {
424 return getHandler();
425 }
426
427 /**
428 * Creates the key listener that will be added to the combo box. If
429 * this method returns null then it will not be added to the combo box.
430 *
431 * @return a {@code KeyListener} or null
432 */
433 protected KeyListener createKeyListener() {
434 return null;
435 }
436
437 /**
438 * Creates a list selection listener that watches for selection changes in
439 * the popup's list. If this method returns null then it will not
440 * be added to the popup list.
441 *
442 * @return an instance of a {@code ListSelectionListener} or null
443 */
444 protected ListSelectionListener createListSelectionListener() {
445 return null;
446 }
447
448 /**
449 * Creates a list data listener which will be added to the
450 * {@code ComboBoxModel}. If this method returns null then
451 * it will not be added to the combo box model.
452 *
453 * @return an instance of a {@code ListDataListener} or null
454 */
455 protected ListDataListener createListDataListener() {
456 return null;
457 }
458
459 /**
460 * Creates a mouse listener that watches for mouse events in
461 * the popup's list. If this method returns null then it will
462 * not be added to the combo box.
463 *
464 * @return an instance of a {@code MouseListener} or null
465 */
466 protected MouseListener createListMouseListener() {
467 return getHandler();
468 }
469
470 /**
471 * Creates a mouse motion listener that watches for mouse motion
472 * events in the popup's list. If this method returns null then it will
473 * not be added to the combo box.
474 *
475 * @return an instance of a {@code MouseMotionListener} or null
476 */
477 protected MouseMotionListener createListMouseMotionListener() {
478 return getHandler();
479 }
480
481 /**
482 * Creates a {@code PropertyChangeListener} which will be added to
483 * the combo box. If this method returns null then it will not
484 * be added to the combo box.
485 *
486 * @return an instance of a {@code PropertyChangeListener} or null
487 */
488 protected PropertyChangeListener createPropertyChangeListener() {
489 return getHandler();
490 }
491
492 /**
493 * Creates an {@code ItemListener} which will be added to the
494 * combo box. If this method returns null then it will not
495 * be added to the combo box.
496 * <p>
497 * Subclasses may override this method to return instances of their own
498 * ItemEvent handlers.
499 *
500 * @return an instance of an {@code ItemListener} or null
501 */
502 protected ItemListener createItemListener() {
503 return getHandler();
504 }
505
506 private Handler getHandler() {
507 if (handler == null) {
508 handler = new Handler();
509 }
510 return handler;
511 }
512
513 /**
514 * Creates the JList used in the popup to display
515 * the items in the combo box model. This method is called when the UI class
516 * is created.
517 *
518 * @return a {@code JList} used to display the combo box items
519 */
520 protected JList<Object> createList() {
521 return new JList<Object>( comboBox.getModel() ) {
522 public void processMouseEvent(MouseEvent e) {
523 if (BasicGraphicsUtils.isMenuShortcutKeyDown(e)) {
524 // Fix for 4234053. Filter out the Control Key from the list.
525 // ie., don't allow CTRL key deselection.
526 Toolkit toolkit = Toolkit.getDefaultToolkit();
527 e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(),
528 e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(),
529 e.getX(), e.getY(),
530 e.getXOnScreen(), e.getYOnScreen(),
531 e.getClickCount(),
532 e.isPopupTrigger(),
533 MouseEvent.NOBUTTON);
534 }
535 super.processMouseEvent(e);
536 }
537 };
538 }
641 scrollerMouseWheelListener = null;
642 }
643 }
644
645 /**
646 * This method adds the necessary listeners to the JComboBox.
647 */
648 protected void installComboBoxListeners() {
649 if ((propertyChangeListener = createPropertyChangeListener()) != null) {
650 comboBox.addPropertyChangeListener(propertyChangeListener);
651 }
652 if ((itemListener = createItemListener()) != null) {
653 comboBox.addItemListener(itemListener);
654 }
655 installComboBoxModelListeners(comboBox.getModel());
656 }
657
658 /**
659 * Installs the listeners on the combo box model. Any listeners installed
660 * on the combo box model should be removed in
661 * {@code uninstallComboBoxModelListeners}.
662 *
663 * @param model The combo box model to install listeners
664 * @see #uninstallComboBoxModelListeners
665 */
666 protected void installComboBoxModelListeners( ComboBoxModel<?> model ) {
667 if (model != null && (listDataListener = createListDataListener()) != null) {
668 model.addListDataListener(listDataListener);
669 }
670 }
671
672 /**
673 * Registers keyboard actions.
674 */
675 protected void installKeyboardActions() {
676
677 /* XXX - shouldn't call this method. take it out for testing.
678 ActionListener action = new ActionListener() {
679 public void actionPerformed(ActionEvent e){
680 }
681 };
755 * BasicComboBoxUI ActionMap/InputMap methods.
756 */
757 public class InvocationKeyHandler extends KeyAdapter {
758 public void keyReleased( KeyEvent e ) {}
759 }
760
761 /**
762 * As of Java 2 platform v 1.4, this class is now obsolete, doesn't do anything, and
763 * is only included for backwards API compatibility. Do not call or
764 * override.
765 */
766 protected class ListSelectionHandler implements ListSelectionListener {
767 public void valueChanged( ListSelectionEvent e ) {}
768 }
769
770 /**
771 * As of 1.4, this class is now obsolete, doesn't do anything, and
772 * is only included for backwards API compatibility. Do not call or
773 * override.
774 * <p>
775 * The functionality has been migrated into {@code ItemHandler}.
776 *
777 * @see #createItemListener
778 */
779 public class ListDataHandler implements ListDataListener {
780 public void contentsChanged( ListDataEvent e ) {}
781
782 public void intervalAdded( ListDataEvent e ) {
783 }
784
785 public void intervalRemoved( ListDataEvent e ) {
786 }
787 }
788
789 /**
790 * This listener hides the popup when the mouse is released in the list.
791 */
792 protected class ListMouseHandler extends MouseAdapter {
793 public void mousePressed( MouseEvent e ) {
794 }
795 public void mouseReleased(MouseEvent anEvent) {
|