Ignore:
Timestamp:
2012-08-18T14:58:25+02:00 (12 years ago)
Author:
Don-vip
Message:

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:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmComboBox.java

    r5429 r5450  
    22package org.openstreetmap.josm.gui.widgets;
    33
     4import java.awt.Toolkit;
    45import java.util.Vector;
    56
     7import javax.accessibility.Accessible;
    68import javax.swing.ComboBoxModel;
    79import javax.swing.DefaultComboBoxModel;
    810import javax.swing.JComboBox;
    9 
    10 import org.openstreetmap.josm.Main;
    11 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
    12 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
     11import javax.swing.JList;
     12import javax.swing.plaf.basic.ComboPopup;
    1313
    1414/**
    1515 * 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 #).
    17  * <p>
    18  * The property {@code gui.combobox.maximum-row-count} can be setup to control this behaviour.
     16 * This is needed because of the default Java behaviour that may display the top-down list off the screen (see #7917).
    1917 *
    2018 * @since 5429
    2119 */
    22 public class JosmComboBox extends JComboBox implements PreferenceChangedListener {
     20public class JosmComboBox extends JComboBox {
    2321
    2422    /**
    25      * This property allows to control the {@link #getMaximumRowCount} of all combo boxes used in JOSM.
     23     * The default prototype value used to compute the maximum number of elements to be displayed at once before
     24     * displaying a scroll bar
    2625     */
    27     public static final String PROP_MAXIMUM_ROW_COUNT = "gui.combobox.maximum-row-count";
     26    public static final String DEFAULT_PROTOTYPE_DISPLAY_VALUE = "Prototype display value";
    2827   
    2928    /**
    3029     * Creates a <code>JosmComboBox</code> with a default data model.
    3130     * The default data model is an empty list of objects.
    32      * Use <code>addItem</code> to add items.  By default the first item
     31     * Use <code>addItem</code> to add items. By default the first item
    3332     * in the data model becomes selected.
    3433     *
     
    3635     */
    3736    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) {
    3855        super();
    39         init();
     56        init(prototypeDisplayValue);
    4057    }
    4158
    4259    /**
    4360     * Creates a <code>JosmComboBox</code> that takes its items from an
    44      * existing <code>ComboBoxModel</code>.  Since the
     61     * existing <code>ComboBoxModel</code>. Since the
    4562     * <code>ComboBoxModel</code> is provided, a combo box created using
    4663     * this constructor does not create a default combo box model and
     
    5370    public JosmComboBox(ComboBoxModel aModel) {
    5471        super(aModel);
    55         init();
     72        init(aModel != null && aModel.getSize() > 0 ? aModel.getElementAt(0) : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
    5673    }
    5774
    5875    /**
    5976     * Creates a <code>JosmComboBox</code> that contains the elements
    60      * in the specified array.  By default the first item in the array
     77     * in the specified array. By default the first item in the array
    6178     * (and therefore the data model) becomes selected.
    6279     *
     
    6683    public JosmComboBox(Object[] items) {
    6784        super(items);
    68         init();
     85        init(items != null && items.length > 0 ? items[0] : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
    6986    }
    7087
    7188    /**
    7289     * Creates a <code>JosmComboBox</code> that contains the elements
    73      * in the specified Vector.  By default the first item in the vector
     90     * in the specified Vector. By default the first item in the vector
    7491     * (and therefore the data model) becomes selected.
    7592     *
     
    7996    public JosmComboBox(Vector<?> items) {
    8097        super(items);
    81         init();
     98        init(items != null && !items.isEmpty() ? items.get(0) : DEFAULT_PROTOTYPE_DISPLAY_VALUE);
    8299    }
    83100   
    84     protected void init() {
    85         setMaximumRowCount(Main.pref.getInteger(PROP_MAXIMUM_ROW_COUNT, 20));
    86     }
    87    
    88     /**
    89      * Registers this combo box to the change of the property {@code gui.combobox.maximum-row-count}.<br/>
    90      * Do not forget to call {@link #unregisterFromPreferenceChange} when the combo box is no longer needed.
    91      * @see #unregisterFromPreferenceChange
    92      */
    93     public final void registerToPreferenceChange() {
    94         Main.pref.addPreferenceChangeListener(this);
    95     }
    96    
    97     /**
    98      * Unregisters this combo box previously registered by {@link #registerToPreferenceChange}.
    99      * @see #registerToPreferenceChange
    100      */
    101     public final void unregisterFromPreferenceChange() {
    102         Main.pref.removePreferenceChangeListener(this);
    103     }
    104 
    105     @Override
    106     public void preferenceChanged(PreferenceChangeEvent e) {
    107         if (PROP_MAXIMUM_ROW_COUNT.equals(e.getKey())) {
    108             setMaximumRowCount(Main.pref.getInteger(PROP_MAXIMUM_ROW_COUNT, 20));
     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));
    109127        }
    110128    }
Note: See TracChangeset for help on using the changeset viewer.