001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
004    package graphlab.ui.components.gmenu;
005    
006    import javax.swing.*;
007    import java.awt.*;
008    import java.util.Arrays;
009    import java.util.Comparator;
010    import java.util.HashMap;
011    import java.util.StringTokenizer;
012    
013    /**
014     * this class is the menu bar of GFrame. it has a difference with JMenuBar which is, if you add 2 menu bars with the
015     * same name, they will be put in one bar.
016     *
017     * @author root
018     */
019    public class GMenuBar extends javax.swing.JMenuBar {
020        /**
021         *
022         */
023        private static final long serialVersionUID = 2020939077780205134L;
024        private HashMap<String, JMenu> menues = new HashMap<String, JMenu>();
025    
026        public GMenuBar() {
027    //        setBackground(new Color(245,245,255));
028    //        setBorder(new EmptyBorder(0,0,0,0));
029        }
030    
031        /**
032         * stores the places given for components
033         */
034        private static HashMap<Component, Integer> componentPlaces = new HashMap<Component, Integer>();
035    
036        /**
037         * inserts the child to parent with the given places,
038         * it doesn't forget the place in the next times that you want to insert another childs
039         * with another places
040         */
041        public static Component insert(JMenu parent, Component child, int place) {
042            place = checkPlaceValue(place, child);
043            int n = parent.getMenuComponentCount();
044            Component[] items = new Component[n + 1];
045            Component[] c = parent.getMenuComponents();
046            System.arraycopy(c, 0, items, 0, n);
047            items[items.length - 1] = child;
048            sortPlacedComponents(items);
049            parent.removeAll();
050            for (int i = 0; i < items.length; i++) {
051                parent.add(items[i], -1);
052            }
053            return child;
054    //        return
055        }
056    
057        private static Component insert(JMenuBar parent, Component child, int place) {
058            place = checkPlaceValue(place, child);
059            int n = parent.getMenuCount();
060            Component[] items = new Component[n + 1];
061            MenuElement[] c = parent.getSubElements();
062            System.arraycopy(c, 0, items, 0, n);
063            items[items.length - 1] = child;
064            sortPlacedComponents(items);
065            parent.removeAll();
066            for (int i = 0; i < items.length; i++) {
067                parent.add(items[i], -1);
068            }
069            return child;
070    //        return
071        }
072    
073        private static int checkPlaceValue(int place, Component child) {
074            if (place == -1) {
075                if (componentPlaces.containsKey(child))
076                    place = componentPlaces.get(child);       //it has given a place before
077                else
078                    place = 1000;
079            }
080            componentPlaces.put(child, place);
081            return place;
082        }
083    
084        private static void sortPlacedComponents(Component[] items) {
085            Arrays.sort(items, new Comparator<Component>() {
086                public int compare(Component o1, Component o2) {
087                    if (componentPlaces.containsKey(o1) && componentPlaces.containsKey(o2)) {
088                        return componentPlaces.get(o1) - componentPlaces.get(o2);
089                    }
090                    return 1;
091                }
092            });
093        }
094    
095        /**
096         * returns a new JMenu with the given label that added to this menu bar
097         * if there was created a menu with the same label before, the old menu
098         * will be returned and no new menu will be created
099         */
100        private JMenu requestMenu(String label) {
101            JMenu jm = menues.get(label);
102            if (jm == null) {
103                JMenu ret = new JMenu(label);
104                menues.put(label, ret);
105                add(ret);
106    //            validate();
107                return ret;
108            } else
109                return jm;
110        }
111    
112        /**
113         * generates a menu from the given path, the path delimiter is "." , so this means
114         * a path in a tree, for example file.generate.star means a 3 layer menu.
115         * it doesn't create duplicate menues if you request it twice the same menu
116         * it just return the privious one,...
117         * <p/>
118         * it is suggested to ONLY use this method for creating sub menues
119         * <p/>
120         * 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)
121         * <p/>
122         * if some place was given for path before, the older value will discarded.
123         */
124        public JMenu getUniqueMenu(String path, int place) {
125            StringTokenizer s = new StringTokenizer(path, ".");
126    //            Scanner s = new Scanner(mname);
127    //            s.useDelimiter(".");
128            if (!path.contains(".")) {       //if it is only a first level menu
129                JMenu ret = requestMenu(path);
130                insert(this, ret, place);
131                return ret;
132    
133            }                               //other wise we have more things to do ...
134            JMenu mnu = new JMenu("---");
135            if (s.hasMoreTokens()) {
136                mnu = requestMenu(s.nextToken());
137                boolean dontSearch_YouCantFindIt = false;
138                while (s.hasMoreTokens()) {             //each token is a level in menu tree
139                    String ss = s.nextToken();
140                    JMenu _mnu = null;
141                    if (!dontSearch_YouCantFindIt) {   //try to find the next level of the menu
142                        for (int i = 0; i < mnu.getMenuComponentCount(); i++) {
143                            Component menuComponent = mnu.getMenuComponent(i);
144                            if (menuComponent instanceof JMenu) {
145                                JMenu _ = (JMenu) menuComponent;
146                                if (_.getText().equals(ss)) {
147                                    _mnu = _;
148                                    break;  //:D it is found
149                                }
150                            }
151                        }
152                    }
153                    if (_mnu == null) {     // if it is not found
154                        _mnu = new JMenu(ss);
155                        dontSearch_YouCantFindIt = true;   //the next levels are also can't be found, so don;t search for them
156                        //so create the next levels
157                        if (s.hasMoreTokens()) mnu.add(_mnu);
158                        else
159                            insert(mnu, _mnu, place);   //the given place applied to last level.
160                    } else if (!s.hasMoreTokens())
161                        insert(mnu, _mnu, place);   //the given place applied to last level.
162    
163    //                else {
164    //                }
165                    mnu = _mnu;
166                }
167            }
168            return mnu;
169    
170        }
171    }
172    //            for (int i = 1; i < items.length - 1; i++) {
173    //                if (items[i] == child) {
174    //                    int rightPlace = componentPlaces.get(items[i + 1]);
175    //                    int leftPlace = componentPlaces.get(items[i - 1]);
176    //                    componentPlaces.put(child, (rightPlace + leftPlace) / 2);
177    //                    found = true;
178    //                }
179    //                ;
180    //            }
181    //            if (!found){    //it was at item[0] or at the end
182    //                if (items[0]==child){
183    //                    componentPlaces.put(child,componentPlaces.get(items[2])/2);
184    //                }
185    //                if (items[items.length-1]==child){
186    //                    componentPlaces.put(child,componentPlaces.get(items[items.length-1])+10);
187    //                }
188    //            }
189    //
190    //