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

Last change on this file since 4077 was 3926, checked in by jttt, 13 years ago

Fix #5998 Filtered + hidden objects are displayed after startup

  • Property svn:eol-style set to native
File size: 11.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;
6
7import java.awt.Color;
8import java.awt.Font;
9import java.awt.Graphics;
10import java.awt.Graphics2D;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.HashSet;
14import java.util.LinkedList;
15import java.util.List;
16import java.util.Map;
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;
32
33/**
34 *
35 * @author Petr_Dlouhý
36 */
37public class FilterTableModel extends AbstractTableModel {
38
39 // number of primitives that are disabled but not hidden
40 public int disabledCount;
41 // number of primitives that are disabled and hidden
42 public int disabledAndHiddenCount;
43
44 public FilterTableModel() {
45 loadPrefs();
46 }
47
48 private final List<Filter> filters = new LinkedList<Filter>();
49 private final FilterMatcher filterMatcher = new FilterMatcher();
50
51 private void updateFilters() {
52 try {
53 filterMatcher.update(filters);
54 executeFilters();
55 } catch (ParseError e) {
56 JOptionPane.showMessageDialog(
57 Main.parent,
58 e.getMessage(),
59 tr("Error in filter"),
60 JOptionPane.ERROR_MESSAGE);
61 }
62 }
63
64 public void executeFilters() {
65 DataSet ds = Main.main.getCurrentDataSet();
66 boolean changed = false;
67 if (ds == null) {
68 disabledAndHiddenCount = 0;
69 disabledCount = 0;
70 changed = true;
71 } else {
72 final Collection<OsmPrimitive> deselect = new HashSet<OsmPrimitive>();
73
74 ds.beginUpdate();
75 try {
76
77 final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
78
79 changed = FilterWorker.executeFilters(all, filterMatcher);
80
81 disabledCount = 0;
82 disabledAndHiddenCount = 0;
83 // collect disabled and selected the primitives
84 for (OsmPrimitive osm : all) {
85 if (osm.isDisabled()) {
86 disabledCount++;
87 if (osm.isSelected()) {
88 deselect.add(osm);
89 }
90 if (osm.isDisabledAndHidden()) {
91 disabledAndHiddenCount++;
92 }
93 }
94 }
95 disabledCount -= disabledAndHiddenCount;
96 } finally {
97 ds.endUpdate();
98 }
99
100 if (!deselect.isEmpty()) {
101 ds.clearSelection(deselect);
102 }
103 }
104
105 if (Main.isDisplayingMapView() && changed) {
106 Main.map.mapView.repaint();
107 Main.map.filterDialog.updateDialogHeader();
108 }
109 }
110
111 public void executeFilters(Collection<? extends OsmPrimitive> primitives) {
112 DataSet ds = Main.main.getCurrentDataSet();
113 if (ds == null)
114 return;
115
116 boolean changed = false;
117 List<OsmPrimitive> deselect = new ArrayList<OsmPrimitive>();
118
119 ds.beginUpdate();
120 try {
121 for (int i=0; i<2; i++) {
122 for (OsmPrimitive primitive: primitives) {
123
124 if (i == 0 && primitive instanceof Node) {
125 continue;
126 }
127
128 if (i == 1 && !(primitive instanceof Node)) {
129 continue;
130 }
131
132 if (primitive.isDisabled()) {
133 disabledCount--;
134 }
135 if (primitive.isDisabledAndHidden()) {
136 disabledAndHiddenCount--;
137 }
138 changed = changed | FilterWorker.executeFilters(primitive, filterMatcher);
139 if (primitive.isDisabled()) {
140 disabledCount++;
141 }
142 if (primitive.isDisabledAndHidden()) {
143 disabledAndHiddenCount++;
144 }
145
146 if (primitive.isSelected() && primitive.isDisabled()) {
147 deselect.add(primitive);
148 }
149
150 }
151 }
152 } finally {
153 ds.endUpdate();
154 }
155
156 if (changed) {
157 Main.map.mapView.repaint();
158 Main.map.filterDialog.updateDialogHeader();
159 ds.clearSelection(deselect);
160 }
161
162 }
163
164 public void clearFilterFlags() {
165 DataSet ds = Main.main.getCurrentDataSet();
166 if (ds != null) {
167 FilterWorker.clearFilterFlags(ds.allPrimitives());
168 }
169 disabledCount = 0;
170 disabledAndHiddenCount = 0;
171 }
172
173 private void loadPrefs() {
174 if (!loadPrefsImpl()) {
175 loadPrefsOld();
176 savePrefs();
177 }
178 }
179
180 private boolean loadPrefsImpl() {
181 List<FilterPreferenceEntry> entries = Main.pref.getListOfStructs("filters.entries", null, FilterPreferenceEntry.class);
182 if (entries == null)
183 return false;
184 for (FilterPreferenceEntry e : entries) {
185 filters.add(new Filter(e));
186 }
187 updateFilters();
188 return true;
189 }
190
191 @Deprecated
192 private void loadPrefsOld() {
193 Map<String, String> prefs = Main.pref.getAllPrefix("filters.filter");
194 for (String value : prefs.values()) {
195 filters.add(new Filter(value));
196 }
197 updateFilters();
198 }
199
200 private void savePrefs() {
201 Collection<FilterPreferenceEntry> entries = new ArrayList<FilterPreferenceEntry>();
202 for (Filter flt : filters) {
203 entries.add(flt.getPreferenceEntry());
204 }
205 Main.pref.putListOfStructs("filters.entries", entries, FilterPreferenceEntry.class);
206 }
207
208 public void addFilter(Filter f) {
209 filters.add(f);
210 savePrefs();
211 updateFilters();
212 fireTableRowsInserted(filters.size() - 1, filters.size() - 1);
213 }
214
215 public void moveDownFilter(int i) {
216 if (i >= filters.size() - 1)
217 return;
218 filters.add(i + 1, filters.remove(i));
219 savePrefs();
220 updateFilters();
221 fireTableRowsUpdated(i, i + 1);
222 }
223
224 public void moveUpFilter(int i) {
225 if (i == 0)
226 return;
227 filters.add(i - 1, filters.remove(i));
228 savePrefs();
229 updateFilters();
230 fireTableRowsUpdated(i - 1, i);
231 }
232
233 public void removeFilter(int i) {
234 filters.remove(i);
235 savePrefs();
236 updateFilters();
237 fireTableRowsDeleted(i, i);
238 }
239
240 public void setFilter(int i, Filter f) {
241 filters.set(i, f);
242 savePrefs();
243 updateFilters();
244 fireTableRowsUpdated(i, i);
245 }
246
247 public Filter getFilter(int i) {
248 return filters.get(i);
249 }
250
251 public int getRowCount() {
252 return filters.size();
253 }
254
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 Filter f = filters.get(row);
294 switch (column) {
295 case 0:
296 f.enable = (Boolean) aValue;
297 savePrefs();
298 updateFilters();
299 fireTableRowsUpdated(row, row);
300 break;
301 case 1:
302 f.hiding = (Boolean) aValue;
303 savePrefs();
304 updateFilters();
305 break;
306 case 2:
307 f.text = (String) aValue;
308 savePrefs();
309 break;
310 case 3:
311 f.inverted = (Boolean) aValue;
312 savePrefs();
313 updateFilters();
314 break;
315 }
316 if (column != 0) {
317 fireTableCellUpdated(row, column);
318 }
319 }
320
321 public Object getValueAt(int row, int column) {
322 Filter f = filters.get(row);
323 switch (column) {
324 case 0:
325 return f.enable;
326 case 1:
327 return f.hiding;
328 case 2:
329 return f.text;
330 case 3:
331 return f.inverted;
332 case 4:
333 switch (f.mode) { /* translators notes must be in front */
334 case replace: /* filter mode: replace */
335 return trc("filter", "R");
336 case add: /* filter mode: add */
337 return trc("filter", "A");
338 case remove: /* filter mode: remove */
339 return trc("filter", "D");
340 case in_selection: /* filter mode: in selection */
341 return trc("filter", "F");
342 }
343 }
344 return null;
345 }
346
347 /**
348 * On screen display label
349 */
350 private static class OSDLabel extends JLabel {
351 public OSDLabel(String text) {
352 super(text);
353 setOpaque(true);
354 setForeground(Color.black);
355 setBackground(new Color(0, 0, 0, 0));
356 setFont(getFont().deriveFont(Font.PLAIN));
357 setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
358 }
359
360 @Override
361 public void paintComponent(Graphics g) {
362 g.setColor(new Color(255, 255, 255, 140));
363 g.fillRoundRect(getX(), getY(), getWidth(), getHeight(), 10, 10);
364 super.paintComponent(g);
365 }
366 }
367
368 private OSDLabel lblOSD = new OSDLabel("");
369
370 public void drawOSDText(Graphics2D g) {
371 String message = "<html>" + tr("<h2>Filter active</h2>");
372
373 if (disabledCount == 0 && disabledAndHiddenCount == 0)
374 return;
375
376 if (disabledAndHiddenCount != 0) {
377 message += tr("<p><b>{0}</b> objects hidden", disabledAndHiddenCount);
378 }
379
380 if (disabledAndHiddenCount != 0 && disabledCount != 0) {
381 message += "<br>";
382 }
383
384 if (disabledCount != 0) {
385 message += tr("<b>{0}</b> objects disabled", disabledCount);
386 }
387
388 message += tr("</p><p>Close the filter dialog to see all objects.<p></html>");
389
390 lblOSD.setText(message);
391 lblOSD.setSize(lblOSD.getPreferredSize());
392
393 int dx = Main.map.mapView.getWidth() - lblOSD.getPreferredSize().width - 15;
394 int dy = 15;
395 g.translate(dx, dy);
396 lblOSD.paintComponent(g);
397 g.translate(-dx, -dy);
398 }
399}
Note: See TracBrowser for help on using the repository browser.