X-Git-Url: https://gitweb.fperrin.net/?a=blobdiff_plain;f=tim%2Fprune%2FApp.java;h=686b3dee485d4b3ffcd58203f2a3e5445be9bb17;hb=8c8868ae29b3252f02e094c02307384cf61ba667;hp=ced255ae111cc194eac8fb0d1db64b2f2b019b36;hpb=54b9d8bc8f0025ccf97a67d9dd217ef1f9cf082f;p=GpsPrune.git diff --git a/tim/prune/App.java b/tim/prune/App.java index ced255a..686b3de 100644 --- a/tim/prune/App.java +++ b/tim/prune/App.java @@ -1,5 +1,7 @@ package tim.prune; +import java.io.File; +import java.util.ArrayList; import java.util.EmptyStackException; import java.util.Set; import java.util.Stack; @@ -7,46 +9,39 @@ import java.util.Stack; import javax.swing.JFrame; import javax.swing.JOptionPane; -import tim.prune.data.Altitude; -import tim.prune.data.Coordinate; +import tim.prune.config.Config; +import tim.prune.data.Checker; import tim.prune.data.DataPoint; import tim.prune.data.Field; import tim.prune.data.LatLonRectangle; -import tim.prune.data.Latitude; -import tim.prune.data.Longitude; +import tim.prune.data.NumberUtils; import tim.prune.data.Photo; import tim.prune.data.PhotoList; +import tim.prune.data.PointCreateOptions; +import tim.prune.data.RecentFile; +import tim.prune.data.SourceInfo; import tim.prune.data.Track; import tim.prune.data.TrackInfo; +import tim.prune.data.SourceInfo.FILE_TYPE; +import tim.prune.data.Unit; +import tim.prune.function.AsyncMediaLoader; +import tim.prune.function.SaveConfig; +import tim.prune.function.SelectTracksFunction; import tim.prune.function.browser.BrowserLauncher; import tim.prune.function.browser.UrlGenerator; import tim.prune.function.edit.FieldEditList; import tim.prune.function.edit.PointEditor; -import tim.prune.function.edit.PointNameEditor; import tim.prune.gui.MenuManager; +import tim.prune.gui.SidebarController; import tim.prune.gui.UndoManager; +import tim.prune.gui.Viewport; import tim.prune.load.FileLoader; import tim.prune.load.JpegLoader; +import tim.prune.load.MediaLinkInfo; +import tim.prune.load.TrackNameList; import tim.prune.save.ExifSaver; import tim.prune.save.FileSaver; -import tim.prune.undo.UndoAddTimeOffset; -import tim.prune.undo.UndoCompress; -import tim.prune.undo.UndoConnectPhoto; -import tim.prune.undo.UndoConnectPhotoWithClone; -import tim.prune.undo.UndoCreatePoint; -import tim.prune.undo.UndoCutAndMove; -import tim.prune.undo.UndoDeletePhoto; -import tim.prune.undo.UndoDeletePoint; -import tim.prune.undo.UndoDeleteRange; -import tim.prune.undo.UndoDisconnectPhoto; -import tim.prune.undo.UndoEditPoint; -import tim.prune.undo.UndoException; -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.UndoReverseSection; +import tim.prune.undo.*; /** @@ -60,11 +55,21 @@ public class App private TrackInfo _trackInfo = null; private int _lastSavePosition = 0; private MenuManager _menuManager = null; + private SidebarController _sidebarController = null; private FileLoader _fileLoader = null; private JpegLoader _jpegLoader = null; private FileSaver _fileSaver = null; private Stack _undoStack = null; private boolean _mangleTimestampsConfirmed = false; + private Viewport _viewport = null; + private ArrayList _dataFiles = null; + private boolean _autoAppendNextFile = false; + private boolean _busyLoading = false; + private AppMode _appMode = AppMode.NORMAL; + + /** Enum for the app mode - currently only two options but may expand later */ + public enum AppMode {NORMAL, DRAWRECT}; + /** * Constructor @@ -103,7 +108,7 @@ public class App public boolean hasDataUnsaved() { return (_undoStack.size() > _lastSavePosition - && (_track.getNumPoints() > 0 || _trackInfo.getPhotoList().getNumPhotos() > 0)); + && (_track.getNumPoints() > 0 || _trackInfo.getPhotoList().hasModifiedMedia())); } /** @@ -114,6 +119,28 @@ public class App return _undoStack; } + /** + * Load the specified data files one by one + * @param inDataFiles arraylist containing File objects to load + */ + public void loadDataFiles(ArrayList inDataFiles) + { + if (inDataFiles == null || inDataFiles.size() == 0) { + _dataFiles = null; + } + else + { + _dataFiles = inDataFiles; + File f = _dataFiles.get(0); + _dataFiles.remove(0); + // Start load of specified file + if (_fileLoader == null) + _fileLoader = new FileLoader(this, _frame); + _autoAppendNextFile = false; // prompt for append + _fileLoader.openFile(f); + } + } + /** * Complete a function execution * @param inUndo undo object to be added to stack @@ -123,6 +150,7 @@ public class App { _undoStack.add(inUndo); UpdateMessageBroker.informSubscribers(inConfirmText); + setCurrentMode(AppMode.NORMAL); } /** @@ -167,7 +195,7 @@ public class App else { if (_fileSaver == null) { - _fileSaver = new FileSaver(this, _frame, _track); + _fileSaver = new FileSaver(this, _frame); } char delim = ','; if (_fileLoader != null) {delim = _fileLoader.getLastUsedDelimiter();} @@ -192,6 +220,10 @@ public class App JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1]) == JOptionPane.YES_OPTION) { + // save settings + if (Config.getConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS)) { + new SaveConfig(this).silentSave(); + } System.exit(0); } } @@ -228,7 +260,7 @@ public class App // add information to undo stack UndoOperation undo = new UndoEditPoint(currentPoint, inUndoList); // pass to track for completion - if (_track.editPoint(currentPoint, inEditList)) + if (_track.editPoint(currentPoint, inEditList, false)) { _undoStack.push(undo); // Confirm point edit @@ -238,24 +270,6 @@ public class App } - /** - * Edit the name of the currently selected (way)point - */ - public void editCurrentPointName() - { - if (_track != null) - { - DataPoint currentPoint = _trackInfo.getCurrentPoint(); - if (currentPoint != null) - { - // Open point dialog to display details - PointNameEditor editor = new PointNameEditor(this, _frame); - editor.showDialog(currentPoint); - } - } - } - - /** * Delete the currently selected point */ @@ -265,13 +279,14 @@ public class App DataPoint currentPoint = _trackInfo.getCurrentPoint(); if (currentPoint != null) { + // Check for photo 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.deletephoto") + " " + currentPhoto.getName(), I18nManager.getText("dialog.deletepoint.title"), JOptionPane.YES_NO_CANCEL_OPTION); if (response == JOptionPane.CANCEL_OPTION || response == JOptionPane.CLOSED_OPTION) @@ -284,10 +299,11 @@ public class App // store necessary information to undo it later int pointIndex = _trackInfo.getSelection().getCurrentPointIndex(); int photoIndex = _trackInfo.getPhotoList().getPhotoIndex(currentPhoto); + int audioIndex = _trackInfo.getAudioList().getAudioIndex(currentPoint.getAudio()); DataPoint nextTrackPoint = _trackInfo.getTrack().getNextTrackPoint(pointIndex + 1); // Construct Undo object UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex, - nextTrackPoint != null && nextTrackPoint.getSegmentStart()); + audioIndex, nextTrackPoint != null && nextTrackPoint.getSegmentStart()); // call track to delete point if (_trackInfo.deletePoint()) { @@ -305,95 +321,15 @@ public class App // decouple photo from point currentPhoto.setDataPoint(null); } + UpdateMessageBroker.informSubscribers(DataSubscriber.PHOTOS_MODIFIED); + } + // Delete audio object (without bothering to ask) + if (audioIndex > -1) { + _trackInfo.getAudioList().deleteAudio(audioIndex); } // Confirm UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.deletepoint.single")); - } - } - } - - - /** - * Delete the currently selected range - */ - public void deleteSelectedRange() - { - if (_track != null) - { - // Find out if photos should be deleted or not - int selStart = _trackInfo.getSelection().getStart(); - int selEnd = _trackInfo.getSelection().getEnd(); - if (selStart >= 0 && selEnd >= selStart) - { - int numToDelete = selEnd - selStart + 1; - boolean[] deletePhotos = new boolean[numToDelete]; - Photo[] photosToDelete = new Photo[numToDelete]; - boolean deleteAll = false; - boolean deleteNone = false; - String[] questionOptions = {I18nManager.getText("button.yes"), I18nManager.getText("button.no"), - I18nManager.getText("button.yestoall"), I18nManager.getText("button.notoall"), - I18nManager.getText("button.cancel")}; - DataPoint point = null; - for (int i=0; i inIndex) + { + // Extend end of selection by 1 + _trackInfo.getSelection().selectRange(selStart, selEnd+1); + } // update listeners UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.createpoint")); } @@ -582,22 +555,13 @@ public class App // Add undo object to stack, set confirm message _undoStack.add(undo); - _trackInfo.getSelection().deselectRange(); + _trackInfo.getSelection().selectRange(-1, -1); UpdateMessageBroker.informSubscribers(); UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.cutandmove")); } } } - - /** - * Select all points - */ - public void selectAll() - { - _trackInfo.getSelection().select(0, 0, _track.getNumPoints()-1); - } - /** * Select nothing */ @@ -608,219 +572,236 @@ public class App _track.clearDeletionMarkers(); } + /** + * Receive loaded data and determine whether to filter on tracks or not + * @param inFieldArray array of fields + * @param inDataArray array of data + * @param inSourceInfo information about the source of the data + * @param inTrackNameList information about the track names + */ + public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, + SourceInfo inSourceInfo, TrackNameList inTrackNameList) + { + // no link array given + informDataLoaded(inFieldArray, inDataArray, null, inSourceInfo, + inTrackNameList, null); + } /** - * Receive loaded data and optionally merge with current Track + * Receive loaded data and determine whether to filter on tracks or not * @param inFieldArray array of fields * @param inDataArray array of data - * @param inAltFormat altitude format - * @param inFilename filename used + * @param inOptions creation options such as units + * @param inSourceInfo information about the source of the data + * @param inTrackNameList information about the track names */ - public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, Altitude.Format inAltFormat, - String inFilename) + public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, + PointCreateOptions inOptions, SourceInfo inSourceInfo, TrackNameList inTrackNameList) + { + // no link array given + informDataLoaded(inFieldArray, inDataArray, inOptions, inSourceInfo, + inTrackNameList, null); + } + + /** + * Receive loaded data and determine whether to filter on tracks or not + * @param inFieldArray array of fields + * @param inDataArray array of data + * @param inOptions creation options such as units + * @param inSourceInfo information about the source of the data + * @param inTrackNameList information about the track names + * @param inLinkInfo links to photo/audio clips + */ + public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, PointCreateOptions inOptions, + SourceInfo inSourceInfo, TrackNameList inTrackNameList, MediaLinkInfo inLinkInfo) { // Check whether loaded array can be properly parsed into a Track Track loadedTrack = new Track(); - loadedTrack.load(inFieldArray, inDataArray, inAltFormat); + loadedTrack.load(inFieldArray, inDataArray, inOptions); if (loadedTrack.getNumPoints() <= 0) { showErrorMessage("error.load.dialogtitle", "error.load.nopoints"); + // load next file if there's a queue + loadNextFile(); return; } + // Check for doubled track + if (Checker.isDoubledTrack(loadedTrack)) { + JOptionPane.showMessageDialog(_frame, I18nManager.getText("dialog.open.contentsdoubled"), + I18nManager.getText("function.open"), JOptionPane.WARNING_MESSAGE); + } + + _busyLoading = true; + // Attach photos and/or audio clips to points + if (inLinkInfo != null) + { + String[] linkArray = inLinkInfo.getLinkArray(); + if (linkArray != null) { + new AsyncMediaLoader(this, inLinkInfo.getZipFile(), linkArray, loadedTrack, inSourceInfo.getFile()).begin(); + } + } + // Look at TrackNameList, decide whether to filter or not + if (inTrackNameList != null && inTrackNameList.getNumTracks() > 1) + { + // Launch a dialog to let the user choose which tracks to load, then continue + new SelectTracksFunction(this, loadedTrack, inSourceInfo, inTrackNameList).begin(); + } + else { + // go directly to load + informDataLoaded(loadedTrack, inSourceInfo); + } + setCurrentMode(AppMode.NORMAL); + } + + + /** + * Receive loaded data and optionally merge with current Track + * @param inLoadedTrack loaded track + * @param inSourceInfo information about the source of the data + */ + public void informDataLoaded(Track inLoadedTrack, SourceInfo inSourceInfo) + { // Decide whether to load or append if (_track.getNumPoints() > 0) { // ask whether to replace or append - int answer = JOptionPane.showConfirmDialog(_frame, - I18nManager.getText("dialog.openappend.text"), - I18nManager.getText("dialog.openappend.title"), - JOptionPane.YES_NO_CANCEL_OPTION); + int answer = 0; + if (_autoAppendNextFile) { + // Automatically append the next file + answer = JOptionPane.YES_OPTION; + } + else { + // Ask whether to append or not + answer = JOptionPane.showConfirmDialog(_frame, + I18nManager.getText("dialog.openappend.text"), + I18nManager.getText("dialog.openappend.title"), + JOptionPane.YES_NO_CANCEL_OPTION); + } + _autoAppendNextFile = false; // reset flag to cancel autoappend + if (answer == JOptionPane.YES_OPTION) { // append data to current Track - _undoStack.add(new UndoLoad(_track.getNumPoints(), loadedTrack.getNumPoints())); - _track.combine(loadedTrack); - // set filename if currently empty - if (_trackInfo.getFileInfo().getNumFiles() == 0) - { - _trackInfo.getFileInfo().setFile(inFilename); - } - else - { - _trackInfo.getFileInfo().addFile(); - } + UndoLoad undo = new UndoLoad(_track.getNumPoints(), inLoadedTrack.getNumPoints()); + undo.setNumPhotosAudios(_trackInfo.getPhotoList().getNumPhotos(), _trackInfo.getAudioList().getNumAudios()); + _undoStack.add(undo); + _track.combine(inLoadedTrack); + // set source information + inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints()); + _trackInfo.getFileInfo().addSource(inSourceInfo); } else if (answer == JOptionPane.NO_OPTION) { // Don't append, replace data PhotoList photos = null; - if (_trackInfo.getPhotoList().hasCorrelatedPhotos()) - { + if (_trackInfo.getPhotoList().hasCorrelatedPhotos()) { photos = _trackInfo.getPhotoList().cloneList(); } - _undoStack.add(new UndoLoad(_trackInfo, inDataArray.length, photos)); + UndoLoad undo = new UndoLoad(_trackInfo, inLoadedTrack.getNumPoints(), photos); + undo.setNumPhotosAudios(_trackInfo.getPhotoList().getNumPhotos(), _trackInfo.getAudioList().getNumAudios()); + _undoStack.add(undo); _lastSavePosition = _undoStack.size(); _trackInfo.getSelection().clearAll(); - _track.load(loadedTrack); - _trackInfo.getFileInfo().setFile(inFilename); - if (photos != null) - { - _trackInfo.getPhotoList().removeCorrelatedPhotos(); - } + _track.load(inLoadedTrack); + inSourceInfo.populatePointObjects(_track, _track.getNumPoints()); + _trackInfo.getFileInfo().replaceSource(inSourceInfo); + _trackInfo.getPhotoList().removeCorrelatedPhotos(); + _trackInfo.getAudioList().removeCorrelatedAudios(); } } else { // Currently no data held, so transfer received data - _undoStack.add(new UndoLoad(_trackInfo, inDataArray.length, null)); + UndoLoad undo = new UndoLoad(_trackInfo, inLoadedTrack.getNumPoints(), null); + undo.setNumPhotosAudios(_trackInfo.getPhotoList().getNumPhotos(), _trackInfo.getAudioList().getNumAudios()); + _undoStack.add(undo); _lastSavePosition = _undoStack.size(); _trackInfo.getSelection().clearAll(); - _track.load(loadedTrack); - _trackInfo.getFileInfo().setFile(inFilename); + _track.load(inLoadedTrack); + inSourceInfo.populatePointObjects(_track, _track.getNumPoints()); + _trackInfo.getFileInfo().addSource(inSourceInfo); } + // Update config before subscribers are told + boolean isRegularLoad = (inSourceInfo.getFileType() != FILE_TYPE.GPSBABEL); + Config.getRecentFileList().addFile(new RecentFile(inSourceInfo.getFile(), isRegularLoad)); UpdateMessageBroker.informSubscribers(); // Update status bar - UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile") + " '" + inFilename + "'"); + UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile") + + " '" + inSourceInfo.getName() + "'"); // update menu _menuManager.informFileLoaded(); + // Remove busy lock + _busyLoading = false; + // load next file if there's a queue + loadNextFile(); } - /** - * Accept a list of loaded photos - * @param inPhotoSet Set of Photo objects + * Inform the app that NO data was loaded, eg cancel pressed + * Only needed if there's another file waiting in the queue */ - public void informPhotosLoaded(Set inPhotoSet) + public void informNoDataLoaded() { - if (inPhotoSet != null && !inPhotoSet.isEmpty()) - { - int[] numsAdded = _trackInfo.addPhotos(inPhotoSet); - int numPhotosAdded = numsAdded[0]; - int numPointsAdded = numsAdded[1]; - if (numPhotosAdded > 0) - { - // Save numbers so load can be undone - _undoStack.add(new UndoLoadPhotos(numPhotosAdded, numPointsAdded)); - } - if (numPhotosAdded == 1) - { - UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.single")); - } - else - { - UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.multi")); - } - // TODO: Improve message when photo(s) fail to load (eg already added) - UpdateMessageBroker.informSubscribers(); - // update menu - _menuManager.informFileLoaded(); - } + // Load next file if there's a queue + loadNextFile(); } - /** - * Connect the current photo to the current point + * External trigger to automatically append the next loaded file + * instead of prompting to replace or append */ - public void connectPhotoToPoint() + public void autoAppendNextFile() { - Photo photo = _trackInfo.getCurrentPhoto(); - DataPoint point = _trackInfo.getCurrentPoint(); - if (photo != null && point != null) - { - if (point.getPhoto() != null) - { - // point already has a photo, confirm cloning of new point - if (JOptionPane.showConfirmDialog(_frame, - I18nManager.getText("dialog.connectphoto.clonepoint"), - I18nManager.getText("dialog.connect.title"), - JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) - { - // Create undo, clone point and attach - int pointIndex = _trackInfo.getSelection().getCurrentPointIndex() + 1; - // insert new point after current one - point = point.clonePoint(); - UndoConnectPhotoWithClone undo = new UndoConnectPhotoWithClone( - point, photo.getFile().getName(), pointIndex); - _track.insertPoint(point, pointIndex); - photo.setDataPoint(point); - point.setPhoto(photo); - _undoStack.add(undo); - UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED); - UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.photo.connect")); - } - } - else - { - // point doesn't currently have a photo, so just connect it - _undoStack.add(new UndoConnectPhoto(point, photo.getFile().getName())); - photo.setDataPoint(point); - point.setPhoto(photo); - UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED); - UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.photo.connect")); - } - } + _autoAppendNextFile = true; } - /** - * Disconnect the current photo from its point + * Load the next file in the waiting list, if any */ - public void disconnectPhotoFromPoint() + private void loadNextFile() { - Photo photo = _trackInfo.getCurrentPhoto(); - if (photo != null && photo.getDataPoint() != null) - { - DataPoint point = photo.getDataPoint(); - _undoStack.add(new UndoDisconnectPhoto(point, photo.getFile().getName())); - // disconnect - photo.setDataPoint(null); - point.setPhoto(null); - UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED); - UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.photo.disconnect")); + if (_dataFiles == null || _dataFiles.size() == 0) { + _dataFiles = null; + } + else { + new Thread(new Runnable() { + public void run() { + File f = _dataFiles.get(0); + _dataFiles.remove(0); + _autoAppendNextFile = true; + _fileLoader.openFile(f); + } + }).start(); } } /** - * Remove the current photo, if any + * Accept a list of loaded photos + * @param inPhotoSet Set of Photo objects */ - public void deleteCurrentPhoto() + public void informPhotosLoaded(Set inPhotoSet) { - // Delete the current photo, and optionally its point too, keeping undo information - Photo currentPhoto = _trackInfo.getCurrentPhoto(); - if (currentPhoto != null) + if (inPhotoSet != null && !inPhotoSet.isEmpty()) { - // Photo is selected, see if it has a point or not - boolean photoDeleted = false; - UndoDeletePhoto undoAction = null; - if (currentPhoto.getDataPoint() == null) + int[] numsAdded = _trackInfo.addPhotos(inPhotoSet); + int numPhotosAdded = numsAdded[0]; + int numPointsAdded = numsAdded[1]; + if (numPhotosAdded > 0) { - // no point attached, so just delete photo - undoAction = new UndoDeletePhoto(currentPhoto, _trackInfo.getSelection().getCurrentPhotoIndex(), - null, -1); - photoDeleted = _trackInfo.deleteCurrentPhoto(false); + // Save numbers so load can be undone + _undoStack.add(new UndoLoadPhotos(numPhotosAdded, numPointsAdded)); } - else - { - // point is attached, so need to confirm point deletion - undoAction = new UndoDeletePhoto(currentPhoto, _trackInfo.getSelection().getCurrentPhotoIndex(), - currentPhoto.getDataPoint(), _trackInfo.getTrack().getPointIndex(currentPhoto.getDataPoint())); - int response = JOptionPane.showConfirmDialog(_frame, - I18nManager.getText("dialog.deletephoto.deletepoint"), - I18nManager.getText("dialog.deletephoto.title"), - JOptionPane.YES_NO_CANCEL_OPTION); - boolean deletePointToo = (response == JOptionPane.YES_OPTION); - // Cancel delete if cancel pressed or dialog closed - if (response == JOptionPane.YES_OPTION || response == JOptionPane.NO_OPTION) - { - photoDeleted = _trackInfo.deleteCurrentPhoto(deletePointToo); - } + if (numPhotosAdded == 1) { + UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.single")); } - // Add undo information to stack if necessary - if (photoDeleted) - { - _undoStack.add(undoAction); + else { + UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.multi")); } + // MAYBE: Improve message when photo(s) fail to load (eg already added) + UpdateMessageBroker.informSubscribers(); + // update menu + if (numPointsAdded > 0) _menuManager.informFileLoaded(); } } @@ -908,32 +889,12 @@ public class App showErrorMessageNoLookup("error.undofailed.title", I18nManager.getText("error.undofailed.text") + " : " + ue.getMessage()); _undoStack.clear(); - UpdateMessageBroker.informSubscribers(); } catch (EmptyStackException empty) {} + UpdateMessageBroker.informSubscribers(); } - /** - * Helper method to parse an Object into an integer - * @param inObject object, eg from dialog - * @return int value given - */ - private static int parseNumber(Object inObject) - { - int num = 0; - if (inObject != null) - { - try - { - num = Integer.parseInt(inObject.toString()); - } - catch (NumberFormatException nfe) - {} - } - return num; - } - /** * Show a map url in an external browser * @param inSourceIndex index of map source to use @@ -964,4 +925,52 @@ public class App JOptionPane.showMessageDialog(_frame, inMessage, I18nManager.getText(inTitleKey), JOptionPane.ERROR_MESSAGE); } + + /** + * @param inViewport viewport object + */ + public void setViewport(Viewport inViewport) + { + _viewport = inViewport; + } + + /** + * @return current viewport object + */ + public Viewport getViewport() + { + return _viewport; + } + + /** + * Set the controller for the full screen mode + * @param inController controller object + */ + public void setSidebarController(SidebarController inController) + { + _sidebarController = inController; + } + + /** + * Toggle sidebars on and off + */ + public void toggleSidebars() + { + _sidebarController.toggle(); + } + + /** @return true if App is currently busy with loading data */ + public boolean isBusyLoading() { + return _busyLoading; + } + + /** @return current app mode */ + public AppMode getCurrentMode() { + return _appMode; + } + + /** @param inMode the current app mode */ + public void setCurrentMode(AppMode inMode) { + _appMode = inMode; + } }