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); } }