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

Last change on this file since 541 was 541, checked in by framm, 16 years ago
  • use waypoint's "desc" attribute in lieu of "name" if "name" is not present
  • add extra marker for trackpoints that have "name" or "desc" set

patch by David Earl <david@…>

File size: 6.6 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.HashMap;
13import java.util.LinkedList;
14import java.util.Map;
15
16import javax.swing.Icon;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.coor.EastNorth;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.gpx.GpxLink;
22import org.openstreetmap.josm.data.gpx.WayPoint;
23import org.openstreetmap.josm.gui.MapView;
24import org.openstreetmap.josm.tools.ImageProvider;
25
26/**
27 * Basic marker class. Requires a position, and supports
28 * a custom icon and a name.
29 *
30 * This class is also used to create appropriate Marker-type objects
31 * when waypoints are imported.
32 *
33 * It hosts a public list object, named makers, containing implementations of
34 * the MarkerMaker interface. Whenever a Marker needs to be created, each
35 * object in makers is called with the waypoint parameters (Lat/Lon and tag
36 * data), and the first one to return a Marker object wins.
37 *
38 * By default, one the list contains one default "Maker" implementation that
39 * will create AudioMarkers for .wav files, ImageMarkers for .png/.jpg/.jpeg
40 * files, and WebMarkers for everything else. (The creation of a WebMarker will
41 * fail if there's no vaild URL in the <link> tag, so it might still make sense
42 * to add Makers for such waypoints at the end of the list.)
43 *
44 * The default implementation only looks at the value of the <link> tag inside
45 * the <wpt> tag of the GPX file.
46 *
47 * <h2>HowTo implement a new Marker</h2>
48 * <ul>
49 * <li> Subclass Marker or ButtonMarker and override <code>containsPoint</code>
50 * if you like to respond to user clicks</li>
51 * <li> Override paint, if you want a custom marker look (not "a label and a symbol")</li>
52 * <li> Implement MarkerCreator to return a new instance of your marker class</li>
53 * <li> In you plugin constructor, add an instance of your MarkerCreator
54 * implementation either on top or bottom of Marker.markerProducers.
55 * Add at top, if your marker should overwrite an current marker or at bottom
56 * if you only add a new marker style.</li>
57 * </ul>
58 *
59 * @author Frederik Ramm <frederik@remote.org>
60 */
61public class Marker implements ActionListener {
62
63 public final EastNorth eastNorth;
64 public final String text;
65 public final Icon symbol;
66
67 /**
68 * Plugins can add their Marker creation stuff at the bottom or top of this list
69 * (depending on whether they want to override default behaviour or just add new
70 * stuff).
71 */
72 public static LinkedList<MarkerProducers> markerProducers = new LinkedList<MarkerProducers>();
73
74 // Add one Maker specifying the default behaviour.
75 static {
76 Marker.markerProducers.add(new MarkerProducers() {
77 public Marker createMarker(WayPoint wpt, File relativePath) {
78 String uri = null;
79 // cheapest way to check whether "link" object exists and is a non-empty
80 // collection of GpxLink objects...
81 try {
82 for (GpxLink oneLink : (Collection<GpxLink>) wpt.attr.get("link")) {
83 uri = oneLink.uri;
84 break;
85 }
86 } catch (Exception ex) {};
87
88 // Try a relative file:// url, if the link is not in an URL-compatible form
89 if (relativePath != null && uri != null && !isWellFormedAddress(uri))
90 uri = new File(relativePath, uri).toURI().toString();
91
92 if (uri == null) {
93 String name_desc = "";
94 if (wpt.attr.containsKey("name")) {
95 name_desc = wpt.getString("name");
96 } else if (wpt.attr.containsKey("desc")) {
97 name_desc = wpt.getString("desc");
98 }
99 return new Marker(wpt.latlon, name_desc, wpt.getString("symbol"));
100 }
101
102 if (uri.endsWith(".wav"))
103 return AudioMarker.create(wpt.latlon, uri);
104 else if (uri.endsWith(".png") || uri.endsWith(".jpg") || uri.endsWith(".jpeg") || uri.endsWith(".gif"))
105 return ImageMarker.create(wpt.latlon, uri);
106 else
107 return WebMarker.create(wpt.latlon, uri);
108 }
109
110 private boolean isWellFormedAddress(String link) {
111 try {
112 new URL(link);
113 return true;
114 } catch (MalformedURLException x) {
115 return false;
116 }
117 }
118 });
119 }
120
121 public Marker(LatLon ll, String text, String iconName) {
122 eastNorth = Main.proj.latlon2eastNorth(ll);
123 this.text = text;
124 Icon symbol = ImageProvider.getIfAvailable("markers",iconName);
125 if (symbol == null)
126 symbol = ImageProvider.getIfAvailable("symbols",iconName);
127 if (symbol == null)
128 symbol = ImageProvider.getIfAvailable("nodes",iconName);
129 this.symbol = symbol;
130 }
131
132 /**
133 * Checks whether the marker display area contains the given point.
134 * Markers not interested in mouse clicks may always return false.
135 *
136 * @param p The point to check
137 * @return <code>true</code> if the marker "hotspot" contains the point.
138 */
139 public boolean containsPoint(Point p) {
140 return false;
141 }
142
143 /**
144 * Called when the mouse is clicked in the marker's hotspot. Never
145 * called for markers which always return false from containsPoint.
146 *
147 * @param ev A dummy ActionEvent
148 */
149 public void actionPerformed(ActionEvent ev) {
150 }
151
152 /**
153 * Paints the marker.
154 * @param g graphics context
155 * @param mv map view
156 * @param mousePressed true if the left mouse button is pressed
157 */
158 public void paint(Graphics g, MapView mv, boolean mousePressed, String show) {
159 Point screen = mv.getPoint(eastNorth);
160 if (symbol != null) {
161 symbol.paintIcon(mv, g, screen.x-symbol.getIconWidth()/2, screen.y-symbol.getIconHeight()/2);
162 } else {
163 g.drawLine(screen.x-2, screen.y-2, screen.x+2, screen.y+2);
164 g.drawLine(screen.x+2, screen.y-2, screen.x-2, screen.y+2);
165 }
166
167 if ((text != null) && (show.equalsIgnoreCase("show")))
168 g.drawString(text, screen.x+4, screen.y+2);
169 }
170
171 /**
172 * Returns an object of class Marker or one of its subclasses
173 * created from the parameters given.
174 *
175 * @param ll lat/lon for marker
176 * @param data hash containing keys and values from the GPX waypoint structure
177 * @param relativePath An path to use for constructing relative URLs or
178 * <code>null</code> for no relative URLs
179 * @return a new Marker object
180 */
181 public static Marker createMarker(WayPoint wpt, File relativePath) {
182 for (MarkerProducers maker : Marker.markerProducers) {
183 Marker marker = maker.createMarker(wpt, relativePath);
184 if (marker != null)
185 return marker;
186 }
187 return null;
188 }
189}
Note: See TracBrowser for help on using the repository browser.