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

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

fix remaining checkstyle issues

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