/* * $Id$ * * Copyright (c) 2008 by Joel Uckelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.tools.menu; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.Action; import javax.swing.JFrame; import javax.swing.JMenuBar; /** * @author Joel Uckelman * @since 3.1.0 */ public abstract class MenuManager { protected static MenuManager instance; public static MenuManager getInstance() { if (instance == null) throw new IllegalStateException(); return instance; } public MenuManager() { if (instance != null) throw new IllegalStateException(); instance = this; } public abstract JMenuBar getMenuBarFor(JFrame fc); public abstract MenuBarProxy getMenuBarProxyFor(JFrame fc); private Map<String,List<MenuItemProxy>> actionLocations = new HashMap<String,List<MenuItemProxy>>(); private Map<String,MenuMarker> markers = new HashMap<String,MenuMarker>(); public MenuItemProxy addKey(String key) { List<MenuItemProxy> items = actionLocations.get(key); if (items == null) { items = new ArrayList<MenuItemProxy>(); actionLocations.put(key, items); } final MenuItemProxy item = new MenuItemProxy(); items.add(item); return item; } public List<MenuItemProxy> getItems(String key) { return actionLocations.get(key); } public void addAction(String key, Action a) { final List<MenuItemProxy> items = actionLocations.get(key); if (items != null) { for (MenuItemProxy i : items) { i.setAction(a); } } } public void removeAction(String key) { addAction(key, null); } public MenuMarker getMarker(String key) { return markers.get(key); } public MenuMarker addMarker(String key) { final MenuMarker marker = new MenuMarker(); markers.put(key, marker); return marker; } public void addToSection(String key, ChildProxy<?> item) { final MenuMarker start = getMarker(key + ".start"); final MenuMarker end = getMarker(key + ".end"); final ParentProxy parent = end.getParent(); final int startPos = parent.getIndex(start); final int endPos = parent.getIndex(end); // do separator check if this is the first item in the group if (parent instanceof MenuProxy && startPos + 1 == endPos) { // check from the end of the group to the next visible item // and insert a separator if that item is not one if (nextVisibleItemNotASeparator(end)) { ((MenuProxy) parent).insertSeparator(endPos+1); } // check from the start of the group to the previous visible // item and insert a separator if that item is not one if (prevVisibleItemNotASeparator(start)) { ((MenuProxy) parent).insertSeparator(startPos); } } // insert the item between the markers parent.insert(item, endPos); } public void removeFromSection(String key, ChildProxy<?> item) { final MenuMarker start = getMarker(key + ".start"); final MenuMarker end = getMarker(key + ".end"); final ParentProxy parent = end.getParent(); // remove the item parent.remove(item); // do separator check if this was the last item in the group if (parent instanceof MenuProxy) { final int startPos = parent.getIndex(start); final int endPos = parent.getIndex(end); if (startPos + 1 == endPos) { if (visibleItemBefore(start)) { // if we have a group on each side, or before but not after; // remove our top separator parent.remove(startPos-1); } else if (visibleItemAfter(end)) { // we have a group after, but none before; // remove our bottom separator parent.remove(endPos+1); } // otherwise, we were the sole group, our parent has no visible // items now } } } private boolean visibleItemAfter(ChildProxy<?> child) { final ParentProxy parent = child.getParent(); final int count = parent.getChildCount(); for (int i = parent.getIndex(child) + 1; i < count; i++) { final ChildProxy<?> c = parent.getChild(i); if (!(c instanceof MenuMarker)) return true; } return false; } private boolean visibleItemBefore(ChildProxy<?> child) { final ParentProxy parent = child.getParent(); for (int i = parent.getIndex(child) - 1; i >= 0; i++) { final ChildProxy<?> c = parent.getChild(i); if (!(c instanceof MenuMarker)) return true; } return false; } private boolean nextVisibleItemNotASeparator(ChildProxy<?> child) { final ParentProxy parent = child.getParent(); final int count = parent.getChildCount(); for (int i = parent.getIndex(child) + 1; i < count; i++) { final ChildProxy<?> c = parent.getChild(i); if (c instanceof MenuMarker) continue; return !(c instanceof SeparatorProxy); } return false; } private boolean prevVisibleItemNotASeparator(ChildProxy<?> child) { final ParentProxy parent = child.getParent(); for (int i = parent.getIndex(child) - 1; i >= 0; i--) { final ChildProxy<?> c = parent.getChild(i); if (c instanceof MenuMarker) continue; return !(c instanceof SeparatorProxy); } return false; } }