| 1 7 8 package javax.swing.plaf.basic; 9 10 import java.awt.*; 11 import java.awt.event.*; 12 import javax.swing.*; 13 import javax.accessibility.*; 14 import javax.swing.FocusManager ; 15 import javax.swing.plaf.*; 16 import javax.swing.border.*; 17 import javax.swing.text.*; 18 import javax.swing.event.*; 19 import java.beans.PropertyChangeListener ; 20 import java.beans.PropertyChangeEvent ; 21 import sun.awt.AppContext; 22 import sun.swing.DefaultLookup; 23 import sun.swing.UIAction; 24 25 49 public class BasicComboBoxUI extends ComboBoxUI { 50 protected JComboBox comboBox; 51 55 protected boolean hasFocus = false; 56 57 private boolean isTableCellEditor = false; 60 private static final String IS_TABLE_CELL_EDITOR = "JComboBox.isTableCellEditor"; 61 62 protected JList listBox; 64 65 protected CellRendererPane currentValuePane = new CellRendererPane(); 68 69 protected ComboPopup popup; 71 72 protected Component editor; 74 75 protected JButton arrowButton; 77 78 85 protected KeyListener keyListener; 86 92 protected FocusListener focusListener; 93 99 protected PropertyChangeListener propertyChangeListener; 100 101 107 protected ItemListener itemListener; 108 109 protected MouseListener popupMouseListener; 111 protected MouseMotionListener popupMouseMotionListener; 112 protected KeyListener popupKeyListener; 113 114 123 protected ListDataListener listDataListener; 124 125 129 private Handler handler; 130 131 135 private long timeFactor = 1000L; 136 137 141 private long lastTime = 0L; 142 private long time = 0L; 143 144 147 JComboBox.KeySelectionManager keySelectionManager; 148 149 protected boolean isMinimumSizeDirty = true; 151 152 protected Dimension cachedMinimumSize = new Dimension( 0, 0 ); 154 155 private boolean isDisplaySizeDirty = true; 157 158 private Dimension cachedDisplaySize = new Dimension( 0, 0 ); 160 161 private static final Object COMBO_UI_LIST_CELL_RENDERER_KEY = 163 new StringBuffer ("DefaultListCellRendererKey"); 164 165 static final StringBuffer HIDE_POPUP_KEY 166 = new StringBuffer ("HidePopupKey"); 167 168 private static ListCellRenderer getDefaultListCellRenderer() { 170 ListCellRenderer renderer = (ListCellRenderer)AppContext. 171 getAppContext().get(COMBO_UI_LIST_CELL_RENDERER_KEY); 172 173 if (renderer == null) { 174 renderer = new DefaultListCellRenderer(); 175 AppContext.getAppContext().put(COMBO_UI_LIST_CELL_RENDERER_KEY, 176 new DefaultListCellRenderer()); 177 } 178 return renderer; 179 } 180 181 184 static void loadActionMap(LazyActionMap map) { 185 map.put(new Actions(Actions.HIDE)); 186 map.put(new Actions(Actions.PAGE_DOWN)); 187 map.put(new Actions(Actions.PAGE_UP)); 188 map.put(new Actions(Actions.HOME)); 189 map.put(new Actions(Actions.END)); 190 map.put(new Actions(Actions.DOWN)); 191 map.put(new Actions(Actions.DOWN_2)); 192 map.put(new Actions(Actions.TOGGLE)); 193 map.put(new Actions(Actions.TOGGLE_2)); 194 map.put(new Actions(Actions.UP)); 195 map.put(new Actions(Actions.UP_2)); 196 map.put(new Actions(Actions.ENTER)); 197 } 198 199 203 public static ComponentUI createUI(JComponent c) { 204 return new BasicComboBoxUI (); 205 } 206 207 public void installUI( JComponent c ) { 208 isMinimumSizeDirty = true; 209 210 comboBox = (JComboBox)c; 211 installDefaults(); 212 popup = createPopup(); 213 listBox = popup.getList(); 214 215 Boolean inTable = (Boolean )c.getClientProperty(IS_TABLE_CELL_EDITOR ); 217 if (inTable != null) { 218 isTableCellEditor = inTable.equals(Boolean.TRUE) ? true : false; 219 } 220 221 if ( comboBox.getRenderer() == null || comboBox.getRenderer() instanceof UIResource ) { 222 comboBox.setRenderer( createRenderer() ); 223 } 224 225 if ( comboBox.getEditor() == null || comboBox.getEditor() instanceof UIResource ) { 226 comboBox.setEditor( createEditor() ); 227 } 228 229 installListeners(); 230 installComponents(); 231 232 comboBox.setLayout( createLayoutManager() ); 233 234 comboBox.setRequestFocusEnabled( true ); 235 236 installKeyboardActions(); 237 238 comboBox.putClientProperty("doNotCancelPopup", HIDE_POPUP_KEY); 239 240 if (keySelectionManager == null || keySelectionManager instanceof UIResource) { 241 keySelectionManager = new DefaultKeySelectionManager(); 242 } 243 comboBox.setKeySelectionManager(keySelectionManager); 244 } 245 246 public void uninstallUI( JComponent c ) { 247 setPopupVisible( comboBox, false); 248 popup.uninstallingUI(); 249 250 uninstallKeyboardActions(); 251 252 comboBox.setLayout( null ); 253 254 uninstallComponents(); 255 uninstallListeners(); 256 uninstallDefaults(); 257 258 if ( comboBox.getRenderer() == null || comboBox.getRenderer() instanceof UIResource ) { 259 comboBox.setRenderer( null ); 260 } 261 if ( comboBox.getEditor() == null || comboBox.getEditor() instanceof UIResource ) { 262 if(comboBox.getEditor().getEditorComponent().hasFocus()) { 263 comboBox.requestFocusInWindow(); 265 } 266 comboBox.setEditor( null ); 267 } 268 269 if (keySelectionManager instanceof UIResource) { 270 comboBox.setKeySelectionManager(null); 271 } 272 273 handler = null; 274 keyListener = null; 275 focusListener = null; 276 listDataListener = null; 277 propertyChangeListener = null; 278 popup = null; 279 listBox = null; 280 comboBox = null; 281 } 282 283 287 protected void installDefaults() { 288 LookAndFeel.installColorsAndFont( comboBox, 289 "ComboBox.background", 290 "ComboBox.foreground", 291 "ComboBox.font" ); 292 LookAndFeel.installBorder( comboBox, "ComboBox.border" ); 293 LookAndFeel.installProperty( comboBox, "opaque", Boolean.TRUE); 294 295 Long l = (Long )UIManager.get("ComboBox.timeFactor"); 296 timeFactor = (l!=null) ? l.longValue() : 1000L; 297 } 298 299 303 protected void installListeners() { 304 if ( (itemListener = createItemListener()) != null) { 305 comboBox.addItemListener( itemListener ); 306 } 307 if ( (propertyChangeListener = createPropertyChangeListener()) != null ) { 308 comboBox.addPropertyChangeListener( propertyChangeListener ); 309 } 310 if ( (keyListener = createKeyListener()) != null ) { 311 comboBox.addKeyListener( keyListener ); 312 } 313 if ( (focusListener = createFocusListener()) != null ) { 314 comboBox.addFocusListener( focusListener ); 315 } 316 if ((popupMouseListener = popup.getMouseListener()) != null) { 317 comboBox.addMouseListener( popupMouseListener ); 318 } 319 if ((popupMouseMotionListener = popup.getMouseMotionListener()) != null) { 320 comboBox.addMouseMotionListener( popupMouseMotionListener ); 321 } 322 if ((popupKeyListener = popup.getKeyListener()) != null) { 323 comboBox.addKeyListener(popupKeyListener); 324 } 325 326 if ( comboBox.getModel() != null ) { 327 if ( (listDataListener = createListDataListener()) != null ) { 328 comboBox.getModel().addListDataListener( listDataListener ); 329 } 330 } 331 } 332 333 337 protected void uninstallDefaults() { 338 LookAndFeel.installColorsAndFont( comboBox, 339 "ComboBox.background", 340 "ComboBox.foreground", 341 "ComboBox.font" ); 342 LookAndFeel.uninstallBorder( comboBox ); 343 } 344 345 350 protected void uninstallListeners() { 351 if ( keyListener != null ) { 352 comboBox.removeKeyListener( keyListener ); 353 } 354 if ( itemListener != null) { 355 comboBox.removeItemListener( itemListener ); 356 } 357 if ( propertyChangeListener != null ) { 358 comboBox.removePropertyChangeListener( propertyChangeListener ); 359 } 360 if ( focusListener != null) { 361 comboBox.removeFocusListener( focusListener ); 362 } 363 if ( popupMouseListener != null) { 364 comboBox.removeMouseListener( popupMouseListener ); 365 } 366 if ( popupMouseMotionListener != null) { 367 comboBox.removeMouseMotionListener( popupMouseMotionListener ); 368 } 369 if (popupKeyListener != null) { 370 comboBox.removeKeyListener(popupKeyListener); 371 } 372 if ( comboBox.getModel() != null ) { 373 if ( listDataListener != null ) { 374 comboBox.getModel().removeListDataListener( listDataListener ); 375 } 376 } 377 } 378 379 385 protected ComboPopup createPopup() { 386 return new BasicComboPopup ( comboBox ); 387 } 388 389 396 protected KeyListener createKeyListener() { 397 return getHandler(); 398 } 399 400 406 protected FocusListener createFocusListener() { 407 return getHandler(); 408 } 409 410 417 protected ListDataListener createListDataListener() { 418 return getHandler(); 419 } 420 421 431 protected ItemListener createItemListener() { 432 return null; 433 } 434 435 442 protected PropertyChangeListener createPropertyChangeListener() { 443 return getHandler(); 444 } 445 446 452 protected LayoutManager createLayoutManager() { 453 return getHandler(); 454 } 455 456 464 protected ListCellRenderer createRenderer() { 465 return new BasicComboBoxRenderer.UIResource (); 466 } 467 468 476 protected ComboBoxEditor createEditor() { 477 return new BasicComboBoxEditor.UIResource (); 478 } 479 480 483 private Handler getHandler() { 484 if (handler == null) { 485 handler = new Handler(); 486 } 487 return handler; 488 } 489 490 494 495 499 508 public class KeyHandler extends KeyAdapter { 509 public void keyPressed( KeyEvent e ) { 510 getHandler().keyPressed(e); 511 } 512 } 513 514 522 public class FocusHandler implements FocusListener { 523 public void focusGained( FocusEvent e ) { 524 getHandler().focusGained(e); 525 } 526 527 public void focusLost( FocusEvent e ) { 528 getHandler().focusLost(e); 529 } 530 } 531 532 542 public class ListDataHandler implements ListDataListener { 543 public void contentsChanged( ListDataEvent e ) { 544 getHandler().contentsChanged(e); 545 } 546 547 public void intervalAdded( ListDataEvent e ) { 548 getHandler().intervalAdded(e); 549 } 550 551 public void intervalRemoved( ListDataEvent e ) { 552 getHandler().intervalRemoved(e); 553 } 554 } 555 556 566 public class ItemHandler implements ItemListener { 567 public void itemStateChanged(ItemEvent e) {} 569 } 570 571 585 public class PropertyChangeHandler implements PropertyChangeListener { 586 public void propertyChange(PropertyChangeEvent e) { 587 getHandler().propertyChange(e); 588 } 589 } 590 591 592 private void updateToolTipTextForChildren() { 595 Component[] children = comboBox.getComponents(); 596 for ( int i = 0; i < children.length; ++i ) { 597 if ( children[i] instanceof JComponent ) { 598 ((JComponent)children[i]).setToolTipText( comboBox.getToolTipText() ); 599 } 600 } 601 } 602 603 612 public class ComboBoxLayoutManager implements LayoutManager { 613 public void addLayoutComponent(String name, Component comp) {} 614 615 public void removeLayoutComponent(Component comp) {} 616 617 public Dimension preferredLayoutSize(Container parent) { 618 return getHandler().preferredLayoutSize(parent); 619 } 620 621 public Dimension minimumLayoutSize(Container parent) { 622 return getHandler().minimumLayoutSize(parent); 623 } 624 625 public void layoutContainer(Container parent) { 626 getHandler().layoutContainer(parent); 627 } 628 } 629 630 634 635 639 644 protected void installComponents() { 645 arrowButton = createArrowButton(); 646 comboBox.add( arrowButton ); 647 648 if (arrowButton != null) { 649 configureArrowButton(); 650 } 651 652 if ( comboBox.isEditable() ) { 653 addEditor(); 654 } 655 656 comboBox.add( currentValuePane ); 657 } 658 659 664 protected void uninstallComponents() { 665 if ( arrowButton != null ) { 666 unconfigureArrowButton(); 667 } 668 if ( editor != null ) { 669 unconfigureEditor(); 670 } 671 comboBox.removeAll(); arrowButton = null; 673 } 674 675 684 public void addEditor() { 685 removeEditor(); 686 editor = comboBox.getEditor().getEditorComponent(); 687 if ( editor != null ) { 688 configureEditor(); 689 comboBox.add(editor); 690 if(comboBox.isFocusOwner()) { 691 editor.requestFocusInWindow(); 693 } 694 } 695 } 696 697 703 public void removeEditor() { 704 if ( editor != null ) { 705 unconfigureEditor(); 706 comboBox.remove( editor ); 707 editor = null; 708 } 709 } 710 711 717 protected void configureEditor() { 718 editor.setEnabled(comboBox.isEnabled()); 720 721 editor.setFont( comboBox.getFont() ); 722 723 if (focusListener != null) { 724 editor.addFocusListener(focusListener); 725 } 726 727 editor.addFocusListener( getHandler() ); 728 729 comboBox.getEditor().addActionListener(getHandler()); 730 731 if(editor instanceof JComponent) { 732 ((JComponent)editor).putClientProperty("doNotCancelPopup", 733 HIDE_POPUP_KEY); 734 ((JComponent)editor).setInheritsPopupMenu(true); 735 } 736 737 comboBox.configureEditor(comboBox.getEditor(),comboBox.getSelectedItem()); 738 } 739 740 746 protected void unconfigureEditor() { 747 if (focusListener != null) { 748 editor.removeFocusListener(focusListener); 749 } 750 751 editor.removeFocusListener(getHandler()); 752 comboBox.getEditor().removeActionListener(getHandler()); 753 } 754 755 761 public void configureArrowButton() { 762 if ( arrowButton != null ) { 763 arrowButton.setEnabled( comboBox.isEnabled() ); 764 arrowButton.setRequestFocusEnabled(false); 765 arrowButton.addMouseListener( popup.getMouseListener() ); 766 arrowButton.addMouseMotionListener( popup.getMouseMotionListener() ); 767 arrowButton.resetKeyboardActions(); 768 arrowButton.putClientProperty("doNotCancelPopup", HIDE_POPUP_KEY); 769 arrowButton.setInheritsPopupMenu(true); 770 } 771 } 772 773 779 public void unconfigureArrowButton() { 780 if ( arrowButton != null ) { 781 arrowButton.removeMouseListener( popup.getMouseListener() ); 782 arrowButton.removeMouseMotionListener( popup.getMouseMotionListener() ); 783 } 784 } 785 786 792 protected JButton createArrowButton() { 793 JButton button = new BasicArrowButton (BasicArrowButton.SOUTH, 794 UIManager.getColor("ComboBox.buttonBackground"), 795 UIManager.getColor("ComboBox.buttonShadow"), 796 UIManager.getColor("ComboBox.buttonDarkShadow"), 797 UIManager.getColor("ComboBox.buttonHighlight")); 798 button.setName("ComboBox.arrowButton"); 799 return button; 800 } 801 802 806 807 811 814 public boolean isPopupVisible( JComboBox c ) { 815 return popup.isVisible(); 816 } 817 818 821 public void setPopupVisible( JComboBox c, boolean v ) { 822 if ( v ) { 823 popup.show(); 824 } else { 825 popup.hide(); 826 } 827 } 828 829 833 public boolean isFocusTraversable( JComboBox c ) { 834 return !comboBox.isEditable(); 835 } 836 837 841 842 845 public void paint( Graphics g, JComponent c ) { 846 hasFocus = comboBox.hasFocus(); 847 if ( !comboBox.isEditable() ) { 848 Rectangle r = rectangleForCurrentValue(); 849 paintCurrentValueBackground(g,r,hasFocus); 850 paintCurrentValue(g,r,hasFocus); 851 } 852 } 853 854 public Dimension getPreferredSize( JComponent c ) { 855 return getMinimumSize(c); 856 } 857 858 861 public Dimension getMinimumSize( JComponent c ) { 862 if ( !isMinimumSizeDirty ) { 863 return new Dimension(cachedMinimumSize); 864 } 865 Dimension size = getDisplaySize(); 866 Insets insets = getInsets(); 867 size.height += insets.top + insets.bottom; 868 int buttonSize = size.height - (insets.top + insets.bottom); 869 size.width += insets.left + insets.right + buttonSize; 870 871 cachedMinimumSize.setSize( size.width, size.height ); 872 isMinimumSizeDirty = false; 873 874 return new Dimension(size); 875 } 876 877 public Dimension getMaximumSize( JComponent c ) { 878 return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); 879 } 880 881 public int getAccessibleChildrenCount(JComponent c) { 883 if ( comboBox.isEditable() ) { 884 return 2; 885 } 886 else { 887 return 1; 888 } 889 } 890 891 public Accessible getAccessibleChild(JComponent c, int i) { 893 switch ( i ) { 896 case 0: 897 if ( popup instanceof Accessible ) { 898 AccessibleContext ac = ((Accessible) popup).getAccessibleContext(); 899 ac.setAccessibleParent(comboBox); 900 return(Accessible) popup; 901 } 902 break; 903 case 1: 904 if ( comboBox.isEditable() 905 && (editor instanceof Accessible) ) { 906 AccessibleContext ac = ((Accessible) editor).getAccessibleContext(); 907 ac.setAccessibleParent(comboBox); 908 return(Accessible) editor; 909 } 910 break; 911 } 912 return null; 913 } 914 915 919 920 924 930 protected boolean isNavigationKey( int keyCode ) { 931 return keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN || 932 keyCode == KeyEvent.VK_KP_UP || keyCode == KeyEvent.VK_KP_DOWN; 933 } 934 935 private boolean isNavigationKey(int keyCode, int modifiers) { 936 InputMap inputMap = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 937 KeyStroke key = KeyStroke.getKeyStroke(keyCode, modifiers); 938 939 if (inputMap != null && inputMap.get(key) != null) { 940 return true; 941 } 942 return false; 943 } 944 945 949 protected void selectNextPossibleValue() { 950 int si; 951 952 if ( isTableCellEditor ) { 953 si = listBox.getSelectedIndex(); 954 } 955 else { 956 si = comboBox.getSelectedIndex(); 957 } 958 959 if ( si < comboBox.getModel().getSize() - 1 ) { 960 if ( isTableCellEditor ) { 961 listBox.setSelectedIndex( si + 1 ); 962 listBox.ensureIndexIsVisible( si + 1 ); 963 } 964 else { 965 comboBox.setSelectedIndex(si+1); 966 } 967 comboBox.repaint(); 968 } 969 } 970 971 975 protected void selectPreviousPossibleValue() { 976 int si; 977 978 if ( isTableCellEditor ) { 979 si = listBox.getSelectedIndex(); 980 } 981 else { 982 si = comboBox.getSelectedIndex(); 983 } 984 985 if ( si > 0 ) { 986 if ( isTableCellEditor ) { 987 listBox.setSelectedIndex( si - 1 ); 988 listBox.ensureIndexIsVisible( si - 1 ); 989 } 990 else { 991 comboBox.setSelectedIndex(si-1); 992 } 993 994 comboBox.repaint(); 995 } 996 } 997 998 1001 protected void toggleOpenClose() { 1002 setPopupVisible(comboBox, !isPopupVisible(comboBox)); 1003 } 1004 1005 1008 protected Rectangle rectangleForCurrentValue() { 1009 int width = comboBox.getWidth(); 1010 int height = comboBox.getHeight(); 1011 Insets insets = getInsets(); 1012 int buttonSize = height - (insets.top + insets.bottom); 1013 if ( arrowButton != null ) { 1014 buttonSize = arrowButton.getWidth(); 1015 } 1016 if(BasicGraphicsUtils.isLeftToRight(comboBox)) { 1017 return new Rectangle(insets.left, insets.top, 1018 &nbs
|