package com.jidesoft.plaf.basic;
import com.jidesoft.plaf.UIDefaultsLookup;
import com.jidesoft.swing.JideButton;
import com.jidesoft.swing.JideSwingUtilities;
import javax.swing.*;
import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
public class BasicJideButtonListener extends BasicButtonListener {
private boolean _mouseOver = false;
public BasicJideButtonListener(AbstractButton b) {
super(b);
}
@Override
public void mouseEntered(MouseEvent e) {
AbstractButton b = (AbstractButton) e.getSource();
ButtonModel model = b.getModel();
if (b.isRolloverEnabled()) {
model.setRollover(true);
}
_mouseOver = true;
if (model.isPressed())
model.setArmed(true);
}
@Override
public void propertyChange(PropertyChangeEvent e) {
super.propertyChange(e);
String prop = e.getPropertyName();
if (JideButton.BUTTON_STYLE_PROPERTY.equals(prop)
|| "opaque".equals(prop)
|| AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY.equals(prop)
) {
AbstractButton b = (AbstractButton) e.getSource();
b.repaint();
}
else if (JideButton.PROPERTY_ORIENTATION.equals(prop)
|| "hideActionText".equals(prop)) {
AbstractButton b = (AbstractButton) e.getSource();
b.invalidate();
b.repaint();
}
else if ("verticalTextPosition".equals(prop)
|| "horizontalTextPosition".equals(prop)) {
AbstractButton b = (AbstractButton) e.getSource();
b.updateUI();
}
}
// when on JideButton on popup, mouseReleased is not triggered for some reason.
// So listen to clicked event instead.
// bug at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4991772
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
cancelMenuIfNecessary(e);
}
@Override
public void mouseReleased(MouseEvent e) {
AbstractButton b = (AbstractButton) e.getSource();
ButtonModel model = b.getModel();
if (b.contains(e.getPoint())) {
if (b.isRolloverEnabled()) {
model.setRollover(true);
}
}
if (!_mouseOver) {
// these two lines order matters. In this order, it would not trigger actionPerformed.
model.setArmed(false);
model.setPressed(false);
}
super.mouseReleased(e);
cancelMenuIfNecessary(e);
}
/**
* Cancel the menu if this button is on JPopupMenu.
*
* @param e the mouse event.
*/
private void cancelMenuIfNecessary(MouseEvent e) {
AbstractButton b = (AbstractButton) e.getSource();
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
MenuElement[] menuElements = manager.getSelectedPath();
for (int i = menuElements.length - 1; i >= 0; i--) {
MenuElement menuElement = menuElements[i];
if (menuElement instanceof JPopupMenu && ((JPopupMenu) menuElement).isAncestorOf(b)) {
b.getModel().setPressed(false);
b.getModel().setArmed(false);
b.getModel().setRollover(false);
if (!Boolean.FALSE.equals(b.getClientProperty(JideButton.CLIENT_PROPERTY_HIDE_POPUPMENU))) {
manager.clearSelectedPath();
}
break;
}
}
}
@Override
public void mouseExited(MouseEvent e) {
AbstractButton b = (AbstractButton) e.getSource();
ButtonModel model = b.getModel();
if (b.isRolloverEnabled()) {
model.setRollover(false);
}
model.setArmed(false);
_mouseOver = false;
}
/**
* Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW UI InputMap.
*
* @param b the button.
*/
void updateMnemonicBinding(AbstractButton b) {
int m = b.getMnemonic();
if (m != 0) {
InputMap map = SwingUtilities.getUIInputMap(
b, JComponent.WHEN_IN_FOCUSED_WINDOW);
if (map == null) {
map = new ComponentInputMapUIResource(b);
SwingUtilities.replaceUIInputMap(b,
JComponent.WHEN_IN_FOCUSED_WINDOW, map);
}
map.clear();
map.put(KeyStroke.getKeyStroke(m, JideSwingUtilities.getFocusAcceleratorKeyMask(), false),
"pressed");
map.put(KeyStroke.getKeyStroke(m, JideSwingUtilities.getFocusAcceleratorKeyMask(), true),
"released");
map.put(KeyStroke.getKeyStroke(m, 0, true), "released");
}
else {
InputMap map = SwingUtilities.getUIInputMap(b, JComponent.
WHEN_IN_FOCUSED_WINDOW);
if (map != null) {
map.clear();
}
}
}
/**
* Returns the ui that is of type <code>clazz</code>, or null if one can not be found.
*
* @param ui the ComponentUI
* @param clazz the class
* @return the UI of the ComponentUI if it is an instance of the type.
*/
static Object getUIOfType(ComponentUI ui, Class clazz) {
if (clazz.isInstance(ui)) {
return ui;
}
return null;
}
/**
* Returns the InputMap for condition <code>condition</code>. Called as part of
* <code>installKeyboardActions</code>.
*
* @param condition the condition.
* @param c the component
* @return the InputMap on the component for the condition.
*/
public InputMap getInputMap(int condition, JComponent c) {
if (condition == JComponent.WHEN_FOCUSED) {
BasicJideButtonUI ui = (BasicJideButtonUI) getUIOfType(
((AbstractButton) c).getUI(), BasicJideButtonUI.class);
if (ui != null) {
return (InputMap) UIDefaultsLookup.get(ui.getPropertyPrefix() + "focusInputMap");
}
}
return null;
}
/**
* Actions for Buttons. Two type of action are supported: pressed: Moves the button to a pressed state released:
* Disarms the button.
*/
private static class Actions extends UIAction {
private static final String PRESS = "pressed";
private static final String RELEASE = "released";
Actions(String name) {
super(name);
}
public void actionPerformed(ActionEvent e) {
AbstractButton b = (AbstractButton) e.getSource();
String key = getName();
if (PRESS.equals(key)) {
ButtonModel model = b.getModel();
model.setArmed(true);
model.setPressed(true);
if (!b.hasFocus() && b.isRequestFocusEnabled()) {
b.requestFocus();
}
}
else if (RELEASE.equals(key)) {
ButtonModel model = b.getModel();
model.setPressed(false);
model.setArmed(false);
}
}
@Override
public boolean isEnabled(Object sender) {
return !(sender != null && (sender instanceof AbstractButton) &&
!((AbstractButton) sender).getModel().isEnabled());
}
}
/**
* Populates Buttons actions.
*
* @param map the action map.
*/
public static void loadActionMap(LazyActionMap map) {
map.put(new Actions(Actions.PRESS));
map.put(new Actions(Actions.RELEASE));
}
@Override
public void installKeyboardActions(JComponent c) {
AbstractButton b = (AbstractButton) c;
// Update the mnemonic binding.
updateMnemonicBinding(b);
LazyActionMap.installLazyActionMap(c, BasicJideButtonListener.class,
"JideButton.actionMap");
InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c);
SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km);
}
}