source: subversion/applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/FindRelationAction.java

Last change on this file was 34551, checked in by donvip, 8 months ago

update to JOSM 14153

File size: 9.4 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                                        || tr(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    /**
203     * I admit, some of it was copypasted from {@link org.openstreetmap.josm.gui.dialogs.RelationListDialog.RelationListModel}.
204     */
205    protected static class FindRelationListModel extends AbstractListModel<Relation> {
206        private final ArrayList<Relation> relations = new ArrayList<>();
207        private DefaultListSelectionModel selectionModel;
208
209        public FindRelationListModel(DefaultListSelectionModel selectionModel) {
210            super();
211            this.selectionModel = selectionModel;
212        }
213
214        public FindRelationListModel() {
215            this(new DefaultListSelectionModel());
216        }
217
218        public DefaultListSelectionModel getSelectionModel() {
219            return selectionModel;
220        }
221
222        @Override
223        public int getSize() {
224            return relations.size();
225        }
226
227        @Override
228        public Relation getElementAt(int index) {
229            return relations.get(index);
230        }
231
232        public void setRelations(Collection<Relation> relations) {
233            int selectedIndex = selectionModel.getMinSelectionIndex();
234            Relation sel = selectedIndex < 0 ? null : getElementAt(selectedIndex);
235
236            this.relations.clear();
237            selectionModel.clearSelection();
238            if (relations != null) {
239                this.relations.addAll(relations);
240            }
241            fireIntervalAdded(this, 0, getSize());
242
243            if (sel != null) {
244                selectedIndex = this.relations.indexOf(sel);
245                if (selectedIndex >= 0) {
246                    selectionModel.addSelectionInterval(selectedIndex, selectedIndex);
247                }
248            }
249            if (selectionModel.isSelectionEmpty() && !this.relations.isEmpty()) {
250                selectionModel.addSelectionInterval(0, 0);
251            }
252        }
253    }
254}
Note: See TracBrowser for help on using the repository browser.