001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.Comparator;
005import java.util.Objects;
006
007import org.openstreetmap.josm.data.StructUtils.StructEntry;
008import org.openstreetmap.josm.data.StructUtils.WriteExplicitly;
009import org.openstreetmap.josm.data.osm.search.SearchMode;
010import org.openstreetmap.josm.data.osm.search.SearchSetting;
011
012/**
013 * Data class representing one entry in the filter dialog.
014 *
015 * @author Petr_DlouhĂ˝
016 * @since 2125
017 */
018public class Filter extends SearchSetting implements Comparable<Filter> {
019    private static final String version = "1";
020
021    /**
022     * Enabled status.
023     * @see FilterPreferenceEntry#enable
024     */
025    public boolean enable = true;
026
027    /**
028     * If this option is activated, the chosen objects are completely hidden.
029     * Otherwise they are disabled and shown in a shade of gray.
030     * @see FilterPreferenceEntry#hiding
031     */
032    public boolean hiding;
033
034    /**
035     * Normally, the specified objects are hidden and the rest is shown.
036     * If this option is activated, only the specified objects are shown and the rest is hidden.
037     * @see FilterPreferenceEntry#inverted
038     */
039    public boolean inverted;
040
041    /**
042     * Constructs a new {@code Filter}.
043     */
044    public Filter() {
045        super();
046        mode = SearchMode.add;
047    }
048
049    /**
050     * Constructs a new {@code Filter} from a {@code SearchSetting}
051     * @param setting {@code SearchSetting} to construct information from
052     * @since 14932
053     */
054    public Filter(SearchSetting setting) {
055        super(setting);
056    }
057
058    /**
059     * Constructs a new {@code Filter} from a {@code SearchSetting} and filter-specific fields from an existing Filter.
060     * @param setting {@code SearchSetting} to construct information from
061     * @param f {@code Filter} to construct filter-specific fields from
062     * @since 15477
063     */
064    public Filter(SearchSetting setting, Filter f) {
065        super(setting);
066        this.enable = f.enable;
067        this.hiding = f.hiding;
068        this.inverted = f.inverted;
069    }
070
071    /**
072     * Constructs a new {@code Filter} from a preference entry.
073     * @param e preference entry
074     */
075    public Filter(FilterPreferenceEntry e) {
076        this();
077        text = e.text;
078        if ("replace".equals(e.mode)) {
079            mode = SearchMode.replace;
080        } else if ("add".equals(e.mode)) {
081            mode = SearchMode.add;
082        } else if ("remove".equals(e.mode)) {
083            mode = SearchMode.remove;
084        } else if ("in_selection".equals(e.mode)) {
085            mode = SearchMode.in_selection;
086        }
087        caseSensitive = e.case_sensitive;
088        regexSearch = e.regex_search;
089        mapCSSSearch = e.mapCSS_search;
090        enable = e.enable;
091        hiding = e.hiding;
092        inverted = e.inverted;
093    }
094
095    public static class FilterPreferenceEntry {
096        @WriteExplicitly
097        @StructEntry public String version = "1";
098
099        @StructEntry public String text;
100
101        /**
102         * Mode selector which defines how a filter is combined with the previous one:<ul>
103         * <li>replace: replace selection</li>
104         * <li>add: add to selection</li>
105         * <li>remove: remove from selection</li>
106         * <li>in_selection: find in selection</li>
107         * </ul>
108         * @see SearchMode
109         */
110        @WriteExplicitly
111        @StructEntry public String mode = "add";
112
113        @StructEntry public boolean case_sensitive;
114
115        @StructEntry public boolean regex_search;
116
117        @StructEntry public boolean mapCSS_search;
118
119        /**
120         * Enabled status.
121         * @see Filter#enable
122         */
123        @WriteExplicitly
124        @StructEntry public boolean enable = true;
125
126        /**
127         * If this option is activated, the chosen objects are completely hidden.
128         * Otherwise they are disabled and shown in a shade of gray.
129         * @see Filter#hiding
130         */
131        @WriteExplicitly
132        @StructEntry public boolean hiding;
133
134        /**
135         * Normally, the specified objects are hidden and the rest is shown.
136         * If this option is activated, only the specified objects are shown and the rest is hidden.
137         * @see Filter#inverted
138         */
139        @WriteExplicitly
140        @StructEntry public boolean inverted;
141
142        @Override
143        public int hashCode() {
144            return Objects.hash(case_sensitive, enable, hiding, inverted, mapCSS_search, mode, regex_search, text, version);
145        }
146
147        @Override
148        public boolean equals(Object obj) {
149            if (this == obj)
150                return true;
151            if (obj == null || getClass() != obj.getClass())
152                return false;
153            FilterPreferenceEntry other = (FilterPreferenceEntry) obj;
154            return case_sensitive == other.case_sensitive
155                    && enable == other.enable
156                    && hiding == other.hiding
157                    && inverted == other.inverted
158                    && mapCSS_search == other.mapCSS_search
159                    && regex_search == other.regex_search
160                    && Objects.equals(mode, other.mode)
161                    && Objects.equals(text, other.text)
162                    && Objects.equals(version, other.version);
163        }
164    }
165
166    /**
167     * Returns a new preference entry for this filter.
168     * @return preference entry
169     */
170    public FilterPreferenceEntry getPreferenceEntry() {
171        FilterPreferenceEntry e = new FilterPreferenceEntry();
172        e.version = version;
173        e.text = text;
174        e.mode = mode.name();
175        e.case_sensitive = caseSensitive;
176        e.regex_search = regexSearch;
177        e.mapCSS_search = mapCSSSearch;
178        e.enable = enable;
179        e.hiding = hiding;
180        e.inverted = inverted;
181        return e;
182    }
183
184    @Override
185    public int compareTo(Filter o) {
186        return Comparator
187                .<Filter, String>comparing(f -> f.text)
188                .thenComparing(f -> f.mode)
189                .thenComparing(f -> f.caseSensitive)
190                .thenComparing(f -> f.regexSearch)
191                .thenComparing(f -> f.mapCSSSearch)
192                .thenComparing(f -> f.enable)
193                .thenComparing(f -> f.hiding)
194                .thenComparing(f -> f.inverted)
195                .compare(this, o);
196    }
197}