source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/TextLabel.java@ 12381

Last change on this file since 12381 was 12381, checked in by michael2402, 7 years ago

More documentation for the gui.mappaint package

  • Property svn:eol-style set to native
File size: 10.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement;
3
4import java.awt.Color;
5import java.awt.Font;
6import java.util.Objects;
7
8import org.openstreetmap.josm.data.osm.OsmPrimitive;
9import org.openstreetmap.josm.gui.mappaint.Cascade;
10import org.openstreetmap.josm.gui.mappaint.Environment;
11import org.openstreetmap.josm.gui.mappaint.Keyword;
12import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.TagKeyReference;
13import org.openstreetmap.josm.gui.mappaint.StyleKeys;
14import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy;
15import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.StaticLabelCompositionStrategy;
16import org.openstreetmap.josm.gui.mappaint.styleelement.LabelCompositionStrategy.TagLookupCompositionStrategy;
17import org.openstreetmap.josm.gui.mappaint.styleelement.placement.PositionForAreaStrategy;
18import org.openstreetmap.josm.tools.CheckParameterUtil;
19import org.openstreetmap.josm.tools.Utils;
20
21/**
22 * Represents the rendering style for a textual label placed somewhere on the map.
23 * @since 3880
24 */
25public class TextLabel implements StyleKeys {
26 /**
27 * The default strategy to use when determining the label of a element.
28 */
29 public static final LabelCompositionStrategy AUTO_LABEL_COMPOSITION_STRATEGY = new DeriveLabelFromNameTagsCompositionStrategy();
30
31 /**
32 * The strategy for building the actual label value for a given a {@link OsmPrimitive}.
33 * Check for null before accessing.
34 */
35 public LabelCompositionStrategy labelCompositionStrategy;
36 /**
37 * the font to be used when rendering
38 */
39 public Font font;
40 /**
41 * The x offset of the text.
42 */
43 public int xOffset;
44 /**
45 * The y offset of the text.
46 */
47 public int yOffset;
48 /**
49 * The color to draw the text in, includes alpha.
50 */
51 public Color color;
52 /**
53 * The radius of the halo effect.
54 */
55 public Float haloRadius;
56 /**
57 * The color of the halo effect.
58 */
59 public Color haloColor;
60
61 /**
62 * The position strategy for this text label.
63 */
64 private final PositionForAreaStrategy labelPositionStrategy;
65
66 /**
67 * Creates a new text element
68 *
69 * @param strategy the strategy indicating how the text is composed for a specific {@link OsmPrimitive} to be rendered.
70 * If null, no label is rendered.
71 * @param font the font to be used. Must not be null.
72 * @param xOffset x offset
73 * @param yOffset y offset
74 * @param color the color to be used. Must not be null
75 * @param haloRadius halo radius
76 * @param haloColor halo color
77 * @param labelPositionStrategy The position in the area.
78 */
79 protected TextLabel(LabelCompositionStrategy strategy, Font font, int xOffset, int yOffset, Color color, Float haloRadius,
80 Color haloColor, PositionForAreaStrategy labelPositionStrategy) {
81 this.labelCompositionStrategy = strategy;
82 this.font = Objects.requireNonNull(font, "font");
83 this.xOffset = xOffset;
84 this.yOffset = yOffset;
85 this.color = Objects.requireNonNull(color, "color");
86 this.haloRadius = haloRadius;
87 this.haloColor = haloColor;
88 this.labelPositionStrategy = Objects.requireNonNull(labelPositionStrategy, "labelPositionStrategy");
89 }
90
91 /**
92 * Copy constructor
93 *
94 * @param other the other element.
95 */
96 public TextLabel(TextLabel other) {
97 this.labelCompositionStrategy = other.labelCompositionStrategy;
98 this.font = other.font;
99 this.xOffset = other.xOffset;
100 this.yOffset = other.yOffset;
101 this.color = other.color;
102 this.haloColor = other.haloColor;
103 this.haloRadius = other.haloRadius;
104 this.labelPositionStrategy = other.labelPositionStrategy;
105 }
106
107 /**
108 * Copy constructor that changes the position strategy.
109 *
110 * @param other the other element.
111 * @param labelPositionStrategy the position
112 */
113 private TextLabel(TextLabel other, PositionForAreaStrategy labelPositionStrategy) {
114 this.labelCompositionStrategy = other.labelCompositionStrategy;
115 this.font = other.font;
116 this.xOffset = other.xOffset;
117 this.yOffset = other.yOffset;
118 this.color = other.color;
119 this.haloColor = other.haloColor;
120 this.haloRadius = other.haloRadius;
121 this.labelPositionStrategy = labelPositionStrategy;
122 }
123
124 /**
125 * Derives a suitable label composition strategy from the style properties in {@code c}.
126 *
127 * @param c the style properties
128 * @param defaultAnnotate whether to return {@link #AUTO_LABEL_COMPOSITION_STRATEGY} if not strategy is found
129 * @return the label composition strategy, or {@code null}
130 */
131 protected static LabelCompositionStrategy buildLabelCompositionStrategy(Cascade c, boolean defaultAnnotate) {
132 /*
133 * If the cascade includes a TagKeyReference we will lookup the rendered label
134 * from a tag value.
135 */
136 TagKeyReference tkr = c.get(TEXT, null, TagKeyReference.class, true);
137 if (tkr != null)
138 return new TagLookupCompositionStrategy(tkr.key);
139
140 /*
141 * Check whether the label composition strategy is given by a keyword
142 */
143 Keyword keyword = c.get(TEXT, null, Keyword.class, true);
144 if (Keyword.AUTO.equals(keyword))
145 return AUTO_LABEL_COMPOSITION_STRATEGY;
146
147 /*
148 * Do we have a static text label?
149 */
150 String text = c.get(TEXT, null, String.class, true);
151 if (text != null)
152 return new StaticLabelCompositionStrategy(text);
153 return defaultAnnotate ? AUTO_LABEL_COMPOSITION_STRATEGY : null;
154 }
155
156 /**
157 * Builds a text element from style properties in {@code c} and the
158 * default text color {@code defaultTextColor}
159 *
160 * @param env the environment
161 * @param defaultTextColor the default text color. Must not be null.
162 * @param defaultAnnotate true, if a text label shall be rendered by default, even if the style sheet
163 * doesn't include respective style declarations
164 * @return the text element or null, if the style properties don't include
165 * properties for text rendering
166 * @throws IllegalArgumentException if {@code defaultTextColor} is null
167 */
168 public static TextLabel create(Environment env, Color defaultTextColor, boolean defaultAnnotate) {
169 CheckParameterUtil.ensureParameterNotNull(defaultTextColor);
170 Cascade c = env.mc.getCascade(env.layer);
171
172 LabelCompositionStrategy strategy = buildLabelCompositionStrategy(c, defaultAnnotate);
173 if (strategy == null) return null;
174 String s = strategy.compose(env.osm);
175 if (s == null) return null;
176 Font font = StyleElement.getFont(c, s);
177
178 float xOffset = 0;
179 float yOffset = 0;
180 float[] offset = c.get(TEXT_OFFSET, null, float[].class);
181 if (offset != null) {
182 if (offset.length == 1) {
183 yOffset = offset[0];
184 } else if (offset.length >= 2) {
185 xOffset = offset[0];
186 yOffset = offset[1];
187 }
188 }
189 xOffset = c.get(TEXT_OFFSET_X, xOffset, Float.class);
190 yOffset = c.get(TEXT_OFFSET_Y, yOffset, Float.class);
191
192 Color color = c.get(TEXT_COLOR, defaultTextColor, Color.class);
193 float alpha = c.get(TEXT_OPACITY, 1f, Float.class);
194 color = Utils.alphaMultiply(color, alpha);
195
196 Float haloRadius = c.get(TEXT_HALO_RADIUS, null, Float.class);
197 if (haloRadius != null && haloRadius <= 0) {
198 haloRadius = null;
199 }
200 Color haloColor = null;
201 if (haloRadius != null) {
202 haloColor = c.get(TEXT_HALO_COLOR, Utils.complement(color), Color.class);
203 float haloAlphaFactor = c.get(TEXT_HALO_OPACITY, 1f, Float.class);
204 haloColor = Utils.alphaMultiply(haloColor, haloAlphaFactor);
205 }
206
207 Keyword positionKeyword = c.get(AreaElement.TEXT_POSITION, null, Keyword.class);
208 PositionForAreaStrategy position = PositionForAreaStrategy.forKeyword(positionKeyword);
209
210 return new TextLabel(strategy, font, (int) xOffset, -(int) yOffset, color, haloRadius, haloColor, position);
211 }
212
213 /**
214 * Replies the label to be rendered for the primitive {@code osm}.
215 *
216 * @param osm the OSM object
217 * @return the label, or null, if {@code osm} is null or if no label can be
218 * derived for {@code osm}
219 */
220 public String getString(OsmPrimitive osm) {
221 if (labelCompositionStrategy == null) return null;
222 return labelCompositionStrategy.compose(osm);
223 }
224
225 /**
226 * Gets the strategy that defines where to place the label.
227 * @return The strategy. Never null.
228 * @since 11722
229 */
230 public PositionForAreaStrategy getLabelPositionStrategy() {
231 return labelPositionStrategy;
232 }
233
234 /**
235 * Creates a new text label with a different position strategy
236 * @param labelPositionStrategy The new position strategy to use
237 * @return The new label
238 */
239 public TextLabel withPosition(PositionForAreaStrategy labelPositionStrategy) {
240 return new TextLabel(this, labelPositionStrategy);
241 }
242
243 @Override
244 public String toString() {
245 return "TextLabel{" + toStringImpl() + '}';
246 }
247
248 protected String toStringImpl() {
249 StringBuilder sb = new StringBuilder(96);
250 sb.append("labelCompositionStrategy=").append(labelCompositionStrategy)
251 .append(" font=").append(font);
252 if (xOffset != 0) {
253 sb.append(" xOffset=").append(xOffset);
254 }
255 if (yOffset != 0) {
256 sb.append(" yOffset=").append(yOffset);
257 }
258 sb.append(" color=").append(Utils.toString(color));
259 if (haloRadius != null) {
260 sb.append(" haloRadius=").append(haloRadius)
261 .append(" haloColor=").append(haloColor);
262 }
263 return sb.toString();
264 }
265
266 @Override
267 public int hashCode() {
268 return Objects.hash(labelCompositionStrategy, font, xOffset, yOffset, color, haloRadius, haloColor);
269 }
270
271 @Override
272 public boolean equals(Object obj) {
273 if (this == obj) return true;
274 if (obj == null || getClass() != obj.getClass()) return false;
275 TextLabel textLabel = (TextLabel) obj;
276 return xOffset == textLabel.xOffset &&
277 yOffset == textLabel.yOffset &&
278 Objects.equals(labelCompositionStrategy, textLabel.labelCompositionStrategy) &&
279 Objects.equals(font, textLabel.font) &&
280 Objects.equals(color, textLabel.color) &&
281 Objects.equals(haloRadius, textLabel.haloRadius) &&
282 Objects.equals(haloColor, textLabel.haloColor);
283 }
284}
Note: See TracBrowser for help on using the repository browser.