source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/JosmComboBox.java@ 5450

Last change on this file since 5450 was 5450, checked in by Don-vip, 12 years ago

fix #7917 - Control the number of items displayed at once in all comboboxes (replaced configurable method with a dynamic method based on screen height and look and feel)

File size: 5.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import java.awt.Toolkit;
5import java.util.Vector;
6
7import javax.accessibility.Accessible;
8import javax.swing.ComboBoxModel;
9import javax.swing.DefaultComboBoxModel;
10import javax.swing.JComboBox;
11import javax.swing.JList;
12import javax.swing.plaf.basic.ComboPopup;
13
14/**
15 * Class overriding each {@link JComboBox} in JOSM to control consistently the number of displayed items at once.<br/>
16 * This is needed because of the default Java behaviour that may display the top-down list off the screen (see #7917).
17 *
18 * @since 5429
19 */
20public class JosmComboBox extends JComboBox {
21
22 /**
23 * The default prototype value used to compute the maximum number of elements to be displayed at once before
24 * displaying a scroll bar
25 */
26 public static final String DEFAULT_PROTOTYPE_DISPLAY_VALUE = "Prototype display value";
27
28 /**
29 * Creates a <code>JosmComboBox</code> with a default data model.
30 * The default data model is an empty list of objects.
31 * Use <code>addItem</code> to add items. By default the first item
32 * in the data model becomes selected.
33 *
34 * @see DefaultComboBoxModel
35 */
36 public JosmComboBox() {
37 this(DEFAULT_PROTOTYPE_DISPLAY_VALUE);
38 }
39
40 /**
41 * Creates a <code>JosmComboBox</code> with a default data model and
42 * the specified prototype display value.
43 * The default data model is an empty list of objects.
44 * Use <code>addItem</code> to add items. By default the first item
45 * in the data model becomes selected.
46 *
47 * @param prototypeDisplayValue the <code>Object</code> used to compute
48 * the maximum number of elements to be displayed at once before
49 * displaying a scroll bar
50 *
51 * @see DefaultComboBoxModel
52 * @since 5450
53 */
54 public JosmComboBox(Object prototypeDisplayValue) {
55 super();
56 init(prototypeDisplayValue);
57 }
58
59 /**
60 * Creates a <code>JosmComboBox</code> that takes its items from an
61 * existing <code>ComboBoxModel</code>. Since the
62 * <code>ComboBoxModel</code> is provided, a combo box created using
63 * this constructor does not create a default combo box model and
64 * may impact how the insert, remove and add methods behave.
65 *
66 * @param aModel the <code>ComboBoxModel</code> that provides the
67 * displayed list of items
68 * @see DefaultComboBoxModel
69 */
70 public JosmComboBox(ComboBoxModel aModel) {
71 super(aModel);
72 init(aModel != null && aModel.getSize() > 0 ? aModel.getElementAt(0) : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
73 }
74
75 /**
76 * Creates a <code>JosmComboBox</code> that contains the elements
77 * in the specified array. By default the first item in the array
78 * (and therefore the data model) becomes selected.
79 *
80 * @param items an array of objects to insert into the combo box
81 * @see DefaultComboBoxModel
82 */
83 public JosmComboBox(Object[] items) {
84 super(items);
85 init(items != null && items.length > 0 ? items[0] : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
86 }
87
88 /**
89 * Creates a <code>JosmComboBox</code> that contains the elements
90 * in the specified Vector. By default the first item in the vector
91 * (and therefore the data model) becomes selected.
92 *
93 * @param items an array of vectors to insert into the combo box
94 * @see DefaultComboBoxModel
95 */
96 public JosmComboBox(Vector<?> items) {
97 super(items);
98 init(items != null && !items.isEmpty() ? items.get(0) : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
99 }
100
101 protected void init(Object prototype) {
102 if (prototype != null) {
103 setPrototypeDisplayValue(prototype);
104 int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
105 // Compute maximum number of visible items based on the preferred size of the combo box.
106 // This assumes that items have the same height as the combo box, which is not granted by the look and feel
107 int maxsize = (screenHeight/getPreferredSize().height) / 2;
108 // If possible, adjust the maximum number of items with the real height of items
109 // It is not granted this works on every platform (tested OK on Windows)
110 for (int i = 0; i < getUI().getAccessibleChildrenCount(this); i++) {
111 Accessible child = getUI().getAccessibleChild(this, i);
112 if (child instanceof ComboPopup) {
113 JList list = ((ComboPopup)child).getList();
114 if (list != null) {
115 if (list.getPrototypeCellValue() != prototype) {
116 list.setPrototypeCellValue(prototype);
117 }
118 int height = list.getFixedCellHeight();
119 if (height > 0) {
120 maxsize = (screenHeight/height) / 2;
121 }
122 }
123 break;
124 }
125 }
126 setMaximumRowCount(Math.max(getMaximumRowCount(), maxsize));
127 }
128 }
129}
Note: See TracBrowser for help on using the repository browser.