source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/LabelCompositionStrategy.java @ 11615

Last change on this file since 11615 was 11615, checked in by Don-vip, 8 months ago

add javadoc

  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement;
3
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.Collections;
7import java.util.List;
8import java.util.Objects;
9
10import org.openstreetmap.josm.Main;
11import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
12import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.tools.LanguageInfo;
15
16/**
17 * <p>Provides an abstract parent class and three concrete sub classes for various
18 * strategies on how to compose the text label which can be rendered close to a node
19 * or within an area in an OSM map.</p>
20 *
21 * <p>The three strategies below support three rules for composing a label:
22 * <ul>
23 *   <li>{@link StaticLabelCompositionStrategy} - the label is given by a static text
24 *   specified in the MapCSS style file</li>
25 *
26 *   <li>{@link TagLookupCompositionStrategy} - the label is given by the content of a
27 *   tag whose name specified in the MapCSS style file</li>
28 *
29 *   <li>{@link DeriveLabelFromNameTagsCompositionStrategy} - the label is given by the value
30 *   of one of the configured "name tags". The list of relevant name tags can be configured
31 *   in the JOSM preferences
32 *   see the preference options <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>.</li>
33 * </ul>
34 * @since  3987 (creation)
35 * @since 10599 (functional interface)
36 */
37@FunctionalInterface
38public interface LabelCompositionStrategy {
39
40    /**
41     * Replies the text value to be rendered as label for the primitive {@code primitive}.
42     *
43     * @param primitive the primitive
44     *
45     * @return the text value to be rendered or null, if primitive is null or
46     * if no suitable value could be composed
47     */
48    String compose(OsmPrimitive primitive);
49
50    /**
51     * Strategy where the label is given by a static text specified in the MapCSS style file.
52     */
53    class StaticLabelCompositionStrategy implements LabelCompositionStrategy {
54        private final String defaultLabel;
55
56        public StaticLabelCompositionStrategy(String defaultLabel) {
57            this.defaultLabel = defaultLabel;
58        }
59
60        @Override
61        public String compose(OsmPrimitive primitive) {
62            return defaultLabel;
63        }
64
65        public String getDefaultLabel() {
66            return defaultLabel;
67        }
68
69        @Override
70        public String toString() {
71            return '{' + getClass().getSimpleName() + " defaultLabel=" + defaultLabel + '}';
72        }
73
74        @Override
75        public int hashCode() {
76            return Objects.hash(defaultLabel);
77        }
78
79        @Override
80        public boolean equals(Object obj) {
81            if (this == obj) return true;
82            if (obj == null || getClass() != obj.getClass()) return false;
83            StaticLabelCompositionStrategy that = (StaticLabelCompositionStrategy) obj;
84            return Objects.equals(defaultLabel, that.defaultLabel);
85        }
86    }
87
88    /**
89     * Strategy where the label is given by the content of a tag whose name specified in the MapCSS style file.
90     */
91    class TagLookupCompositionStrategy implements LabelCompositionStrategy {
92
93        private final String defaultLabelTag;
94
95        public TagLookupCompositionStrategy(String defaultLabelTag) {
96            if (defaultLabelTag != null) {
97                defaultLabelTag = defaultLabelTag.trim();
98                if (defaultLabelTag.isEmpty()) {
99                    defaultLabelTag = null;
100                }
101            }
102            this.defaultLabelTag = defaultLabelTag;
103        }
104
105        @Override
106        public String compose(OsmPrimitive primitive) {
107            if (defaultLabelTag == null) return null;
108            if (primitive == null) return null;
109            return primitive.get(defaultLabelTag);
110        }
111
112        public String getDefaultLabelTag() {
113            return defaultLabelTag;
114        }
115
116        @Override
117        public String toString() {
118            return '{' + getClass().getSimpleName() + " defaultLabelTag=" + defaultLabelTag + '}';
119        }
120
121        @Override
122        public int hashCode() {
123            return Objects.hash(defaultLabelTag);
124        }
125
126        @Override
127        public boolean equals(Object obj) {
128            if (this == obj) return true;
129            if (obj == null || getClass() != obj.getClass()) return false;
130            TagLookupCompositionStrategy that = (TagLookupCompositionStrategy) obj;
131            return Objects.equals(defaultLabelTag, that.defaultLabelTag);
132        }
133    }
134
135    /**
136     * Strategy where the label is given by the value of one of the configured "name tags".
137     * The list of relevant name tags can be configured in the JOSM preferences
138     * see the preference options <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>
139     */
140    class DeriveLabelFromNameTagsCompositionStrategy implements LabelCompositionStrategy, PreferenceChangedListener {
141
142        /**
143         * The list of default name tags from which a label candidate is derived.
144         */
145        private static final String[] DEFAULT_NAME_TAGS = {
146            "name:" + LanguageInfo.getJOSMLocaleCode(),
147            "name",
148            "int_name",
149            "distance",
150            "ref",
151            "operator",
152            "brand",
153            "addr:housenumber"
154        };
155
156        /**
157         * The list of default name complement tags from which a label candidate is derived.
158         */
159        private static final String[] DEFAULT_NAME_COMPLEMENT_TAGS = {
160            "capacity"
161        };
162
163        private List<String> nameTags = new ArrayList<>();
164        private List<String> nameComplementTags = new ArrayList<>();
165
166        /**
167         * <p>Creates the strategy and initializes its name tags from the preferences.</p>
168         */
169        public DeriveLabelFromNameTagsCompositionStrategy() {
170            initNameTagsFromPreferences();
171        }
172
173        private static List<String> buildNameTags(List<String> nameTags) {
174            List<String> result = new ArrayList<>();
175            if (nameTags != null) {
176                for (String tag: nameTags) {
177                    if (tag == null) {
178                        continue;
179                    }
180                    tag = tag.trim();
181                    if (tag.isEmpty()) {
182                        continue;
183                    }
184                    result.add(tag);
185                }
186            }
187            return result;
188        }
189
190        /**
191         * Sets the name tags to be looked up in order to build up the label.
192         *
193         * @param nameTags the name tags. null values are ignored.
194         */
195        public void setNameTags(List<String> nameTags) {
196            this.nameTags = buildNameTags(nameTags);
197        }
198
199        /**
200         * Sets the name complement tags to be looked up in order to build up the label.
201         *
202         * @param nameComplementTags the name complement tags. null values are ignored.
203         * @since 6541
204         */
205        public void setNameComplementTags(List<String> nameComplementTags) {
206            this.nameComplementTags = buildNameTags(nameComplementTags);
207        }
208
209        /**
210         * Replies an unmodifiable list of the name tags used to compose the label.
211         *
212         * @return the list of name tags
213         */
214        public List<String> getNameTags() {
215            return Collections.unmodifiableList(nameTags);
216        }
217
218        /**
219         * Replies an unmodifiable list of the name complement tags used to compose the label.
220         *
221         * @return the list of name complement tags
222         * @since 6541
223         */
224        public List<String> getNameComplementTags() {
225            return Collections.unmodifiableList(nameComplementTags);
226        }
227
228        /**
229         * Initializes the name tags to use from a list of default name tags (see
230         * {@link #DEFAULT_NAME_TAGS} and {@link #DEFAULT_NAME_COMPLEMENT_TAGS})
231         * and from name tags configured in the preferences using the keys
232         * <tt>mappaint.nameOrder</tt> and <tt>mappaint.nameComplementOrder</tt>.
233         */
234        public final void initNameTagsFromPreferences() {
235            if (Main.pref == null) {
236                this.nameTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_TAGS));
237                this.nameComplementTags = new ArrayList<>(Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS));
238            } else {
239                this.nameTags = new ArrayList<>(
240                        Main.pref.getCollection("mappaint.nameOrder", Arrays.asList(DEFAULT_NAME_TAGS))
241                );
242                this.nameComplementTags = new ArrayList<>(
243                        Main.pref.getCollection("mappaint.nameComplementOrder", Arrays.asList(DEFAULT_NAME_COMPLEMENT_TAGS))
244                );
245            }
246        }
247
248        private String getPrimitiveName(OsmPrimitive n) {
249            StringBuilder name = new StringBuilder();
250            if (!n.hasKeys()) return null;
251            for (String rn : nameTags) {
252                String val = n.get(rn);
253                if (val != null) {
254                    name.append(val);
255                    break;
256                }
257            }
258            for (String rn : nameComplementTags) {
259                String comp = n.get(rn);
260                if (comp != null) {
261                    if (name.length() == 0) {
262                        name.append(comp);
263                    } else {
264                        name.append(" (").append(comp).append(')');
265                    }
266                    break;
267                }
268            }
269            return name.toString();
270        }
271
272        @Override
273        public String compose(OsmPrimitive primitive) {
274            if (primitive == null) return null;
275            return getPrimitiveName(primitive);
276        }
277
278        @Override
279        public String toString() {
280            return '{' + getClass().getSimpleName() + '}';
281        }
282
283        @Override
284        public void preferenceChanged(PreferenceChangeEvent e) {
285            if (e.getKey() != null && e.getKey().startsWith("mappaint.name")) {
286                initNameTagsFromPreferences();
287            }
288        }
289    }
290}
Note: See TracBrowser for help on using the repository browser.