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

Last change on this file since 6340 was 6105, checked in by Don-vip, 11 years ago

see #8902 - Small performance enhancements / coding style (patch by shinigami):

  • removed useles null checks before instanceof
  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import static org.openstreetmap.josm.tools.Utils.equal;
5
6import java.awt.Color;
7import java.awt.Rectangle;
8
9import org.openstreetmap.josm.data.osm.Node;
10import org.openstreetmap.josm.data.osm.OsmPrimitive;
11import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
12import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
13import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
14import org.openstreetmap.josm.tools.CheckParameterUtil;
15
16/**
17 * Text style attached to a style with a bounding box, like an icon or a symbol.
18 */
19public class BoxTextElemStyle extends ElemStyle {
20
21 public enum HorizontalTextAlignment { LEFT, CENTER, RIGHT }
22 public enum VerticalTextAlignment { ABOVE, TOP, CENTER, BOTTOM, BELOW }
23
24 public static interface BoxProvider {
25 BoxProviderResult get();
26 }
27
28 public static class BoxProviderResult {
29 private Rectangle box;
30 private boolean temporary;
31
32 public BoxProviderResult(Rectangle box, boolean temporary) {
33 this.box = box;
34 this.temporary = temporary;
35 }
36
37 /**
38 * The box
39 */
40 public Rectangle getBox() {
41 return box;
42 }
43
44 /**
45 * True, if the box can change in future calls of the BoxProvider get() method
46 */
47 public boolean isTemporary() {
48 return temporary;
49 }
50 }
51
52 public static class SimpleBoxProvider implements BoxProvider {
53 private Rectangle box;
54
55 public SimpleBoxProvider(Rectangle box) {
56 this.box = box;
57 }
58
59 @Override
60 public BoxProviderResult get() {
61 return new BoxProviderResult(box, false);
62 }
63
64 @Override
65 public int hashCode() {
66 return box.hashCode();
67 }
68
69 @Override
70 public boolean equals(Object obj) {
71 if (!(obj instanceof BoxProvider))
72 return false;
73 final BoxProvider other = (BoxProvider) obj;
74 BoxProviderResult resultOther = other.get();
75 if (resultOther.isTemporary()) return false;
76 return box.equals(resultOther.getBox());
77 }
78 }
79
80 public static final Rectangle ZERO_BOX = new Rectangle(0, 0, 0, 0);
81
82 public TextElement text;
83 // Either boxProvider or box is not null. If boxProvider is different from
84 // null, this means, that the box can still change in future, otherwise
85 // it is fixed.
86 protected BoxProvider boxProvider;
87 protected Rectangle box;
88 public HorizontalTextAlignment hAlign;
89 public VerticalTextAlignment vAlign;
90
91 public BoxTextElemStyle(Cascade c, TextElement text, BoxProvider boxProvider, Rectangle box, 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(c, DEFAULT_TEXT_COLOR, false);
116 if (text == null) return null;
117 // Skip any primtives 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 if (equal(hAlignKW.val, "left")) {
125 hAlign = HorizontalTextAlignment.LEFT;
126 } else if (equal(hAlignKW.val, "center")) {
127 hAlign = HorizontalTextAlignment.CENTER;
128 } else if (equal(hAlignKW.val, "right")) {
129 hAlign = HorizontalTextAlignment.RIGHT;
130 }
131 VerticalTextAlignment vAlign = VerticalTextAlignment.BOTTOM;
132 String vAlignStr = c.get("text-anchor-vertical", Keyword.BOTTOM, Keyword.class).val;
133 if (equal(vAlignStr, "above")) {
134 vAlign = VerticalTextAlignment.ABOVE;
135 } else if (equal(vAlignStr, "top")) {
136 vAlign = VerticalTextAlignment.TOP;
137 } else if (equal(vAlignStr, "center")) {
138 vAlign = VerticalTextAlignment.CENTER;
139 } else if (equal(vAlignStr, "bottom")) {
140 vAlign = VerticalTextAlignment.BOTTOM;
141 } else if (equal(vAlignStr, "below")) {
142 vAlign = VerticalTextAlignment.BELOW;
143 }
144
145 return new BoxTextElemStyle(c, text, boxProvider, box, hAlign, vAlign);
146 }
147
148 public Rectangle getBox() {
149 if (boxProvider != null) {
150 BoxProviderResult result = boxProvider.get();
151 if (!result.isTemporary()) {
152 box = result.getBox();
153 boxProvider = null;
154 }
155 return result.getBox();
156 }
157 return box;
158 }
159
160 public static final BoxTextElemStyle SIMPLE_NODE_TEXT_ELEMSTYLE;
161 static {
162 MultiCascade mc = new MultiCascade();
163 Cascade c = mc.getOrCreateCascade("default");
164 c.put(TEXT, Keyword.AUTO);
165 Node n = new Node();
166 n.put("name", "dummy");
167 SIMPLE_NODE_TEXT_ELEMSTYLE = create(new Environment(n, mc, "default", null), NodeElemStyle.SIMPLE_NODE_ELEMSTYLE.getBoxProvider());
168 if (SIMPLE_NODE_TEXT_ELEMSTYLE == null) throw new AssertionError();
169 }
170 /*
171 * Caches the default text color from the preferences.
172 *
173 * FIXME: the cache isn't updated if the user changes the preference during a JOSM
174 * session. There should be preference listener updating this cache.
175 */
176 static private Color DEFAULT_TEXT_COLOR = null;
177 static private void initDefaultParameters() {
178 if (DEFAULT_TEXT_COLOR != null) return;
179 DEFAULT_TEXT_COLOR = PaintColors.TEXT.get();
180 }
181
182 @Override
183 public void paintPrimitive(OsmPrimitive osm, MapPaintSettings settings, StyledMapRenderer painter, boolean selected, boolean member) {
184 if (osm instanceof Node) {
185 painter.drawBoxText((Node) osm, this);
186 }
187 }
188
189 @Override
190 public boolean equals(Object obj) {
191 if (!super.equals(obj))
192 return false;
193 if (obj == null || getClass() != obj.getClass())
194 return false;
195 final BoxTextElemStyle other = (BoxTextElemStyle) obj;
196 if (!text.equals(other.text)) return false;
197 if (boxProvider != null) {
198 if (!boxProvider.equals(other.boxProvider)) return false;
199 } else if (other.boxProvider != null)
200 return false;
201 else {
202 if (!box.equals(other.box)) return false;
203 }
204 if (hAlign != other.hAlign) return false;
205 if (vAlign != other.vAlign) return false;
206 return true;
207 }
208
209 @Override
210 public int hashCode() {
211 int hash = super.hashCode();
212 hash = 97 * hash + text.hashCode();
213 if (boxProvider != null) {
214 hash = 97 * hash + boxProvider.hashCode();
215 } else {
216 hash = 97 * hash + box.hashCode();
217 }
218 hash = 97 * hash + hAlign.hashCode();
219 hash = 97 * hash + vAlign.hashCode();
220 return hash;
221 }
222
223 @Override
224 public String toString() {
225 return "BoxTextElemStyle{" + super.toString() + " " + text.toStringImpl() + " box=" + box + " hAlign=" + hAlign + " vAlign=" + vAlign + '}';
226 }
227
228}
Note: See TracBrowser for help on using the repository browser.