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

Last change on this file since 9371 was 9371, checked in by simon04, 8 years ago

Java 7: use Objects.equals and Objects.hash

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