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

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