]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/MenuManager.java
Version 10, May 2010
[GpsPrune.git] / tim / prune / gui / MenuManager.java
1 package tim.prune.gui;
2
3 import java.awt.Toolkit;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.awt.event.KeyEvent;
7
8 import javax.swing.JButton;
9 import javax.swing.JCheckBoxMenuItem;
10 import javax.swing.JMenu;
11 import javax.swing.JMenuBar;
12 import javax.swing.JMenuItem;
13 import javax.swing.JToolBar;
14 import javax.swing.KeyStroke;
15
16 import tim.prune.App;
17 import tim.prune.DataSubscriber;
18 import tim.prune.FunctionLibrary;
19 import tim.prune.GenericFunction;
20 import tim.prune.I18nManager;
21 import tim.prune.UpdateMessageBroker;
22 import tim.prune.config.Config;
23 import tim.prune.data.Photo;
24 import tim.prune.data.PhotoList;
25 import tim.prune.data.Selection;
26 import tim.prune.data.Track;
27 import tim.prune.data.TrackInfo;
28 import tim.prune.function.RearrangeWaypointsFunction.Rearrange;
29 import tim.prune.function.browser.UrlGenerator;
30
31 /**
32  * Class to manage the menu bar and tool bar,
33  * including enabling and disabling the items
34  */
35 public class MenuManager implements DataSubscriber
36 {
37         private App _app = null;
38         private Track _track = null;
39         private Selection _selection = null;
40         private PhotoList _photos = null;
41
42         // Menu items which need enabling/disabling
43         private JMenuItem _sendGpsItem = null;
44         private JMenuItem _saveItem = null;
45         private JMenuItem _exportKmlItem = null;
46         private JMenuItem _exportGpxItem = null;
47         private JMenuItem _exportPovItem = null;
48         private JMenuItem _undoItem = null;
49         private JMenuItem _clearUndoItem = null;
50         private JMenuItem _editPointItem = null;
51         private JMenuItem _editWaypointNameItem = null;
52         private JMenuItem _deletePointItem = null;
53         private JMenuItem _deleteRangeItem = null;
54         private JMenuItem _compressItem = null;
55         private JMenuItem _deleteMarkedPointsItem = null;
56         private JMenuItem _interpolateItem = null;
57         private JMenuItem _averageItem = null;
58         private JMenuItem _selectAllItem = null;
59         private JMenuItem _selectNoneItem = null;
60         private JMenuItem _selectStartItem = null;
61         private JMenuItem _selectEndItem = null;
62         private JMenuItem _findWaypointItem = null;
63         private JMenuItem _duplicatePointItem = null;
64         private JMenuItem _reverseItem = null;
65         private JMenuItem _addTimeOffsetItem = null;
66         private JMenuItem _addAltitudeOffsetItem = null;
67         private JMenuItem _mergeSegmentsItem = null;
68         private JMenu     _rearrangeMenu = null;
69         private JMenuItem _cutAndMoveItem = null;
70         private JMenuItem _convertNamesToTimesItem = null;
71         private JCheckBoxMenuItem _mapCheckbox = null;
72         private JMenuItem _show3dItem = null;
73         private JMenu     _browserMapMenu = null;
74         private JMenuItem _chartItem = null;
75         private JMenuItem _getGpsiesItem = null;
76         private JMenuItem _lookupSrtmItem = null;
77         private JMenuItem _distanceItem = null;
78         private JMenuItem _fullRangeDetailsItem = null;
79         private JMenuItem _saveExifItem = null;
80         private JMenuItem _connectPhotoItem = null;
81         private JMenuItem _deletePhotoItem = null;
82         private JMenuItem _disconnectPhotoItem = null;
83         private JMenuItem _correlatePhotosItem = null;
84         private JMenuItem _rearrangePhotosItem = null;
85         private JMenuItem _rotatePhotoLeft = null;
86         private JMenuItem _rotatePhotoRight = null;
87         private JMenuItem _ignoreExifThumb = null;
88         private JCheckBoxMenuItem _onlineCheckbox = null;
89
90         // ActionListeners for reuse by menu and toolbar
91         private ActionListener _openFileAction = null;
92         private ActionListener _addPhotoAction = null;
93         private ActionListener _saveAction = null;
94         private ActionListener _undoAction = null;
95         private ActionListener _editPointAction = null;
96         private ActionListener _deletePointAction = null;
97         private ActionListener _deleteRangeAction = null;
98         private ActionListener _selectStartAction = null;
99         private ActionListener _selectEndAction = null;
100         private ActionListener _connectPhotoAction = null;
101
102         // Toolbar buttons which need enabling/disabling
103         private JButton _saveButton = null;
104         private JButton _undoButton = null;
105         private JButton _editPointButton = null;
106         private JButton _deletePointButton = null;
107         private JButton _deleteRangeButton = null;
108         private JButton _selectStartButton = null;
109         private JButton _selectEndButton = null;
110         private JButton _connectPhotoButton = null;
111
112         /** Array of key events */
113         private static final int[] KEY_EVENTS = {
114                 KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D, KeyEvent.VK_E,
115                 KeyEvent.VK_F, KeyEvent.VK_G, KeyEvent.VK_H, KeyEvent.VK_I, KeyEvent.VK_J,
116                 KeyEvent.VK_K, KeyEvent.VK_L, KeyEvent.VK_M, KeyEvent.VK_N, KeyEvent.VK_O,
117                 KeyEvent.VK_P, KeyEvent.VK_Q, KeyEvent.VK_R, KeyEvent.VK_S, KeyEvent.VK_T,
118                 KeyEvent.VK_U, KeyEvent.VK_V, KeyEvent.VK_W, KeyEvent.VK_X, KeyEvent.VK_Y, KeyEvent.VK_Z};
119
120
121         /**
122          * Constructor
123          * @param inApp application to call on menu actions
124          * @param inTrackInfo track info object
125          */
126         public MenuManager(App inApp, TrackInfo inTrackInfo)
127         {
128                 _app = inApp;
129                 _track = inTrackInfo.getTrack();
130                 _selection = inTrackInfo.getSelection();
131                 _photos = inTrackInfo.getPhotoList();
132         }
133
134
135         /**
136          * Create a JMenuBar containing all menu items
137          * @return JMenuBar
138          */
139         public JMenuBar createMenuBar()
140         {
141                 JMenuBar menubar = new JMenuBar();
142                 JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
143                 setAltKey(fileMenu, "altkey.menu.file");
144                 // Open file
145                 JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("function.open"));
146                 setShortcut(openMenuItem, "shortcut.menu.file.open");
147                 _openFileAction = new ActionListener() {
148                         public void actionPerformed(ActionEvent e)
149                         {
150                                 _app.openFile();
151                         }
152                 };
153                 openMenuItem.addActionListener(_openFileAction);
154                 fileMenu.add(openMenuItem);
155                 // Add photos
156                 JMenuItem addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
157                 _addPhotoAction = new ActionListener() {
158                         public void actionPerformed(ActionEvent e)
159                         {
160                                 _app.addPhotos();
161                         }
162                 };
163                 addPhotosMenuItem.addActionListener(_addPhotoAction);
164                 fileMenu.add(addPhotosMenuItem);
165                 fileMenu.addSeparator();
166                 // Load from GPS
167                 JMenuItem loadFromGpsMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSLOAD);
168                 setShortcut(loadFromGpsMenuItem, "shortcut.menu.file.load");
169                 fileMenu.add(loadFromGpsMenuItem);
170                 // Send to GPS
171                 _sendGpsItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSSAVE);
172                 _sendGpsItem.setEnabled(false);
173                 fileMenu.add(_sendGpsItem);
174                 fileMenu.addSeparator();
175                 // Save
176                 _saveItem = new JMenuItem(I18nManager.getText("menu.file.save"), KeyEvent.VK_S);
177                 setShortcut(_saveItem, "shortcut.menu.file.save");
178                 _saveAction = new ActionListener() {
179                         public void actionPerformed(ActionEvent e)
180                         {
181                                 _app.saveFile();
182                         }
183                 };
184                 _saveItem.addActionListener(_saveAction);
185                 _saveItem.setEnabled(false);
186                 fileMenu.add(_saveItem);
187                 // Export - Kml
188                 _exportKmlItem = makeMenuItem(FunctionLibrary.FUNCTION_KMLEXPORT);
189                 _exportKmlItem.setEnabled(false);
190                 fileMenu.add(_exportKmlItem);
191                 // Gpx
192                 _exportGpxItem = makeMenuItem(FunctionLibrary.FUNCTION_GPXEXPORT);
193                 _exportGpxItem.setEnabled(false);
194                 fileMenu.add(_exportGpxItem);
195                 // Pov
196                 _exportPovItem = makeMenuItem(FunctionLibrary.FUNCTION_POVEXPORT);
197                 _exportPovItem.setEnabled(false);
198                 fileMenu.add(_exportPovItem);
199                 fileMenu.addSeparator();
200                 JMenuItem exitMenuItem = new JMenuItem(I18nManager.getText("menu.file.exit"));
201                 exitMenuItem.addActionListener(new ActionListener() {
202                         public void actionPerformed(ActionEvent e)
203                         {
204                                 _app.exit();
205                         }
206                 });
207                 fileMenu.add(exitMenuItem);
208                 menubar.add(fileMenu);
209                 // Track menu
210                 JMenu trackMenu = new JMenu(I18nManager.getText("menu.track"));
211                 setAltKey(trackMenu, "altkey.menu.track");
212                 _undoItem = new JMenuItem(I18nManager.getText("menu.track.undo"));
213                 setShortcut(_undoItem, "shortcut.menu.track.undo");
214                 _undoAction = new ActionListener() {
215                         public void actionPerformed(ActionEvent e)
216                         {
217                                 _app.beginUndo();
218                         }
219                 };
220                 _undoItem.addActionListener(_undoAction);
221                 _undoItem.setEnabled(false);
222                 trackMenu.add(_undoItem);
223                 _clearUndoItem = new JMenuItem(I18nManager.getText("menu.track.clearundo"));
224                 _clearUndoItem.addActionListener(new ActionListener() {
225                         public void actionPerformed(ActionEvent e)
226                         {
227                                 _app.clearUndo();
228                         }
229                 });
230                 _clearUndoItem.setEnabled(false);
231                 trackMenu.add(_clearUndoItem);
232                 trackMenu.addSeparator();
233                 _compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS);
234                 setShortcut(_compressItem, "shortcut.menu.edit.compress");
235                 _compressItem.setEnabled(false);
236                 trackMenu.add(_compressItem);
237                 _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
238                 _deleteMarkedPointsItem.addActionListener(new ActionListener() {
239                         public void actionPerformed(ActionEvent e)
240                         {
241                                 _app.finishCompressTrack();
242                         }
243                 });
244                 _deleteMarkedPointsItem.setEnabled(false);
245                 trackMenu.add(_deleteMarkedPointsItem);
246                 trackMenu.addSeparator();
247                 // Rearrange waypoints
248                 _rearrangeMenu = new JMenu(I18nManager.getText("menu.track.rearrange"));
249                 _rearrangeMenu.setEnabled(false);
250                 JMenuItem  rearrangeStartItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.start"));
251                 rearrangeStartItem.addActionListener(new ActionListener() {
252                         public void actionPerformed(ActionEvent e)
253                         {
254                                 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_START);
255                         }
256                 });
257                 rearrangeStartItem.setEnabled(true);
258                 _rearrangeMenu.add(rearrangeStartItem);
259                 JMenuItem rearrangeEndItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.end"));
260                 rearrangeEndItem.addActionListener(new ActionListener() {
261                         public void actionPerformed(ActionEvent e)
262                         {
263                                 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_END);
264                         }
265                 });
266                 rearrangeEndItem.setEnabled(true);
267                 _rearrangeMenu.add(rearrangeEndItem);
268                 JMenuItem rearrangeNearestItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.nearest"));
269                 rearrangeNearestItem.addActionListener(new ActionListener() {
270                         public void actionPerformed(ActionEvent e)
271                         {
272                                 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_NEAREST);
273                         }
274                 });
275                 rearrangeNearestItem.setEnabled(true);
276                 _rearrangeMenu.add(rearrangeNearestItem);
277                 trackMenu.add(_rearrangeMenu);
278                 // Get gpsies tracks
279                 _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES);
280                 _getGpsiesItem.setEnabled(false);
281                 trackMenu.add(_getGpsiesItem);
282                 _lookupSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_SRTM);
283                 _lookupSrtmItem.setEnabled(false);
284                 trackMenu.add(_lookupSrtmItem);
285                 menubar.add(trackMenu);
286
287                 // Range menu
288                 JMenu rangeMenu = new JMenu(I18nManager.getText("menu.range"));
289                 setAltKey(rangeMenu, "altkey.menu.range");
290                 _selectAllItem = new JMenuItem(I18nManager.getText("menu.range.all"));
291                 setShortcut(_selectAllItem, "shortcut.menu.range.all");
292                 _selectAllItem.setEnabled(false);
293                 _selectAllItem.addActionListener(new ActionListener() {
294                         public void actionPerformed(ActionEvent e)
295                         {
296                                 _selection.selectRange(0, _track.getNumPoints()-1);
297                         }
298                 });
299                 rangeMenu.add(_selectAllItem);
300                 _selectNoneItem = new JMenuItem(I18nManager.getText("menu.range.none"));
301                 _selectNoneItem.setEnabled(false);
302                 _selectNoneItem.addActionListener(new ActionListener() {
303                         public void actionPerformed(ActionEvent e)
304                         {
305                                 _app.selectNone();
306                         }
307                 });
308                 rangeMenu.add(_selectNoneItem);
309                 rangeMenu.addSeparator();
310                 _selectStartItem = new JMenuItem(I18nManager.getText("menu.range.start"));
311                 _selectStartItem.setEnabled(false);
312                 _selectStartAction = new ActionListener() {
313                         public void actionPerformed(ActionEvent e)
314                         {
315                                 _selection.selectRangeStart();
316                         }
317                 };
318                 _selectStartItem.addActionListener(_selectStartAction);
319                 rangeMenu.add(_selectStartItem);
320                 _selectEndItem = new JMenuItem(I18nManager.getText("menu.range.end"));
321                 _selectEndItem.setEnabled(false);
322                 _selectEndAction = new ActionListener() {
323                         public void actionPerformed(ActionEvent e)
324                         {
325                                 _selection.selectRangeEnd();
326                         }
327                 };
328                 _selectEndItem.addActionListener(_selectEndAction);
329                 rangeMenu.add(_selectEndItem);
330                 rangeMenu.addSeparator();
331                 _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.range.deleterange"));
332                 _deleteRangeAction = new ActionListener() {
333                         public void actionPerformed(ActionEvent e)
334                         {
335                                 _app.deleteSelectedRange();
336                         }
337                 };
338                 _deleteRangeItem.addActionListener(_deleteRangeAction);
339                 _deleteRangeItem.setEnabled(false);
340                 rangeMenu.add(_deleteRangeItem);
341                 _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
342                 _reverseItem.addActionListener(new ActionListener() {
343                         public void actionPerformed(ActionEvent e)
344                         {
345                                 _app.reverseRange();
346                         }
347                 });
348                 _reverseItem.setEnabled(false);
349                 rangeMenu.add(_reverseItem);
350                 _addTimeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_TIME_OFFSET);
351                 _addTimeOffsetItem.setEnabled(false);
352                 rangeMenu.add(_addTimeOffsetItem);
353                 _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET);
354                 _addAltitudeOffsetItem.setEnabled(false);
355                 rangeMenu.add(_addAltitudeOffsetItem);
356                 _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.range.mergetracksegments"));
357                 _mergeSegmentsItem.addActionListener(new ActionListener() {
358                         public void actionPerformed(ActionEvent e)
359                         {
360                                 _app.mergeTrackSegments();
361                         }
362                 });
363                 _mergeSegmentsItem.setEnabled(false);
364                 rangeMenu.add(_mergeSegmentsItem);
365                 rangeMenu.addSeparator();
366                 _interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
367                 _interpolateItem.addActionListener(new ActionListener() {
368                         public void actionPerformed(ActionEvent e)
369                         {
370                                 _app.interpolateSelection();
371                         }
372                 });
373                 _interpolateItem.setEnabled(false);
374                 rangeMenu.add(_interpolateItem);
375                 _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
376                 _averageItem.addActionListener(new ActionListener() {
377                         public void actionPerformed(ActionEvent e)
378                         {
379                                 _app.averageSelection();
380                         }
381                 });
382                 _averageItem.setEnabled(false);
383                 rangeMenu.add(_averageItem);
384                 _cutAndMoveItem = new JMenuItem(I18nManager.getText("menu.range.cutandmove"));
385                 _cutAndMoveItem.addActionListener(new ActionListener() {
386                         public void actionPerformed(ActionEvent e)
387                         {
388                                 _app.cutAndMoveSelection();
389                         }
390                 });
391                 _cutAndMoveItem.setEnabled(false);
392                 rangeMenu.add(_cutAndMoveItem);
393                 _convertNamesToTimesItem = makeMenuItem(FunctionLibrary.FUNCTION_CONVERT_NAMES_TO_TIMES);
394                 _convertNamesToTimesItem.setEnabled(false);
395                 rangeMenu.add(_convertNamesToTimesItem);
396                 menubar.add(rangeMenu);
397
398                 // Point menu
399                 JMenu pointMenu = new JMenu(I18nManager.getText("menu.point"));
400                 setAltKey(pointMenu, "altkey.menu.point");
401                 _editPointItem = new JMenuItem(I18nManager.getText("menu.point.editpoint"));
402                 _editPointAction = new ActionListener() {
403                         public void actionPerformed(ActionEvent e)
404                         {
405                                 _app.editCurrentPoint();
406                         }
407                 };
408                 _editPointItem.addActionListener(_editPointAction);
409                 _editPointItem.setEnabled(false);
410                 pointMenu.add(_editPointItem);
411                 _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME);
412                 _editWaypointNameItem.setEnabled(false);
413                 pointMenu.add(_editWaypointNameItem);
414                 _deletePointItem = new JMenuItem(I18nManager.getText("menu.point.deletepoint"));
415                 _deletePointAction = new ActionListener() {
416                         public void actionPerformed(ActionEvent e)
417                         {
418                                 _app.deleteCurrentPoint();
419                         }
420                 };
421                 _deletePointItem.addActionListener(_deletePointAction);
422                 _deletePointItem.setEnabled(false);
423                 _deletePointItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
424                 pointMenu.add(_deletePointItem);
425                 pointMenu.addSeparator();
426                 // find a waypoint
427                 _findWaypointItem = makeMenuItem(FunctionLibrary.FUNCTION_FIND_WAYPOINT);
428                 _findWaypointItem.setEnabled(false);
429                 pointMenu.add(_findWaypointItem);
430                 // duplicate current point
431                 _duplicatePointItem = makeMenuItem(FunctionLibrary.FUNCTION_DUPLICATE_POINT);
432                 _duplicatePointItem.setEnabled(false);
433                 pointMenu.add(_duplicatePointItem);
434                 // paste coordinates function
435                 JMenuItem pasteCoordsItem = makeMenuItem(FunctionLibrary.FUNCTION_PASTE_COORDINATES);
436                 pointMenu.add(pasteCoordsItem);
437                 menubar.add(pointMenu);
438
439                 // Add view menu
440                 JMenu viewMenu = new JMenu(I18nManager.getText("menu.view"));
441                 setAltKey(viewMenu, "altkey.menu.view");
442                 // Turn map display on/off
443                 _mapCheckbox = new JCheckBoxMenuItem(
444                         I18nManager.getText("menu.map.showmap"), false);
445                 _mapCheckbox.addActionListener(new ActionListener() {
446                         public void actionPerformed(ActionEvent e) {
447                                 Config.setConfigBoolean(Config.KEY_SHOW_MAP, _mapCheckbox.isSelected());
448                                 UpdateMessageBroker.informSubscribers();
449                         }
450                 });
451                 viewMenu.add(_mapCheckbox);
452                 _show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D);
453                 _show3dItem.setEnabled(false);
454                 viewMenu.add(_show3dItem);
455                 // browser submenu
456                 _browserMapMenu = new JMenu(I18nManager.getText("menu.view.browser"));
457                 _browserMapMenu.setEnabled(false);
458                 JMenuItem googleMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.google"));
459                 googleMapsItem.addActionListener(new ActionListener() {
460                         public void actionPerformed(ActionEvent e)
461                         {
462                                 _app.showExternalMap(UrlGenerator.MAP_SOURCE_GOOGLE);
463                         }
464                 });
465                 _browserMapMenu.add(googleMapsItem);
466                 JMenuItem openMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.openstreetmap"));
467                 openMapsItem.addActionListener(new ActionListener() {
468                         public void actionPerformed(ActionEvent e)
469                         {
470                                 _app.showExternalMap(UrlGenerator.MAP_SOURCE_OSM);
471                         }
472                 });
473                 _browserMapMenu.add(openMapsItem);
474                 JMenuItem mapquestMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.mapquest"));
475                 mapquestMapsItem.addActionListener(new ActionListener() {
476                         public void actionPerformed(ActionEvent e)
477                         {
478                                 _app.showExternalMap(UrlGenerator.MAP_SOURCE_MAPQUEST);
479                         }
480                 });
481                 _browserMapMenu.add(mapquestMapsItem);
482                 JMenuItem yahooMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.yahoo"));
483                 yahooMapsItem.addActionListener(new ActionListener() {
484                         public void actionPerformed(ActionEvent e)
485                         {
486                                 _app.showExternalMap(UrlGenerator.MAP_SOURCE_YAHOO);
487                         }
488                 });
489                 _browserMapMenu.add(yahooMapsItem);
490                 JMenuItem bingMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.bing"));
491                 bingMapsItem.addActionListener(new ActionListener() {
492                         public void actionPerformed(ActionEvent e)
493                         {
494                                 _app.showExternalMap(UrlGenerator.MAP_SOURCE_BING);
495                         }
496                 });
497                 _browserMapMenu.add(bingMapsItem);
498                 viewMenu.add(_browserMapMenu);
499                 // Charts
500                 _chartItem = makeMenuItem(FunctionLibrary.FUNCTION_CHARTS);
501                 _chartItem.setEnabled(false);
502                 viewMenu.add(_chartItem);
503                 // Distances
504                 _distanceItem = makeMenuItem(FunctionLibrary.FUNCTION_DISTANCES);
505                 _distanceItem.setEnabled(false);
506                 viewMenu.add(_distanceItem);
507                 // full range details
508                 _fullRangeDetailsItem = makeMenuItem(FunctionLibrary.FUNCTION_FULL_RANGE_DETAILS);
509                 _fullRangeDetailsItem.setEnabled(false);
510                 viewMenu.add(_fullRangeDetailsItem);
511                 menubar.add(viewMenu);
512
513                 // Add photo menu
514                 JMenu photoMenu = new JMenu(I18nManager.getText("menu.photo"));
515                 setAltKey(photoMenu, "altkey.menu.photo");
516                 addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
517                 addPhotosMenuItem.addActionListener(_addPhotoAction);
518                 photoMenu.add(addPhotosMenuItem);
519                 _saveExifItem = new JMenuItem(I18nManager.getText("menu.photo.saveexif"));
520                 _saveExifItem.addActionListener(new ActionListener() {
521                         public void actionPerformed(ActionEvent e)
522                         {
523                                 _app.saveExif();
524                         }
525                 });
526                 _saveExifItem.setEnabled(false);
527                 photoMenu.add(_saveExifItem);
528                 _connectPhotoItem = new JMenuItem(I18nManager.getText("menu.photo.connect"));
529                 _connectPhotoAction = new ActionListener() {
530                         public void actionPerformed(ActionEvent e)
531                         {
532                                 _app.connectPhotoToPoint();
533                         }
534                 };
535                 _connectPhotoItem.addActionListener(_connectPhotoAction);
536                 _connectPhotoItem.setEnabled(false);
537                 photoMenu.addSeparator();
538                 photoMenu.add(_connectPhotoItem);
539                 // disconnect photo
540                 _disconnectPhotoItem = new JMenuItem(I18nManager.getText("menu.photo.disconnect"));
541                 _disconnectPhotoItem.addActionListener(new ActionListener() {
542                         public void actionPerformed(ActionEvent e)
543                         {
544                                 _app.disconnectPhotoFromPoint();
545                         }
546                 });
547                 _disconnectPhotoItem.setEnabled(false);
548                 photoMenu.add(_disconnectPhotoItem);
549                 _deletePhotoItem = new JMenuItem(I18nManager.getText("menu.photo.delete"));
550                 _deletePhotoItem.addActionListener(new ActionListener() {
551                         public void actionPerformed(ActionEvent e)
552                         {
553                                 _app.deleteCurrentPhoto();
554                         }
555                 });
556                 _deletePhotoItem.setEnabled(false);
557                 photoMenu.add(_deletePhotoItem);
558                 // Rotate current photo
559                 _rotatePhotoLeft = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_LEFT);
560                 _rotatePhotoLeft.setEnabled(false);
561                 photoMenu.add(_rotatePhotoLeft);
562                 _rotatePhotoRight = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_RIGHT);
563                 _rotatePhotoRight.setEnabled(false);
564                 photoMenu.add(_rotatePhotoRight);
565                 _ignoreExifThumb = makeMenuItem(FunctionLibrary.FUNCTION_IGNORE_EXIF_THUMB);
566                 _ignoreExifThumb.setEnabled(false);
567                 photoMenu.add(_ignoreExifThumb);
568                 photoMenu.addSeparator();
569                 // correlate all photos
570                 _correlatePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_PHOTOS);
571                 _correlatePhotosItem.setEnabled(false);
572                 photoMenu.add(_correlatePhotosItem);
573                 // rearrange photo points
574                 _rearrangePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_REARRANGE_PHOTOS);
575                 _rearrangePhotosItem.setEnabled(false);
576                 photoMenu.add(_rearrangePhotosItem);
577                 menubar.add(photoMenu);
578
579                 // Settings menu
580                 JMenu settingsMenu = new JMenu(I18nManager.getText("menu.settings"));
581                 setAltKey(settingsMenu, "altkey.menu.settings");
582                 // Set the map background
583                 JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
584                 settingsMenu.add(mapBgItem);
585                 _onlineCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.settings.onlinemode"));
586                 _onlineCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ONLINE_MODE));
587                 _onlineCheckbox.addActionListener(new ActionListener() {
588                         public void actionPerformed(ActionEvent e) {
589                                 boolean isOnline = _onlineCheckbox.isSelected();
590                                 Config.setConfigBoolean(Config.KEY_ONLINE_MODE, isOnline);
591                                 if (isOnline) {UpdateMessageBroker.informSubscribers();}
592                         }
593                 });
594                 settingsMenu.add(_onlineCheckbox);
595                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_DISK_CACHE));
596                 settingsMenu.addSeparator();
597                 // Set kmz image size
598                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE));
599                 // Set program paths
600                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS));
601                 // Set colours
602                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS));
603                 // Set language
604                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE));
605                 settingsMenu.addSeparator();
606                 // Save configuration
607                 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG));
608                 menubar.add(settingsMenu);
609
610                 // Help menu
611                 JMenu helpMenu = new JMenu(I18nManager.getText("menu.help"));
612                 setAltKey(helpMenu, "altkey.menu.help");
613                 JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
614                 setShortcut(helpItem, "shortcut.menu.help.help");
615                 helpMenu.add(helpItem);
616                 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS));
617                 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_ABOUT));
618                 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION));
619                 menubar.add(helpMenu);
620
621                 return menubar;
622         }
623
624         /**
625          * Convenience method for making a menu item using a function
626          * @param inFunction function
627          * @return menu item using localized name of function
628          */
629         private static JMenuItem makeMenuItem(GenericFunction inFunction)
630         {
631                 JMenuItem item = new JMenuItem(I18nManager.getText(inFunction.getNameKey()));
632                 item.addActionListener(new FunctionLauncher(inFunction));
633                 return item;
634         }
635
636         /**
637          * Set the alt key for the given menu
638          * @param inMenu menu to set
639          * @param inKey key to lookup to get language-sensitive altkey
640          */
641         private static void setAltKey(JMenu inMenu, String inKey)
642         {
643                 // Lookup the key in the properties
644                 String altKey = I18nManager.getText(inKey);
645                 if (altKey != null && altKey.length() == 1)
646                 {
647                         int code = altKey.charAt(0) - 'A';
648                         if (code >= 0 && code < 26)
649                         {
650                                 // Found a valid code between A and Z
651                                 inMenu.setMnemonic(KEY_EVENTS[code]);
652                         }
653                 }
654         }
655
656         /**
657          * Set the shortcut key for the given menu item
658          * @param inMenuItem menu item to set
659          * @param inKey key to lookup to get language-sensitive shortcut
660          */
661         private static void setShortcut(JMenuItem inMenuItem, String inKey)
662         {
663                 // Lookup the key in the properties
664                 String altKey = I18nManager.getText(inKey);
665                 if (altKey != null && altKey.length() == 1)
666                 {
667                         int code = altKey.charAt(0) - 'A';
668                         if (code >= 0 && code < 26)
669                         {
670                                 // Found a valid code between A and Z
671                                 inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code],
672                                         Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
673                                 // use platform-specific key mask so Ctrl on Linux/Win, Clover on Mac
674                         }
675                 }
676         }
677
678         /**
679          * Create a JToolBar containing all toolbar buttons
680          * @return toolbar containing buttons
681          */
682         public JToolBar createToolBar()
683         {
684                 JToolBar toolbar = new JToolBar();
685                 // Add text file
686                 JButton openFileButton = new JButton(IconManager.getImageIcon(IconManager.OPEN_FILE));
687                 openFileButton.setToolTipText(I18nManager.getText("function.open"));
688                 openFileButton.addActionListener(_openFileAction);
689                 toolbar.add(openFileButton);
690                 // Add photo
691                 JButton addPhotoButton = new JButton(IconManager.getImageIcon(IconManager.ADD_PHOTO));
692                 addPhotoButton.setToolTipText(I18nManager.getText("menu.file.addphotos"));
693                 addPhotoButton.addActionListener(_addPhotoAction);
694                 toolbar.add(addPhotoButton);
695                 // Save
696                 _saveButton = new JButton(IconManager.getImageIcon(IconManager.SAVE_FILE));
697                 _saveButton.setToolTipText(I18nManager.getText("menu.file.save"));
698                 _saveButton.addActionListener(_saveAction);
699                 _saveButton.setEnabled(false);
700                 toolbar.add(_saveButton);
701                 // Undo
702                 _undoButton = new JButton(IconManager.getImageIcon(IconManager.UNDO));
703                 _undoButton.setToolTipText(I18nManager.getText("menu.track.undo"));
704                 _undoButton.addActionListener(_undoAction);
705                 _undoButton.setEnabled(false);
706                 toolbar.add(_undoButton);
707                 // Edit point
708                 _editPointButton = new JButton(IconManager.getImageIcon(IconManager.EDIT_POINT));
709                 _editPointButton.setToolTipText(I18nManager.getText("menu.point.editpoint"));
710                 _editPointButton.addActionListener(_editPointAction);
711                 _editPointButton.setEnabled(false);
712                 toolbar.add(_editPointButton);
713                 // Delete point
714                 _deletePointButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_POINT));
715                 _deletePointButton.setToolTipText(I18nManager.getText("menu.point.deletepoint"));
716                 _deletePointButton.addActionListener(_deletePointAction);
717                 _deletePointButton.setEnabled(false);
718                 toolbar.add(_deletePointButton);
719                 // Delete range
720                 _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
721                 _deleteRangeButton.setToolTipText(I18nManager.getText("menu.range.deleterange"));
722                 _deleteRangeButton.addActionListener(_deleteRangeAction);
723                 _deleteRangeButton.setEnabled(false);
724                 toolbar.add(_deleteRangeButton);
725                 // Select start, end
726                 _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
727                 _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
728                 _selectStartButton.addActionListener(_selectStartAction);
729                 _selectStartButton.setEnabled(false);
730                 toolbar.add(_selectStartButton);
731                 _selectEndButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_END));
732                 _selectEndButton.setToolTipText(I18nManager.getText("menu.range.end"));
733                 _selectEndButton.addActionListener(_selectEndAction);
734                 _selectEndButton.setEnabled(false);
735                 toolbar.add(_selectEndButton);
736                 _connectPhotoButton = new JButton(IconManager.getImageIcon(IconManager.CONNECT_PHOTO));
737                 _connectPhotoButton.setToolTipText(I18nManager.getText("menu.photo.connect"));
738                 _connectPhotoButton.addActionListener(_connectPhotoAction);
739                 _connectPhotoButton.setEnabled(false);
740                 toolbar.add(_connectPhotoButton);
741                 // finish off
742                 toolbar.setFloatable(false);
743                 return toolbar;
744         }
745
746
747         /**
748          * Method to update menu when file loaded
749          */
750         public void informFileLoaded()
751         {
752                 // save, undo, delete enabled
753                 _sendGpsItem.setEnabled(true);
754                 _saveItem.setEnabled(true);
755                 _undoItem.setEnabled(true);
756                 _compressItem.setEnabled(true);
757                 _deleteMarkedPointsItem.setEnabled(false);
758         }
759
760
761         /**
762          * @see tim.prune.DataSubscriber#dataUpdated(tim.prune.data.Track)
763          */
764         public void dataUpdated(byte inUpdateType)
765         {
766                 boolean hasData = (_track != null && _track.getNumPoints() > 0);
767                 // set functions which require data
768                 _sendGpsItem.setEnabled(hasData);
769                 _saveItem.setEnabled(hasData);
770                 _saveButton.setEnabled(hasData);
771                 _exportKmlItem.setEnabled(hasData);
772                 _exportGpxItem.setEnabled(hasData);
773                 _exportPovItem.setEnabled(hasData);
774                 _compressItem.setEnabled(hasData);
775                 _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
776                 _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
777                 _selectAllItem.setEnabled(hasData);
778                 _selectNoneItem.setEnabled(hasData);
779                 _show3dItem.setEnabled(hasData);
780                 _chartItem.setEnabled(hasData);
781                 _browserMapMenu.setEnabled(hasData);
782                 _distanceItem.setEnabled(hasData);
783                 _getGpsiesItem.setEnabled(hasData);
784                 _lookupSrtmItem.setEnabled(hasData);
785                 _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
786                 // is undo available?
787                 boolean hasUndo = !_app.getUndoStack().isEmpty();
788                 _undoItem.setEnabled(hasUndo);
789                 _undoButton.setEnabled(hasUndo);
790                 _clearUndoItem.setEnabled(hasUndo);
791                 // is there a current point?
792                 boolean hasPoint = (hasData && _selection.getCurrentPointIndex() >= 0);
793                 _editPointItem.setEnabled(hasPoint);
794                 _editPointButton.setEnabled(hasPoint);
795                 _editWaypointNameItem.setEnabled(hasPoint);
796                 _deletePointItem.setEnabled(hasPoint);
797                 _deletePointButton.setEnabled(hasPoint);
798                 _selectStartItem.setEnabled(hasPoint);
799                 _selectStartButton.setEnabled(hasPoint);
800                 _selectEndItem.setEnabled(hasPoint);
801                 _selectEndButton.setEnabled(hasPoint);
802                 _duplicatePointItem.setEnabled(hasPoint);
803                 // are there any photos?
804                 boolean anyPhotos = _photos != null && _photos.getNumPhotos() > 0;
805                 _saveExifItem.setEnabled(anyPhotos);
806                 // is there a current photo?
807                 boolean hasPhoto = anyPhotos && _selection.getCurrentPhotoIndex() >= 0;
808                 // connect is available if photo and point selected, and photo has no point
809                 Photo currentPhoto = _photos.getPhoto(_selection.getCurrentPhotoIndex());
810                 boolean connectAvailable = hasPhoto && hasPoint && currentPhoto != null
811                         && currentPhoto.getDataPoint() == null;
812                 _connectPhotoItem.setEnabled(connectAvailable);
813                 _connectPhotoButton.setEnabled(connectAvailable);
814                 _disconnectPhotoItem.setEnabled(hasPhoto && currentPhoto != null && currentPhoto.getDataPoint() != null);
815                 _correlatePhotosItem.setEnabled(anyPhotos && hasData);
816                 _rearrangePhotosItem.setEnabled(anyPhotos && hasData && _track.getNumPoints() > 1);
817                 _deletePhotoItem.setEnabled(hasPhoto);
818                 _rotatePhotoLeft.setEnabled(hasPhoto);
819                 _rotatePhotoRight.setEnabled(hasPhoto);
820                 _ignoreExifThumb.setEnabled(hasPhoto && currentPhoto != null && currentPhoto.getExifThumbnail() != null);
821                 // is there a current range?
822                 boolean hasRange = (hasData && _selection.hasRangeSelected());
823                 _deleteRangeItem.setEnabled(hasRange);
824                 _deleteRangeButton.setEnabled(hasRange);
825                 _interpolateItem.setEnabled(hasRange
826                         && (_selection.getEnd() - _selection.getStart()) == 1);
827                 _averageItem.setEnabled(hasRange);
828                 _mergeSegmentsItem.setEnabled(hasRange);
829                 _reverseItem.setEnabled(hasRange);
830                 _addTimeOffsetItem.setEnabled(hasRange);
831                 _addAltitudeOffsetItem.setEnabled(hasRange);
832                 _convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
833                 _fullRangeDetailsItem.setEnabled(hasRange);
834                 // Is the currently selected point outside the current range?
835                 _cutAndMoveItem.setEnabled(hasRange && hasPoint &&
836                         (_selection.getCurrentPointIndex() < _selection.getStart()
837                                 || _selection.getCurrentPointIndex() > (_selection.getEnd()+1)));
838                 // Has the map been switched on/off?
839                 boolean mapsOn = Config.getConfigBoolean(Config.KEY_SHOW_MAP);
840                 if (_mapCheckbox.isSelected() != mapsOn) {
841                         _mapCheckbox.setSelected(mapsOn);
842                 }
843         }
844
845
846         /**
847          * Ignore action completed signals
848          * @see tim.prune.DataSubscriber#actionCompleted(java.lang.String)
849          */
850         public void actionCompleted(String inMessage)
851         {}
852 }