import org.eclipse.swt.widgets.Text;
import org.geotools.referencing.CRS;
import org.simantics.district.imports.CSVImportModel;
-import org.simantics.district.imports.ui.controls.DynamicComboFieldEditor;
+import org.simantics.district.network.ui.DynamicComboFieldEditor;
public class CSVImportWizardPage extends WizardPage {
protected URI uri;
protected URL service;
- protected HttpURLConnection connection;
-
public WebService(String address) throws URISyntaxException, MalformedURLException {
this.uri = new URI(address);
this.service = uri.toURL();
}
}
+ @Override
+ public void clear() {
+ for (TileJob job : queries.values()) {
+ job.cancel();
+ }
+ queries.clear();
+ }
+
}
}
}
+ public void setWebService(WebService webService) {
+ this.service = webService;
+ }
+
}
import java.awt.Image;
import java.util.LinkedList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import org.simantics.maps.ProvisionException;
import org.simantics.maps.query.Query;
import org.simantics.maps.tile.IFilter;
import org.simantics.maps.tile.ITileProvider;
import org.simantics.maps.tile.TileKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @author Tuukka Lehtonen
*/
public class TileJob implements Runnable {
- LinkedList<Query<TileKey, Image>> queue = new LinkedList<Query<TileKey, Image>>();
- Executor executor = new ScheduledThreadPoolExecutor(1);
- ITileProvider provider;
+ private static final Logger LOGGER = LoggerFactory.getLogger(TileJob.class);
+ private static final AtomicInteger counter = new AtomicInteger();
+
+ private LinkedList<Query<TileKey, Image>> queue = new LinkedList<>();
+ private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, runnable -> {
+ Thread thread = new Thread(runnable, getClass().getSimpleName() + "-" + counter.getAndIncrement());
+ thread.setDaemon(true);
+ return thread;
+ });
+ private ITileProvider provider;
public TileJob() {
}
Image result = doQuery(job.source);
job.listener.queryComplete(job, result);
} catch (Exception e) {
+ LOGGER.error("Querying failed for job {}", job, e);
job.listener.queryFailed(job, e);
}
}
this.queue = result;
}
+ public void dispose() {
+ executor.shutdown();
+ try {
+ if (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
+ // this should shutdown for good
+ List<Runnable> unfinished = executor.shutdownNow();
+ LOGGER.warn("TileJob did not terminate in time - left jobs {}", unfinished);
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+
}
getJob().removeJob(job);
}
+ @Override
+ public void clear() {
+ getJob().clear();
+ getJob().dispose();
+ }
+
}
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class MapsClientPreferenceInitializer extends AbstractPreferenceInitializer {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MapsClientPreferenceInitializer.class);
+
public MapsClientPreferenceInitializer() {
}
@Override
public void initializeDefaultPreferences() {
Preferences node = MapsClientPreferences.getPreferences();
-
+
try {
String[] keys = node.keys();
List<String> keyss = Arrays.asList(keys);
node.put(MapsClientPreferences.P_TILESERVER_URL, possibleBuiltin);
}
} catch (BackingStoreException e) {
- e.printStackTrace();
+ LOGGER.error("Could not get keys for node {}", node, e);
}
}
}
import java.net.MalformedURLException;
import java.net.URL;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.InstanceScope;
-import org.osgi.service.prefs.Preferences;
public class MapsClientPreferences {
// TODO: fix this, currently copied from MapsServerPreferences
public static final String P_DEFAULT_PORT = "org.simantics.maps.server.defaultPort";
+ public static final String P_CURRENT_MBTILES = "org.simantics.maps.server.currentMbTiles";
public static final String P_CURRENT_TM2STYLE = "org.simantics.maps.server.currentTM2Style";
public static final String P_SERVER_NODE = "org.simantics.maps.server";
- public static Preferences getServerPreferences() {
+
+ public static IEclipsePreferences getServerPreferences() {
return InstanceScope.INSTANCE.getNode(P_SERVER_NODE);
}
- public static Preferences getPreferences() {
+ public static IEclipsePreferences getPreferences() {
return InstanceScope.INSTANCE.getNode(P_NODE);
}
return null;
}
+ public static void addPreferenceChangeListenerMapsServer(IPreferenceChangeListener listener) {
+ getServerPreferences().addPreferenceChangeListener(listener);
+ }
+
+ public static void removePreferenceChangeListenerMapsServer(IPreferenceChangeListener listener) {
+ getServerPreferences().removePreferenceChangeListener(listener);
+ }
+
}
import java.awt.geom.Rectangle2D;
import java.awt.image.ImageObserver;
import java.awt.image.VolatileImage;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.simantics.maps.MapScalingTransform;
import org.simantics.maps.WebService;
import org.simantics.maps.osm.OSMTileProvider;
}
};
+ private IPreferenceChangeListener listener;
+
public void init() {
- // Construct WebService from client properties
- String url;
- if (MapsClientPreferences.useBuiltinServer())
- url = MapsClientPreferences.possibleBuiltinServerURL();
- else
- url = MapsClientPreferences.tileserverURL();
- if (!url.endsWith("/"))
- url = url + "/";
-
try {
- ITileProvider provider = new OSMTileProvider(new WebService(url), TILE_PIXEL_SIZE);
+ OSMTileProvider provider = new OSMTileProvider(new WebService(computeUrl()), TILE_PIXEL_SIZE);
+
+ listener = event -> {
+ // if tiles or style change we want to flush the tile cache
+ if (MapsClientPreferences.P_CURRENT_MBTILES.equals(event.getKey()) || MapsClientPreferences.P_CURRENT_TM2STYLE.equals(event.getKey())) {
+ if (tileCache != null) {
+ tileCache.clear();
+ }
+ try {
+ provider.setWebService(new WebService(computeUrl()));
+ } catch (MalformedURLException | URISyntaxException e) {
+ LOGGER.error("Unable to update WebService with new url", e);
+ }
+ }
+ };
+ MapsClientPreferences.addPreferenceChangeListenerMapsServer(listener);
// Try to load eclipse specific implementation of TileJobQueue, if it doesn't exist, fall back to pojo implementation
try {
}
}
+ private static String computeUrl() {
+ // Construct WebService from client properties
+ String url;
+ if (MapsClientPreferences.useBuiltinServer())
+ url = MapsClientPreferences.possibleBuiltinServerURL();
+ else
+ url = MapsClientPreferences.tileserverURL();
+ if (!url.endsWith("/"))
+ url = url + "/";
+ return url;
+ }
+
+ @Override
+ public void cleanup() {
+ MapsClientPreferences.removePreferenceChangeListenerMapsServer(listener);
+ tileCache.clear();
+ job.clear();
+ }
+
@SyncField("enabled")
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
*/
public void setTileProvider(ITileProvider provider);
+ public void clear();
+
}
\ No newline at end of file
for (ITileListener l : tileListeners) {
l.tileUpdated(key, image);
}
- }
+ }
+
+ public void clear() {
+ synchronized (this) {
+ for (LevelCache level : levels.values()) {
+ level.cache.clear();
+ }
+ }
+ }
}
-package org.simantics.district.imports.ui.controls;
+package org.simantics.district.network.ui;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.swt.SWT;
try {
c4326 = CRS.decode("EPSG:4326");
} catch (Exception e) {
- LOGGER.error("Could not initialize epsg:4326", e);
+ LOGGER.error("Could not initialize EPSG:4326", e);
}
}
tifInterface.close();
}
} else {
- System.out.println("not found");
+ //System.out.println("not found");
}
}
return new Double(0); // use 0 by default for now
org.eclipse.e4.core.commands,
org.eclipse.e4.core.contexts,
org.simantics.ui,
- org.slf4j.api
+ org.slf4j.api,
+ org.simantics.district.network.ui;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
// execute in a separate thread to not slow down the startup process
if (LOGGER.isDebugEnabled())
LOGGER.debug("Starting tileserver mapnik automatically");
- new TileserverMapnikStartJob().schedule();
+ new TileserverMapnikStartJob(status -> {}).schedule();
}
}
package org.simantics.maps.server.ui;
import java.util.Optional;
+import java.util.function.Consumer;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
public class TileserverMapnikStartJob extends Job {
private static final Logger LOGGER = LoggerFactory.getLogger(TileserverMapnikStartJob.class);
+ private Consumer<IStatus> callback;
- public TileserverMapnikStartJob() {
+ public TileserverMapnikStartJob(Consumer<IStatus> callback) {
super("Tileserver start job");
+ this.callback = callback;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("Starting tileserver", 100);
+ IStatus status = Status.OK_STATUS;
try {
StartListener startListener = new StartListener(monitor);
TileserverMapnikInstance.get().start(Optional.of(startListener));
if (startListener.module != null || startListener.returnValue != 0)
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not install " + String.valueOf(startListener.module) + " with returnValue " + startListener.returnValue);
- return Status.OK_STATUS;
+ status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not install " + String.valueOf(startListener.module) + " with returnValue " + startListener.returnValue);
} catch (Exception e) {
LOGGER.error("Could not start tileserver-mapnik", e);
- return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not start tileserver-mapnik: " + e.getMessage());
+ status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not start tileserver-mapnik: " + e.getMessage());
}
+ callback.accept(status);
+ return status;
}
private class StartListener implements TileserverStartListener {
import org.eclipse.jface.preference.FileFieldEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.IntegerFieldEditor;
+import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.simantics.district.maps.server.TileserverMapnik;
import org.simantics.district.maps.server.TileserverMapnikInstance;
import org.simantics.district.maps.server.prefs.MapsServerPreferences;
+import org.simantics.district.network.ui.DynamicComboFieldEditor;
import org.simantics.maps.server.ui.TileserverMapnikStartJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private FileFieldEditor addNew;
+ private DynamicComboFieldEditor currentTilesSelector;
+
public MapsServerPreferencePage() {
super(GRID);
setDescription("Maps server preferences");
private void createServerStatusField(Composite parent) {
Label label = new Label(parent, SWT.NONE);
-
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(label);
+
Button b = new Button(parent, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(b);
updateWidgets(label, b);
b.addSelectionListener(new SelectionAdapter() {
server.stop();
updateWidgets(label, b);
} else {
- new TileserverMapnikStartJob().schedule();
+ new TileserverMapnikStartJob(status -> {
+ parent.getDisplay().asyncExec(() -> {
+ updateWidgets(label, b);
+ });
+ }).schedule();
}
} catch (Exception ex) {
LOGGER.error("Could not start/stop server", ex);
BooleanFieldEditor automatically = new BooleanFieldEditor(MapsServerPreferences.P_START_AUTOMATICALLY, "Start tileserver automatically", serverGroup);
addField(automatically);
- Button openInExplorer = new Button(serverGroup, SWT.NONE);
- openInExplorer.setText("Open server folder");
- openInExplorer.addSelectionListener(new SelectionAdapter() {
-
- @Override
- public void widgetSelected(SelectionEvent e) {
-// E4WorkbenchUtils.showInSystemExplorer("");
- }
- });
-
+ StringFieldEditor serverFolder = new StringFieldEditor(MapsServerPreferences.P_SERVER_FOLDER, "Server folder", serverGroup);
+ serverFolder.setEnabled(false, serverGroup);
+ addField(serverFolder);
+
GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(serverGroup);
}
namesAndValues[i] = nameAndValue;
}
- ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_TM2STYLE, "Tile Styles", namesAndValues, parent);
+ ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_TM2STYLE, "Selected Style", namesAndValues, parent);
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(selector.getLabelControl(parent));
addField(selector);
} catch (IOException e) {
e.printStackTrace();
private void createTilesGroup() {
Group tilesGroup = new Group(getFieldEditorParent(), SWT.NONE);
- tilesGroup.setText("MBTiles");
- GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(tilesGroup);
-
+ tilesGroup.setText("Vector Tiles");
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(tilesGroup);
createTilesField(tilesGroup);
- GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(tilesGroup);
+ GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(tilesGroup);
}
private void createTilesField(Composite parent) {
try {
- List<String> tiles = server.availableMBTiles();
-
- String[][] namesAndValues = new String[tiles.size()][];
- for (int i = 0; i < tiles.size(); i++) {
- String style = tiles.get(i);
- String[] nameAndValue = new String[2];
- nameAndValue[0] = style;
- nameAndValue[1] = style;
- namesAndValues[i] = nameAndValue;
- }
+
+ String[][] namesAndValues = computeNamesAndValues();
+ currentTilesSelector = new DynamicComboFieldEditor(MapsServerPreferences.P_CURRENT_MBTILES, "Current Tiles", namesAndValues, parent);
- ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_MBTILES, "MBTiles", namesAndValues, parent);
- addField(selector);
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(currentTilesSelector.getLabelControl(parent));
+ addField(currentTilesSelector);
+
+ Composite newParent = new Composite(parent, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(newParent);
+ GridLayoutFactory.fillDefaults().numColumns(3).applyTo(newParent);
- addNew = new FileFieldEditor("Add new tiles", "Add new tiles", parent);
+ addNew = new FileFieldEditor("Add new tiles", "Add new tiles", newParent);
+ //GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(addNew.getTextControl(newParent));
+ //addField(addNew);
addNew.setPropertyChangeListener(new IPropertyChangeListener() {
@Override
}
}
+ private String[][] computeNamesAndValues() throws IOException {
+ List<String> tiles = server.availableMBTiles();
+ String[][] namesAndValues = new String[tiles.size()][];
+ for (int i = 0; i < tiles.size(); i++) {
+ String style = tiles.get(i);
+ String[] nameAndValue = new String[2];
+ nameAndValue[0] = style;
+ nameAndValue[1] = style;
+ namesAndValues[i] = nameAndValue;
+ }
+ return namesAndValues;
+ }
+
@Override
protected void performApply() {
// Upload new mbtiles file
Path target = server.getDataDirectory().resolve(p.getFileName());
try {
Files.copy(p, target);
+ addNew.setStringValue("");
} catch (IOException e) {
String message = "Could not upload " + fileLocation + " to " + target.toAbsolutePath();
LOGGER.error(message, e);
setErrorMessage(message);
}
}
+ try {
+ currentTilesSelector.updateCombo(computeNamesAndValues());
+ currentTilesSelector.load();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
super.performApply();
}
try {
server.stop();
- new TileserverMapnikStartJob().schedule();
+ new TileserverMapnikStartJob(status -> {}).schedule();
} catch (Exception e) {
LOGGER.error("Could not restart tileserver-mapnik", e);
}
import java.io.IOException;
import java.net.URISyntaxException;
+import java.nio.file.Paths;
+
+import org.simantics.district.maps.server.prefs.MapsServerPreferences;
public class TileserverMapnikInstance {
public static synchronized TileserverMapnik get() throws IOException, URISyntaxException {
if (INSTANCE == null)
- INSTANCE = new TileserverMapnik(Activator.getTileserverMapnikRoot());
+ INSTANCE = new TileserverMapnik(Paths.get(MapsServerPreferences.serverFolder()));
return INSTANCE;
}
}
package org.simantics.district.maps.server.prefs;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.service.prefs.Preferences;
import org.simantics.district.maps.server.Activator;
public static final String P_CURRENT_TM2STYLE = "org.simantics.maps.server.currentTM2Style";
+ public static final String P_SERVER_FOLDER = "org.simantics.maps.server.serverFolder";
+
public static Preferences getPreferences() {
return InstanceScope.INSTANCE.getNode(MapsServerPreferences.P_NODE);
}
return getPreferences().get(P_CURRENT_TM2STYLE, "mapbox-studio-osm-bright.tm2");
}
+ public static String serverFolder() throws IOException, URISyntaxException {
+ return getPreferences().get(P_SERVER_FOLDER, Activator.getTileserverMapnikRoot().toAbsolutePath().toString());
+ }
}