source: josm/trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java@ 2017

Last change on this file since 2017 was 2017, checked in by Gubaer, 15 years ago

removed OptionPaneUtil
cleanup of deprecated Layer API
cleanup of deprecated APIs in OsmPrimitive and Way
cleanup of imports

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1// License: GPL. Copyright 2008 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.layer.markerlayer;
3
4import java.awt.Graphics;
5import java.awt.Point;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.io.File;
9import java.net.MalformedURLException;
10import java.net.URL;
11import java.util.Collection;
12import java.util.LinkedList;
13
14import javax.swing.Icon;
15
16import org.openstreetmap.josm.data.coor.CachedLatLon;
17import org.openstreetmap.josm.data.coor.EastNorth;
18import org.openstreetmap.josm.data.coor.LatLon;
19import org.openstreetmap.josm.data.gpx.GpxData;
20import org.openstreetmap.josm.data.gpx.GpxLink;
21import org.openstreetmap.josm.data.gpx.WayPoint;
22import org.openstreetmap.josm.gui.MapView;
23import org.openstreetmap.josm.tools.ImageProvider;
24
25/**
26 * Basic marker class. Requires a position, and supports
27 * a custom icon and a name.
28 *
29 * This class is also used to create appropriate Marker-type objects
30 * when waypoints are imported.
31 *
32 * It hosts a public list object, named makers, containing implementations of
33 * the MarkerMaker interface. Whenever a Marker needs to be created, each
34 * object in makers is called with the waypoint parameters (Lat/Lon and tag
35 * data), and the first one to return a Marker object wins.
36 *
37 * By default, one the list contains one default "Maker" implementation that
38 * will create AudioMarkers for .wav files, ImageMarkers for .png/.jpg/.jpeg
39 * files, and WebMarkers for everything else. (The creation of a WebMarker will
40 * fail if there's no vaild URL in the <link> tag, so it might still make sense
41 * to add Makers for such waypoints at the end of the list.)
42 *
43 * The default implementation only looks at the value of the <link> tag inside
44 * the <wpt> tag of the GPX file.
45 *
46 * <h2>HowTo implement a new Marker</h2>
47 * <ul>
48 * <li> Subclass Marker or ButtonMarker and override <code>containsPoint</code>
49 * if you like to respond to user clicks</li>
50 * <li> Override paint, if you want a custom marker look (not "a label and a symbol")</li>
51 * <li> Implement MarkerCreator to return a new instance of your marker class</li>
52 * <li> In you plugin constructor, add an instance of your MarkerCreator
53 * implementation either on top or bottom of Marker.markerProducers.
54 * Add at top, if your marker should overwrite an current marker or at bottom
55 * if you only add a new marker style.</li>
56 * </ul>
57 *
58 * @author Frederik Ramm <frederik@remote.org>
59 */
60public class Marker implements ActionListener {
61 public final String text;
62 public final Icon symbol;
63 public final MarkerLayer parentLayer;
64 public double time; /* absolute time of marker since epoch */
65 public double offset; /* time offset in seconds from the gpx point from which it was derived,
66 may be adjusted later to sync with other data, so not final */
67
68 private CachedLatLon coor;
69
70 public final void setCoor(LatLon coor) {
71 if(this.coor == null) {
72 this.coor = new CachedLatLon(coor);
73 } else {
74 this.coor.setCoor(coor);
75 }
76 }
77
78 public final LatLon getCoor() {
79 return coor;
80 }
81
82 public final void setEastNorth(EastNorth eastNorth) {
83 coor.setEastNorth(eastNorth);
84 }
85
86 public final EastNorth getEastNorth() {
87 return coor.getEastNorth();
88 }
89
90 /**
91 * Plugins can add their Marker creation stuff at the bottom or top of this list
92 * (depending on whether they want to override default behaviour or just add new
93 * stuff).
94 */
95 public static LinkedList<MarkerProducers> markerProducers = new LinkedList<MarkerProducers>();
96
97 // Add one Maker specifying the default behaviour.
98 static {
99 Marker.markerProducers.add(new MarkerProducers() {
100 @SuppressWarnings("unchecked")
101 public Marker createMarker(WayPoint wpt, File relativePath, MarkerLayer parentLayer, double time, double offset) {
102 String uri = null;
103 // cheapest way to check whether "link" object exists and is a non-empty
104 // collection of GpxLink objects...
105 try {
106 for (GpxLink oneLink : (Collection<GpxLink>) wpt.attr.get(GpxData.META_LINKS)) {
107 uri = oneLink.uri;
108 break;
109 }
110 } catch (Exception ex) {}
111
112 // Try a relative file:// url, if the link is not in an URL-compatible form
113 if (relativePath != null && uri != null && !isWellFormedAddress(uri)) {
114 uri = new File(relativePath.getParentFile(), uri).toURI().toString();
115 }
116
117 String name_desc = "";
118 if (wpt.attr.containsKey("name")) {
119 name_desc = wpt.getString("name");
120 } else if (wpt.attr.containsKey("desc")) {
121 name_desc = wpt.getString("desc");
122 }
123
124 if (uri == null)
125 return new Marker(wpt.getCoor(), name_desc, wpt.getString("symbol"), parentLayer, time, offset);
126 else if (uri.endsWith(".wav"))
127 return AudioMarker.create(wpt.getCoor(), name_desc, uri, parentLayer, time, offset);
128 else if (uri.endsWith(".png") || uri.endsWith(".jpg") || uri.endsWith(".jpeg") || uri.endsWith(".gif"))
129 return ImageMarker.create(wpt.getCoor(), uri, parentLayer, time, offset);
130 else
131 return WebMarker.create(wpt.getCoor(), uri, parentLayer, time, offset);
132 }
133
134 private boolean isWellFormedAddress(String link) {
135 try {
136 new URL(link);
137 return true;
138 } catch (MalformedURLException x) {
139 return false;
140 }
141 }
142 });
143 }
144
145 public Marker(LatLon ll, String text, String iconName, MarkerLayer parentLayer, double time, double offset) {
146 setCoor(ll);
147 this.text = text;
148 this.offset = offset;
149 this.time = time;
150 Icon symbol = ImageProvider.getIfAvailable("markers",iconName);
151 if (symbol == null) {
152 symbol = ImageProvider.getIfAvailable("symbols",iconName);
153 }
154 if (symbol == null) {
155 symbol = ImageProvider.getIfAvailable("nodes",iconName);
156 }
157 this.symbol = symbol;
158 this.parentLayer = parentLayer;
159 }
160
161 /**
162 * Checks whether the marker display area contains the given point.
163 * Markers not interested in mouse clicks may always return false.
164 *
165 * @param p The point to check
166 * @return <code>true</code> if the marker "hotspot" contains the point.
167 */
168 public boolean containsPoint(Point p) {
169 return false;
170 }
171
172 /**
173 * Called when the mouse is clicked in the marker's hotspot. Never
174 * called for markers which always return false from containsPoint.
175 *
176 * @param ev A dummy ActionEvent
177 */
178 public void actionPerformed(ActionEvent ev) {
179 }
180
181 /**
182 * Paints the marker.
183 * @param g graphics context
184 * @param mv map view
185 * @param mousePressed true if the left mouse button is pressed
186 */
187 public void paint(Graphics g, MapView mv, boolean mousePressed, String show) {
188 Point screen = mv.getPoint(getEastNorth());
189 if (symbol != null && show.equalsIgnoreCase("show")) {
190 symbol.paintIcon(mv, g, screen.x-symbol.getIconWidth()/2, screen.y-symbol.getIconHeight()/2);
191 } else {
192 g.drawLine(screen.x-2, screen.y-2, screen.x+2, screen.y+2);
193 g.drawLine(screen.x+2, screen.y-2, screen.x-2, screen.y+2);
194 }
195
196 if ((text != null) && (show.equalsIgnoreCase("show"))) {
197 g.drawString(text, screen.x+4, screen.y+2);
198 }
199 }
200
201 /**
202 * Returns an object of class Marker or one of its subclasses
203 * created from the parameters given.
204 *
205 * @param wpt waypoint data for marker
206 * @param relativePath An path to use for constructing relative URLs or
207 * <code>null</code> for no relative URLs
208 * @param offset double in seconds as the time offset of this marker from
209 * the GPX file from which it was derived (if any).
210 * @return a new Marker object
211 */
212 public static Marker createMarker(WayPoint wpt, File relativePath, MarkerLayer parentLayer, double time, double offset) {
213 for (MarkerProducers maker : Marker.markerProducers) {
214 Marker marker = maker.createMarker(wpt, relativePath, parentLayer, time, offset);
215 if (marker != null)
216 return marker;
217 }
218 return null;
219 }
220
221 /**
222 * Returns an AudioMarker derived from this Marker and the provided uri
223 * Subclasses of specific marker types override this to return null as they can't
224 * be turned into AudioMarkers. This includes AudioMarkers themselves, as they
225 * already have audio.
226 *
227 * @param uri uri of wave file
228 * @return AudioMarker
229 */
230
231 public AudioMarker audioMarkerFromMarker(String uri) {
232 AudioMarker audioMarker = AudioMarker.create(getCoor(), this.text, uri, this.parentLayer, this.time, this.offset);
233 return audioMarker;
234 }
235}
Note: See TracBrowser for help on using the repository browser.