Commit 4e8e8e36 authored by Hallvard Trætteberg's avatar Hallvard Trætteberg
Browse files

Adds File menu and corresponding controller.

parent 453aacfb
package tdt4140.gr1800.app.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
......@@ -17,7 +21,7 @@ public class App {
private Collection<GeoLocations> geoLocations;
public Iterable<String> getGeoLocationNames() {
Collection<String> names = new ArrayList<String>(geoLocations.size());
Collection<String> names = new ArrayList<String>(geoLocations != null ? geoLocations.size() : 0);
if (geoLocations != null) {
for (GeoLocations geoLocations : geoLocations) {
names.add(geoLocations.getName());
......@@ -25,7 +29,7 @@ public class App {
}
return names;
}
public boolean hasGeoLocations(String name) {
if (geoLocations != null) {
for (GeoLocations geoLocations : geoLocations) {
......@@ -47,4 +51,46 @@ public class App {
}
return null;
}
//
private DocumentStorageImpl<Collection<GeoLocations>, File> documentStorage = new DocumentStorageImpl<Collection<GeoLocations>, File>() {
@Override
protected Collection<GeoLocations> getDocument() {
return geoLocations;
}
@Override
protected void setDocument(Collection<GeoLocations> document) {
geoLocations = document;
}
@Override
protected Collection<GeoLocations> createDocument() {
return new ArrayList<GeoLocations>();
}
@Override
protected Collection<GeoLocations> loadDocument(File file) throws IOException {
try {
return geoLocationsLoader.loadLocations(new FileInputStream(file));
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
protected void storeDocument(Collection<GeoLocations> document, File file) throws IOException {
try {
geoLocationsLoader.saveLocations(document, new FileOutputStream(file));
} catch (Exception e) {
throw new IOException(e);
}
}
};
public IDocumentStorage<File> getDocumentStorage() {
return documentStorage;
}
}
package tdt4140.gr1800.app.core;
import java.io.IOException;
public abstract class DocumentStorageImpl<D, L> implements IDocumentStorage<L> {
private L documentLocation;
@Override
public L getDocumentLocation() {
return documentLocation;
}
@Override
public void setDocumentLocation(L documentLocation) {
this.documentLocation = documentLocation;
}
protected abstract D getDocument();
protected abstract void setDocument(D document);
protected abstract D createDocument();
protected abstract D loadDocument(L storage) throws IOException;
protected abstract void storeDocument(D document, L storage) throws IOException;
@Override
public void newDocument() {
setDocument(createDocument());
}
@Override
public void openDocument(L storage) throws IOException {
setDocument(loadDocument(storage));
}
@Override
public void saveDocument() throws IOException {
storeDocument(getDocument(), getDocumentLocation());
}
public void saveDocumentAs(L documentLocation) throws IOException {
setDocumentLocation(documentLocation);
saveDocument();
}
public void saveCopyAs(L documentLocation) throws IOException {
storeDocument(getDocument(), documentLocation);
}
}
package tdt4140.gr1800.app.core;
import java.io.IOException;
public interface IDocumentStorage<L> {
public L getDocumentLocation();
public void setDocumentLocation(L documentLocation);
public void newDocument();
public void openDocument(L documentLocation) throws IOException;
public void saveDocument() throws IOException;
}
package tdt4140.gr1800.app.ui;
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.IDocumentStorage;
public class FileMenuController {
private 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>();
@FXML
private Menu recentMenu;
protected void updateRecentMenu(File file) {
recentFiles.remove(file);
recentFiles.add(0, file);
recentMenu.getItems().clear();
for (File recentFile : recentFiles) {
MenuItem menuItem = new MenuItem();
menuItem.setText(recentFile.toString());
menuItem.setOnAction(event -> handleOpenAction(event));
recentMenu.getItems().add(menuItem);
}
}
private FileChooser fileChooser;
protected FileChooser getFileChooser() {
if (fileChooser == null) {
fileChooser = new FileChooser();
}
return fileChooser;
}
@FXML
public void handleOpenAction(ActionEvent event) {
File selection = null;
if (event.getSource() instanceof MenuItem) {
File file = new File(((MenuItem) event.getSource()).getText());
if (file.exists()) {
selection = file;
}
}
if (selection == null) {
FileChooser fileChooser = getFileChooser();
selection = fileChooser.showOpenDialog(null);
}
if (selection != null) {
try {
documentStorage.openDocument(selection);
updateRecentMenu(selection);
fireDocumentChanged();
} catch (IOException e) {
// TODO
}
}
}
@FXML
public void handleSaveAction() {
try {
documentStorage.saveDocument();
} catch (IOException e) {
// TODO
}
}
@FXML
public void handleSaveAsAction() {
FileChooser fileChooser = getFileChooser();
File selection = fileChooser.showSaveDialog(null);
File oldStorage = documentStorage.getDocumentLocation();
try {
documentStorage.setDocumentLocation(selection);
documentStorage.saveDocument();
} catch (IOException e) {
// TODO
documentStorage.setDocumentLocation(oldStorage);
}
}
@FXML
public void handleSaveCopyAsAction() {
FileChooser fileChooser = getFileChooser();
File selection = fileChooser.showSaveDialog(null);
File oldStorage = documentStorage.getDocumentLocation();
try {
documentStorage.setDocumentLocation(selection);
documentStorage.saveDocument();
} catch (IOException e) {
// TODO
} finally {
documentStorage.setDocumentLocation(oldStorage);
}
}
}
package tdt4140.gr1800.app.ui;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.event.UIEventType;
import com.lynden.gmapsfx.javascript.object.GoogleMap;
import com.lynden.gmapsfx.javascript.object.MVCArray;
import com.lynden.gmapsfx.javascript.object.MapOptions;
import com.lynden.gmapsfx.javascript.object.MapShape;
import com.lynden.gmapsfx.javascript.object.MapTypeIdEnum;
import com.lynden.gmapsfx.javascript.object.Marker;
import com.lynden.gmapsfx.javascript.object.MarkerOptions;
import com.lynden.gmapsfx.shapes.Polyline;
import com.lynden.gmapsfx.shapes.PolylineOptions;
import java.util.Iterator;
import fxmapcontrol.MapBase;
import fxmapcontrol.MapItemsControl;
import fxmapcontrol.MapNode;
import fxmapcontrol.MapTileLayer;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import tdt4140.gr1800.app.core.App;
import tdt4140.gr1800.app.core.GeoLocations;
import tdt4140.gr1800.app.core.LatLong;
public class FxAppController implements MapComponentInitializedListener {
public class FxAppController {
@FXML
private TextField geolocationsFileText;
private FileMenuController fileMenuController;
@FXML
private ComboBox<String> geoLocationsSelector;
@FXML
private GoogleMapView mapView;
private GoogleMap map;
private MapBase mapView;
private MapItemsControl<MapNode> markersParent;
@FXML
private Slider zoomSlider;
......@@ -51,133 +33,62 @@ public class FxAppController implements MapComponentInitializedListener {
@FXML
public void initialize() {
mapView.addMapInializedListener(this);
app = new App();
fileMenuController.setDocumentStorage(app.getDocumentStorage());
fileMenuController.setOnDocumentChanged(documentStorage -> initMapMarkers());
geoLocationsSelector.getSelectionModel().selectedItemProperty().addListener((stringProperty, oldValue, newValue) -> updateGeoLocations());
zoomSlider.valueProperty().addListener((doubleProperty, oldValue, newValue) -> map.setZoom((int) zoomSlider.getValue()));
mapView.getChildren().add(MapTileLayer.getOpenStreetMapLayer());
mapView.zoomLevelProperty().bind(zoomSlider.valueProperty());
markersParent = new MapItemsControl<MapNode>();
mapView.getChildren().add(markersParent);
}
private Object updateGeoLocations() {
return null;
}
private Map<GeoLocations, MapShape> shapes = new HashMap<GeoLocations, MapShape>();
private Map<GeoLocations, Collection<Marker>> markers = new HashMap<GeoLocations, Collection<Marker>>();
private void initMapMarkers() {
map.clearMarkers();
markersParent.getItems().clear();
for (String geoLocationName : app.getGeoLocationNames()) {
GeoLocations geoLocations = app.getGeoLocations(geoLocationName);
if (geoLocations.isPath()) {
Collection<com.lynden.gmapsfx.javascript.object.LatLong> latLongs = new ArrayList<com.lynden.gmapsfx.javascript.object.LatLong>();
for (LatLong latLong : geoLocations) {
double lat = latLong.latitude, lon = latLong.longitude;
latLongs.add(new com.lynden.gmapsfx.javascript.object.LatLong(lat, lon));
}
MVCArray mvc = new MVCArray(latLongs.toArray(new com.lynden.gmapsfx.javascript.object.LatLong[latLongs.size()]));
PolylineOptions options = new PolylineOptions()
.path(mvc)
.strokeColor("red")
.strokeWeight(2);
Polyline polyline = new Polyline(options);
map.addMapShape(polyline);
this.shapes.put(geoLocations, polyline);
} else {
Collection<Marker> markers = new ArrayList<Marker>();
for (LatLong latLong : geoLocations) {
double lat = latLong.latitude, lon = latLong.longitude;
MarkerOptions options = new MarkerOptions().label(geoLocationName)
.position(new com.lynden.gmapsfx.javascript.object.LatLong(lat, lon));
Marker marker = new Marker(options);
map.addMarker(marker);
markers.add(marker);
MapMarker lastMarker = null;
for (LatLong latLong : geoLocations) {
MapMarker mapMarker = new MapMarker(latLong);
markersParent.getItems().add(mapMarker);
if (geoLocations.isPath() && lastMarker != null) {
MapPathLine pathLine = new MapPathLine(lastMarker, mapMarker);
markersParent.getItems().add(pathLine);
}
this.markers.put(geoLocations, markers);
lastMarker = mapMarker;
}
geoLocationsSelector.getItems().add(geoLocationName);
}
map.setCenter(getCenter(null));
map.addMouseEventHandler(UIEventType.click, (event) -> {
com.lynden.gmapsfx.javascript.object.LatLong latLong = event.getLatLong();
System.out.println("Latitude: " + latLong.getLatitude());
System.out.println("Longitude: " + latLong.getLongitude());
});
LatLong center = getCenter(null);
System.out.println("Map markers initialized");
}
private com.lynden.gmapsfx.javascript.object.LatLong getCenter(GeoLocations geoLocations) {
private LatLong getCenter(GeoLocations geoLocations) {
double latSum = 0.0, lonSum = 0.0;
int num = 0;
Iterator<String> names = null;
if (geoLocations == null) {
for (String geoLocationName : app.getGeoLocationNames()) {
geoLocations = app.getGeoLocations(geoLocationName);
for (LatLong latLong : geoLocations) {
double lat = latLong.latitude, lon = latLong.longitude;
latSum += lat;
lonSum += lon;
num++;
}
names = app.getGeoLocationNames().iterator();
}
while (geoLocations != null || (names != null && names.hasNext())) {
if (names != null) {
geoLocations = app.getGeoLocations(names.next());
}
} else {
for (LatLong latLong : geoLocations) {
double lat = latLong.latitude, lon = latLong.longitude;
latSum += lat;
lonSum += lon;
num++;
}
}
return new com.lynden.gmapsfx.javascript.object.LatLong(latSum / num, lonSum / num);
}
@Override
public void mapInitialized() {
// Set the initial properties of the map.
MapOptions mapOptions = new MapOptions();
mapOptions
.mapType(MapTypeIdEnum.ROADMAP)
.center(new com.lynden.gmapsfx.javascript.object.LatLong(63.0, 10.0))
.overviewMapControl(false)
.panControl(false)
.rotateControl(false)
.scaleControl(false)
.streetViewControl(false)
.zoomControl(false)
.zoom(zoomSlider.getValue());
map = mapView.createMap(mapOptions);
System.out.println("Map initialized: " + map);
if (app.getGeoLocationNames().iterator().hasNext()) {
initMapMarkers();
}
}
@FXML
public void loadGeolocationsFile() {
try {
URI fileUri = new URI(geolocationsFileText.getText());
app.loadGeoLocations(fileUri);
System.out.println("GeoLocations initialized: " + app.getGeoLocationNames());
if (map != null) {
initMapMarkers();
if (names != null) {
geoLocations = null;
}
} catch (Exception e) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Exception when loading from " + geolocationsFileText.getText() + ": " + e.getMessage());
alert.setContentText(e.getMessage());
alert.show();
}
}
@FXML
public void handleBrowseGeolocationsFile() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select geo-locations file");
File file = fileChooser.showOpenDialog(mapView.getScene().getWindow());
if (file == null) {
file = new File(".");
}
geolocationsFileText.setText(file.toURI().toString());
geolocationsFileText.getOnAction().handle(null);
return new LatLong(latSum / num, lonSum / num);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<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"/>
<Menu fx:id="recentMenu" text="Open Recent"/>
<MenuItem text="Save" onAction="#handleSaveAction"/>
<MenuItem text="Save As..." onAction="#handleSaveAsAction"/>
<MenuItem text="Save Copy As..." onAction="#handleSaveCopyAsAction"/>
</items>
</Menu>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment