From d72e6349234a249293b4bf371c9aa34b68aaf42b Mon Sep 17 00:00:00 2001 From: Hallvard Traetteberg <hal@ntnu.no> Date: Mon, 5 Feb 2018 22:59:39 +0100 Subject: [PATCH] Some refactorings and improved testing. --- .../java/tdt4140/gr1800/app/core/App.java | 43 ++---- .../app/core/IGeoLocationsListener.java | 6 - .../{core => doc}/DocumentStorageImpl.java | 34 ++++- .../app/{core => doc}/IDocumentImporter.java | 2 +- .../gr1800/app/doc/IDocumentListener.java | 5 + .../app/{core => doc}/IDocumentLoader.java | 2 +- .../{core => doc}/IDocumentPersistence.java | 2 +- .../app/{core => doc}/IDocumentSaver.java | 2 +- .../app/{core => doc}/IDocumentStorage.java | 5 +- .../app/doc/IDocumentStorageListener.java | 5 + .../gr1800/app/gpx/GpxDocumentConverter.java | 2 +- .../gr1800/app/gpx/GpxDocumentLoader.java | 2 +- .../tdt4140/gr1800/app/core/geoLocations.json | 4 +- .../java/tdt4140/gr1800/app/core/AppTest.java | 2 + .../gr1800/app/core/Achterbroek-route.gpx | 4 + .../gr1800/app/core/Achterbroek-track.gpx | 4 + .../gr1800/app/ui/FileMenuController.java | 51 +++---- .../gr1800/app/ui/FxAppController.java | 42 ++++-- .../tdt4140/gr1800/app/ui/FileMenu.fxml | 12 +- .../java/tdt4140/gr1800/app/ui/FxAppTest.java | 133 +++++++++++++++++- 20 files changed, 260 insertions(+), 102 deletions(-) delete mode 100644 tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IGeoLocationsListener.java rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/DocumentStorageImpl.java (56%) rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/IDocumentImporter.java (80%) create mode 100644 tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentListener.java rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/IDocumentLoader.java (76%) rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/IDocumentPersistence.java (75%) rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/IDocumentSaver.java (78%) rename tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/{core => doc}/IDocumentStorage.java (63%) create mode 100644 tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorageListener.java diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java index b7bd765..defe620 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/App.java @@ -9,6 +9,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.stream.Collectors; +import tdt4140.gr1800.app.doc.DocumentStorageImpl; +import tdt4140.gr1800.app.doc.IDocumentImporter; +import tdt4140.gr1800.app.doc.IDocumentLoader; +import tdt4140.gr1800.app.doc.IDocumentPersistence; +import tdt4140.gr1800.app.doc.IDocumentStorage; import tdt4140.gr1800.app.gpx.GpxDocumentConverter; import tdt4140.gr1800.app.json.GeoLocationsJsonPersistence; @@ -67,40 +72,6 @@ public class App { return result; } - public void setGeoLocations(Collection<GeoLocations> geoLocations) { - this.geoLocations = new ArrayList<>(geoLocations); - fireGeoLocationsUpdated(null); - } - - public void addGeoLocations(GeoLocations geoLocations) { - if (hasGeoLocations(geoLocations.getName())) { - throw new IllegalArgumentException("Duplicate geo-locations name: " + geoLocations.getName()); - } - this.geoLocations.add(geoLocations); - fireGeoLocationsUpdated(geoLocations); - } - - public void removeGeoLocations(GeoLocations geoLocations) { - this.geoLocations.remove(geoLocations); - fireGeoLocationsUpdated(geoLocations); - } - - private Collection<IGeoLocationsListener> geoLocationsListeners = new ArrayList<>(); - - public void addGeoLocationsListener(IGeoLocationsListener listener) { - geoLocationsListeners.add(listener); - } - - public void removeGeoLocationsListener(IGeoLocationsListener listener) { - geoLocationsListeners.remove(listener); - } - - protected void fireGeoLocationsUpdated(GeoLocations geoLocations) { - for (IGeoLocationsListener listener : geoLocationsListeners) { - listener.geoLocationsUpdated(geoLocations); - } - } - // private IDocumentPersistence<Collection<GeoLocations>, File> documentPersistence = new IDocumentPersistence<Collection<GeoLocations>, File>() { @@ -125,7 +96,9 @@ public class App { @Override protected void setDocument(Collection<GeoLocations> document) { - setGeoLocations(document); + Collection<GeoLocations> oldDocument = getDocument(); + App.this.geoLocations = document; + fireDocumentChanged(oldDocument); } @Override diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IGeoLocationsListener.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IGeoLocationsListener.java deleted file mode 100644 index 787f85d..0000000 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IGeoLocationsListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package tdt4140.gr1800.app.core; - -public interface IGeoLocationsListener { - - public void geoLocationsUpdated(GeoLocations geoLocations); -} diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/DocumentStorageImpl.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java similarity index 56% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/DocumentStorageImpl.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java index b673c87..6a104a6 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/DocumentStorageImpl.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/DocumentStorageImpl.java @@ -1,6 +1,8 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; public abstract class DocumentStorageImpl<D, L> implements IDocumentStorage<L>, IDocumentPersistence<D, L> { @@ -13,17 +15,45 @@ public abstract class DocumentStorageImpl<D, L> implements IDocumentStorage<L>, @Override public void setDocumentLocation(L documentLocation) { + L oldDocumentLocation = this.documentLocation; this.documentLocation = documentLocation; + fireDocumentLocationChanged(oldDocumentLocation); } protected void setDocumentAndLocation(D document, L documentLocation) { setDocument(document); setDocumentLocation(documentLocation); } - + protected abstract D getDocument(); protected abstract void setDocument(D document); + // + + private Collection<IDocumentStorageListener<L>> documentListeners = new ArrayList<IDocumentStorageListener<L>>(); + + public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener) { + documentListeners.add(documentStorageListener); + } + + public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener) { + documentListeners.remove(documentStorageListener); + } + + protected void fireDocumentLocationChanged(L oldDocumentLocation) { + for (IDocumentStorageListener<L> documentStorageListener : documentListeners) { + documentStorageListener.documentLocationChanged(documentLocation, oldDocumentLocation); + } + } + + protected void fireDocumentChanged(D oldDocument) { + for (IDocumentStorageListener<L> documentListener : documentListeners) { + if (documentListener instanceof IDocumentListener) { + ((IDocumentListener<D, L>) documentListener).documentChanged(getDocument(), oldDocument); + } + } + } + protected abstract D createDocument(); @Override diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentImporter.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java similarity index 80% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentImporter.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java index c37c4c5..ba8b8ec 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentImporter.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentImporter.java @@ -1,4 +1,4 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; import java.io.IOException; diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentListener.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentListener.java new file mode 100644 index 0000000..62b8ce2 --- /dev/null +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentListener.java @@ -0,0 +1,5 @@ +package tdt4140.gr1800.app.doc; + +public interface IDocumentListener<D, L> extends IDocumentStorageListener<L>{ + public void documentChanged(D document, D oldDocument); +} diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentLoader.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java similarity index 76% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentLoader.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java index 928fd9b..ecb029b 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentLoader.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentLoader.java @@ -1,4 +1,4 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; public interface IDocumentLoader<D, L> { public D loadDocument(L documentLocation) throws Exception; diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentPersistence.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java similarity index 75% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentPersistence.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java index 756f85d..9fbd23a 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentPersistence.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentPersistence.java @@ -1,4 +1,4 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; public interface IDocumentPersistence<D, L> extends IDocumentLoader<D, L>, IDocumentSaver<D, L> { } diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentSaver.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentSaver.java similarity index 78% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentSaver.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentSaver.java index 4d2ee0a..b9a5d92 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentSaver.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentSaver.java @@ -1,4 +1,4 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; public interface IDocumentSaver<D, L> { public void saveDocument(D document, L documentLocation) throws Exception; diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentStorage.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java similarity index 63% rename from tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentStorage.java rename to tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java index 147bd16..a037c42 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/IDocumentStorage.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorage.java @@ -1,4 +1,4 @@ -package tdt4140.gr1800.app.core; +package tdt4140.gr1800.app.doc; import java.io.IOException; import java.util.Collection; @@ -7,6 +7,9 @@ public interface IDocumentStorage<L> { public L getDocumentLocation(); public void setDocumentLocation(L documentLocation); + public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); + public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); + public void newDocument(); public void openDocument(L documentLocation) throws IOException; public void saveDocument() throws IOException; diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorageListener.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorageListener.java new file mode 100644 index 0000000..1a21cdc --- /dev/null +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/doc/IDocumentStorageListener.java @@ -0,0 +1,5 @@ +package tdt4140.gr1800.app.doc; + +public interface IDocumentStorageListener<L> { + public void documentLocationChanged(L documentLocation, L oldDocumentLocation); +} diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java index 55550bf..7324eb5 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentConverter.java @@ -11,8 +11,8 @@ import io.jenetics.jpx.Track; import io.jenetics.jpx.TrackSegment; import io.jenetics.jpx.WayPoint; import tdt4140.gr1800.app.core.GeoLocations; -import tdt4140.gr1800.app.core.IDocumentLoader; import tdt4140.gr1800.app.core.LatLong; +import tdt4140.gr1800.app.doc.IDocumentLoader; public class GpxDocumentConverter implements IDocumentLoader<Collection<GeoLocations>, File> { diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java index 28e971d..b7dcb43 100644 --- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java +++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/gpx/GpxDocumentLoader.java @@ -4,7 +4,7 @@ import java.io.InputStream; import java.net.URL; import io.jenetics.jpx.GPX; -import tdt4140.gr1800.app.core.IDocumentLoader; +import tdt4140.gr1800.app.doc.IDocumentLoader; public class GpxDocumentLoader implements IDocumentLoader<GPX, URL> { diff --git a/tdt4140-gr1800/app.core/src/main/resources/tdt4140/gr1800/app/core/geoLocations.json b/tdt4140-gr1800/app.core/src/main/resources/tdt4140/gr1800/app/core/geoLocations.json index 2561822..bfda7a4 100644 --- a/tdt4140-gr1800/app.core/src/main/resources/tdt4140/gr1800/app/core/geoLocations.json +++ b/tdt4140-gr1800/app.core/src/main/resources/tdt4140/gr1800/app/core/geoLocations.json @@ -1,13 +1,13 @@ [ { - "id" : "1", + "name" : "1", "locations" : [ { "latitude" : "63", "longitude" : "10" }, [ "63.1", "10.1" ] ] }, { - "id" : "2", + "name" : "2", "path" : "true", "locations" : [ { "latitude" : "64", "longitude" : "11" }, diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/AppTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/AppTest.java index 8add303..60baab3 100644 --- a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/AppTest.java +++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/AppTest.java @@ -8,6 +8,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import tdt4140.gr1800.app.doc.IDocumentStorage; + public class AppTest { private App app; diff --git a/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-route.gpx b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-route.gpx index e6ce496..a006258 100644 --- a/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-route.gpx +++ b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-route.gpx @@ -6,6 +6,10 @@ xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"> +<metadata> + <bounds minlat="51.396017" minlon="4.498043" maxlat="51.430402" maxlon="4.556108"/> +</metadata> + <wpt lat="51.39709" lon="4.501519"> <name>START</name> </wpt> diff --git a/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-track.gpx b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-track.gpx index 279b657..755f740 100644 --- a/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-track.gpx +++ b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/Achterbroek-track.gpx @@ -6,6 +6,10 @@ xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"> +<metadata> + <bounds minlat="51.396017" minlon="4.498043" maxlat="51.430402" maxlon="4.556108"/> +</metadata> + <wpt lat="51.39709" lon="4.501519"> <name>START</name> </wpt> diff --git a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java index 8575711..e7566ea 100644 --- a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java +++ b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FileMenuController.java @@ -4,40 +4,26 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import javafx.stage.FileChooser; -import tdt4140.gr1800.app.core.IDocumentImporter; -import tdt4140.gr1800.app.core.IDocumentStorage; +import tdt4140.gr1800.app.doc.IDocumentImporter; +import tdt4140.gr1800.app.doc.IDocumentStorage; public class FileMenuController { - private IDocumentStorage<File> documentStorage; + IDocumentStorage<File> documentStorage; public void setDocumentStorage(IDocumentStorage<File> documentStorage) { this.documentStorage = documentStorage; } - - private Consumer<IDocumentStorage<File>> onDocumentChanged; - - public void setOnDocumentChanged(Consumer<IDocumentStorage<File>> onDocumentChanged) { - this.onDocumentChanged = onDocumentChanged; - } @FXML public void handleNewAction() { documentStorage.newDocument(); - fireDocumentChanged(); - } - - private void fireDocumentChanged() { - if (onDocumentChanged != null) { - onDocumentChanged.accept(documentStorage); - } } private List<File> recentFiles = new ArrayList<File>(); @@ -59,7 +45,7 @@ public class FileMenuController { private FileChooser fileChooser; - protected FileChooser getFileChooser() { + FileChooser getFileChooser() { if (fileChooser == null) { fileChooser = new FileChooser(); } @@ -80,13 +66,16 @@ public class FileMenuController { selection = fileChooser.showOpenDialog(null); } if (selection != null) { - try { - documentStorage.openDocument(selection); - updateRecentMenu(selection); - fireDocumentChanged(); - } catch (IOException e) { - // TODO - } + handleOpenAction(selection); + } + } + + void handleOpenAction(File selection) { + try { + documentStorage.openDocument(selection); + updateRecentMenu(selection); + } catch (IOException e) { + // TODO } } @@ -103,6 +92,10 @@ public class FileMenuController { public void handleSaveAsAction() { FileChooser fileChooser = getFileChooser(); File selection = fileChooser.showSaveDialog(null); + handleSaveAsAction(selection); + } + + void handleSaveAsAction(File selection) { File oldStorage = documentStorage.getDocumentLocation(); try { documentStorage.setDocumentLocation(selection); @@ -117,6 +110,10 @@ public class FileMenuController { public void handleSaveCopyAsAction() { FileChooser fileChooser = getFileChooser(); File selection = fileChooser.showSaveDialog(null); + handleSaveCopyAsAction(selection); + } + + void handleSaveCopyAsAction(File selection) { File oldStorage = documentStorage.getDocumentLocation(); try { documentStorage.setDocumentLocation(selection); @@ -135,6 +132,10 @@ public class FileMenuController { // String path = selection.getPath(); // int pos = path.lastIndexOf('.'); // String ext = (pos > 0 ? path.substring(pos + 1) : null); + handleImportAction(selection); + } + + void handleImportAction(File selection) { for (IDocumentImporter<File> importer : documentStorage.getDocumentImporters()) { try { importer.importDocument(selection); diff --git a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FxAppController.java b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FxAppController.java index 20c6562..060a5a4 100644 --- a/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FxAppController.java +++ b/tdt4140-gr1800/app.ui/src/main/java/tdt4140/gr1800/app/ui/FxAppController.java @@ -1,5 +1,7 @@ package tdt4140.gr1800.app.ui; +import java.io.File; +import java.util.Collection; import java.util.Iterator; import fxmapcontrol.Location; @@ -7,27 +9,29 @@ import fxmapcontrol.MapBase; import fxmapcontrol.MapItemsControl; import fxmapcontrol.MapNode; import fxmapcontrol.MapTileLayer; +import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.Slider; import tdt4140.gr1800.app.core.App; import tdt4140.gr1800.app.core.GeoLocated; import tdt4140.gr1800.app.core.GeoLocations; -import tdt4140.gr1800.app.core.IGeoLocationsListener; import tdt4140.gr1800.app.core.LatLong; +import tdt4140.gr1800.app.doc.IDocumentListener; +import tdt4140.gr1800.app.doc.IDocumentStorage; -public class FxAppController implements IGeoLocationsListener { +public class FxAppController implements IDocumentListener<Collection<GeoLocations>, File> { @FXML - private FileMenuController fileMenuController; + FileMenuController fileMenuController; @FXML private ComboBox<String> geoLocationsSelector; @FXML - private MapBase mapView; + MapBase mapView; - private MapItemsControl<MapNode> markersParent; + MapItemsControl<MapNode> markersParent; @FXML private Slider zoomSlider; @@ -37,8 +41,9 @@ public class FxAppController implements IGeoLocationsListener { @FXML public void initialize() { app = new App(); - fileMenuController.setDocumentStorage(app.getDocumentStorage()); - fileMenuController.setOnDocumentChanged(documentStorage -> initMapMarkers()); + IDocumentStorage<File> documentStorage = app.getDocumentStorage(); + fileMenuController.setDocumentStorage(documentStorage); + documentStorage.addDocumentStorageListener(this); geoLocationsSelector.getSelectionModel().selectedItemProperty().addListener((stringProperty, oldValue, newValue) -> updateGeoLocations()); @@ -48,10 +53,24 @@ public class FxAppController implements IGeoLocationsListener { }); markersParent = new MapItemsControl<MapNode>(); mapView.getChildren().add(markersParent); - - app.addGeoLocationsListener(this); } + // + + @Override + public void documentLocationChanged(File documentLocation, File oldDocumentLocation) { + } + @Override + public void documentChanged(Collection<GeoLocations> document, Collection<GeoLocations> oldDocument) { + if (Platform.isFxApplicationThread()) { + initMapMarkers(); + } else { + Platform.runLater(() -> initMapMarkers()); + } + } + + // + private Object updateGeoLocations() { return null; } @@ -100,9 +119,4 @@ public class FxAppController implements IGeoLocationsListener { } return new LatLong(latSum / num, lonSum / num); } - - @Override - public void geoLocationsUpdated(GeoLocations geoLocations) { - initMapMarkers(); - } } diff --git a/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml b/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml index 9515c49..5de3493 100644 --- a/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml +++ b/tdt4140-gr1800/app.ui/src/main/resources/tdt4140/gr1800/app/ui/FileMenu.fxml @@ -7,14 +7,14 @@ <Menu xmlns:fx="http://javafx.com/fxml" text="File" fx:controller="tdt4140.gr1800.app.ui.FileMenuController"> <items> - <MenuItem text="New" onAction="#handleNewAction"/> - <MenuItem text="Open..." onAction="#handleOpenAction"/> + <MenuItem text="New" accelerator="Meta+N" onAction="#handleNewAction"/> + <MenuItem text="Open..." accelerator="Meta+O" onAction="#handleOpenAction"/> <Menu fx:id="recentMenu" text="Open Recent"/> <SeparatorMenuItem/> - <MenuItem text="Save" onAction="#handleSaveAction"/> - <MenuItem text="Save As..." onAction="#handleSaveAsAction"/> - <MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/> + <MenuItem text="Save" accelerator="Meta+S" onAction="#handleSaveAction"/> + <MenuItem text="Save As..." onAction="#handleSaveAsAction"/> + <MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/> <SeparatorMenuItem/> - <MenuItem text="Import..." onAction="#handleImportAction"/> + <MenuItem text="Import..." onAction="#handleImportAction"/> </items> </Menu> diff --git a/tdt4140-gr1800/app.ui/src/test/java/tdt4140/gr1800/app/ui/FxAppTest.java b/tdt4140-gr1800/app.ui/src/test/java/tdt4140/gr1800/app/ui/FxAppTest.java index 5bded2b..b31cb41 100644 --- a/tdt4140-gr1800/app.ui/src/test/java/tdt4140/gr1800/app/ui/FxAppTest.java +++ b/tdt4140-gr1800/app.ui/src/test/java/tdt4140/gr1800/app/ui/FxAppTest.java @@ -1,16 +1,37 @@ package tdt4140.gr1800.app.ui; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.testfx.framework.junit.ApplicationTest; +import org.testfx.util.WaitForAsyncUtils; import fxmapcontrol.MapBase; +import fxmapcontrol.MapItemsControl; +import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.ComboBox; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyCodeCombination; +import javafx.scene.input.KeyCombination; +import javafx.stage.FileChooser; import javafx.stage.Stage; +import tdt4140.gr1800.app.core.GeoLocations; +import tdt4140.gr1800.app.doc.IDocumentStorageListener; public class FxAppTest extends ApplicationTest { @@ -21,20 +42,122 @@ public class FxAppTest extends ApplicationTest { } } + private FxAppController controller; + @Override public void start(Stage stage) throws Exception { - Parent root = FXMLLoader.load(getClass().getResource("FxApp.fxml")); - + FXMLLoader loader = new FXMLLoader(getClass().getResource("FxApp.fxml")); + Parent root = loader.load(); + this.controller = loader.getController(); Scene scene = new Scene(root); stage.setTitle("JavaFX and Maven"); stage.setScene(scene); stage.show(); } + + private File geoLocationsDotJson = null; + @Before + public void ensureGeoLocationsDotJson() { + openGeoLocationsDotJson(); + WaitForAsyncUtils.waitForFxEvents(); + } + + protected void openGeoLocationsDotJson() { + Assert.assertNotNull(this.controller); + InputStream inputStream = GeoLocations.class.getResourceAsStream("geoLocations.json"); + try { + geoLocationsDotJson = File.createTempFile("geoLocations", ".json"); + geoLocationsDotJson.deleteOnExit(); + Files.copy(inputStream, geoLocationsDotJson.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + Assert.fail(e.getMessage()); + } + try { + controller.fileMenuController.documentStorage.openDocument(geoLocationsDotJson); + } catch (IOException e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testMapExists() { + Node map = lookup("#mapView").query(); + Assert.assertTrue(map instanceof MapBase); + } + + private <T> T getItem(Iterable<?> items, Class<T> clazz, int num) { + for (Object child : items) { + if (clazz.isInstance(child)) { + num--; + if (num <= 0) { + return (T) child; + } + } + } + return null; + } + + private <T> Collection<T> getItems(Iterable<?> items, Class<T> clazz, int count) { + Collection<T> result = new ArrayList<T>(); + for (Object child : items) { + if (clazz.isInstance(child)) { + result.add((T) child); + count--; + if (count <= 0) { + return result; + } + } + } + return null; + } + @Test - public void testMapExists() { - Node map = lookup("#mapView").query(); - Assert.assertTrue(map instanceof MapBase); + public void testMapHasMarkers() { + Assert.assertNotNull(getItems(controller.markersParent.getItems(), MapMarker.class, 4)); + } + + @Test + public void testGeoLocationsSelector() { + Node combo = lookup("#geoLocationsSelector").query(); + Assert.assertTrue(combo instanceof ComboBox); + ObservableList<?> items = ((ComboBox<?>) combo).getItems(); + Assert.assertEquals(2, items.size()); + Assert.assertEquals("1 (2)", items.get(0)); + Assert.assertEquals("2 (2)", items.get(1)); + } + +// @Test + public void testOpenTestDocument() { + try { + InputStream inputStream = GeoLocations.class.getResourceAsStream("geoLocations.json"); + File tempFile = File.createTempFile("geoLocations", ".json"); + tempFile.deleteOnExit(); + Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + FileChooser fileChooser = controller.fileMenuController.getFileChooser(); + fileChooser.setInitialDirectory(tempFile.getParentFile()); +// fileChooser.setInitialFileName(tempFile.getName()); + KeyCodeCombination openKeys = new KeyCodeCombination(KeyCode.O, KeyCombination.META_DOWN); + push(openKeys); + sleep(1, TimeUnit.SECONDS); + String name = tempFile.getName().substring(0, 1); + for (int i = 0; i < name.length(); i++) { + push(KeyCode.getKeyCode(String.valueOf(name.charAt(i)).toUpperCase())); + } + final File[] documentLocations = new File[1]; + controller.fileMenuController.documentStorage.addDocumentStorageListener(new IDocumentStorageListener<File>() { + @Override + public void documentLocationChanged(File documentLocation, File oldDocumentLocation) { + documentLocations[0] = documentLocation; + } + }); + push(KeyCode.ENTER); + sleep(1, TimeUnit.SECONDS); + Assert.assertEquals(tempFile.getCanonicalPath(), String.valueOf(documentLocations[0])); + } catch (IOException e) { + System.out.println(e); + Assert.fail(e.getMessage()); + } } } -- GitLab