001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.awt.Dimension;
008import java.awt.event.ActionEvent;
009import java.awt.event.ActionListener;
010import java.awt.event.KeyEvent;
011
012import javax.swing.DefaultListCellRenderer;
013import javax.swing.JLabel;
014import javax.swing.JList;
015import javax.swing.JMenuItem;
016import javax.swing.ListCellRenderer;
017
018import org.openstreetmap.josm.Main;
019import org.openstreetmap.josm.actions.JosmAction;
020import org.openstreetmap.josm.gui.ExtendedDialog;
021import org.openstreetmap.josm.gui.MainMenu;
022import org.openstreetmap.josm.gui.widgets.SearchTextResultListPanel;
023import org.openstreetmap.josm.tools.Shortcut;
024
025public final class MenuItemSearchDialog extends ExtendedDialog {
026
027    private final Selector selector;
028    private static final MenuItemSearchDialog INSTANCE = new MenuItemSearchDialog(Main.main.menu);
029
030    private MenuItemSearchDialog(MainMenu menu) {
031        super(Main.parent, tr("Search menu items"), new String[]{tr("Select"), tr("Cancel")});
032        this.selector = new Selector(menu);
033        this.selector.setDblClickListener(new ActionListener() {
034            @Override
035            public void actionPerformed(ActionEvent e) {
036                buttonAction(0, null);
037            }
038        });
039        setContent(selector, false);
040        setPreferredSize(new Dimension(600, 300));
041    }
042
043    /**
044     * Returns the unique instance of {@code MenuItemSearchDialog}.
045     *
046     * @return the unique instance of {@code MenuItemSearchDialog}.
047     */
048    public static synchronized MenuItemSearchDialog getInstance() {
049        return INSTANCE;
050    }
051
052    @Override
053    public ExtendedDialog showDialog() {
054        selector.init();
055        super.showDialog();
056        selector.clearSelection();
057        return this;
058    }
059
060    @Override
061    protected void buttonAction(int buttonIndex, ActionEvent evt) {
062        super.buttonAction(buttonIndex, evt);
063        if (buttonIndex == 0 && selector.getSelectedItem() != null && selector.getSelectedItem().isEnabled()) {
064            selector.getSelectedItem().getAction().actionPerformed(evt);
065        }
066    }
067
068    private static class Selector extends SearchTextResultListPanel<JMenuItem> {
069
070        private final MainMenu menu;
071
072        Selector(MainMenu menu) {
073            super();
074            this.menu = menu;
075            lsResult.setCellRenderer(new CellRenderer());
076        }
077
078        public JMenuItem getSelectedItem() {
079            final JMenuItem selected = lsResult.getSelectedValue();
080            if (selected != null) {
081                return selected;
082            } else if (!lsResultModel.isEmpty()) {
083                return lsResultModel.getElementAt(0);
084            } else {
085                return null;
086            }
087        }
088
089        @Override
090        protected void filterItems() {
091            lsResultModel.setItems(menu.findMenuItems(edSearchText.getText(), true));
092        }
093    }
094
095    private static class CellRenderer implements ListCellRenderer<JMenuItem> {
096
097        private final DefaultListCellRenderer def = new DefaultListCellRenderer();
098
099        @Override
100        public Component getListCellRendererComponent(JList<? extends JMenuItem> list, JMenuItem value, int index,
101                                                      boolean isSelected, boolean cellHasFocus) {
102            final JLabel label = (JLabel) def.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
103            label.setText(value.getText());
104            label.setIcon(value.getIcon());
105            label.setEnabled(value.isEnabled());
106            final JMenuItem item = new JMenuItem(value.getText());
107            item.setAction(value.getAction());
108            if (isSelected) {
109                item.setBackground(list.getSelectionBackground());
110                item.setForeground(list.getSelectionForeground());
111            } else {
112                item.setBackground(list.getBackground());
113                item.setForeground(list.getForeground());
114            }
115            return item;
116        }
117    }
118
119    public static class Action extends JosmAction {
120
121        public Action() {
122            super(tr("Search menu items"), "dialogs/search", null,
123                    Shortcut.registerShortcut("help:search-items", "Search menu items", KeyEvent.VK_SPACE, Shortcut.CTRL),
124                    true, "dialogs/search-items", false);
125        }
126
127        @Override
128        public void actionPerformed(ActionEvent e) {
129            MenuItemSearchDialog.getInstance().showDialog();
130        }
131    }
132}