import javax.swing.JFrame;
import javax.swing.JOptionPane;
+import tim.prune.browser.BrowserLauncher;
+import tim.prune.browser.UrlGenerator;
import tim.prune.correlate.PhotoCorrelator;
import tim.prune.correlate.PointPair;
import tim.prune.data.DataPoint;
import tim.prune.edit.PointNameEditor;
import tim.prune.gui.MenuManager;
import tim.prune.gui.UndoManager;
+import tim.prune.gui.map.MapWindow;
import tim.prune.load.FileLoader;
import tim.prune.load.JpegLoader;
import tim.prune.save.ExifSaver;
import tim.prune.undo.UndoInsert;
import tim.prune.undo.UndoLoad;
import tim.prune.undo.UndoLoadPhotos;
+import tim.prune.undo.UndoMergeTrackSegments;
import tim.prune.undo.UndoOperation;
import tim.prune.undo.UndoRearrangeWaypoints;
import tim.prune.undo.UndoReverseSection;
private KmlExporter _kmlExporter = null;
private GpxExporter _gpxExporter = null;
private PovExporter _povExporter = null;
+ private BrowserLauncher _browserLauncher = null;
private Stack _undoStack = null;
- private UpdateMessageBroker _broker = null;
private boolean _reversePointsConfirmed = false;
// Constants
/**
* Constructor
* @param inFrame frame object for application
- * @param inBroker message broker
*/
- public App(JFrame inFrame, UpdateMessageBroker inBroker)
+ public App(JFrame inFrame)
{
_frame = inFrame;
_undoStack = new Stack();
- _broker = inBroker;
- _track = new Track(_broker);
- _trackInfo = new TrackInfo(_track, _broker);
+ _track = new Track();
+ _trackInfo = new TrackInfo(_track);
}
/**
- * Add a photo or a directory of photos which are already correlated
+ * Add a photo or a directory of photos
*/
public void addPhotos()
{
if (_jpegLoader == null)
_jpegLoader = new JpegLoader(this, _frame);
- _jpegLoader.openFile();
+ _jpegLoader.openDialog();
}
if (_track.editPoint(currentPoint, inEditList))
{
_undoStack.push(undo);
+ // Confirm point edit
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.point.edit"));
}
}
}
*/
public void deleteCurrentPoint()
{
- if (_track != null)
+ if (_track == null) {return;}
+ DataPoint currentPoint = _trackInfo.getCurrentPoint();
+ if (currentPoint != null)
{
- DataPoint currentPoint = _trackInfo.getCurrentPoint();
- if (currentPoint != null)
+ boolean deletePhoto = false;
+ Photo currentPhoto = currentPoint.getPhoto();
+ if (currentPhoto != null)
+ {
+ // Confirm deletion of photo or decoupling
+ int response = JOptionPane.showConfirmDialog(_frame,
+ I18nManager.getText("dialog.deletepoint.deletephoto") + " " + currentPhoto.getFile().getName(),
+ I18nManager.getText("dialog.deletepoint.title"),
+ JOptionPane.YES_NO_CANCEL_OPTION);
+ if (response == JOptionPane.CANCEL_OPTION || response == JOptionPane.CLOSED_OPTION)
+ {
+ // cancel pressed- abort delete
+ return;
+ }
+ if (response == JOptionPane.YES_OPTION) {deletePhoto = true;}
+ }
+ // store necessary information to undo it later
+ int pointIndex = _trackInfo.getSelection().getCurrentPointIndex();
+ int photoIndex = _trackInfo.getPhotoList().getPhotoIndex(currentPhoto);
+ DataPoint nextTrackPoint = _trackInfo.getTrack().getNextTrackPoint(pointIndex + 1);
+ // Construct Undo object
+ UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex,
+ nextTrackPoint != null && nextTrackPoint.getSegmentStart());
+ // call track to delete point
+ if (_trackInfo.deletePoint())
{
- boolean deletePhoto = false;
- Photo currentPhoto = currentPoint.getPhoto();
+ // Delete was successful so add undo info to stack
+ _undoStack.push(undo);
if (currentPhoto != null)
{
- // Confirm deletion of photo or decoupling
- int response = JOptionPane.showConfirmDialog(_frame,
- I18nManager.getText("dialog.deletepoint.deletephoto") + " " + currentPhoto.getFile().getName(),
- I18nManager.getText("dialog.deletepoint.title"),
- JOptionPane.YES_NO_CANCEL_OPTION);
- if (response == JOptionPane.CANCEL_OPTION || response == JOptionPane.CLOSED_OPTION)
+ // delete photo if necessary
+ if (deletePhoto)
{
- // cancel pressed- abort delete
- return;
+ _trackInfo.getPhotoList().deletePhoto(photoIndex);
}
- if (response == JOptionPane.YES_OPTION) {deletePhoto = true;}
- }
- // add information to undo stack
- int pointIndex = _trackInfo.getSelection().getCurrentPointIndex();
- int photoIndex = _trackInfo.getPhotoList().getPhotoIndex(currentPhoto);
- // Undo object needs to know index of photo in list (if any) to restore
- UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex);
- // call track to delete point
- if (_trackInfo.deletePoint())
- {
- _undoStack.push(undo);
- if (currentPhoto != null)
+ else
{
- // delete photo if necessary
- if (deletePhoto)
- {
- _trackInfo.getPhotoList().deletePhoto(photoIndex);
- }
- else
- {
- // decouple photo from point
- currentPhoto.setDataPoint(null);
- }
+ // decouple photo from point
+ currentPhoto.setDataPoint(null);
}
}
+ // Confirm
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.deletepoint.single"));
}
}
}
}
}
// add information to undo stack
- UndoOperation undo = new UndoDeleteRange(_trackInfo);
+ UndoDeleteRange undo = new UndoDeleteRange(_trackInfo);
// delete requested photos
for (int i=0; i<numToDelete; i++)
{
if (_trackInfo.deleteRange())
{
_undoStack.push(undo);
+ // Confirm
+ UpdateMessageBroker.informSubscribers("" + numToDelete + " "
+ + I18nManager.getText("confirm.deletepoint.multi"));
}
}
}
String message = null;
if (numDeleted == 1)
{
- message = "1 " + I18nManager.getText("dialog.deleteduplicates.single.text");
+ message = "1 " + I18nManager.getText("confirm.deleteduplicates.single");
}
else
{
- message = "" + numDeleted + " " + I18nManager.getText("dialog.deleteduplicates.multi.text");
+ message = "" + numDeleted + " " + I18nManager.getText("confirm.deleteduplicates.multi");
}
- JOptionPane.showMessageDialog(_frame, message,
- I18nManager.getText("dialog.deleteduplicates.title"), JOptionPane.INFORMATION_MESSAGE);
+ // Pass message to broker
+ UpdateMessageBroker.informSubscribers(message);
}
else
{
+ // No duplicates found to delete
JOptionPane.showMessageDialog(_frame,
I18nManager.getText("dialog.deleteduplicates.nonefound"),
I18nManager.getText("dialog.deleteduplicates.title"), JOptionPane.INFORMATION_MESSAGE);
{
undo.setNumPointsDeleted(numPointsDeleted);
_undoStack.add(undo);
- JOptionPane.showMessageDialog(_frame,
- I18nManager.getText("dialog.compresstrack.text") + " - "
- + numPointsDeleted + " "
- + (numPointsDeleted==1?I18nManager.getText("dialog.compresstrack.single.text"):I18nManager.getText("dialog.compresstrack.multi.text")),
- I18nManager.getText("dialog.compresstrack.title"), JOptionPane.INFORMATION_MESSAGE);
+ UpdateMessageBroker.informSubscribers("" + numPointsDeleted + " "
+ + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi")));
}
else
{
/**
- * Reverse a section of the track
+ * Reverse the currently selected section of the track
*/
public void reverseRange()
{
I18nManager.getText("dialog.confirmreversetrack.title"),
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION && (_reversePointsConfirmed = true)))
{
- UndoReverseSection undo = new UndoReverseSection(selStart, selEnd);
+ UndoReverseSection undo = new UndoReverseSection(_track, selStart, selEnd);
// call track to reverse range
if (_track.reverseRange(selStart, selEnd))
{
_undoStack.add(undo);
+ // Confirm
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.reverserange"));
+ }
+ }
+ }
+
+ /**
+ * Merge the track segments within the current selection
+ */
+ public void mergeTrackSegments()
+ {
+ if (_trackInfo.getSelection().hasRangeSelected())
+ {
+ // Maybe could check segment start flags to see if it's worth merging
+ // If first track point is already start and no other seg starts then do nothing
+
+ int selStart = _trackInfo.getSelection().getStart();
+ int selEnd = _trackInfo.getSelection().getEnd();
+ // Make undo object
+ UndoMergeTrackSegments undo = new UndoMergeTrackSegments(_track, selStart, selEnd);
+ // Call track to merge segments
+ if (_track.mergeTrackSegments(selStart, selEnd)) {
+ _undoStack.add(undo);
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.mergetracksegments"));
}
}
}
public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, int inAltFormat, String inFilename)
{
// Check whether loaded array can be properly parsed into a Track
- Track loadedTrack = new Track(_broker);
+ Track loadedTrack = new Track();
loadedTrack.load(inFieldArray, inDataArray, inAltFormat);
if (loadedTrack.getNumPoints() <= 0)
{
_trackInfo.loadTrack(inFieldArray, inDataArray, inAltFormat);
_trackInfo.getFileInfo().setFile(inFilename);
}
- _broker.informSubscribers();
+ UpdateMessageBroker.informSubscribers();
+ // Update status bar
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile") + " '" + inFilename + "'");
// update menu
_menuManager.informFileLoaded();
}
}
if (numPhotosAdded == 1)
{
- JOptionPane.showMessageDialog(_frame,
- "" + numPhotosAdded + " " + I18nManager.getText("dialog.jpegload.photoadded"),
- I18nManager.getText("dialog.jpegload.title"), JOptionPane.INFORMATION_MESSAGE);
+ UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.single"));
}
else
{
- JOptionPane.showMessageDialog(_frame,
- "" + numPhotosAdded + " " + I18nManager.getText("dialog.jpegload.photosadded"),
- I18nManager.getText("dialog.jpegload.title"), JOptionPane.INFORMATION_MESSAGE);
+ UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.multi"));
}
// TODO: Improve message when photo(s) fail to load (eg already added)
- _broker.informSubscribers();
+ UpdateMessageBroker.informSubscribers();
// update menu
_menuManager.informFileLoaded();
}
_undoStack.add(new UndoConnectPhoto(point, photo.getFile().getName()));
photo.setDataPoint(point);
point.setPhoto(photo);
- _broker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
+ UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.photo.connect"));
}
}
// disconnect
photo.setDataPoint(null);
point.setPhoto(null);
- _broker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
+ UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.photo.disconnect"));
}
}
public void beginCorrelatePhotos()
{
PhotoCorrelator correlator = new PhotoCorrelator(this, _frame);
- // TODO: Do we need to keep a reference to this object to reuse it later?
+ // TODO: Do we need to keep a reference to this Photo Correlator object to reuse it later?
correlator.begin();
}
undo.setNumPhotosCorrelated(numPhotos);
_undoStack.add(undo);
// confirm correlation
- JOptionPane.showMessageDialog(_frame, "" + numPhotos + " "
- + (numPhotos==1?I18nManager.getText("dialog.correlate.confirmsingle.text"):I18nManager.getText("dialog.correlate.confirmmultiple.text")),
- I18nManager.getText("dialog.correlate.title"),
- JOptionPane.INFORMATION_MESSAGE);
+ UpdateMessageBroker.informSubscribers("" + numPhotos + " "
+ + (numPhotos==1?I18nManager.getText("confirm.correlate.single"):I18nManager.getText("confirm.correlate.multi")));
// observers already informed by track update
}
}
{
if (_undoStack.isEmpty())
{
+ // Nothing to undo
JOptionPane.showMessageDialog(_frame, I18nManager.getText("dialog.undo.none.text"),
I18nManager.getText("dialog.undo.none.title"), JOptionPane.INFORMATION_MESSAGE);
}
_undoStack.clear();
_lastSavePosition = 0;
if (unsaved) _lastSavePosition = -1;
- _broker.informSubscribers();
+ UpdateMessageBroker.informSubscribers();
}
}
{
((UndoOperation) _undoStack.pop()).performUndo(_trackInfo);
}
- JOptionPane.showMessageDialog(_frame, "" + inNumUndos + " "
- + (inNumUndos==1?I18nManager.getText("dialog.confirmundo.single.text"):I18nManager.getText("dialog.confirmundo.multiple.text")),
- I18nManager.getText("dialog.confirmundo.title"),
- JOptionPane.INFORMATION_MESSAGE);
+ String message = "" + inNumUndos + " "
+ + (inNumUndos==1?I18nManager.getText("confirm.undo.single"):I18nManager.getText("confirm.undo.multi"));
+ UpdateMessageBroker.informSubscribers(message);
}
catch (UndoException ue)
{
I18nManager.getText("error.undofailed.title"),
JOptionPane.ERROR_MESSAGE);
_undoStack.clear();
- _broker.informSubscribers();
+ UpdateMessageBroker.informSubscribers();
}
catch (EmptyStackException empty) {}
}
I18nManager.getText("menu.help"),
JOptionPane.INFORMATION_MESSAGE);
}
+
+ /**
+ * Show an OSM map window
+ */
+ public void showOsmMap()
+ {
+ MapWindow map = new MapWindow(_track);
+ map.pack();
+ map.show();
+ }
+
+ /**
+ * Show a map url in an external browser
+ */
+ public void showExternalMap(int inSourceIndex)
+ {
+ if (_browserLauncher == null) {_browserLauncher = new BrowserLauncher();}
+ _browserLauncher.launchBrowser(UrlGenerator.generateUrl(inSourceIndex, _trackInfo));
+ }
}