GNU Classpath (0.19) | ||
Frames | No Frames |
1: /* BasicComboPopup.java -- 2: Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.plaf.basic; 40: 41: import java.awt.Component; 42: import java.awt.Dimension; 43: import java.awt.Insets; 44: import java.awt.Point; 45: import java.awt.Rectangle; 46: import java.awt.event.ItemEvent; 47: import java.awt.event.ItemListener; 48: import java.awt.event.KeyAdapter; 49: import java.awt.event.KeyEvent; 50: import java.awt.event.KeyListener; 51: import java.awt.event.MouseAdapter; 52: import java.awt.event.MouseEvent; 53: import java.awt.event.MouseListener; 54: import java.awt.event.MouseMotionAdapter; 55: import java.awt.event.MouseMotionListener; 56: import java.beans.PropertyChangeEvent; 57: import java.beans.PropertyChangeListener; 58: 59: import javax.swing.ComboBoxModel; 60: import javax.swing.JComboBox; 61: import javax.swing.JLabel; 62: import javax.swing.JList; 63: import javax.swing.JPopupMenu; 64: import javax.swing.JScrollBar; 65: import javax.swing.JScrollPane; 66: import javax.swing.ListCellRenderer; 67: import javax.swing.ListSelectionModel; 68: import javax.swing.SwingConstants; 69: import javax.swing.SwingUtilities; 70: import javax.swing.Timer; 71: import javax.swing.event.ListDataEvent; 72: import javax.swing.event.ListDataListener; 73: import javax.swing.event.ListSelectionEvent; 74: import javax.swing.event.ListSelectionListener; 75: import javax.swing.event.PopupMenuEvent; 76: import javax.swing.event.PopupMenuListener; 77: 78: /** 79: * UI Delegate for ComboPopup 80: * 81: * @author Olga Rodimina 82: */ 83: public class BasicComboPopup extends JPopupMenu implements ComboPopup 84: { 85: /* Timer for autoscrolling */ 86: protected Timer autoscrollTimer; 87: 88: /** ComboBox associated with this popup */ 89: protected JComboBox comboBox; 90: 91: /** FIXME: Need to document */ 92: protected boolean hasEntered; 93: 94: /** 95: * Indicates whether the scroll bar located in popup menu with comboBox's 96: * list of items is currently autoscrolling. This happens when mouse event 97: * originated in the combo box and is dragged outside of its bounds 98: */ 99: protected boolean isAutoScrolling; 100: 101: /** ItemListener listening to the selection changes in the combo box */ 102: protected ItemListener itemListener; 103: 104: /** This listener is not used */ 105: protected KeyListener keyListener; 106: 107: /** JList which is used to display item is the combo box */ 108: protected JList list; 109: 110: /** This listener is not used */ 111: protected ListDataListener listDataListener; 112: 113: /** 114: * MouseListener listening to mouse events occuring in the combo box's 115: * list. 116: */ 117: protected MouseListener listMouseListener; 118: 119: /** 120: * MouseMotionListener listening to mouse motion events occuring in the 121: * combo box's list 122: */ 123: protected MouseMotionListener listMouseMotionListener; 124: 125: /** This listener is not used */ 126: protected ListSelectionListener listSelectionListener; 127: 128: /** MouseListener listening to mouse events occuring in the combo box */ 129: protected MouseListener mouseListener; 130: 131: /** 132: * MouseMotionListener listening to mouse motion events occuring in the 133: * combo box 134: */ 135: protected MouseMotionListener mouseMotionListener; 136: 137: /** 138: * PropertyChangeListener listening to changes occuring in the bound 139: * properties of the combo box 140: */ 141: protected PropertyChangeListener propertyChangeListener; 142: 143: /** direction for scrolling down list of combo box's items */ 144: protected static final int SCROLL_DOWN = 1; 145: 146: /** direction for scrolling up list of combo box's items */ 147: protected static final int SCROLL_UP = 0; 148: 149: /** Indicates auto scrolling direction */ 150: protected int scrollDirection; 151: 152: /** JScrollPane that contains list portion of the combo box */ 153: protected JScrollPane scroller; 154: 155: /** This field is not used */ 156: protected boolean valueIsAdjusting; 157: 158: /** 159: * Creates a new BasicComboPopup object. 160: * 161: * @param comboBox the combo box with which this popup should be associated 162: */ 163: public BasicComboPopup(JComboBox comboBox) 164: { 165: this.comboBox = comboBox; 166: installComboBoxListeners(); 167: configurePopup(); 168: setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled()); 169: } 170: 171: /** 172: * This method displays drow down list of combo box items on the screen. 173: */ 174: public void show() 175: { 176: Rectangle cbBounds = comboBox.getBounds(); 177: 178: // popup should have same width as the comboBox and should be hight anough 179: // to display number of rows equal to 'maximumRowCount' property 180: int popupHeight = getPopupHeightForRowCount(comboBox.getMaximumRowCount()); 181: 182: list.setPreferredSize(new Dimension(cbBounds.width, popupHeight)); 183: Insets insets1 = getInsets(); 184: Insets insets2 = scroller.getInsets(); 185: super.setPopupSize(cbBounds.width, popupHeight + insets1.top 186: + insets1.bottom + insets2.top + insets2.bottom); 187: 188: // Highlight selected item in the combo box's drop down list 189: if (comboBox.getSelectedIndex() != -1) 190: list.setSelectedIndex(comboBox.getSelectedIndex()); 191: 192: //scroll scrollbar s.t. selected item is visible 193: JScrollBar scrollbar = scroller.getVerticalScrollBar(); 194: int selectedIndex = comboBox.getSelectedIndex(); 195: if (selectedIndex > comboBox.getMaximumRowCount()) 196: scrollbar.setValue(getPopupHeightForRowCount(selectedIndex)); 197: 198: // location specified is relative to comboBox 199: super.show(comboBox, 0, cbBounds.height); 200: } 201: 202: /** 203: * This method hides drop down list of items 204: */ 205: public void hide() 206: { 207: super.setVisible(false); 208: } 209: 210: /** 211: * Return list cointaining JComboBox's items 212: * 213: * @return list cointaining JComboBox's items 214: */ 215: public JList getList() 216: { 217: return list; 218: } 219: 220: /** 221: * Returns MouseListener that is listening to mouse events occuring in the 222: * combo box. 223: * 224: * @return MouseListener 225: */ 226: public MouseListener getMouseListener() 227: { 228: return mouseListener; 229: } 230: 231: /** 232: * Returns MouseMotionListener that is listening to mouse motion events 233: * occuring in the combo box. 234: * 235: * @return MouseMotionListener 236: */ 237: public MouseMotionListener getMouseMotionListener() 238: { 239: return mouseMotionListener; 240: } 241: 242: /** 243: * Returns KeyListener listening to key events occuring in the combo box. 244: * This method returns null because KeyHandler is not longer used. 245: * 246: * @return KeyListener 247: */ 248: public KeyListener getKeyListener() 249: { 250: return keyListener; 251: } 252: 253: /** 254: * This method uninstalls the UI for the given JComponent. 255: */ 256: public void uninstallingUI() 257: { 258: uninstallComboBoxModelListeners(comboBox.getModel()); 259: 260: uninstallListeners(); 261: uninstallKeyboardActions(); 262: } 263: 264: /** 265: * This method uninstalls listeners that were listening to changes occuring 266: * in the comb box's data model 267: * 268: * @param model data model for the combo box from which to uninstall 269: * listeners 270: */ 271: protected void uninstallComboBoxModelListeners(ComboBoxModel model) 272: { 273: model.removeListDataListener(listDataListener); 274: } 275: 276: /** 277: * This method uninstalls keyboard actions installed by the UI. 278: */ 279: protected void uninstallKeyboardActions() 280: { 281: // FIXME: Need to implement 282: } 283: 284: /** 285: * This method fires PopupMenuEvent indicating that combo box's popup list 286: * of items will become visible 287: */ 288: protected void firePopupMenuWillBecomeVisible() 289: { 290: PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); 291: 292: for (int i = 0; i < ll.length; i++) 293: ll[i].popupMenuWillBecomeVisible(new PopupMenuEvent(comboBox)); 294: } 295: 296: /** 297: * This method fires PopupMenuEvent indicating that combo box's popup list 298: * of items will become invisible. 299: */ 300: protected void firePopupMenuWillBecomeInvisible() 301: { 302: PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); 303: 304: for (int i = 0; i < ll.length; i++) 305: ll[i].popupMenuWillBecomeInvisible(new PopupMenuEvent(comboBox)); 306: } 307: 308: /** 309: * This method fires PopupMenuEvent indicating that combo box's popup list 310: * of items was closed without selection. 311: */ 312: protected void firePopupMenuCanceled() 313: { 314: PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); 315: 316: for (int i = 0; i < ll.length; i++) 317: ll[i].popupMenuCanceled(new PopupMenuEvent(comboBox)); 318: } 319: 320: /** 321: * Creates MouseListener to listen to mouse events occuring in the combo 322: * box. Note that this listener doesn't listen to mouse events occuring in 323: * the popup portion of the combo box, it only listens to main combo box 324: * part. 325: * 326: * @return new MouseMotionListener that listens to mouse events occuring in 327: * the combo box 328: */ 329: protected MouseListener createMouseListener() 330: { 331: return new InvocationMouseHandler(); 332: } 333: 334: /** 335: * Create Mouse listener that listens to mouse dragging events occuring in 336: * the combo box. This listener is responsible for changing the selection 337: * in the combo box list to the component over which mouse is being 338: * currently dragged 339: * 340: * @return new MouseMotionListener that listens to mouse dragging events 341: * occuring in the combo box 342: */ 343: protected MouseMotionListener createMouseMotionListener() 344: { 345: return new InvocationMouseMotionHandler(); 346: } 347: 348: /** 349: * KeyListener created in this method is not used anymore. 350: * 351: * @return KeyListener that does nothing 352: */ 353: protected KeyListener createKeyListener() 354: { 355: return new InvocationKeyHandler(); 356: } 357: 358: /** 359: * ListSelectionListener created in this method is not used anymore 360: * 361: * @return ListSelectionListener that does nothing 362: */ 363: protected ListSelectionListener createListSelectionListener() 364: { 365: return new ListSelectionHandler(); 366: } 367: 368: /** 369: * Creates ListDataListener. This method returns null, because 370: * ListDataHandler class is obsolete and is no longer used. 371: * 372: * @return null 373: */ 374: protected ListDataListener createListDataListener() 375: { 376: return null; 377: } 378: 379: /** 380: * This method creates ListMouseListener to listen to mouse events occuring 381: * in the combo box's item list. 382: * 383: * @return MouseListener to listen to mouse events occuring in the combo 384: * box's items list. 385: */ 386: protected MouseListener createListMouseListener() 387: { 388: return new ListMouseHandler(); 389: } 390: 391: /** 392: * Creates ListMouseMotionlistener to listen to mouse motion events occuring 393: * in the combo box's list. This listener is responsible for highlighting 394: * items in the list when mouse is moved over them. 395: * 396: * @return MouseMotionListener that handles mouse motion events occuring in 397: * the list of the combo box. 398: */ 399: protected MouseMotionListener createListMouseMotionListener() 400: { 401: return new ListMouseMotionHandler(); 402: } 403: 404: /** 405: * Creates PropertyChangeListener to handle changes in the JComboBox's bound 406: * properties. 407: * 408: * @return PropertyChangeListener to handle changes in the JComboBox's bound 409: * properties. 410: */ 411: protected PropertyChangeListener createPropertyChangeListener() 412: { 413: return new PropertyChangeHandler(); 414: } 415: 416: /** 417: * Creates new ItemListener that will listen to ItemEvents occuring in the 418: * combo box. 419: * 420: * @return ItemListener to listen to ItemEvents occuring in the combo box. 421: */ 422: protected ItemListener createItemListener() 423: { 424: return new ItemHandler(); 425: } 426: 427: /** 428: * Creates JList that will be used to display items in the combo box. 429: * 430: * @return JList that will be used to display items in the combo box. 431: */ 432: protected JList createList() 433: { 434: JList l = new JList(comboBox.getModel()); 435: l.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 436: return l; 437: } 438: 439: /** 440: * This method configures the list of comboBox's items by setting default 441: * properties and installing listeners. 442: */ 443: protected void configureList() 444: { 445: list.setModel(comboBox.getModel()); 446: list.setVisibleRowCount(comboBox.getMaximumRowCount()); 447: installListListeners(); 448: } 449: 450: /** 451: * This method installs list listeners. 452: */ 453: protected void installListListeners() 454: { 455: // mouse listener listening to mouse events occuring in the 456: // combo box's list of items. 457: listMouseListener = createListMouseListener(); 458: list.addMouseListener(listMouseListener); 459: 460: // mouse listener listening to mouse motion events occuring in the 461: // combo box's list of items 462: listMouseMotionListener = createListMouseMotionListener(); 463: list.addMouseMotionListener(listMouseMotionListener); 464: 465: listSelectionListener = createListSelectionListener(); 466: list.addListSelectionListener(listSelectionListener); 467: } 468: 469: /** 470: * This method creates scroll pane that will contain the list of comboBox's 471: * items inside of it. 472: * 473: * @return JScrollPane 474: */ 475: protected JScrollPane createScroller() 476: { 477: return new JScrollPane(); 478: } 479: 480: /** 481: * This method configures scroll pane to contain list of comboBox's items 482: */ 483: protected void configureScroller() 484: { 485: scroller.getViewport().setView(list); 486: scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 487: } 488: 489: /** 490: * This method configures popup menu that will be used to display Scrollpane 491: * with list of items inside of it. 492: */ 493: protected void configurePopup() 494: { 495: // initialize list that will be used to display combo box's items 496: this.list = createList(); 497: ((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT); 498: configureList(); 499: 500: // initialize scroller. Add list to the scroller. 501: scroller = createScroller(); 502: configureScroller(); 503: 504: // add scroller with list inside of it to JPopupMenu 505: super.add(scroller); 506: } 507: 508: /* 509: * This method installs listeners that will listen to changes occuring 510: * in the combo box. 511: */ 512: protected void installComboBoxListeners() 513: { 514: // mouse listener that listens to mouse event in combo box 515: mouseListener = createMouseListener(); 516: comboBox.addMouseListener(mouseListener); 517: 518: // mouse listener that listens to mouse dragging events in the combo box 519: mouseMotionListener = createMouseMotionListener(); 520: comboBox.addMouseMotionListener(mouseMotionListener); 521: 522: // item listener listenening to selection events in the combo box 523: itemListener = createItemListener(); 524: comboBox.addItemListener(itemListener); 525: 526: propertyChangeListener = createPropertyChangeListener(); 527: comboBox.addPropertyChangeListener(propertyChangeListener); 528: } 529: 530: /** 531: * This method installs listeners that will listen to changes occuring in 532: * the comb box's data model 533: * 534: * @param model data model for the combo box for which to install listeners 535: */ 536: protected void installComboBoxModelListeners(ComboBoxModel model) 537: { 538: // list data listener to listen for ListDataEvents in combo box. 539: // This listener is now obsolete and nothing is done here 540: listDataListener = createListDataListener(); 541: comboBox.getModel().addListDataListener(listDataListener); 542: } 543: 544: /** 545: * DOCUMENT ME! 546: */ 547: protected void installKeyboardActions() 548: { 549: // FIXME: Need to implement 550: } 551: 552: /** 553: * This method always returns false to indicate that items in the combo box 554: * list are not focus traversable. 555: * 556: * @return false 557: */ 558: public boolean isFocusTraversable() 559: { 560: return false; 561: } 562: 563: /** 564: * This method start scrolling combo box's list of items either up or down 565: * depending on the specified 'direction' 566: * 567: * @param direction of the scrolling. 568: */ 569: protected void startAutoScrolling(int direction) 570: { 571: // FIXME: add timer 572: isAutoScrolling = true; 573: 574: if (direction == SCROLL_UP) 575: autoScrollUp(); 576: else 577: autoScrollDown(); 578: } 579: 580: /** 581: * This method stops scrolling the combo box's list of items 582: */ 583: protected void stopAutoScrolling() 584: { 585: // FIXME: add timer 586: isAutoScrolling = false; 587: } 588: 589: /** 590: * This method scrolls up list of combo box's items up and highlights that 591: * just became visible. 592: */ 593: protected void autoScrollUp() 594: { 595: // scroll up the scroll bar to make the item above visible 596: JScrollBar scrollbar = scroller.getVerticalScrollBar(); 597: int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), 598: SwingConstants.VERTICAL, 599: SCROLL_UP); 600: 601: scrollbar.setValue(scrollbar.getValue() - scrollToNext); 602: 603: // If we haven't reached the begging of the combo box's list of items, 604: // then highlight next element above currently highlighted element 605: if (list.getSelectedIndex() != 0) 606: list.setSelectedIndex(list.getSelectedIndex() - 1); 607: } 608: 609: /** 610: * This method scrolls down list of combo box's and highlights item in the 611: * list that just became visible. 612: */ 613: protected void autoScrollDown() 614: { 615: // scroll scrollbar down to make next item visible 616: JScrollBar scrollbar = scroller.getVerticalScrollBar(); 617: int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), 618: SwingConstants.VERTICAL, 619: SCROLL_DOWN); 620: scrollbar.setValue(scrollbar.getValue() + scrollToNext); 621: 622: // If we haven't reached the end of the combo box's list of items 623: // then highlight next element below currently highlighted element 624: if (list.getSelectedIndex() + 1 != comboBox.getItemCount()) 625: list.setSelectedIndex(list.getSelectedIndex() + 1); 626: } 627: 628: /** 629: * This method helps to delegate focus to the right component in the 630: * JComboBox. If the comboBox is editable then focus is sent to 631: * ComboBoxEditor, otherwise it is delegated to JComboBox. 632: * 633: * @param e MouseEvent 634: */ 635: protected void delegateFocus(MouseEvent e) 636: { 637: // FIXME: Need to implement 638: } 639: 640: /** 641: * This method displays combo box popup if the popup is not currently shown 642: * on the screen and hides it if it is currently visible 643: */ 644: protected void togglePopup() 645: { 646: if (BasicComboPopup.this.isVisible()) 647: hide(); 648: else 649: show(); 650: } 651: 652: /** 653: * DOCUMENT ME! 654: * 655: * @param e DOCUMENT ME! 656: * 657: * @return DOCUMENT ME! 658: */ 659: protected MouseEvent convertMouseEvent(MouseEvent e) 660: { 661: return null; 662: } 663: 664: /** 665: * Returns required height of the popup such that number of items visible in 666: * it are equal to the maximum row count. By default 667: * comboBox.maximumRowCount=8 668: * 669: * @param maxRowCount number of maximum visible rows in the combo box's 670: * popup list of items 671: * 672: * @return height of the popup required to fit number of items equal to 673: * JComboBox.maximumRowCount. 674: */ 675: protected int getPopupHeightForRowCount(int maxRowCount) 676: { 677: int totalHeight = 0; 678: ListCellRenderer rend = list.getCellRenderer(); 679: 680: if (comboBox.getItemCount() < maxRowCount) 681: maxRowCount = comboBox.getItemCount(); 682: 683: for (int i = 0; i < maxRowCount; i++) 684: { 685: Component comp = rend.getListCellRendererComponent(list, 686: comboBox.getModel() 687: .getElementAt(i), 688: -1, false, false); 689: Dimension dim = comp.getPreferredSize(); 690: totalHeight += dim.height; 691: } 692: 693: return totalHeight; 694: } 695: 696: /** 697: * DOCUMENT ME! 698: * 699: * @param px DOCUMENT ME! 700: * @param py DOCUMENT ME! 701: * @param pw DOCUMENT ME! 702: * @param ph DOCUMENT ME! 703: * 704: * @return DOCUMENT ME! 705: */ 706: protected Rectangle computePopupBounds(int px, int py, int pw, int ph) 707: { 708: return new Rectangle(px, py, pw, ph); 709: } 710: 711: /** 712: * This method changes the selection in the list to the item over which the 713: * mouse is currently located. 714: * 715: * @param anEvent MouseEvent 716: * @param shouldScroll DOCUMENT ME! 717: */ 718: protected void updateListBoxSelectionForEvent(MouseEvent anEvent, 719: boolean shouldScroll) 720: { 721: // TODO: We need to handle the shouldScroll parameter somehow. 722: int index = list.locationToIndex(anEvent.getPoint()); 723: // Check for valid index. 724: if (index >= 0) 725: list.setSelectedIndex(index); 726: } 727: 728: /** 729: * InvocationMouseHandler is a listener that listens to mouse events 730: * occuring in the combo box. Note that this listener doesn't listen to 731: * mouse events occuring in the popup portion of the combo box, it only 732: * listens to main combo box part(area that displays selected item). This 733: * listener is responsible for showing and hiding popup portion of the 734: * combo box. 735: */ 736: protected class InvocationMouseHandler extends MouseAdapter 737: { 738: /** 739: * Creates a new InvocationMouseHandler object. 740: */ 741: protected InvocationMouseHandler() 742: { 743: // Nothing to do here. 744: } 745: 746: /** 747: * This method is invoked whenever mouse is being pressed over the main 748: * part of the combo box. This method will show popup if the popup is 749: * not shown on the screen right now, and it will hide popup otherwise. 750: * 751: * @param e MouseEvent that should be handled 752: */ 753: public void mousePressed(MouseEvent e) 754: { 755: if (comboBox.isEnabled()) 756: togglePopup(); 757: } 758: 759: /** 760: * This method is invoked whenever mouse event was originated in the combo 761: * box and released either in the combBox list of items or in the combo 762: * box itself. 763: * 764: * @param e MouseEvent that should be handled 765: */ 766: public void mouseReleased(MouseEvent e) 767: { 768: // Get component over which mouse was released 769: Component src = (Component) e.getSource(); 770: int x = e.getX(); 771: int y = e.getY(); 772: Component releasedComponent = SwingUtilities.getDeepestComponentAt(src, 773: x, y); 774: 775: // if mouse was released inside the bounds of combo box then do nothing, 776: // Otherwise if mouse was released inside the list of combo box items 777: // then change selection and close popup 778: if (! (releasedComponent instanceof JComboBox)) 779: { 780: // List model contains the item over which mouse is released, 781: // since it is updated every time the mouse is moved over a different 782: // item in the list. Now that the mouse is released we need to 783: // update model of the combo box as well. 784: comboBox.setSelectedIndex(list.getSelectedIndex()); 785: 786: if (isAutoScrolling) 787: stopAutoScrolling(); 788: hide(); 789: } 790: } 791: } 792: 793: /** 794: * InvocationMouseMotionListener is a mouse listener that listens to mouse 795: * dragging events occuring in the combo box. 796: */ 797: protected class InvocationMouseMotionHandler extends MouseMotionAdapter 798: { 799: /** 800: * Creates a new InvocationMouseMotionHandler object. 801: */ 802: protected InvocationMouseMotionHandler() 803: { 804: // Nothing to do here. 805: } 806: 807: /** 808: * This method is responsible for highlighting item in the drop down list 809: * over which the mouse is currently being dragged. 810: */ 811: public void mouseDragged(MouseEvent e) 812: { 813: // convert point of the drag event relative to combo box list component 814: // figure out over which list cell the mouse is currently being dragged 815: // and highlight the cell. The list model is changed but the change has 816: // no effect on combo box's data model. The list model is changed so 817: // that the appropriate item would be highlighted in the combo box's 818: // list. 819: if (BasicComboPopup.this.isVisible()) 820: { 821: int cbHeight = (int) comboBox.getPreferredSize().getHeight(); 822: int popupHeight = BasicComboPopup.this.getSize().height; 823: 824: // if mouse is dragged inside the the combo box's items list. 825: if (e.getY() > cbHeight && ! (e.getY() - cbHeight >= popupHeight)) 826: { 827: int index = list.locationToIndex(new Point(e.getX(), 828: (int) (e.getY() 829: - cbHeight))); 830: 831: int firstVisibleIndex = list.getFirstVisibleIndex(); 832: 833: // list.locationToIndex returns item's index that would 834: // be located at the specified point if the first item that 835: // is visible is item 0. However in the JComboBox it is not 836: // necessarily the case since list is contained in the 837: // JScrollPane so we need to adjust the index returned. 838: if (firstVisibleIndex != 0) 839: // FIXME: adjusted index here is off by one. I am adding one 840: // here to compensate for that. This should be 841: // index += firstVisibleIndex. Remove +1 once the bug is fixed. 842: index += firstVisibleIndex + 1; 843: 844: list.setSelectedIndex(index); 845: } 846: else 847: { 848: // if mouse is being dragged at the bottom of combo box's list 849: // of items or at the very top then scroll the list in the 850: // desired direction. 851: boolean movingUP = e.getY() < cbHeight; 852: boolean movingDown = e.getY() > cbHeight; 853: 854: if (movingUP) 855: { 856: scrollDirection = SCROLL_UP; 857: startAutoScrolling(SCROLL_UP); 858: } 859: else if (movingDown) 860: { 861: scrollDirection = SCROLL_DOWN; 862: startAutoScrolling(SCROLL_DOWN); 863: } 864: } 865: } 866: } 867: } 868: 869: /** 870: * ItemHandler is an item listener that listens to selection events occuring 871: * in the combo box. FIXME: should specify here what it does when item is 872: * selected or deselected in the combo box list. 873: */ 874: protected class ItemHandler extends Object implements ItemListener 875: { 876: /** 877: * Creates a new ItemHandler object. 878: */ 879: protected ItemHandler() 880: { 881: // Nothing to do here. 882: } 883: 884: /** 885: * This method responds to the selection events occuring in the combo box. 886: * 887: * @param e ItemEvent specifying the combo box's selection 888: */ 889: public void itemStateChanged(ItemEvent e) 890: { 891: // TODO: What should be done here? 892: } 893: } 894: 895: /** 896: * ListMouseHandler is a listener that listens to mouse events occuring in 897: * the combo box's list of items. This class is responsible for hiding 898: * popup portion of the combo box if the mouse is released inside the combo 899: * box's list. 900: */ 901: protected class ListMouseHandler extends MouseAdapter 902: { 903: protected ListMouseHandler() 904: { 905: // Nothing to do here. 906: } 907: 908: public void mousePressed(MouseEvent e) 909: { 910: // TODO: What should be do here? 911: } 912: 913: public void mouseReleased(MouseEvent anEvent) 914: { 915: int index = list.locationToIndex(anEvent.getPoint()); 916: // Check for valid index. 917: if (index >= 0) 918: comboBox.setSelectedIndex(index); 919: hide(); 920: } 921: } 922: 923: /** 924: * ListMouseMotionHandler listens to mouse motion events occuring in the 925: * combo box's list. This class is responsible for highlighting items in 926: * the list when mouse is moved over them 927: */ 928: protected class ListMouseMotionHandler extends MouseMotionAdapter 929: { 930: protected ListMouseMotionHandler() 931: { 932: // Nothing to do here. 933: } 934: 935: public void mouseMoved(MouseEvent anEvent) 936: { 937: updateListBoxSelectionForEvent(anEvent, false); 938: } 939: } 940: 941: /** 942: * This class listens to changes occuring in the bound properties of the 943: * combo box 944: */ 945: protected class PropertyChangeHandler extends Object 946: implements PropertyChangeListener 947: { 948: protected PropertyChangeHandler() 949: { 950: // Nothing to do here. 951: } 952: 953: public void propertyChange(PropertyChangeEvent e) 954: { 955: if (e.getPropertyName().equals("renderer")) 956: { 957: list.setCellRenderer((ListCellRenderer) e.getNewValue()); 958: revalidate(); 959: repaint(); 960: } 961: if (e.getPropertyName().equals("dataModel")) 962: { 963: list.setModel((ComboBoxModel) e.getNewValue()); 964: revalidate(); 965: repaint(); 966: } 967: } 968: } 969: 970: // ------ private helper methods -------------------- 971: 972: /** 973: * This method uninstalls listeners installed by the UI 974: */ 975: private void uninstallListeners() 976: { 977: uninstallListListeners(); 978: uninstallComboBoxListeners(); 979: uninstallComboBoxModelListeners(comboBox.getModel()); 980: } 981: 982: /** 983: * This method uninstalls Listeners registered with combo boxes list of 984: * items 985: */ 986: private void uninstallListListeners() 987: { 988: list.removeMouseListener(listMouseListener); 989: listMouseListener = null; 990: 991: list.removeMouseMotionListener(listMouseMotionListener); 992: listMouseMotionListener = null; 993: } 994: 995: /** 996: * This method uninstalls listeners listening to combo box associated with 997: * this popup menu 998: */ 999: private void uninstallComboBoxListeners() 1000: { 1001: comboBox.removeMouseListener(mouseListener); 1002: mouseListener = null; 1003: 1004: comboBox.removeMouseMotionListener(mouseMotionListener); 1005: mouseMotionListener = null; 1006: 1007: comboBox.removeItemListener(itemListener); 1008: itemListener = null; 1009: 1010: comboBox.removePropertyChangeListener(propertyChangeListener); 1011: propertyChangeListener = null; 1012: } 1013: 1014: // -------------------------------------------------------------------- 1015: // The following classes are here only for backwards API compatibility 1016: // They aren't used. 1017: // -------------------------------------------------------------------- 1018: 1019: /** 1020: * This class is not used any more. 1021: */ 1022: public class ListDataHandler extends Object implements ListDataListener 1023: { 1024: public ListDataHandler() 1025: { 1026: // Nothing to do here. 1027: } 1028: 1029: public void contentsChanged(ListDataEvent e) 1030: { 1031: // Nothing to do here. 1032: } 1033: 1034: public void intervalAdded(ListDataEvent e) 1035: { 1036: // Nothing to do here. 1037: } 1038: 1039: public void intervalRemoved(ListDataEvent e) 1040: { 1041: // Nothing to do here. 1042: } 1043: } 1044: 1045: /** 1046: * This class is not used anymore 1047: */ 1048: protected class ListSelectionHandler extends Object 1049: implements ListSelectionListener 1050: { 1051: protected ListSelectionHandler() 1052: { 1053: // Nothing to do here. 1054: } 1055: 1056: public void valueChanged(ListSelectionEvent e) 1057: { 1058: // Nothing to do here. 1059: } 1060: } 1061: 1062: /** 1063: * This class is not used anymore 1064: */ 1065: public class InvocationKeyHandler extends KeyAdapter 1066: { 1067: public InvocationKeyHandler() 1068: { 1069: // Nothing to do here. 1070: } 1071: 1072: public void keyReleased(KeyEvent e) 1073: { 1074: // Nothing to do here. 1075: } 1076: } 1077: }
GNU Classpath (0.19) |