source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/BoxTextElemStyle.java@ 9078

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

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.awt.Color;
5import java.awt.Rectangle;
6
7import org.openstreetmap.josm.data.osm.Node;
8import org.openstreetmap.josm.data.osm.OsmPrimitive;
9import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
10import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
11import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
12import org.openstreetmap.josm.tools.CheckParameterUtil;
13
14/**
15 * Text style attached to a style with a bounding box, like an icon or a symbol.
16 */
17public class BoxTextElemStyle extends ElemStyle {
18
19 public enum HorizontalTextAlignment { LEFT, CENTER, RIGHT }
20
21 public enum VerticalTextAlignment { ABOVE, TOP, CENTER, BOTTOM, BELOW }
22
23 public interface BoxProvider {
24 BoxProviderResult get();
25 }
26
27 public static class BoxProviderResult {
28 private final Rectangle box;
29 private final boolean temporary;
30
31 public BoxProviderResult(Rectangle box, boolean temporary) {
32 this.box = box;
33 this.temporary = temporary;
34 }
35
36 /**
37 * Returns the box.
38 * @return the box
39 */
40 public Rectangle getBox() {
41 return box;
42 }
43
44 /**
45 * Determines if the box can change in future calls of the {@link BoxProvider#get()} method
46 * @return {@code true} if the box can change in future calls of the {@code BoxProvider#get()} method
47 */
48 public boolean isTemporary() {
49 return temporary;
50 }
51 }
52
53 public static class SimpleBoxProvider implements BoxProvider {
54 private final Rectangle box;
55
56 /**
57 * Constructs a new {@code SimpleBoxProvider}.
58 * @param box the box
59 */
60 public SimpleBoxProvider(Rectangle box) {
61 this.box = box;
62 }
63
64 @Override
65 public BoxProviderResult get() {
66 return new BoxProviderResult(box, false);
67 }
68
69 @Override
70 public int hashCode() {
71 return box.hashCode();
72 }
73
74 @Override
75 public boolean equals(Object obj) {
76 if (!(obj instanceof BoxProvider))
77 return false;
78 final BoxProvider other = (BoxProvider) obj;
79 BoxProviderResult resultOther = other.get();
80 if (resultOther.isTemporary()) return false;
81 return box.equals(resultOther.getBox());
82 }
83 }
84
85 public static final Rectangle ZERO_BOX = new Rectangle(0, 0, 0, 0);
86
87 public TextElement text;
88 // Either boxProvider or box is not null. If boxProvider is different from
89 // null, this means, that the box can still change in future, otherwise
90 // it is fixed.
91 protected BoxProvider boxProvider;
92 protected Rectangle box;
93 public HorizontalTextAlignment hAlign;
94 public VerticalTextAlignment vAlign;
95
96 public BoxTextElemStyle(Cascade c, TextElement text, BoxProvider boxProvider, Rectangle box,
97 HorizontalTextAlignment hAlign, VerticalTextAlignment vAlign) {
98 super(c, 5f);
99 CheckParameterUtil.ensureParameterNotNull(text);
100 CheckParameterUtil.ensureParameterNotNull(hAlign);
101 CheckParameterUtil.ensureParameterNotNull(vAlign);
102 this.text = text;
103 this.boxProvider = boxProvider;
104 this.box = box == null ? ZERO_BOX : box;
105 this.hAlign = hAlign;
106 this.vAlign = vAlign;
107 }
108
109 public static BoxTextElemStyle create(Environment env, BoxProvider boxProvider) {
110 return create(env, boxProvider, null);
111 }
112
113 public static BoxTextElemStyle create(Environment env, Rectangle box) {
114 return create(env, null, box);
115 }
116
117 public static BoxTextElemStyle create(Environment env, BoxProvider boxProvider, Rectangle box) {
118 initDefaultParameters();
119 Cascade c = env.mc.getCascade(env.layer);
120
121 TextElement text = TextElement.create(env, DEFAULT_TEXT_COLOR, false);
122 if (text == null) return null;
123 // Skip any primitives that don't have text to draw. (Styles are recreated for any tag change.)
124 // The concrete text to render is not cached in this object, but computed for each
125 // repaint. This way, one BoxTextElemStyle object can be used by multiple primitives (to save memory).
126 if (text.labelCompositionStrategy.compose(env.osm) == null) return null;
127
128 HorizontalTextAlignment hAlign = HorizontalTextAlignment.RIGHT;
129 Keyword hAlignKW = c.get(TEXT_ANCHOR_HORIZONTAL, Keyword.RIGHT, Keyword.class);
130 switch (hAlignKW.val) {
131 case "left":
132 hAlign = HorizontalTextAlignment.LEFT;
133 break;
134 case "center":
135 hAlign = HorizontalTextAlignment.CENTER;
136 }
137 VerticalTextAlignment vAlign = VerticalTextAlignment.BOTTOM;
138 Keyword vAlignKW = c.get(TEXT_ANCHOR_VERTICAL, Keyword.BOTTOM, Keyword.class);
139 switch (vAlignKW.val) {
140 case "bottom":
141 vAlign = VerticalTextAlignment.BOTTOM;
142 break;
143 case "above":
144 vAlign = VerticalTextAlignment.ABOVE;
145 break;
146 case "top":
147 vAlign = VerticalTextAlignment.TOP;
148 break;
149 case "center":
150 vAlign = VerticalTextAlignment.CENTER;
151 break;
152 case "below":
153 vAlign = VerticalTextAlignment.BELOW;
154 }
155
156 return new BoxTextElemStyle(c, text, boxProvider, box, hAlign, vAlign);
157 }
158
159 public Rectangle getBox() {
160 if (boxProvider != null) {
161 BoxProviderResult result = boxProvider.get();
162 if (!result.isTemporary()) {
163 box = result.getBox();
164 boxProvider = null;
165 }
166 return result.getBox();
167 }
168 return box;
169 }
170
171 public static final BoxTextElemStyle SIMPLE_NODE_TEXT_ELEMSTYLE;
172 static {
173 MultiCascade mc = new MultiCascade();
174 Cascade c = mc.getOrCreateCascade("default");
175 c.put(TEXT, Keyword.AUTO);
176 Node n = new Node();
177 n.put("name", "dummy");
178 SIMPLE_NODE_TEXT_ELEMSTYLE = create(new Environment(n, mc, "default", null), NodeElemStyle.SIMPLE_NODE_ELEMSTYLE.getBoxProvider());
179 if (SIMPLE_NODE_TEXT_ELEMSTYLE == null) throw new AssertionError();
180 }
181
182 /*
183 * Caches the default text color from the preferences.
184 *
185 * FIXME: the cache isn't updated if the user changes the preference during a JOSM
186 * session. There should be preference listener updating this cache.
187 */
188 private static volatile Color DEFAULT_TEXT_COLOR;
189
190 private static void initDefaultParameters() {
191 if (DEFAULT_TEXT_COLOR != null) return;
192 DEFAULT_TEXT_COLOR = PaintColors.TEXT.get();
193 }
194
195 @Override
196 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings settings, StyledMapRenderer painter,
197 boolean selected, boolean outermember, boolean member) {
198 if (osm instanceof Node) {
199 painter.drawBoxText((Node) osm, this);
200 }
201 }
202
203 @Override
204 public boolean equals(Object obj) {
205 if (!super.equals(obj))
206 return false;
207 if (obj == null || getClass() != obj.getClass())
208 return false;
209 final BoxTextElemStyle other = (BoxTextElemStyle) obj;
210 if (!text.equals(other.text)) return false;
211 if (boxProvider != null) {
212 if (!boxProvider.equals(other.boxProvider)) return false;
213 } else if (other.boxProvider != null)
214 return false;
215 else {
216 if (!box.equals(other.box)) return false;
217 }
218 if (hAlign != other.hAlign) return false;
219 if (vAlign != other.vAlign) return false;
220 return true;
221 }
222
223 @Override
224 public int hashCode() {
225 int hash = super.hashCode();
226 hash = 97 * hash + text.hashCode();
227 if (boxProvider != null) {
228 hash = 97 * hash + boxProvider.hashCode();
229 } else {
230 hash = 97 * hash + box.hashCode();
231 }
232 hash = 97 * hash + hAlign.hashCode();
233 hash = 97 * hash + vAlign.hashCode();
234 return hash;
235 }
236
237 @Override
238 public String toString() {
239 return "BoxTextElemStyle{" + super.toString() + ' ' + text.toStringImpl()
240 + " box=" + box + " hAlign=" + hAlign + " vAlign=" + vAlign + '}';
241 }
242}
Note: See TracBrowser for help on using the repository browser.