/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ /* * Copyright (c) 2001-2009 JGoodies Karsten Lentzsch. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of JGoodies Karsten Lentzsch nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package de.cismet.cids.editors; import Sirius.server.middleware.types.MetaClass; import com.jgoodies.looks.Options; import com.jgoodies.looks.plastic.PlasticComboBoxUI; import java.awt.Component; import java.awt.Rectangle; import java.util.Comparator; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.ListCellRenderer; import javax.swing.ScrollPaneConstants; import javax.swing.UIManager; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.ComboPopup; import javax.swing.plaf.metal.MetalScrollBarUI; import de.cismet.cids.dynamics.CidsBean; /** * Wraps a DefaultBindableCombobox and add a horizontal scrollbar, if required. * * @author therter * @version $Revision$, $Date$ */ public class DefaultBindableScrollableComboBox extends DefaultBindableReferenceCombo { //~ Constructors ----------------------------------------------------------- /** * Creates a new ScrollableComboBox object. */ public DefaultBindableScrollableComboBox() { super(); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } /** * Creates a new ScrollableComboBox object. * * @param mc DOCUMENT ME! */ public DefaultBindableScrollableComboBox(final MetaClass mc) { super(mc); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } /** * Creates a new ScrollableComboBox object. * * @param comparator DOCUMENT ME! */ public DefaultBindableScrollableComboBox(final Comparator<CidsBean> comparator) { super(comparator); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } /** * Creates a new ScrollableComboBox object. * * @param mc DOCUMENT ME! * @param nullable DOCUMENT ME! * @param onlyUsed DOCUMENT ME! */ public DefaultBindableScrollableComboBox(final MetaClass mc, final boolean nullable, final boolean onlyUsed) { super(mc, nullable, onlyUsed); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } /** * Creates a new ScrollableComboBox object. * * @param mc DOCUMENT ME! * @param nullable DOCUMENT ME! * @param onlyUsed DOCUMENT ME! * @param comparator DOCUMENT ME! */ public DefaultBindableScrollableComboBox(final MetaClass mc, final boolean nullable, final boolean onlyUsed, final Comparator<CidsBean> comparator) { super(mc, nullable, onlyUsed, comparator); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } //~ Methods ---------------------------------------------------------------- @Override public void setUI(final ComboBoxUI ui) { super.setUI(ui); if (getUI() instanceof PlasticComboBoxUI) { setUI(ScrollableComboUI.createUI(null)); } } } /** * DOCUMENT ME! * * @version $Revision$, $Date$ */ class ScrollableComboUI extends PlasticComboBoxUI { //~ Constructors ----------------------------------------------------------- /** * Creates a new ScrollableComboUI object. */ private ScrollableComboUI() { } //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * * @param b DOCUMENT ME! * * @return DOCUMENT ME! */ public static ComponentUI createUI(final JComponent b) { // ensures the invocation of ensurePhantomHasPlasticUI() of the super type; PlasticComboBoxUI.createUI(b); return new ScrollableComboUI(); } @Override protected ComboPopup createPopup() { return new PlasticScrollableComboPopup(comboBox); } //~ Inner Classes ---------------------------------------------------------- /** * Differs from the BasicComboPopup in that it uses the standard popmenu border and honors an optional popup * prototype display value. * * <p>This code was written by Karsten Lentzsch and modified by therter</p> * * @version $Revision$, $Date$ */ private class PlasticScrollableComboPopup extends BasicComboPopup { //~ Constructors ------------------------------------------------------- /** * Creates a new PlasticScrollableComboPopup object. * * @param combo DOCUMENT ME! */ private PlasticScrollableComboPopup(final JComboBox combo) { super(combo); } //~ Methods ------------------------------------------------------------ /** * Configures the list created by #createList(). */ @Override protected void configureList() { super.configureList(); list.setForeground(UIManager.getColor("MenuItem.foreground")); list.setBackground(UIManager.getColor("MenuItem.background")); } @Override protected JScrollPane createScroller() { final JScrollPane sp = new JScrollPane( list, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); return sp; } /** * Configures the JScrollPane created by #createScroller(). */ @Override protected void configureScroller() { super.configureScroller(); scroller.getVerticalScrollBar().putClientProperty( MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE); scroller.getHorizontalScrollBar().putClientProperty( MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE); } /** * Calculates the placement and size of the popup portion of the combo box based on the combo box location and * the enclosing screen bounds. If no transformations are required, then the returned rectangle will have the * same values as the parameters. * * <p>In addition to the superclass behavior, this class offers to use the combo's popup prototype display value * to compute the popup menu width. This is an optional feature of the JGoodies Plastic L&fs implemented via * a client property key.</p> * * <p>If a prototype is set, the popup width is the maximum of the combobox width and the prototype based popup * width. For the latter the renderer is used to render the prototype. The prototype based popup width is the * prototype's width plus the scrollbar width - if any. The scrollbar test checks if there are more items than * the combo's maximum row count.</p> * * @param px starting x location * @param py starting y location * @param pw starting width * @param ph starting height * * @return a rectangle which represents the placement and size of the popup * * @see Options#COMBO_POPUP_PROTOTYPE_DISPLAY_VALUE_KEY * @see JComboBox#getMaximumRowCount() */ @Override protected Rectangle computePopupBounds(final int px, final int py, int pw, final int ph) { final Rectangle defaultBounds = super.computePopupBounds(px, py, pw, ph); final Object popupPrototypeDisplayValue = comboBox.getClientProperty( Options.COMBO_POPUP_PROTOTYPE_DISPLAY_VALUE_KEY); if (popupPrototypeDisplayValue == null) { return defaultBounds; } final ListCellRenderer renderer = list.getCellRenderer(); final Component c = renderer.getListCellRendererComponent( list, popupPrototypeDisplayValue, -1, true, true); pw = c.getPreferredSize().width; final boolean hasVerticalScrollBar = comboBox.getItemCount() > comboBox.getMaximumRowCount(); if (hasVerticalScrollBar) { // Add the scrollbar width. final JScrollBar verticalBar = scroller.getVerticalScrollBar(); pw += verticalBar.getPreferredSize().width; } final Rectangle prototypeBasedBounds = super.computePopupBounds(px, py, pw, ph); return (prototypeBasedBounds.width > defaultBounds.width) ? prototypeBasedBounds : defaultBounds; } } }