package org.javabuilders.swing.handler.property;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ActionMap;
import javax.swing.ComponentInputMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ActionMapUIResource;
import org.javabuilders.BuildException;
import org.javabuilders.BuildProcess;
import org.javabuilders.BuilderConfig;
import org.javabuilders.Node;
import org.javabuilders.handler.AbstractPropertyHandler;
import org.javabuilders.swing.SwingJavaBuilderUtils;
import org.javabuilders.swing.SwingJavaBuilderUtils.ActionDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Text handler for all buttons (takes care of mnemonics and acelerators as well)
* @author Jacek Furmankiewicz
*
*/
public class AbstractButtonTextHandler extends AbstractPropertyHandler {
private static final Logger LOG = LoggerFactory.getLogger(AbstractButtonTextHandler.class);
public static final String TEXT = "text";
public AbstractButtonTextHandler() {
super(TEXT);
}
/* (non-Javadoc)
* @see org.javabuilders.handler.IPropertyHandler#handle(org.javabuilders.BuilderConfig, org.javabuilders.BuildProcess, org.javabuilders.Node, java.lang.String)
*/
@SuppressWarnings("serial")
public void handle(BuilderConfig config, BuildProcess process, Node node, String key) throws BuildException {
String text = String.valueOf(node.getProperties().get(key));
final AbstractButton button = (AbstractButton)node.getMainObject();
ActionDefinition def = SwingJavaBuilderUtils.getActionDefintion(text);
button.setText(def.getText());
if (def.getMnemonic() != null) {
button.setMnemonic(def.getMnemonic());
}
//accelerators can be called on JMenuItems only, but on JMenu (throws Swing exception)
if (def.getAccelerator() != null) {
if (button instanceof JMenuItem && !(button instanceof JMenu)) {
JMenuItem menuItem = (JMenuItem) button;
menuItem.setAccelerator(def.getAccelerator());
} else {
//special logic to support accelerator on JButton (issue 86)
if (button instanceof JButton) {
InputMap keyMap = new ComponentInputMap(button);
keyMap.put(def.getAccelerator(), "action");
ActionMap actionMap = new ActionMapUIResource();
actionMap.put("action", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
ActionEvent evt = new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "action");
//fire event listeners
if (button.getActionListeners() != null) {
for(ActionListener listener : button.getActionListeners()) {
listener.actionPerformed(evt);
}
}
//handle existing defined action
if (button.getAction() != null && !button.getAction().equals(this)) {
button.getAction().actionPerformed(evt);
}
}
});
SwingUtilities.replaceUIActionMap(button, actionMap);
SwingUtilities.replaceUIInputMap(button, JComponent.WHEN_IN_FOCUSED_WINDOW, keyMap);
//add accelerator info to tooltip if not used
if (button.getToolTipText() == null || button.getToolTipText().length() == 0) {
button.setToolTipText(def.getAcceleratorText());
}
} else {
LOG.warn("Ignored accelerator: can only be set on JMenuItem(s) or JButton(s): " + text);
}
}
}
}
}