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

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

Do not include text label in area style - use a separate class and start merging code for on-line and in-area drawing.

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