3 import java.awt.Toolkit;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.awt.event.KeyEvent;
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;
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.AudioClip;
24 import tim.prune.data.Photo;
25 import tim.prune.data.RecentFile;
26 import tim.prune.data.RecentFileList;
27 import tim.prune.data.Selection;
28 import tim.prune.data.Track;
29 import tim.prune.data.TrackInfo;
30 import tim.prune.function.RearrangeWaypointsFunction.Rearrange;
31 import tim.prune.function.browser.UrlGenerator;
34 * Class to manage the menu bar and tool bar,
35 * including enabling and disabling the items
37 public class MenuManager implements DataSubscriber
39 private App _app = null;
40 private Track _track = null;
41 private Selection _selection = null;
43 // Menu items which need enabling/disabling
44 private JMenuItem _sendGpsItem = null;
45 private JMenuItem _saveItem = null;
46 private JMenuItem _exportKmlItem = null;
47 private JMenuItem _exportGpxItem = null;
48 private JMenuItem _exportPovItem = null;
49 private JMenuItem _exportSvgItem = null;
50 private JMenu _recentFileMenu = null;
51 private JMenuItem _undoItem = null;
52 private JMenuItem _clearUndoItem = null;
53 private JMenuItem _editPointItem = null;
54 private JMenuItem _editWaypointNameItem = null;
55 private JMenuItem _deletePointItem = null;
56 private JMenuItem _deleteRangeItem = null;
57 private JMenuItem _compressItem = null;
58 private JMenuItem _deleteMarkedPointsItem = null;
59 private JMenuItem _interpolateItem = null;
60 private JMenuItem _averageItem = null;
61 private JMenuItem _selectAllItem = null;
62 private JMenuItem _selectNoneItem = null;
63 private JMenuItem _selectStartItem = null;
64 private JMenuItem _selectEndItem = null;
65 private JMenuItem _findWaypointItem = null;
66 private JMenuItem _duplicatePointItem = null;
67 private JMenuItem _reverseItem = null;
68 private JMenuItem _addTimeOffsetItem = null;
69 private JMenuItem _addAltitudeOffsetItem = null;
70 private JMenuItem _mergeSegmentsItem = null;
71 private JMenu _rearrangeMenu = null;
72 private JMenuItem _cutAndMoveItem = null;
73 private JMenuItem _convertNamesToTimesItem = null;
74 private JMenuItem _deleteFieldValuesItem = null;
75 private JCheckBoxMenuItem _mapCheckbox = null;
76 private JMenuItem _show3dItem = null;
77 private JMenu _browserMapMenu = null;
78 private JMenuItem _chartItem = null;
79 private JMenuItem _getGpsiesItem = null;
80 private JMenuItem _uploadGpsiesItem = null;
81 private JMenuItem _lookupSrtmItem = null;
82 private JMenuItem _lookupWikipediaItem = null;
83 private JMenuItem _downloadOsmItem = null;
84 private JMenuItem _distanceItem = null;
85 private JMenuItem _fullRangeDetailsItem = null;
86 private JMenuItem _saveExifItem = null;
87 private JMenuItem _photoPopupItem = null;
88 private JMenuItem _selectNoPhotoItem = null;
89 private JMenuItem _connectPhotoItem = null;
90 private JMenuItem _removePhotoItem = null;
91 private JMenuItem _disconnectPhotoItem = null;
92 private JMenuItem _correlatePhotosItem = null;
93 private JMenuItem _rearrangePhotosItem = null;
94 private JMenuItem _rotatePhotoLeft = null;
95 private JMenuItem _rotatePhotoRight = null;
96 private JMenuItem _ignoreExifThumb = null;
97 private JMenuItem _connectAudioItem = null;
98 private JMenuItem _disconnectAudioItem = null;
99 private JMenuItem _removeAudioItem = null;
100 private JMenuItem _correlateAudiosItem = null;
101 private JMenuItem _selectNoAudioItem = null;
102 private JCheckBoxMenuItem _onlineCheckbox = null;
103 private JCheckBoxMenuItem _autosaveSettingsCheckbox = null;
105 // ActionListeners for reuse by menu and toolbar
106 private ActionListener _openFileAction = null;
107 private ActionListener _addPhotoAction = null;
108 private ActionListener _saveAction = null;
109 private ActionListener _undoAction = null;
110 private ActionListener _editPointAction = null;
111 private ActionListener _deletePointAction = null;
112 private ActionListener _deleteRangeAction = null;
113 private ActionListener _selectStartAction = null;
114 private ActionListener _selectEndAction = null;
116 // Toolbar buttons which need enabling/disabling
117 private JButton _saveButton = null;
118 private JButton _undoButton = null;
119 private JButton _editPointButton = null;
120 private JButton _deletePointButton = null;
121 private JButton _deleteRangeButton = null;
122 private JButton _selectStartButton = null;
123 private JButton _selectEndButton = null;
124 private JButton _connectButton = null;
126 /** Array of key events */
127 private static final int[] KEY_EVENTS = {
128 KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D, KeyEvent.VK_E,
129 KeyEvent.VK_F, KeyEvent.VK_G, KeyEvent.VK_H, KeyEvent.VK_I, KeyEvent.VK_J,
130 KeyEvent.VK_K, KeyEvent.VK_L, KeyEvent.VK_M, KeyEvent.VK_N, KeyEvent.VK_O,
131 KeyEvent.VK_P, KeyEvent.VK_Q, KeyEvent.VK_R, KeyEvent.VK_S, KeyEvent.VK_T,
132 KeyEvent.VK_U, KeyEvent.VK_V, KeyEvent.VK_W, KeyEvent.VK_X, KeyEvent.VK_Y, KeyEvent.VK_Z};
137 * @param inApp application to call on menu actions
138 * @param inTrackInfo track info object
140 public MenuManager(App inApp, TrackInfo inTrackInfo)
143 _track = inTrackInfo.getTrack();
144 _selection = inTrackInfo.getSelection();
149 * Create a JMenuBar containing all menu items
152 public JMenuBar createMenuBar()
154 JMenuBar menubar = new JMenuBar();
155 JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
156 setAltKey(fileMenu, "altkey.menu.file");
158 JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("function.open"));
159 setShortcut(openMenuItem, "shortcut.menu.file.open");
160 _openFileAction = new ActionListener() {
161 public void actionPerformed(ActionEvent e) {
165 openMenuItem.addActionListener(_openFileAction);
166 fileMenu.add(openMenuItem);
167 // import through gpsbabel
168 JMenuItem importBabelItem = makeMenuItem(FunctionLibrary.FUNCTION_IMPORTBABEL);
169 fileMenu.add(importBabelItem);
171 JMenuItem addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
172 _addPhotoAction = new ActionListener() {
173 public void actionPerformed(ActionEvent e) {
177 addPhotosMenuItem.addActionListener(_addPhotoAction);
178 fileMenu.add(addPhotosMenuItem);
180 JMenuItem addAudioMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_LOAD_AUDIO);
181 fileMenu.add(addAudioMenuItem);
183 _recentFileMenu = new JMenu(I18nManager.getText("menu.file.recentfiles"));
184 _recentFileMenu.setEnabled(false);
185 fileMenu.add(_recentFileMenu);
186 fileMenu.addSeparator();
188 JMenuItem loadFromGpsMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSLOAD);
189 setShortcut(loadFromGpsMenuItem, "shortcut.menu.file.load");
190 fileMenu.add(loadFromGpsMenuItem);
192 _sendGpsItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSSAVE, false);
193 fileMenu.add(_sendGpsItem);
194 fileMenu.addSeparator();
196 _saveItem = new JMenuItem(I18nManager.getText("menu.file.save"), KeyEvent.VK_S);
197 setShortcut(_saveItem, "shortcut.menu.file.save");
198 _saveAction = new ActionListener() {
199 public void actionPerformed(ActionEvent e) {
203 _saveItem.addActionListener(_saveAction);
204 _saveItem.setEnabled(false);
205 fileMenu.add(_saveItem);
207 _exportKmlItem = makeMenuItem(FunctionLibrary.FUNCTION_KMLEXPORT, false);
208 fileMenu.add(_exportKmlItem);
210 _exportGpxItem = makeMenuItem(FunctionLibrary.FUNCTION_GPXEXPORT, false);
211 fileMenu.add(_exportGpxItem);
213 _exportPovItem = makeMenuItem(FunctionLibrary.FUNCTION_POVEXPORT, false);
214 fileMenu.add(_exportPovItem);
216 _exportSvgItem = makeMenuItem(FunctionLibrary.FUNCTION_SVGEXPORT, false);
217 fileMenu.add(_exportSvgItem);
218 fileMenu.addSeparator();
219 JMenuItem exitMenuItem = new JMenuItem(I18nManager.getText("menu.file.exit"));
220 exitMenuItem.addActionListener(new ActionListener() {
221 public void actionPerformed(ActionEvent e) {
225 fileMenu.add(exitMenuItem);
226 menubar.add(fileMenu);
229 JMenu trackMenu = new JMenu(I18nManager.getText("menu.track"));
230 setAltKey(trackMenu, "altkey.menu.track");
231 _undoItem = new JMenuItem(I18nManager.getText("menu.track.undo"));
232 setShortcut(_undoItem, "shortcut.menu.track.undo");
233 _undoAction = new ActionListener() {
234 public void actionPerformed(ActionEvent e) {
238 _undoItem.addActionListener(_undoAction);
239 _undoItem.setEnabled(false);
240 trackMenu.add(_undoItem);
241 _clearUndoItem = new JMenuItem(I18nManager.getText("menu.track.clearundo"));
242 _clearUndoItem.addActionListener(new ActionListener() {
243 public void actionPerformed(ActionEvent e) {
247 _clearUndoItem.setEnabled(false);
248 trackMenu.add(_clearUndoItem);
249 trackMenu.addSeparator();
250 _compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS, false);
251 setShortcut(_compressItem, "shortcut.menu.edit.compress");
252 trackMenu.add(_compressItem);
253 _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
254 _deleteMarkedPointsItem.addActionListener(new ActionListener() {
255 public void actionPerformed(ActionEvent e) {
256 _app.finishCompressTrack();
259 _deleteMarkedPointsItem.setEnabled(false);
260 trackMenu.add(_deleteMarkedPointsItem);
261 trackMenu.addSeparator();
262 // Rearrange waypoints
263 _rearrangeMenu = new JMenu(I18nManager.getText("menu.track.rearrange"));
264 _rearrangeMenu.setEnabled(false);
265 JMenuItem rearrangeStartItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.start"));
266 rearrangeStartItem.addActionListener(new ActionListener() {
267 public void actionPerformed(ActionEvent e) {
268 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_START);
271 rearrangeStartItem.setEnabled(true);
272 _rearrangeMenu.add(rearrangeStartItem);
273 JMenuItem rearrangeEndItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.end"));
274 rearrangeEndItem.addActionListener(new ActionListener() {
275 public void actionPerformed(ActionEvent e) {
276 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_END);
279 rearrangeEndItem.setEnabled(true);
280 _rearrangeMenu.add(rearrangeEndItem);
281 JMenuItem rearrangeNearestItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.nearest"));
282 rearrangeNearestItem.addActionListener(new ActionListener() {
283 public void actionPerformed(ActionEvent e) {
284 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_NEAREST);
287 rearrangeNearestItem.setEnabled(true);
288 _rearrangeMenu.add(rearrangeNearestItem);
289 trackMenu.add(_rearrangeMenu);
291 _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES, false);
292 trackMenu.add(_getGpsiesItem);
294 _uploadGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_UPLOAD_GPSIES, false);
295 trackMenu.add(_uploadGpsiesItem);
296 _lookupSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_SRTM, false);
297 trackMenu.add(_lookupSrtmItem);
298 _lookupWikipediaItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_WIKIPEDIA, false);
299 trackMenu.add(_lookupWikipediaItem);
300 JMenuItem searchWikipediaNamesItem = makeMenuItem(FunctionLibrary.FUNCTION_SEARCH_WIKIPEDIA);
301 trackMenu.add(searchWikipediaNamesItem);
302 _downloadOsmItem = makeMenuItem(FunctionLibrary.FUNCTION_DOWNLOAD_OSM, false);
303 trackMenu.add(_downloadOsmItem);
304 menubar.add(trackMenu);
307 JMenu rangeMenu = new JMenu(I18nManager.getText("menu.range"));
308 setAltKey(rangeMenu, "altkey.menu.range");
309 _selectAllItem = new JMenuItem(I18nManager.getText("menu.range.all"));
310 setShortcut(_selectAllItem, "shortcut.menu.range.all");
311 _selectAllItem.setEnabled(false);
312 _selectAllItem.addActionListener(new ActionListener() {
313 public void actionPerformed(ActionEvent e) {
314 _selection.selectRange(0, _track.getNumPoints()-1);
317 rangeMenu.add(_selectAllItem);
318 _selectNoneItem = new JMenuItem(I18nManager.getText("menu.range.none"));
319 _selectNoneItem.setEnabled(false);
320 _selectNoneItem.addActionListener(new ActionListener() {
321 public void actionPerformed(ActionEvent e) {
325 rangeMenu.add(_selectNoneItem);
326 rangeMenu.addSeparator();
327 _selectStartItem = new JMenuItem(I18nManager.getText("menu.range.start"));
328 _selectStartItem.setEnabled(false);
329 _selectStartAction = new ActionListener() {
330 public void actionPerformed(ActionEvent e) {
331 _selection.selectRangeStart();
334 _selectStartItem.addActionListener(_selectStartAction);
335 rangeMenu.add(_selectStartItem);
336 _selectEndItem = new JMenuItem(I18nManager.getText("menu.range.end"));
337 _selectEndItem.setEnabled(false);
338 _selectEndAction = new ActionListener() {
339 public void actionPerformed(ActionEvent e) {
340 _selection.selectRangeEnd();
343 _selectEndItem.addActionListener(_selectEndAction);
344 rangeMenu.add(_selectEndItem);
345 rangeMenu.addSeparator();
346 _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.range.deleterange"));
347 _deleteRangeAction = new ActionListener() {
348 public void actionPerformed(ActionEvent e) {
349 _app.deleteSelectedRange();
352 _deleteRangeItem.addActionListener(_deleteRangeAction);
353 _deleteRangeItem.setEnabled(false);
354 rangeMenu.add(_deleteRangeItem);
355 _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
356 _reverseItem.addActionListener(new ActionListener() {
357 public void actionPerformed(ActionEvent e) {
361 _reverseItem.setEnabled(false);
362 rangeMenu.add(_reverseItem);
363 _addTimeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_TIME_OFFSET, false);
364 rangeMenu.add(_addTimeOffsetItem);
365 _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET, false);
366 rangeMenu.add(_addAltitudeOffsetItem);
367 _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.range.mergetracksegments"));
368 _mergeSegmentsItem.addActionListener(new ActionListener() {
369 public void actionPerformed(ActionEvent e) {
370 _app.mergeTrackSegments();
373 _mergeSegmentsItem.setEnabled(false);
374 rangeMenu.add(_mergeSegmentsItem);
375 _deleteFieldValuesItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_FIELD_VALUES, false);
376 rangeMenu.add(_deleteFieldValuesItem);
377 rangeMenu.addSeparator();
378 _interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
379 _interpolateItem.addActionListener(new ActionListener() {
380 public void actionPerformed(ActionEvent e) {
381 _app.interpolateSelection();
384 _interpolateItem.setEnabled(false);
385 rangeMenu.add(_interpolateItem);
386 _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
387 _averageItem.addActionListener(new ActionListener() {
388 public void actionPerformed(ActionEvent e) {
389 _app.averageSelection();
392 _averageItem.setEnabled(false);
393 rangeMenu.add(_averageItem);
394 _cutAndMoveItem = new JMenuItem(I18nManager.getText("menu.range.cutandmove"));
395 _cutAndMoveItem.addActionListener(new ActionListener() {
396 public void actionPerformed(ActionEvent e)
398 _app.cutAndMoveSelection();
401 _cutAndMoveItem.setEnabled(false);
402 rangeMenu.add(_cutAndMoveItem);
403 _convertNamesToTimesItem = makeMenuItem(FunctionLibrary.FUNCTION_CONVERT_NAMES_TO_TIMES, false);
404 rangeMenu.add(_convertNamesToTimesItem);
405 menubar.add(rangeMenu);
408 JMenu pointMenu = new JMenu(I18nManager.getText("menu.point"));
409 setAltKey(pointMenu, "altkey.menu.point");
410 _editPointItem = new JMenuItem(I18nManager.getText("menu.point.editpoint"));
411 _editPointAction = new ActionListener() {
412 public void actionPerformed(ActionEvent e) {
413 _app.editCurrentPoint();
416 _editPointItem.addActionListener(_editPointAction);
417 _editPointItem.setEnabled(false);
418 pointMenu.add(_editPointItem);
419 _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME, false);
420 pointMenu.add(_editWaypointNameItem);
421 _deletePointItem = new JMenuItem(I18nManager.getText("menu.point.deletepoint"));
422 _deletePointAction = new ActionListener() {
423 public void actionPerformed(ActionEvent e) {
424 _app.deleteCurrentPoint();
427 _deletePointItem.addActionListener(_deletePointAction);
428 _deletePointItem.setEnabled(false);
429 _deletePointItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
430 pointMenu.add(_deletePointItem);
431 pointMenu.addSeparator();
433 _findWaypointItem = makeMenuItem(FunctionLibrary.FUNCTION_FIND_WAYPOINT, false);
434 pointMenu.add(_findWaypointItem);
435 // duplicate current point
436 _duplicatePointItem = makeMenuItem(FunctionLibrary.FUNCTION_DUPLICATE_POINT, false);
437 pointMenu.add(_duplicatePointItem);
438 // paste coordinates function
439 JMenuItem pasteCoordsItem = makeMenuItem(FunctionLibrary.FUNCTION_PASTE_COORDINATES);
440 pointMenu.add(pasteCoordsItem);
441 menubar.add(pointMenu);
444 JMenu viewMenu = new JMenu(I18nManager.getText("menu.view"));
445 setAltKey(viewMenu, "altkey.menu.view");
446 // Turn map display on/off
447 _mapCheckbox = new JCheckBoxMenuItem(
448 I18nManager.getText("menu.map.showmap"), false);
449 _mapCheckbox.addActionListener(new ActionListener() {
450 public void actionPerformed(ActionEvent e) {
451 Config.setConfigBoolean(Config.KEY_SHOW_MAP, _mapCheckbox.isSelected());
452 UpdateMessageBroker.informSubscribers();
455 viewMenu.add(_mapCheckbox);
456 // Turn off the sidebars
457 JCheckBoxMenuItem sidebarsCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.view.showsidebars"));
458 sidebarsCheckbox.setSelected(true);
459 sidebarsCheckbox.addActionListener(new ActionListener() {
460 public void actionPerformed(ActionEvent e) {
461 _app.toggleSidebars();
464 sidebarsCheckbox.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0)); // shortcut F11
465 viewMenu.add(sidebarsCheckbox);
467 _show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D, false);
468 viewMenu.add(_show3dItem);
470 _browserMapMenu = new JMenu(I18nManager.getText("menu.view.browser"));
471 _browserMapMenu.setEnabled(false);
472 JMenuItem googleMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.google"));
473 googleMapsItem.addActionListener(new ActionListener() {
474 public void actionPerformed(ActionEvent e) {
475 _app.showExternalMap(UrlGenerator.MAP_SOURCE_GOOGLE);
478 _browserMapMenu.add(googleMapsItem);
479 JMenuItem openMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.openstreetmap"));
480 openMapsItem.addActionListener(new ActionListener() {
481 public void actionPerformed(ActionEvent e) {
482 _app.showExternalMap(UrlGenerator.MAP_SOURCE_OSM);
485 _browserMapMenu.add(openMapsItem);
486 JMenuItem mapquestMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.mapquest"));
487 mapquestMapsItem.addActionListener(new ActionListener() {
488 public void actionPerformed(ActionEvent e) {
489 _app.showExternalMap(UrlGenerator.MAP_SOURCE_MAPQUEST);
492 _browserMapMenu.add(mapquestMapsItem);
493 JMenuItem yahooMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.yahoo"));
494 yahooMapsItem.addActionListener(new ActionListener() {
495 public void actionPerformed(ActionEvent e) {
496 _app.showExternalMap(UrlGenerator.MAP_SOURCE_YAHOO);
499 _browserMapMenu.add(yahooMapsItem);
500 JMenuItem bingMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.bing"));
501 bingMapsItem.addActionListener(new ActionListener() {
502 public void actionPerformed(ActionEvent e) {
503 _app.showExternalMap(UrlGenerator.MAP_SOURCE_BING);
506 _browserMapMenu.add(bingMapsItem);
507 viewMenu.add(_browserMapMenu);
509 _chartItem = makeMenuItem(FunctionLibrary.FUNCTION_CHARTS, false);
510 viewMenu.add(_chartItem);
512 _distanceItem = makeMenuItem(FunctionLibrary.FUNCTION_DISTANCES, false);
513 viewMenu.add(_distanceItem);
514 // full range details
515 _fullRangeDetailsItem = makeMenuItem(FunctionLibrary.FUNCTION_FULL_RANGE_DETAILS, false);
516 viewMenu.add(_fullRangeDetailsItem);
517 menubar.add(viewMenu);
520 JMenu photoMenu = new JMenu(I18nManager.getText("menu.photo"));
521 setAltKey(photoMenu, "altkey.menu.photo");
522 addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
523 addPhotosMenuItem.addActionListener(_addPhotoAction);
524 photoMenu.add(addPhotosMenuItem);
525 _saveExifItem = new JMenuItem(I18nManager.getText("menu.photo.saveexif"));
526 _saveExifItem.addActionListener(new ActionListener() {
527 public void actionPerformed(ActionEvent e) {
531 _saveExifItem.setEnabled(false);
532 photoMenu.add(_saveExifItem);
533 // Deselect current photo
534 _selectNoPhotoItem = new JMenuItem(I18nManager.getText("menu.range.none"));
535 _selectNoPhotoItem.setEnabled(false);
536 _selectNoPhotoItem.addActionListener(new ActionListener() {
537 public void actionPerformed(ActionEvent e) {
538 _app.getTrackInfo().selectPhoto(-1);
541 photoMenu.add(_selectNoPhotoItem);
542 photoMenu.addSeparator();
543 _connectPhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_CONNECT_TO_POINT, false);
544 photoMenu.add(_connectPhotoItem);
546 _disconnectPhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_DISCONNECT_PHOTO, false);
547 photoMenu.add(_disconnectPhotoItem);
548 _removePhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_REMOVE_PHOTO, false);
549 photoMenu.add(_removePhotoItem);
550 // Rotate current photo
551 _rotatePhotoLeft = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_LEFT, false);
552 photoMenu.add(_rotatePhotoLeft);
553 _rotatePhotoRight = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_RIGHT, false);
554 photoMenu.add(_rotatePhotoRight);
556 _photoPopupItem = makeMenuItem(FunctionLibrary.FUNCTION_PHOTO_POPUP, false);
557 photoMenu.add(_photoPopupItem);
558 _ignoreExifThumb = makeMenuItem(FunctionLibrary.FUNCTION_IGNORE_EXIF_THUMB, false);
559 photoMenu.add(_ignoreExifThumb);
560 photoMenu.addSeparator();
561 // correlate all photos
562 _correlatePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_PHOTOS, false);
563 photoMenu.add(_correlatePhotosItem);
564 // rearrange photo points
565 _rearrangePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_REARRANGE_PHOTOS, false);
566 photoMenu.add(_rearrangePhotosItem);
567 menubar.add(photoMenu);
570 JMenu audioMenu = new JMenu(I18nManager.getText("menu.audio"));
571 setAltKey(audioMenu, "altkey.menu.audio");
572 addAudioMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_LOAD_AUDIO);
573 audioMenu.add(addAudioMenuItem);
574 _selectNoAudioItem = new JMenuItem(I18nManager.getText("menu.range.none"));
575 _selectNoAudioItem.setEnabled(false);
576 _selectNoAudioItem.addActionListener(new ActionListener() {
577 public void actionPerformed(ActionEvent e) {
578 _app.getTrackInfo().selectAudio(-1);
581 audioMenu.add(_selectNoAudioItem);
582 audioMenu.addSeparator();
584 _connectAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_CONNECT_TO_POINT, false);
585 audioMenu.add(_connectAudioItem);
586 // Disconnect current audio clip
587 _disconnectAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_DISCONNECT_AUDIO, false);
588 audioMenu.add(_disconnectAudioItem);
589 // Remove current audio clip
590 _removeAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_REMOVE_AUDIO, false);
591 audioMenu.add(_removeAudioItem);
592 audioMenu.addSeparator();
593 // Correlate audio clips
594 _correlateAudiosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_AUDIOS, false);
595 audioMenu.add(_correlateAudiosItem);
596 menubar.add(audioMenu);
599 JMenu settingsMenu = new JMenu(I18nManager.getText("menu.settings"));
600 setAltKey(settingsMenu, "altkey.menu.settings");
601 // Set the map background
602 JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
603 settingsMenu.add(mapBgItem);
604 _onlineCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.settings.onlinemode"));
605 _onlineCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ONLINE_MODE));
606 _onlineCheckbox.addActionListener(new ActionListener() {
607 public void actionPerformed(ActionEvent e) {
608 boolean isOnline = _onlineCheckbox.isSelected();
609 Config.setConfigBoolean(Config.KEY_ONLINE_MODE, isOnline);
610 if (isOnline) {UpdateMessageBroker.informSubscribers();}
613 settingsMenu.add(_onlineCheckbox);
614 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_DISK_CACHE));
615 settingsMenu.addSeparator();
616 // Set kmz image size
617 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE));
619 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS));
621 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS));
622 // Set line width used for drawing
623 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LINE_WIDTH));
625 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE));
626 settingsMenu.addSeparator();
627 // Save configuration
628 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG));
629 _autosaveSettingsCheckbox = new JCheckBoxMenuItem(
630 I18nManager.getText("menu.settings.autosave"), false);
631 _autosaveSettingsCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS));
632 _autosaveSettingsCheckbox.addActionListener(new ActionListener() {
633 public void actionPerformed(ActionEvent e) {
634 Config.setConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS, _autosaveSettingsCheckbox.isSelected());
637 settingsMenu.add(_autosaveSettingsCheckbox);
638 menubar.add(settingsMenu);
641 JMenu helpMenu = new JMenu(I18nManager.getText("menu.help"));
642 setAltKey(helpMenu, "altkey.menu.help");
643 JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
644 setShortcut(helpItem, "shortcut.menu.help.help");
645 helpMenu.add(helpItem);
646 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS));
647 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_ABOUT));
648 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION));
649 menubar.add(helpMenu);
655 * Convenience method for making a menu item using a function
656 * @param inFunction function
657 * @param inEnabled flag to specify initial enabled state
658 * @return menu item using localized name of function
660 private static JMenuItem makeMenuItem(GenericFunction inFunction, boolean inEnabled)
662 JMenuItem item = makeMenuItem(inFunction);
663 item.setEnabled(inEnabled);
668 * Convenience method for making a menu item using a function
669 * @param inFunction function
670 * @return menu item using localized name of function
672 private static JMenuItem makeMenuItem(GenericFunction inFunction)
674 JMenuItem item = new JMenuItem(I18nManager.getText(inFunction.getNameKey()));
675 item.addActionListener(new FunctionLauncher(inFunction));
680 * Set the alt key for the given menu
681 * @param inMenu menu to set
682 * @param inKey key to lookup to get language-sensitive altkey
684 private static void setAltKey(JMenu inMenu, String inKey)
686 // Lookup the key in the properties
687 String altKey = I18nManager.getText(inKey);
688 if (altKey != null && altKey.length() == 1)
690 int code = altKey.charAt(0) - 'A';
691 if (code >= 0 && code < 26)
693 // Found a valid code between A and Z
694 inMenu.setMnemonic(KEY_EVENTS[code]);
700 * Set the shortcut key for the given menu item
701 * @param inMenuItem menu item to set
702 * @param inKey key to lookup to get language-sensitive shortcut
704 private static void setShortcut(JMenuItem inMenuItem, String inKey)
706 // Lookup the key in the properties
707 String altKey = I18nManager.getText(inKey);
708 if (altKey != null && altKey.length() == 1)
710 int code = altKey.charAt(0) - 'A';
711 if (code >= 0 && code < 26)
713 // Found a valid code between A and Z
714 inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code],
715 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
716 // use platform-specific key mask so Ctrl on Linux/Win, Clover on Mac
722 * Create a JToolBar containing all toolbar buttons
723 * @return toolbar containing buttons
725 public JToolBar createToolBar()
727 JToolBar toolbar = new JToolBar();
729 JButton openFileButton = new JButton(IconManager.getImageIcon(IconManager.OPEN_FILE));
730 openFileButton.setToolTipText(I18nManager.getText("function.open"));
731 openFileButton.addActionListener(_openFileAction);
732 toolbar.add(openFileButton);
734 JButton addPhotoButton = new JButton(IconManager.getImageIcon(IconManager.ADD_PHOTO));
735 addPhotoButton.setToolTipText(I18nManager.getText("menu.file.addphotos"));
736 addPhotoButton.addActionListener(_addPhotoAction);
737 toolbar.add(addPhotoButton);
739 _saveButton = new JButton(IconManager.getImageIcon(IconManager.SAVE_FILE));
740 _saveButton.setToolTipText(I18nManager.getText("menu.file.save"));
741 _saveButton.addActionListener(_saveAction);
742 _saveButton.setEnabled(false);
743 toolbar.add(_saveButton);
745 _undoButton = new JButton(IconManager.getImageIcon(IconManager.UNDO));
746 _undoButton.setToolTipText(I18nManager.getText("menu.track.undo"));
747 _undoButton.addActionListener(_undoAction);
748 _undoButton.setEnabled(false);
749 toolbar.add(_undoButton);
751 _editPointButton = new JButton(IconManager.getImageIcon(IconManager.EDIT_POINT));
752 _editPointButton.setToolTipText(I18nManager.getText("menu.point.editpoint"));
753 _editPointButton.addActionListener(_editPointAction);
754 _editPointButton.setEnabled(false);
755 toolbar.add(_editPointButton);
757 _deletePointButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_POINT));
758 _deletePointButton.setToolTipText(I18nManager.getText("menu.point.deletepoint"));
759 _deletePointButton.addActionListener(_deletePointAction);
760 _deletePointButton.setEnabled(false);
761 toolbar.add(_deletePointButton);
763 _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
764 _deleteRangeButton.setToolTipText(I18nManager.getText("menu.range.deleterange"));
765 _deleteRangeButton.addActionListener(_deleteRangeAction);
766 _deleteRangeButton.setEnabled(false);
767 toolbar.add(_deleteRangeButton);
769 _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
770 _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
771 _selectStartButton.addActionListener(_selectStartAction);
772 _selectStartButton.setEnabled(false);
773 toolbar.add(_selectStartButton);
774 _selectEndButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_END));
775 _selectEndButton.setToolTipText(I18nManager.getText("menu.range.end"));
776 _selectEndButton.addActionListener(_selectEndAction);
777 _selectEndButton.setEnabled(false);
778 toolbar.add(_selectEndButton);
780 _connectButton = new JButton(IconManager.getImageIcon(IconManager.CONNECT_PHOTO));
781 _connectButton.setToolTipText(I18nManager.getText(FunctionLibrary.FUNCTION_CONNECT_TO_POINT.getNameKey()));
782 _connectButton.addActionListener(new ActionListener() {
783 public void actionPerformed(ActionEvent arg0) {
784 FunctionLibrary.FUNCTION_CONNECT_TO_POINT.begin();
787 _connectButton.setEnabled(false);
788 toolbar.add(_connectButton);
790 toolbar.setFloatable(false);
796 * Method to update menu when file loaded
798 public void informFileLoaded()
800 // save, undo, delete enabled
801 _sendGpsItem.setEnabled(true);
802 _saveItem.setEnabled(true);
803 _undoItem.setEnabled(true);
804 _compressItem.setEnabled(true);
805 _deleteMarkedPointsItem.setEnabled(false);
810 * @see tim.prune.DataSubscriber#dataUpdated(tim.prune.data.Track)
812 public void dataUpdated(byte inUpdateType)
814 boolean hasData = (_track != null && _track.getNumPoints() > 0);
815 // set functions which require data
816 _sendGpsItem.setEnabled(hasData);
817 _saveItem.setEnabled(hasData);
818 _saveButton.setEnabled(hasData);
819 _exportKmlItem.setEnabled(hasData);
820 _exportGpxItem.setEnabled(hasData);
821 _exportPovItem.setEnabled(hasData);
822 _exportSvgItem.setEnabled(hasData);
823 _compressItem.setEnabled(hasData);
824 _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
825 _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
826 _selectAllItem.setEnabled(hasData);
827 _selectNoneItem.setEnabled(hasData);
828 _show3dItem.setEnabled(hasData);
829 _chartItem.setEnabled(hasData);
830 _browserMapMenu.setEnabled(hasData);
831 _distanceItem.setEnabled(hasData);
832 _getGpsiesItem.setEnabled(hasData);
833 _uploadGpsiesItem.setEnabled(hasData && _track.hasTrackPoints());
834 _lookupSrtmItem.setEnabled(hasData);
835 _lookupWikipediaItem.setEnabled(hasData);
836 _downloadOsmItem.setEnabled(hasData);
837 _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
838 // is undo available?
839 boolean hasUndo = !_app.getUndoStack().isEmpty();
840 _undoItem.setEnabled(hasUndo);
841 _undoButton.setEnabled(hasUndo);
842 _clearUndoItem.setEnabled(hasUndo);
843 // is there a current point?
844 boolean hasPoint = (hasData && _selection.getCurrentPointIndex() >= 0);
845 _editPointItem.setEnabled(hasPoint);
846 _editPointButton.setEnabled(hasPoint);
847 _editWaypointNameItem.setEnabled(hasPoint);
848 _deletePointItem.setEnabled(hasPoint);
849 _deletePointButton.setEnabled(hasPoint);
850 _selectStartItem.setEnabled(hasPoint);
851 _selectStartButton.setEnabled(hasPoint);
852 _selectEndItem.setEnabled(hasPoint);
853 _selectEndButton.setEnabled(hasPoint);
854 _duplicatePointItem.setEnabled(hasPoint);
855 // are there any photos?
856 boolean anyPhotos = _app.getTrackInfo().getPhotoList().getNumPhotos() > 0;
857 _saveExifItem.setEnabled(anyPhotos && _app.getTrackInfo().getPhotoList().hasMediaWithFile());
858 // is there a current photo, audio?
859 Photo currentPhoto = _app.getTrackInfo().getCurrentPhoto();
860 boolean hasPhoto = currentPhoto != null;
861 AudioClip currentAudio = _app.getTrackInfo().getCurrentAudio();
862 boolean hasAudio = currentAudio != null;
863 // connect is available if (photo/audio) and point selected, and media has no point
864 boolean connectAvailable = (hasPhoto && hasPoint && currentPhoto.getDataPoint() == null)
865 || (hasAudio && hasPoint && currentAudio.getDataPoint() == null);
866 _connectPhotoItem.setEnabled(hasPhoto && hasPoint && currentPhoto.getDataPoint() == null);
867 _connectButton.setEnabled(connectAvailable);
868 _disconnectPhotoItem.setEnabled(hasPhoto && currentPhoto.getDataPoint() != null);
869 _correlatePhotosItem.setEnabled(anyPhotos && hasData);
870 _rearrangePhotosItem.setEnabled(anyPhotos && hasData && _track.getNumPoints() > 1);
871 _removePhotoItem.setEnabled(hasPhoto);
872 _rotatePhotoLeft.setEnabled(hasPhoto);
873 _rotatePhotoRight.setEnabled(hasPhoto);
874 _photoPopupItem.setEnabled(hasPhoto);
875 _ignoreExifThumb.setEnabled(hasPhoto && currentPhoto.getExifThumbnail() != null);
876 _selectNoPhotoItem.setEnabled(hasPhoto);
877 boolean anyAudios = _app.getTrackInfo().getAudioList().getNumAudios() > 0;
878 _selectNoAudioItem.setEnabled(hasAudio);
879 _removeAudioItem.setEnabled(hasAudio);
880 _connectAudioItem.setEnabled(hasAudio && hasPoint && currentAudio.getDataPoint() == null);
881 _disconnectAudioItem.setEnabled(hasAudio && _app.getTrackInfo().getCurrentAudio().getDataPoint() != null);
882 _correlateAudiosItem.setEnabled(anyAudios && hasData);
883 // is there a current range?
884 boolean hasRange = (hasData && _selection.hasRangeSelected());
885 _deleteRangeItem.setEnabled(hasRange);
886 _deleteRangeButton.setEnabled(hasRange);
887 _interpolateItem.setEnabled(hasRange
888 && (_selection.getEnd() - _selection.getStart()) == 1);
889 _averageItem.setEnabled(hasRange);
890 _mergeSegmentsItem.setEnabled(hasRange);
891 _reverseItem.setEnabled(hasRange);
892 _addTimeOffsetItem.setEnabled(hasRange);
893 _addAltitudeOffsetItem.setEnabled(hasRange);
894 _convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
895 _deleteFieldValuesItem.setEnabled(hasRange);
896 _fullRangeDetailsItem.setEnabled(hasRange);
897 // Is the currently selected point outside the current range?
898 _cutAndMoveItem.setEnabled(hasRange && hasPoint &&
899 (_selection.getCurrentPointIndex() < _selection.getStart()
900 || _selection.getCurrentPointIndex() > (_selection.getEnd()+1)));
901 // Has the map been switched on/off?
902 boolean mapsOn = Config.getConfigBoolean(Config.KEY_SHOW_MAP);
903 if (_mapCheckbox.isSelected() != mapsOn) {
904 _mapCheckbox.setSelected(mapsOn);
906 // Are there any recently-used files?
907 RecentFileList rfl = Config.getRecentFileList();
908 final int numRecentFiles = rfl.getNumEntries();
909 final boolean hasRecentFiles = numRecentFiles > 0;
910 _recentFileMenu.setEnabled(hasRecentFiles);
913 int numItems = _recentFileMenu.getMenuComponentCount();
914 if (numItems == numRecentFiles)
916 // Right number of items, just change texts
917 for (int i=0; i<numRecentFiles; i++)
919 JMenuItem item = _recentFileMenu.getItem(i);
920 item.setText(rfl.getFile(i)==null?"":rfl.getFile(i).getFile().getName());
921 item.setToolTipText(rfl.getFile(i)==null?null:rfl.getFile(i).getFile().getAbsolutePath());
927 _recentFileMenu.removeAll();
928 for (int i=0; i<rfl.getSize(); i++)
930 RecentFile rf = rfl.getFile(i);
931 if (rf != null && rf.isValid())
933 JMenuItem menuItem = new JMenuItem(rf.getFile().getName());
934 menuItem.setToolTipText(rf.getFile().getAbsolutePath());
935 menuItem.addActionListener(new RecentFileTrigger(_app, i));
936 _recentFileMenu.add(menuItem);
945 * Ignore action completed signals
946 * @see tim.prune.DataSubscriber#actionCompleted(java.lang.String)
948 public void actionCompleted(String inMessage)