/*
* @(#)ContextualMenuHelper.java
*
* $Date: 2015-05-30 18:43:22 -0700 (Sat, 30 May 2015) $
*
* Copyright (c) 2013 by Jeremy Wood.
* All rights reserved.
*
* The copyright of this software is owned by Jeremy Wood.
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* Jeremy Wood. For details see accompanying license terms.
*
* This software is probably, but not necessarily, discussed here:
* https://javagraphics.java.net/
*
* That site should also contain the most recent official version
* of this software. (See the SVN repository for more details.)
*/
package com.bric.swing;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;
import com.bric.util.BooleanProperty;
import com.bric.util.EnumProperty;
public class ContextualMenuHelper {
private static final String MENU_KEY = ContextualMenuHelper.class.getName()+".menuKey";
/** Add a menu item that invokes the argument Runnable when selected.
* @param runnable this is invoked (via SwingUtilities.invokeLater()) when this menu
* item is selected.
*/
public static void add(JComponent jc,String menuItemName,Runnable runnable) {
ContextualMenuHelper cmh = getContextualMenuHelper(jc);
cmh.add(menuItemName, runnable);
}
private static ContextualMenuHelper getContextualMenuHelper(JComponent jc) {
ContextualMenuHelper cmh = (ContextualMenuHelper)jc.getClientProperty(MENU_KEY);
if(cmh==null) {
cmh = new ContextualMenuHelper(jc);
jc.putClientProperty(MENU_KEY, cmh);
}
return cmh;
}
/** Add a checkbox menu item to control a BooleanProperty.
* @param runnable this is invoked (via SwingUtilities.invokeLater()) when this menu
* item is selected.
*/
public static void addToggle(JComponent jc,BooleanProperty property,Runnable runnable) {
ContextualMenuHelper cmh = getContextualMenuHelper(jc);
cmh.addToggle(property, runnable);
}
/** Add a submenu that offers a choice of radiobutton menu items
* to control an EnumProperty.
* @param runnable this is invoked (via SwingUtilities.invokeLater()) when any
* choice is selected.
*/
public static void addPopupMenu(String popupName,JComponent jc,EnumProperty<?> property,Runnable runnable) {
ContextualMenuHelper cmh = getContextualMenuHelper(jc);
cmh.addPopupMenu(popupName, property, runnable);
}
public ContextualMenuHelper() {}
public ContextualMenuHelper(JComponent jc) {
addComponent(jc);
}
public void addComponent(JComponent jc) {
jc.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
showPopupMenu(e);
}
@Override
public void mousePressed(MouseEvent e) {
showPopupMenu(e);
}
@Override
public void mouseReleased(MouseEvent e) {
showPopupMenu(e);
}
private void showPopupMenu(final MouseEvent e) {
if(!e.isPopupTrigger())
return;
e.consume();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showPopup(e.getComponent(), e.getX(), e.getY());
}
});
}
});
jc.putClientProperty(MENU_KEY, this);
}
JPopupMenu popup = new JPopupMenu();
public void add(String menuItemName,final Runnable runnable) {
JMenuItem menuItem = new JMenuItem(menuItemName);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(runnable);
}
});
popup.add(menuItem);
}
public void addToggle(final BooleanProperty property,final Runnable runnable) {
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(property.getName());
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
property.setValue(menuItem.isSelected());
SwingUtilities.invokeLater(runnable);
}
});
property.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuItem.setSelected(property.getValue());
}
});
SwingUtilities.invokeLater(runnable);
}
});
popup.add(menuItem);
}
public void addPopupMenu(String popupName,final EnumProperty property,final Runnable runnable) {
Object[] values = property.getValues();
JMenu myPopup = new JMenu(popupName);
for(int a = 0; a<values.length; a++) {
final Object currentValue = values[a];
final JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(currentValue.toString());
myPopup.add(menuItem);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
property.setValue(currentValue);
SwingUtilities.invokeLater(runnable);
}
});
property.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuItem.setSelected(currentValue.equals(property.getValue()));
}
});
SwingUtilities.invokeLater(runnable);
}
});
menuItem.setSelected(currentValue.equals(property.getValue()));
}
popup.add(myPopup);
}
protected void showPopup(Component c,int x,int y) {
popup.show(c, x, y);
}
/** Clear any registered contextual menu information for this component.
*
* @param component the component to purge all contextual menu info for.
*/
public static void clear(JComponent component) {
ContextualMenuHelper cmh = (ContextualMenuHelper)component.getClientProperty(MENU_KEY);
if(cmh==null) return;
cmh.popup.removeAll();
}
}