Ticket #24482: autofilter_04_multi.patch
| File autofilter_04_multi.patch, 13.8 KB (added by , 6 months ago) |
|---|
-
src/org/openstreetmap/josm/gui/MapView.java
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java index 978c3f612b..f4034e72a4 100644
a b LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener { 620 620 } 621 621 622 622 MapFrame map = MainApplication.getMap(); 623 if (AutoFilterManager.getInstance().getCurrent AutoFilter() != null) {623 if (AutoFilterManager.getInstance().getCurrentCombinedFilter() != null) { 624 624 AutoFilterManager.getInstance().drawOSDText(tempG); 625 625 } else if (MainApplication.isDisplayingMapView() && map.filterDialog != null) { 626 626 map.filterDialog.drawOSDText(tempG); -
src/org/openstreetmap/josm/gui/autofilter/AutoFilterButton.java
diff --git a/src/org/openstreetmap/josm/gui/autofilter/AutoFilterButton.java b/src/org/openstreetmap/josm/gui/autofilter/AutoFilterButton.java index d12685529b..ec14133f2c 100644
a b public class AutoFilterButton extends JButton { 35 35 super(new JosmAction(filter.getLabel(), null, filter.getDescription(), null, false) { 36 36 @Override 37 37 public synchronized void actionPerformed(ActionEvent e) { 38 38 39 AutoFilterManager afm = AutoFilterManager.getInstance(); 39 if (filter.equals(afm.getCurrentAutoFilter())) { 40 afm.setCurrentAutoFilter(null); 41 MainApplication.getMap().filterDialog.getFilterModel().executeFilters(true); 42 } else { 40 41 if (afm.getCurrentAutoFilters().isEmpty()) { 43 42 afm.setCurrentAutoFilter(filter); 43 } else { 44 if ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0 45 || (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) { 46 if (afm.getCurrentAutoFilters().contains(filter)) { 47 afm.removeCurrentAutoFilter(filter); 48 } else { 49 afm.addCurrentAutoFilter(filter); 50 } 51 } else { 52 if (afm.getCurrentAutoFilters().size() == 1 && afm.getCurrentAutoFilters().contains(filter)) { 53 afm.setCurrentAutoFilter(null); 54 } else { 55 afm.setCurrentAutoFilter(filter); 56 } 57 } 44 58 } 59 45 60 } 46 61 }); 47 62 this.filter = filter; … … public class AutoFilterButton extends JButton { 54 69 protected void paintComponent(Graphics g) { 55 70 if (getModel().isPressed()) { 56 71 g.setColor(PROP_COLOR.get().darker().darker()); 57 } else if (getModel().isRollover() || AutoFilterManager.getInstance().getCurrentAutoFilter () == filter) {72 } else if (getModel().isRollover() || AutoFilterManager.getInstance().getCurrentAutoFilters().contains(filter)) { 58 73 g.setColor(PROP_COLOR.get().darker()); 59 74 } else { 60 75 g.setColor(PROP_COLOR.get()); -
src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java
diff --git a/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java b/src/org/openstreetmap/josm/gui/autofilter/AutoFilterManager.java index 5643cf12ca..ba5514dc03 100644
a b import java.util.NavigableSet; 14 14 import java.util.Objects; 15 15 import java.util.TreeMap; 16 16 import java.util.TreeSet; 17 import java.util.stream.Collectors; 17 18 18 19 import org.openstreetmap.josm.actions.mapmode.MapMode; 19 20 import org.openstreetmap.josm.data.osm.BBox; … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 109 110 AutoFilterRule enabledRule; 110 111 111 112 /** 112 * The currently selected auto filter, if any. 113 * The currently selected auto filters, if any. 114 * If more than one auto filter is active, elements will match if they match at least one of them. 113 115 */ 114 private AutoFilter currentAutoFilter;116 private final List<AutoFilter> currentAutoFilters = new ArrayList<>(); 115 117 116 118 /** 117 119 * Returns the unique instance. … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 139 141 && enabledRule.getMinZoomLevel() <= Selector.GeneralSelector.scale2level(map.mapView.getDist100Pixel())) { 140 142 // Retrieve the values from current rule visible on screen 141 143 NavigableSet<Integer> values = getNumericValues(); 142 // Make sure current auto filter button remains visible even if no data is found, to allow user to disable it143 if (currentAutoFilter != null) {144 // Make sure current auto filter buttons remain visible even if no data is found, to allow user to disable them 145 for (var currentAutoFilter : currentAutoFilters) { 144 146 values.add(currentAutoFilter.getFilter().value); 145 147 } 146 148 if (!values.equals(buttons.keySet())) { … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 184 186 } 185 187 } 186 188 189 /** The combination of multiple {@link CompiledFilter}s */ 190 static class CombinedFilter extends Filter implements MatchSupplier { 191 192 private final List<CompiledFilter> filters; 193 194 CombinedFilter(List<CompiledFilter> filters) { 195 196 if (filters == null || filters.isEmpty()) throw new IllegalArgumentException("no filters provided"); 197 198 this.filters = filters; 199 200 boolean hiding = filters.get(0).hiding; 201 String key = filters.get(0).rule.getKey(); 202 List<String> values = new ArrayList<>(); 203 204 for (CompiledFilter filter : filters) { 205 if (hiding != filter.hiding) throw new IllegalArgumentException("non-matching hiding properties"); 206 if (!Objects.equals(key, filter.rule.getKey())) throw new IllegalArgumentException("non-matching keys"); 207 values.add(filter.rule.formatValue(filter.value)); 208 } 209 210 this.hiding = hiding; 211 this.enable = true; 212 this.inverted = true; 213 this.text = key + "~" + String.join("|", values); 214 215 } 216 217 @Override 218 public SearchCompiler.Match get() { 219 return new SearchCompiler.Match() { 220 @Override 221 public boolean match(OsmPrimitive osm) { 222 return filters.stream().anyMatch(filter -> filter.get().match(osm)); 223 } 224 }; 225 } 226 227 @Override 228 public int hashCode() { 229 return 31 * super.hashCode() + Objects.hash(filters); 230 } 231 232 @Override 233 public boolean equals(Object obj) { 234 if (this == obj) 235 return true; 236 if (!super.equals(obj) || getClass() != obj.getClass()) 237 return false; 238 CombinedFilter other = (CombinedFilter) obj; 239 return Objects.equals(filters, other.filters); 240 } 241 } 242 187 243 static class Match extends SearchCompiler.Match { 188 244 final AutoFilterRule rule; 189 245 final int value; … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 226 282 String label = enabledRule.formatValue(value); 227 283 AutoFilter autoFilter = new AutoFilter(label, filter.text, filter); 228 284 AutoFilterButton button = new AutoFilterButton(autoFilter); 229 if ( autoFilter.equals(currentAutoFilter)) {285 if (currentAutoFilters.contains(autoFilter)) { 230 286 button.getModel().setPressed(true); 231 287 } 232 288 maxWidth = Math.max(maxWidth, button.getPreferredSize().width); … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 325 381 } 326 382 327 383 private synchronized void updateFiltersFull() { 328 if ( currentAutoFilter != null) {384 if (!currentAutoFilters.isEmpty()) { 329 385 model.executeFilters(); 330 386 } 331 387 } 332 388 333 389 private synchronized void updateFiltersEvent(AbstractDatasetChangedEvent event, boolean affectedOnly) { 334 if ( currentAutoFilter != null) {390 if (!currentAutoFilters.isEmpty()) { 335 391 Collection<? extends OsmPrimitive> prims = event.getPrimitives(); 336 392 model.executeFilters(affectedOnly ? FilterModel.getAffectedPrimitives(prims) : prims); 337 393 } … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 394 450 } 395 451 396 452 /** 397 * Returns the currently selected auto filter , if any.398 * @return the currently selected auto filter , or null453 * Returns the currently selected auto filters, if any. 454 * @return the currently selected auto filters. Can be empty. 399 455 */ 400 public synchronized AutoFilter getCurrentAutoFilter() { 401 return currentAutoFilter; 456 public synchronized List<AutoFilter> getCurrentAutoFilters() { 457 return currentAutoFilters; 458 } 459 460 /** 461 * Returns a combination of all {@link #getCurrentAutoFilters()}, if any. 462 * @return a single combined filter, or null 463 */ 464 public Filter getCurrentCombinedFilter() { 465 if (currentAutoFilters.isEmpty()) { 466 return null; 467 } else if (currentAutoFilters.size() == 1) { 468 return currentAutoFilters.get(0).getFilter(); 469 } else { 470 return new CombinedFilter(currentAutoFilters.stream().map(AutoFilter::getFilter).collect(Collectors.toList())); 471 } 402 472 } 403 473 404 474 /** … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 406 476 * @param autoFilter the currently selected auto filter, or null 407 477 */ 408 478 public synchronized void setCurrentAutoFilter(AutoFilter autoFilter) { 409 model.clearFilters(); 410 currentAutoFilter = autoFilter; 479 currentAutoFilters.clear(); 411 480 if (autoFilter != null) { 412 model.addFilter(autoFilter.getFilter()); 481 currentAutoFilters.add(autoFilter); 482 } 483 updateModelFilters(); 484 } 485 486 public synchronized void addCurrentAutoFilter(AutoFilter autoFilter) { 487 if (!currentAutoFilters.contains(autoFilter)) { 488 currentAutoFilters.add(autoFilter); 489 updateModelFilters(); 490 } 491 } 492 493 public synchronized void removeCurrentAutoFilter(AutoFilter autoFilter) { 494 if (currentAutoFilters.contains(autoFilter)) { 495 currentAutoFilters.removeIf(it -> Objects.equals(it, autoFilter)); 496 updateModelFilters(); 497 } 498 } 499 500 private synchronized void updateModelFilters() { 501 model.clearFilters(); 502 if (currentAutoFilters.isEmpty()) { 503 if (MainApplication.getMap() != null) { 504 MainApplication.getMap().filterDialog.getFilterModel().executeFilters(true); 505 } 506 } else { 507 model.addFilter(getCurrentCombinedFilter()); 413 508 model.executeFilters(); 414 if (model.isChanged()) { 415 OsmDataLayer dataLayer = MainApplication.getLayerManager().getActiveDataLayer(); 416 if (dataLayer != null) { 417 dataLayer.invalidate(); 418 } 509 // update the data layer (necessary even if model.isChanged() == false to update the OSDText) 510 OsmDataLayer dataLayer = MainApplication.getLayerManager().getActiveDataLayer(); 511 if (dataLayer != null) { 512 dataLayer.invalidate(); 419 513 } 420 514 } 421 515 } … … implements ZoomChangeListener, MapModeChangeListener, DataSetListener, Preferenc 425 519 * @param g The graphics to draw that text on. 426 520 */ 427 521 public synchronized void drawOSDText(Graphics2D g) { 522 String filterText = Objects.requireNonNull(getCurrentCombinedFilter()).text; 523 String lengthLimitedFilterText = filterText.length() > 18 ? filterText.substring(0, 18) + "…" : filterText; 428 524 model.drawOSDText(g, lblOSD, 429 tr("<h2>Filter active: {0}</h2>", currentAutoFilter.getFilter().text),525 tr("<h2>Filter active: {0}</h2>", lengthLimitedFilterText), 430 526 tr("</p><p>Click again on filter button to see all objects.</p></html>")); 431 527 } 432 528 -
src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java
diff --git a/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java b/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java index 595dbd9a9c..fc8553f65e 100644
a b public class FilterTableModel extends AbstractTableModel implements SortableTabl 98 98 * @since 14206 99 99 */ 100 100 public void executeFilters(boolean force) { 101 if (AutoFilterManager.getInstance().getCurrent AutoFilter() == null && (force || model.hasFilters())) {101 if (AutoFilterManager.getInstance().getCurrentCombinedFilter() == null && (force || model.hasFilters())) { 102 102 model.executeFilters(); 103 103 updateMap(); 104 104 } … … public class FilterTableModel extends AbstractTableModel implements SortableTabl 111 111 * @since 14206 112 112 */ 113 113 public void executeFilters(Collection<? extends OsmPrimitive> primitives, boolean force) { 114 if (AutoFilterManager.getInstance().getCurrent AutoFilter() == null && (force || model.hasFilters())) {114 if (AutoFilterManager.getInstance().getCurrentCombinedFilter() == null && (force || model.hasFilters())) { 115 115 model.executeFilters(primitives); 116 116 updateMap(); 117 117 }
