1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62:
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78:
79:
85: public class BasicComboBoxUI extends ComboBoxUI
86: {
87:
91: protected JButton arrowButton;
92:
93:
96: protected JComboBox comboBox;
97:
98:
103: protected Component editor;
104:
105:
108: protected FocusListener focusListener;
109:
110:
113: protected boolean hasFocus;
114:
115:
118: protected ItemListener itemListener;
119:
120:
123: protected KeyListener keyListener;
124:
125:
128: private MouseListener mouseListener;
129:
130:
135: protected JList listBox;
136:
137:
140: protected ListDataListener listDataListener;
141:
142:
145: protected ComboPopup popup;
146: protected KeyListener popupKeyListener;
147: protected MouseListener popupMouseListener;
148: protected MouseMotionListener popupMouseMotionListener;
149:
150:
153: protected PropertyChangeListener propertyChangeListener;
154:
155:
158: private Color shadow;
159: private Color darkShadow;
160: private Color highlight;
161: private Color lightHighlight;
162:
163:
166: Dimension largestItemSize;
167:
168:
169:
170:
171:
173: static final Insets borderInsets = new Insets(2, 2, 2, 2);
174:
175:
176:
177:
178: static final int arrowButtonWidth = 15;
179:
180:
181: protected Dimension cachedMinimumSize;
182: protected CellRendererPane currentValuePane;
183: protected boolean isMinimumSizeDirty;
184:
185:
188: public BasicComboBoxUI()
189: {
190: }
191:
192:
200: public static ComponentUI createUI(JComponent c)
201: {
202: return new BasicComboBoxUI();
203: }
204:
205:
210: public void installUI(JComponent c)
211: {
212: super.installUI(c);
213:
214: if (c instanceof JComboBox)
215: {
216: comboBox = (JComboBox) c;
217: comboBox.setOpaque(true);
218: comboBox.setLayout(createLayoutManager());
219: installDefaults();
220: installComponents();
221: installListeners();
222: installKeyboardActions();
223: }
224: }
225:
226:
231: public void uninstallUI(JComponent c)
232: {
233: uninstallKeyboardActions();
234: uninstallListeners();
235: uninstallComponents();
236: uninstallDefaults();
237: comboBox = null;
238: }
239:
240:
244: protected void installDefaults()
245: {
246: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
247:
248: comboBox.setBackground(defaults.getColor("ComboBox.background"));
249: comboBox.setFont(defaults.getFont("ComboBox.font"));
250: comboBox.setForeground(defaults.getColor("ComboBox.foreground"));
251:
252:
253:
254: shadow = defaults.getColor("Button.shadow");
255: darkShadow = defaults.getColor("Button.darkShadow");
256: lightHighlight = defaults.getColor("Button.light");
257: highlight = defaults.getColor("Button.highlight");
258: }
259:
260:
263: protected void installListeners()
264: {
265:
266: propertyChangeListener = createPropertyChangeListener();
267: comboBox.addPropertyChangeListener(propertyChangeListener);
268:
269: focusListener = createFocusListener();
270: comboBox.addFocusListener(focusListener);
271:
272: itemListener = createItemListener();
273: comboBox.addItemListener(itemListener);
274:
275: keyListener = createKeyListener();
276: comboBox.addKeyListener(keyListener);
277:
278: mouseListener = createMouseListener();
279: comboBox.addMouseListener(mouseListener);
280:
281:
282: listDataListener = createListDataListener();
283: comboBox.getModel().addListDataListener(listDataListener);
284:
285: configureArrowButton();
286: }
287:
288:
292: protected void uninstallDefaults()
293: {
294: UIDefaults defaults = UIManager.getLookAndFeelDefaults();
295:
296: comboBox.setBackground(null);
297: comboBox.setFont(null);
298: comboBox.setForeground(null);
299:
300: shadow = null;
301: darkShadow = null;
302: lightHighlight = null;
303: highlight = null;
304: }
305:
306:
309: protected void uninstallListeners()
310: {
311: comboBox.removePropertyChangeListener(propertyChangeListener);
312: propertyChangeListener = null;
313:
314: comboBox.removeFocusListener(focusListener);
315: focusListener = null;
316:
317: comboBox.removeItemListener(itemListener);
318: itemListener = null;
319:
320: comboBox.removeKeyListener(keyListener);
321: keyListener = null;
322:
323: comboBox.removeMouseListener(mouseListener);
324: mouseListener = null;
325:
326: comboBox.getModel().removeListDataListener(listDataListener);
327: listDataListener = null;
328:
329: unconfigureArrowButton();
330: }
331:
332:
337: protected ComboPopup createPopup()
338: {
339: return new BasicComboPopup(comboBox);
340: }
341:
342:
347: protected KeyListener createKeyListener()
348: {
349: return new KeyHandler();
350: }
351:
352:
358: private MouseListener createMouseListener()
359: {
360: return new MouseHandler();
361: }
362:
363:
369: protected FocusListener createFocusListener()
370: {
371: return new FocusHandler();
372: }
373:
374:
379: protected ListDataListener createListDataListener()
380: {
381: return new ListDataHandler();
382: }
383:
384:
390: protected ItemListener createItemListener()
391: {
392: return new ItemHandler();
393: }
394:
395:
401: protected PropertyChangeListener createPropertyChangeListener()
402: {
403: return new PropertyChangeHandler();
404: }
405:
406:
411: protected LayoutManager createLayoutManager()
412: {
413: return new ComboBoxLayoutManager();
414: }
415:
416:
422: protected ListCellRenderer createRenderer()
423: {
424: return new BasicComboBoxRenderer();
425: }
426:
427:
435: protected ComboBoxEditor createEditor()
436: {
437: return new BasicComboBoxEditor();
438: }
439:
440:
445: protected void installComponents()
446: {
447:
448: arrowButton = createArrowButton();
449:
450: comboBox.add(arrowButton);
451:
452:
453:
454: listBox = new JList();
455:
456: Color background = arrowButton.getBackground();
457: listBox.setBackground(background);
458: listBox.setSelectionBackground(background.darker());
459:
460: Color foreground = arrowButton.getForeground();
461: listBox.setForeground(foreground);
462: listBox.setSelectionForeground(foreground);
463:
464:
465:
466:
467: comboBox.setRenderer(createRenderer());
468:
469: comboBox.setEditor(createEditor());
470: editor = comboBox.getEditor().getEditorComponent();
471:
472:
473: popup = createPopup();
474:
475: comboBox.revalidate();
476: }
477:
478:
481: protected void uninstallComponents()
482: {
483:
484: unconfigureArrowButton();
485: comboBox.remove(arrowButton);
486: arrowButton = null;
487:
488: listBox = null;
489: popup = null;
490:
491: comboBox.setRenderer(null);
492:
493: comboBox.setEditor(null);
494: editor = null;
495: }
496:
497:
500: public void addEditor()
501: {
502: comboBox.add(editor);
503: }
504:
505:
508: public void removeEditor()
509: {
510: comboBox.remove(editor);
511: }
512:
513:
516: protected void configureEditor()
517: {
518:
519: }
520:
521:
524: protected void unconfigureEditor()
525: {
526:
527: }
528:
529:
532: public void configureArrowButton()
533: {
534: arrowButton.addMouseListener(mouseListener);
535: }
536:
537:
541: public void unconfigureArrowButton()
542: {
543: arrowButton.removeMouseListener(mouseListener);
544: }
545:
546:
553: protected JButton createArrowButton()
554: {
555: return new BasicArrowButton(BasicArrowButton.SOUTH);
556: }
557:
558:
567: public boolean isPopupVisible(JComboBox c)
568: {
569: return popup.isVisible();
570: }
571:
572:
579: public void setPopupVisible(JComboBox c, boolean v)
580: {
581: if (v)
582: popup.show();
583: else
584: popup.hide();
585: }
586:
587:
594: public boolean isFocusTraversable(JComboBox c)
595: {
596: if (comboBox.isEditable())
597: return true;
598:
599: return false;
600: }
601:
602:
608: public void paint(Graphics g, JComponent c)
609: {
610: if (c instanceof JComboBox)
611: {
612: JComboBox cb = (JComboBox) c;
613:
614: paintBorder(g, comboBox.getBounds(), hasFocus);
615:
616: Rectangle rect = rectangleForCurrentValue();
617: paintCurrentValueBackground(g, rect, hasFocus);
618: paintCurrentValue(g, rect, hasFocus);
619: }
620: }
621:
622: private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus)
623: {
624: int x = 0;
625: int y = 0;
626: int width = bounds.width;
627: int height = bounds.height;
628:
629: Color oldColor = g.getColor();
630:
631: if (! arrowButton.getModel().isPressed())
632: BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray,
633: Color.white, Color.gray, Color.white);
634: else
635: {
636: g.setColor(darkShadow);
637: g.drawRect(x, y, width, height);
638: g.setColor(shadow);
639: g.drawRect(x + 1, y + 1, width - 3, height - 3);
640: }
641: g.setColor(oldColor);
642: }
643:
644:
651: public Dimension getPreferredSize(JComponent c)
652: {
653:
654:
655: return null;
656: }
657:
658:
666: public Dimension getMinimumSize(JComponent c)
667: {
668: return null;
669: }
670:
671:
679: public Dimension getMaximumSize(JComponent c)
680: {
681: return null;
682: }
683:
684: public int getAccessibleChildrenCount(JComponent c)
685: {
686:
687: return 0;
688: }
689:
690: public Accessible getAccessibleChild(JComponent c, int i)
691: {
692:
693: return null;
694: }
695:
696:
704: protected boolean isNavigationKey(int keyCode)
705: {
706: return false;
707: }
708:
709:
713: protected void selectNextPossibleValue()
714: {
715: int index = comboBox.getSelectedIndex();
716: if (index != comboBox.getItemCount() - 1)
717: comboBox.setSelectedIndex(index + 1);
718: }
719:
720:
724: protected void selectPreviousPossibleValue()
725: {
726: int index = comboBox.getSelectedIndex();
727: if (index != 0)
728: comboBox.setSelectedIndex(index - 1);
729: }
730:
731:
735: protected void toggleOpenClose()
736: {
737: setPopupVisible(comboBox, ! isPopupVisible(comboBox));
738: }
739:
740:
747: protected Rectangle rectangleForCurrentValue()
748: {
749: Rectangle cbBounds = comboBox.getBounds();
750:
751:
752: Rectangle rectForCurrentValue = new Rectangle(cbBounds.x
753: + borderInsets.left,
754: cbBounds.y
755: + borderInsets.top,
756: cbBounds.width
757: - arrowButtonWidth
758: - borderInsets.left
759: - borderInsets.right,
760: cbBounds.height
761: - borderInsets.top
762: - borderInsets.bottom);
763:
764: return rectForCurrentValue;
765: }
766:
767:
772: protected Insets getInsets()
773: {
774: return new Insets(0, 0, 0, 0);
775: }
776:
777:
786: public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus)
787: {
788: if (! comboBox.isEditable())
789: {
790: Object currentValue = comboBox.getSelectedItem();
791: boolean isPressed = arrowButton.getModel().isPressed();
792:
793:
797: Component comp = comboBox.getRenderer()
798: .getListCellRendererComponent(listBox,
799: (currentValue != null ? currentValue : ""),
800: -1,
801: isPressed,
802: hasFocus);
803: if (! comboBox.isEnabled())
804: comp.setEnabled(false);
805:
806: g.translate(borderInsets.left, borderInsets.top);
807: comp.setBounds(0, 0, bounds.width, bounds.height);
808: comp.paint(g);
809: g.translate(-borderInsets.left, -borderInsets.top);
810:
811: comboBox.revalidate();
812: }
813: else
814: comboBox.getEditor().setItem(comboBox.getSelectedItem());
815: }
816:
817:
827: public void paintCurrentValueBackground(Graphics g, Rectangle bounds,
828: boolean hasFocus)
829: {
830:
831:
832: }
833:
834:
840: protected Dimension getDefaultSize()
841: {
842: return new Dimension(6, 17);
843: }
844:
845:
851: protected Dimension getLargestItemSize()
852: {
853: ComboBoxModel model = comboBox.getModel();
854: int numItems = model.getSize();
855:
856:
857:
858: if (numItems == 0)
859: {
860: largestItemSize = getDefaultSize();
861: return largestItemSize;
862: }
863:
864: Dimension size = new Dimension(0, 0);
865:
866:
867:
868: ListCellRenderer renderer = comboBox.getRenderer();
869:
870: for (int i = 0; i < numItems; i++)
871: {
872: Object item = model.getElementAt(i);
873: String s = item.toString();
874: Component comp = renderer.getListCellRendererComponent(listBox, item,
875: -1, false, false);
876:
877: if (comp.getPreferredSize().getWidth() > size.getWidth())
878: size = comp.getPreferredSize();
879: }
880:
881: largestItemSize = size;
882: return largestItemSize;
883: }
884:
885:
889: protected void installKeyboardActions()
890: {
891:
892: }
893:
894:
898: protected void uninstallKeyboardActions()
899: {
900:
901: }
902:
903:
906: public class ComboBoxLayoutManager extends Object implements LayoutManager
907: {
908:
911: public ComboBoxLayoutManager()
912: {
913: }
914:
915: public void addLayoutComponent(String name, Component comp)
916: {
917:
918: }
919:
920: public void removeLayoutComponent(Component comp)
921: {
922:
923: }
924:
925:
932: public Dimension preferredLayoutSize(Container parent)
933: {
934: Dimension d = new Dimension(0, 0);
935:
936: if (largestItemSize == null)
937: largestItemSize = getLargestItemSize();
938:
939:
940: d.width += largestItemSize.getWidth();
941: d.height += largestItemSize.getHeight();
942:
943:
944: d.width += arrowButtonWidth;
945:
946:
947: d.width += borderInsets.left + borderInsets.right;
948: d.height += borderInsets.left + borderInsets.right;
949:
950:
951: Insets insets = parent.getInsets();
952: d.width += insets.left + insets.right;
953: d.width += insets.left + insets.right;
954:
955: return d;
956: }
957:
958: public Dimension minimumLayoutSize(Container parent)
959: {
960: return preferredLayoutSize(parent);
961: }
962:
963:
971: public void layoutContainer(Container parent)
972: {
973:
974:
975: int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2;
976:
977: if (comboBox.isEditable())
978: editor.setBounds(borderInsets.left, borderInsets.top, editorWidth,
979: comboBox.getBounds().height - borderInsets.left
980: - borderInsets.top);
981:
982: arrowButton.setBounds(editorWidth, 2, arrowButtonWidth,
983: comboBox.getBounds().height - 4);
984: comboBox.revalidate();
985: }
986: }
987:
988:
994: public class FocusHandler extends Object implements FocusListener
995: {
996:
999: public FocusHandler()
1000: {
1001: }
1002:
1003:
1009: public void focusGained(FocusEvent e)
1010: {
1011: hasFocus = true;
1012: comboBox.repaint();
1013: }
1014:
1015:
1021: public void focusLost(FocusEvent e)
1022: {
1023: hasFocus = false;
1024: comboBox.repaint();
1025: popup.hide();
1026: }
1027: }
1028:
1029:
1033: public class ItemHandler extends Object implements ItemListener
1034: {
1035:
1038: public ItemHandler()
1039: {
1040: }
1041:
1042:
1048: public void itemStateChanged(ItemEvent e)
1049: {
1050: comboBox.repaint();
1051: }
1052: }
1053:
1054:
1057: public class KeyHandler extends KeyAdapter
1058: {
1059: public KeyHandler()
1060: {
1061: }
1062:
1063:
1067: public void keyPressed(KeyEvent e)
1068: {
1069:
1070:
1071: }
1072: }
1073:
1074:
1077: public class ListDataHandler extends Object implements ListDataListener
1078: {
1079:
1082: public ListDataHandler()
1083: {
1084: }
1085:
1086:
1091: public void contentsChanged(ListDataEvent e)
1092: {
1093:
1094: }
1095:
1096:
1102: public void intervalAdded(ListDataEvent e)
1103: {
1104:
1105: int start = e.getIndex0();
1106: int end = e.getIndex1();
1107:
1108: ComboBoxModel model = comboBox.getModel();
1109: ListCellRenderer renderer = comboBox.getRenderer();
1110:
1111: if (largestItemSize == null)
1112: largestItemSize = new Dimension(0, 0);
1113:
1114: for (int i = start; i < end; i++)
1115: {
1116: Object item = model.getElementAt(i);
1117: Component comp = renderer.getListCellRendererComponent(new JList(),
1118: item, -1,
1119: false, false);
1120: if (comp.getPreferredSize().getWidth() > largestItemSize.getWidth())
1121: largestItemSize = comp.getPreferredSize();
1122: }
1123: }
1124:
1125:
1131: public void intervalRemoved(ListDataEvent e)
1132: {
1133:
1134: largestItemSize = getLargestItemSize();
1135: comboBox.repaint();
1136: }
1137: }
1138:
1139:
1142: public class PropertyChangeHandler extends Object
1143: implements PropertyChangeListener
1144: {
1145: public PropertyChangeHandler()
1146: {
1147: }
1148:
1149:
1152: public void propertyChange(PropertyChangeEvent e)
1153: {
1154: if (e.getPropertyName().equals("enabled"))
1155: {
1156: arrowButton.setEnabled(comboBox.isEnabled());
1157:
1158: if (comboBox.isEditable())
1159: comboBox.getEditor().getEditorComponent().setEnabled(comboBox
1160: .isEnabled());
1161: }
1162: else if (e.getPropertyName().equals("editable"))
1163: {
1164: if (comboBox.isEditable())
1165: {
1166: configureEditor();
1167: addEditor();
1168: }
1169: else
1170: {
1171: unconfigureEditor();
1172: removeEditor();
1173: }
1174:
1175: comboBox.revalidate();
1176: comboBox.repaint();
1177: }
1178: else if (e.getPropertyName().equals("dataModel"))
1179: {
1180:
1181: ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue();
1182: if (oldModel != null)
1183: oldModel.removeListDataListener(listDataListener);
1184:
1185: if ((ComboBoxModel) e.getNewValue() != null)
1186: comboBox.getModel().addListDataListener(listDataListener);
1187: }
1188:
1189:
1190: }
1191: }
1192:
1193:
1198: private class MouseHandler extends MouseAdapter
1199: {
1200:
1206: public void mousePressed(MouseEvent e)
1207: {
1208: if (comboBox.isEnabled())
1209: {
1210: if (e.getSource() instanceof JComboBox)
1211: {
1212: arrowButton.getModel().setPressed(true);
1213: arrowButton.getModel().setArmed(true);
1214: }
1215:
1216: comboBox.repaint();
1217:
1218: if (e.getSource() instanceof BasicArrowButton)
1219: toggleOpenClose();
1220: }
1221: }
1222:
1223:
1229: public void mouseReleased(MouseEvent e)
1230: {
1231: if (comboBox.isEnabled())
1232: {
1233: if (e.getSource() instanceof JComboBox)
1234: {
1235: arrowButton.getModel().setPressed(false);
1236: arrowButton.getModel().setArmed(false);
1237: }
1238:
1239: comboBox.repaint();
1240: }
1241: }
1242: }
1243: }