package org.freeplane.plugin.workspace.components.menu;
import java.util.Stack;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.tree.TreePath;
import org.freeplane.core.ui.AFreeplaneAction;
import org.freeplane.core.ui.SelectableAction;
import org.freeplane.core.ui.components.JAutoCheckBoxMenuItem;
import org.freeplane.core.ui.components.JFreeplaneMenuItem;
import org.freeplane.features.mode.Controller;
import org.freeplane.plugin.workspace.WorkspaceUtils;
import org.freeplane.plugin.workspace.actions.AWorkspaceAction;
import org.freeplane.plugin.workspace.model.AWorkspaceTreeNode;
public class WorkspacePopupMenuBuilder {
public static final String SEPARATOR = "-----";
public WorkspacePopupMenuBuilder() {
}
public static void addAction(final JComponent popupMenu, AFreeplaneAction action) {
assert action != null;
assert popupMenu != null;
final JMenuItem item;
if (action.getClass().getAnnotation(SelectableAction.class) != null) {
item = new JAutoCheckBoxMenuItem(action);
}
else {
item = new JFreeplaneMenuItem(action);
}
popupMenu.add(item);
return;
}
public static void insertAction(final WorkspacePopupMenu popupMenu, AFreeplaneAction action, int index) {
assert action != null;
assert popupMenu != null;
final JMenuItem item;
if (action.getClass().getAnnotation(SelectableAction.class) != null) {
item = new JAutoCheckBoxMenuItem(action);
}
else {
item = new JFreeplaneMenuItem(action);
}
popupMenu.add(item, index);
addListeners(popupMenu, action);
return;
}
public static void insertAction(final WorkspacePopupMenu popupMenu, String actionKey, int index) {
assert actionKey != null;
assert popupMenu != null;
if(actionKey.equals(SEPARATOR)) {
popupMenu.add(new JPopupMenu.Separator(), index);
}
else {
AFreeplaneAction action = Controller.getCurrentController().getAction(actionKey);
if(action == null) {
return;
}
final JMenuItem item;
if (action.getClass().getAnnotation(SelectableAction.class) != null) {
item = new JAutoCheckBoxMenuItem(action);
}
else {
item = new JFreeplaneMenuItem(action);
}
popupMenu.add(item, index);
addListeners(popupMenu, action);
}
return;
}
public static void addActions(final WorkspacePopupMenu popupMenu, final String[] keys) {
assert popupMenu != null;
assert keys != null;
Stack<JMenu> subMenuStack = new Stack<JMenu>();
for(String key : keys) {
if(key == null) {
continue;
}
else
if(key.equals(SEPARATOR)) {
if(subMenuStack.size() == 0) {
popupMenu.addSeparator();
}
else {
subMenuStack.peek().addSeparator();
}
}
else if(key.startsWith("beginSubMenu")) {
String popupName = key.substring("beginSubMenu".length());
JMenu subMenu = new JMenu(popupName);
(subMenuStack.size() == 0 ? popupMenu : subMenuStack.peek()).add(subMenu);
subMenuStack.push(subMenu);
}
else if(key.equals("endSubMenu")) {
subMenuStack.pop();
}
else {
AFreeplaneAction action = Controller.getCurrentController().getAction(key);
if(action == null) {
continue;
}
addAction(popupMenu, subMenuStack.size() == 0 ? popupMenu : subMenuStack.peek(), action);
}
}
}
private static void addAction(WorkspacePopupMenu popupMenu, JComponent jComponent, AFreeplaneAction action) {
addAction(jComponent, action);
addListeners(popupMenu, action);
}
public static String createSubMenu(String name) {
return "beginSubMenu"+name;
}
public static String endSubMenu() {
return "endSubMenu";
}
private static void addListeners(final WorkspacePopupMenu popupMenu, final AFreeplaneAction action) {
if (action instanceof PopupMenuListener) {
popupMenu.addPopupMenuListener(new DelegatingPopupMenuListener((PopupMenuListener) action, popupMenu));
}
if (AFreeplaneAction.checkSelectionOnPopup(action)) {
popupMenu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuCanceled(final PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) {
}
public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
if(action instanceof AWorkspaceAction && e.getSource() instanceof WorkspacePopupMenu) {
WorkspacePopupMenu menu = ((WorkspacePopupMenu)e.getSource());
AWorkspaceTreeNode node = (AWorkspaceTreeNode) ((JTree)menu.getInvoker()).getPathForLocation(menu.getInvokerLocation().x, menu.getInvokerLocation().y).getLastPathComponent();
((AWorkspaceAction) action).setSelectedFor(node);
}
else {
action.setSelected();
}
}
});
}
if (AFreeplaneAction.checkEnabledOnPopup(action)) {
popupMenu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuCanceled(final PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) {
}
public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
if(action instanceof AWorkspaceAction && e.getSource() instanceof WorkspacePopupMenu) {
WorkspacePopupMenu menu = ((WorkspacePopupMenu)e.getSource());
TreePath path = ((JTree)menu.getInvoker()).getPathForLocation(menu.getInvokerLocation().x, menu.getInvokerLocation().y);
if(path != null) {
AWorkspaceTreeNode node = (AWorkspaceTreeNode) path.getLastPathComponent();
((AWorkspaceAction) action).setEnabledFor(node);
} else {
((AWorkspaceAction) action).setEnabledFor((AWorkspaceTreeNode) WorkspaceUtils.getModel().getRoot());
}
}
else {
action.setEnabled();
}
}
});
}
}
static private class DelegatingPopupMenuListener implements PopupMenuListener {
final private PopupMenuListener listener;
final private Object source;
public DelegatingPopupMenuListener(final PopupMenuListener listener, final Object source) {
super();
this.listener = listener;
this.source = source;
}
public Object getSource() {
return source;
}
private PopupMenuEvent newEvent() {
return new PopupMenuEvent(getSource());
}
public void popupMenuCanceled(final PopupMenuEvent e) {
listener.popupMenuCanceled(newEvent());
}
public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) {
listener.popupMenuWillBecomeInvisible(newEvent());
}
public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
listener.popupMenuWillBecomeVisible(newEvent());
}
}
}