package org.simantics.maps.server.ui.prefs; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.FileFieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.preferences.ScopedPreferenceStore; 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.maps.server.ui.TileserverMapnikStartJob; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MapsServerPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { private static final Logger LOGGER = LoggerFactory.getLogger(MapsServerPreferencePage.class); private TileserverMapnik server; private FileFieldEditor addNew; public MapsServerPreferencePage() { super(GRID); setDescription("Maps server preferences"); } @Override public void init(IWorkbench workbench) { try { server = TileserverMapnikInstance.get(); } catch (IOException | URISyntaxException e) { LOGGER.error("Could not initialize " + getClass(), e); } } @Override protected IPreferenceStore doGetPreferenceStore() { return new ScopedPreferenceStore(InstanceScope.INSTANCE, MapsServerPreferences.P_NODE); } private void createServerStatusField(Composite parent) { Label label = new Label(parent, SWT.NONE); Button b = new Button(parent, SWT.NONE); updateWidgets(label, b); b.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { if (server.isRunning()) { server.stop(); updateWidgets(label, b); } else { new TileserverMapnikStartJob().schedule(); } } catch (Exception ex) { LOGGER.error("Could not start/stop server", ex); } } }); } private void updateWidgets(Label label, Button b) { String labelText = ""; String buttonText = ""; int labelColor = -1; try { if (server.isRunning()) { buttonText = "Stop"; labelText = "running"; labelColor = SWT.COLOR_DARK_GREEN; } else { labelText = "stopped"; buttonText = "Start"; } } catch (IOException | InterruptedException e) { LOGGER.error("Could not create server status field!", e); labelText = "unknown"; labelColor = SWT.COLOR_DARK_RED; } label.setText("Tileserver is currently " + labelText); label.setForeground(getShell().getDisplay().getSystemColor(labelColor)); b.setText(buttonText + " server"); } private void createGeneralGroup() { Group serverGroup = new Group(getFieldEditorParent(), SWT.NONE); serverGroup.setText("General"); GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(serverGroup); createServerStatusField(serverGroup); IntegerFieldEditor port = new IntegerFieldEditor(MapsServerPreferences.P_DEFAULT_PORT, "Tileserver port", serverGroup); addField(port); 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(""); } }); GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(serverGroup); } @Override protected void createFieldEditors() { createGeneralGroup(); createStylesGroup(); createTilesGroup(); } private void createStylesGroup() { Group stylesGroup = new Group(getFieldEditorParent(), SWT.NONE); stylesGroup.setText("Styles"); GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(stylesGroup); createTM2StylesField(stylesGroup); GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(stylesGroup); } private void createTM2StylesField(Composite parent) { try { List styles = server.listStyles(); String[][] namesAndValues = new String[styles.size()][]; for (int i = 0; i < styles.size(); i++) { String style = styles.get(i); String[] nameAndValue = new String[2]; nameAndValue[0] = style; nameAndValue[1] = style; namesAndValues[i] = nameAndValue; } ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_TM2STYLE, "Tile Styles", namesAndValues, 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); createTilesField(tilesGroup); GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(tilesGroup); } private void createTilesField(Composite parent) { try { List 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; } ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_MBTILES, "MBTiles", namesAndValues, parent); addField(selector); addNew = new FileFieldEditor("Add new tiles", "Add new tiles", parent); addNew.setPropertyChangeListener(new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { System.out.println(event); } }); } catch (IOException e) { LOGGER.error("Could not create tiles field", e); } } @Override protected void performApply() { // Upload new mbtiles file String fileLocation = addNew.getStringValue(); if (fileLocation != null && !fileLocation.isEmpty()) { Path p = Paths.get(fileLocation); Path target = server.getDataDirectory().resolve(p.getFileName()); try { Files.copy(p, target); } catch (IOException e) { String message = "Could not upload " + fileLocation + " to " + target.toAbsolutePath(); LOGGER.error(message, e); setErrorMessage(message); } } super.performApply(); } @Override public boolean performOk() { boolean success = super.performOk(); try { server.stop(); new TileserverMapnikStartJob().schedule(); } catch (Exception e) { LOGGER.error("Could not restart tileserver-mapnik", e); } return success; } }