source: osm/applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/FindRelationAction.java@ 35196

Last change on this file since 35196 was 35196, checked in by donvip, 6 years ago

fix #josm18262 - IAE

File size: 9.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package relcontext.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Dialog.ModalityType;
8import java.awt.Dimension;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.KeyAdapter;
12import java.awt.event.KeyEvent;
13import java.awt.event.MouseAdapter;
14import java.awt.event.MouseEvent;
15import java.util.ArrayList;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.List;
19
20import javax.swing.AbstractListModel;
21import javax.swing.DefaultListSelectionModel;
22import javax.swing.JDialog;
23import javax.swing.JList;
24import javax.swing.JOptionPane;
25import javax.swing.JPanel;
26import javax.swing.JScrollPane;
27import javax.swing.JTextField;
28import javax.swing.ListSelectionModel;
29import javax.swing.SwingUtilities;
30
31import org.openstreetmap.josm.actions.JosmAction;
32import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
33import org.openstreetmap.josm.data.osm.Relation;
34import org.openstreetmap.josm.gui.MainApplication;
35import org.openstreetmap.josm.gui.PrimitiveRenderer;
36import org.openstreetmap.josm.tools.Logging;
37import org.openstreetmap.josm.tools.Shortcut;
38
39import relcontext.ChosenRelation;
40
41/**
42 * Opens a list of all relations with keyword search field. Choose selected relation.
43 *
44 * @author Zverik
45 */
46public class FindRelationAction extends JosmAction {
47 protected ChosenRelation chRel;
48
49 public FindRelationAction(ChosenRelation chRel) {
50 super(tr("Find"), "relcontext/find", tr("Find a relation"),
51 Shortcut.registerShortcut("reltoolbox:find", tr("Relation Toolbox: {0}", tr("Find a relation")),
52 KeyEvent.VK_F, Shortcut.ALT_CTRL), false);
53 this.chRel = chRel;
54 }
55
56 @Override
57 public void actionPerformed(ActionEvent e) {
58 JPanel panel = new JPanel(new BorderLayout());
59 final JTextField searchField = new JTextField();
60 panel.add(searchField, BorderLayout.NORTH);
61 final FindRelationListModel relationsData = new FindRelationListModel();
62 final JList<Relation> relationsList = new JList<>(relationsData);
63 relationsList.setSelectionModel(relationsData.getSelectionModel());
64 relationsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
65 relationsList.setCellRenderer(new PrimitiveRenderer());
66 panel.add(new JScrollPane(relationsList,
67 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER);
68 panel.setPreferredSize(new Dimension(400, 400));
69
70 final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
71 @Override
72 public void selectInitialValue() {
73 searchField.requestFocusInWindow();
74 }
75 };
76 final JDialog dlg = optionPane.createDialog(MainApplication.getMainFrame(), tr("Find a relation"));
77 dlg.setModalityType(ModalityType.DOCUMENT_MODAL);
78
79 relationsList.addMouseListener(new MouseAdapter() {
80 @Override
81 public void mouseClicked(MouseEvent e) {
82 if (e.getClickCount() >= 2 && !relationsList.isSelectionEmpty()) {
83 dlg.setVisible(false);
84 optionPane.setValue(JOptionPane.OK_OPTION);
85 }
86 }
87 });
88
89 searchField.addActionListener(new ActionListener() {
90 @Override
91 public void actionPerformed(ActionEvent e) {
92 if (!relationsList.isSelectionEmpty()) {
93 dlg.setVisible(false);
94 optionPane.setValue(JOptionPane.OK_OPTION);
95 }
96 }
97 });
98
99 searchField.addKeyListener(new KeyAdapter() {
100 @Override
101 public void keyTyped(KeyEvent e) {
102 SwingUtilities.invokeLater(new Runnable() {
103 @Override
104 public void run() {
105 updateRelationData(relationsData, searchField.getText());
106 }
107 });
108 }
109
110 @Override
111 public void keyPressed(KeyEvent e) {
112 if (shouldForward(e)) {
113 relationsList.dispatchEvent(e);
114 }
115 }
116
117 @Override
118 public void keyReleased(KeyEvent e) {
119 if (shouldForward(e)) {
120 relationsList.dispatchEvent(e);
121 }
122 }
123
124 private boolean shouldForward(KeyEvent e) {
125 return e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN
126 || e.getKeyCode() == KeyEvent.VK_PAGE_DOWN || e.getKeyCode() == KeyEvent.VK_PAGE_UP
127 || e.getKeyCode() == KeyEvent.VK_HOME || e.getKeyCode() == KeyEvent.VK_END;
128 }
129 });
130
131 updateRelationData(relationsData, null);
132 dlg.setVisible(true);
133
134 Object answer = optionPane.getValue();
135 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
136 || (answer instanceof Integer && (Integer) answer != JOptionPane.OK_OPTION))
137 return;
138
139 Relation r = relationsList.getSelectedValue();
140 if (r != null) {
141 chRel.set(r);
142 }
143 }
144
145 @Override
146 protected void updateEnabledState() {
147 setEnabled(getLayerManager().getEditDataSet() != null);
148 }
149
150 protected void updateRelationData(FindRelationListModel data, String filter) {
151 String[] keywords = filter == null ? new String[0] : filter.split("\\s+");
152 if (keywords.length > 0) {
153 List<String> filteredKeywords = new ArrayList<>(keywords.length);
154 for (String s : keywords) {
155 if (s.length() > 0) {
156 filteredKeywords.add(s.trim().toLowerCase());
157 }
158 }
159 keywords = filteredKeywords.toArray(new String[0]);
160 }
161
162 if (Logging.isDebugEnabled()) {
163 Logging.debug("keywords.length = " + keywords.length);
164 for (int i = 0; i < keywords.length; i++) {
165 Logging.debug("keyword["+i+"] = " + keywords[i]);
166 }
167 }
168
169 List<Relation> relations = new ArrayList<>();
170 if (getLayerManager().getEditLayer() != null) {
171 for (Relation r : getLayerManager().getEditLayer().data.getRelations()) {
172 if (!r.isDeleted() && r.isVisible() && !r.isIncomplete()) {
173 boolean add = true;
174 for (int i = 0; i < keywords.length && add; i++) {
175 boolean ok = false;
176 if (String.valueOf(r.getPrimitiveId().getUniqueId()).contains(keywords[i])) {
177 ok = true;
178 } else {
179 for (String key : r.keySet()) {
180 if (key.contains(keywords[i]) || r.get(key).toLowerCase().contains(keywords[i])
181 || safetr(r.get(key)).toLowerCase().contains(keywords[i])) {
182 ok = true;
183 break;
184 }
185 }
186 }
187 if (!ok) {
188 add = false;
189 }
190 }
191 if (add) {
192 relations.add(r);
193 }
194 }
195 }
196 }
197
198 Collections.sort(relations, DefaultNameFormatter.getInstance().getRelationComparator());
199 data.setRelations(relations);
200 }
201
202 private static String safetr(String s) {
203 try {
204 return tr(s);
205 } catch (IllegalArgumentException e) {
206 Logging.trace(e);
207 return s;
208 }
209 }
210
211 /**
212 * I admit, some of it was copypasted from {@link org.openstreetmap.josm.gui.dialogs.RelationListDialog.RelationListModel}.
213 */
214 protected static class FindRelationListModel extends AbstractListModel<Relation> {
215 private final ArrayList<Relation> relations = new ArrayList<>();
216 private DefaultListSelectionModel selectionModel;
217
218 public FindRelationListModel(DefaultListSelectionModel selectionModel) {
219 super();
220 this.selectionModel = selectionModel;
221 }
222
223 public FindRelationListModel() {
224 this(new DefaultListSelectionModel());
225 }
226
227 public DefaultListSelectionModel getSelectionModel() {
228 return selectionModel;
229 }
230
231 @Override
232 public int getSize() {
233 return relations.size();
234 }
235
236 @Override
237 public Relation getElementAt(int index) {
238 return relations.get(index);
239 }
240
241 public void setRelations(Collection<Relation> relations) {
242 int selectedIndex = selectionModel.getMinSelectionIndex();
243 Relation sel = selectedIndex < 0 ? null : getElementAt(selectedIndex);
244
245 this.relations.clear();
246 selectionModel.clearSelection();
247 if (relations != null) {
248 this.relations.addAll(relations);
249 }
250 fireIntervalAdded(this, 0, getSize());
251
252 if (sel != null) {
253 selectedIndex = this.relations.indexOf(sel);
254 if (selectedIndex >= 0) {
255 selectionModel.addSelectionInterval(selectedIndex, selectedIndex);
256 }
257 }
258 if (selectionModel.isSelectionEmpty() && !this.relations.isEmpty()) {
259 selectionModel.addSelectionInterval(0, 0);
260 }
261 }
262 }
263}
Note: See TracBrowser for help on using the repository browser.