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

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