package com.onaro.util.jfc.mixedvalue; import static com.onaro.util.jfc.mixedvalue.MixedValueConstants.MIXED_VALUE; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.UIManager; import org.apache.commons.lang3.StringUtils; /** * An extension to {@link JComboBox} allowing for a special "mixed" valued. Used when editing multiple values which are * not the same, though the user can set all of them to the same value selected from the list. *

* Once the user clics on the field, the mixed mode, if set, is reset and the value clears and a value is selected. */ public class MixedComboBox extends JComboBox { private static final long serialVersionUID = 1L; /** * Tells if the current value is this special "mixed". */ private boolean mixed; /** * Font to use for the special "mixed" value. */ private Font italicFont; /** * Standard font to use for any value but the special "mixed" value. */ private Font plainFont; /** * Initializes this mixed-value combo-box field. Records the default fonts. Registers the listeners that will * clear the "mixed mode" once the user clicks on the field. * @param items the values from which the user can select */ public MixedComboBox(final Object items[]) { this(new DefaultComboBoxModel(items)); } /** * Initializes this mixed-value combo-box field. Records the default fonts. Registers the listeners that will * clear the "mixed mode" once the user clicks on the field. * @param aModel the model for this combo-box */ public MixedComboBox(ComboBoxModel aModel) { super(aModel); italicFont = getFont().deriveFont(Font.ITALIC); plainFont = getFont().deriveFont(Font.PLAIN); addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (getSelectedIndex() >= 0) { setMixed(false); } } }); } public void reset() { // set the current selected item. selectedItemReminder = dataModel.getSelectedItem(); } /** * Sets the mixed mode of this field. When set to true, the field will show "mixed" in italic, blue font. * @param mixed true if the field should enter the "mixed mode" */ public void setMixed(boolean mixed) { if (this.mixed != mixed) { this.mixed = mixed; if (mixed) setSelectedIndex(-1); } } /** * Tells if the field is currently in "mixed mode". * @return true if the field is in "mixed mode" */ public boolean isMixed() { return mixed; } protected boolean isDontCare(Object value){ return value == null; } /** * Override the original method to guarantee enough space for all values. * @return */ public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); size.setSize(size.getWidth()+10,size.getHeight()); return size; } public void setRenderer(ListCellRenderer renderer) { super.setRenderer(new MixedCellRenderer(renderer)); } private class MixedCellRenderer implements ListCellRenderer { ListCellRenderer encapsulatedRenderer; public MixedCellRenderer(ListCellRenderer encapsulatedRenderer) { this.encapsulatedRenderer = encapsulatedRenderer; } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { /** * Render "DONT_CARE" as blank. */ if (isDontCare(value)) value = StringUtils.EMPTY; /** * Render "MIXED" as blue italic */ if(isMixed() && index < 0) { list.setForeground(UIManager.getColor("mixedValue.color")); //$NON-NLS-1$ list.setFont(italicFont); value = MIXED_VALUE; }else{ list.setForeground(Color.BLACK); list.setFont(plainFont); } return encapsulatedRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } } }