source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java @ 11452

Last change on this file since 11452 was 11452, checked in by Don-vip, 2 years ago

sonar - fb-contrib:SEO_SUBOPTIMAL_EXPRESSION_ORDER - Performance - Method orders expressions in a conditional in a sub optimal way

  • Property svn:eol-style set to native
File size: 12.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trc;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.Color;
9import java.awt.Font;
10import java.awt.Graphics;
11import java.awt.Graphics2D;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.HashSet;
15import java.util.LinkedList;
16import java.util.List;
17
18import javax.swing.BorderFactory;
19import javax.swing.JLabel;
20import javax.swing.JOptionPane;
21import javax.swing.table.AbstractTableModel;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
25import org.openstreetmap.josm.data.osm.DataSet;
26import org.openstreetmap.josm.data.osm.Filter;
27import org.openstreetmap.josm.data.osm.Filter.FilterPreferenceEntry;
28import org.openstreetmap.josm.data.osm.FilterMatcher;
29import org.openstreetmap.josm.data.osm.FilterWorker;
30import org.openstreetmap.josm.data.osm.Node;
31import org.openstreetmap.josm.data.osm.OsmPrimitive;
32import org.openstreetmap.josm.tools.Utils;
33
34/**
35 *
36 * @author Petr_Dlouhý
37 */
38public class FilterTableModel extends AbstractTableModel {
39
40    public static final int COL_ENABLED = 0;
41    public static final int COL_HIDING = 1;
42    public static final int COL_TEXT = 2;
43    public static final int COL_INVERTED = 3;
44
45    // number of primitives that are disabled but not hidden
46    public int disabledCount;
47    // number of primitives that are disabled and hidden
48    public int disabledAndHiddenCount;
49
50    /**
51     * Constructs a new {@code FilterTableModel}.
52     */
53    public FilterTableModel() {
54        loadPrefs();
55    }
56
57    private final transient List<Filter> filters = new LinkedList<>();
58    private final transient FilterMatcher filterMatcher = new FilterMatcher();
59
60    private void updateFilters() {
61        filterMatcher.reset();
62        for (Filter filter : filters) {
63            try {
64                filterMatcher.add(filter);
65            } catch (ParseError e) {
66                Main.error(e);
67                JOptionPane.showMessageDialog(
68                        Main.parent,
69                        tr("<html>Error in filter <code>{0}</code>:<br>{1}", Utils.shortenString(filter.text, 80), e.getMessage()),
70                        tr("Error in filter"),
71                        JOptionPane.ERROR_MESSAGE);
72                filter.enable = false;
73                savePrefs();
74            }
75        }
76        executeFilters();
77    }
78
79    public void executeFilters() {
80        DataSet ds = Main.getLayerManager().getEditDataSet();
81        boolean changed = false;
82        if (ds == null) {
83            disabledAndHiddenCount = 0;
84            disabledCount = 0;
85            changed = true;
86        } else {
87            final Collection<OsmPrimitive> deselect = new HashSet<>();
88
89            ds.beginUpdate();
90            try {
91
92                final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
93
94                changed = FilterWorker.executeFilters(all, filterMatcher);
95
96                disabledCount = 0;
97                disabledAndHiddenCount = 0;
98                // collect disabled and selected the primitives
99                for (OsmPrimitive osm : all) {
100                    if (osm.isDisabled()) {
101                        disabledCount++;
102                        if (osm.isSelected()) {
103                            deselect.add(osm);
104                        }
105                        if (osm.isDisabledAndHidden()) {
106                            disabledAndHiddenCount++;
107                        }
108                    }
109                }
110                disabledCount -= disabledAndHiddenCount;
111            } finally {
112                ds.endUpdate();
113            }
114
115            if (!deselect.isEmpty()) {
116                ds.clearSelection(deselect);
117            }
118        }
119
120        if (changed && Main.isDisplayingMapView()) {
121            Main.map.mapView.repaint();
122            Main.map.filterDialog.updateDialogHeader();
123        }
124    }
125
126    public void executeFilters(Collection<? extends OsmPrimitive> primitives) {
127        DataSet ds = Main.getLayerManager().getEditDataSet();
128        if (ds == null)
129            return;
130
131        boolean changed = false;
132        List<OsmPrimitive> deselect = new ArrayList<>();
133
134        ds.beginUpdate();
135        try {
136            for (int i = 0; i < 2; i++) {
137                for (OsmPrimitive primitive: primitives) {
138
139                    if (i == 0 && primitive instanceof Node) {
140                        continue;
141                    }
142
143                    if (i == 1 && !(primitive instanceof Node)) {
144                        continue;
145                    }
146
147                    if (primitive.isDisabled()) {
148                        disabledCount--;
149                    }
150                    if (primitive.isDisabledAndHidden()) {
151                        disabledAndHiddenCount--;
152                    }
153                    changed = changed | FilterWorker.executeFilters(primitive, filterMatcher);
154                    if (primitive.isDisabled()) {
155                        disabledCount++;
156                    }
157                    if (primitive.isDisabledAndHidden()) {
158                        disabledAndHiddenCount++;
159                    }
160
161                    if (primitive.isSelected() && primitive.isDisabled()) {
162                        deselect.add(primitive);
163                    }
164
165                }
166            }
167        } finally {
168            ds.endUpdate();
169        }
170
171        if (changed) {
172            Main.map.mapView.repaint();
173            Main.map.filterDialog.updateDialogHeader();
174            ds.clearSelection(deselect);
175        }
176
177    }
178
179    public void clearFilterFlags() {
180        DataSet ds = Main.getLayerManager().getEditDataSet();
181        if (ds != null) {
182            FilterWorker.clearFilterFlags(ds.allPrimitives());
183        }
184        disabledCount = 0;
185        disabledAndHiddenCount = 0;
186    }
187
188    private void loadPrefs() {
189        List<FilterPreferenceEntry> entries = Main.pref.getListOfStructs("filters.entries", null, FilterPreferenceEntry.class);
190        if (entries != null) {
191            for (FilterPreferenceEntry e : entries) {
192                filters.add(new Filter(e));
193            }
194            updateFilters();
195        }
196    }
197
198    private void savePrefs() {
199        Collection<FilterPreferenceEntry> entries = new ArrayList<>();
200        for (Filter flt : filters) {
201            entries.add(flt.getPreferenceEntry());
202        }
203        Main.pref.putListOfStructs("filters.entries", entries, FilterPreferenceEntry.class);
204    }
205
206    public void addFilter(Filter f) {
207        filters.add(f);
208        savePrefs();
209        updateFilters();
210        fireTableRowsInserted(filters.size() - 1, filters.size() - 1);
211    }
212
213    public void moveDownFilter(int i) {
214        if (i >= filters.size() - 1)
215            return;
216        filters.add(i + 1, filters.remove(i));
217        savePrefs();
218        updateFilters();
219        fireTableRowsUpdated(i, i + 1);
220    }
221
222    public void moveUpFilter(int i) {
223        if (i == 0)
224            return;
225        filters.add(i - 1, filters.remove(i));
226        savePrefs();
227        updateFilters();
228        fireTableRowsUpdated(i - 1, i);
229    }
230
231    public void removeFilter(int i) {
232        filters.remove(i);
233        savePrefs();
234        updateFilters();
235        fireTableRowsDeleted(i, i);
236    }
237
238    public void setFilter(int i, Filter f) {
239        filters.set(i, f);
240        savePrefs();
241        updateFilters();
242        fireTableRowsUpdated(i, i);
243    }
244
245    public Filter getFilter(int i) {
246        return filters.get(i);
247    }
248
249    @Override
250    public int getRowCount() {
251        return filters.size();
252    }
253
254    @Override
255    public int getColumnCount() {
256        return 5;
257    }
258
259    @Override
260    public String getColumnName(int column) {
261        String[] names = {/* translators notes must be in front */
262                /* column header: enable filter */trc("filter", "E"),
263                /* column header: hide filter */trc("filter", "H"),
264                /* column header: filter text */trc("filter", "Text"),
265                /* column header: inverted filter */trc("filter", "I"),
266                /* column header: filter mode */trc("filter", "M")};
267        return names[column];
268    }
269
270    @Override
271    public Class<?> getColumnClass(int column) {
272        Class<?>[] classes = {Boolean.class, Boolean.class, String.class, Boolean.class, String.class};
273        return classes[column];
274    }
275
276    public boolean isCellEnabled(int row, int column) {
277        if (!filters.get(row).enable && column != 0)
278            return false;
279        return true;
280    }
281
282    @Override
283    public boolean isCellEditable(int row, int column) {
284        if (!filters.get(row).enable && column != 0)
285            return false;
286        if (column < 4)
287            return true;
288        return false;
289    }
290
291    @Override
292    public void setValueAt(Object aValue, int row, int column) {
293        if (row >= filters.size()) {
294            return;
295        }
296        Filter f = filters.get(row);
297        switch (column) {
298        case COL_ENABLED:
299            f.enable = (Boolean) aValue;
300            savePrefs();
301            updateFilters();
302            fireTableRowsUpdated(row, row);
303            break;
304        case COL_HIDING:
305            f.hiding = (Boolean) aValue;
306            savePrefs();
307            updateFilters();
308            break;
309        case COL_TEXT:
310            f.text = (String) aValue;
311            savePrefs();
312            break;
313        case COL_INVERTED:
314            f.inverted = (Boolean) aValue;
315            savePrefs();
316            updateFilters();
317            break;
318        default: // Do nothing
319        }
320        if (column != 0) {
321            fireTableCellUpdated(row, column);
322        }
323    }
324
325    @Override
326    public Object getValueAt(int row, int column) {
327        if (row >= filters.size()) {
328            return null;
329        }
330        Filter f = filters.get(row);
331        switch (column) {
332        case COL_ENABLED:
333            return f.enable;
334        case COL_HIDING:
335            return f.hiding;
336        case COL_TEXT:
337            return f.text;
338        case COL_INVERTED:
339            return f.inverted;
340        case 4:
341            switch (f.mode) { /* translators notes must be in front */
342            case replace: /* filter mode: replace */
343                return trc("filter", "R");
344            case add: /* filter mode: add */
345                return trc("filter", "A");
346            case remove: /* filter mode: remove */
347                return trc("filter", "D");
348            case in_selection: /* filter mode: in selection */
349                return trc("filter", "F");
350            default:
351                Main.warn("Unknown filter mode: " + f.mode);
352            }
353            break;
354        default: // Do nothing
355        }
356        return null;
357    }
358
359    /**
360     * On screen display label
361     */
362    private static class OSDLabel extends JLabel {
363        OSDLabel(String text) {
364            super(text);
365            setOpaque(true);
366            setForeground(Color.black);
367            setBackground(new Color(0, 0, 0, 0));
368            setFont(getFont().deriveFont(Font.PLAIN));
369            setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
370        }
371
372        @Override
373        public void paintComponent(Graphics g) {
374            g.setColor(new Color(255, 255, 255, 140));
375            g.fillRoundRect(getX(), getY(), getWidth(), getHeight(), 10, 10);
376            super.paintComponent(g);
377        }
378    }
379
380    private final OSDLabel lblOSD = new OSDLabel("");
381
382    public void drawOSDText(Graphics2D g) {
383        String message = "<html>" + tr("<h2>Filter active</h2>");
384
385        if (disabledCount == 0 && disabledAndHiddenCount == 0)
386            return;
387
388        if (disabledAndHiddenCount != 0) {
389            /* for correct i18n of plural forms - see #9110 */
390            message += trn("<p><b>{0}</b> object hidden", "<p><b>{0}</b> objects hidden", disabledAndHiddenCount, disabledAndHiddenCount);
391        }
392
393        if (disabledAndHiddenCount != 0 && disabledCount != 0) {
394            message += "<br>";
395        }
396
397        if (disabledCount != 0) {
398            /* for correct i18n of plural forms - see #9110 */
399            message += trn("<b>{0}</b> object disabled", "<b>{0}</b> objects disabled", disabledCount, disabledCount);
400        }
401
402        message += tr("</p><p>Close the filter dialog to see all objects.<p></html>");
403
404        lblOSD.setText(message);
405        lblOSD.setSize(lblOSD.getPreferredSize());
406
407        int dx = Main.map.mapView.getWidth() - lblOSD.getPreferredSize().width - 15;
408        int dy = 15;
409        g.translate(dx, dy);
410        lblOSD.paintComponent(g);
411        g.translate(-dx, -dy);
412    }
413
414    /**
415     * Returns the list of filters.
416     * @return the list of filters
417     */
418    public List<Filter> getFilters() {
419        return filters;
420    }
421}
Note: See TracBrowser for help on using the repository browser.