/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.tools; import java.awt.Component; import java.awt.Dimension; import java.awt.Toolkit; import javax.accessibility.Accessible; import javax.swing.ComboBoxModel; import javax.swing.JComboBox; import javax.swing.JList; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.plaf.basic.BasicComboBoxRenderer; /** * A combo box which can use a predefined preferred size. Can also show the full value as tool tip in cases where the * strings were too short. * * @author Ingo Mierswa */ public class ExtendedJComboBox extends JComboBox { private static final long serialVersionUID = 8320969518243948543L; private static class ExtendedComboBoxRenderer extends BasicComboBoxRenderer { private static final long serialVersionUID = -6192190927539294311L; @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); if (index >= 0) { list.setToolTipText((value == null) ? null : value.toString()); } } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } setFont(list.getFont()); setText((value == null) ? "" : value.toString()); return this; } } private boolean isScrollingToTopOnChange = false; // this listener is used to scroll back on top, if the data has been changed. private ListDataListener scrollToTopListener = new ListDataListener() { @Override public void intervalRemoved(ListDataEvent e) { } @Override public void intervalAdded(ListDataEvent e) { if (isScrollingToTopOnChange) { Accessible accessibleChild = ExtendedJComboBox.this.getUI().getAccessibleChild(ExtendedJComboBox.this, 0); if (!(accessibleChild instanceof JPopupMenu)) { return; } Object scrollPaneObject = ((JPopupMenu) accessibleChild).getComponent(0); if (scrollPaneObject instanceof JScrollPane) ((JScrollPane) scrollPaneObject).getVerticalScrollBar().setValue(0); } } @Override public void contentsChanged(ListDataEvent e) { } }; private int preferredWidth = -1; private int minimumWidth = -1; private boolean layingOut = false; private boolean wide = true; public ExtendedJComboBox(String[] values) { this(-1, -1, true, values); } public ExtendedJComboBox() { this(-1, -1); } public ExtendedJComboBox(int preferredWidth) { this(preferredWidth, -1); } public ExtendedJComboBox(int preferredWidth, int minimumWidth) { this(preferredWidth, minimumWidth, true); } public ExtendedJComboBox(int preferredWidth, int minimumWidth, boolean wide) { this(preferredWidth, minimumWidth, wide, new String[0]); } public ExtendedJComboBox(ComboBoxModel model) { this(-1, -1, true, model); } public ExtendedJComboBox(int preferredWidth, int minimumWidth, boolean wide, ComboBoxModel model) { super(model); this.preferredWidth = preferredWidth; this.minimumWidth = minimumWidth; this.wide = wide; model.addListDataListener(scrollToTopListener); } public ExtendedJComboBox(int preferredWidth, int minimumWidth, boolean wide, String[] values) { super(values); this.preferredWidth = preferredWidth; this.minimumWidth = minimumWidth; this.wide = wide; setRenderer(new ExtendedComboBoxRenderer()); } public void setPreferredWidth(int preferredWidth) { this.preferredWidth = preferredWidth; } @Override public void setModel(ComboBoxModel aModel) { super.setModel(aModel); aModel.addListDataListener(scrollToTopListener); } public boolean isScrollingToTopOnChange() { return isScrollingToTopOnChange; } /** * If the scrolling is enabled, the scroll bar of the combo box pop up list will be scrolled to top * when the model's data changed. */ public void enableScrollingToTopOnChange(boolean enable) { isScrollingToTopOnChange = enable; } public boolean isWide() { return wide; } public void setWide(boolean wide) { this.wide = wide; } @Override public Dimension getPreferredSize() { Dimension dim = super.getPreferredSize(); if (this.preferredWidth != -1) { return new Dimension(preferredWidth, (int) dim.getHeight()); } else { return dim; } } @Override public Dimension getMinimumSize() { Dimension dim = super.getMinimumSize(); if (this.minimumWidth != -1) { return new Dimension(minimumWidth, (int) dim.getHeight()); } else { return dim; } } @Override public void doLayout() { try { layingOut = true; super.doLayout(); } finally { layingOut = false; } } @Override public Dimension getSize() { Dimension dim = super.getSize(); if (!layingOut && isWide()) dim.width = Math.max(dim.width, super.getPreferredSize().width); dim.width = Math.min(dim.width, Toolkit.getDefaultToolkit().getScreenSize().width - 40); return dim; } }