/*
* Copyright (C) 2012 Jason Gedge <http://www.gedge.ca>
*
* This file is part of the OpGraph project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
*/
package ca.gedge.opgraph.app.components;
import java.awt.Component;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import ca.gedge.opgraph.util.Pair;
/**
* An implementation of {@link PathAddressableMenu} that operates on a given
* menu element.
*/
public class PathAddressableMenuImpl implements PathAddressableMenu {
/** The root element to base paths off of */
private MenuElement root;
/**
* Constructs a path-adressable menu with a given menu element as its root.
*
* @param root the menu element to use as root
*/
public PathAddressableMenuImpl(MenuElement root) {
this.root = root;
}
//
// PathAddressableMenu
//
@Override
public JMenu getMenu(String path) {
final MenuElement elem = getMenuElement(path);
return (elem != null && (elem instanceof JMenu) ? (JMenu)elem : null);
}
@Override
public JMenuItem getMenuItem(String path) {
final MenuElement elem = getMenuElement(path);
return (elem != null && (elem instanceof JMenuItem) ? (JMenuItem)elem : null);
}
@Override
public MenuElement getMenuElement(String path) {
final Pair<String, MenuElement> deepest = getDeepestMenuElement(root, path);
return ((deepest.getFirst().length() == path.length()) ? deepest.getSecond() : null);
}
@Override
public JMenu addMenu(String path, String text) {
final Pair<String, MenuElement> deepest = getDeepestMenuElement(root, path);
final String name = path.substring(deepest.getFirst().length());
JMenu ret = null;
if(name.indexOf('/') == -1) {
if(deepest.getSecond() instanceof JMenu) {
ret = new JMenu(text);
ret.setName(name);
((JMenu)deepest.getSecond()).add(ret);
} else if(deepest.getSecond() instanceof JPopupMenu) {
ret = new JMenu(text);
ret.setName(name);
ret.setIcon(null);
((JPopupMenu)deepest.getSecond()).add(ret);
} else if(deepest.getSecond() instanceof JMenuBar) {
ret = new JMenu(text);
ret.setName(name);
((JMenuBar)deepest.getSecond()).add(ret);
}
}
return ret;
}
@Override
public JMenuItem addMenuItem(String path, Action action) {
final Pair<String, MenuElement> deepest = getDeepestMenuElement(root, path);
final String name = path.substring(deepest.getFirst().length());
JMenuItem ret = null;
if(name.indexOf('/') == -1) {
if(deepest.getSecond() instanceof JMenu) {
ret = new JMenuItem(action);
ret.setName(name);
ret.setIcon(null);
((JMenu)deepest.getSecond()).add(ret);
} else if(deepest.getSecond() instanceof JPopupMenu) {
ret = new JMenuItem(action);
ret.setName(name);
ret.setIcon(null);
((JPopupMenu)deepest.getSecond()).add(ret);
} else if(deepest.getSecond() instanceof JMenuBar) {
ret = new JMenuItem(action);
ret.setName(name);
ret.setIcon(null);
((JMenuBar)deepest.getSecond()).add(ret);
}
}
return ret;
}
@Override
public Component addComponent(String path, Component component) {
final Pair<String, MenuElement> deepest = getDeepestMenuElement(root, path);
final String name = path.substring(deepest.getFirst().length());
if(name.indexOf('/') == -1) {
component.setName(name);
if(deepest.getSecond() instanceof JMenu) {
((JMenu)deepest.getSecond()).add(component);
} else if(deepest.getSecond() instanceof JPopupMenu) {
((JPopupMenu)deepest.getSecond()).add(component);
} else if(deepest.getSecond() instanceof JMenuBar) {
((JMenuBar)deepest.getSecond()).add(component);
}
} else component = null;
return component;
}
@Override
public void addSeparator(String path) {
final Pair<String, MenuElement> deepest = getDeepestMenuElement(root, path);
if(deepest.getFirst().length() == path.length()) {
if(deepest.getSecond().getSubElements().length > 0) {
if(deepest.getSecond() instanceof JMenu) {
((JMenu)deepest.getSecond()).addSeparator();
} else if(deepest.getSecond() instanceof JPopupMenu) {
((JPopupMenu)deepest.getSecond()).addSeparator();
}
}
}
}
private Pair<String, MenuElement> getDeepestMenuElement(MenuElement elem, String path) {
int position = 0;
if(elem != null && path != null) {
final String [] components = path.split("/");
int index = 0;
// Go as deep as we can go
while(index < components.length) {
final int oldIndex = index;
for(MenuElement subelem : elem.getSubElements()) {
if(components[index].equals(subelem.getComponent().getName())) {
position += components[index].length() + 1;
++index;
elem = subelem;
break;
}
}
// If we didn't move, stop
if(index == oldIndex)
break;
}
if(index == components.length)
--position;
}
return new Pair<String, MenuElement>(path.substring(0, position), elem);
}
}