public interface MenuElement {
public Component getComponent();
public MenuElement[] getSubElements();
public void menuSelectionChanged(boolean isInclude);
public void processKeyEvent(KeyEvent event, MenuElement path[], MenuSelectionManager mgr);
public void processMouseEvent(MouseEvent event, MenuElement path[], MenuSelectionManager mgr);
}
import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import javax.swing.ButtonModel;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JToggleButton;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.event.MouseInputListener;
class JToggleButtonMenuItem extends JToggleButton implements MenuElement {
Color savedForeground = null;
private static MenuElement NO_SUB_ELEMENTS[] = new MenuElement[0];
public JToggleButtonMenuItem(String label) {
super(label);
init();
}
private void init() {
updateUI();
setRequestFocusEnabled(false);
// Borrows heavily from BasicMenuUI
MouseInputListener mouseInputListener = new MouseInputListener() {
// If mouse released over this menu item, activate it
public void mouseReleased(MouseEvent mouseEvent) {
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
Point point = mouseEvent.getPoint();
if ((point.x >= 0) && (point.x < getWidth()) && (point.y >= 0) && (point.y < getHeight())) {
menuSelectionManager.clearSelectedPath();
// Component automatically handles "selection" at this point
// doClick(0); // not necessary
} else {
menuSelectionManager.processMouseEvent(mouseEvent);
}
}
// If mouse moves over menu item, add to selection path, so it becomes
// armed
public void mouseEntered(MouseEvent mouseEvent) {
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
menuSelectionManager.setSelectedPath(getPath());
}
// When mouse moves away from menu item, disarm it and select something
// else
public void mouseExited(MouseEvent mouseEvent) {
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
MenuElement path[] = menuSelectionManager.getSelectedPath();
if (path.length > 1) {
MenuElement newPath[] = new MenuElement[path.length - 1];
for (int i = 0, c = path.length - 1; i < c; i++) {
newPath[i] = path[i];
}
menuSelectionManager.setSelectedPath(newPath);
}
}
// Pass along drag events
public void mouseDragged(MouseEvent mouseEvent) {
MenuSelectionManager.defaultManager().processMouseEvent(mouseEvent);
}
public void mouseClicked(MouseEvent mouseEvent) {
}
public void mousePressed(MouseEvent mouseEvent) {
}
public void mouseMoved(MouseEvent mouseEvent) {
}
};
addMouseListener(mouseInputListener);
addMouseMotionListener(mouseInputListener);
}
// MenuElement methods
public Component getComponent() {
return this;
}
public MenuElement[] getSubElements() {
// No subelements
return NO_SUB_ELEMENTS;
}
public void menuSelectionChanged(boolean isIncluded) {
ButtonModel model = getModel();
// Only change armed state if different
if (model.isArmed() != isIncluded) {
model.setArmed(isIncluded);
}
if (isIncluded) {
savedForeground = getForeground();
if (!savedForeground.equals(Color.BLUE)) {
setForeground(Color.BLUE);
} else {
// In case foreground blue, use something different
setForeground(Color.RED);
}
} else {
setForeground(savedForeground);
// If null, get foreground from installed look and feel
if (savedForeground == null) {
updateUI();
}
}
}
public void processKeyEvent(KeyEvent keyEvent, MenuElement path[], MenuSelectionManager manager) {
// If user presses space while menu item armed, select it
if (getModel().isArmed()) {
int keyChar = keyEvent.getKeyChar();
if (keyChar == KeyEvent.VK_SPACE) {
manager.clearSelectedPath();
System.out.println("Selected: JToggleButtonMenuItem, by KeyEvent");
doClick(0); // inherited from AbstractButton
}
}
}
public void processMouseEvent(MouseEvent mouseEvent, MenuElement path[],
MenuSelectionManager manager) {
// For when mouse dragged over menu and button released
if (mouseEvent.getID() == MouseEvent.MOUSE_RELEASED) {
manager.clearSelectedPath();
System.out.println("Selected: JToggleButtonMenuItem, by MouseEvent");
doClick(0); // inherited from AbstractButton
}
}
// Borrows heavily from BasicMenuItemUI.getPath()
private MenuElement[] getPath() {
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
MenuElement oldPath[] = menuSelectionManager.getSelectedPath();
MenuElement newPath[];
int oldPathLength = oldPath.length;
if (oldPathLength == 0)
return new MenuElement[0];
Component parent = getParent();
if (oldPath[oldPathLength - 1].getComponent() == parent) {
// Going deeper under the parent menu
newPath = new MenuElement[oldPathLength + 1];
System.arraycopy(oldPath, 0, newPath, 0, oldPathLength);
newPath[oldPathLength] = this;
} else {
// Sibling/child menu item currently selected
int newPathPosition;
for (newPathPosition = oldPath.length - 1; newPathPosition >= 0; newPathPosition--) {
if (oldPath[newPathPosition].getComponent() == parent) {
break;
}
}
newPath = new MenuElement[newPathPosition + 2];
System.arraycopy(oldPath, 0, newPath, 0, newPathPosition + 1);
newPath[newPathPosition + 1] = this;
}
return newPath;
}
}
public class JToggleButtonMenuItemDemo {
public static void main(final String args[]) {
JFrame frame = new JFrame("MenuSample Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
// File Menu, F - Mnemonic
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
menuBar.add(fileMenu);
// File->New, N - Mnemonic
JToggleButtonMenuItem newMenuItem = new JToggleButtonMenuItem("New");
fileMenu.add(newMenuItem);
frame.setJMenuBar(menuBar);
frame.setSize(350, 250);
frame.setVisible(true);
}
}