1:
37:
38:
39: package ;
40:
41: import ;
42:
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: import ;
63:
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: import ;
79: import ;
80: import ;
81:
82:
88: public class BasicComboBoxUI extends ComboBoxUI
89: {
90:
94: protected JButton arrowButton;
95:
96:
99: protected JComboBox comboBox;
100:
101:
107: protected Component editor;
108:
109:
112: protected FocusListener focusListener;
113:
114:
117: protected boolean hasFocus;
118:
119:
122: protected ItemListener itemListener;
123:
124:
128: protected KeyListener keyListener;
129:
130:
135: protected JList listBox;
136:
137:
140: protected ListDataListener listDataListener;
141:
142:
145: protected ComboPopup popup;
146:
147: protected KeyListener popupKeyListener;
148:
149: protected MouseListener popupMouseListener;
150:
151: protected MouseMotionListener popupMouseMotionListener;
152:
153:
156: protected PropertyChangeListener propertyChangeListener;
157:
158:
161: Dimension displaySize = new Dimension();
162:
163:
166: protected CellRendererPane currentValuePane;
167:
168:
172: protected Dimension cachedMinimumSize;
173:
174:
177: protected boolean isMinimumSizeDirty = true;
178:
179:
182: public BasicComboBoxUI()
183: {
184: currentValuePane = new CellRendererPane();
185: cachedMinimumSize = new Dimension();
186: }
187:
188:
196: public static ComponentUI createUI(JComponent c)
197: {
198: return new BasicComboBoxUI();
199: }
200:
201:
208: public void installUI(JComponent c)
209: {
210: super.installUI(c);
211:
212: if (c instanceof JComboBox)
213: {
214: isMinimumSizeDirty = true;
215: comboBox = (JComboBox) c;
216: installDefaults();
217:
218:
219:
220:
221: ListCellRenderer renderer = comboBox.getRenderer();
222: if (renderer == null || renderer instanceof UIResource)
223: comboBox.setRenderer(createRenderer());
224:
225: ComboBoxEditor currentEditor = comboBox.getEditor();
226: if (currentEditor == null || currentEditor instanceof UIResource)
227: {
228: currentEditor = createEditor();
229: comboBox.setEditor(currentEditor);
230: }
231: editor = currentEditor.getEditorComponent();
232:
233: installComponents();
234: installListeners();
235: if (arrowButton != null)
236: configureArrowButton();
237: if (editor != null)
238: configureEditor();
239: comboBox.setLayout(createLayoutManager());
240: comboBox.setFocusable(true);
241: installKeyboardActions();
242: }
243: }
244:
245:
252: public void uninstallUI(JComponent c)
253: {
254: setPopupVisible(comboBox, false);
255: popup.uninstallingUI();
256: uninstallKeyboardActions();
257: comboBox.setLayout(null);
258: uninstallComponents();
259: uninstallListeners();
260: uninstallDefaults();
261: comboBox = null;
262: }
263:
264:
270: protected void installDefaults()
271: {
272: LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background",
273: "ComboBox.foreground", "ComboBox.font");
274: LookAndFeel.installBorder(comboBox, "ComboBox.border");
275: }
276:
277:
282: protected void installListeners()
283: {
284:
285: propertyChangeListener = createPropertyChangeListener();
286: comboBox.addPropertyChangeListener(propertyChangeListener);
287:
288: focusListener = createFocusListener();
289: editor.addFocusListener(focusListener);
290:
291: itemListener = createItemListener();
292: comboBox.addItemListener(itemListener);
293:
294: keyListener = createKeyListener();
295: comboBox.addKeyListener(keyListener);
296:
297:
298: listDataListener = createListDataListener();
299: comboBox.getModel().addListDataListener(listDataListener);
300:
301:
302: popupMouseListener = popup.getMouseListener();
303: comboBox.addMouseListener(popupMouseListener);
304:
305: popupMouseMotionListener = popup.getMouseMotionListener();
306: comboBox.addMouseMotionListener(popupMouseMotionListener);
307:
308: popupKeyListener = popup.getKeyListener();
309: comboBox.addKeyListener(popupKeyListener);
310: }
311:
312:
318: protected void uninstallDefaults()
319: {
320: if (comboBox.getFont() instanceof UIResource)
321: comboBox.setFont(null);
322:
323: if (comboBox.getForeground() instanceof UIResource)
324: comboBox.setForeground(null);
325:
326: if (comboBox.getBackground() instanceof UIResource)
327: comboBox.setBackground(null);
328:
329: LookAndFeel.uninstallBorder(comboBox);
330: }
331:
332:
337: protected void uninstallListeners()
338: {
339: comboBox.removePropertyChangeListener(propertyChangeListener);
340: propertyChangeListener = null;
341:
342: comboBox.removeFocusListener(focusListener);
343: listBox.removeFocusListener(focusListener);
344: focusListener = null;
345:
346: comboBox.removeItemListener(itemListener);
347: itemListener = null;
348:
349: comboBox.removeKeyListener(keyListener);
350: keyListener = null;
351:
352: comboBox.getModel().removeListDataListener(listDataListener);
353: listDataListener = null;
354:
355: if (popupMouseListener != null)
356: comboBox.removeMouseListener(popupMouseListener);
357: popupMouseListener = null;
358:
359: if (popupMouseMotionListener != null)
360: comboBox.removeMouseMotionListener(popupMouseMotionListener);
361: popupMouseMotionListener = null;
362:
363: if (popupKeyListener != null)
364: comboBox.removeKeyListener(popupKeyListener);
365: popupKeyListener = null;
366: }
367:
368:
373: protected ComboPopup createPopup()
374: {
375: return new BasicComboPopup(comboBox);
376: }
377:
378:
383: protected KeyListener createKeyListener()
384: {
385: return new KeyHandler();
386: }
387:
388:
394: protected FocusListener createFocusListener()
395: {
396: return new FocusHandler();
397: }
398:
399:
404: protected ListDataListener createListDataListener()
405: {
406: return new ListDataHandler();
407: }
408:
409:
415: protected ItemListener createItemListener()
416: {
417: return new ItemHandler();
418: }
419:
420:
426: protected PropertyChangeListener createPropertyChangeListener()
427: {
428: return new PropertyChangeHandler();
429: }
430:
431:
437: protected LayoutManager createLayoutManager()
438: {
439: return new ComboBoxLayoutManager();
440: }
441:
442:
448: protected ListCellRenderer createRenderer()
449: {
450: return new BasicComboBoxRenderer.UIResource();
451: }
452:
453:
461: protected ComboBoxEditor createEditor()
462: {
463: return new BasicComboBoxEditor.UIResource();
464: }
465:
466:
471: protected void installComponents()
472: {
473:
474: popup = createPopup();
475: listBox = popup.getList();
476:
477:
478: arrowButton = createArrowButton();
479: comboBox.add(arrowButton);
480:
481: if (comboBox.isEditable())
482: addEditor();
483:
484: comboBox.add(currentValuePane);
485: }
486:
487:
492: protected void uninstallComponents()
493: {
494:
495: unconfigureArrowButton();
496: comboBox.remove(arrowButton);
497: arrowButton = null;
498:
499: popup = null;
500:
501: if (comboBox.getRenderer() instanceof UIResource)
502: comboBox.setRenderer(null);
503:
504:
505:
506: ComboBoxEditor currentEditor = comboBox.getEditor();
507: if (currentEditor instanceof UIResource)
508: {
509: comboBox.setEditor(null);
510: editor = null;
511: }
512: }
513:
514:
517: public void addEditor()
518: {
519: removeEditor();
520: editor = comboBox.getEditor().getEditorComponent();
521: comboBox.add(editor);
522: }
523:
524:
527: public void removeEditor()
528: {
529: if (editor != null)
530: {
531: unconfigureEditor();
532: comboBox.remove(editor);
533: }
534: }
535:
536:
539: protected void configureEditor()
540: {
541: editor.setFont(comboBox.getFont());
542: if (popupKeyListener != null)
543: editor.addKeyListener(popupKeyListener);
544: comboBox.configureEditor(comboBox.getEditor(),
545: comboBox.getSelectedItem());
546: }
547:
548:
551: protected void unconfigureEditor()
552: {
553: if (popupKeyListener != null)
554: editor.removeKeyListener(popupKeyListener);
555: }
556:
557:
562: public void configureArrowButton()
563: {
564: if (arrowButton != null)
565: {
566: arrowButton.setEnabled(comboBox.isEnabled());
567: arrowButton.setFocusable(false);
568: if (popupMouseListener != null)
569: arrowButton.addMouseListener(popupMouseListener);
570: if (popupMouseMotionListener != null)
571: arrowButton.addMouseMotionListener(popupMouseMotionListener);
572: }
573: }
574:
575:
583: public void unconfigureArrowButton()
584: {
585: if (arrowButton != null)
586: {
587: if (popupMouseListener != null)
588: arrowButton.removeMouseListener(popupMouseListener);
589: if (popupMouseMotionListener != null)
590: arrowButton.removeMouseMotionListener(popupMouseMotionListener);
591: }
592: }
593:
594:
601: protected JButton createArrowButton()
602: {
603: return new BasicArrowButton(BasicArrowButton.SOUTH);
604: }
605:
606:
615: public boolean isPopupVisible(JComboBox c)
616: {
617: return popup.isVisible();
618: }
619:
620:
627: public void setPopupVisible(JComboBox c, boolean v)
628: {
629: if (v)
630: popup.show();
631: else
632: popup.hide();
633: }
634:
635:
642: public boolean isFocusTraversable(JComboBox c)
643: {
644: if (!comboBox.isEditable())
645: return true;
646:
647: return false;
648: }
649:
650:
656: public void paint(Graphics g, JComponent c)
657: {
658: hasFocus = comboBox.hasFocus();
659: if (! comboBox.isEditable())
660: {
661: Rectangle rect = rectangleForCurrentValue();
662: paintCurrentValueBackground(g, rect, hasFocus);
663: paintCurrentValue(g, rect, hasFocus);
664: }
665: }
666:
667:
674: public Dimension getPreferredSize(JComponent c)
675: {
676: return getMinimumSize(c);
677: }
678:
679:
687: public Dimension getMinimumSize(JComponent c)
688: {
689: if (isMinimumSizeDirty)
690: {
691: Insets i = getInsets();
692: Dimension d = getDisplaySize();
693: d.width += i.left + i.right + d.height;
694: cachedMinimumSize = new Dimension(d.width, d.height + i.top + i.bottom);
695: isMinimumSizeDirty = false;
696: }
697: return new Dimension(cachedMinimumSize);
698: }
699:
700:
708: public Dimension getMaximumSize(JComponent c)
709: {
710: return new Dimension(32767, 32767);
711: }
712:
713: public int getAccessibleChildrenCount(JComponent c)
714: {
715:
716: return 0;
717: }
718:
719: public Accessible getAccessibleChild(JComponent c, int i)
720: {
721:
722: return null;
723: }
724:
725:
733: protected boolean isNavigationKey(int keyCode)
734: {
735: return false;
736: }
737:
738:
742: protected void selectNextPossibleValue()
743: {
744: int index = comboBox.getSelectedIndex();
745: if (index != comboBox.getItemCount() - 1)
746: comboBox.setSelectedIndex(index + 1);
747: }
748:
749:
753: protected void selectPreviousPossibleValue()
754: {
755: int index = comboBox.getSelectedIndex();
756: if (index != 0)
757: comboBox.setSelectedIndex(index - 1);
758: }
759:
760:
764: protected void toggleOpenClose()
765: {
766: setPopupVisible(comboBox, ! isPopupVisible(comboBox));
767: }
768:
769:
776: protected Rectangle rectangleForCurrentValue()
777: {
778: int w = comboBox.getWidth();
779: int h = comboBox.getHeight();
780: Insets i = comboBox.getInsets();
781: int arrowSize = h - (i.top + i.bottom);
782: if (arrowButton != null)
783: {
784: arrowSize = arrowButton.getWidth();
785: }
786: return new Rectangle(i.left, i.top, w - (i.left + i.right + arrowSize),
787: h - (i.top + i.left));
788: }
789:
790:
795: protected Insets getInsets()
796: {
797: return comboBox.getInsets();
798: }
799:
800:
809: public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus)
810: {
811: Object currentValue = comboBox.getSelectedItem();
812: boolean isPressed = arrowButton.getModel().isPressed();
813:
814:
818: ListCellRenderer renderer = comboBox.getRenderer();
819: if (comboBox.getSelectedIndex() != -1)
820: {
821: Component comp;
822: if (hasFocus && ! isPopupVisible(comboBox))
823: {
824: comp = renderer.getListCellRendererComponent(listBox,
825: comboBox.getSelectedItem(),
826: -1, true, false);
827: }
828: else
829: {
830: comp = renderer.getListCellRendererComponent(listBox,
831: comboBox.getSelectedItem(),
832: -1, false, false);
833: Color bg = UIManager.getColor("ComboBox.disabledForeground");
834: comp.setBackground(bg);
835: }
836: comp.setFont(comboBox.getFont());
837: if (hasFocus && ! isPopupVisible(comboBox))
838: {
839: comp.setForeground(listBox.getSelectionForeground());
840: comp.setBackground(listBox.getSelectionBackground());
841: }
842: else if (comboBox.isEnabled())
843: {
844: comp.setForeground(comboBox.getForeground());
845: comp.setBackground(comboBox.getBackground());
846: }
847: else
848: {
849: Color fg = UIManager.getColor("ComboBox.disabledForeground");
850: comp.setForeground(fg);
851: Color bg = UIManager.getColor("ComboBox.disabledBackground");
852: comp.setBackground(bg);
853: }
854: currentValuePane.paintComponent(g, comp, comboBox, bounds.x, bounds.y,
855: bounds.width, bounds.height);
856: }
857: }
858:
859:
869: public void paintCurrentValueBackground(Graphics g, Rectangle bounds,
870: boolean hasFocus)
871: {
872: Color saved = g.getColor();
873: if (comboBox.isEnabled())
874: {
875: g.setColor(UIManager.getColor("UIManager.background"));
876: }
877: else
878: {
879: g.setColor(UIManager.getColor("UIManager.disabledBackground"));
880: }
881: g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
882: g.setColor(saved);
883: }
884:
885: private static final ListCellRenderer DEFAULT_RENDERER
886: = new DefaultListCellRenderer();
887:
888:
897: protected Dimension getDefaultSize()
898: {
899: Component comp = DEFAULT_RENDERER.getListCellRendererComponent(listBox,
900: " ", -1,
901: false,
902: false);
903: currentValuePane.add(comp);
904: comp.setFont(comboBox.getFont());
905: Dimension d = comp.getPreferredSize();
906: currentValuePane.remove(comp);
907: return d;
908: }
909:
910:
916: protected Dimension getDisplaySize()
917: {
918: Dimension dim = new Dimension();
919: ListCellRenderer renderer = comboBox.getRenderer();
920: if (renderer == null)
921: {
922: renderer = DEFAULT_RENDERER;
923: }
924:
925: Object prototype = comboBox.getPrototypeDisplayValue();
926: if (prototype != null)
927: {
928: Component comp = renderer.getListCellRendererComponent
929: (listBox, prototype, -1, false, false);
930: currentValuePane.add(comp);
931: comp.setFont(comboBox.getFont());
932: Dimension renderSize = comp.getPreferredSize();
933: currentValuePane.remove(comp);
934: dim.height = renderSize.height;
935: dim.width = renderSize.width;
936: }
937: else
938: {
939: ComboBoxModel model = comboBox.getModel();
940: int size = model.getSize();
941: if (size > 0)
942: {
943: for (int i = 0; i < size; ++i)
944: {
945: Component comp = renderer.getListCellRendererComponent
946: (listBox, model.getElementAt(i), -1, false, false);
947: currentValuePane.add(comp);
948: comp.setFont(comboBox.getFont());
949: Dimension renderSize = comp.getPreferredSize();
950: currentValuePane.remove(comp);
951: dim.width = Math.max(dim.width, renderSize.width);
952: dim.height = Math.max(dim.height, renderSize.height);
953: }
954: }
955: else
956: {
957: dim = getDefaultSize();
958: if (comboBox.isEditable())
959: dim.width = 100;
960: }
961: }
962: if (comboBox.isEditable())
963: {
964: Dimension editSize = editor.getPreferredSize();
965: dim.width = Math.max(dim.width, editSize.width);
966: dim.height = Math.max(dim.height, editSize.height);
967: }
968: displaySize.setSize(dim.width, dim.height);
969: return dim;
970: }
971:
972:
976: protected void installKeyboardActions()
977: throws NotImplementedException
978: {
979:
980: }
981:
982:
986: protected void uninstallKeyboardActions()
987: throws NotImplementedException
988: {
989:
990: }
991:
992:
998: public class ComboBoxLayoutManager implements LayoutManager
999: {
1000:
1003: public ComboBoxLayoutManager()
1004: {
1005:
1006: }
1007:
1008:
1015: public void addLayoutComponent(String name, Component comp)
1016: {
1017:
1018: }
1019:
1020:
1026: public void removeLayoutComponent(Component comp)
1027: {
1028:
1029: }
1030:
1031:
1039: public Dimension preferredLayoutSize(Container parent)
1040: {
1041: return parent.getPreferredSize();
1042: }
1043:
1044:
1051: public Dimension minimumLayoutSize(Container parent)
1052: {
1053: return parent.getMinimumSize();
1054: }
1055:
1056:
1064: public void layoutContainer(Container parent)
1065: {
1066:
1067:
1068: Insets i = getInsets();
1069: int arrowSize = comboBox.getHeight() - (i.top + i.bottom);
1070: int editorWidth = comboBox.getBounds().width - arrowSize;
1071:
1072: if (arrowButton != null)
1073: arrowButton.setBounds(comboBox.getWidth() - (i.right + arrowSize),
1074: i.top, arrowSize, arrowSize);
1075: if (editor != null)
1076: editor.setBounds(rectangleForCurrentValue());
1077: }
1078: }
1079:
1080:
1086: public class FocusHandler extends Object implements FocusListener
1087: {
1088:
1091: public FocusHandler()
1092: {
1093:
1094: }
1095:
1096:
1102: public void focusGained(FocusEvent e)
1103: {
1104: hasFocus = true;
1105: comboBox.repaint();
1106: }
1107:
1108:
1114: public void focusLost(FocusEvent e)
1115: {
1116: hasFocus = false;
1117: if (! e.isTemporary() && comboBox.isLightWeightPopupEnabled())
1118: setPopupVisible(comboBox, false);
1119: comboBox.repaint();
1120: }
1121: }
1122:
1123:
1127: public class ItemHandler extends Object implements ItemListener
1128: {
1129:
1132: public ItemHandler()
1133: {
1134:
1135: }
1136:
1137:
1143: public void itemStateChanged(ItemEvent e)
1144: {
1145: ComboBoxModel model = comboBox.getModel();
1146: Object v = model.getSelectedItem();
1147: if (editor != null)
1148: {
1149: comboBox.configureEditor(comboBox.getEditor(), v);
1150: }
1151: comboBox.repaint();
1152: }
1153: }
1154:
1155:
1158: public class KeyHandler extends KeyAdapter
1159: {
1160: public KeyHandler()
1161: {
1162:
1163: }
1164:
1165:
1168: public void keyPressed(KeyEvent e)
1169: {
1170:
1171:
1172: }
1173: }
1174:
1175:
1178: public class ListDataHandler extends Object implements ListDataListener
1179: {
1180:
1183: public ListDataHandler()
1184: {
1185:
1186: }
1187:
1188:
1193: public void contentsChanged(ListDataEvent e)
1194: {
1195: if (e.getIndex0() != -1 || e.getIndex1() != -1)
1196: {
1197: isMinimumSizeDirty = true;
1198: comboBox.revalidate();
1199: }
1200: if (editor != null)
1201: {
1202: comboBox.configureEditor(comboBox.getEditor(),
1203: comboBox.getSelectedItem());
1204: }
1205: comboBox.repaint();
1206: }
1207:
1208:
1213: public void intervalAdded(ListDataEvent e)
1214: {
1215: int start = e.getIndex0();
1216: int end = e.getIndex1();
1217: if (start == 0 && comboBox.getItemCount() - (end - start + 1) == 0)
1218: {
1219: contentsChanged(e);
1220: }
1221: else if (start != -1 || end != -1)
1222: {
1223: ListCellRenderer renderer = comboBox.getRenderer();
1224: ComboBoxModel model = comboBox.getModel();
1225: int w = displaySize.width;
1226: int h = displaySize.height;
1227:
1228: for (int i = start; i <= end; ++i)
1229: {
1230: Component comp =
1231: renderer.getListCellRendererComponent(listBox,
1232: model.getElementAt(i),
1233: -1, false, false);
1234: currentValuePane.add(comp);
1235: comp.setFont(comboBox.getFont());
1236: Dimension dim = comp.getPreferredSize();
1237: w = Math.max(w, dim.width);
1238: h = Math.max(h, dim.height);
1239: currentValuePane.remove(comp);
1240: }
1241: if (displaySize.width < w || displaySize.height < h)
1242: {
1243: if (displaySize.width < w)
1244: {
1245: displaySize.width = w;
1246: }
1247: if (displaySize.height < h)
1248: {
1249: displaySize.height = h;
1250: }
1251: comboBox.revalidate();
1252: if (editor != null)
1253: {
1254: comboBox.configureEditor(comboBox.getEditor(),
1255: comboBox.getSelectedItem());
1256: }
1257: }
1258: }
1259:
1260: }
1261:
1262:
1268: public void intervalRemoved(ListDataEvent e)
1269: {
1270: contentsChanged(e);
1271: }
1272: }
1273:
1274:
1277: public class PropertyChangeHandler extends Object
1278: implements PropertyChangeListener
1279: {
1280:
1283: public PropertyChangeHandler()
1284: {
1285:
1286: }
1287:
1288:
1293: public void propertyChange(PropertyChangeEvent e)
1294: {
1295:
1296: isMinimumSizeDirty = true;
1297:
1298: if (e.getPropertyName().equals("enabled"))
1299: {
1300: arrowButton.setEnabled(comboBox.isEnabled());
1301:
1302: if (comboBox.isEditable())
1303: comboBox.getEditor().getEditorComponent().setEnabled(comboBox
1304: .isEnabled());
1305: }
1306: else if (e.getPropertyName().equals("editable"))
1307: {
1308: if (comboBox.isEditable())
1309: {
1310: configureEditor();
1311: addEditor();
1312: }
1313: else
1314: {
1315: unconfigureEditor();
1316: removeEditor();
1317: }
1318:
1319: comboBox.revalidate();
1320: comboBox.repaint();
1321: }
1322: else if (e.getPropertyName().equals("dataModel"))
1323: {
1324:
1325: ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue();
1326: if (oldModel != null)
1327: oldModel.removeListDataListener(listDataListener);
1328:
1329: if ((ComboBoxModel) e.getNewValue() != null)
1330: comboBox.getModel().addListDataListener(listDataListener);
1331: }
1332: else if (e.getPropertyName().equals("font"))
1333: {
1334: Font font = (Font) e.getNewValue();
1335: editor.setFont(font);
1336: listBox.setFont(font);
1337: arrowButton.setFont(font);
1338: comboBox.revalidate();
1339: comboBox.repaint();
1340: }
1341:
1342:
1343: }
1344: }
1345:
1346: }