Changeset 12400 in josm for trunk/src


Ignore:
Timestamp:
2017-06-11T22:26:15+02:00 (7 years ago)
Author:
Don-vip
Message:

see #14929 - Automatic filters on numeric tag values (level, layer, maxspeed, voltage)

Location:
trunk/src/org/openstreetmap/josm
Files:
6 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapView.java

    r12391 r12400  
    5050import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
    5151import org.openstreetmap.josm.gui.MapViewState.MapViewRectangle;
     52import org.openstreetmap.josm.gui.autofilter.AutoFilterManager;
    5253import org.openstreetmap.josm.gui.datatransfer.OsmTransferHandler;
    5354import org.openstreetmap.josm.gui.layer.GpxLayer;
     
    289290            add(c);
    290291        }
     292        if (AutoFilterManager.PROP_AUTO_FILTER_ENABLED.get()) {
     293            AutoFilterManager.getInstance().enableAutoFilterRule(AutoFilterManager.PROP_AUTO_FILTER_RULE.get());
     294        }
    291295        setTransferHandler(new OsmTransferHandler());
    292296    }
     
    558562        }
    559563
    560         if (Main.isDisplayingMapView() && Main.map.filterDialog != null) {
     564        if (AutoFilterManager.getInstance().getCurrentAutoFilter() != null) {
     565            AutoFilterManager.getInstance().drawOSDText(tempG);
     566        } else if (Main.isDisplayingMapView() && Main.map.filterDialog != null) {
    561567            Main.map.filterDialog.drawOSDText(tempG);
    562568        }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/FilterDialog.java

    r12298 r12400  
    1111import java.util.ArrayList;
    1212import java.util.Arrays;
    13 import java.util.Collection;
    14 import java.util.HashSet;
    1513import java.util.List;
    16 import java.util.Set;
    17 import java.util.Stack;
    1814
    1915import javax.swing.AbstractAction;
     
    3228import org.openstreetmap.josm.actions.search.SearchAction;
    3329import org.openstreetmap.josm.data.osm.Filter;
    34 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    35 import org.openstreetmap.josm.data.osm.Relation;
    36 import org.openstreetmap.josm.data.osm.RelationMember;
    37 import org.openstreetmap.josm.data.osm.Way;
     30import org.openstreetmap.josm.data.osm.FilterModel;
    3831import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
    3932import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
     
    9487        DatasetEventManager.getInstance().removeDatasetListener(this);
    9588        MapFrame.removeMapModeChangeListener(this);
    96         filterModel.clearFilterFlags();
     89        filterModel.model.clearFilterFlags();
    9790        Main.map.mapView.repaint();
    9891    }
     
    302295    public void updateDialogHeader() {
    303296        SwingUtilities.invokeLater(() -> setTitle(
    304                 tr("Filter Hidden:{0} Disabled:{1}", filterModel.disabledAndHiddenCount, filterModel.disabledCount)));
     297                tr("Filter Hidden:{0} Disabled:{1}",
     298                        filterModel.model.getDisabledAndHiddenCount(), filterModel.model.getDisabledCount())));
    305299    }
    306300
     
    313307    }
    314308
    315     /**
    316      * Returns the list of primitives whose filtering can be affected by change in primitive
    317      * @param primitives list of primitives to check
    318      * @return List of primitives whose filtering can be affected by change in source primitives
    319      */
    320     private static Collection<OsmPrimitive> getAffectedPrimitives(Collection<? extends OsmPrimitive> primitives) {
    321         // Filters can use nested parent/child expression so complete tree is necessary
    322         Set<OsmPrimitive> result = new HashSet<>();
    323         Stack<OsmPrimitive> stack = new Stack<>();
    324         stack.addAll(primitives);
    325 
    326         while (!stack.isEmpty()) {
    327             OsmPrimitive p = stack.pop();
    328 
    329             if (result.contains(p)) {
    330                 continue;
    331             }
    332 
    333             result.add(p);
    334 
    335             if (p instanceof Way) {
    336                 for (OsmPrimitive n: ((Way) p).getNodes()) {
    337                     stack.push(n);
    338                 }
    339             } else if (p instanceof Relation) {
    340                 for (RelationMember rm: ((Relation) p).getMembers()) {
    341                     stack.push(rm.getMember());
    342                 }
    343             }
    344 
    345             for (OsmPrimitive ref: p.getReferrers()) {
    346                 stack.push(ref);
    347             }
    348         }
    349 
    350         return result;
    351     }
    352 
    353309    @Override
    354310    public void dataChanged(DataChangedEvent event) {
     
    378334    @Override
    379335    public void relationMembersChanged(RelationMembersChangedEvent event) {
    380         filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
     336        filterModel.executeFilters(FilterModel.getAffectedPrimitives(event.getPrimitives()));
    381337    }
    382338
    383339    @Override
    384340    public void tagsChanged(TagsChangedEvent event) {
    385         filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
     341        filterModel.executeFilters(FilterModel.getAffectedPrimitives(event.getPrimitives()));
    386342    }
    387343
    388344    @Override
    389345    public void wayNodesChanged(WayNodesChangedEvent event) {
    390         filterModel.executeFilters(getAffectedPrimitives(event.getPrimitives()));
     346        filterModel.executeFilters(FilterModel.getAffectedPrimitives(event.getPrimitives()));
    391347    }
    392348
  • trunk/src/org/openstreetmap/josm/gui/dialogs/FilterTableModel.java

    r12389 r12400  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55import static org.openstreetmap.josm.tools.I18n.trc;
    6 import static org.openstreetmap.josm.tools.I18n.trn;
    76
    87import java.awt.Graphics2D;
    9 import java.util.ArrayList;
    108import java.util.Collection;
    11 import java.util.HashSet;
    12 import java.util.LinkedList;
    139import java.util.List;
    1410
    15 import javax.swing.JOptionPane;
    1611import javax.swing.table.AbstractTableModel;
    1712
    1813import org.openstreetmap.josm.Main;
    19 import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
    20 import org.openstreetmap.josm.data.osm.DataSet;
    2114import org.openstreetmap.josm.data.osm.Filter;
    22 import org.openstreetmap.josm.data.osm.Filter.FilterPreferenceEntry;
    23 import org.openstreetmap.josm.data.osm.FilterMatcher;
    24 import org.openstreetmap.josm.data.osm.FilterWorker;
    25 import org.openstreetmap.josm.data.osm.Node;
     15import org.openstreetmap.josm.data.osm.FilterModel;
    2616import org.openstreetmap.josm.data.osm.OsmPrimitive;
    27 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     17import org.openstreetmap.josm.gui.autofilter.AutoFilterManager;
    2818import org.openstreetmap.josm.gui.widgets.OSDLabel;
    29 import org.openstreetmap.josm.tools.Utils;
    3019
    3120/**
     
    5443
    5544    /**
    56      * number of primitives that are disabled but not hidden
    57      */
    58     public int disabledCount;
    59     /**
    60      * number of primitives that are disabled and hidden
    61      */
    62     public int disabledAndHiddenCount;
     45     * The filter model
     46     */
     47    final FilterModel model = new FilterModel();
    6348
    6449    /**
     
    7459    }
    7560
    76     private final transient List<Filter> filters = new LinkedList<>();
    77     private final transient FilterMatcher filterMatcher = new FilterMatcher();
    78 
    7961    private void updateFilters() {
    80         filterMatcher.reset();
    81         for (Filter filter : filters) {
    82             try {
    83                 filterMatcher.add(filter);
    84             } catch (ParseError e) {
    85                 Main.error(e);
    86                 JOptionPane.showMessageDialog(
    87                         Main.parent,
    88                         tr("<html>Error in filter <code>{0}</code>:<br>{1}",
    89                                 Utils.escapeReservedCharactersHTML(Utils.shortenString(filter.text, 80)),
    90                                 Utils.escapeReservedCharactersHTML(e.getMessage())),
    91                         tr("Error in filter"),
    92                         JOptionPane.ERROR_MESSAGE);
    93                 filter.enable = false;
    94                 savePrefs();
    95             }
    96         }
     62        AutoFilterManager.getInstance().setCurrentAutoFilter(null);
    9763        executeFilters();
    9864    }
     
    10268     */
    10369    public void executeFilters() {
    104         DataSet ds = Main.getLayerManager().getEditDataSet();
    105         boolean changed = false;
    106         if (ds == null) {
    107             disabledAndHiddenCount = 0;
    108             disabledCount = 0;
    109             changed = true;
    110         } else {
    111             final Collection<OsmPrimitive> deselect = new HashSet<>();
    112 
    113             ds.beginUpdate();
    114             try {
    115 
    116                 final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
    117 
    118                 changed = FilterWorker.executeFilters(all, filterMatcher);
    119 
    120                 disabledCount = 0;
    121                 disabledAndHiddenCount = 0;
    122                 // collect disabled and selected the primitives
    123                 for (OsmPrimitive osm : all) {
    124                     if (osm.isDisabled()) {
    125                         disabledCount++;
    126                         if (osm.isSelected()) {
    127                             deselect.add(osm);
    128                         }
    129                         if (osm.isDisabledAndHidden()) {
    130                             disabledAndHiddenCount++;
    131                         }
    132                     }
    133                 }
    134                 disabledCount -= disabledAndHiddenCount;
    135             } finally {
    136                 ds.endUpdate();
    137             }
    138 
    139             if (!deselect.isEmpty()) {
    140                 ds.clearSelection(deselect);
    141             }
    142         }
    143 
    144         if (changed && Main.isDisplayingMapView()) {
     70        if (AutoFilterManager.getInstance().getCurrentAutoFilter() == null) {
     71            model.executeFilters();
    14572            updateMap();
    14673        }
     
    15279     */
    15380    public void executeFilters(Collection<? extends OsmPrimitive> primitives) {
    154         DataSet ds = Main.getLayerManager().getEditDataSet();
    155         if (ds == null)
    156             return;
    157 
    158         boolean changed = false;
    159         List<OsmPrimitive> deselect = new ArrayList<>();
    160 
    161         ds.beginUpdate();
    162         try {
    163             for (int i = 0; i < 2; i++) {
    164                 for (OsmPrimitive primitive: primitives) {
    165 
    166                     if (i == 0 && primitive instanceof Node) {
    167                         continue;
    168                     }
    169 
    170                     if (i == 1 && !(primitive instanceof Node)) {
    171                         continue;
    172                     }
    173 
    174                     if (primitive.isDisabled()) {
    175                         disabledCount--;
    176                     }
    177                     if (primitive.isDisabledAndHidden()) {
    178                         disabledAndHiddenCount--;
    179                     }
    180                     changed |= FilterWorker.executeFilters(primitive, filterMatcher);
    181                     if (primitive.isDisabled()) {
    182                         disabledCount++;
    183                     }
    184                     if (primitive.isDisabledAndHidden()) {
    185                         disabledAndHiddenCount++;
    186                     }
    187 
    188                     if (primitive.isSelected() && primitive.isDisabled()) {
    189                         deselect.add(primitive);
    190                     }
    191 
    192                 }
    193             }
    194         } finally {
    195             ds.endUpdate();
    196         }
    197 
    198         if (changed) {
     81        if (AutoFilterManager.getInstance().getCurrentAutoFilter() == null) {
     82            model.executeFilters(primitives);
    19983            updateMap();
    200             ds.clearSelection(deselect);
    201         }
    202     }
    203 
    204     private static void updateMap() {
    205         OsmDataLayer editLayer = Main.getLayerManager().getEditLayer();
    206         if (editLayer != null) {
    207             editLayer.invalidate();
    208         }
    209         Main.map.filterDialog.updateDialogHeader();
    210     }
    211 
    212     /**
    213      * Clears all filtered flags from all primitives in the dataset
    214      */
    215     public void clearFilterFlags() {
    216         DataSet ds = Main.getLayerManager().getEditDataSet();
    217         if (ds != null) {
    218             FilterWorker.clearFilterFlags(ds.allPrimitives());
    219         }
    220         disabledCount = 0;
    221         disabledAndHiddenCount = 0;
     84        }
     85    }
     86
     87    private void updateMap() {
     88        if (Main.map != null && model.isChanged()) {
     89            Main.map.filterDialog.updateDialogHeader();
     90        }
    22291    }
    22392
    22493    private void loadPrefs() {
    225         List<FilterPreferenceEntry> entries = Main.pref.getListOfStructs("filters.entries", null, FilterPreferenceEntry.class);
    226         if (entries != null) {
    227             for (FilterPreferenceEntry e : entries) {
    228                 filters.add(new Filter(e));
    229             }
    230             updateFilters();
    231         }
     94        model.loadPrefs("filters.entries");
    23295    }
    23396
    23497    private void savePrefs() {
    235         Collection<FilterPreferenceEntry> entries = new ArrayList<>();
    236         for (Filter flt : filters) {
    237             entries.add(flt.getPreferenceEntry());
    238         }
    239         Main.pref.putListOfStructs("filters.entries", entries, FilterPreferenceEntry.class);
     98        model.savePrefs("filters.entries");
    24099    }
    241100
     
    245104     */
    246105    public void addFilter(Filter filter) {
    247         filters.add(filter);
    248         savePrefs();
    249         updateFilters();
    250         fireTableRowsInserted(filters.size() - 1, filters.size() - 1);
     106        if (model.addFilter(filter)) {
     107            savePrefs();
     108            updateFilters();
     109            int size = model.getFiltersCount();
     110            fireTableRowsInserted(size - 1, size - 1);
     111        }
    251112    }
    252113
     
    256117     */
    257118    public void moveDownFilter(int rowIndex) {
    258         if (rowIndex >= filters.size() - 1)
    259             return;
    260         filters.add(rowIndex + 1, filters.remove(rowIndex));
    261         savePrefs();
    262         updateFilters();
    263         fireTableRowsUpdated(rowIndex, rowIndex + 1);
     119        if (model.moveDownFilter(rowIndex)) {
     120            savePrefs();
     121            updateFilters();
     122            fireTableRowsUpdated(rowIndex, rowIndex + 1);
     123        }
    264124    }
    265125
     
    269129     */
    270130    public void moveUpFilter(int rowIndex) {
    271         if (rowIndex == 0)
    272             return;
    273         filters.add(rowIndex - 1, filters.remove(rowIndex));
    274         savePrefs();
    275         updateFilters();
    276         fireTableRowsUpdated(rowIndex - 1, rowIndex);
     131        if (model.moveUpFilter(rowIndex)) {
     132            savePrefs();
     133            updateFilters();
     134            fireTableRowsUpdated(rowIndex - 1, rowIndex);
     135        }
    277136    }
    278137
     
    282141     */
    283142    public void removeFilter(int rowIndex) {
    284         filters.remove(rowIndex);
    285         savePrefs();
    286         updateFilters();
    287         fireTableRowsDeleted(rowIndex, rowIndex);
     143        if (model.removeFilter(rowIndex) != null) {
     144            savePrefs();
     145            updateFilters();
     146            fireTableRowsDeleted(rowIndex, rowIndex);
     147        }
    288148    }
    289149
     
    294154     */
    295155    public void setFilter(int rowIndex, Filter filter) {
    296         filters.set(rowIndex, filter);
     156        model.setFilter(rowIndex, filter);
    297157        savePrefs();
    298158        updateFilters();
     
    306166     */
    307167    public Filter getFilter(int rowIndex) {
    308         return filters.get(rowIndex);
     168        return model.getFilter(rowIndex);
    309169    }
    310170
    311171    @Override
    312172    public int getRowCount() {
    313         return filters.size();
     173        return model.getFiltersCount();
    314174    }
    315175
     
    343203     */
    344204    public boolean isCellEnabled(int row, int column) {
    345         return filters.get(row).enable || column == 0;
     205        return model.getFilter(row).enable || column == 0;
    346206    }
    347207
     
    353213    @Override
    354214    public void setValueAt(Object aValue, int row, int column) {
    355         if (row >= filters.size()) {
     215        if (row >= model.getFiltersCount()) {
    356216            return;
    357217        }
    358         Filter f = filters.get(row);
     218        Filter f = model.getFilter(row);
    359219        switch (column) {
    360220        case COL_ENABLED:
    361221            f.enable = (Boolean) aValue;
    362             savePrefs();
    363             updateFilters();
    364             fireTableRowsUpdated(row, row);
     222            setFilter(row, f);
    365223            break;
    366224        case COL_HIDING:
    367225            f.hiding = (Boolean) aValue;
    368             savePrefs();
    369             updateFilters();
     226            setFilter(row, f);
    370227            break;
    371228        case COL_TEXT:
     
    375232        case COL_INVERTED:
    376233            f.inverted = (Boolean) aValue;
    377             savePrefs();
    378             updateFilters();
     234            setFilter(row, f);
    379235            break;
    380236        default: // Do nothing
     
    387243    @Override
    388244    public Object getValueAt(int row, int column) {
    389         if (row >= filters.size()) {
     245        if (row >= model.getFiltersCount()) {
    390246            return null;
    391247        }
    392         Filter f = filters.get(row);
     248        Filter f = model.getFilter(row);
    393249        switch (column) {
    394250        case COL_ENABLED:
     
    424280     */
    425281    public void drawOSDText(Graphics2D g) {
    426         String message = "<html>" + tr("<h2>Filter active</h2>");
    427 
    428         if (disabledCount == 0 && disabledAndHiddenCount == 0)
    429             return;
    430 
    431         if (disabledAndHiddenCount != 0) {
    432             /* for correct i18n of plural forms - see #9110 */
    433             message += trn("<p><b>{0}</b> object hidden", "<p><b>{0}</b> objects hidden", disabledAndHiddenCount, disabledAndHiddenCount);
    434         }
    435 
    436         if (disabledAndHiddenCount != 0 && disabledCount != 0) {
    437             message += "<br>";
    438         }
    439 
    440         if (disabledCount != 0) {
    441             /* for correct i18n of plural forms - see #9110 */
    442             message += trn("<b>{0}</b> object disabled", "<b>{0}</b> objects disabled", disabledCount, disabledCount);
    443         }
    444 
    445         message += tr("</p><p>Close the filter dialog to see all objects.<p></html>");
    446 
    447         lblOSD.setText(message);
    448         lblOSD.setSize(lblOSD.getPreferredSize());
    449 
    450         int dx = Main.map.mapView.getWidth() - lblOSD.getPreferredSize().width - 15;
    451         int dy = 15;
    452         g.translate(dx, dy);
    453         lblOSD.paintComponent(g);
    454         g.translate(-dx, -dy);
     282        model.drawOSDText(g, lblOSD,
     283                tr("<h2>Filter active</h2>"),
     284                tr("</p><p>Close the filter dialog to see all objects.<p></html>"));
    455285    }
    456286
     
    460290     */
    461291    public List<Filter> getFilters() {
    462         return filters;
     292        return model.getFilters();
    463293    }
    464294}
  • trunk/src/org/openstreetmap/josm/gui/preferences/display/DrawingPreference.java

    r11090 r12400  
    1515import org.openstreetmap.josm.Main;
    1616import org.openstreetmap.josm.actions.ExpertToggleAction;
     17import org.openstreetmap.josm.gui.autofilter.AutoFilterManager;
     18import org.openstreetmap.josm.gui.autofilter.AutoFilterRule;
    1719import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
    1820import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
     
    2123import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
    2224import org.openstreetmap.josm.gui.util.GuiHelper;
     25import org.openstreetmap.josm.gui.widgets.JosmComboBox;
    2326import org.openstreetmap.josm.tools.GBC;
    2427
     
    4851    private final JCheckBox inactive = new JCheckBox(tr("Draw inactive layers in other color"));
    4952    private final JCheckBox discardableKeys = new JCheckBox(tr("Display discardable keys"));
     53    private final JCheckBox autoFilters = new JCheckBox(tr("Use auto filters"));
     54    private final JLabel lblRule = new JLabel(tr("Rule"));
     55    private final JosmComboBox<AutoFilterRule> autoFilterRules = new JosmComboBox<>(
     56            AutoFilterManager.getInstance().getAutoFilterRules().toArray(new AutoFilterRule[] {}));
    5057
    5158    // Options that affect performance
     
    131138        discardableKeys.setSelected(Main.pref.getBoolean("display.discardable-keys", false));
    132139
     140        // auto filters
     141        autoFilters.setToolTipText(tr("Display buttons to automatically filter numeric values of a predefined tag"));
     142        autoFilters.setSelected(AutoFilterManager.PROP_AUTO_FILTER_ENABLED.get());
     143        autoFilters.addActionListener(e -> {
     144            lblRule.setEnabled(autoFilters.isSelected());
     145            autoFilterRules.setEnabled(autoFilters.isSelected());
     146        });
     147        autoFilterRules.setToolTipText("Rule defining which tag will provide automatic filters, below a certain zoom level");
     148        autoFilterRules.setSelectedItem(AutoFilterManager.getInstance().getAutoFilterRule(AutoFilterManager.PROP_AUTO_FILTER_RULE.get()));
     149
    133150        JLabel performanceLabel = new JLabel(tr("Options that affect drawing performance"));
    134151
     
    157174        panel.add(inactive, GBC.eop().insets(20, 0, 0, 0));
    158175        panel.add(discardableKeys, GBC.eop().insets(20, 0, 0, 0));
     176        panel.add(autoFilters, GBC.eop().insets(20, 0, 0, 0));
     177        panel.add(lblRule, GBC.std().insets(40, 0, 0, 0));
     178        panel.add(autoFilterRules, GBC.eop().fill(GBC.HORIZONTAL).insets(5, 0, 0, 0));
    159179
    160180        ExpertToggleAction.addVisibilitySwitcher(performanceLabel);
     
    188208        Main.pref.put("draw.helper-line", drawHelperLine.isSelected());
    189209        Main.pref.put("display.discardable-keys", discardableKeys.isSelected());
     210        AutoFilterManager.PROP_AUTO_FILTER_ENABLED.put(autoFilters.isSelected());
     211        AutoFilterManager.PROP_AUTO_FILTER_RULE.put(((AutoFilterRule) autoFilterRules.getSelectedItem()).getKey());
    190212        int vn = Main.pref.getInteger("mappaint.node.virtual-size", 8);
    191213        if (virtualNodes.isSelected()) {
Note: See TracChangeset for help on using the changeset viewer.