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 width - (insets.left + insets.right + buttonSize), 1019 height - (insets.top + insets.bottom)); 1020 } 1021 else { 1022 return new Rectangle(insets.left + buttonSize, insets.top, 1023 width - (insets.left + insets.right + buttonSize), 1024 height - (insets.top + insets.bottom)); 1025 } 1026 } 1027 1028 1031 protected Insets getInsets() { 1032 return comboBox.getInsets(); 1033 } 1034 1035 1039 1040 1044 1047 public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) { 1048 ListCellRenderer renderer = comboBox.getRenderer(); 1049 Component c; 1050 1051 if ( hasFocus && !isPopupVisible(comboBox) ) { 1052 c = renderer.getListCellRendererComponent( listBox, 1053 comboBox.getSelectedItem(), 1054 -1, 1055 true, 1056 false ); 1057 } 1058 else { 1059 c = renderer.getListCellRendererComponent( listBox, 1060 comboBox.getSelectedItem(), 1061 -1, 1062 false, 1063 false ); 1064 c.setBackground(UIManager.getColor("ComboBox.background")); 1065 } 1066 c.setFont(comboBox.getFont()); 1067 if ( hasFocus && !isPopupVisible(comboBox) ) { 1068 c.setForeground(listBox.getSelectionForeground()); 1069 c.setBackground(listBox.getSelectionBackground()); 1070 } 1071 else { 1072 if ( comboBox.isEnabled() ) { 1073 c.setForeground(comboBox.getForeground()); 1074 c.setBackground(comboBox.getBackground()); 1075 } 1076 else { 1077 c.setForeground(DefaultLookup.getColor( 1078 comboBox, this, "ComboBox.disabledForeground", null)); 1079 c.setBackground(DefaultLookup.getColor( 1080 comboBox, this, "ComboBox.disabledBackground", null)); 1081 } 1082 } 1083 1084 boolean shouldValidate = false; 1086 if (c instanceof JPanel) { 1087 shouldValidate = true; 1088 } 1089 1090 currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y, 1091 bounds.width,bounds.height, shouldValidate); 1092 } 1093 1094 1097 public void paintCurrentValueBackground(Graphics g,Rectangle bounds,boolean hasFocus) { 1098 Color t = g.getColor(); 1099 if ( comboBox.isEnabled() ) 1100 g.setColor(DefaultLookup.getColor(comboBox, this, 1101 "ComboBox.background", null)); 1102 else 1103 g.setColor(DefaultLookup.getColor(comboBox, this, 1104 "ComboBox.disabledBackground", null)); 1105 g.fillRect(bounds.x,bounds.y,bounds.width,bounds.height); 1106 g.setColor(t); 1107 } 1108 1109 1112 void repaintCurrentValue() { 1113 Rectangle r = rectangleForCurrentValue(); 1114 comboBox.repaint(r.x,r.y,r.width,r.height); 1115 } 1116 1117 1121 1122 1126 1133 protected Dimension getDefaultSize() { 1134 Dimension d = getSizeForComponent(getDefaultListCellRenderer().getListCellRendererComponent(listBox, " ", -1, false, false)); 1136 1137 return new Dimension(d.width, d.height); 1138 } 1139 1140 1152 protected Dimension getDisplaySize() { 1153 if (!isDisplaySizeDirty) { 1154 return new Dimension(cachedDisplaySize); 1155 } 1156 Dimension result = new Dimension(); 1157 1158 ListCellRenderer renderer = comboBox.getRenderer(); 1159 if (renderer == null) { 1160 renderer = new DefaultListCellRenderer(); 1161 } 1162 1163 Object prototypeValue = comboBox.getPrototypeDisplayValue(); 1164 if (prototypeValue != null) { 1165 result = getSizeForComponent(renderer.getListCellRendererComponent(listBox, 1167 prototypeValue, 1168 -1, false, false)); 1169 } else { 1170 ComboBoxModel model = comboBox.getModel(); 1173 int modelSize = model.getSize(); 1174 Dimension d; 1175 1176 Component cpn; 1177 1178 if (modelSize > 0 ) { 1179 for (int i = 0; i < modelSize ; i++ ) { 1180 d = getSizeForComponent(renderer.getListCellRendererComponent(listBox, 1183 model.getElementAt(i), 1184 -1, false, false)); 1185 result.width = Math.max(result.width,d.width); 1186 result.height = Math.max(result.height,d.height); 1187 1188 } 1189 } else { 1190 result = getDefaultSize(); 1191 if (comboBox.isEditable()) { 1192 result.width = 100; 1193 } 1194 } 1195 } 1196 1197 if ( comboBox.isEditable() ) { 1198 Dimension d = editor.getPreferredSize(); 1199 result.width = Math.max(result.width,d.width); 1200 result.height = Math.max(result.height,d.height); 1201 } 1202 1203 cachedDisplaySize.setSize(result.width, result.height); 1205 isDisplaySizeDirty = false; 1206 1207 return result; 1208 } 1209 1210 1216 private Dimension getSizeForComponent(Component comp) { 1217 currentValuePane.add(comp); 1218 comp.setFont(comboBox.getFont()); 1219 Dimension d = comp.getPreferredSize(); 1220 currentValuePane.remove(comp); 1221 return d; 1222 } 1223 1224 1225 1229 1230 1234 1238 protected void installKeyboardActions() { 1239 InputMap km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 1240 SwingUtilities.replaceUIInputMap(comboBox, JComponent. 1241 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km); 1242 1243 1244 LazyActionMap.installLazyActionMap(comboBox, BasicComboBoxUI .class, 1245 "ComboBox.actionMap"); 1246 } 1247 1248 InputMap getInputMap(int condition) { 1249 if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { 1250 return (InputMap)DefaultLookup.get(comboBox, this, 1251 "ComboBox.ancestorInputMap"); 1252 } 1253 return null; 1254 } 1255 1256 boolean isTableCellEditor() { 1257 return isTableCellEditor; 1258 } 1259 1260 1263 protected void uninstallKeyboardActions() { 1264 SwingUtilities.replaceUIInputMap(comboBox, JComponent. 1265 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); 1266 SwingUtilities.replaceUIActionMap(comboBox, null); 1267 } 1268 1269 1270 private static class Actions extends UIAction { 1274 private static final String HIDE = "hidePopup"; 1275 private static final String DOWN = "selectNext"; 1276 private static final String DOWN_2 = "selectNext2"; 1277 private static final String TOGGLE = "togglePopup"; 1278 private static final String TOGGLE_2 = "spacePopup"; 1279 private static final String UP = "selectPrevious"; 1280 private static final String UP_2 = "selectPrevious2"; 1281 private static final String ENTER = "enterPressed"; 1282 private static final String PAGE_DOWN = "pageDownPassThrough"; 1283 private static final String PAGE_UP = "pageUpPassThrough"; 1284 private static final String HOME = "homePassThrough"; 1285 private static final String END = "endPassThrough"; 1286 1287 Actions(String name) { 1288 super(name); 1289 } 1290 1291 public void actionPerformed( ActionEvent e ) { 1292 String key = getName(); 1293 JComboBox comboBox = (JComboBox)e.getSource(); 1294 BasicComboBoxUI ui = (BasicComboBoxUI )BasicLookAndFeel.getUIOfType( 1295 comboBox.getUI(), BasicComboBoxUI .class); 1296 if (key == HIDE) { 1297 comboBox.firePopupMenuCanceled(); 1298 comboBox.setPopupVisible(false); 1299 } 1300 else if (key == PAGE_DOWN || key == PAGE_UP || 1301 key == HOME || key == END) { 1302 int index = getNextIndex(comboBox, key); 1303 if (index >= 0 && index < comboBox.getItemCount()) { 1304 comboBox.setSelectedIndex(index); 1305 } 1306 } 1307 else if (key == DOWN) { 1308 if (comboBox.isShowing() ) { 1309 if ( comboBox.isPopupVisible() ) { 1310 if (ui != null) { 1311 ui.selectNextPossibleValue(); 1312 } 1313 } else { 1314 comboBox.setPopupVisible(true); 1315 } 1316 } 1317 } 1318 else if (key == DOWN_2) { 1319 if (comboBox.isShowing() ) { 1323 if ( (comboBox.isEditable() || 1324 (ui != null && ui.isTableCellEditor())) 1325 && !comboBox.isPopupVisible() ) { 1326 comboBox.setPopupVisible(true); 1327 } else { 1328 if (ui != null) { 1329 ui.selectNextPossibleValue(); 1330 } 1331 } 1332 } 1333 } 1334 else if (key == TOGGLE || key == TOGGLE_2) { 1335 if (ui != null && (key == TOGGLE || !comboBox.isEditable())) { 1336 if ( ui.isTableCellEditor() ) { 1337 comboBox.setSelectedIndex(ui.popup.getList(). 1340 getSelectedIndex()); 1341 } 1342 else { 1343 comboBox.setPopupVisible(!comboBox.isPopupVisible()); 1344 } 1345 } 1346 } 1347 else if (key == UP) { 1348 if (ui != null) { 1349 if (ui.isPopupVisible(comboBox)) { 1350 ui.selectPreviousPossibleValue(); 1351 } 1352 else if (DefaultLookup.getBoolean(comboBox, ui, 1353 "ComboBox.showPopupOnNavigation", false)) { 1354 ui.setPopupVisible(comboBox, true); 1355 } 1356 } 1357 } 1358 else if (key == UP_2) { 1359 if (comboBox.isShowing() && ui != null) { 1362 if ( comboBox.isEditable() && !comboBox.isPopupVisible()) { 1363 comboBox.setPopupVisible(true); 1364 } else { 1365 ui.selectPreviousPossibleValue(); 1366 } 1367 } 1368 } 1369 1370 else if (key == ENTER) { 1371 if ( ui != null && ui.isTableCellEditor() ) { 1372 comboBox.setSelectedIndex(ui.popup.getList(). 1375 getSelectedIndex()); 1376 } 1377 else { 1378 if (comboBox.isPopupVisible()) { 1379 comboBox.setPopupVisible(false); 1380 } else { 1381 JRootPane root = SwingUtilities.getRootPane(comboBox); 1385 if (root != null) { 1386 InputMap im = root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 1387 ActionMap am = root.getActionMap(); 1388 if (im != null && am != null) { 1389 Object obj = im.get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0)); 1390 if (obj != null) { 1391 Action action = am.get(obj); 1392 if (action != null) { 1393 action.actionPerformed(new ActionEvent( 1394 root, e.getID(), e.getActionCommand(), 1395 e.getWhen(), e.getModifiers())); 1396 } 1397 } 1398 } 1399 } 1400 } 1401 } 1402 } 1403 } 1404 1405 private int getNextIndex(JComboBox comboBox, String key) { 1406 if (key == PAGE_UP) { 1407 int listHeight = comboBox.getMaximumRowCount(); 1408 int index = comboBox.getSelectedIndex() - listHeight; 1409 return (index < 0 ? 0: index); 1410 } 1411 else if (key == PAGE_DOWN) { 1412 int listHeight = comboBox.getMaximumRowCount(); 1413 int index = comboBox.getSelectedIndex() + listHeight; 1414 int max = comboBox.getItemCount(); 1415 return (index < max ? index: max-1); 1416 } 1417 else if (key == HOME) { 1418 return 0; 1419 } 1420 else if (key == END) { 1421 return comboBox.getItemCount() - 1; 1422 } 1423 return comboBox.getSelectedIndex(); 1424 } 1425 1426 public boolean isEnabled(Object c) { 1427 if (getName() == HIDE) { 1428 return (c != null && ((JComboBox)c).isPopupVisible()); 1429 } 1430 return true; 1431 } 1432 } 1433 1437 1438 private class Handler implements ActionListener, FocusListener, 1442 KeyListener, LayoutManager, 1443 ListDataListener, PropertyChangeListener { 1444 public void propertyChange(PropertyChangeEvent e) { 1448 String propertyName = e.getPropertyName(); 1449 JComboBox comboBox = (JComboBox)e.getSource(); 1450 1451 if ( propertyName == "model" ) { 1452 ComboBoxModel newModel = (ComboBoxModel)e.getNewValue(); 1453 ComboBoxModel oldModel = (ComboBoxModel)e.getOldValue(); 1454 1455 if ( oldModel != null && listDataListener != null ) { 1456 oldModel.removeListDataListener( listDataListener ); 1457 } 1458 1459 if ( newModel != null && listDataListener != null ) { 1460 newModel.addListDataListener( listDataListener ); 1461 } 1462 1463 if ( editor != null ) { 1464 comboBox.configureEditor( comboBox.getEditor(), comboBox.getSelectedItem() ); 1465 } 1466 isMinimumSizeDirty = true; 1467 isDisplaySizeDirty = true; 1468 comboBox.revalidate(); 1469 comboBox.repaint(); 1470 } 1471 else if ( propertyName == "editor" && comboBox.isEditable() ) { 1472 addEditor(); 1473 comboBox.revalidate(); 1474 } 1475 else if ( propertyName == "editable" ) { 1476 if ( comboBox.isEditable() ) { 1477 comboBox.setRequestFocusEnabled( false ); 1478 addEditor(); 1479 } else { 1480 comboBox.setRequestFocusEnabled( true ); 1481 removeEditor(); 1482 } 1483 1484 updateToolTipTextForChildren(); 1485 1486 comboBox.revalidate(); 1487 } 1488 else if ( propertyName == "enabled" ) { 1489 boolean enabled = comboBox.isEnabled(); 1490 if ( editor != null ) 1491 editor.setEnabled(enabled); 1492 if ( arrowButton != null ) 1493 arrowButton.setEnabled(enabled); 1494 comboBox.repaint(); 1495 } 1496 else if ( propertyName == "maximumRowCount" ) { 1497 if ( isPopupVisible( comboBox ) ) { 1498 setPopupVisible(comboBox, false); 1499 setPopupVisible(comboBox, true); 1500 } 1501 } 1502 else if ( propertyName == "font" ) { 1503 listBox.setFont( comboBox.getFont() ); 1504 if ( editor != null ) { 1505 editor.setFont( comboBox.getFont() ); 1506 } 1507 isMinimumSizeDirty = true; 1508 comboBox.validate(); 1509 } 1510 else if ( propertyName == JComponent.TOOL_TIP_TEXT_KEY ) { 1511 updateToolTipTextForChildren(); 1512 } 1513 else if ( propertyName == BasicComboBoxUI.IS_TABLE_CELL_EDITOR ) { 1514 Boolean inTable = (Boolean )e.getNewValue(); 1515 isTableCellEditor = inTable.equals(Boolean.TRUE) ? true : false; 1516 } 1517 else if (propertyName == "prototypeDisplayValue") { 1518 isMinimumSizeDirty = true; 1519 isDisplaySizeDirty = true; 1520 comboBox.revalidate(); 1521 } 1522 else if (propertyName == "renderer") { 1523 isMinimumSizeDirty = true; 1524 isDisplaySizeDirty = true; 1525 comboBox.revalidate(); 1526 } 1527 } 1528 1529 1530 1534 public void keyPressed( KeyEvent e ) { 1539 if ( isNavigationKey(e.getKeyCode(), e.getModifiers()) ) { 1540 lastTime = 0L; 1541 } else if ( comboBox.isEnabled() && comboBox.getModel().getSize()!=0 && 1542 isTypeAheadKey( e ) ) { 1543 time = e.getWhen(); 1544 if ( comboBox.selectWithKeyChar(e.getKeyChar()) ) { 1545 e.consume(); 1546 } 1547 } 1548 } 1549 1550 public void keyTyped(KeyEvent e) { 1551 } 1552 1553 public void keyReleased(KeyEvent e) { 1554 } 1555 1556 private boolean isTypeAheadKey( KeyEvent e ) { 1557 return !e.isAltDown() && !e.isControlDown() && !e.isMetaDown(); 1558 } 1559 1560 1567 public void focusGained( FocusEvent e ) { 1568 if (e.getSource() == comboBox.getEditor().getEditorComponent()) { 1569 return; 1570 } 1571 hasFocus = true; 1572 comboBox.repaint(); 1573 1574 if (comboBox.isEditable() && editor != null) { 1575 editor.requestFocus(); 1576 } 1577 } 1578 1579 public void focusLost( FocusEvent e ) { 1580 if (e.getSource() == comboBox.getEditor().getEditorComponent()) { 1581 ComboBoxEditor editor = comboBox.getEditor(); 1582 Object item = editor.getItem(); 1583 1584 if (!e.isTemporary() && item != null && 1585 !item.equals( comboBox.getSelectedItem())) { 1586 comboBox.actionPerformed 1587 (new ActionEvent(editor, 0, "", 1588 EventQueue.getMostRecentEventTime(), 0)); 1589 } 1590 } 1591 1592 hasFocus = false; 1593 if (!e.isTemporary()) { 1594 setPopupVisible(comboBox, false); 1595 } 1596 comboBox.repaint(); 1597 } 1598 1599 1603 public void contentsChanged( ListDataEvent e ) { 1605 if ( !(e.getIndex0() == -1 && e.getIndex1() == -1) ) { 1606 isMinimumSizeDirty = true; 1607 comboBox.revalidate(); 1608 } 1609 1610 if (comboBox.isEditable() && editor != null) { 1613 comboBox.configureEditor( comboBox.getEditor(), 1614 comboBox.getSelectedItem() ); 1615 } 1616 1617 comboBox.repaint(); 1618 } 1619 1620 public void intervalAdded( ListDataEvent e ) { 1621 isDisplaySizeDirty = true; 1622 contentsChanged( e ); 1623 } 1624 1625 public void intervalRemoved( ListDataEvent e ) { 1626 isDisplaySizeDirty = true; 1627 contentsChanged( e ); 1628 } 1629 1630 1634 public void addLayoutComponent(String name, Component comp) {} 1638 1639 public void removeLayoutComponent(Component comp) {} 1640 1641 public Dimension preferredLayoutSize(Container parent) { 1642 return parent.getPreferredSize(); 1643 } 1644 1645 public Dimension minimumLayoutSize(Container parent) { 1646 return parent.getMinimumSize(); 1647 } 1648 1649 public void layoutContainer(Container parent) { 1650 JComboBox cb = (JComboBox)parent; 1651 int width = cb.getWidth(); 1652 int height = cb.getHeight(); 1653 1654 Insets insets = getInsets(); 1655 int buttonSize = height - (insets.top + insets.bottom); 1656 Rectangle cvb; 1657 1658 if ( arrowButton != null ) { 1659 if(BasicGraphicsUtils.isLeftToRight(cb)) { 1660 arrowButton.setBounds( width - (insets.right + buttonSize), 1661 insets.top, 1662 buttonSize, buttonSize); 1663 } 1664 else { 1665 arrowButton.setBounds( insets.left, insets.top, 1666 buttonSize, buttonSize); 1667 } 1668 } 1669 if ( editor != null ) { 1670 cvb = rectangleForCurrentValue(); 1671 editor.setBounds(cvb); 1672 } 1673 } 1674 1675 1676 1683 public void actionPerformed(ActionEvent evt) { 1687 Object item = comboBox.getEditor().getItem(); 1688 1689 if (item != null && item.equals(comboBox.getSelectedItem())) { 1690 ActionMap am = comboBox.getActionMap(); 1691 if (am != null) { 1692 Action action = am.get("enterPressed"); 1693 if (action != null) { 1694 action.actionPerformed(new ActionEvent(comboBox, evt.getID(), 1695 evt.getActionCommand(), 1696 evt.getModifiers())); 1697 } 1698 } 1699 } 1700 } 1701 } 1702 1703 class DefaultKeySelectionManager implements JComboBox.KeySelectionManager, UIResource { 1704 private String prefix = ""; 1705 private String typedString = ""; 1706 1707 public int selectionForKey(char aKey,ComboBoxModel aModel) { 1708 if (lastTime == 0L) { 1709 prefix = ""; 1710 typedString = ""; 1711 } 1712 boolean startingFromSelection = true; 1713 1714 int startIndex = comboBox.getSelectedIndex(); 1715 if (time - lastTime < timeFactor) { 1716 typedString += aKey; 1717 if((prefix.length() == 1) && (aKey == prefix.charAt(0))) { 1718 startIndex++; 1721 } else { 1722 prefix = typedString; 1723 } 1724 } else { 1725 startIndex++; 1726 typedString = "" + aKey; 1727 prefix = typedString; 1728 } 1729 lastTime = time; 1730 1731 if (startIndex < 0 || startIndex >= aModel.getSize()) { 1732 startingFromSelection = false; 1733 startIndex = 0; 1734 } 1735 int index = listBox.getNextMatch(prefix, startIndex, 1736 Position.Bias.Forward); 1737 if (index < 0 && startingFromSelection) { index = listBox.getNextMatch(prefix, 0, 1739 Position.Bias.Forward); 1740 } 1741 return index; 1742 } 1743 } 1744 1745} 1746 | Popular Tags |