001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.tagging;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.awt.MouseInfo;
008import java.awt.Point;
009import java.awt.event.ActionEvent;
010import java.io.Serializable;
011import java.util.ArrayList;
012import java.util.Collections;
013import java.util.Comparator;
014import java.util.List;
015
016import javax.swing.Action;
017import javax.swing.JMenu;
018import javax.swing.JMenuItem;
019import javax.swing.JPopupMenu;
020import javax.swing.JSeparator;
021
022import org.openstreetmap.josm.Main;
023import org.openstreetmap.josm.tools.AlphanumComparator;
024
025public class TaggingPresetMenu extends TaggingPreset {
026    public JMenu menu = null; // set by TaggingPresets
027
028    private static class PresetTextComparator implements Comparator<JMenuItem>, Serializable {
029        @Override
030        public int compare(JMenuItem o1, JMenuItem o2) {
031            if (Main.main.menu.presetSearchAction.equals(o1.getAction()))
032                return -1;
033            else if (Main.main.menu.presetSearchAction.equals(o2.getAction()))
034                return 1;
035            else
036                return AlphanumComparator.getInstance().compare(o1.getText(), o2.getText());
037        }
038    }
039
040    @Override
041    public void setDisplayName() {
042        putValue(Action.NAME, getName());
043        /** Tooltips should be shown for the toolbar buttons, but not in the menu. */
044        putValue(OPTIONAL_TOOLTIP_TEXT, (group != null ?
045                tr("Preset group {1} / {0}", getLocaleName(), group.getName()) :
046                    tr("Preset group {0}", getLocaleName())));
047        putValue("toolbar", "tagginggroup_" + getRawName());
048    }
049
050    private Component copyMenuComponent(Component menuComponent) {
051        if (menuComponent instanceof JMenu) {
052            JMenu menu = (JMenu)menuComponent;
053            JMenu result = new JMenu(menu.getAction());
054            for (Component item:menu.getMenuComponents()) {
055                result.add(copyMenuComponent(item));
056            }
057            result.setText(menu.getText());
058            return result;
059        } else if (menuComponent instanceof JMenuItem) {
060            JMenuItem menuItem = (JMenuItem)menuComponent;
061            JMenuItem result = new JMenuItem(menuItem.getAction());
062            result.setText(menuItem.getText());
063            return result;
064        } else if(menuComponent instanceof JSeparator) {
065            return new JSeparator();
066        } else {
067            return menuComponent;
068        }
069    }
070
071    @Override
072    public void actionPerformed(ActionEvent e) {
073        Object s = e.getSource();
074        if (menu != null && s instanceof Component) {
075            JPopupMenu pm = new JPopupMenu(getName());
076            for (Component c : menu.getMenuComponents()) {
077                pm.add(copyMenuComponent(c));
078            }
079            Point p = MouseInfo.getPointerInfo().getLocation();
080            pm.show(Main.parent, p.x-Main.parent.getX(), p.y-Main.parent.getY());
081        }
082    }
083
084    /**
085     * Sorts the menu items using the translated item text
086     */
087    public void sortMenu(){
088        TaggingPresetMenu.sortMenu(this.menu);
089    }
090
091    /**
092     * Sorts the menu items using the translated item text
093     */
094    public static void sortMenu(JMenu menu){
095        Component[] items = menu.getMenuComponents();
096        PresetTextComparator comp = new PresetTextComparator();
097        List<JMenuItem> sortarray = new ArrayList<>();
098        int lastSeparator = 0;
099        for (int i = 0; i < items.length; i++) {
100            Object item = items[i];
101            if (item instanceof JMenu){
102                sortMenu((JMenu)item);
103            }
104            if (item instanceof JMenuItem){
105                sortarray.add((JMenuItem)item);
106                if (i == items.length-1){
107                    Collections.sort(sortarray, comp);
108                    int pos = 0;
109                    for (JMenuItem menuItem : sortarray) {
110                        int oldPos;
111                        if (lastSeparator == 0){
112                            oldPos=pos;
113                        } else {
114                            oldPos = pos+lastSeparator+1;
115                        }
116                        menu.add(menuItem, oldPos);
117                        pos++;
118                    }
119                    sortarray = new ArrayList<>();
120                    lastSeparator = 0;
121                }
122            } else if (item instanceof JSeparator){
123                Collections.sort(sortarray, comp);
124                int pos = 0;
125                for (JMenuItem menuItem : sortarray) {
126                    int oldPos;
127                    if(lastSeparator == 0){
128                        oldPos=pos;
129                    }else {
130                        oldPos = pos+lastSeparator+1;
131                    }
132                    menu.add(menuItem, oldPos);
133                    pos++;
134                }
135                sortarray = new ArrayList<>();
136                lastSeparator = i;
137            }
138        }
139    }
140}