// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.ui.components.gmenu;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.StringTokenizer;
/**
* this class is the menu bar of GFrame. it has a difference with JMenuBar which is, if you add 2 menu bars with the
* same name, they will be put in one bar.
*
* @author root
*/
public class GMenuBar extends javax.swing.JMenuBar {
/**
*
*/
private static final long serialVersionUID = 2020939077780205134L;
private HashMap<String, JMenu> menues = new HashMap<>();
public GMenuBar() {
// setBackground(new Color(245,245,255));
// setBorder(new EmptyBorder(0,0,0,0));
}
/**
* stores the places given for components
*/
private static HashMap<Component, Integer> componentPlaces = new HashMap<>();
/**
* inserts the child to parent with the given places,
* it doesn't forget the place in the next times that you want to insert another childs
* with another places
*/
public static Component insert(JMenu parent, Component child, int place) {
place = checkPlaceValue(place, child);
int n = parent.getMenuComponentCount();
Component[] items = new Component[n + 1];
Component[] c = parent.getMenuComponents();
System.arraycopy(c, 0, items, 0, n);
items[items.length - 1] = child;
sortPlacedComponents(items);
parent.removeAll();
for (Component item : items) {
parent.add(item, -1);
}
return child;
}
private static Component insert(JMenuBar parent, Component child, int place) {
place = checkPlaceValue(place, child);
int n = parent.getMenuCount();
Component[] items = new Component[n + 1];
MenuElement[] c = parent.getSubElements();
System.arraycopy(c, 0, items, 0, n);
items[items.length - 1] = child;
sortPlacedComponents(items);
parent.removeAll();
for (Component item : items) {
parent.add(item, -1);
}
return child;
}
private static int checkPlaceValue(int place, Component child) {
if (place == -1) {
if (componentPlaces.containsKey(child))
place = componentPlaces.get(child); //it has given a place before
else
place = 1000;
}
componentPlaces.put(child, place);
return place;
}
private static void sortPlacedComponents(Component[] items) {
Arrays.sort(items, (o1, o2) -> {
if (componentPlaces.containsKey(o1) && componentPlaces.containsKey(o2)) {
return componentPlaces.get(o1) - componentPlaces.get(o2);
}
return 1;
});
}
/**
* returns a new JMenu with the given label that added to this menu bar
* if there was created a menu with the same label before, the old menu
* will be returned and no new menu will be created
*/
private JMenu requestMenu(String label) {
JMenu jm = menues.get(label);
if (jm == null) {
JMenu ret = new JMenu(label);
menues.put(label, ret);
add(ret);
// validate();
return ret;
} else
return jm;
}
/**
* generates a menu from the given path, the path delimiter is "." , so this means
* a path in a tree, for example file.generate.star means a 3 layer menu.
* it doesn't create duplicate menues if you request it twice the same menu
* it just return the privious one,...
* <p/>
* it is suggested to ONLY use this method for creating sub menues
* <p/>
* if you have no idea on place just take it -1 , (in this case it normally sets it to 1000, but if it was given some value to it before it takes the older value)
* <p/>
* if some place was given for path before, the older value will discarded.
*/
public JMenu getUniqueMenu(String path, int place) {
StringTokenizer s = new StringTokenizer(path, ".");
// Scanner s = new Scanner(mname);
// s.useDelimiter(".");
if (!path.contains(".")) { //if it is only a first level menu
JMenu ret = requestMenu(path);
insert(this, ret, place);
return ret;
} //other wise we have more things to do ...
JMenu mnu = new JMenu("---");
if (s.hasMoreTokens()) {
mnu = requestMenu(s.nextToken());
boolean dontSearch_YouCantFindIt = false;
while (s.hasMoreTokens()) { //each token is a level in menu tree
String ss = s.nextToken();
JMenu _mnu = null;
if (!dontSearch_YouCantFindIt) { //try to find the next level of the menu
for (int i = 0; i < mnu.getMenuComponentCount(); i++) {
Component menuComponent = mnu.getMenuComponent(i);
if (menuComponent instanceof JMenu) {
JMenu menu = (JMenu) menuComponent;
if (menu.getText().equals(ss)) {
_mnu = menu;
break; //:D it is found
}
}
}
}
if (_mnu == null) { // if it is not found
_mnu = new JMenu(ss);
dontSearch_YouCantFindIt = true; //the next levels are also can't be found, so don;t search for them
//so create the next levels
if (s.hasMoreTokens()) mnu.add(_mnu);
else
insert(mnu, _mnu, place); //the given place applied to last level.
} else if (!s.hasMoreTokens())
insert(mnu, _mnu, place); //the given place applied to last level.
// else {
// }
mnu = _mnu;
}
}
return mnu;
}
}
// for (int i = 1; i < items.length - 1; i++) {
// if (items[i] == child) {
// int rightPlace = componentPlaces.get(items[i + 1]);
// int leftPlace = componentPlaces.get(items[i - 1]);
// componentPlaces.put(child, (rightPlace + leftPlace) / 2);
// found = true;
// }
// ;
// }
// if (!found){ //it was at item[0] or at the end
// if (items[0]==child){
// componentPlaces.put(child,componentPlaces.get(items[2])/2);
// }
// if (items[items.length-1]==child){
// componentPlaces.put(child,componentPlaces.get(items[items.length-1])+10);
// }
// }
//
//