source: josm/trunk/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java@ 402

Last change on this file since 402 was 402, checked in by framm, 17 years ago
  • started adding support for uploading GPX files, not complete yet, disabled
File size: 15.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.layer;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.CheckboxGroup;
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.Graphics;
11import java.awt.GridBagLayout;
12import java.awt.Point;
13import java.awt.event.ActionEvent;
14import java.awt.event.ActionListener;
15import java.io.BufferedReader;
16import java.io.ByteArrayOutputStream;
17import java.io.File;
18import java.io.FileInputStream;
19import java.io.InputStreamReader;
20import java.io.OutputStream;
21import java.net.HttpURLConnection;
22import java.net.URL;
23import java.net.URLConnection;
24import java.net.UnknownHostException;
25import java.util.Collection;
26import java.util.LinkedList;
27
28import javax.swing.AbstractAction;
29import javax.swing.Box;
30import javax.swing.ButtonGroup;
31import javax.swing.Icon;
32import javax.swing.JCheckBox;
33import javax.swing.JColorChooser;
34import javax.swing.JFileChooser;
35import javax.swing.JLabel;
36import javax.swing.JMenuItem;
37import javax.swing.JOptionPane;
38import javax.swing.JPanel;
39import javax.swing.JRadioButton;
40import javax.swing.JSeparator;
41import javax.swing.JTextField;
42import javax.swing.filechooser.FileFilter;
43
44import org.openstreetmap.josm.Main;
45import org.openstreetmap.josm.actions.GpxExportAction;
46import org.openstreetmap.josm.actions.RenameLayerAction;
47import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
48import org.openstreetmap.josm.data.coor.EastNorth;
49import org.openstreetmap.josm.data.coor.LatLon;
50import org.openstreetmap.josm.data.osm.DataSet;
51import org.openstreetmap.josm.data.osm.Node;
52import org.openstreetmap.josm.data.osm.Way;
53import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
54import org.openstreetmap.josm.gui.MapView;
55import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
56import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
57import org.openstreetmap.josm.io.MultiPartFormOutputStream;
58import org.openstreetmap.josm.io.OsmWriter;
59import org.openstreetmap.josm.tools.ColorHelper;
60import org.openstreetmap.josm.tools.DontShowAgainInfo;
61import org.openstreetmap.josm.tools.GBC;
62import org.openstreetmap.josm.tools.ImageProvider;
63import org.openstreetmap.josm.tools.UrlLabel;
64
65/**
66 * A layer holding data from a gps source.
67 * The data is read only.
68 *
69 * @author imi
70 */
71public class RawGpsLayer extends Layer implements PreferenceChangedListener {
72
73 public class ConvertToDataLayerAction extends AbstractAction {
74 public ConvertToDataLayerAction() {
75 super(tr("Convert to data layer"), ImageProvider.get("converttoosm"));
76 }
77 public void actionPerformed(ActionEvent e) {
78 JPanel msg = new JPanel(new GridBagLayout());
79 msg.add(new JLabel(tr("<html>Upload of unprocessed GPS data as map data is considered harmful.<br>If you want to upload traces, look here:")), GBC.eol());
80 msg.add(new UrlLabel(tr("http://www.openstreetmap.org/traces")), GBC.eop());
81 if (!DontShowAgainInfo.show("convert_to_data", msg))
82 return;
83 DataSet ds = new DataSet();
84 for (Collection<GpsPoint> c : data) {
85 Way w = new Way();
86 for (GpsPoint p : c) {
87 Node n = new Node(p.latlon);
88 ds.nodes.add(n);
89 w.nodes.add(n);
90 }
91 ds.ways.add(w);
92 }
93 Main.main.addLayer(new OsmDataLayer(ds, tr("Converted from: {0}", RawGpsLayer.this.name), null));
94 Main.main.removeLayer(RawGpsLayer.this);
95 }
96 }
97
98 public class UploadTraceAction extends AbstractAction {
99 public UploadTraceAction() {
100 super(tr("Upload this trace..."), ImageProvider.get("uploadtrace"));
101 }
102 public void actionPerformed(ActionEvent e) {
103 JPanel msg = new JPanel(new GridBagLayout());
104 msg.add(new JLabel(tr("<html>This functionality has been added only recently. Please<br>"+
105 "use with care and check if it works as expected.</html>")), GBC.eop());
106 ButtonGroup bg = new ButtonGroup();
107 JRadioButton c1 = null;
108 JRadioButton c2 = null;
109
110 if (associatedFile != null) {
111 c1 = new JRadioButton(tr("Upload track filtered by JOSM"), false);
112 c2 = new JRadioButton(tr("Upload raw file: {0}", associatedFile.getName()), true);
113 }
114 else
115 {
116 c1 = new JRadioButton(tr("Upload track filtered by JOSM"), true);
117 c2 = new JRadioButton(tr("Upload raw file: "), false);
118 c2.setEnabled(false);
119 }
120 c1.setEnabled(false);
121 bg.add(c1);
122 bg.add(c2);
123
124 msg.add(c1, GBC.eol());
125 msg.add(c2, GBC.eop());
126
127
128 JTextField description = new JTextField();
129 JTextField tags = new JTextField();
130 msg.add(new JLabel(tr("Description:")), GBC.std());
131 msg.add(description, GBC.eol().fill(GBC.HORIZONTAL));
132 msg.add(new JLabel(tr("Tags:")), GBC.std());
133 msg.add(tags, GBC.eol().fill(GBC.HORIZONTAL));
134 JCheckBox c3 = new JCheckBox("public");
135 msg.add(c3, GBC.eop());
136 msg.add(new JLabel("Please ensure that you don't upload your traces twice."), GBC.eop());
137
138 int answer = JOptionPane.showConfirmDialog(Main.parent, msg, tr("GPX-Upload"), JOptionPane.OK_CANCEL_OPTION);
139 if (answer == JOptionPane.OK_OPTION)
140 {
141 try {
142 String version = Main.pref.get("osm-server.version", "0.5");
143 URL url = new URL(Main.pref.get("osm-server.url") +
144 "/" + version + "/gpx/create");
145
146 // create a boundary string
147 String boundary = MultiPartFormOutputStream.createBoundary();
148 URLConnection urlConn = MultiPartFormOutputStream.createConnection(url);
149 urlConn.setRequestProperty("Accept", "*/*");
150 urlConn.setRequestProperty("Content-Type",
151 MultiPartFormOutputStream.getContentType(boundary));
152 // set some other request headers...
153 urlConn.setRequestProperty("Connection", "Keep-Alive");
154 urlConn.setRequestProperty("Cache-Control", "no-cache");
155 // no need to connect cuz getOutputStream() does it
156 MultiPartFormOutputStream out =
157 new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary);
158 out.writeField("description", description.getText());
159 out.writeField("tags", tags.getText());
160 out.writeField("public", (c3.getSelectedObjects() != null) ? "1" : "0");
161 // upload a file
162 out.writeFile("gpx_file", "text/xml", associatedFile);
163 // can also write bytes directly
164 // out.writeFile("myFile", "text/plain", "C:\\test.txt",
165 // "This is some file text.".getBytes("ASCII"));
166 out.close();
167 // read response from server
168 BufferedReader in = new BufferedReader(
169 new InputStreamReader(urlConn.getInputStream()));
170 String line = "";
171 while((line = in.readLine()) != null) {
172 System.out.println(line);
173 }
174 in.close();
175
176 /*
177 int retCode = activeConnection.getResponseCode();
178 System.out.println("got return: "+retCode);
179 String retMsg = activeConnection.getResponseMessage();
180 activeConnection.disconnect();
181 if (retCode != 200) {
182 // Look for a detailed error message from the server
183 if (activeConnection.getHeaderField("Error") != null)
184 retMsg += "\n" + activeConnection.getHeaderField("Error");
185
186 // Report our error
187 ByteArrayOutputStream o = new ByteArrayOutputStream();
188 System.out.println(new String(o.toByteArray(), "UTF-8").toString());
189 throw new RuntimeException(retCode+" "+retMsg);
190 }
191 */
192 } catch (UnknownHostException ex) {
193 throw new RuntimeException(tr("Unknown host")+": "+ex.getMessage(), ex);
194 } catch (Exception ex) {
195 //if (cancel)
196 // return; // assume cancel
197 if (ex instanceof RuntimeException)
198 throw (RuntimeException)ex;
199 throw new RuntimeException(ex.getMessage(), ex);
200 }
201 }
202 }
203 }
204
205 public static class GpsPoint {
206 public final LatLon latlon;
207 public final EastNorth eastNorth;
208 public final String time;
209 public GpsPoint(LatLon ll, String t) {
210 latlon = ll;
211 eastNorth = Main.proj.latlon2eastNorth(ll);
212 time = t;
213 }
214 }
215
216 /**
217 * A list of ways which containing a list of points.
218 */
219 public final Collection<Collection<GpsPoint>> data;
220 public final boolean fromServer;
221
222 public RawGpsLayer(boolean fromServer, Collection<Collection<GpsPoint>> data, String name, File associatedFile) {
223 super(name);
224 this.fromServer = fromServer;
225 this.associatedFile = associatedFile;
226 this.data = data;
227 Main.pref.listener.add(this);
228 }
229
230 /**
231 * Return a static icon.
232 */
233 @Override public Icon getIcon() {
234 return ImageProvider.get("layer", "rawgps_small");
235 }
236
237 @Override public void paint(Graphics g, MapView mv) {
238 String gpsCol = Main.pref.get("color.gps point");
239 String gpsColSpecial = Main.pref.get("color.layer "+name);
240 if (!gpsColSpecial.equals(""))
241 g.setColor(ColorHelper.html2color(gpsColSpecial));
242 else if (!gpsCol.equals(""))
243 g.setColor(ColorHelper.html2color(gpsCol));
244 else
245 g.setColor(Color.GRAY);
246 Point old = null;
247
248 boolean force = Main.pref.getBoolean("draw.rawgps.lines.force");
249 boolean lines = Main.pref.getBoolean("draw.rawgps.lines");
250 String linesKey = "draw.rawgps.lines.layer "+name;
251 if (Main.pref.hasKey(linesKey))
252 lines = Main.pref.getBoolean(linesKey);
253 boolean large = Main.pref.getBoolean("draw.rawgps.large");
254 for (Collection<GpsPoint> c : data) {
255 if (!force)
256 old = null;
257 for (GpsPoint p : c) {
258 Point screen = mv.getPoint(p.eastNorth);
259 if (lines && old != null)
260 g.drawLine(old.x, old.y, screen.x, screen.y);
261 else if (!large)
262 g.drawRect(screen.x, screen.y, 0, 0);
263 if (large)
264 g.fillRect(screen.x-1, screen.y-1, 3, 3);
265 old = screen;
266 }
267 }
268 }
269
270 @Override public String getToolTipText() {
271 int points = 0;
272 for (Collection<GpsPoint> c : data)
273 points += c.size();
274 String tool = data.size()+" "+trn("track", "tracks", data.size())
275 +" "+points+" "+trn("point", "points", points);
276 if (associatedFile != null)
277 tool = "<html>"+tool+"<br>"+associatedFile.getPath()+"</html>";
278 return tool;
279 }
280
281 @Override public void mergeFrom(Layer from) {
282 RawGpsLayer layer = (RawGpsLayer)from;
283 data.addAll(layer.data);
284 }
285
286 @Override public boolean isMergable(Layer other) {
287 return other instanceof RawGpsLayer;
288 }
289
290 @Override public void visitBoundingBox(BoundingXYVisitor v) {
291 for (Collection<GpsPoint> c : data)
292 for (GpsPoint p : c)
293 v.visit(p.eastNorth);
294 }
295
296 @Override public Object getInfoComponent() {
297 StringBuilder b = new StringBuilder();
298 int points = 0;
299 for (Collection<GpsPoint> c : data) {
300 b.append("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"+trn("a track with {0} point","a track with {0} points", c.size(), c.size())+"<br>");
301 points += c.size();
302 }
303 b.append("</html>");
304 return "<html>"+trn("{0} consists of {1} track", "{0} consists of {1} tracks", data.size(), name, data.size())+" ("+trn("{0} point", "{0} points", points, points)+")<br>"+b.toString();
305 }
306
307 @Override public Component[] getMenuEntries() {
308 JMenuItem line = new JMenuItem(tr("Customize line drawing"), ImageProvider.get("mapmode/addsegment"));
309 line.addActionListener(new ActionListener(){
310 public void actionPerformed(ActionEvent e) {
311 JRadioButton[] r = new JRadioButton[3];
312 r[0] = new JRadioButton(tr("Use global settings."));
313 r[1] = new JRadioButton(tr("Draw lines between points for this layer."));
314 r[2] = new JRadioButton(tr("Do not draw lines between points for this layer."));
315 ButtonGroup group = new ButtonGroup();
316 Box panel = Box.createVerticalBox();
317 for (JRadioButton b : r) {
318 group.add(b);
319 panel.add(b);
320 }
321 String propName = "draw.rawgps.lines.layer "+name;
322 if (Main.pref.hasKey(propName))
323 group.setSelected(r[Main.pref.getBoolean(propName) ? 1:2].getModel(), true);
324 else
325 group.setSelected(r[0].getModel(), true);
326 int answer = JOptionPane.showConfirmDialog(Main.parent, panel, tr("Select line drawing options"), JOptionPane.OK_CANCEL_OPTION);
327 if (answer == JOptionPane.CANCEL_OPTION)
328 return;
329 if (group.getSelection() == r[0].getModel())
330 Main.pref.put(propName, null);
331 else
332 Main.pref.put(propName, group.getSelection() == r[1].getModel());
333 Main.map.repaint();
334 }
335 });
336
337 JMenuItem color = new JMenuItem(tr("Customize Color"), ImageProvider.get("colorchooser"));
338 color.addActionListener(new ActionListener(){
339 public void actionPerformed(ActionEvent e) {
340 String col = Main.pref.get("color.layer "+name, Main.pref.get("color.gps point", ColorHelper.color2html(Color.gray)));
341 JColorChooser c = new JColorChooser(ColorHelper.html2color(col));
342 Object[] options = new Object[]{tr("OK"), tr("Cancel"), tr("Default")};
343 int answer = JOptionPane.showOptionDialog(Main.parent, c, tr("Choose a color"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
344 switch (answer) {
345 case 0:
346 Main.pref.put("color.layer "+name, ColorHelper.color2html(c.getColor()));
347 break;
348 case 1:
349 return;
350 case 2:
351 Main.pref.put("color.layer "+name, null);
352 break;
353 }
354 Main.map.repaint();
355 }
356 });
357
358 JMenuItem tagimage = new JMenuItem(tr("Import images"), ImageProvider.get("tagimages"));
359 tagimage.addActionListener(new ActionListener(){
360 public void actionPerformed(ActionEvent e) {
361 JFileChooser fc = new JFileChooser(Main.pref.get("tagimages.lastdirectory"));
362 fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
363 fc.setMultiSelectionEnabled(true);
364 fc.setAcceptAllFileFilterUsed(false);
365 fc.setFileFilter(new FileFilter(){
366 @Override public boolean accept(File f) {
367 return f.isDirectory() || f.getName().toLowerCase().endsWith(".jpg");
368 }
369 @Override public String getDescription() {
370 return tr("JPEG images (*.jpg)");
371 }
372 });
373 fc.showOpenDialog(Main.parent);
374 File[] sel = fc.getSelectedFiles();
375 if (sel == null || sel.length == 0)
376 return;
377 LinkedList<File> files = new LinkedList<File>();
378 addRecursiveFiles(files, sel);
379 Main.pref.put("tagimages.lastdirectory", fc.getCurrentDirectory().getPath());
380 GeoImageLayer.create(files, RawGpsLayer.this);
381 }
382
383 private void addRecursiveFiles(LinkedList<File> files, File[] sel) {
384 for (File f : sel) {
385 if (f.isDirectory())
386 addRecursiveFiles(files, f.listFiles());
387 else if (f.getName().toLowerCase().endsWith(".jpg"))
388 files.add(f);
389 }
390 }
391 });
392
393 if (Main.applet)
394 return new Component[]{
395 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
396 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
397 new JSeparator(),
398 color,
399 line,
400 new JMenuItem(new ConvertToDataLayerAction()),
401 //new JMenuItem(new UploadTraceAction()),
402 new JSeparator(),
403 new JMenuItem(new RenameLayerAction(associatedFile, this)),
404 new JSeparator(),
405 new JMenuItem(new LayerListPopup.InfoAction(this))};
406 return new Component[]{
407 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)),
408 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)),
409 new JSeparator(),
410 new JMenuItem(new GpxExportAction(this)),
411 color,
412 line,
413 tagimage,
414 new JMenuItem(new ConvertToDataLayerAction()),
415 //new JMenuItem(new UploadTraceAction()),
416 new JSeparator(),
417 new JMenuItem(new RenameLayerAction(associatedFile, this)),
418 new JSeparator(),
419 new JMenuItem(new LayerListPopup.InfoAction(this))};
420 }
421
422 public void preferenceChanged(String key, String newValue) {
423 if (Main.map != null && (key.equals("draw.rawgps.lines") || key.equals("draw.rawgps.lines.force")))
424 Main.map.repaint();
425 }
426
427 @Override public void destroy() {
428 Main.pref.listener.remove(RawGpsLayer.this);
429 }
430}
Note: See TracBrowser for help on using the repository browser.