- Timestamp:
- 2016-01-09T12:00:51+01:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/MainApplication.java
r9238 r9347 473 473 splash.dispose(); 474 474 mainFrame.setVisible(true); 475 main.gettingStarted.requestFocusInWindow();476 475 } 477 476 }); -
trunk/src/org/openstreetmap/josm/gui/MainMenu.java
r9320 r9347 7 7 8 8 import java.awt.Component; 9 import java.awt.DefaultFocusTraversalPolicy;10 import java.awt.Dimension;11 9 import java.awt.GraphicsEnvironment; 12 import java.awt.event.ActionEvent;13 10 import java.awt.event.KeyEvent; 14 import java.awt.event.KeyListener;15 11 import java.util.ArrayList; 16 12 import java.util.HashMap; … … 19 15 import java.util.Map; 20 16 21 import javax.swing.Action;22 import javax.swing.Box;23 17 import javax.swing.JCheckBoxMenuItem; 24 18 import javax.swing.JMenu; … … 27 21 import javax.swing.JPopupMenu; 28 22 import javax.swing.JSeparator; 29 import javax.swing.JTextField;30 23 import javax.swing.KeyStroke; 31 import javax.swing.MenuElement;32 import javax.swing.MenuSelectionManager;33 import javax.swing.event.DocumentEvent;34 import javax.swing.event.DocumentListener;35 24 import javax.swing.event.MenuEvent; 36 25 import javax.swing.event.MenuListener; … … 125 114 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 126 115 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 116 import org.openstreetmap.josm.gui.dialogs.MenuItemSearchDialog; 127 117 import org.openstreetmap.josm.gui.io.RecentlyOpenedFilesMenu; 128 118 import org.openstreetmap.josm.gui.layer.Layer; … … 132 122 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSearchAction; 133 123 import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetSearchPrimitiveDialog; 134 import org.openstreetmap.josm.gui.widgets.DisableShortcutsOnFocusGainedTextField;135 124 import org.openstreetmap.josm.tools.Shortcut; 136 125 … … 404 393 public FullscreenToggleAction fullscreenToggleAction; 405 394 406 /**407 * Popup menu to display menu items search result.408 */409 private final JPopupMenu searchResultsMenu = new JPopupMenu();410 411 395 /** this menu listener hides unnecessary JSeparators in a menu list but does not remove them. 412 396 * If at a later time the separators are required, they will be made visible again. Intended … … 441 425 442 426 /** 443 * @return the default position of tnew top-level menus427 * @return the default position of new top-level menus 444 428 * @since 6088 445 429 */ … … 818 802 }); 819 803 804 add(helpMenu, new MenuItemSearchDialog.Action()); 805 helpMenu.addSeparator(); 820 806 add(helpMenu, statusreport); 821 807 add(helpMenu, reportbug); … … 824 810 add(helpMenu, help); 825 811 add(helpMenu, about); 826 add(Box.createHorizontalGlue());827 final DisableShortcutsOnFocusGainedTextField searchField = createSearchField();828 add(searchField);829 830 // Do not let search field take the focus automatically831 setFocusTraversalPolicyProvider(true);832 setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {833 @Override834 protected boolean accept(Component aComponent) {835 return super.accept(aComponent) && !searchField.equals(aComponent);836 }837 });838 812 839 813 windowMenu.addMenuListener(menuSeparatorHandler); … … 854 828 855 829 /** 856 * Create search field.857 * @return the search field858 */859 private DisableShortcutsOnFocusGainedTextField createSearchField() {860 DisableShortcutsOnFocusGainedTextField searchField = new DisableShortcutsOnFocusGainedTextField() {861 @Override862 public Dimension getPreferredSize() {863 // JMenuBar uses a BoxLayout and it doesn't seem possible to specify a size factor,864 // so compute the preferred size dynamically865 return new Dimension(Math.min(200, Math.max(25, getMaximumAvailableWidth())),866 helpMenu.getPreferredSize().height);867 }868 };869 Shortcut searchFieldShortcut = Shortcut.registerShortcut("menu:search-field", tr("Search menu items"), KeyEvent.VK_R, Shortcut.MNEMONIC);870 searchFieldShortcut.setFocusAccelerator(searchField);871 searchField.setEditable(true);872 searchField.setMaximumSize(new Dimension(200, helpMenu.getPreferredSize().height));873 searchField.setHint(tr("Search menu items"));874 searchField.setToolTipText(Main.platform.makeTooltip(tr("Search menu items"), searchFieldShortcut));875 searchField.addKeyListener(new SearchFieldKeyListener());876 searchField.getDocument().addDocumentListener(new SearchFieldTextListener(this, searchField));877 return searchField;878 }879 880 /**881 830 * Search main menu for items with {@code textToFind} in title. 882 831 * @param textToFind The text to find 832 * @param skipPresets whether to skip the {@link #presetsMenu} in the search 883 833 * @return not null list of found menu items. 884 834 */ 885 p rivate List<JMenuItem> findMenuItems(String textToFind) {886 // Explicit ely use default locale in this case, because we're looking for translated strings835 public List<JMenuItem> findMenuItems(String textToFind, boolean skipPresets) { 836 // Explicitly use default locale in this case, because we're looking for translated strings 887 837 textToFind = textToFind.toLowerCase(Locale.getDefault()); 888 838 List<JMenuItem> result = new ArrayList<>(); 889 890 // Iterate over main menus 891 for (MenuElement menuElement : getSubElements()) { 892 if (!(menuElement instanceof JMenu)) continue; 893 894 JMenu mainMenuItem = (JMenu) menuElement; 895 if (mainMenuItem.getAction() != null && mainMenuItem.getText().toLowerCase(Locale.getDefault()).contains(textToFind)) { 896 result.add(mainMenuItem); 839 for (int i = 0; i < getMenuCount(); i++) { 840 if (getMenu(i) != null && (!skipPresets || presetsMenu != getMenu(i))) { 841 findMenuItems(getMenu(i), textToFind, result); 897 842 } 898 899 //Search recursively900 findMenuItems(mainMenuItem, textToFind, result);901 843 } 902 844 return result; … … 908 850 * @param menu menu in which search will be performed 909 851 * @param textToFind The text to find 910 * @param result resulting list of menu items852 * @param result resulting list of menu items 911 853 */ 912 854 private static void findMenuItems(final JMenu menu, final String textToFind, final List<JMenuItem> result) { … … 915 857 if (menuItem == null) continue; 916 858 917 // Explicit ely use default locale in this case, because we're looking for translated strings859 // Explicitly use default locale in this case, because we're looking for translated strings 918 860 if (menuItem.getAction() != null && menuItem.getText().toLowerCase(Locale.getDefault()).contains(textToFind)) { 919 861 result.add(menuItem); … … 977 919 } 978 920 979 /**980 * This listener is designed to handle ENTER key pressed in menu search field.981 * When user presses Enter key then selected item of "searchResultsMenu" is triggered.982 */983 private static class SearchFieldKeyListener implements KeyListener {984 985 @Override986 public void keyPressed(KeyEvent e) {987 if (e.getKeyCode() == KeyEvent.VK_ENTER) {988 // On ENTER selected menu item must be triggered989 MenuElement[] selection = MenuSelectionManager.defaultManager().getSelectedPath();990 if (selection.length > 1) {991 MenuElement selectedElement = selection[selection.length-1];992 if (selectedElement instanceof JMenuItem) {993 JMenuItem selectedItem = (JMenuItem) selectedElement;994 Action menuAction = selectedItem.getAction();995 menuAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));996 if (Main.isDebugEnabled()) {997 Main.debug(getClass().getName()+" consuming event "+e);998 }999 e.consume();1000 }1001 }1002 }1003 }1004 1005 @Override1006 public void keyTyped(KeyEvent e) {1007 // Not used1008 }1009 1010 @Override1011 public void keyReleased(KeyEvent e) {1012 // Not used1013 }1014 }1015 1016 private class SearchFieldTextListener implements DocumentListener {1017 private final JTextField searchField;1018 private final MainMenu mainMenu;1019 private String currentSearchText;1020 1021 SearchFieldTextListener(MainMenu mainMenu, JTextField searchField) {1022 this.mainMenu = mainMenu;1023 this.searchField = searchField;1024 }1025 1026 @Override1027 public void insertUpdate(DocumentEvent e) {1028 doSearch(searchField.getText());1029 }1030 1031 @Override1032 public void removeUpdate(DocumentEvent e) {1033 doSearch(searchField.getText());1034 }1035 1036 @Override1037 public void changedUpdate(DocumentEvent e) {1038 doSearch(searchField.getText());1039 }1040 1041 //TODO: perform some delay (maybe 200 ms) before actual searching.1042 void doSearch(String searchTerm) {1043 // Explicitely use default locale in this case, because we're looking for translated strings1044 searchTerm = searchTerm.trim().toLowerCase(Locale.getDefault());1045 1046 if (searchTerm.equals(currentSearchText)) {1047 return;1048 }1049 currentSearchText = searchTerm;1050 if (searchTerm.isEmpty()) {1051 // No text to search1052 hideMenu();1053 return;1054 }1055 1056 List<JMenuItem> searchResult = mainMenu.findMenuItems(currentSearchText);1057 if (searchResult.isEmpty()) {1058 // Nothing found1059 hideMenu();1060 return;1061 }1062 1063 if (searchResult.size() > 20) {1064 // Too many items found...1065 searchResult = searchResult.subList(0, 20);1066 }1067 1068 // Update Popup menu1069 searchResultsMenu.removeAll();1070 for (JMenuItem foundItem : searchResult) {1071 searchResultsMenu.add(foundItem.getText()).setAction(foundItem.getAction());1072 }1073 // Put menu right under search field1074 searchResultsMenu.pack();1075 searchResultsMenu.show(mainMenu, searchField.getX(), searchField.getY() + searchField.getHeight());1076 1077 // This is tricky. User still is able to edit search text. While Up and Down keys are handled by Popup Menu.1078 searchField.requestFocusInWindow();1079 }1080 1081 private void hideMenu() {1082 searchResultsMenu.setVisible(false);1083 }1084 }1085 921 } -
trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetSelector.java
r9304 r9347 8 8 import java.awt.Dimension; 9 9 import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener;11 10 import java.awt.event.ItemEvent; 12 11 import java.awt.event.ItemListener; 13 import java.awt.event.KeyAdapter;14 import java.awt.event.KeyEvent;15 import java.awt.event.MouseAdapter;16 import java.awt.event.MouseEvent;17 12 import java.util.ArrayList; 18 13 import java.util.Collection; … … 27 22 28 23 import javax.swing.AbstractAction; 29 import javax.swing.AbstractListModel;30 24 import javax.swing.Action; 31 25 import javax.swing.BoxLayout; … … 37 31 import javax.swing.JPanel; 38 32 import javax.swing.JPopupMenu; 39 import javax.swing.JScrollPane;40 33 import javax.swing.ListCellRenderer; 41 import javax.swing.event.DocumentEvent;42 import javax.swing.event.DocumentListener;43 34 import javax.swing.event.ListSelectionEvent; 44 35 import javax.swing.event.ListSelectionListener; … … 54 45 import org.openstreetmap.josm.gui.tagging.presets.items.Roles; 55 46 import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role; 56 import org.openstreetmap.josm.gui.widgets.JosmTextField;57 47 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher; 48 import org.openstreetmap.josm.gui.widgets.SearchTextResultListPanel; 58 49 import org.openstreetmap.josm.tools.Predicate; 59 50 import org.openstreetmap.josm.tools.Utils; … … 63 54 * @since 6068 64 55 */ 65 public class TaggingPresetSelector extends JPanelimplements SelectionChangedListener {56 public class TaggingPresetSelector extends SearchTextResultListPanel<TaggingPreset> implements SelectionChangedListener { 66 57 67 58 private static final int CLASSIFICATION_IN_FAVORITES = 300; … … 73 64 private static final BooleanProperty ONLY_APPLICABLE = new BooleanProperty("taggingpreset.dialog.only-applicable-to-selection", true); 74 65 75 private final JosmTextField edSearchText;76 private final JList<TaggingPreset> lsResult;77 66 private final JCheckBox ckOnlyApplicable; 78 67 private final JCheckBox ckSearchInTags; … … 80 69 private boolean typesInSelectionDirty = true; 81 70 private final transient PresetClassifications classifications = new PresetClassifications(); 82 private final ResultListModel lsResultModel = new ResultListModel();83 84 private final transient List<ListSelectionListener> listSelectionListeners = new ArrayList<>();85 86 private transient ActionListener dblClickListener;87 private transient ActionListener clickListener;88 71 89 72 private static class ResultListCellRenderer implements ListCellRenderer<TaggingPreset> { … … 96 79 result.setIcon((Icon) tp.getValue(Action.SMALL_ICON)); 97 80 return result; 98 }99 }100 101 private static class ResultListModel extends AbstractListModel<TaggingPreset> {102 103 private transient List<PresetClassification> presets = new ArrayList<>();104 105 public synchronized void setPresets(List<PresetClassification> presets) {106 this.presets = presets;107 fireContentsChanged(this, 0, Integer.MAX_VALUE);108 }109 110 @Override111 public synchronized TaggingPreset getElementAt(int index) {112 return presets.get(index).preset;113 }114 115 @Override116 public synchronized int getSize() {117 return presets.size();118 }119 120 public synchronized boolean isEmpty() {121 return presets.isEmpty();122 81 } 123 82 } … … 219 178 */ 220 179 public TaggingPresetSelector(boolean displayOnlyApplicable, boolean displaySearchInTags) { 221 super(new BorderLayout()); 180 super(); 181 lsResult.setCellRenderer(new ResultListCellRenderer()); 222 182 classifications.loadPresets(TaggingPresets.getTaggingPresets()); 223 224 edSearchText = new JosmTextField();225 edSearchText.getDocument().addDocumentListener(new DocumentListener() {226 @Override227 public void removeUpdate(DocumentEvent e) {228 filterPresets();229 }230 231 @Override232 public void insertUpdate(DocumentEvent e) {233 filterPresets();234 }235 236 @Override237 public void changedUpdate(DocumentEvent e) {238 filterPresets();239 }240 });241 edSearchText.addKeyListener(new KeyAdapter() {242 @Override243 public void keyPressed(KeyEvent e) {244 switch (e.getKeyCode()) {245 case KeyEvent.VK_DOWN:246 selectPreset(lsResult.getSelectedIndex() + 1);247 break;248 case KeyEvent.VK_UP:249 selectPreset(lsResult.getSelectedIndex() - 1);250 break;251 case KeyEvent.VK_PAGE_DOWN:252 selectPreset(lsResult.getSelectedIndex() + 10);253 break;254 case KeyEvent.VK_PAGE_UP:255 selectPreset(lsResult.getSelectedIndex() - 10);256 break;257 case KeyEvent.VK_HOME:258 selectPreset(0);259 break;260 case KeyEvent.VK_END:261 selectPreset(lsResultModel.getSize());262 break;263 }264 }265 });266 add(edSearchText, BorderLayout.NORTH);267 268 lsResult = new JList<>(lsResultModel);269 lsResult.setCellRenderer(new ResultListCellRenderer());270 lsResult.addMouseListener(new MouseAdapter() {271 @Override272 public void mouseClicked(MouseEvent e) {273 if (e.getClickCount() > 1) {274 if (dblClickListener != null)275 dblClickListener.actionPerformed(null);276 } else {277 if (clickListener != null)278 clickListener.actionPerformed(null);279 }280 }281 });282 add(new JScrollPane(lsResult), BorderLayout.CENTER);283 183 284 184 JPanel pnChecks = new JPanel(); … … 292 192 @Override 293 193 public void itemStateChanged(ItemEvent e) { 294 filter Presets();194 filterItems(); 295 195 } 296 196 }); … … 306 206 @Override 307 207 public void itemStateChanged(ItemEvent e) { 308 filter Presets();208 filterItems(); 309 209 } 310 210 }); … … 317 217 318 218 setPreferredSize(new Dimension(400, 300)); 319 filter Presets();219 filterItems(); 320 220 JPopupMenu popupMenu = new JPopupMenu(); 321 221 popupMenu.add(new AbstractAction(tr("Add toolbar button")) { … … 331 231 } 332 232 333 private synchronized void selectPreset(int newIndex) {334 if (newIndex < 0) {335 newIndex = 0;336 }337 if (newIndex > lsResultModel.getSize() - 1) {338 newIndex = lsResultModel.getSize() - 1;339 }340 lsResult.setSelectedIndex(newIndex);341 lsResult.ensureIndexIsVisible(newIndex);342 }343 344 233 /** 345 234 * Search expression can be in form: "group1/group2/name" where names can contain multiple words 346 235 */ 347 private synchronized void filterPresets() { 236 @Override 237 protected synchronized void filterItems() { 348 238 //TODO Save favorites to file 349 239 String text = edSearchText.getText().toLowerCase(Locale.ENGLISH); … … 357 247 358 248 final TaggingPreset oldPreset = lsResult.getSelectedValue(); 359 lsResultModel.setPresets(result); 249 lsResultModel.setItems(Utils.transform(result, new Utils.Function<PresetClassification, TaggingPreset>() { 250 @Override 251 public TaggingPreset apply(PresetClassification x) { 252 return x.preset; 253 } 254 })); 360 255 final TaggingPreset newPreset = lsResult.getSelectedValue(); 361 256 if (!Objects.equals(oldPreset, newPreset)) { … … 491 386 } 492 387 388 @Override 493 389 public synchronized void init() { 494 390 if (ckOnlyApplicable != null) { … … 496 392 ckOnlyApplicable.setSelected(!getTypesInSelection().isEmpty() && ONLY_APPLICABLE.get()); 497 393 } 498 listSelectionListeners.clear(); 499 edSearchText.setText(""); 500 filterPresets(); 394 super.init(); 501 395 } 502 396 … … 505 399 classifications.loadPresets(presets); 506 400 init(); 507 }508 509 public synchronized void clearSelection() {510 lsResult.getSelectionModel().clearSelection();511 401 } 512 402 … … 547 437 lsResult.setSelectedValue(p, true); 548 438 } 549 550 public synchronized int getItemCount() {551 return lsResultModel.getSize();552 }553 554 public void setDblClickListener(ActionListener dblClickListener) {555 this.dblClickListener = dblClickListener;556 }557 558 public void setClickListener(ActionListener clickListener) {559 this.clickListener = clickListener;560 }561 562 /**563 * Adds a selection listener to the presets list.564 * @param selectListener The list selection listener565 * @since 7412566 */567 public synchronized void addSelectionListener(ListSelectionListener selectListener) {568 lsResult.getSelectionModel().addListSelectionListener(selectListener);569 listSelectionListeners.add(selectListener);570 }571 572 /**573 * Removes a selection listener from the presets list.574 * @param selectListener The list selection listener575 * @since 7412576 */577 public synchronized void removeSelectionListener(ListSelectionListener selectListener) {578 listSelectionListeners.remove(selectListener);579 lsResult.getSelectionModel().removeListSelectionListener(selectListener);580 }581 439 }
Note:
See TracChangeset
for help on using the changeset viewer.