1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components;
21
22 import java.awt.BorderLayout;
23 import java.awt.Component;
24 import java.awt.Container;
25 import java.awt.Dimension;
26 import java.awt.FlowLayout;
27 import java.awt.Graphics;
28 import java.awt.Insets;
29 import java.awt.LayoutManager;
30 import java.awt.Rectangle;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.awt.event.ItemEvent;
34 import java.awt.event.ItemListener;
35 import java.awt.event.KeyAdapter;
36 import java.awt.event.KeyEvent;
37 import java.awt.event.KeyListener;
38 import java.awt.event.WindowAdapter;
39 import java.awt.event.WindowEvent;
40 import java.util.Vector;
41
42 import javax.swing.CellRendererPane;
43 import javax.swing.ComboBoxModel;
44 import javax.swing.DefaultComboBoxModel;
45 import javax.swing.JComboBox;
46 import javax.swing.JComponent;
47 import javax.swing.JFrame;
48 import javax.swing.JPanel;
49 import javax.swing.ListCellRenderer;
50 import javax.swing.plaf.ComboBoxUI;
51 import javax.swing.plaf.basic.BasicComboBoxRenderer;
52 import javax.swing.plaf.basic.BasicComboBoxUI;
53 import javax.swing.plaf.basic.BasicComboPopup;
54 import javax.swing.plaf.metal.MetalBorders;
55
56 import com.cosylab.gui.components.util.ColorHelper;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public class SimpleComboBox extends JComboBox
82 {
83
84 private static final long serialVersionUID = -7775055879270581688L;
85
86
87
88
89 public static int SIMPLE_STYLE = 0;
90
91
92
93
94 public static int DROP_DOWN_STYLE = 3;
95
96
97
98
99 public static int SWITCH_STYLE_POPUP_ENABLED = 1;
100
101
102
103
104 public static int SWITCH_STYLE_POPUP_DISABLED = 2;
105
106 public enum Style {
107 SIMPLE_STYLE,
108 SWITCH_STYLE_POPUP_ENABLED,
109 SWITCH_STYLE_POPUP_DISABLED,
110 DROP_DOWN_STYLE
111 };
112
113 private ListCellRenderer selectedItemRenderer = null;
114 private int style = SIMPLE_STYLE;
115
116 private String HIDE_POPUP_KEY;
117
118 private Style styleE;
119
120
121
122
123
124
125
126
127 public SimpleComboBox(ComboBoxModel aModel)
128 {
129 super(aModel);
130 init();
131 }
132
133
134
135
136
137
138
139
140 public SimpleComboBox(Object[] items)
141 {
142 super(items);
143 init();
144 }
145
146
147
148
149
150
151
152
153 public SimpleComboBox(Vector items)
154 {
155 super(items);
156 init();
157 }
158
159
160
161
162
163
164 public SimpleComboBox()
165 {
166 super();
167 init();
168 }
169
170 private void init()
171 {
172
173 super.setUI(new BasicComboBoxUI());
174 HIDE_POPUP_KEY = String.valueOf(getClientProperty("doNotCancelPopup"));
175
176 setUI(new SimpleComboBoxUI());
177 setBorder(new MetalBorders.Flush3DBorder());
178 }
179
180
181
182
183
184
185
186
187 public void setUI(ComboBoxUI ui)
188 {
189
190 if (ui instanceof SimpleComboBoxUI) {
191 super.setUI(ui);
192 }
193 }
194
195
196
197
198
199
200 public ListCellRenderer getSelectedItemRenderer()
201 {
202 return selectedItemRenderer;
203 }
204
205 @Override
206 public void setEnabled(boolean b) {
207 super.setEnabled(b);
208 ComboBoxUI ui = getUI();
209 if (ui instanceof SwitchComboBoxUI) {
210 ((SwitchComboBoxUI)ui).leftButton.setEnabled(b);
211 ((SwitchComboBoxUI)ui).rightButton.setEnabled(b);
212 } else if (ui instanceof DropComboBoxUI) {
213 ((DropComboBoxUI)ui).dropButton.setEnabled(b);
214 }
215 }
216
217
218
219
220
221
222
223
224
225
226 public void setSelectedItemRenderer(
227 ListCellRenderer newSelectedItemRenderer)
228 {
229 ListCellRenderer oldSelectedItemRenderer = selectedItemRenderer;
230 selectedItemRenderer = newSelectedItemRenderer;
231 firePropertyChange("selectedItemRenderer", oldSelectedItemRenderer,
232 newSelectedItemRenderer);
233 }
234
235
236
237
238
239
240 public int getStyle()
241 {
242 return style;
243 }
244
245 public void setStyle(Style newStyleE) {
246 if (styleE == newStyleE) {
247 return;
248 }
249
250 if (newStyleE == Style.SIMPLE_STYLE) {
251 setUI(new SimpleComboBoxUI());
252 } else if (newStyleE == Style.DROP_DOWN_STYLE) {
253 setUI(new DropComboBoxUI());
254 } else if (newStyleE == Style.SWITCH_STYLE_POPUP_ENABLED) {
255 SwitchComboBoxUI ui = new SwitchComboBoxUI();
256 setUI(ui);
257 ui.setPopupEnabled(true);
258 } else if (newStyleE == Style.SWITCH_STYLE_POPUP_DISABLED) {
259 SwitchComboBoxUI ui = new SwitchComboBoxUI();
260 setUI(ui);
261 ui.setPopupEnabled(false);
262 } else {
263 throw (new IllegalArgumentException());
264 }
265
266 Style oldStyleE = styleE;
267 styleE = newStyleE;
268 firePropertyChange("style", oldStyleE, newStyleE);
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 public void setStyle(int newStyle)
286 {
287 setStyle(Style.values()[newStyle]);
288 }
289
290
291
292
293
294
295 public static void main(String[] args)
296 {
297 JFrame frame = new JFrame("SimpleComboBox Demo");
298 final SimpleComboBox box = new SimpleComboBox();
299 DefaultComboBoxModel model = new DefaultComboBoxModel();
300
301 for (int i = 1; i <= 50; i++) {
302 model.addElement("item " + i);
303 }
304
305 box.setModel(model);
306
307 final JComboBox box1 = new JComboBox();
308 DefaultComboBoxModel model1 = new DefaultComboBoxModel();
309 for (Style st : Style.values()) {
310 model1.addElement(st);
311 }
312 box1.setModel(model1);
313 box1.addActionListener(new ActionListener() {
314 public void actionPerformed(ActionEvent e)
315 {
316 box.setStyle(((Style)box1.getSelectedItem()));
317 }
318 });
319
320 frame.getContentPane().setLayout(new FlowLayout());
321 frame.getContentPane().add(box);
322 frame.getContentPane().add(box1);
323 frame.setSize(500, 200);
324 frame.addWindowListener(new WindowAdapter() {
325 public void windowClosing(WindowEvent e)
326 {
327 System.exit(0);
328 }
329 });
330 frame.setVisible(true);
331 }
332
333
334
335
336
337
338
339
340
341 public static class SimpleComboBoxUI extends ComboBoxUI
342 {
343 protected SimpleComboBox comboBox = null;
344 protected BasicComboPopup popup = null;
345 protected CellRendererPane cellRenderingPane = null;
346 protected ItemListener itemListener;
347
348
349
350
351 public SimpleComboBoxUI()
352 {
353 super();
354 }
355
356
357
358
359
360
361
362
363
364
365 public boolean isFocusTraversable(JComboBox c)
366 {
367
368
369 return !comboBox.isEditable();
370 }
371
372
373
374
375
376
377
378
379
380
381 public boolean isPopupVisible(JComboBox c)
382 {
383
384
385 if (popup == null) {
386 return false;
387 }
388
389 return popup.isVisible();
390 }
391
392
393
394
395
396
397
398
399
400 public void setPopupVisible( JComboBox c, boolean v ) {
401 if ( v ) {
402 popup.show();
403 } else {
404 popup.hide();
405 }
406 }
407
408
409
410
411
412
413
414
415 public void installUI(JComponent c)
416 {
417
418
419 comboBox = (SimpleComboBox)c;
420 popup = new BasicComboPopup(comboBox) {
421 private static final long serialVersionUID = -5379054665405013304L;
422
423
424
425
426 protected KeyListener createKeyListener() {
427 return new KeyAdapter() {
428 public void keyPressed(KeyEvent e) {
429 if (e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_RIGHT) getList().setSelectedIndex(list.getSelectedIndex()-1);
430 if (e.getKeyCode()==KeyEvent.VK_DOWN || e.getKeyCode()==KeyEvent.VK_LEFT) getList().setSelectedIndex(list.getSelectedIndex()+1);
431 if (e.getKeyCode()==KeyEvent.VK_ENTER) {
432 comboBox.setSelectedIndex(getList().getSelectedIndex());
433 hide();
434 }
435 if (e.getKeyCode()==KeyEvent.VK_ESCAPE) hide();
436 getList().ensureIndexIsVisible(getList().getSelectedIndex());
437 }
438 };
439
440 }
441 };
442 comboBox.addKeyListener(popup.getKeyListener());
443 cellRenderingPane = new CellRendererPane();
444 itemListener = new ItemListener() {
445 public void itemStateChanged(ItemEvent e)
446 {
447 comboBox.revalidate();
448 comboBox.repaint();
449 }
450 };
451
452 comboBox.addItemListener(itemListener);
453 comboBox.addMouseListener(popup.getMouseListener());
454 comboBox.addMouseMotionListener(popup.getMouseMotionListener());
455 comboBox.setLayout(new ComboBoxLayoutManager());
456 comboBox.add(cellRenderingPane, BorderLayout.CENTER);
457
458 comboBox.putClientProperty("doNotCancelPopup", comboBox.HIDE_POPUP_KEY);
459
460 }
461
462
463
464
465
466
467
468
469 public void uninstallUI(JComponent c)
470 {
471
472 super.uninstallUI(c);
473 comboBox.removeItemListener(itemListener);
474 comboBox.removeMouseListener(popup.getMouseListener());
475 comboBox.removeMouseMotionListener(popup.getMouseMotionListener());
476 comboBox.setLayout(null);
477 comboBox.remove(cellRenderingPane);
478 comboBox = null;
479 popup = null;
480 cellRenderingPane = null;
481 itemListener = null;
482 }
483
484
485
486
487
488
489
490
491
492
493 public Dimension getMaximumSize(JComponent c)
494 {
495
496
497 return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
498 }
499
500
501
502
503
504
505
506
507
508
509 public Dimension getMinimumSize(JComponent c)
510 {
511
512
513 return getPreferredSize(c);
514 }
515
516
517
518
519
520
521
522
523
524
525
526 public Dimension getPreferredSize(JComponent c)
527 {
528
529
530 return calculatePreferredSize();
531 }
532
533
534
535
536
537
538
539
540
541
542 public void paint(Graphics g, JComponent jc)
543 {
544
545
546 if (comboBox.getRenderer() == null) {
547 comboBox.setRenderer(new BasicComboBoxRenderer.UIResource());
548 }
549
550 Component c = null;
551
552 if (comboBox.getSelectedItemRenderer() == null) {
553 c = comboBox.getRenderer().getListCellRendererComponent(popup
554 .getList(), comboBox.getSelectedItem(),
555 comboBox.getSelectedIndex(), true, comboBox.hasFocus());
556 } else {
557 c = comboBox.getSelectedItemRenderer()
558 .getListCellRendererComponent(popup.getList(),
559 comboBox.getSelectedItem(),
560 comboBox.getSelectedIndex(), true, comboBox.hasFocus());
561 }
562
563 Rectangle bounds = calculateRendererCellRectangle();
564
565
566 boolean shouldValidate = false;
567
568 if (c instanceof JPanel) {
569 shouldValidate = true;
570 }
571
572 cellRenderingPane.paintComponent(g, c, comboBox, bounds.x,
573 bounds.y, bounds.width, bounds.height, shouldValidate);
574 }
575
576
577
578
579
580 protected Rectangle calculateRendererCellRectangle()
581 {
582 int width = comboBox.getWidth();
583 int height = comboBox.getHeight();
584 Insets insets = comboBox.getInsets();
585
586 return new Rectangle(insets.left, insets.top,
587 width - (insets.left + insets.right),
588 height - (insets.top + insets.bottom));
589 }
590
591
592
593
594 protected void calculateLayout()
595 {
596
597 }
598
599
600
601
602
603 protected Dimension calculatePreferredSize()
604 {
605 if (comboBox.getRenderer() == null) {
606 comboBox.setRenderer(new BasicComboBoxRenderer.UIResource());
607 }
608
609 Component c = null;
610 int width = 0;
611 int height = 0;
612
613 for (int i = 0; i < popup.getList().getModel().getSize(); i++) {
614 if (comboBox.getSelectedItemRenderer() == null) {
615 c = comboBox.getRenderer().getListCellRendererComponent(popup
616 .getList(), comboBox.getItemAt(i), i, true,
617 comboBox.hasFocus());
618 } else {
619 c = comboBox.getSelectedItemRenderer()
620 .getListCellRendererComponent(popup.getList(),
621 comboBox.getItemAt(i), i, true, comboBox.hasFocus());
622 }
623
624 width = Math.max(c.getPreferredSize().width, width);
625 height = Math.max(c.getPreferredSize().height, height);
626 }
627
628 Insets insets = comboBox.getInsets();
629
630 int buttonSize = ArrowButton.PREFERRED_SIZE;
631
632 Dimension retVal = new Dimension(buttonSize+insets.left + insets.right + width,
633 insets.top + insets.bottom + height);
634
635 return retVal;
636 }
637
638
639
640
641
642
643 protected class ComboBoxLayoutManager implements LayoutManager
644 {
645
646
647
648
649
650
651
652
653
654 public void addLayoutComponent(String name, Component comp)
655 {
656 }
657
658
659
660
661
662
663
664
665 public void removeLayoutComponent(Component comp)
666 {
667 }
668
669
670
671
672
673
674
675
676
677
678 public Dimension preferredLayoutSize(Container parent)
679 {
680 return parent.getPreferredSize();
681 }
682
683
684
685
686
687
688
689
690
691
692 public Dimension minimumLayoutSize(Container parent)
693 {
694 return parent.getMinimumSize();
695 }
696
697
698
699
700
701
702
703
704
705 public void layoutContainer(Container parent)
706 {
707 ((SimpleComboBoxUI)((SimpleComboBox)parent).getUI())
708 .calculateLayout();
709 }
710 }
711 }
712
713
714
715
716
717
718 public static class SwitchComboBoxUI extends SimpleComboBoxUI
719 {
720 protected ArrowButton leftButton = null;
721 protected ArrowButton rightButton = null;
722 private boolean popupEnabled = true;
723 private boolean mustSetPopup = false;
724
725
726
727
728 protected SimpleButton getLeftButton()
729 {
730 if (leftButton == null) {
731 leftButton = new ArrowButton(ArrowButton.LEFT);
732 leftButton.addActionListener(new ActionListener() {
733 public void actionPerformed(ActionEvent e)
734 {
735 if (comboBox.getSelectedIndex() > 0) {
736 comboBox.setSelectedIndex(comboBox
737 .getSelectedIndex() - 1);
738 }
739 }
740 });
741 leftButton.setBackground(ColorHelper.getControl());
742 leftButton.setBorder(null);
743 leftButton.setPressedBorder(null);
744 leftButton.putClientProperty("doNotCancelPopup", comboBox.HIDE_POPUP_KEY);
745 }
746
747 return leftButton;
748 }
749
750
751
752
753 protected SimpleButton getRightButton()
754 {
755 if (rightButton == null) {
756 rightButton = new ArrowButton(ArrowButton.RIGHT);
757 rightButton.addActionListener(new ActionListener() {
758 public void actionPerformed(ActionEvent e)
759 {
760 if (comboBox.getSelectedIndex() < (comboBox
761 .getItemCount() - 1)) {
762 comboBox.setSelectedIndex(comboBox
763 .getSelectedIndex() + 1);
764 }
765 }
766 });
767 rightButton.setBackground(ColorHelper.getControl());
768 rightButton.setBorder(null);
769 rightButton.setPressedBorder(null);
770 rightButton.putClientProperty("doNotCancelPopup", comboBox.HIDE_POPUP_KEY);
771 }
772
773 return rightButton;
774 }
775
776
777
778
779
780 protected Dimension calculatePreferredSize()
781 {
782 Dimension retVal = super.calculatePreferredSize();
783 retVal.width += ArrowButton.PREFERRED_SIZE;
784
785 return retVal;
786 }
787
788
789
790
791
792 protected Rectangle calculateRendererCellRectangle()
793 {
794 Rectangle retVal = super.calculateRendererCellRectangle();
795 retVal.x += getRightButton().getBounds().width;
796 retVal.width -= (getRightButton().getBounds().width
797 + getLeftButton().getBounds().width);
798
799 return retVal;
800 }
801
802
803
804
805 protected void calculateLayout()
806 {
807 int width = comboBox.getWidth();
808 int height = comboBox.getHeight();
809 Insets insets = comboBox.getInsets();
810
811 int buttonSize = height - (insets.top + insets.bottom);
812
813 getLeftButton().setBounds(insets.left, insets.top, buttonSize,
814 buttonSize);
815 getRightButton().setBounds(width - (insets.right + buttonSize),
816 insets.top, buttonSize, buttonSize);
817 }
818
819
820
821
822
823
824 public boolean isPopupEnabled()
825 {
826 return popupEnabled;
827 }
828
829
830
831
832
833
834
835 public void setPopupEnabled(boolean newPopupEnabled)
836 {
837 if (popupEnabled == newPopupEnabled) {
838 return;
839 }
840
841 popupEnabled = newPopupEnabled;
842
843 if (comboBox == null) {
844 mustSetPopup = true;
845
846 return;
847 } else {
848 mustSetPopup = false;
849 }
850
851 if (popupEnabled) {
852 comboBox.addMouseListener(popup.getMouseListener());
853 comboBox.addMouseMotionListener(popup.getMouseMotionListener());
854 } else {
855 comboBox.removeMouseListener(popup.getMouseListener());
856 comboBox.removeMouseMotionListener(popup.getMouseMotionListener());
857 }
858 }
859
860
861
862
863
864
865
866
867
868 public void uninstallUI(JComponent c)
869 {
870 comboBox.remove(getRightButton());
871 comboBox.remove(getLeftButton());
872 rightButton = null;
873 leftButton = null;
874 super.uninstallUI(c);
875 }
876
877
878
879
880
881
882
883
884
885 public void installUI(JComponent c)
886 {
887 super.installUI(c);
888 comboBox.add(getRightButton(), BorderLayout.EAST);
889 comboBox.add(getLeftButton(), BorderLayout.WEST);
890
891 if (mustSetPopup) {
892 setPopupEnabled(popupEnabled);
893 }
894 }
895 }
896
897
898
899
900
901
902
903
904 public static class DropComboBoxUI extends SimpleComboBoxUI
905 {
906 protected ArrowButton dropButton = null;
907
908
909
910
911 protected SimpleButton getDropButton()
912 {
913 if (dropButton == null) {
914 dropButton = new ArrowButton(ArrowButton.DOWN);
915 dropButton.addMouseListener(popup.getMouseListener());
916 dropButton.addMouseMotionListener(popup.getMouseMotionListener());
917 dropButton.setBackground(ColorHelper.getControl());
918 dropButton.setBorder(null);
919 dropButton.setPressedBorder(null);
920 dropButton.putClientProperty("doNotCancelPopup", comboBox.HIDE_POPUP_KEY);
921 }
922
923 return dropButton;
924 }
925
926
927
928
929
930 protected Dimension calculatePreferredSize()
931 {
932 Dimension retVal = super.calculatePreferredSize();
933
934
935 return retVal;
936 }
937
938
939
940
941
942 protected Rectangle calculateRendererCellRectangle()
943 {
944 Rectangle retVal = super.calculateRendererCellRectangle();
945 retVal.width -= getDropButton().getBounds().width;
946
947 return retVal;
948 }
949
950
951
952
953 protected void calculateLayout()
954 {
955 int width = comboBox.getWidth();
956 int height = comboBox.getHeight();
957 Insets insets = comboBox.getInsets();
958
959 int buttonSize = height - (insets.top + insets.bottom);
960
961 getDropButton().setBounds(width - (insets.right + buttonSize),
962 insets.top, buttonSize, buttonSize);
963 }
964
965
966
967
968
969
970
971
972
973 public void uninstallUI(JComponent c)
974 {
975 comboBox.remove(getDropButton());
976 dropButton = null;
977 super.uninstallUI(c);
978 }
979
980
981
982
983 public void installUI(JComponent c)
984 {
985 super.installUI(c);
986 comboBox.add(getDropButton(), BorderLayout.EAST);
987 }
988 }
989 }
990
991