This repository has been archived on 2021-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
envoy/src/main/java/envoy/client/ui/ContextMenu.java

199 lines
6.6 KiB
Java

package envoy.client.ui;
import java.awt.Component;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
/**
* This class defines a menu that will be automatically called if
* {@link MouseEvent#isPopupTrigger()} returns true for the parent component.
* The user has the possibility to directly add actions to be performed when
* clicking on the element with the selected String. Additionally, for each
* element an {@link Icon} can be added, but it must not be.
* If the key(text) of an element starts with one of the predefined values, a
* special component will be called: either a {@link JRadioButtonMenuItem}, a
* {@link JCheckBoxMenuItem} or a {@link JMenu} will be created.<br>
* <br>
* Project: <strong>envoy-client</strong><br>
* File: <strong>ContextMenu.java</strong><br>
* Created: <strong>17 Mar 2020</strong><br>
*
* @author Leon Hofmeister
* @since Envoy Client v0.1-beta
*/
public class ContextMenu extends JPopupMenu {
private static final long serialVersionUID = 0L;
/**
* If a key starts with this String, a {@link JCheckBoxMenuItem} will be created
*/
public static final String checkboxMenuItem = "ChBoMI";
/**
* If a key starts with this String, a {@link JRadioButtonMenuItem} will be
* created
*/
public static final String radioButtonMenuItem = "RaBuMI";
/**
* If a key starts with this String, a {@link JMenu} will be created
*/
public static final String subMenuItem = "SubMI";
private Map<String, ActionListener> items = new HashMap<>();
private Map<String, Icon> icons = new HashMap<>();
private Map<String, Integer> mnemonics = new HashMap<>();
private ButtonGroup radioButtonGroup = new ButtonGroup();
private boolean built = false;
/**
* @param parent the component which will call this
* {@link ContextMenu}
* @since Envoy Client v0.1-beta
*/
public ContextMenu(Component parent) { setInvoker(parent); }
/**
* @param label the string that a UI may use to display as a title
* for the pop-up menu
* @param parent the component which will call this
* {@link ContextMenu}
* @param itemsWithActions a map of all strings to be displayed with according
* actions
* @param itemIcons the icons to be displayed before a name, if wanted.
* Only keys in here will have an Icon displayed. More
* precisely, all keys here not included in the first
* map will be thrown out.
* @param itemMnemonics the keyboard shortcuts that need to be pressed to
* automatically execute the {@link JMenuItem} with the
* given text
* @since Envoy Client v0.1-beta
*/
public ContextMenu(String label, Component parent, Map<String, ActionListener> itemsWithActions, Map<String, Icon> itemIcons,
Map<String, Integer> itemMnemonics) {
super(label);
setInvoker(parent);
this.items = (itemsWithActions != null) ? itemsWithActions : items;
this.icons = (itemIcons != null) ? itemIcons : icons;
this.mnemonics = (itemMnemonics != null) ? itemMnemonics : mnemonics;
}
/**
* Prepares the PopupMenu to be displayed. Should only be used once all map
* values have been set.
*
* @return this instance of {@link ContextMenu} to allow chaining behind the
* constructor
* @since Envoy Client v0.1-beta
*/
public ContextMenu build() {
items.forEach((text, action) -> {
// case radio button wanted
AbstractButton item;
if (text.startsWith(radioButtonMenuItem)) {
item = new JRadioButtonMenuItem(text.substring(radioButtonMenuItem.length()), icons.containsKey(text) ? icons.get(text) : null);
radioButtonGroup.add(item);
// case check box wanted
} else if (text.startsWith(checkboxMenuItem))
item = new JCheckBoxMenuItem(text.substring(checkboxMenuItem.length()), icons.containsKey(text) ? icons.get(text) : null);
// case sub-menu wanted
else if (text.startsWith(subMenuItem)) item = new JMenu(text.substring(subMenuItem.length()));
else // normal JMenuItem wanted
item = new JMenuItem(text, icons.containsKey(text) ? icons.get(text) : null);
item.addActionListener(action);
if (mnemonics.containsKey(text)) item.setMnemonic(mnemonics.get(text));
add(item);
});
if (getInvoker() != null) {
getInvoker().addMouseListener(getShowingListener());
built = true;
}
return this;
}
/**
* @param label the string that a UI may use to display as a title for the
* pop-up menu.
* @since Envoy Client v0.1-beta
*/
public ContextMenu(String label) { super(label); }
private MouseAdapter getShowingListener() {
return new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) { action(e); }
@Override
public void mousePressed(MouseEvent e) { action(e); }
@Override
public void mouseReleased(MouseEvent e) { action(e); }
private void action(MouseEvent e) {
if (!built) build();
if (e.isPopupTrigger()) // hides the menu if already visible
if (!isVisible()) show(e.getComponent(), e.getX(), e.getY());
else setVisible(false);
}
};
}
/**
* Removes all subcomponents of this menu.
*
* @since Envoy Client v0.1-beta
*/
public void clear() {
removeAll();
items = new HashMap<>();
icons = new HashMap<>();
mnemonics = new HashMap<>();
}
/**
* @return the items
* @since Envoy Client v0.1-beta
*/
public Map<String, ActionListener> getItems() { return items; }
/**
* @param items the items with the displayed text and the according action to
* take once called
* @since Envoy Client v0.1-beta
*/
public void setItems(Map<String, ActionListener> items) { this.items = items; }
/**
* @return the icons
* @since Envoy Client v0.1-beta
*/
public Map<String, Icon> getIcons() { return icons; }
/**
* @param icons the icons to set
* @since Envoy Client v0.1-beta
*/
public void setIcons(Map<String, Icon> icons) { this.icons = icons; }
/**
* @return the mnemonics (the keyboard shortcuts that automatically execute the
* command for a {@link JMenuItem} with corresponding text)
* @since Envoy Client v0.1-beta
*/
public Map<String, Integer> getMnemonics() { return mnemonics; }
/**
* @param mnemonics the keyboard shortcuts that need to be pressed to
* automatically execute the {@link JMenuItem} with the given
* text
* @since Envoy Client v0.1-beta
*/
public void setMnemonics(Map<String, Integer> mnemonics) { this.mnemonics = mnemonics; }
}