Index: MainMenu.java
===================================================================
--- MainMenu.java	(revision 7881)
+++ MainMenu.java	(working copy)
@@ -6,18 +6,31 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Component;
+import java.awt.Dimension;
 import java.awt.GraphicsEnvironment;
+import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
+import javax.swing.Action;
 import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComponent;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
 import javax.swing.JPopupMenu;
 import javax.swing.JSeparator;
+import javax.swing.JTextField;
+import javax.swing.JTextPane;
 import javax.swing.KeyStroke;
+import javax.swing.MenuElement;
+import javax.swing.MenuSelectionManager;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
 
@@ -384,6 +397,11 @@
     public final DialogsToggleAction dialogsToggleAction = new DialogsToggleAction();
     public FullscreenToggleAction fullscreenToggleAction = null;
 
+    /**
+     * Popup menu to display menu items search result.
+     */
+    private JPopupMenu searchResultsMenu = new JPopupMenu();
+
     /** this menu listener hides unnecessary JSeparators in a menu list but does not remove them.
      * If at a later time the separators are required, they will be made visible again. Intended
      * usage is make menus not look broken if separators are used to group the menu and some of
@@ -772,13 +790,86 @@
         current.setAccelerator(Shortcut.registerShortcut("system:help", tr("Help"), KeyEvent.VK_F1,
                 Shortcut.DIRECT).getKeyStroke());
         add(helpMenu, about);
+        add(createSpacer(50));
+        add(createSearchField());
 
-
         windowMenu.addMenuListener(menuSeparatorHandler);
 
         new PresetsMenuEnabler(presetsMenu).refreshEnabled();
     }
 
+    /**
+     * Create spacer: empty component with fixed width.
+     */
+    private JComponent createSpacer(int pixels) {
+        JTextPane spacer = new JTextPane();
+        spacer.setMinimumSize(new Dimension(pixels, 0));
+        spacer.setMaximumSize(new Dimension(pixels, 0));
+        return spacer;
+    }
+
+    /**
+     * Create search field.
+     */
+    private JComponent createSearchField() {
+        JTextField searchField = new JTextField();
+        searchField.setEditable(true);
+        searchField.setMaximumSize(new Dimension(200, 50));
+        searchField.setToolTipText(marktr("Search menu items"));
+        searchField.addKeyListener(new SearchFieldKeyListener());
+        searchField.getDocument().addDocumentListener(new SearchFieldTextListener(this, searchField));
+        return searchField;
+    }
+
+    /**
+     * Search main menu for items with {@param textToFind} in title.
+     * @param textToFind
+     * @return not null list of found menu items.
+     */
+    private List<JMenuItem> findMenuItems(String textToFind) {
+        textToFind = textToFind.toLowerCase();
+        LinkedList<JMenuItem> result = new LinkedList<>();
+        int menuCount = getMenuCount();
+
+        //Iterate over main menus
+        for(MenuElement menuElement : getSubElements()) {
+            if( !(menuElement instanceof JMenu) ) continue;
+
+            JMenu mainMenuItem = (JMenu) menuElement;
+            if(mainMenuItem.getAction()!=null && mainMenuItem.getText().toLowerCase().contains(textToFind)) {
+                result.add(mainMenuItem);
+            }
+
+            //Search recursively
+            findMenuItems(mainMenuItem, textToFind, result);
+        }
+        return result;
+    }
+
+    /**
+     * Recursive walker for menu items. Only menu items with action are selected. If menu item
+     * contains {@param textToFind} it's appended to result.
+     * @param menu
+     * @param textToFind
+     * @param result
+     */
+    private void findMenuItems(final JMenu menu, final String textToFind, final List<JMenuItem> result) {
+        int count = menu.getItemCount();
+        for(int i=0; i<count; i++) {
+            JMenuItem menuItem = menu.getItem(i);
+            if(menuItem == null) continue;
+
+            if (menuItem.getAction()!=null && menuItem.getText().toLowerCase().contains(textToFind)) {
+                result.add(menuItem);
+            }
+
+            //Go recursive if needed
+            if(menuItem instanceof JMenu) {
+                findMenuItems((JMenu) menuItem, textToFind, result);
+            }
+        }
+    }
+
     protected void showAudioMenu(boolean showMenu) {
         if (showMenu && audioMenu == null) {
             audioMenu = addMenu(marktr("Audio"), KeyEvent.VK_U, defaultMenuPos, ht("/Menu/Audio"));
@@ -826,4 +917,105 @@
             refreshEnabled();
         }
     }
+
+    /**
+     * This listener is designed to handle ENTER key pressed in menu search field.
+     * When user presses Enter key then selected item of "searchResultsMenu" is triggered.
+     */
+    class SearchFieldKeyListener implements KeyListener {
+        public SearchFieldKeyListener() {
+            super();
+        }
+
+        @Override
+        public void keyPressed(KeyEvent e) {
+            if(e.getKeyCode() == KeyEvent.VK_ENTER) {
+                //On ENTER selected menu item must be triggered
+                MenuElement[] selection = MenuSelectionManager.defaultManager().getSelectedPath();
+                if(selection.length > 1) {
+                    MenuElement selectedElement = selection[selection.length-1];
+                    if(selectedElement instanceof JMenuItem) {
+                        JMenuItem selectedItem = (JMenuItem) selectedElement;
+                        Action menuAction = selectedItem.getAction();
+                        menuAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
+                        e.consume();
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void keyTyped(KeyEvent e) { }
+
+        @Override
+        public void keyReleased(KeyEvent e) { }
+    }
+
+    class SearchFieldTextListener implements DocumentListener {
+        private final JTextField searchField;
+        private final MainMenu mainMenu;
+        private String currentSearchText = null;
+
+        public SearchFieldTextListener(MainMenu mainMenu, JTextField searchField) {
+            this.mainMenu = mainMenu;
+            this.searchField = searchField;
+        }
+
+        @Override
+        public void insertUpdate(DocumentEvent e) {
+            doSearch(searchField.getText());
+        }
+
+        @Override
+        public void removeUpdate(DocumentEvent e) {
+            doSearch(searchField.getText());
+        }
+
+        @Override
+        public void changedUpdate(DocumentEvent e) {
+            doSearch(searchField.getText());
+        }
+
+        //TODO: perform some delay (maybe 200 ms) before actual searching.
+        void doSearch(String searchTerm) {
+            searchTerm = searchTerm.trim().toLowerCase();
+
+            if (searchTerm.equals(currentSearchText)) {
+                return;
+            }
+            currentSearchText = searchTerm;
+            if (searchTerm.length() == 0) {
+                //No text to search
+                hideMenu();
+                return;
+            }
+
+            List<JMenuItem> searchResult = mainMenu.findMenuItems(currentSearchText);
+            if(searchResult.size() == 0) {
+                //Nothing found
+                hideMenu();
+                return;
+            }
+
+            if(searchResult.size() > 20) {
+                //Too many items found...
+                searchResult = searchResult.subList(0, 20);
+            }
+
+            //Update Popup menu
+            searchResultsMenu.removeAll();
+            for (JMenuItem foundItem : searchResult) {
+                searchResultsMenu.add(foundItem.getText()).setAction(foundItem.getAction());
+            }
+            searchResultsMenu.pack();
+            searchResultsMenu.show(mainMenu, searchField.getX(), searchField.getY() + searchField.getHeight()); //Put menu right under search field
+
+            searchField.grabFocus(); //This is tricky. User still is able to edit search text. While Up and Down keys are handled by Popup Menu.
+        }
+
+        private void hideMenu() {
+            searchResultsMenu.setVisible(false);
+        }
+
+    }
 }
