Ignore:
Timestamp:
2010-06-03T09:19:19+02:00 (14 years ago)
Author:
bastiK
Message:

see #4998 - Impossible to select nodes with filter

Location:
trunk/src/org/openstreetmap/josm/data/osm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r3210 r3300  
    485485     *-----------------------------------------------------*/
    486486
    487     public void setDisabled(OsmPrimitive... osm) {
    488         if (osm.length == 1 && osm[0] == null) {
    489             setDisabled();
    490             return;
    491         }
    492         clearDisabled(allPrimitives());
    493         for (OsmPrimitive o : osm)
    494             if (o != null) {
    495                 o.setDisabled(true);
    496             }
    497     }
    498 
    499     public void setDisabled(Collection<? extends OsmPrimitive> selection) {
    500         clearDisabled(nodes);
    501         clearDisabled(ways);
    502         clearDisabled(relations);
    503         for (OsmPrimitive osm : selection) {
    504             osm.setDisabled(true);
    505         }
    506     }
    507 
    508     /**
    509      * Remove the disabled parameter from every value in the collection.
    510      * @param list The collection to remove the disabled parameter from.
    511      */
    512     private void clearDisabled(Collection<? extends OsmPrimitive> list) {
    513         for (OsmPrimitive osm : list) {
    514             osm.setDisabled(false);
    515         }
    516     }
    517 
    518 
    519     public void setFiltered(Collection<? extends OsmPrimitive> selection) {
    520         clearFiltered(nodes);
    521         clearFiltered(ways);
    522         clearFiltered(relations);
    523         for (OsmPrimitive osm : selection) {
    524             osm.setFiltered(true);
    525         }
    526     }
    527 
    528     public void setFiltered(OsmPrimitive... osm) {
    529         if (osm.length == 1 && osm[0] == null) {
    530             setFiltered();
    531             return;
    532         }
    533         clearFiltered(nodes);
    534         clearFiltered(ways);
    535         clearFiltered(relations);
    536         for (OsmPrimitive o : osm)
    537             if (o != null) {
    538                 o.setFiltered(true);
    539             }
    540     }
    541 
    542     /**
    543      * Remove the filtered parameter from every value in the collection.
    544      * @param list The collection to remove the filtered parameter from.
    545      */
    546     private void clearFiltered(Collection<? extends OsmPrimitive> list) {
    547         if (list == null)
    548             return;
    549         for (OsmPrimitive osm : list) {
    550             osm.setFiltered(false);
    551         }
    552     }
     487    /**
     488     * TODO: can be removed if no longer needed
     489     *
     490     * Currently, the filter flags are updated directly for the primitives.
     491     * On the long run there might be listeners for filter changes,
     492     * so the control needs to be moved to this place again.
     493     */
     494
     495//    public void setDisabled(OsmPrimitive... osm) {
     496//        if (osm.length == 1 && osm[0] == null) {
     497//            setDisabled();
     498//            return;
     499//        }
     500//        clearDisabled(allPrimitives());
     501//        for (OsmPrimitive o : osm)
     502//            if (o != null) {
     503//                o.setDisabled(true);
     504//            }
     505//    }
     506//
     507//    public void setDisabled(Collection<? extends OsmPrimitive> selection) {
     508//        clearDisabled(nodes);
     509//        clearDisabled(ways);
     510//        clearDisabled(relations);
     511//        for (OsmPrimitive osm : selection) {
     512//            osm.setDisabled(true);
     513//        }
     514//    }
     515//
     516//    /**
     517//     * Remove the disabled parameter from every value in the collection.
     518//     * @param list The collection to remove the disabled parameter from.
     519//     */
     520//    private void clearDisabled(Collection<? extends OsmPrimitive> list) {
     521//        for (OsmPrimitive osm : list) {
     522//            osm.setDisabled(false);
     523//        }
     524//    }
     525//
     526//
     527//    public void setFiltered(Collection<? extends OsmPrimitive> selection) {
     528//        clearFiltered(nodes);
     529//        clearFiltered(ways);
     530//        clearFiltered(relations);
     531//        for (OsmPrimitive osm : selection) {
     532//            osm.setFiltered(true);
     533//        }
     534//    }
     535//
     536//    public void setFiltered(OsmPrimitive... osm) {
     537//        if (osm.length == 1 && osm[0] == null) {
     538//            setFiltered();
     539//            return;
     540//        }
     541//        clearFiltered(nodes);
     542//        clearFiltered(ways);
     543//        clearFiltered(relations);
     544//        for (OsmPrimitive o : osm)
     545//            if (o != null) {
     546//                o.setFiltered(true);
     547//            }
     548//    }
     549//
     550//    /**
     551//     * Remove the filtered parameter from every value in the collection.
     552//     * @param list The collection to remove the filtered parameter from.
     553//     */
     554//    private void clearFiltered(Collection<? extends OsmPrimitive> list) {
     555//        if (list == null)
     556//            return;
     557//        for (OsmPrimitive osm : list) {
     558//            osm.setFiltered(false);
     559//        }
     560//    }
    553561
    554562    @Override public DataSet clone() {
  • trunk/src/org/openstreetmap/josm/data/osm/Filter.java

    r3083 r3300  
    1212
    1313    public Boolean enable = true;
    14     public Boolean hide = false;
     14    public Boolean hiding = false;
    1515    public Boolean inverted = false;
    16     public Boolean applyForChildren = true;
    1716    public Filter() {
    1817        super("", SearchMode.add, false, false);
     
    4342        regexSearch = Boolean.parseBoolean(prfs[4]);
    4443        enable = Boolean.parseBoolean(prfs[6]);
    45         hide = Boolean.parseBoolean(prfs[7]);
     44        hiding = Boolean.parseBoolean(prfs[7]);
    4645        inverted = Boolean.parseBoolean(prfs[8]);
    47         applyForChildren = Boolean.parseBoolean(prfs[9]);
    48 
    4946    }
    5047
    5148    public String getPrefString(){
    5249        return version + ";" +
    53         text + ";" + mode + ";" + caseSensitive + ";" + regexSearch + ";" +
    54         "legacy" + ";" + enable + ";" + hide + ";" +
    55         inverted + ";" + applyForChildren;
     50            text + ";" + mode + ";" + caseSensitive + ";" + regexSearch + ";" +
     51            "legacy" + ";" + enable + ";" + hiding + ";" +
     52            inverted + ";" +
     53            "false"; // last parameter is not used any more (was: applyForChildren)
    5654    }
    5755}
  • trunk/src/org/openstreetmap/josm/data/osm/Filters.java

    r3199 r3300  
    1010
    1111import java.util.Collection;
     12import java.util.HashSet;
    1213import java.util.LinkedList;
    1314import java.util.List;
     
    2021import org.openstreetmap.josm.Main;
    2122import org.openstreetmap.josm.actions.search.SearchAction;
    22 import org.openstreetmap.josm.actions.search.SearchAction.Function;
     23import org.openstreetmap.josm.tools.Property;
    2324
    2425/**
     
    2627 * @author Petr_Dlouhý
    2728 */
    28 public class Filters extends AbstractTableModel{
    29 
    30     public int disabledCount, hiddenCount;
    31 
    32     public Filters(){
     29public class Filters extends AbstractTableModel {
     30
     31    // number of primitives that are disabled but not hidden
     32    public int disabledCount;
     33    // number of primitives that are disabled and hidden
     34    public int disabledAndHiddenCount;
     35
     36    public Filters() {
    3337        loadPrefs();
    3438    }
     
    3640    private List<Filter> filters = new LinkedList<Filter>();
    3741
     42    /**
     43     * Apply the filters to the primitives of the data set.
     44     *
     45     * There are certain rules to ensure that a way is not displayed "naked"
     46     * without its nodes (1) and on the other hand to avoid hiding a way but
     47     * leaving its nodes visible as a cloud of points (2).
     48     *
     49     * In normal (non-inverted) mode only problem (2) is relevant.
     50     * Untagged child nodes of filtered ways that are not used by other
     51     * unfiltered ways are filtered as well.
     52     *
     53     * If a filter applies explicitly to a node, (2) is ignored and it
     54     * is filtered in any case.
     55     *
     56     * In inverted mode usually only problem (1) is relevant.
     57     * If the inverted filter applies explicitly to a node, this no longer
     58     * means it is filtered in any case:
     59     * E.g. the filter [searchtext="highway=footway", inverted=true] displays
     60     * the footways only. But that does not mean, the nodes of the footway
     61     * (which do not have the highway tag) should be filtered as well.
     62     *
     63     * So first the Filter is applied for ways and relations. Then to nodes
     64     * (but hides them only if they are not used by any unfiltered way).
     65     */
    3866    public void executeFilters(){
    39         Collection<OsmPrimitive> seld = new LinkedList<OsmPrimitive> ();
    40         Collection<OsmPrimitive> self = new LinkedList<OsmPrimitive> ();
    4167        DataSet ds = Main.main.getCurrentDataSet();
    42         if(ds == null)return;
    43         ds.setFiltered();
    44         ds.setDisabled();
     68        if (ds == null)
     69            return;
     70
     71        final Collection<OsmPrimitive> all = ds.allNonDeletedCompletePrimitives();
     72        // temporary set to collect the primitives returned by the search engine
     73        final Collection<OsmPrimitive> collect = new HashSet<OsmPrimitive>();
     74
     75        // an auxiliary property to collect the results of the search engine
     76        class CollectProperty implements Property<OsmPrimitive,Boolean> {
     77            boolean collectValue;
     78            boolean hidden;
     79
     80            /**
     81             * Depending on the parameters, there are 4 different instances
     82             * of this class.
     83             *
     84             * @param collectValue
     85             *          If true: collect only those primitives that are added
     86             *              by the search engine.
     87             *          If false: Collect only those primitives that are removed
     88             *              by the search engine.
     89             * @param hidden Whether the property refers to primitives that
     90             *          are disabled and hidden or to primitives
     91             *          that are disabled only.
     92             */
     93            public CollectProperty(boolean collectValue, boolean hidden) {
     94                this.collectValue = collectValue;
     95                this.hidden = hidden;
     96            }
     97
     98            public Boolean get(OsmPrimitive osm) {
     99                if (hidden)
     100                    return osm.isDisabledAndHidden();
     101                else
     102                    return osm.isDisabled();
     103            }
     104
     105            public void set(OsmPrimitive osm, Boolean value) {
     106                if (collectValue == value.booleanValue()) {
     107                    collect.add(osm);
     108                }
     109            }
     110        }
     111
     112        clearFilterFlags();
     113
    45114        for (Filter flt : filters){
    46             if(flt.enable){
    47                 SearchAction.getSelection(flt, seld, new Function(){
    48                     public Boolean isSomething(OsmPrimitive o){
    49                         return o.isDisabled();
    50                     }
    51                 });
    52                 if(flt.hide) {
    53                     SearchAction.getSelection(flt, self, new Function(){
    54                         public Boolean isSomething(OsmPrimitive o){
    55                             return o.isFiltered();
     115            if (flt.enable) {
     116                collect.clear();
     117                // Decide, whether primitives are collected that are added to the current
     118                // selection or those that are removed from the current selection
     119                boolean collectValue = flt.mode == SearchAction.SearchMode.replace || flt.mode == SearchAction.SearchMode.add;
     120                Property<OsmPrimitive,Boolean> collectProp = new CollectProperty(collectValue, flt.hiding);
     121
     122                SearchAction.getSelection(flt, all, collectProp);
     123
     124                switch (flt.mode) {
     125                    case replace:
     126                        for (OsmPrimitive osm : all) {
     127                            osm.unsetDisabledState();
    56128                        }
    57                     });
     129                    case add:
     130                        if (!flt.inverted) {
     131                            for (OsmPrimitive osm : collect) {
     132                                osm.setDisabledState(flt.hiding);
     133                            }
     134
     135                            // Find child nodes of hidden ways and add them to the hidden nodes
     136                            for (OsmPrimitive osm : collect) {
     137                                if (osm instanceof Way) {
     138                                    nodes:
     139                                    for (Node n : ((Way)osm).getNodes()) {
     140                                        // if node is already disabled, there is nothing to do
     141                                        if (n.isDisabledAndHidden() || (!flt.hiding && n.isDisabled()))
     142                                            continue;
     143
     144                                        // if the node is tagged, don't disable it
     145                                        if (n.isTagged())
     146                                            continue;
     147
     148                                        // if the node has undisabled parent ways, don't disable it
     149                                        for (OsmPrimitive ref : n.getReferrers()) {
     150                                            if (ref instanceof Way) {
     151                                                if (!ref.isDisabled())
     152                                                    continue nodes;
     153                                                if (flt.hiding && !ref.isDisabledAndHidden())
     154                                                    continue nodes;
     155                                            }
     156                                        }
     157                                        n.setDisabledState(flt.hiding);
     158                                    }
     159                                }
     160                            }
     161                        } else { // inverted filter in add mode
     162                            // update flags, except for nodes
     163                            for (OsmPrimitive osm : collect) {
     164                                if (!(osm instanceof Node)) {
     165                                    osm.setDisabledState(flt.hiding);
     166                                }
     167                            }
     168
     169                            // update flags for nodes
     170                            nodes:
     171                            for (OsmPrimitive osm : collect) {
     172                                if (osm instanceof Node) {
     173                                    // if node is already disabled, there is nothing to do
     174                                    if (osm.isDisabledAndHidden() || (!flt.hiding && osm.isDisabled()))
     175                                        continue;
     176
     177                                    // if the node has undisabled parent ways, don't disable it
     178                                    for (OsmPrimitive ref : osm.getReferrers()) {
     179                                        if (ref instanceof Way) {
     180                                            if (!ref.isDisabled())
     181                                                continue nodes;
     182                                            if (flt.hiding && !ref.isDisabledAndHidden())
     183                                                continue nodes;
     184                                        }
     185                                    }
     186                                    osm.setDisabledState(flt.hiding);
     187                                }
     188                            }
     189                        }
     190                        break;
     191                    case remove:
     192                    case in_selection:
     193                        if (!flt.inverted) {
     194                            // make the described primitive undisabled again
     195                            for (OsmPrimitive osm : collect) {
     196                                osm.unsetDisabledState();
     197                            }
     198
     199                            // Undisable the child nodes of undisabled ways
     200                            for (OsmPrimitive osm : collect) {
     201                                if (osm instanceof Way) {
     202                                    for (Node n : ((Way) osm).getNodes()) {
     203                                        n.unsetDisabledState();
     204                                    }
     205                                }
     206                            }
     207                        } else { // inverted filter in remove mode
     208                            // make the described primitive undisabled again
     209                            for (OsmPrimitive osm : collect) {
     210                                osm.unsetDisabledState();
     211                            }
     212
     213                            // Undisable the child nodes of undisabled ways
     214                            for (OsmPrimitive osm : collect) {
     215                                if (osm instanceof Way) {
     216                                    for (Node n : ((Way) osm).getNodes()) {
     217                                        n.unsetDisabledState();
     218                                    }
     219                                }
     220                            }
     221                        }
     222                        break;
     223                    default:
     224                        throw new IllegalStateException();
    58225                }
    59226            }
    60227        }
    61         disabledCount = seld.size() - self.size();
    62         hiddenCount = self.size();
    63         ds.setFiltered(self);
    64         ds.setDisabled(seld);
    65 
    66         ds.clearSelection(seld);
     228
     229        disabledCount = 0;
     230        disabledAndHiddenCount = 0;
     231        // collect disabled and selected the primitives
     232        final Collection<OsmPrimitive> deselect = new HashSet<OsmPrimitive>();
     233        for (OsmPrimitive osm : all) {
     234            if (osm.isDisabled()) {
     235                disabledCount++;
     236                if (osm.isSelected()) {
     237                    deselect.add(osm);
     238                }
     239                if (osm.isDisabledAndHidden()) {
     240                    disabledAndHiddenCount++;
     241                }
     242            }
     243        }
     244        disabledCount -= disabledAndHiddenCount;
     245        if (!deselect.isEmpty()) {
     246            ds.clearSelection(deselect);
     247        }
    67248
    68249        Main.map.mapView.repaint();
     
    72253        DataSet ds = Main.main.getCurrentDataSet();
    73254        if (ds != null) {
    74             ds.setFiltered();
    75             ds.setDisabled();
     255            for (OsmPrimitive osm : ds.allPrimitives()) {
     256                osm.unsetDisabledState();
     257            }
    76258        }
    77259        disabledCount = 0;
    78         hiddenCount = 0;
    79         Main.map.mapView.repaint();
    80     }
    81 
     260        disabledAndHiddenCount = 0;
     261    }
    82262
    83263    private void loadPrefs() {
     
    158338
    159339    public int getColumnCount(){
    160         return 6;
     340        return 5;
    161341    }
    162342
     
    167347                /* column header: hide filter */               trc("filter", "H"),
    168348                /* column header: filter text */               trc("filter", "Text"),
    169                 /* column header: apply filter for children */ trc("filter", "C"),
    170349                /* column header: inverted filter */           trc("filter", "I"),
    171350                /* column header: filter mode */               trc("filter", "M")
     
    176355    @Override
    177356    public Class<?> getColumnClass(int column){
    178         Class<?>[] classes = { Boolean.class, Boolean.class, String.class, Boolean.class, Boolean.class, String.class };
     357        Class<?>[] classes = { Boolean.class, Boolean.class, String.class, Boolean.class, String.class };
    179358        return classes[column];
    180359    }
     
    188367    public boolean isCellEditable(int row, int column){
    189368        if(!filters.get(row).enable && column!=0) return false;
    190         if(column < 5)return true;
     369        if(column < 4)return true;
    191370        return false;
    192371    }
     
    203382            break;
    204383        case 1:
    205             f.hide = (Boolean)aValue;
     384            f.hiding = (Boolean)aValue;
    206385            savePref(row);
    207386            executeFilters();
     
    212391            break;
    213392        case 3:
    214             f.applyForChildren = (Boolean)aValue;
    215             savePref(row);
    216             executeFilters();
    217             break;
    218         case 4:
    219393            f.inverted = (Boolean)aValue;
    220394            savePref(row);
     
    231405        switch(column){
    232406        case 0: return f.enable;
    233         case 1: return f.hide;
     407        case 1: return f.hiding;
    234408        case 2: return f.text;
    235         case 3: return f.applyForChildren;
    236         case 4: return f.inverted;
    237         case 5:
     409        case 3: return f.inverted;
     410        case 4:
    238411            switch(f.mode){ /* translators notes must be in front */
    239412            case replace:      /* filter mode: replace */      return trc("filter", "R");
     
    246419    }
    247420
     421    /**
     422     * On screen display label
     423     */
    248424    private static class OSDLabel extends JLabel {
    249425        public OSDLabel(String text) {
     
    269445        String message = "<html>"+tr("<h2>Filter active</h2>");
    270446
    271         if (disabledCount == 0 && hiddenCount == 0)
     447        if (disabledCount == 0 && disabledAndHiddenCount == 0)
    272448            return;
    273449
    274         if (hiddenCount != 0) {
    275             message += tr("<p><b>{0}</b> objects hidden", hiddenCount);
    276         }
    277 
    278         if (hiddenCount != 0 && disabledCount != 0) {
     450        if (disabledAndHiddenCount != 0) {
     451            message += tr("<p><b>{0}</b> objects hidden", disabledAndHiddenCount);
     452        }
     453
     454        if (disabledAndHiddenCount != 0 && disabledCount != 0) {
    279455            message += "<br>";
    280456        }
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r3262 r3300  
    6262    /**
    6363     * An object can be disabled by the filter mechanism.
    64      * Then it will show in a shade of grey on the map.
     64     * Then it will show in a shade of gray on the map or it is completely
     65     * hidden from the view.
    6566     * Disabled objects usually cannot be selected or modified
    6667     * while the filter is active.
     
    7879
    7980    /**
    80      * An object can be filtered by the filter mechanism.
    81      * Then it will be hidden on the map and usually
    82      * cannot be selected or modified while the filter is active.
    83      */
    84     private static final int FLAG_FILTERED = 1 << 4;
     81     * This flag is only relevant if an object is disabled by the
     82     * filter mechanism (i.e. FLAG_DISABLED is set).
     83     * Then it indicates, whether it is completely hidden or
     84     * just shown in gray color.
     85     *
     86     * When the primitive is not disabled, this flag should be
     87     * unset as well (for efficient access).
     88     */
     89    private static final int FLAG_HIDE_IF_DISABLED = 1 << 4;
    8590
    8691    /**
     
    302307    /* accessors                                                                            */
    303308    /* ------------------------------------------------------------------------------------ */
    304     /**
    305      * Sets whether this primitive is disabled or not.
    306      *
    307      * @param disabled true, if this primitive is disabled; false, otherwise
    308      */
    309     public void setDisabled(boolean disabled) {
    310         if (disabled) {
    311             flags |= FLAG_DISABLED;
     309
     310    /**
     311     * Make the primitive disabled (e.g. if a filter applies).
     312     * To enable the primitive again, use unsetDisabledState.
     313     * @param hide if the primitive should be completely hidden from view or
     314     *             just shown in gray color.
     315     */
     316    public void setDisabledState(boolean hide) {
     317        flags |= FLAG_DISABLED;
     318        if (hide) {
     319            flags |= FLAG_HIDE_IF_DISABLED;
    312320        } else {
    313             flags &= ~FLAG_DISABLED;
    314         }
    315 
    316     }
    317 
    318     /**
    319      * Replies true, if this primitive is disabled.
    320      *
    321      * @return true, if this primitive is disabled
     321            flags &= ~FLAG_HIDE_IF_DISABLED;
     322        }
     323    }
     324
     325    /**
     326     * Remove the disabled flag from the primitive.
     327     * Afterwards, the primitive is displayed normally and can be selected
     328     * again.
     329     */
     330    public void unsetDisabledState() {
     331        flags &= ~FLAG_DISABLED;
     332        flags &= ~FLAG_HIDE_IF_DISABLED;
     333    }
     334
     335    /**
     336     * Replies true, if this primitive is disabled. (E.g. a filter
     337     * applies)
    322338     */
    323339    public boolean isDisabled() {
    324340        return (flags & FLAG_DISABLED) != 0;
    325341    }
    326     /**
    327      * Sets whether this primitive is filtered out or not.
    328      *
    329      * @param filtered true, if this primitive is filtered out; false, otherwise
    330      */
    331     public void setFiltered(boolean filtered) {
    332         if (filtered) {
    333             flags |= FLAG_FILTERED;
    334         } else {
    335             flags &= ~FLAG_FILTERED;
    336         }
    337     }
    338     /**
    339      * Replies true, if this primitive is filtered out.
    340      *
    341      * @return true, if this primitive is filtered out
    342      */
     342
     343    /**
     344     * Replies true, if this primitive is disabled and marked as
     345     * completely hidden on the map.
     346     */
     347    public boolean isDisabledAndHidden() {
     348        return (((flags & FLAG_DISABLED) != 0) && ((flags & FLAG_HIDE_IF_DISABLED) != 0));
     349    }
     350
     351    @Deprecated
    343352    public boolean isFiltered() {
    344         return (flags & FLAG_FILTERED) != 0;
     353        return isDisabledAndHidden();
    345354    }
    346355
     
    394403
    395404    public boolean isSelectable() {
    396         return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_DISABLED + FLAG_FILTERED)) == 0;
     405        return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_DISABLED + FLAG_HIDE_IF_DISABLED)) == 0;
    397406    }
    398407
    399408    public boolean isDrawable() {
    400         return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_FILTERED)) == 0;
     409        return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_HIDE_IF_DISABLED)) == 0;
    401410    }
    402411
Note: See TracChangeset for help on using the changeset viewer.