/**
*
*/
package javax.swing.origamist;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.DefaultButtonModel;
import javax.swing.Icon;
/**
* A dropdown button that can contain some buttons that belong to a specified {@link BoundButtonGroup}. If a button from
* the button group gets selected, the dropdown's main button will display the selected button's text and icon and it
* will be set pressed. If the group's selection isn't a button from this dropdown, the dropdown will display a default
* text and icon.
*
* The display of the text and icon of the selected subitem is performed via a bound property listener, so the main
* button's values will change together with the selected button's values.
*
* @author Martin Pecka
*/
public class JDropDownButtonReflectingSelectionGroup extends JDropDownButton
{
/** */
private static final long serialVersionUID = -8836179816349374400L;
/** The button group this dropdown will reflect. */
protected BoundButtonGroup group;
/** The listener that will listen to the <code>selection</code> property of the group. */
protected PropertyChangeListener listener;
/** The listener that will listen to the <code>text</code> and <code>icon</code> properties of the selected button. */
protected PropertyChangeListener buttonValueListener;
/** The currently selected button in the group, if it is contained in this button's popup. */
protected AbstractButton selection = null;
/** The default text of the button. */
protected String text = "";
/** The default tooltip of the button. */
protected String tooltip = "";
/** The default icon. */
protected Icon icon = null;
/** The default mnemonic. */
protected int mnemonic = 0;
/** The model to be used for main button. */
protected DefaultButtonModel selectedModel = null;
/**
* @param mainButton
* @param group The button group this dropdown will reflect.
*/
public JDropDownButtonReflectingSelectionGroup(AbstractButton mainButton, BoundButtonGroup group)
{
super(mainButton);
setGroup(group);
}
/**
* @param icon
* @param size
* @param group The button group this dropdown will reflect.
*/
public JDropDownButtonReflectingSelectionGroup(Icon icon, Dimension size, BoundButtonGroup group)
{
super(icon, size);
setGroup(group);
}
/**
* @param icon
* @param group The button group this dropdown will reflect.
*/
public JDropDownButtonReflectingSelectionGroup(Icon icon, BoundButtonGroup group)
{
super(icon);
setGroup(group);
}
/**
* @param mainButton
* @param arrowButton
* @param group The button group this dropdown will reflect.
*/
public JDropDownButtonReflectingSelectionGroup(JRolloverButton mainButton, JRolloverButton arrowButton,
BoundButtonGroup group)
{
super(mainButton, arrowButton);
setGroup(group);
}
/**
* @param mainButton
* @param group The button group this dropdown will reflect.
*/
public JDropDownButtonReflectingSelectionGroup(JRolloverButton mainButton, BoundButtonGroup group)
{
super(mainButton);
setGroup(group);
}
@Override
protected void init()
{
super.init();
selectedModel = new DefaultButtonModel() {
/** */
private static final long serialVersionUID = 3516987790537298167L;
@Override
public boolean isArmed()
{
if (selection != null)
return true;
else
return super.isArmed();
}
@Override
public boolean isPressed()
{
if (selection != null)
return true;
else
return super.isPressed();
}
};
mainButton.setModel(selectedModel);
mainButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e)
{
// because Swing doesn't fire a button's action if it is clicked and already is "pressed" before the
// click, we need to simulate the button's action manually
mainButton.getAction().actionPerformed(new ActionEvent(e.getSource(), e.getID(), "click"));
}
});
buttonValueListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if (!AbstractButton.TEXT_CHANGED_PROPERTY.equals(evt.getPropertyName())
&& !AbstractButton.ICON_CHANGED_PROPERTY.equals(evt.getPropertyName()))
return;
configureMainButtonFromSubItem((AbstractButton) evt.getSource());
}
};
listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if (!"selection".equals(evt.getPropertyName()))
return;
if (group == null) // shouldn't happen, but for sure
return;
ButtonModel oldSelection = (ButtonModel) evt.getOldValue();
ButtonModel newSelection = (ButtonModel) evt.getNewValue();
AbstractButton oldBtn = group.getButtonForModel(oldSelection);
AbstractButton newBtn = group.getButtonForModel(newSelection);
// if popup doesn't contain the new button, then we want this to behave as if nothing was selected
if (!popup.isAncestorOf(newBtn))
newBtn = null;
if (oldSelection == newSelection)
return;
selection = newBtn;
if (oldBtn != null) {
oldBtn.removePropertyChangeListener(buttonValueListener);
}
if (newBtn != null) {
newBtn.addPropertyChangeListener(AbstractButton.TEXT_CHANGED_PROPERTY, buttonValueListener);
newBtn.addPropertyChangeListener(AbstractButton.ICON_CHANGED_PROPERTY, buttonValueListener);
configureMainButtonFromSubItem(newBtn);
} else if (oldBtn != null) {
configureMainButtonToDefault();
}
}
};
}
/**
* Set the main button's values from the item's values.
*
* @param item The source of values.
*/
protected void configureMainButtonFromSubItem(AbstractButton item)
{
mainButton.setText(item.getText());
mainButton.setIcon(item.getIcon());
mainButton.setToolTipText(item.getToolTipText());
mainButton.setMnemonic(item.getMnemonic());
invalidate();
repaint();
}
/**
* Set the default values to the main button.
*/
protected void configureMainButtonToDefault()
{
mainButton.setText(text);
mainButton.setIcon(icon);
mainButton.setToolTipText(tooltip);
mainButton.setMnemonic(mnemonic);
invalidate();
repaint();
}
/**
* @return The button group this dropdown will reflect.
*/
public BoundButtonGroup getGroup()
{
return group;
}
/**
* @param group The button group this dropdown will reflect.
*/
public void setGroup(BoundButtonGroup group)
{
if (group == this.group)
return;
selection = null;
if (this.group != null)
this.group.removePropertyChangeListener(listener);
this.group = group;
if (group != null)
group.addPropertyChangeListener("selection", listener);
}
@Override
public void setText(String text)
{
super.setText(text);
this.text = text;
}
@Override
public void setIcon(Icon defaultIcon)
{
super.setIcon(defaultIcon);
this.icon = defaultIcon;
}
@Override
public void setToolTipText(String text)
{
super.setToolTipText(text);
tooltip = text;
}
@Override
public void setMnemonic(int mnemonic)
{
super.setMnemonic(mnemonic);
this.mnemonic = mnemonic;
}
}