From aa3abaece3b2917a6959d5da1ba8af8ea52e2dbe Mon Sep 17 00:00:00 2001 From: Hallvard Traetteberg <hal@ntnu.no> Date: Sun, 25 Aug 2019 23:39:31 +0200 Subject: [PATCH] Fjernet generell File-meny (#4) --- .../doc/AbstractDocumentStorageImpl.java | 154 ------------- .../java/fxutil/doc/FileMenuController.java | 216 ------------------ .../java/fxutil/doc/IDocumentImporter.java | 21 -- .../java/fxutil/doc/IDocumentListener.java | 20 -- .../main/java/fxutil/doc/IDocumentLoader.java | 23 -- .../java/fxutil/doc/IDocumentPersistence.java | 4 - .../main/java/fxutil/doc/IDocumentSaver.java | 21 -- .../java/fxutil/doc/IDocumentStorage.java | 68 ------ .../fxutil/doc/IDocumentStorageListener.java | 19 -- .../fxutil/doc/SimpleJsonFileStorageImpl.java | 68 ------ .../java/simpleex/ui/FxAppController.java | 104 +++++++-- .../main/java/simpleex/ui/LatLongsApp.java | 101 -------- .../java/simpleex/ui/LatLongsStorage.java | 28 --- .../main/resources/simpleex/ui/FileMenu.fxml | 23 -- .../src/main/resources/simpleex/ui/FxApp.fxml | 7 +- .../test/resources/simpleex/ui/FileMenu.fxml | 23 -- .../src/test/resources/simpleex/ui/FxApp.fxml | 7 +- 17 files changed, 96 insertions(+), 811 deletions(-) delete mode 100644 simpleexample/src/main/java/fxutil/doc/AbstractDocumentStorageImpl.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/FileMenuController.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentImporter.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentListener.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentLoader.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentPersistence.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentSaver.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentStorage.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/IDocumentStorageListener.java delete mode 100644 simpleexample/src/main/java/fxutil/doc/SimpleJsonFileStorageImpl.java delete mode 100644 simpleexample/src/main/java/simpleex/ui/LatLongsApp.java delete mode 100644 simpleexample/src/main/java/simpleex/ui/LatLongsStorage.java delete mode 100644 simpleexample/src/main/resources/simpleex/ui/FileMenu.fxml delete mode 100644 simpleexample/src/test/resources/simpleex/ui/FileMenu.fxml diff --git a/simpleexample/src/main/java/fxutil/doc/AbstractDocumentStorageImpl.java b/simpleexample/src/main/java/fxutil/doc/AbstractDocumentStorageImpl.java deleted file mode 100644 index 94fa81a..0000000 --- a/simpleexample/src/main/java/fxutil/doc/AbstractDocumentStorageImpl.java +++ /dev/null @@ -1,154 +0,0 @@ -package fxutil.doc; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; - -/** - * Incomplete implementation of **IDocumentStorage**, to simplify implementing ones for specific - * document and location types. The main missing methods are for getting and setting the current - * document, creating an empty one and creating an **InputStream** from a location. - * - * @author hal - * - * @param <D> the document type - * @param <L> the location type - */ -public abstract class AbstractDocumentStorageImpl<D, L> -implements IDocumentStorage<L>, IDocumentPersistence<D, L> { - - private L documentLocation = null; - - @Override - public L getDocumentLocation() { - return documentLocation; - } - - @Override - public void setDocumentLocation(final L documentLocation) { - final L oldDocumentLocation = this.documentLocation; - this.documentLocation = documentLocation; - fireDocumentLocationChanged(oldDocumentLocation); - } - - protected void setDocumentAndLocation(final D document, final L documentLocation) { - setDocument(document); - setDocumentLocation(documentLocation); - } - - /** - * Returns the current document. - * - * @return the current document - */ - protected abstract D getDocument(); - - /** - * Sets the current document. - * - * @param document the new document - */ - protected abstract void setDocument(D document); - - // - - private final Collection<IDocumentStorageListener<L>> documentListeners = - new ArrayList<IDocumentStorageListener<L>>(); - - @Override - public void addDocumentStorageListener( - final IDocumentStorageListener<L> documentStorageListener) { - documentListeners.add(documentStorageListener); - } - - @Override - public void removeDocumentStorageListener( - final IDocumentStorageListener<L> documentStorageListener) { - documentListeners.remove(documentStorageListener); - } - - protected void fireDocumentLocationChanged(final L oldDocumentLocation) { - for (final IDocumentStorageListener<L> documentStorageListener : documentListeners) { - documentStorageListener.documentLocationChanged(documentLocation, oldDocumentLocation); - } - } - - protected void fireDocumentChanged(final D oldDocument) { - for (final IDocumentStorageListener<L> documentListener : documentListeners) { - if (documentListener instanceof IDocumentListener) { - ((IDocumentListener<D, L>) documentListener).documentChanged(getDocument(), oldDocument); - } - } - } - - /** - * Creates a new and empty document. - * - * @return - */ - protected abstract D createDocument(); - - @Override - public void newDocument() { - setDocumentAndLocation(createDocument(), null); - } - - /** - * Creates an InputStream from a location. - * - * @param location the location - * @return the location's InputStream - * @throws IOException when the InputStream cannot be created - */ - protected abstract InputStream toInputStream(L location) throws IOException; - - protected InputStream toInputStream(final File location) throws IOException { - return new FileInputStream(location); - } - - protected InputStream toInputStream(final URL location) throws IOException { - return location.openStream(); - } - - protected InputStream toInputStream(final URI location) throws IOException { - return toInputStream(location.toURL()); - } - - @Override - public void openDocument(final L storage) throws IOException { - try (InputStream input = toInputStream(storage)) { - setDocumentAndLocation(loadDocument(input), storage); - } catch (final Exception e) { - throw new IOException(e); - } - } - - @Override - public void saveDocument() throws IOException { - try { - saveDocument(getDocument(), getDocumentLocation()); - } catch (final Exception e) { - throw new IOException(e); - } - } - - public void saveDocumentAs(final L documentLocation) throws IOException { - final L oldDocumentLocation = getDocumentLocation(); - setDocumentLocation(documentLocation); - try { - saveDocument(); - } catch (final IOException e) { - setDocumentLocation(oldDocumentLocation); - throw e; - } - } - - public void saveCopyAs(final L documentLocation) throws Exception { - saveDocument(getDocument(), documentLocation); - } -} diff --git a/simpleexample/src/main/java/fxutil/doc/FileMenuController.java b/simpleexample/src/main/java/fxutil/doc/FileMenuController.java deleted file mode 100644 index afe841c..0000000 --- a/simpleexample/src/main/java/fxutil/doc/FileMenuController.java +++ /dev/null @@ -1,216 +0,0 @@ -package fxutil.doc; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Menu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.TextInputDialog; -import javafx.stage.FileChooser; - -public class FileMenuController { - - private IDocumentStorage<File> documentStorage; - - public void setDocumentStorage(final IDocumentStorage<File> documentStorage) { - this.documentStorage = documentStorage; - if (importMenu != null) { - importMenu.setDisable(documentStorage.getDocumentImporters().isEmpty()); - } - } - - @FXML - public void handleNewAction() { - documentStorage.newDocument(); - } - - private final List<File> recentFiles = new ArrayList<File>(); - - @FXML - private Menu recentMenu; - - protected void updateRecentMenu(final File file) { - recentFiles.remove(file); - recentFiles.add(0, file); - recentMenu.getItems().clear(); - for (final File recentFile : recentFiles) { - final MenuItem menuItem = new MenuItem(); - menuItem.setText(recentFile.toString()); - menuItem.setOnAction(event -> handleOpenAction(event)); - recentMenu.getItems().add(menuItem); - } - } - - private FileChooser fileChooser; - - FileChooser getFileChooser() { - if (fileChooser == null) { - fileChooser = new FileChooser(); - } - return fileChooser; - } - - @FXML - public void handleOpenAction(final ActionEvent event) { - File selection = null; - if (event.getSource() instanceof MenuItem) { - final File file = new File(((MenuItem) event.getSource()).getText()); - if (file.exists()) { - selection = file; - } - } - if (selection == null) { - final FileChooser fileChooser = getFileChooser(); - selection = fileChooser.showOpenDialog(null); - } - if (selection != null) { - handleOpenAction(selection); - } - } - - void handleOpenAction(final File selection) { - try { - documentStorage.openDocument(selection); - updateRecentMenu(selection); - } catch (final IOException e) { - showExceptionDialog("Oops, problem when opening " + selection, e); - } - } - - private void showExceptionDialog(final String message) { - final Alert alert = new Alert(AlertType.ERROR, message, ButtonType.CLOSE); - alert.showAndWait(); - } - - private void showExceptionDialog(final String message, final Exception e) { - showExceptionDialog(message + ": " + e.getLocalizedMessage()); - } - - private void showSaveExceptionDialog(final File location, final Exception e) { - showExceptionDialog("Oops, problem saving to " + location, e); - } - - @FXML - public void handleSaveAction() { - if (documentStorage.getDocumentLocation() == null) { - handleSaveAsAction(); - } else { - try { - documentStorage.saveDocument(); - } catch (final IOException e) { - showSaveExceptionDialog(documentStorage.getDocumentLocation(), e); - } - } - } - - @FXML - public void handleSaveAsAction() { - final FileChooser fileChooser = getFileChooser(); - final File selection = fileChooser.showSaveDialog(null); - handleSaveAsAction(selection); - } - - void handleSaveAsAction(final File selection) { - final File oldStorage = documentStorage.getDocumentLocation(); - try { - documentStorage.setDocumentLocation(selection); - documentStorage.saveDocument(); - } catch (final IOException e) { - showSaveExceptionDialog(documentStorage.getDocumentLocation(), e); - documentStorage.setDocumentLocation(oldStorage); - } - } - - @FXML - public void handleSaveCopyAsAction() { - final FileChooser fileChooser = getFileChooser(); - final File selection = fileChooser.showSaveDialog(null); - handleSaveCopyAsAction(selection); - } - - void handleSaveCopyAsAction(final File selection) { - final File oldStorage = documentStorage.getDocumentLocation(); - try { - documentStorage.setDocumentLocation(selection); - documentStorage.saveDocument(); - } catch (final IOException e) { - showSaveExceptionDialog(selection, e); - } finally { - documentStorage.setDocumentLocation(oldStorage); - } - } - - @FXML - private Menu importMenu; - - @FXML - public void handleFileImportAction() { - final FileChooser fileChooser = getFileChooser(); - final File selection = fileChooser.showOpenDialog(null); - // String path = selection.getPath(); - // int pos = path.lastIndexOf('.'); - // String ext = (pos > 0 ? path.substring(pos + 1) : null); - handleFileImportAction(selection); - } - - void handleFileImportAction(final File selection) { - for (final IDocumentImporter importer : documentStorage.getDocumentImporters()) { - try (InputStream input = new FileInputStream(selection)) { - importer.importDocument(input); - break; - } catch (final Exception e) { - } - } - } - - private TextInputDialog inputDialog; - - @FXML - public void handleUrlImportAction() { - if (inputDialog == null) { - inputDialog = new TextInputDialog(); - } - inputDialog.setTitle("Import from URL"); - inputDialog.setHeaderText("Enter URL to import from"); - inputDialog.setContentText("Enter URL: "); - // https://developer.garmin.com/downloads/connect-api/sample_file.gpx - while (true) { - final Optional<String> result = inputDialog.showAndWait(); - if (!result.isPresent()) { - break; - } - try { - if (handleUrlImportAction(new URL(result.get()))) { - break; - } - inputDialog.setHeaderText("Problems reading it..."); - inputDialog.setContentText("Enter another URL: "); - } catch (final MalformedURLException e1) { - inputDialog.setContentText("Enter a valid URL: "); - } - } - } - - boolean handleUrlImportAction(final URL url) { - for (final IDocumentImporter importer : documentStorage.getDocumentImporters()) { - try (InputStream input = url.openStream()) { - importer.importDocument(input); - return true; - } catch (final Exception e) { - System.err.println(e.getMessage()); - } - } - return false; - } -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentImporter.java b/simpleexample/src/main/java/fxutil/doc/IDocumentImporter.java deleted file mode 100644 index 1477a39..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentImporter.java +++ /dev/null @@ -1,21 +0,0 @@ -package fxutil.doc; - -import java.io.IOException; -import java.io.InputStream; - -/** - * An interface with a method for importing domain data from a location. The main use is supporting - * an **import** action in a **File** menu. - * - * @author hal - * - */ -public interface IDocumentImporter { - /** - * Loads a document from the input stream and sets it as the current document. - * - * @param inputStream the document to import - * @throws IOException when the document cannot imported - */ - public void importDocument(InputStream inputStream) throws IOException; -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentListener.java b/simpleexample/src/main/java/fxutil/doc/IDocumentListener.java deleted file mode 100644 index c8c3079..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package fxutil.doc; - -/** - * Listener interface for the (contents of) the (current) document of an IDocumentStorage, e.g. when - * an **open** action is performed. - * - * @author hal - * - * @param <D> the document type - * @param <L> the location type - */ -public interface IDocumentListener<D, L> extends IDocumentStorageListener<L> { - /** - * Notifies that the current document has changed. - * - * @param document the new document - * @param oldDocument the previous document - */ - public void documentChanged(D document, D oldDocument); -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentLoader.java b/simpleexample/src/main/java/fxutil/doc/IDocumentLoader.java deleted file mode 100644 index 5862261..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentLoader.java +++ /dev/null @@ -1,23 +0,0 @@ -package fxutil.doc; - -import java.io.InputStream; - -/** - * An interface with a method for loading and returning a document (domain data container) from an - * InputStream. This allows various ways of loading or importing domain data, with different sources - * and formats. - * - * @author hal - * - * @param <D> the document type - */ -public interface IDocumentLoader<D> { - /** - * Loads and returns a new document from an InputStream - * - * @param inputStream the InputStream to load from - * @return the loaded document - * @throws Exception when the document couldn't be loaded - */ - public D loadDocument(InputStream inputStream) throws Exception; -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentPersistence.java b/simpleexample/src/main/java/fxutil/doc/IDocumentPersistence.java deleted file mode 100644 index d53b8dd..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentPersistence.java +++ /dev/null @@ -1,4 +0,0 @@ -package fxutil.doc; - -public interface IDocumentPersistence<D, L> extends IDocumentLoader<D>, IDocumentSaver<D, L> { -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentSaver.java b/simpleexample/src/main/java/fxutil/doc/IDocumentSaver.java deleted file mode 100644 index 9bfa7be..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentSaver.java +++ /dev/null @@ -1,21 +0,0 @@ -package fxutil.doc; - -/** - * An interface with a method for saving a document (domain data container) to a location. This - * allows various ways of saving or exporting domain data, to different locations and formats. - * - * @author hal - * - * @param <D> the document type - * @param <L> the location type - */ -public interface IDocumentSaver<D, L> { - /** - * Saves the provided document to the provided location - * - * @param document the document to save - * @param documentLocation the location to save to - * @throws Exception when the document couldn't be saved - */ - public void saveDocument(D document, L documentLocation) throws Exception; -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentStorage.java b/simpleexample/src/main/java/fxutil/doc/IDocumentStorage.java deleted file mode 100644 index 5eecaa0..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentStorage.java +++ /dev/null @@ -1,68 +0,0 @@ -package fxutil.doc; - -import java.io.IOException; -import java.util.Collection; - -/** - * An interface with the methods necessary for supporting the standard File menu actions. The class - * representing the document (domain data container) is implicit in the implementation of this - * interface. The interface includes methods for getting and setting the location and creating, - * opening and saving the (current) document. - * - * @author hal - * - * @param <L> The type of the location, typically java.io.File. - */ -public interface IDocumentStorage<L> { - /** - * Returns the current location (of the current document). - * - * @return the current location - */ - public L getDocumentLocation(); - - /** - * Sets the current location (of the current document), can be used by a save-as action. - * - * @param documentLocation the new document location - */ - public void setDocumentLocation(L documentLocation); - - /** - * Adds an IDocumentStorageListener that will be notified when the current location changes. - * - * @param documentStorageListener the listener to add - */ - - public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); - - /** - * Removes an IDocumentStorageListener. - * - * @param documentStorageListener the listener to remove - */ - public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); - - /** - * Creates a new documents and sets it as the current one, can be used by a new action. - */ - public void newDocument(); - - /** - * Loads a documents from the provided location and sets it as the current one, can be used by an - * open action. - */ - public void openDocument(L documentLocation) throws IOException; - - /** - * Saves the current document (to the current location), can be used by a save action. - */ - public void saveDocument() throws IOException; - - /** - * Returns the set of IDocumentImporters, can be used by an import action. - * - * @return - */ - public Collection<IDocumentImporter> getDocumentImporters(); -} diff --git a/simpleexample/src/main/java/fxutil/doc/IDocumentStorageListener.java b/simpleexample/src/main/java/fxutil/doc/IDocumentStorageListener.java deleted file mode 100644 index c5d3f0f..0000000 --- a/simpleexample/src/main/java/fxutil/doc/IDocumentStorageListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package fxutil.doc; - -/** - * Listener interface for the (current) location of the (current) document of an IDocumentStorage, - * e.g. when a **save-as** action is performed. - * - * @author hal - * - * @param <L> the document location type - */ -public interface IDocumentStorageListener<L> { - /** - * Notifies that the current document location has changed. - * - * @param documentLocation the new document location - * @param oldDocumentLocation the previous document location - */ - public void documentLocationChanged(L documentLocation, L oldDocumentLocation); -} diff --git a/simpleexample/src/main/java/fxutil/doc/SimpleJsonFileStorageImpl.java b/simpleexample/src/main/java/fxutil/doc/SimpleJsonFileStorageImpl.java deleted file mode 100644 index b081765..0000000 --- a/simpleexample/src/main/java/fxutil/doc/SimpleJsonFileStorageImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package fxutil.doc; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collection; -import java.util.Collections; - -public abstract class SimpleJsonFileStorageImpl<T> extends AbstractDocumentStorageImpl<T, File> -implements IDocumentStorage<File> { - - private T document; - - private final ObjectMapper objectMapper; - - private final Class<T> documentClass; - - public SimpleJsonFileStorageImpl(final Class<T> documentClass) { - this.documentClass = documentClass; - final SimpleModule module = new SimpleModule(); - configureJacksonModule(module); - objectMapper = new ObjectMapper(); - objectMapper.registerModule(module); - } - - protected abstract void configureJacksonModule(final SimpleModule module); - - @Override - public T loadDocument(final InputStream inputStream) throws Exception { - return objectMapper.readValue(inputStream, documentClass); - } - - @Override - public void saveDocument(final T document, final File documentLocation) throws Exception { - try (OutputStream outputStream = new FileOutputStream(documentLocation, false)) { - objectMapper.writeValue(outputStream, document); - } - } - - @Override - public Collection<IDocumentImporter> getDocumentImporters() { - return Collections.emptyList(); - } - - @Override - public T getDocument() { - return document; - } - - @Override - public void setDocument(final T document) { - final T oldDocument = this.document; - this.document = document; - fireDocumentChanged(oldDocument); - } - - @Override - protected T createDocument() { - try { - return documentClass.getDeclaredConstructor().newInstance(); - } catch (final Exception e) { - throw new RuntimeException("Exception when instantiating " + documentClass, e); - } - } -} diff --git a/simpleexample/src/main/java/simpleex/ui/FxAppController.java b/simpleexample/src/main/java/simpleex/ui/FxAppController.java index 9750644..1795682 100644 --- a/simpleexample/src/main/java/simpleex/ui/FxAppController.java +++ b/simpleexample/src/main/java/simpleex/ui/FxAppController.java @@ -1,40 +1,52 @@ package simpleex.ui; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; import fxmapcontrol.Location; import fxmapcontrol.MapBase; import fxmapcontrol.MapItemsControl; import fxmapcontrol.MapNode; import fxmapcontrol.MapProjection; -import fxutil.doc.FileMenuController; -import fxutil.doc.IDocumentListener; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.Optional; import javafx.collections.FXCollections; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.geometry.Point2D; import javafx.scene.Node; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; import javafx.scene.control.ListView; import javafx.scene.control.Slider; +import javafx.stage.FileChooser; import simpleex.core.LatLong; import simpleex.core.LatLongs; +import simpleex.json.LatLongDeserializer; +import simpleex.json.LatLongSerializer; +import simpleex.json.LatLongsDeserializer; +import simpleex.json.LatLongsSerializer; -public class FxAppController extends FileMenuController - implements IDocumentListener<LatLongs, File> { +public class FxAppController { - private final LatLongsStorage latLongsStorage; + private LatLongs latLongs; public FxAppController() { - latLongsStorage = new LatLongsStorage(); - latLongsStorage.addDocumentStorageListener(this); + latLongs = new LatLongs(); } public LatLongs getLatLongs() { - return latLongsStorage.getDocument(); + return latLongs; } // to make it testable public void setLatLongs(final LatLongs latLongs) { - latLongsStorage.setDocument(latLongs); + this.latLongs = latLongs; updateLocationViewList(0); } @@ -57,12 +69,10 @@ public class FxAppController extends FileMenuController @FXML private void initialize() { - // fileMenuController. - setDocumentStorage(latLongsStorage); // map stuff // mapView.getChildren().add(MapTileLayer.getOpenStreetMapLayer()); zoomSlider.valueProperty() - .addListener((prop, oldValue, newValue) -> mapView.setZoomLevel(zoomSlider.getValue())); + .addListener((prop, oldValue, newValue) -> mapView.setZoomLevel(zoomSlider.getValue())); zoomSlider.setValue(8); markersParent = new MapItemsControl<MapNode>(); mapView.getChildren().add(markersParent); @@ -72,7 +82,7 @@ public class FxAppController extends FileMenuController draggableMarkerController = new DraggableNodeController(Optional.of(this::handleMarkerDragged)); // the location list locationListView.getSelectionModel().selectedIndexProperty() - .addListener((prop, oldValue, newValue) -> updateMapMarker(true)); + .addListener((prop, oldValue, newValue) -> updateMapMarker(true)); } private void handleMapDragged(final Node node, final double dx, final double dy) { @@ -155,14 +165,68 @@ public class FxAppController extends FileMenuController } } - // IDocumentListener + // File menu items - @Override - public void documentLocationChanged(final File documentLocation, - final File oldDocumentLocation) {} + private FileChooser fileChooser; - @Override - public void documentChanged(final LatLongs document, final LatLongs oldDocument) { - updateLocationViewList(0); + private FileChooser getFileChooser() { + if (fileChooser == null) { + fileChooser = new FileChooser(); + } + return fileChooser; + } + + @FXML + void handleOpenAction(final ActionEvent event) { + final FileChooser fileChooser = getFileChooser(); + final File selection = fileChooser.showOpenDialog(null); + if (selection != null) { + try (InputStream input = new FileInputStream(selection) ){ + setLatLongs(getObjectMapper().readValue(input, LatLongs.class)); + } catch (final IOException e) { + showExceptionDialog("Oops, problem when opening " + selection, e); + } + } + } + + private ObjectMapper objectMapper; + + public ObjectMapper getObjectMapper() { + if (objectMapper == null) { + final SimpleModule module = new SimpleModule(); + module.addSerializer(LatLong.class, new LatLongSerializer()); + module.addSerializer(LatLongs.class, new LatLongsSerializer()); + module.addDeserializer(LatLong.class, new LatLongDeserializer()); + module.addDeserializer(LatLongs.class, new LatLongsDeserializer()); + objectMapper = new ObjectMapper(); + objectMapper.registerModule(module); + } + return objectMapper; + } + + private void showExceptionDialog(final String message) { + final Alert alert = new Alert(AlertType.ERROR, message, ButtonType.CLOSE); + alert.showAndWait(); + } + + private void showExceptionDialog(final String message, final Exception e) { + showExceptionDialog(message + ": " + e.getLocalizedMessage()); + } + + private void showSaveExceptionDialog(final File location, final Exception e) { + showExceptionDialog("Oops, problem saving to " + location, e); + } + + @FXML + void handleSaveAction() { + final FileChooser fileChooser = getFileChooser(); + final File selection = fileChooser.showSaveDialog(null); + if (selection != null ) { + try (OutputStream outputStream = new FileOutputStream(selection, false)) { + getObjectMapper().writeValue(outputStream, getLatLongs()); + } catch (final IOException e) { + showSaveExceptionDialog(selection, e); + } + } } } diff --git a/simpleexample/src/main/java/simpleex/ui/LatLongsApp.java b/simpleexample/src/main/java/simpleex/ui/LatLongsApp.java deleted file mode 100644 index df7517b..0000000 --- a/simpleexample/src/main/java/simpleex/ui/LatLongsApp.java +++ /dev/null @@ -1,101 +0,0 @@ -package simpleex.ui; - -import fxutil.doc.AbstractDocumentStorageImpl; -import fxutil.doc.IDocumentImporter; -import fxutil.doc.IDocumentLoader; -import fxutil.doc.IDocumentPersistence; -import fxutil.doc.IDocumentStorage; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.stream.Collectors; -import simpleex.core.LatLongs; - -public class LatLongsApp { - - private LatLongs latLongs = null; - - private final IDocumentPersistence<LatLongs, File> documentPersistence = - new IDocumentPersistence<LatLongs, File>() { - - @Override - public LatLongs loadDocument(final InputStream inputStream) throws Exception { - // TODO - return null; - } - - @Override - public void saveDocument(final LatLongs document, final File documentLocation) - throws Exception { - try (OutputStream output = new FileOutputStream(documentLocation)) { - // TODO - } - } - }; - - private final AbstractDocumentStorageImpl<LatLongs, File> documentStorage = - new AbstractDocumentStorageImpl<LatLongs, File>() { - - @Override - protected LatLongs getDocument() { - return latLongs; - } - - @Override - protected void setDocument(final LatLongs document) { - final LatLongs oldDocument = getDocument(); - LatLongsApp.this.latLongs = document; - fireDocumentChanged(oldDocument); - } - - @Override - protected LatLongs createDocument() { - return new LatLongs(); - } - - @Override - protected InputStream toInputStream(final File storage) throws IOException { - return new FileInputStream(storage); - } - - @Override - public LatLongs loadDocument(final InputStream inputStream) throws Exception { - return documentPersistence.loadDocument(inputStream); - } - - @Override - public void saveDocument(final LatLongs document, final File documentLocation) - throws Exception { - documentPersistence.saveDocument(document, documentLocation); - } - - @Override - public Collection<IDocumentImporter> getDocumentImporters() { - return documentLoaders.stream().map(loader -> new IDocumentImporter() { - @Override - public void importDocument(final InputStream inputStream) throws IOException { - try { - setDocumentAndLocation(loader.loadDocument(inputStream), null); - } catch (final Exception e) { - throw new IOException(e); - } - } - }).collect(Collectors.toList()); - } - }; - - public IDocumentStorage<File> getDocumentStorage() { - return documentStorage; - } - - private final Collection<IDocumentLoader<LatLongs>> documentLoaders = Arrays.asList(); - - public Iterable<IDocumentLoader<LatLongs>> getDocumentLoaders() { - return documentLoaders; - } -} diff --git a/simpleexample/src/main/java/simpleex/ui/LatLongsStorage.java b/simpleexample/src/main/java/simpleex/ui/LatLongsStorage.java deleted file mode 100644 index ede6de2..0000000 --- a/simpleexample/src/main/java/simpleex/ui/LatLongsStorage.java +++ /dev/null @@ -1,28 +0,0 @@ -package simpleex.ui; - -import com.fasterxml.jackson.databind.module.SimpleModule; -import fxutil.doc.IDocumentStorage; -import fxutil.doc.SimpleJsonFileStorageImpl; -import java.io.File; -import simpleex.core.LatLong; -import simpleex.core.LatLongs; -import simpleex.json.LatLongDeserializer; -import simpleex.json.LatLongSerializer; -import simpleex.json.LatLongsDeserializer; -import simpleex.json.LatLongsSerializer; - -public class LatLongsStorage extends SimpleJsonFileStorageImpl<LatLongs> - implements IDocumentStorage<File> { - - public LatLongsStorage() { - super(LatLongs.class); - } - - @Override - protected void configureJacksonModule(final SimpleModule module) { - module.addSerializer(LatLong.class, new LatLongSerializer()); - module.addSerializer(LatLongs.class, new LatLongsSerializer()); - module.addDeserializer(LatLong.class, new LatLongDeserializer()); - module.addDeserializer(LatLongs.class, new LatLongsDeserializer()); - } -} diff --git a/simpleexample/src/main/resources/simpleex/ui/FileMenu.fxml b/simpleexample/src/main/resources/simpleex/ui/FileMenu.fxml deleted file mode 100644 index 61fbe58..0000000 --- a/simpleexample/src/main/resources/simpleex/ui/FileMenu.fxml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?import java.lang.*?> -<?import javafx.scene.control.Menu?> -<?import javafx.scene.control.MenuItem?> -<?import javafx.scene.control.SeparatorMenuItem?> - -<Menu xmlns:fx="http://javafx.com/fxml" text="File" fx:controller="fxutil.doc.FileMenuController"> - <items> - <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" accelerator="Meta+S" onAction="#handleSaveAction"/> - <MenuItem text="Save As..." onAction="#handleSaveAsAction"/> - <MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/> - <SeparatorMenuItem/> - <Menu fx:id="importMenu" text="Import"> - <MenuItem text="File..." onAction="#handleFileImportAction"/> - <MenuItem text="URL..." onAction="#handleUrlImportAction"/> - </Menu> - </items> -</Menu> diff --git a/simpleexample/src/main/resources/simpleex/ui/FxApp.fxml b/simpleexample/src/main/resources/simpleex/ui/FxApp.fxml index a2410dd..01fbe1d 100644 --- a/simpleexample/src/main/resources/simpleex/ui/FxApp.fxml +++ b/simpleexample/src/main/resources/simpleex/ui/FxApp.fxml @@ -24,7 +24,12 @@ <VBox> <MenuBar > <menus> - <fx:include fx:id="fileMenu" source="FileMenu.fxml"/> + <Menu text="File"> + <items> + <MenuItem text="Open..." accelerator="Meta+O" onAction="#handleOpenAction"/> + <MenuItem text="Save" accelerator="Meta+S" onAction="#handleSaveAction"/> + </items> + </Menu> </menus> </MenuBar> </VBox> diff --git a/simpleexample/src/test/resources/simpleex/ui/FileMenu.fxml b/simpleexample/src/test/resources/simpleex/ui/FileMenu.fxml deleted file mode 100644 index 61fbe58..0000000 --- a/simpleexample/src/test/resources/simpleex/ui/FileMenu.fxml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?import java.lang.*?> -<?import javafx.scene.control.Menu?> -<?import javafx.scene.control.MenuItem?> -<?import javafx.scene.control.SeparatorMenuItem?> - -<Menu xmlns:fx="http://javafx.com/fxml" text="File" fx:controller="fxutil.doc.FileMenuController"> - <items> - <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" accelerator="Meta+S" onAction="#handleSaveAction"/> - <MenuItem text="Save As..." onAction="#handleSaveAsAction"/> - <MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/> - <SeparatorMenuItem/> - <Menu fx:id="importMenu" text="Import"> - <MenuItem text="File..." onAction="#handleFileImportAction"/> - <MenuItem text="URL..." onAction="#handleUrlImportAction"/> - </Menu> - </items> -</Menu> diff --git a/simpleexample/src/test/resources/simpleex/ui/FxApp.fxml b/simpleexample/src/test/resources/simpleex/ui/FxApp.fxml index a2410dd..01fbe1d 100644 --- a/simpleexample/src/test/resources/simpleex/ui/FxApp.fxml +++ b/simpleexample/src/test/resources/simpleex/ui/FxApp.fxml @@ -24,7 +24,12 @@ <VBox> <MenuBar > <menus> - <fx:include fx:id="fileMenu" source="FileMenu.fxml"/> + <Menu text="File"> + <items> + <MenuItem text="Open..." accelerator="Meta+O" onAction="#handleOpenAction"/> + <MenuItem text="Save" accelerator="Meta+S" onAction="#handleSaveAction"/> + </items> + </Menu> </menus> </MenuBar> </VBox> -- GitLab