source: josm/src/org/openstreetmap/josm/Main.java@ 124

Last change on this file since 124 was 124, checked in by imi, 18 years ago

added "Reverse Segments" action

File size: 14.0 KB
Line 
1package org.openstreetmap.josm;
2import static org.openstreetmap.josm.tools.I18n.tr;
3
4import java.awt.BorderLayout;
5import java.awt.Component;
6import java.awt.Dimension;
7import java.awt.Rectangle;
8import java.awt.Toolkit;
9import java.awt.event.ActionEvent;
10import java.io.File;
11import java.net.URI;
12import java.net.URISyntaxException;
13import java.util.Collection;
14import java.util.LinkedList;
15import java.util.Map;
16import java.util.StringTokenizer;
17import java.util.concurrent.Executor;
18import java.util.concurrent.Executors;
19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
21
22import javax.swing.AbstractAction;
23import javax.swing.Action;
24import javax.swing.JMenu;
25import javax.swing.JMenuBar;
26import javax.swing.JOptionPane;
27import javax.swing.JPanel;
28import javax.swing.JSeparator;
29import javax.swing.JToolBar;
30import javax.swing.UIManager;
31
32import org.openstreetmap.josm.actions.AboutAction;
33import org.openstreetmap.josm.actions.DownloadAction;
34import org.openstreetmap.josm.actions.ExitAction;
35import org.openstreetmap.josm.actions.GpxExportAction;
36import org.openstreetmap.josm.actions.OpenAction;
37import org.openstreetmap.josm.actions.PreferencesAction;
38import org.openstreetmap.josm.actions.RedoAction;
39import org.openstreetmap.josm.actions.SaveAction;
40import org.openstreetmap.josm.actions.UndoAction;
41import org.openstreetmap.josm.actions.UploadAction;
42import org.openstreetmap.josm.actions.mapmode.MapMode;
43import org.openstreetmap.josm.command.ChangeCommand;
44import org.openstreetmap.josm.command.Command;
45import org.openstreetmap.josm.command.SequenceCommand;
46import org.openstreetmap.josm.data.Bounds;
47import org.openstreetmap.josm.data.Preferences;
48import org.openstreetmap.josm.data.osm.DataSet;
49import org.openstreetmap.josm.data.osm.Node;
50import org.openstreetmap.josm.data.osm.OsmPrimitive;
51import org.openstreetmap.josm.data.osm.Segment;
52import org.openstreetmap.josm.data.projection.Epsg4326;
53import org.openstreetmap.josm.data.projection.Projection;
54import org.openstreetmap.josm.gui.MapFrame;
55import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
56import org.openstreetmap.josm.gui.dialogs.AnnotationTester;
57import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
58import org.openstreetmap.josm.gui.layer.Layer;
59import org.openstreetmap.josm.gui.layer.OsmDataLayer;
60import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
61import org.openstreetmap.josm.tools.ImageProvider;
62
63abstract public class Main {
64 /**
65 * Global parent component for all dialogs and message boxes
66 */
67 public static Component parent;
68 /**
69 * Global application window. Use this as JOPtionPane-parent to center on application.
70 */
71 public static Main main;
72 /**
73 * The worker thread slave. This is for executing all long and intensive
74 * calculations. The executed runnables are guaranteed to be executed seperatly
75 * and sequenciel.
76 */
77 public final static Executor worker = Executors.newSingleThreadExecutor();
78 /**
79 * Global application preferences
80 */
81 public static Preferences pref = new Preferences();
82 /**
83 * The global dataset.
84 */
85 public static DataSet ds = new DataSet();
86 /**
87 * The projection method used.
88 */
89 public static Projection proj;
90 /**
91 * The MapFrame. Use setMapFrame to set or clear it.
92 */
93 public static MapFrame map;
94
95 /**
96 * Set or clear (if passed <code>null</code>) the map.
97 */
98 public final void setMapFrame(final MapFrame map) {
99 Main.map = map;
100 panel.setVisible(false);
101 panel.removeAll();
102 if (map != null) {
103 map.fillPanel(panel);
104 panel.setVisible(true);
105 map.mapView.addLayerChangeListener(new LayerChangeListener(){
106 public void activeLayerChange(final Layer oldLayer, final Layer newLayer) {
107 setLayerMenu(newLayer.getMenuEntries());
108 }
109 public void layerAdded(final Layer newLayer) {
110 if (newLayer instanceof OsmDataLayer)
111 Main.main.editLayer().listenerCommands.add(redoUndoListener);
112 }
113 public void layerRemoved(final Layer oldLayer) {
114 if (oldLayer instanceof OsmDataLayer)
115 Main.main.editLayer().listenerCommands.add(redoUndoListener);
116 if (map.mapView.getAllLayers().isEmpty())
117 setLayerMenu(null);
118 }
119 });
120 if (map.mapView.editLayer != null)
121 map.mapView.editLayer.listenerCommands.add(redoUndoListener);
122 }
123 redoUndoListener.commandChanged(0,0);
124 }
125
126 /**
127 * Set the layer menu (changed when active layer changes).
128 */
129 public final void setLayerMenu(Component[] entries) {
130 if (entries == null || entries.length == 0)
131 layerMenu.setVisible(false);
132 else {
133 layerMenu.removeAll();
134 for (Component c : entries)
135 layerMenu.add(c);
136 layerMenu.setVisible(true);
137 }
138 }
139
140 /**
141 * Remove the specified layer from the map. If it is the last layer, remove the map as well.
142 */
143 public final void removeLayer(final Layer layer) {
144 map.mapView.removeLayer(layer);
145 if (layer instanceof OsmDataLayer)
146 ds = new DataSet();
147 if (map.mapView.getAllLayers().isEmpty())
148 setMapFrame(null);
149 }
150 public Main() {
151 main = this;
152 contentPane.add(panel, BorderLayout.CENTER);
153
154 final Action annotationTesterAction = new AbstractAction(){
155 public void actionPerformed(ActionEvent e) {
156 String annotationSources = pref.get("annotation.sources");
157 if (annotationSources.equals("")) {
158 JOptionPane.showMessageDialog(Main.parent, "You have to specify annotation sources in the preferences first.");
159 return;
160 }
161 String[] args = annotationSources.split(";");
162 new AnnotationTester(args);
163 }
164 };
165 annotationTesterAction.putValue(Action.NAME, tr("Annotation Preset Tester"));
166 annotationTesterAction.putValue(Action.SMALL_ICON, ImageProvider.get("annotation-tester"));
167 final Action reverseSegmentAction = new AbstractAction(){
168 public void actionPerformed(ActionEvent e) {
169 Collection<OsmPrimitive> sel = Main.ds.getSelected();
170 boolean hasSegments = false;
171 for (OsmPrimitive osm : sel) {
172 if (osm instanceof Segment) {
173 hasSegments = true;
174 break;
175 }
176 }
177 if (!hasSegments) {
178 JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one segment."));
179 return;
180 }
181 Collection<Command> c = new LinkedList<Command>();
182 for (OsmPrimitive osm : sel) {
183 if (!(osm instanceof Segment))
184 continue;
185 Segment s = (Segment)osm;
186 Segment snew = new Segment(s);
187 Node n = snew.from;
188 snew.from = snew.to;
189 snew.to = n;
190 c.add(new ChangeCommand(s, snew));
191 }
192 editLayer().add(new SequenceCommand(tr("Reverse Segments"), c));
193 map.repaint();
194 }
195 };
196 reverseSegmentAction.putValue(Action.NAME, tr("Reverse Segments"));
197 reverseSegmentAction.putValue(Action.SMALL_ICON, ImageProvider.get("segmentflip"));
198
199 final Action uploadAction = new UploadAction();
200 final Action saveAction = new SaveAction();
201 final Action gpxExportAction = new GpxExportAction(null);
202 final Action exitAction = new ExitAction();
203 final Action preferencesAction = new PreferencesAction();
204 final Action aboutAction = new AboutAction();
205
206 final JMenu fileMenu = new JMenu(tr("Files"));
207 fileMenu.setMnemonic('F');
208 fileMenu.add(openAction);
209 fileMenu.add(saveAction);
210 fileMenu.add(gpxExportAction);
211 fileMenu.addSeparator();
212 fileMenu.add(exitAction);
213 mainMenu.add(fileMenu);
214
215
216 final JMenu connectionMenu = new JMenu(tr("Connection"));
217 connectionMenu.setMnemonic('C');
218 connectionMenu.add(downloadAction);
219 //connectionMenu.add(new DownloadIncompleteAction());
220 connectionMenu.add(uploadAction);
221 mainMenu.add(connectionMenu);
222
223 layerMenu = new JMenu(tr("Layer"));
224 layerMenu.setMnemonic('L');
225 mainMenu.add(layerMenu);
226 layerMenu.setVisible(false);
227
228 final JMenu editMenu = new JMenu(tr("Edit"));
229 editMenu.setMnemonic('E');
230 editMenu.add(undoAction);
231 editMenu.add(redoAction);
232 editMenu.addSeparator();
233 editMenu.add(reverseSegmentAction);
234 editMenu.addSeparator();
235 editMenu.add(preferencesAction);
236 mainMenu.add(editMenu);
237
238 mainMenu.add(new JSeparator());
239 final JMenu helpMenu = new JMenu(tr("Help"));
240 helpMenu.setMnemonic('H');
241 helpMenu.add(annotationTesterAction);
242 helpMenu.addSeparator();
243 helpMenu.add(aboutAction);
244 mainMenu.add(helpMenu);
245
246 // creating toolbar
247 final JToolBar toolBar = new JToolBar();
248 toolBar.setFloatable(false);
249 toolBar.add(downloadAction);
250 toolBar.add(uploadAction);
251 toolBar.addSeparator();
252 toolBar.add(openAction);
253 toolBar.add(saveAction);
254 toolBar.add(gpxExportAction);
255 toolBar.addSeparator();
256 toolBar.add(undoAction);
257 toolBar.add(redoAction);
258 toolBar.addSeparator();
259 toolBar.add(reverseSegmentAction);
260 toolBar.addSeparator();
261 toolBar.add(preferencesAction);
262 contentPane.add(toolBar, BorderLayout.NORTH);
263
264 contentPane.updateUI();
265 }
266 /**
267 * Add a new layer to the map. If no map exist, create one.
268 */
269 public final void addLayer(final Layer layer) {
270 if (map == null) {
271 final MapFrame mapFrame = new MapFrame();
272 setMapFrame(mapFrame);
273 mapFrame.selectMapMode((MapMode)mapFrame.getDefaultButtonAction());
274 mapFrame.setVisible(true);
275 mapFrame.setVisibleDialogs();
276 }
277 map.mapView.addLayer(layer);
278 }
279 /**
280 * @return The edit osm layer. If none exist, it will be created.
281 */
282 public final OsmDataLayer editLayer() {
283 if (map == null || map.mapView.editLayer == null)
284 addLayer(new OsmDataLayer(ds, tr("unnamed"), false));
285 return map.mapView.editLayer;
286 }
287
288
289
290
291 /**
292 * Use this to register shortcuts to
293 */
294 public static final JPanel contentPane = new JPanel(new BorderLayout());
295
296
297 ////////////////////////////////////////////////////////////////////////////////////////
298 // Implementation part
299 ////////////////////////////////////////////////////////////////////////////////////////
300
301
302 private static JPanel panel = new JPanel(new BorderLayout());
303
304 protected final JMenuBar mainMenu = new JMenuBar();
305 protected static Rectangle bounds;
306
307 private final UndoAction undoAction = new UndoAction();
308 private final RedoAction redoAction = new RedoAction();
309 private final OpenAction openAction = new OpenAction();
310 private final DownloadAction downloadAction = new DownloadAction();
311
312 private final CommandQueueListener redoUndoListener = new CommandQueueListener(){
313 public void commandChanged(final int queueSize, final int redoSize) {
314 undoAction.setEnabled(queueSize > 0);
315 redoAction.setEnabled(redoSize > 0);
316 }
317 };
318 private JMenu layerMenu;
319
320 /**
321 * Should be called before the main constructor to setup some parameter stuff
322 * @param args The parsed argument list.
323 */
324 public static void preConstructorInit(Map<String, Collection<String>> args) {
325 try {
326 Main.pref.upgrade(Integer.parseInt(AboutAction.version));
327 } catch (NumberFormatException e1) {
328 }
329
330 try {
331 Main.proj = (Projection)Class.forName(Main.pref.get("projection")).newInstance();
332 } catch (final Exception e) {
333 e.printStackTrace();
334 JOptionPane.showMessageDialog(null, tr("The projection could not be read from preferences. Using EPSG:4263."));
335 Main.proj = new Epsg4326();
336 }
337
338 try {
339 UIManager.setLookAndFeel(Main.pref.get("laf"));
340 contentPane.updateUI();
341 panel.updateUI();
342 } catch (final Exception e) {
343 e.printStackTrace();
344 }
345 UIManager.put("OptionPane.okIcon", ImageProvider.get("ok"));
346 UIManager.put("OptionPane.yesIcon", UIManager.get("OptionPane.okIcon"));
347 UIManager.put("OptionPane.cancelIcon", ImageProvider.get("cancel"));
348 UIManager.put("OptionPane.noIcon", UIManager.get("OptionPane.cancelIcon"));
349
350 Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
351 if (args.containsKey("geometry")) {
352 String geometry = args.get("geometry").iterator().next();
353 final Matcher m = Pattern.compile("(\\d+)x(\\d+)(([+-])(\\d+)([+-])(\\d+))?").matcher(geometry);
354 if (m.matches()) {
355 int w = Integer.valueOf(m.group(1));
356 int h = Integer.valueOf(m.group(2));
357 int x = 0, y = 0;
358 if (m.group(3) != null) {
359 x = Integer.valueOf(m.group(5));
360 y = Integer.valueOf(m.group(7));
361 if (m.group(4).equals("-"))
362 x = screenDimension.width - x - w;
363 if (m.group(6).equals("-"))
364 y = screenDimension.height - y - h;
365 }
366 bounds = new Rectangle(x,y,w,h);
367 } else
368 System.out.println("Ignoring malformed geometry: "+geometry);
369 }
370 if (bounds == null)
371 bounds = !args.containsKey("no-fullscreen") ? new Rectangle(0,0,screenDimension.width,screenDimension.height) : new Rectangle(1000,740);
372 }
373
374 public void postConstructorProcessCmdLine(Map<String, Collection<String>> args) {
375 if (args.containsKey("download"))
376 for (String s : args.get("download"))
377 downloadFromParamString(false, s);
378 if (args.containsKey("downloadgps"))
379 for (String s : args.get("downloadgps"))
380 downloadFromParamString(true, s);
381 if (args.containsKey("selection"))
382 for (String s : args.get("selection"))
383 SelectionListDialog.search(s, SelectionListDialog.SearchMode.add);
384 }
385
386 private static void downloadFromParamString(final boolean rawGps, String s) {
387 if (s.startsWith("http:")) {
388 final Bounds b = DownloadAction.osmurl2bounds(s);
389 if (b == null)
390 JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed url: \"{0}\"", s));
391 else
392 main.downloadAction.download(false, b.min.lat(), b.min.lon(), b.max.lat(), b.max.lon());
393 return;
394 }
395
396 if (s.startsWith("file:")) {
397 try {
398 main.openAction.openFile(new File(new URI(s)));
399 } catch (URISyntaxException e) {
400 JOptionPane.showMessageDialog(Main.parent, tr("Ignoring malformed file url: \"{0}\"", s));
401 }
402 return;
403 }
404
405 final StringTokenizer st = new StringTokenizer(s, ",");
406 if (st.countTokens() == 4) {
407 try {
408 main.downloadAction.download(rawGps, Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()));
409 return;
410 } catch (final NumberFormatException e) {
411 }
412 }
413
414 main.openAction.openFile(new File(s));
415 }
416}
Note: See TracBrowser for help on using the repository browser.