source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/BoxTextElement.java@ 9278

Last change on this file since 9278 was 9278, checked in by bastiK, 9 years ago

move ElemStyle classes to new package, rename to (Style)Element

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