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.AudioFile;
24 import tim.prune.data.Photo;
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;
32 * Class to manage the menu bar and tool bar,
33 * including enabling and disabling the items
35 public class MenuManager implements DataSubscriber
37 private App _app = null;
38 private Track _track = null;
39 private Selection _selection = null;
41 // Menu items which need enabling/disabling
42 private JMenuItem _sendGpsItem = null;
43 private JMenuItem _saveItem = null;
44 private JMenuItem _exportKmlItem = null;
45 private JMenuItem _exportGpxItem = null;
46 private JMenuItem _exportPovItem = null;
47 private JMenuItem _exportSvgItem = 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 JMenuItem _deleteFieldValuesItem = null;
72 private JCheckBoxMenuItem _mapCheckbox = null;
73 private JMenuItem _show3dItem = null;
74 private JMenu _browserMapMenu = null;
75 private JMenuItem _chartItem = null;
76 private JMenuItem _getGpsiesItem = null;
77 private JMenuItem _uploadGpsiesItem = null;
78 private JMenuItem _lookupSrtmItem = null;
79 private JMenuItem _lookupWikipediaItem = null;
80 private JMenuItem _downloadOsmItem = null;
81 private JMenuItem _distanceItem = null;
82 private JMenuItem _fullRangeDetailsItem = null;
83 private JMenuItem _saveExifItem = null;
84 private JMenuItem _photoPopupItem = null;
85 private JMenuItem _selectNoPhotoItem = null;
86 private JMenuItem _connectPhotoItem = null;
87 private JMenuItem _removePhotoItem = null;
88 private JMenuItem _disconnectPhotoItem = null;
89 private JMenuItem _correlatePhotosItem = null;
90 private JMenuItem _rearrangePhotosItem = null;
91 private JMenuItem _rotatePhotoLeft = null;
92 private JMenuItem _rotatePhotoRight = null;
93 private JMenuItem _ignoreExifThumb = null;
94 private JMenuItem _connectAudioItem = null;
95 private JMenuItem _disconnectAudioItem = null;
96 private JMenuItem _removeAudioItem = null;
97 private JMenuItem _correlateAudiosItem = null;
98 private JMenuItem _selectNoAudioItem = null;
99 private JCheckBoxMenuItem _onlineCheckbox = null;
101 // ActionListeners for reuse by menu and toolbar
102 private ActionListener _openFileAction = null;
103 private ActionListener _addPhotoAction = null;
104 private ActionListener _saveAction = null;
105 private ActionListener _undoAction = null;
106 private ActionListener _editPointAction = null;
107 private ActionListener _deletePointAction = null;
108 private ActionListener _deleteRangeAction = null;
109 private ActionListener _selectStartAction = null;
110 private ActionListener _selectEndAction = null;
112 // Toolbar buttons which need enabling/disabling
113 private JButton _saveButton = null;
114 private JButton _undoButton = null;
115 private JButton _editPointButton = null;
116 private JButton _deletePointButton = null;
117 private JButton _deleteRangeButton = null;
118 private JButton _selectStartButton = null;
119 private JButton _selectEndButton = null;
120 private JButton _connectButton = null;
122 /** Array of key events */
123 private static final int[] KEY_EVENTS = {
124 KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D, KeyEvent.VK_E,
125 KeyEvent.VK_F, KeyEvent.VK_G, KeyEvent.VK_H, KeyEvent.VK_I, KeyEvent.VK_J,
126 KeyEvent.VK_K, KeyEvent.VK_L, KeyEvent.VK_M, KeyEvent.VK_N, KeyEvent.VK_O,
127 KeyEvent.VK_P, KeyEvent.VK_Q, KeyEvent.VK_R, KeyEvent.VK_S, KeyEvent.VK_T,
128 KeyEvent.VK_U, KeyEvent.VK_V, KeyEvent.VK_W, KeyEvent.VK_X, KeyEvent.VK_Y, KeyEvent.VK_Z};
133 * @param inApp application to call on menu actions
134 * @param inTrackInfo track info object
136 public MenuManager(App inApp, TrackInfo inTrackInfo)
139 _track = inTrackInfo.getTrack();
140 _selection = inTrackInfo.getSelection();
145 * Create a JMenuBar containing all menu items
148 public JMenuBar createMenuBar()
150 JMenuBar menubar = new JMenuBar();
151 JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
152 setAltKey(fileMenu, "altkey.menu.file");
154 JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("function.open"));
155 setShortcut(openMenuItem, "shortcut.menu.file.open");
156 _openFileAction = new ActionListener() {
157 public void actionPerformed(ActionEvent e) {
161 openMenuItem.addActionListener(_openFileAction);
162 fileMenu.add(openMenuItem);
164 JMenuItem addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
165 _addPhotoAction = new ActionListener() {
166 public void actionPerformed(ActionEvent e) {
170 addPhotosMenuItem.addActionListener(_addPhotoAction);
171 fileMenu.add(addPhotosMenuItem);
173 JMenuItem addAudioMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_LOAD_AUDIO);
174 fileMenu.add(addAudioMenuItem);
175 fileMenu.addSeparator();
177 JMenuItem loadFromGpsMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSLOAD);
178 setShortcut(loadFromGpsMenuItem, "shortcut.menu.file.load");
179 fileMenu.add(loadFromGpsMenuItem);
181 _sendGpsItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSSAVE, false);
182 fileMenu.add(_sendGpsItem);
183 fileMenu.addSeparator();
185 _saveItem = new JMenuItem(I18nManager.getText("menu.file.save"), KeyEvent.VK_S);
186 setShortcut(_saveItem, "shortcut.menu.file.save");
187 _saveAction = new ActionListener() {
188 public void actionPerformed(ActionEvent e) {
192 _saveItem.addActionListener(_saveAction);
193 _saveItem.setEnabled(false);
194 fileMenu.add(_saveItem);
196 _exportKmlItem = makeMenuItem(FunctionLibrary.FUNCTION_KMLEXPORT, false);
197 fileMenu.add(_exportKmlItem);
199 _exportGpxItem = makeMenuItem(FunctionLibrary.FUNCTION_GPXEXPORT, false);
200 fileMenu.add(_exportGpxItem);
202 _exportPovItem = makeMenuItem(FunctionLibrary.FUNCTION_POVEXPORT, false);
203 fileMenu.add(_exportPovItem);
205 _exportSvgItem = makeMenuItem(FunctionLibrary.FUNCTION_SVGEXPORT, false);
206 fileMenu.add(_exportSvgItem);
207 fileMenu.addSeparator();
208 JMenuItem exitMenuItem = new JMenuItem(I18nManager.getText("menu.file.exit"));
209 exitMenuItem.addActionListener(new ActionListener() {
210 public void actionPerformed(ActionEvent e) {
214 fileMenu.add(exitMenuItem);
215 menubar.add(fileMenu);
217 JMenu trackMenu = new JMenu(I18nManager.getText("menu.track"));
218 setAltKey(trackMenu, "altkey.menu.track");
219 _undoItem = new JMenuItem(I18nManager.getText("menu.track.undo"));
220 setShortcut(_undoItem, "shortcut.menu.track.undo");
221 _undoAction = new ActionListener() {
222 public void actionPerformed(ActionEvent e) {
226 _undoItem.addActionListener(_undoAction);
227 _undoItem.setEnabled(false);
228 trackMenu.add(_undoItem);
229 _clearUndoItem = new JMenuItem(I18nManager.getText("menu.track.clearundo"));
230 _clearUndoItem.addActionListener(new ActionListener() {
231 public void actionPerformed(ActionEvent e) {
235 _clearUndoItem.setEnabled(false);
236 trackMenu.add(_clearUndoItem);
237 trackMenu.addSeparator();
238 _compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS, false);
239 setShortcut(_compressItem, "shortcut.menu.edit.compress");
240 trackMenu.add(_compressItem);
241 _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
242 _deleteMarkedPointsItem.addActionListener(new ActionListener() {
243 public void actionPerformed(ActionEvent e) {
244 _app.finishCompressTrack();
247 _deleteMarkedPointsItem.setEnabled(false);
248 trackMenu.add(_deleteMarkedPointsItem);
249 trackMenu.addSeparator();
250 // Rearrange waypoints
251 _rearrangeMenu = new JMenu(I18nManager.getText("menu.track.rearrange"));
252 _rearrangeMenu.setEnabled(false);
253 JMenuItem rearrangeStartItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.start"));
254 rearrangeStartItem.addActionListener(new ActionListener() {
255 public void actionPerformed(ActionEvent e) {
256 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_START);
259 rearrangeStartItem.setEnabled(true);
260 _rearrangeMenu.add(rearrangeStartItem);
261 JMenuItem rearrangeEndItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.end"));
262 rearrangeEndItem.addActionListener(new ActionListener() {
263 public void actionPerformed(ActionEvent e) {
264 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_END);
267 rearrangeEndItem.setEnabled(true);
268 _rearrangeMenu.add(rearrangeEndItem);
269 JMenuItem rearrangeNearestItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.nearest"));
270 rearrangeNearestItem.addActionListener(new ActionListener() {
271 public void actionPerformed(ActionEvent e) {
272 FunctionLibrary.FUNCTION_REARRANGE_WAYPOINTS.rearrangeWaypoints(Rearrange.TO_NEAREST);
275 rearrangeNearestItem.setEnabled(true);
276 _rearrangeMenu.add(rearrangeNearestItem);
277 trackMenu.add(_rearrangeMenu);
279 _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES, false);
280 trackMenu.add(_getGpsiesItem);
282 _uploadGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_UPLOAD_GPSIES, false);
283 trackMenu.add(_uploadGpsiesItem);
284 _lookupSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_SRTM, false);
285 trackMenu.add(_lookupSrtmItem);
286 _lookupWikipediaItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_WIKIPEDIA, false);
287 trackMenu.add(_lookupWikipediaItem);
288 JMenuItem searchWikipediaNamesItem = makeMenuItem(FunctionLibrary.FUNCTION_SEARCH_WIKIPEDIA);
289 trackMenu.add(searchWikipediaNamesItem);
290 _downloadOsmItem = makeMenuItem(FunctionLibrary.FUNCTION_DOWNLOAD_OSM, false);
291 trackMenu.add(_downloadOsmItem);
292 menubar.add(trackMenu);
295 JMenu rangeMenu = new JMenu(I18nManager.getText("menu.range"));
296 setAltKey(rangeMenu, "altkey.menu.range");
297 _selectAllItem = new JMenuItem(I18nManager.getText("menu.range.all"));
298 setShortcut(_selectAllItem, "shortcut.menu.range.all");
299 _selectAllItem.setEnabled(false);
300 _selectAllItem.addActionListener(new ActionListener() {
301 public void actionPerformed(ActionEvent e) {
302 _selection.selectRange(0, _track.getNumPoints()-1);
305 rangeMenu.add(_selectAllItem);
306 _selectNoneItem = new JMenuItem(I18nManager.getText("menu.range.none"));
307 _selectNoneItem.setEnabled(false);
308 _selectNoneItem.addActionListener(new ActionListener() {
309 public void actionPerformed(ActionEvent e) {
313 rangeMenu.add(_selectNoneItem);
314 rangeMenu.addSeparator();
315 _selectStartItem = new JMenuItem(I18nManager.getText("menu.range.start"));
316 _selectStartItem.setEnabled(false);
317 _selectStartAction = new ActionListener() {
318 public void actionPerformed(ActionEvent e) {
319 _selection.selectRangeStart();
322 _selectStartItem.addActionListener(_selectStartAction);
323 rangeMenu.add(_selectStartItem);
324 _selectEndItem = new JMenuItem(I18nManager.getText("menu.range.end"));
325 _selectEndItem.setEnabled(false);
326 _selectEndAction = new ActionListener() {
327 public void actionPerformed(ActionEvent e) {
328 _selection.selectRangeEnd();
331 _selectEndItem.addActionListener(_selectEndAction);
332 rangeMenu.add(_selectEndItem);
333 rangeMenu.addSeparator();
334 _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.range.deleterange"));
335 _deleteRangeAction = new ActionListener() {
336 public void actionPerformed(ActionEvent e) {
337 _app.deleteSelectedRange();
340 _deleteRangeItem.addActionListener(_deleteRangeAction);
341 _deleteRangeItem.setEnabled(false);
342 rangeMenu.add(_deleteRangeItem);
343 _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
344 _reverseItem.addActionListener(new ActionListener() {
345 public void actionPerformed(ActionEvent e) {
349 _reverseItem.setEnabled(false);
350 rangeMenu.add(_reverseItem);
351 _addTimeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_TIME_OFFSET, false);
352 rangeMenu.add(_addTimeOffsetItem);
353 _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET, false);
354 rangeMenu.add(_addAltitudeOffsetItem);
355 _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.range.mergetracksegments"));
356 _mergeSegmentsItem.addActionListener(new ActionListener() {
357 public void actionPerformed(ActionEvent e) {
358 _app.mergeTrackSegments();
361 _mergeSegmentsItem.setEnabled(false);
362 rangeMenu.add(_mergeSegmentsItem);
363 _deleteFieldValuesItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_FIELD_VALUES, false);
364 rangeMenu.add(_deleteFieldValuesItem);
365 rangeMenu.addSeparator();
366 _interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
367 _interpolateItem.addActionListener(new ActionListener() {
368 public void actionPerformed(ActionEvent e) {
369 _app.interpolateSelection();
372 _interpolateItem.setEnabled(false);
373 rangeMenu.add(_interpolateItem);
374 _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
375 _averageItem.addActionListener(new ActionListener() {
376 public void actionPerformed(ActionEvent e) {
377 _app.averageSelection();
380 _averageItem.setEnabled(false);
381 rangeMenu.add(_averageItem);
382 _cutAndMoveItem = new JMenuItem(I18nManager.getText("menu.range.cutandmove"));
383 _cutAndMoveItem.addActionListener(new ActionListener() {
384 public void actionPerformed(ActionEvent e)
386 _app.cutAndMoveSelection();
389 _cutAndMoveItem.setEnabled(false);
390 rangeMenu.add(_cutAndMoveItem);
391 _convertNamesToTimesItem = makeMenuItem(FunctionLibrary.FUNCTION_CONVERT_NAMES_TO_TIMES, false);
392 rangeMenu.add(_convertNamesToTimesItem);
393 menubar.add(rangeMenu);
396 JMenu pointMenu = new JMenu(I18nManager.getText("menu.point"));
397 setAltKey(pointMenu, "altkey.menu.point");
398 _editPointItem = new JMenuItem(I18nManager.getText("menu.point.editpoint"));
399 _editPointAction = new ActionListener() {
400 public void actionPerformed(ActionEvent e) {
401 _app.editCurrentPoint();
404 _editPointItem.addActionListener(_editPointAction);
405 _editPointItem.setEnabled(false);
406 pointMenu.add(_editPointItem);
407 _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME, false);
408 pointMenu.add(_editWaypointNameItem);
409 _deletePointItem = new JMenuItem(I18nManager.getText("menu.point.deletepoint"));
410 _deletePointAction = new ActionListener() {
411 public void actionPerformed(ActionEvent e) {
412 _app.deleteCurrentPoint();
415 _deletePointItem.addActionListener(_deletePointAction);
416 _deletePointItem.setEnabled(false);
417 _deletePointItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
418 pointMenu.add(_deletePointItem);
419 pointMenu.addSeparator();
421 _findWaypointItem = makeMenuItem(FunctionLibrary.FUNCTION_FIND_WAYPOINT, false);
422 pointMenu.add(_findWaypointItem);
423 // duplicate current point
424 _duplicatePointItem = makeMenuItem(FunctionLibrary.FUNCTION_DUPLICATE_POINT, false);
425 pointMenu.add(_duplicatePointItem);
426 // paste coordinates function
427 JMenuItem pasteCoordsItem = makeMenuItem(FunctionLibrary.FUNCTION_PASTE_COORDINATES);
428 pointMenu.add(pasteCoordsItem);
429 menubar.add(pointMenu);
432 JMenu viewMenu = new JMenu(I18nManager.getText("menu.view"));
433 setAltKey(viewMenu, "altkey.menu.view");
434 // Turn map display on/off
435 _mapCheckbox = new JCheckBoxMenuItem(
436 I18nManager.getText("menu.map.showmap"), false);
437 _mapCheckbox.addActionListener(new ActionListener() {
438 public void actionPerformed(ActionEvent e) {
439 Config.setConfigBoolean(Config.KEY_SHOW_MAP, _mapCheckbox.isSelected());
440 UpdateMessageBroker.informSubscribers();
443 viewMenu.add(_mapCheckbox);
444 // Turn off the sidebars
445 JCheckBoxMenuItem sidebarsCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.view.showsidebars"));
446 sidebarsCheckbox.setSelected(true);
447 sidebarsCheckbox.addActionListener(new ActionListener() {
448 public void actionPerformed(ActionEvent e) {
449 _app.toggleSidebars();
452 viewMenu.add(sidebarsCheckbox);
454 _show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D, false);
455 viewMenu.add(_show3dItem);
457 _browserMapMenu = new JMenu(I18nManager.getText("menu.view.browser"));
458 _browserMapMenu.setEnabled(false);
459 JMenuItem googleMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.google"));
460 googleMapsItem.addActionListener(new ActionListener() {
461 public void actionPerformed(ActionEvent e) {
462 _app.showExternalMap(UrlGenerator.MAP_SOURCE_GOOGLE);
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 _app.showExternalMap(UrlGenerator.MAP_SOURCE_OSM);
472 _browserMapMenu.add(openMapsItem);
473 JMenuItem mapquestMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.mapquest"));
474 mapquestMapsItem.addActionListener(new ActionListener() {
475 public void actionPerformed(ActionEvent e) {
476 _app.showExternalMap(UrlGenerator.MAP_SOURCE_MAPQUEST);
479 _browserMapMenu.add(mapquestMapsItem);
480 JMenuItem yahooMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.yahoo"));
481 yahooMapsItem.addActionListener(new ActionListener() {
482 public void actionPerformed(ActionEvent e) {
483 _app.showExternalMap(UrlGenerator.MAP_SOURCE_YAHOO);
486 _browserMapMenu.add(yahooMapsItem);
487 JMenuItem bingMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.bing"));
488 bingMapsItem.addActionListener(new ActionListener() {
489 public void actionPerformed(ActionEvent e) {
490 _app.showExternalMap(UrlGenerator.MAP_SOURCE_BING);
493 _browserMapMenu.add(bingMapsItem);
494 viewMenu.add(_browserMapMenu);
496 _chartItem = makeMenuItem(FunctionLibrary.FUNCTION_CHARTS, false);
497 viewMenu.add(_chartItem);
499 _distanceItem = makeMenuItem(FunctionLibrary.FUNCTION_DISTANCES, false);
500 viewMenu.add(_distanceItem);
501 // full range details
502 _fullRangeDetailsItem = makeMenuItem(FunctionLibrary.FUNCTION_FULL_RANGE_DETAILS, false);
503 viewMenu.add(_fullRangeDetailsItem);
504 menubar.add(viewMenu);
507 JMenu photoMenu = new JMenu(I18nManager.getText("menu.photo"));
508 setAltKey(photoMenu, "altkey.menu.photo");
509 addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
510 addPhotosMenuItem.addActionListener(_addPhotoAction);
511 photoMenu.add(addPhotosMenuItem);
512 _saveExifItem = new JMenuItem(I18nManager.getText("menu.photo.saveexif"));
513 _saveExifItem.addActionListener(new ActionListener() {
514 public void actionPerformed(ActionEvent e) {
518 _saveExifItem.setEnabled(false);
519 photoMenu.add(_saveExifItem);
520 // Deselect current photo
521 _selectNoPhotoItem = new JMenuItem(I18nManager.getText("menu.range.none"));
522 _selectNoPhotoItem.setEnabled(false);
523 _selectNoPhotoItem.addActionListener(new ActionListener() {
524 public void actionPerformed(ActionEvent e) {
525 _app.getTrackInfo().selectPhoto(-1);
528 photoMenu.add(_selectNoPhotoItem);
529 photoMenu.addSeparator();
530 _connectPhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_CONNECT_TO_POINT, false);
531 photoMenu.add(_connectPhotoItem);
533 _disconnectPhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_DISCONNECT_PHOTO, false);
534 photoMenu.add(_disconnectPhotoItem);
535 _removePhotoItem = makeMenuItem(FunctionLibrary.FUNCTION_REMOVE_PHOTO, false);
536 photoMenu.add(_removePhotoItem);
537 // Rotate current photo
538 _rotatePhotoLeft = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_LEFT, false);
539 photoMenu.add(_rotatePhotoLeft);
540 _rotatePhotoRight = makeMenuItem(FunctionLibrary.FUNCTION_ROTATE_PHOTO_RIGHT, false);
541 photoMenu.add(_rotatePhotoRight);
543 _photoPopupItem = makeMenuItem(FunctionLibrary.FUNCTION_PHOTO_POPUP, false);
544 photoMenu.add(_photoPopupItem);
545 _ignoreExifThumb = makeMenuItem(FunctionLibrary.FUNCTION_IGNORE_EXIF_THUMB, false);
546 photoMenu.add(_ignoreExifThumb);
547 photoMenu.addSeparator();
548 // correlate all photos
549 _correlatePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_PHOTOS, false);
550 photoMenu.add(_correlatePhotosItem);
551 // rearrange photo points
552 _rearrangePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_REARRANGE_PHOTOS, false);
553 photoMenu.add(_rearrangePhotosItem);
554 menubar.add(photoMenu);
557 JMenu audioMenu = new JMenu(I18nManager.getText("menu.audio"));
558 setAltKey(audioMenu, "altkey.menu.audio");
559 addAudioMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_LOAD_AUDIO);
560 audioMenu.add(addAudioMenuItem);
561 _selectNoAudioItem = new JMenuItem(I18nManager.getText("menu.range.none"));
562 _selectNoAudioItem.setEnabled(false);
563 _selectNoAudioItem.addActionListener(new ActionListener() {
564 public void actionPerformed(ActionEvent e) {
565 _app.getTrackInfo().selectAudio(-1);
568 audioMenu.add(_selectNoAudioItem);
569 audioMenu.addSeparator();
571 _connectAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_CONNECT_TO_POINT, false);
572 audioMenu.add(_connectAudioItem);
573 // Disconnect current audio file
574 _disconnectAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_DISCONNECT_AUDIO, false);
575 audioMenu.add(_disconnectAudioItem);
576 // Remove current audio file
577 _removeAudioItem = makeMenuItem(FunctionLibrary.FUNCTION_REMOVE_AUDIO, false);
578 audioMenu.add(_removeAudioItem);
579 audioMenu.addSeparator();
580 // Correlate audio files
581 _correlateAudiosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_AUDIOS, false);
582 audioMenu.add(_correlateAudiosItem);
583 menubar.add(audioMenu);
586 JMenu settingsMenu = new JMenu(I18nManager.getText("menu.settings"));
587 setAltKey(settingsMenu, "altkey.menu.settings");
588 // Set the map background
589 JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
590 settingsMenu.add(mapBgItem);
591 _onlineCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.settings.onlinemode"));
592 _onlineCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ONLINE_MODE));
593 _onlineCheckbox.addActionListener(new ActionListener() {
594 public void actionPerformed(ActionEvent e) {
595 boolean isOnline = _onlineCheckbox.isSelected();
596 Config.setConfigBoolean(Config.KEY_ONLINE_MODE, isOnline);
597 if (isOnline) {UpdateMessageBroker.informSubscribers();}
600 settingsMenu.add(_onlineCheckbox);
601 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_DISK_CACHE));
602 settingsMenu.addSeparator();
603 // Set kmz image size
604 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE));
606 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS));
608 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS));
609 // Set line width used for drawing
610 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LINE_WIDTH));
612 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE));
613 settingsMenu.addSeparator();
614 // Save configuration
615 settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG));
616 menubar.add(settingsMenu);
619 JMenu helpMenu = new JMenu(I18nManager.getText("menu.help"));
620 setAltKey(helpMenu, "altkey.menu.help");
621 JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
622 setShortcut(helpItem, "shortcut.menu.help.help");
623 helpMenu.add(helpItem);
624 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS));
625 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_ABOUT));
626 helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION));
627 menubar.add(helpMenu);
633 * Convenience method for making a menu item using a function
634 * @param inFunction function
635 * @param inEnabled flag to specify initial enabled state
636 * @return menu item using localized name of function
638 private static JMenuItem makeMenuItem(GenericFunction inFunction, boolean inEnabled)
640 JMenuItem item = makeMenuItem(inFunction);
641 item.setEnabled(inEnabled);
646 * Convenience method for making a menu item using a function
647 * @param inFunction function
648 * @return menu item using localized name of function
650 private static JMenuItem makeMenuItem(GenericFunction inFunction)
652 JMenuItem item = new JMenuItem(I18nManager.getText(inFunction.getNameKey()));
653 item.addActionListener(new FunctionLauncher(inFunction));
658 * Set the alt key for the given menu
659 * @param inMenu menu to set
660 * @param inKey key to lookup to get language-sensitive altkey
662 private static void setAltKey(JMenu inMenu, String inKey)
664 // Lookup the key in the properties
665 String altKey = I18nManager.getText(inKey);
666 if (altKey != null && altKey.length() == 1)
668 int code = altKey.charAt(0) - 'A';
669 if (code >= 0 && code < 26)
671 // Found a valid code between A and Z
672 inMenu.setMnemonic(KEY_EVENTS[code]);
678 * Set the shortcut key for the given menu item
679 * @param inMenuItem menu item to set
680 * @param inKey key to lookup to get language-sensitive shortcut
682 private static void setShortcut(JMenuItem inMenuItem, String inKey)
684 // Lookup the key in the properties
685 String altKey = I18nManager.getText(inKey);
686 if (altKey != null && altKey.length() == 1)
688 int code = altKey.charAt(0) - 'A';
689 if (code >= 0 && code < 26)
691 // Found a valid code between A and Z
692 inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code],
693 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
694 // use platform-specific key mask so Ctrl on Linux/Win, Clover on Mac
700 * Create a JToolBar containing all toolbar buttons
701 * @return toolbar containing buttons
703 public JToolBar createToolBar()
705 JToolBar toolbar = new JToolBar();
707 JButton openFileButton = new JButton(IconManager.getImageIcon(IconManager.OPEN_FILE));
708 openFileButton.setToolTipText(I18nManager.getText("function.open"));
709 openFileButton.addActionListener(_openFileAction);
710 toolbar.add(openFileButton);
712 JButton addPhotoButton = new JButton(IconManager.getImageIcon(IconManager.ADD_PHOTO));
713 addPhotoButton.setToolTipText(I18nManager.getText("menu.file.addphotos"));
714 addPhotoButton.addActionListener(_addPhotoAction);
715 toolbar.add(addPhotoButton);
717 _saveButton = new JButton(IconManager.getImageIcon(IconManager.SAVE_FILE));
718 _saveButton.setToolTipText(I18nManager.getText("menu.file.save"));
719 _saveButton.addActionListener(_saveAction);
720 _saveButton.setEnabled(false);
721 toolbar.add(_saveButton);
723 _undoButton = new JButton(IconManager.getImageIcon(IconManager.UNDO));
724 _undoButton.setToolTipText(I18nManager.getText("menu.track.undo"));
725 _undoButton.addActionListener(_undoAction);
726 _undoButton.setEnabled(false);
727 toolbar.add(_undoButton);
729 _editPointButton = new JButton(IconManager.getImageIcon(IconManager.EDIT_POINT));
730 _editPointButton.setToolTipText(I18nManager.getText("menu.point.editpoint"));
731 _editPointButton.addActionListener(_editPointAction);
732 _editPointButton.setEnabled(false);
733 toolbar.add(_editPointButton);
735 _deletePointButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_POINT));
736 _deletePointButton.setToolTipText(I18nManager.getText("menu.point.deletepoint"));
737 _deletePointButton.addActionListener(_deletePointAction);
738 _deletePointButton.setEnabled(false);
739 toolbar.add(_deletePointButton);
741 _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
742 _deleteRangeButton.setToolTipText(I18nManager.getText("menu.range.deleterange"));
743 _deleteRangeButton.addActionListener(_deleteRangeAction);
744 _deleteRangeButton.setEnabled(false);
745 toolbar.add(_deleteRangeButton);
747 _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
748 _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
749 _selectStartButton.addActionListener(_selectStartAction);
750 _selectStartButton.setEnabled(false);
751 toolbar.add(_selectStartButton);
752 _selectEndButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_END));
753 _selectEndButton.setToolTipText(I18nManager.getText("menu.range.end"));
754 _selectEndButton.addActionListener(_selectEndAction);
755 _selectEndButton.setEnabled(false);
756 toolbar.add(_selectEndButton);
758 _connectButton = new JButton(IconManager.getImageIcon(IconManager.CONNECT_PHOTO));
759 _connectButton.setToolTipText(I18nManager.getText(FunctionLibrary.FUNCTION_CONNECT_TO_POINT.getNameKey()));
760 _connectButton.addActionListener(new ActionListener() {
761 public void actionPerformed(ActionEvent arg0) {
762 FunctionLibrary.FUNCTION_CONNECT_TO_POINT.begin();
765 _connectButton.setEnabled(false);
766 toolbar.add(_connectButton);
768 toolbar.setFloatable(false);
774 * Method to update menu when file loaded
776 public void informFileLoaded()
778 // save, undo, delete enabled
779 _sendGpsItem.setEnabled(true);
780 _saveItem.setEnabled(true);
781 _undoItem.setEnabled(true);
782 _compressItem.setEnabled(true);
783 _deleteMarkedPointsItem.setEnabled(false);
788 * @see tim.prune.DataSubscriber#dataUpdated(tim.prune.data.Track)
790 public void dataUpdated(byte inUpdateType)
792 boolean hasData = (_track != null && _track.getNumPoints() > 0);
793 // set functions which require data
794 _sendGpsItem.setEnabled(hasData);
795 _saveItem.setEnabled(hasData);
796 _saveButton.setEnabled(hasData);
797 _exportKmlItem.setEnabled(hasData);
798 _exportGpxItem.setEnabled(hasData);
799 _exportPovItem.setEnabled(hasData);
800 _exportSvgItem.setEnabled(hasData);
801 _compressItem.setEnabled(hasData);
802 _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
803 _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
804 _selectAllItem.setEnabled(hasData);
805 _selectNoneItem.setEnabled(hasData);
806 _show3dItem.setEnabled(hasData);
807 _chartItem.setEnabled(hasData);
808 _browserMapMenu.setEnabled(hasData);
809 _distanceItem.setEnabled(hasData);
810 _getGpsiesItem.setEnabled(hasData);
811 _uploadGpsiesItem.setEnabled(hasData && _track.hasTrackPoints());
812 _lookupSrtmItem.setEnabled(hasData);
813 _lookupWikipediaItem.setEnabled(hasData);
814 _downloadOsmItem.setEnabled(hasData);
815 _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
816 // is undo available?
817 boolean hasUndo = !_app.getUndoStack().isEmpty();
818 _undoItem.setEnabled(hasUndo);
819 _undoButton.setEnabled(hasUndo);
820 _clearUndoItem.setEnabled(hasUndo);
821 // is there a current point?
822 boolean hasPoint = (hasData && _selection.getCurrentPointIndex() >= 0);
823 _editPointItem.setEnabled(hasPoint);
824 _editPointButton.setEnabled(hasPoint);
825 _editWaypointNameItem.setEnabled(hasPoint);
826 _deletePointItem.setEnabled(hasPoint);
827 _deletePointButton.setEnabled(hasPoint);
828 _selectStartItem.setEnabled(hasPoint);
829 _selectStartButton.setEnabled(hasPoint);
830 _selectEndItem.setEnabled(hasPoint);
831 _selectEndButton.setEnabled(hasPoint);
832 _duplicatePointItem.setEnabled(hasPoint);
833 // are there any photos?
834 boolean anyPhotos = _app.getTrackInfo().getPhotoList().getNumPhotos() > 0;
835 _saveExifItem.setEnabled(anyPhotos);
836 // is there a current photo, audio?
837 Photo currentPhoto = _app.getTrackInfo().getCurrentPhoto();
838 boolean hasPhoto = currentPhoto != null;
839 AudioFile currentAudio = _app.getTrackInfo().getCurrentAudio();
840 boolean hasAudio = currentAudio != null;
841 // connect is available if (photo/audio) and point selected, and media has no point
842 boolean connectAvailable = (hasPhoto && hasPoint && currentPhoto.getDataPoint() == null)
843 || (hasAudio && hasPoint && currentAudio.getDataPoint() == null);
844 _connectPhotoItem.setEnabled(hasPhoto && hasPoint && currentPhoto.getDataPoint() == null);
845 _connectButton.setEnabled(connectAvailable);
846 _disconnectPhotoItem.setEnabled(hasPhoto && currentPhoto.getDataPoint() != null);
847 _correlatePhotosItem.setEnabled(anyPhotos && hasData);
848 _rearrangePhotosItem.setEnabled(anyPhotos && hasData && _track.getNumPoints() > 1);
849 _removePhotoItem.setEnabled(hasPhoto);
850 _rotatePhotoLeft.setEnabled(hasPhoto);
851 _rotatePhotoRight.setEnabled(hasPhoto);
852 _photoPopupItem.setEnabled(hasPhoto);
853 _ignoreExifThumb.setEnabled(hasPhoto && currentPhoto.getExifThumbnail() != null);
854 _selectNoPhotoItem.setEnabled(hasPhoto);
855 boolean anyAudios = _app.getTrackInfo().getAudioList().getNumAudios() > 0;
856 _selectNoAudioItem.setEnabled(hasAudio);
857 _removeAudioItem.setEnabled(hasAudio);
858 _connectAudioItem.setEnabled(hasAudio && hasPoint && currentAudio.getDataPoint() == null);
859 _disconnectAudioItem.setEnabled(hasAudio && _app.getTrackInfo().getCurrentAudio().getDataPoint() != null);
860 _correlateAudiosItem.setEnabled(anyAudios && hasData);
861 // is there a current range?
862 boolean hasRange = (hasData && _selection.hasRangeSelected());
863 _deleteRangeItem.setEnabled(hasRange);
864 _deleteRangeButton.setEnabled(hasRange);
865 _interpolateItem.setEnabled(hasRange
866 && (_selection.getEnd() - _selection.getStart()) == 1);
867 _averageItem.setEnabled(hasRange);
868 _mergeSegmentsItem.setEnabled(hasRange);
869 _reverseItem.setEnabled(hasRange);
870 _addTimeOffsetItem.setEnabled(hasRange);
871 _addAltitudeOffsetItem.setEnabled(hasRange);
872 _convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
873 _deleteFieldValuesItem.setEnabled(hasRange);
874 _fullRangeDetailsItem.setEnabled(hasRange);
875 // Is the currently selected point outside the current range?
876 _cutAndMoveItem.setEnabled(hasRange && hasPoint &&
877 (_selection.getCurrentPointIndex() < _selection.getStart()
878 || _selection.getCurrentPointIndex() > (_selection.getEnd()+1)));
879 // Has the map been switched on/off?
880 boolean mapsOn = Config.getConfigBoolean(Config.KEY_SHOW_MAP);
881 if (_mapCheckbox.isSelected() != mapsOn) {
882 _mapCheckbox.setSelected(mapsOn);
888 * Ignore action completed signals
889 * @see tim.prune.DataSubscriber#actionCompleted(java.lang.String)
891 public void actionCompleted(String inMessage)