Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • akselsa/course-material
  • it1901/course-material
2 results
Show changes
Showing
with 0 additions and 874 deletions
package simpleex.ui;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import simpleex.core.LatLongs;
public class FxApp extends Application {
@Override
public void start(final Stage stage) throws Exception {
final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("FxApp.fxml"));
final Parent root = fxmlLoader.load();
final FxAppController controller = fxmlLoader.getController();
controller.setLatLongs(new LatLongs(63.1, 11.2, 63.2, 11.0));
final Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(final String[] args) {
// only needed on ios
System.setProperty("os.target", "ios");
System.setProperty("os.name", "iOS");
System.setProperty("glass.platform", "ios");
System.setProperty("targetos.name", "iOS");
launch(args);
}
}
package simpleex.ui;
import java.io.File;
import java.util.Optional;
import fxmapcontrol.Location;
import fxmapcontrol.MapBase;
import fxmapcontrol.MapItemsControl;
import fxmapcontrol.MapNode;
import fxmapcontrol.MapProjection;
import fxutil.doc.FileMenuController;
import fxutil.doc.IDocumentListener;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.ListView;
import javafx.scene.control.Slider;
import simpleex.core.LatLong;
import simpleex.core.LatLongs;
public class FxAppController extends FileMenuController implements IDocumentListener<LatLongs, File> {
private final LatLongsStorage latLongsStorage;
public FxAppController() {
latLongsStorage = new LatLongsStorage();
latLongsStorage.addDocumentStorageListener(this);
}
public LatLongs getLatLongs() {
return latLongsStorage.getDocument();
}
// to make it testable
public void setLatLongs(final LatLongs latLongs) {
latLongsStorage.setDocument(latLongs);
updateLocationViewList(0);
}
// @FXML
// private FileMenuController fileMenuController;
@FXML
private ListView<LatLong> locationListView;
@FXML
private MapBase mapView;
private MapItemsControl<MapNode> markersParent;
private Optional<MapMarker> marker = Optional.empty();
private DraggableNodeController draggableMapController = null;
private DraggableNodeController draggableMarkerController = null;
@FXML
private Slider zoomSlider;
@FXML
private void initialize() {
// fileMenuController.
setDocumentStorage(latLongsStorage);
// map stuff
// mapView.getChildren().add(MapTileLayer.getOpenStreetMapLayer());
zoomSlider.valueProperty().addListener((prop, oldValue, newValue) -> mapView.setZoomLevel(zoomSlider.getValue()));
zoomSlider.setValue(8);
markersParent = new MapItemsControl<MapNode>();
mapView.getChildren().add(markersParent);
draggableMapController = new DraggableNodeController(Optional.of(this::handleMapDragged));
draggableMapController.setImmediate(true);
draggableMapController.attach(mapView);
draggableMarkerController = new DraggableNodeController(Optional.of(this::handleMarkerDragged));
// the location list
locationListView.getSelectionModel().selectedIndexProperty().addListener((prop, oldValue, newValue) -> updateMapMarker(true));
}
private void handleMapDragged(final Node node, final double dx, final double dy) {
final MapProjection projection = mapView.getProjection();
final Point2D point = projection.locationToViewportPoint(mapView.getCenter());
final Location newCenter = projection.viewportPointToLocation(point.add(-dx, -dy));
mapView.setCenter(newCenter);
}
private void handleMarkerDragged(final Node node, final double dx, final double dy) {
final MapProjection projection = mapView.getProjection();
final Point2D point = projection.locationToViewportPoint(marker.get().getLocation());
final Location newLocation = projection.viewportPointToLocation(point.add(dx, dy));
getLatLongs().setLatLong(locationListView.getSelectionModel().getSelectedIndex(), location2LatLong(newLocation));
updateLocationViewListSelection(false);
}
private LatLong location2LatLong(final Location newLocation) {
return new LatLong(newLocation.getLatitude(), newLocation.getLongitude());
}
private void updateMapMarker(final boolean centerOnMarker) {
final int num = locationListView.getSelectionModel().getSelectedIndex();
if (num < 0 || num >= getLatLongs().getLatLongCount()) {
markersParent.getItems().clear();
if (draggableMarkerController != null) {
draggableMarkerController.detach(marker.get());
}
marker = Optional.empty();
} else {
final LatLong latLong = getLatLongs().getLatLong(num);
if (marker.isEmpty()) {
final MapMarker aMarker = new MapMarker(latLong);
markersParent.getItems().add(aMarker);
if (draggableMarkerController != null) {
draggableMarkerController.attach(aMarker);
}
marker = Optional.of(aMarker);
} else {
marker.get().setLocation(latLong);
}
if (centerOnMarker) {
mapView.setCenter(marker.get().getLocation());
}
}
}
@FXML
private void handleAddLocation() {
final Location center = mapView.getCenter();
final int pos = getLatLongs().addLatLong(location2LatLong(center));
updateLocationViewList(pos);
}
private void updateLocationViewListSelection(final Boolean updateMapMarker) {
final int selectedIndex = locationListView.getSelectionModel().getSelectedIndex();
updateLocationViewListItem(selectedIndex);
if (updateMapMarker != null) {
updateMapMarker(updateMapMarker);
}
}
private void updateLocationViewListItem(final int index) {
locationListView.getItems().set(index, getLatLongs().getLatLong(index));
}
private void updateLocationViewList(int selectedIndex) {
final LatLong[] latLongs = new LatLong[getLatLongs().getLatLongCount()];
for (int i = 0; i < latLongs.length; i++) {
latLongs[i] = getLatLongs().getLatLong(i);
}
final int oldSelectionIndex = locationListView.getSelectionModel().getSelectedIndex();
locationListView.setItems(FXCollections.observableArrayList(latLongs));
if (selectedIndex < 0 || selectedIndex >= latLongs.length) {
selectedIndex = oldSelectionIndex;
}
if (selectedIndex >= 0 && selectedIndex < getLatLongs().getLatLongCount()) {
locationListView.getSelectionModel().select(selectedIndex);
}
}
// IDocumentListener
@Override
public void documentLocationChanged(final File documentLocation, final File oldDocumentLocation) {
}
@Override
public void documentChanged(final LatLongs document, final LatLongs oldDocument) {
updateLocationViewList(0);
}
}
package simpleex.ui;
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 fxutil.doc.AbstractDocumentStorageImpl;
import fxutil.doc.IDocumentImporter;
import fxutil.doc.IDocumentLoader;
import fxutil.doc.IDocumentPersistence;
import fxutil.doc.IDocumentStorage;
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;
}
}
package simpleex.ui;
import java.io.File;
import com.fasterxml.jackson.databind.module.SimpleModule;
import fxutil.doc.IDocumentStorage;
import fxutil.doc.SimpleJsonFileStorageImpl;
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());
}
}
package simpleex.ui;
import fxmapcontrol.Location;
import fxmapcontrol.MapItem;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import simpleex.core.LatLong;
public class MapMarker extends MapItem<LatLong> {
public MapMarker(final LatLong latLong) {
setLocation(latLong);
final Circle circle = new Circle();
circle.setRadius(5);
circle.setFill(Color.BLUE);
getChildren().add(circle);
}
public final void setLocation(final LatLong latLong) {
setLocation(new Location(latLong.getLatitude(), latLong.getLongitude()));
}
}
# The UI source code, a minimal JavaFX/FXML UI
\ No newline at end of file
<?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>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Slider?>
<?import fxmapcontrol.MapBase?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Label?>
<?import fxmapcontrol.MapTileLayer?>
<?import fxmapcontrol.TileSource?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<BorderPane xmlns:fx="http://javafx.com/fxml"
fx:controller="simpleex.ui.FxAppController"
prefHeight="750" prefWidth="1000">
<top>
<VBox>
<MenuBar >
<menus>
<fx:include fx:id="fileMenu" source="FileMenu.fxml"/>
</menus>
</MenuBar>
</VBox>
</top>
<left>
<VBox fillWidth="true">
<ListView fx:id="locationListView"/>
<Button text="Add location" onAction="#handleAddLocation"/>
</VBox>
</left>
<center>
<VBox>
<MapBase fx:id="mapView">
<MapTileLayer name="OpenStreetMap" minZoomLevel="0" maxZoomLevel="17">
<tileSource>
<TileSource urlFormat="http://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png"/>
<!--
<TileSource urlFormat="https://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
<TileSource urlFormat="http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&amp;zoom={z}&amp;x={x}&amp;y={y}"/>
<TileSource urlFormat="http://mt1.google.com/vt/lyrs=m@129&amp;hl=en&amp;s=Galileo&amp;z={z}&amp;x={x}&amp;y={y}"/>
-->
</tileSource>
</MapTileLayer>
</MapBase>
<Slider fx:id="zoomSlider" min="1" max="20" value="9"/>
</VBox>
</center>
</BorderPane>
package simpleex.core;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
public class LatLongTest {
@Test
public void testToString() {
final LatLong latLong = new LatLong(63.0, 10.0);
Assert.assertEquals(Double.toString(63) + "," + Double.toString(10), latLong.toString());
}
@Test
public void testValueOf() {
testLatLong(LatLong.valueOf("63.0, 10.0"), 63.0, 10.0);
testLatLong(LatLong.valueOf("63.0, 10.0", ","), 63.0, 10.0);
testLatLong(LatLong.valueOf("63.0; 10.0", ";"), 63.0, 10.0);
try {
testLatLong(LatLong.valueOf("63.0; 10.0", ","), 63.0, 10.0);
Assert.fail("Should throw IllegalArgumentException");
} catch (final IllegalArgumentException e) {
} catch (final Exception e) {
Assert.fail("Should throw IllegalArgumentException");
}
}
private void testLatLong(final LatLong latLong, final double lat, final double lon) {
Assert.assertEquals(lat, latLong.getLatitude(), 0.0);
Assert.assertEquals(lon, latLong.getLongitude(), 0.0);
}
@Test
public void testEquals() {
Assert.assertTrue(new LatLong(63.0, 10.0).equals(new LatLong(63.0, 10.0)));
Assert.assertFalse(new LatLong(10.0, 63.0).equals(new LatLong(63.0, 10.0)));
Assert.assertFalse(new LatLong(10.0, 63.0).equals(null));
}
@Test
public void testHashCode() {
final Map<LatLong, String> map = new HashMap<>();
map.put(new LatLong(63.0, 10.0), "first");
map.put(new LatLong(63.0, 10.0), "second");
Assert.assertEquals(1, map.size());
Assert.assertEquals("second", map.get(new LatLong(63.0, 10.0)));
}
@Test
public void testDistance() {
final LatLong trd = new LatLong(63.4217137055, 10.4221522734);
final LatLong str = new LatLong(63.0339713594, 10.2946225585);
checkDistance(trd.distance(trd), 0.0, 10.0);
checkDistance(str.distance(str), 0.0, 10.0);
checkDistance(trd.distance(str), 43000.0, 45000.0);
checkDistance(str.distance(trd), 43000.0, 45000.0);
checkDistance(LatLong.distance(trd, trd), 0.0, 10.0);
checkDistance(LatLong.distance(str, str), 0.0, 10.0);
checkDistance(LatLong.distance(trd, str), 43000.0, 45000.0);
checkDistance(LatLong.distance(str, trd), 43000.0, 45000.0);
}
private void checkDistance(final double d, final double lower, final double upper) {
Assert.assertTrue(d + " isn't between " + lower + " and " + upper, d <= upper && d >= lower);
}
}
package simpleex.core;
import java.util.Arrays;
import java.util.Iterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class LatLongsTest {
private LatLongs latLongs;
@Before
public void setUp() {
latLongs = new LatLongs();
}
@Test
public void testEmptyConstructor() {
Assert.assertEquals(0, latLongs.getLatLongCount());
}
private static void checkLatLongs(final LatLongs latLongs1, final LatLong... latLongs2) {
Assert.assertEquals(latLongs2.length, latLongs1.getLatLongCount());
final Iterator<LatLong> it = latLongs1.iterator();
for (int i = 0; i < latLongs2.length; i++) {
Assert.assertTrue(it.hasNext());
Assert.assertEquals(latLongs2[i], latLongs1.getLatLong(i));
Assert.assertEquals(latLongs2[i], it.next());
}
Assert.assertFalse(it.hasNext());
}
@Test
public void testConstructor() {
checkLatLongs(new LatLongs(63.0, 10.3, 63.1, 10.2), new LatLong(63.0, 10.3), new LatLong(63.1, 10.2));
checkLatLongs(new LatLongs(new LatLong(63.0, 10.3), new LatLong(63.1, 10.2)), new LatLong(63.0, 10.3), new LatLong(63.1, 10.2));
checkLatLongs(new LatLongs(Arrays.asList(new LatLong(63.1, 10.2), new LatLong(63.1, 10.1))), new LatLong(63.1, 10.2), new LatLong(63.1, 10.1));
}
@Test
public void testAddLatLong() {
latLongs.addLatLong(new LatLong(63.0, 10.3));
Assert.assertEquals(1, latLongs.getLatLongCount());
latLongs.addLatLong(new LatLong(63.1, 10.2));
Assert.assertEquals(2, latLongs.getLatLongCount());
}
@Test
public void testAddLatLongs() {
final LatLongs lls1 = new LatLongs();
lls1.addLatLongs(63.0, 10.3, 63.1, 10.2);
checkLatLongs(lls1, new LatLong(63.0, 10.3), new LatLong(63.1, 10.2));
final LatLongs lls2 = new LatLongs();
lls2.addLatLongs(new LatLong(63.0, 10.3), new LatLong(63.1, 10.2));
checkLatLongs(lls2, new LatLong(63.0, 10.3), new LatLong(63.1, 10.2));
final LatLongs lls3 = new LatLongs();
lls3.addLatLongs(Arrays.asList(new LatLong(63.1, 10.2), new LatLong(63.1, 10.1)));
checkLatLongs(lls3, new LatLong(63.1, 10.2), new LatLong(63.1, 10.1));
}
}
package simpleex.json;
import java.io.IOException;
import org.junit.Assert;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public abstract class AbstractJsonTest {
private ObjectMapper objectMapper;
public ObjectMapper getObjectMapper() {
return objectMapper;
}
protected void setUp() {
objectMapper = createObjectMapper();
}
protected abstract ObjectMapper createObjectMapper();
protected <T> SimpleModule createSimpleModule(final Class<T> clazz, final JsonSerializer<T> serializer, final JsonDeserializer<T> deserializer) {
return new SimpleModule()
.addSerializer(clazz, serializer)
.addDeserializer(clazz, deserializer);
}
protected <T> ObjectMapper createObjectMapper(final Class<T> clazz, final JsonSerializer<T> serializer, final JsonDeserializer<T> deserializer) {
return new ObjectMapper().registerModule(createSimpleModule(clazz, serializer, deserializer));
}
protected void assertEqualsIgnoreWhitespace(final String expected, final String actual) throws Exception {
Assert.assertEquals(expected, actual.replaceAll("\\s+", ""));
}
protected void assertWriteValue(final String expected, final Object value) throws Exception {
assertEqualsIgnoreWhitespace(expected, getObjectMapper().writeValueAsString(value));
}
protected <T> T readValue(final String s, final Class<T> clazz) throws IOException, JsonParseException, JsonMappingException {
return getObjectMapper().readValue(s, clazz);
}
}
package simpleex.json;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import simpleex.core.LatLong;
public class LatLongJsonTest extends AbstractJsonTest {
@Before
@Override
public void setUp() {
super.setUp();
}
@Override
protected ObjectMapper createObjectMapper() {
return createObjectMapper(LatLong.class, new LatLongSerializer(), new LatLongDeserializer());
}
@Test
public void testLatLongSerialization() throws Exception {
assertWriteValue("{\"latitude\":63.1,\"longitude\":12.3}", new LatLong(63.1, 12.3));
}
@Test
public void testLatLongObjectDeserialization() throws Exception {
Assert.assertEquals(new LatLong(63.1, 12.3), readValue("{\"latitude\":63.1,\"longitude\":12.3}", LatLong.class));
}
@Test
public void testLatLongArrayDeserialization() throws Exception {
Assert.assertEquals(new LatLong(63.1, 12.3), readValue("[ 63.1, 12.3 ]", LatLong.class));
}
}
package simpleex.json;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import simpleex.core.LatLong;
import simpleex.core.LatLongs;
public class LatLongsJsonTest extends AbstractJsonTest {
@Before
@Override
public void setUp() {
super.setUp();
}
@Override
protected ObjectMapper createObjectMapper() {
final SimpleModule module = createSimpleModule(LatLong.class,new LatLongSerializer(), new LatLongDeserializer());
module.addSerializer(LatLongs.class, new LatLongsSerializer());
module.addDeserializer(LatLongs.class, new LatLongsDeserializer());
return new ObjectMapper().registerModule(module);
}
@Test
public void testLatLongsSerialization() throws Exception {
assertWriteValue("[{\"latitude\":63.1,\"longitude\":12.3},{\"latitude\":63.0,\"longitude\":12.4}]", new LatLongs(new LatLong(63.1, 12.3), new LatLong(63.0, 12.4)));
}
@Test
public void testLatLongsDeserialization() throws Exception {
final LatLongs latLongs = readValue("[{\"latitude\":63.1,\"longitude\":12.3}, [63.0,12.4]]", LatLongs.class);
Assert.assertEquals(2, latLongs.getLatLongCount());
Assert.assertEquals(new LatLong(63.1, 12.3), latLongs.getLatLong(0));
Assert.assertEquals(new LatLong(63.0, 12.4), latLongs.getLatLong(1));
}
}
package simpleex.ui;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.testfx.framework.junit.ApplicationTest;
import fxmapcontrol.Location;
import fxmapcontrol.MapBase;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import simpleex.core.LatLong;
import simpleex.core.LatLongs;
public class FxAppTest extends ApplicationTest {
@BeforeClass
public static void headless() {
if (Boolean.valueOf(System.getProperty("gitlab-ci", "false"))) {
System.setProperty("prism.verbose", "true"); // optional
System.setProperty("java.awt.headless", "true");
System.setProperty("testfx.robot", "glass");
System.setProperty("testfx.headless", "true");
System.setProperty("glass.platform", "Monocle");
System.setProperty("monocle.platform", "Headless");
System.setProperty("prism.order", "sw");
System.setProperty("prism.text", "t2k");
System.setProperty("testfx.setup.timeout", "2500");
}
}
private FxAppController controller;
private LatLongs latLongs;
@Override
public void start(final Stage stage) throws Exception {
final FXMLLoader loader = new FXMLLoader(getClass().getResource("FxApp.fxml"));
final Parent root = loader.load();
this.controller = loader.getController();
setUpLatLongs();
final Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private List<LatLong> latLongList;
private void setUpLatLongs() {
// test data
latLongList = new ArrayList<>(List.of(new LatLong(63.1, 11.2), new LatLong(63.2, 11.0)));
// "mocked" (faked) LatLongs object with very specific and limited behavior
latLongs = mock(LatLongs.class);
// get nth LatLong object
when(latLongs.getLatLong(anyInt())).then(invocation -> latLongList.get(invocation.getArgument(0)));
// get the number of LatLong objects
when(latLongs.getLatLongCount()).then(invocation -> latLongList.size());
// iterator for LatLong objects
when(latLongs.iterator()).then(invocation -> latLongList.iterator());
controller.setLatLongs(latLongs);
}
@Test
public void testController() {
Assert.assertNotNull(this.controller);
}
@Test
public void testLocationListView() {
final ListView<?> locationListView = lookup("#locationListView").query();
// list contains equals elements in same order
Assert.assertEquals(latLongList, locationListView.getItems());
// first list element is auto-selected
Assert.assertEquals(0, locationListView.getSelectionModel().getSelectedIndex());
}
@Test
public void testMapView() {
final MapBase mapView = lookup("#mapView").query();
// center of map view is approx. the first LatLong object
final Location center = mapView.getCenter();
final double epsilon = 0.000001; // round-off error
Assert.assertEquals(latLongList.get(0).getLatitude(), center.getLatitude(), epsilon);
Assert.assertEquals(latLongList.get(0).getLongitude(), center.getLongitude(), epsilon);
}
@Test
public void testAddLocation() {
// needs map center
final Location center = ((MapBase) lookup("#mapView").query()).getCenter();
// add behavior for add
final LatLong latLong = new LatLong(center.getLatitude(), center.getLongitude());
when(latLongs.addLatLong(latLong)).thenReturn(2); // add center
// make test less sensitive to exact button text
final Button addLocButton = lookup(node -> node instanceof Button && ((Button) node).getText().toLowerCase().startsWith("add loc")).query();
clickOn(addLocButton);
}
}
<?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>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Slider?>
<?import fxmapcontrol.MapBase?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Label?>
<?import fxmapcontrol.MapTileLayer?>
<?import fxmapcontrol.TileSource?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<BorderPane xmlns:fx="http://javafx.com/fxml"
fx:controller="simpleex.ui.FxAppController"
prefHeight="750" prefWidth="1000">
<top>
<VBox>
<MenuBar >
<menus>
<fx:include fx:id="fileMenu" source="FileMenu.fxml"/>
</menus>
</MenuBar>
</VBox>
</top>
<left>
<VBox fillWidth="true">
<ListView fx:id="locationListView"/>
<Button text="Add location" onAction="#handleAddLocation"/>
</VBox>
</left>
<center>
<VBox>
<MapBase fx:id="mapView">
<MapTileLayer name="OpenStreetMap" minZoomLevel="0" maxZoomLevel="17">
<tileSource>
<TileSource urlFormat="http://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png"/>
<!--
<TileSource urlFormat="https://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
<TileSource urlFormat="http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&amp;zoom={z}&amp;x={x}&amp;y={y}"/>
<TileSource urlFormat="http://mt1.google.com/vt/lyrs=m@129&amp;hl=en&amp;s=Galileo&amp;z={z}&amp;x={x}&amp;y={y}"/>
-->
</tileSource>
</MapTileLayer>
</MapBase>
<Slider fx:id="zoomSlider" min="1" max="20" value="9"/>
</VBox>
</center>
</BorderPane>