source: josm/trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java@ 1451

Last change on this file since 1451 was 1451, checked in by stoecker, 15 years ago

fix #2247. patch by xeen - cleanup search history

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions.search;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.util.Collection;
10import java.util.LinkedList;
11
12import javax.swing.ButtonGroup;
13import javax.swing.JCheckBox;
14import javax.swing.JLabel;
15import javax.swing.JOptionPane;
16import javax.swing.JPanel;
17import javax.swing.JRadioButton;
18import javax.swing.JTextField;
19
20import org.openstreetmap.josm.Main;
21import org.openstreetmap.josm.actions.JosmAction;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.gui.ExtendedDialog;
24import org.openstreetmap.josm.tools.GBC;
25import org.openstreetmap.josm.tools.Shortcut;
26
27public class SearchAction extends JosmAction {
28
29 public static final int SEARCH_HISTORY_SIZE = 10;
30
31 public static enum SearchMode {
32 replace, add, remove
33 }
34
35 public static final LinkedList<SearchSetting> searchHistory = new LinkedList<SearchSetting>();
36
37 private static SearchSetting lastSearch = null;
38
39 public SearchAction() {
40 super(tr("Search..."), "dialogs/search", tr("Search for objects."),
41 Shortcut.registerShortcut("system:find", tr("Search..."), KeyEvent.VK_F, Shortcut.GROUP_HOTKEY), true);
42 }
43
44 public void actionPerformed(ActionEvent e) {
45 if (Main.map == null) {
46 JOptionPane.showMessageDialog(Main.parent, tr("No data loaded."));
47 return;
48 }
49 SearchSetting s = lastSearch;
50 if (s == null)
51 s = new SearchSetting("", false, false, SearchMode.replace);
52 showSearchDialog(s);
53 }
54
55 public void showSearchDialog(SearchSetting initialValues) {
56 JLabel label = new JLabel(tr("Please enter a search string."));
57 final JTextField input = new JTextField(initialValues.text);
58 input.selectAll();
59 input.requestFocusInWindow();
60 JRadioButton replace = new JRadioButton(tr("replace selection"), initialValues.mode == SearchMode.replace);
61 JRadioButton add = new JRadioButton(tr("add to selection"), initialValues.mode == SearchMode.add);
62 JRadioButton remove = new JRadioButton(tr("remove from selection"), initialValues.mode == SearchMode.remove);
63 ButtonGroup bg = new ButtonGroup();
64 bg.add(replace);
65 bg.add(add);
66 bg.add(remove);
67
68 JCheckBox caseSensitive = new JCheckBox(tr("case sensitive"), initialValues.caseSensitive);
69 JCheckBox regexSearch = new JCheckBox(tr("regular expression"), initialValues.regexSearch);
70
71 JPanel left = new JPanel(new GridBagLayout());
72 left.add(label, GBC.eop());
73 left.add(input, GBC.eop().fill(GBC.HORIZONTAL));
74 left.add(replace, GBC.eol());
75 left.add(add, GBC.eol());
76 left.add(remove, GBC.eop());
77 left.add(caseSensitive, GBC.eol());
78 left.add(regexSearch, GBC.eol());
79
80 JPanel right = new JPanel();
81 right.add(new JLabel("<html><ul>"
82 + "<li>"+tr("<b>Baker Street</b> - 'Baker' and 'Street' in any key or name.")+"</li>"
83 + "<li>"+tr("<b>\"Baker Street\"</b> - 'Baker Street' in any key or name.")+"</li>"
84 + "<li>"+tr("<b>name:Bak</b> - 'Bak' anywhere in the name.")+"</li>"
85 + "<li>"+tr("<b>-name:Bak</b> - not 'Bak' in the name.")+"</li>"
86 + "<li>"+tr("<b>foot:</b> - key=foot set to any value.")+"</li>"
87 + "<li>"+tr("<u>Special targets:</u>")+"</li>"
88 + "<li>"+tr("<b>type:</b> - type of the object (<b>node</b>, <b>way</b>, <b>relation</b>)")+"</li>"
89 + "<li>"+tr("<b>user:</b>... - all objects changed by user")+"</li>"
90 + "<li>"+tr("<b>id:</b>... - object with given ID")+"</li>"
91 + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes")+"</li>"
92 + "<li>"+tr("<b>modified</b> - all changed objects")+"</li>"
93 + "<li>"+tr("<b>selected</b> - all selected objects")+"</li>"
94 + "<li>"+tr("<b>incomplete</b> - all incomplete objects")+"</li>"
95 + "<li>"+tr("<b>untagged</b> - all untagged objects")+"</li>"
96 + "<li>"+tr("Use <b>|</b> or <b>OR</b> to combine with logical or")+"</li>"
97 + "<li>"+tr("Use <b>\"</b> to quote operators (e.g. if key contains :)")+"</li>"
98 + "<li>"+tr("Use <b>(</b> and <b>)</b> to group expressions")+"</li>"
99 + "</ul></html>"));
100
101 final JPanel p = new JPanel();
102 p.add(left);
103 p.add(right);
104
105 int result = new ExtendedDialog(Main.parent,
106 tr("Search"),
107 p,
108 new String[] {tr("Start Search"), tr("Cancel")},
109 new String[] {"dialogs/search.png", "cancel.png"}).getValue();
110 if(result != 1) return;
111
112 // User pressed OK - let's perform the search
113 SearchMode mode = replace.isSelected() ? SearchAction.SearchMode.replace
114 : (add.isSelected() ? SearchAction.SearchMode.add : SearchAction.SearchMode.remove);
115 SearchSetting setting = new SearchSetting(input.getText(), caseSensitive.isSelected(), regexSearch.isSelected(), mode);
116 searchWithHistory(setting);
117 }
118
119 /**
120 * Adds the search specified by the settings in <code>s</code> to the
121 * search history and performs the search.
122 *
123 * @param s
124 */
125 public static void searchWithHistory(SearchSetting s) {
126 if(searchHistory.isEmpty() || !s.equals(searchHistory.getFirst()))
127 searchHistory.addFirst(s);
128 while (searchHistory.size() > SEARCH_HISTORY_SIZE)
129 searchHistory.removeLast();
130 lastSearch = s;
131 search(s.text, s.mode, s.caseSensitive, s.regexSearch);
132 }
133
134 public static void searchWithoutHistory(SearchSetting s) {
135 lastSearch = s;
136 search(s.text, s.mode, s.caseSensitive, s.regexSearch);
137 }
138
139 public static void search(String search, SearchMode mode, boolean caseSensitive, boolean regexSearch) {
140 if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://")
141 || search.startsWith("file:/")) {
142 SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode);
143 if (loader.url != null) {
144 Main.worker.execute(loader);
145 return;
146 }
147 }
148 try {
149 Collection<OsmPrimitive> sel = Main.ds.getSelected();
150 SearchCompiler.Match matcher = SearchCompiler.compile(search, caseSensitive, regexSearch);
151 int foundMatches = 0;
152 for (OsmPrimitive osm : Main.ds.allNonDeletedCompletePrimitives()) {
153 if (mode == SearchMode.replace) {
154 if (matcher.match(osm)) {
155 sel.add(osm);
156 ++foundMatches;
157 } else
158 sel.remove(osm);
159 } else if (mode == SearchMode.add && !osm.selected && matcher.match(osm)) {
160 sel.add(osm);
161 ++foundMatches;
162 } else if (mode == SearchMode.remove && osm.selected && matcher.match(osm)) {
163 sel.remove(osm);
164 ++foundMatches;
165 }
166 }
167 Main.ds.setSelected(sel);
168 if (foundMatches == 0) {
169 String msg = null;
170 if (mode == SearchMode.replace)
171 msg = tr("No match found for ''{0}''", search);
172 else if (mode == SearchMode.add)
173 msg = tr("Nothing added to selection by searching for ''{0}''", search);
174 else if (mode == SearchMode.remove)
175 msg = tr("Nothing removed from selection by searching for ''{0}''", search);
176 Main.map.statusLine.setHelpText(msg);
177 JOptionPane.showMessageDialog(Main.parent, msg);
178 } else
179 Main.map.statusLine.setHelpText(tr("Found {0} matches", foundMatches));
180 } catch (SearchCompiler.ParseError e) {
181 JOptionPane.showMessageDialog(Main.parent, e.getMessage());
182 }
183 }
184
185 public static class SearchSetting {
186 String text;
187 SearchMode mode;
188 boolean caseSensitive;
189 boolean regexSearch;
190
191 public SearchSetting(String text, boolean caseSensitive, boolean regexSearch, SearchMode mode) {
192 super();
193 this.caseSensitive = caseSensitive;
194 this.regexSearch = regexSearch;
195 this.mode = mode;
196 this.text = text;
197 }
198
199 @Override
200 public String toString() {
201 String cs = caseSensitive ? tr("CI") : tr("CS");
202 String rx = regexSearch ? (", " + tr("RX")) : "";
203 return "\"" + text + "\" (" + cs + rx + ", " + mode + ")";
204 }
205
206 public boolean equals(Object other) {
207 if(!(other instanceof SearchSetting))
208 return false;
209 SearchSetting o = (SearchSetting) other;
210 return (o.caseSensitive == this.caseSensitive
211 && o.regexSearch == this.regexSearch
212 && o.mode.equals(this.mode)
213 && o.text.equals(this.text));
214 }
215 }
216}
Note: See TracBrowser for help on using the repository browser.