]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server.ui/src/org/simantics/maps/server/ui/prefs/MapsServerPreferencePage.java
Make background map preference changes apply immediately
[simantics/district.git] / org.simantics.maps.server.ui / src / org / simantics / maps / server / ui / prefs / MapsServerPreferencePage.java
1 package org.simantics.maps.server.ui.prefs;
2
3 import java.io.IOException;
4 import java.net.URISyntaxException;
5 import java.nio.file.Files;
6 import java.nio.file.Path;
7 import java.nio.file.Paths;
8 import java.util.List;
9
10 import org.eclipse.core.runtime.preferences.InstanceScope;
11 import org.eclipse.jface.layout.GridDataFactory;
12 import org.eclipse.jface.layout.GridLayoutFactory;
13 import org.eclipse.jface.preference.BooleanFieldEditor;
14 import org.eclipse.jface.preference.ComboFieldEditor;
15 import org.eclipse.jface.preference.FieldEditorPreferencePage;
16 import org.eclipse.jface.preference.FileFieldEditor;
17 import org.eclipse.jface.preference.IPreferenceStore;
18 import org.eclipse.jface.preference.IntegerFieldEditor;
19 import org.eclipse.jface.preference.StringFieldEditor;
20 import org.eclipse.jface.util.IPropertyChangeListener;
21 import org.eclipse.jface.util.PropertyChangeEvent;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.SelectionAdapter;
24 import org.eclipse.swt.events.SelectionEvent;
25 import org.eclipse.swt.widgets.Button;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Group;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.ui.IWorkbench;
30 import org.eclipse.ui.IWorkbenchPreferencePage;
31 import org.eclipse.ui.preferences.ScopedPreferenceStore;
32 import org.simantics.district.maps.server.TileserverMapnik;
33 import org.simantics.district.maps.server.TileserverMapnikInstance;
34 import org.simantics.district.maps.server.prefs.MapsServerPreferences;
35 import org.simantics.district.network.ui.DynamicComboFieldEditor;
36 import org.simantics.maps.server.ui.TileserverMapnikStartJob;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class MapsServerPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
41
42     private static final Logger LOGGER = LoggerFactory.getLogger(MapsServerPreferencePage.class);
43     
44     private TileserverMapnik server;
45
46     private FileFieldEditor addNew;
47
48     private DynamicComboFieldEditor currentTilesSelector;
49
50     public MapsServerPreferencePage() {
51         super(GRID);
52         setDescription("Maps server preferences");
53     }
54     
55     @Override
56     public void init(IWorkbench workbench) {
57         try {
58             server = TileserverMapnikInstance.get();
59         } catch (IOException | URISyntaxException e) {
60             LOGGER.error("Could not initialize " + getClass(), e);
61         }
62     }
63
64     @Override
65     protected IPreferenceStore doGetPreferenceStore() {
66         return new ScopedPreferenceStore(InstanceScope.INSTANCE, MapsServerPreferences.P_NODE);
67     }
68
69     private void createServerStatusField(Composite parent) {
70         Label label = new Label(parent, SWT.NONE);
71         GridDataFactory.fillDefaults().grab(true, false).applyTo(label);
72         
73         Button b = new Button(parent, SWT.NONE);
74         GridDataFactory.fillDefaults().grab(true, false).applyTo(b);
75         updateWidgets(label, b);
76         b.addSelectionListener(new SelectionAdapter() {
77             
78             @Override
79             public void widgetSelected(SelectionEvent e) {
80                 try {
81                     if (server.isRunning()) {
82                         server.stop();
83                         updateWidgets(label, b);
84                     } else {
85                         new TileserverMapnikStartJob(status -> {
86                             parent.getDisplay().asyncExec(() -> {
87                                 updateWidgets(label, b);
88                             });
89                         }).schedule();
90                     }
91                 } catch (Exception ex) {
92                     LOGGER.error("Could not start/stop server", ex);
93                 }
94             }
95         });
96     }
97     
98     private void updateWidgets(Label label, Button b) {
99         String labelText = "";
100         String buttonText = "";
101         int labelColor = -1;
102         try {
103             if (server.isRunning()) {
104                 buttonText = "Stop";
105                 labelText = "running";
106                 labelColor = SWT.COLOR_DARK_GREEN;
107             } else {
108                 labelText = "stopped";
109                 buttonText = "Start";
110             }
111         } catch (IOException | InterruptedException e) {
112             LOGGER.error("Could not create server status field!", e);
113             labelText = "unknown";
114             labelColor = SWT.COLOR_DARK_RED;
115         }
116         label.setText("Tileserver is currently " + labelText);
117         label.setForeground(getShell().getDisplay().getSystemColor(labelColor));
118         
119         b.setText(buttonText + " server");
120     }
121     
122     private void createGeneralGroup() {
123         Group serverGroup = new Group(getFieldEditorParent(), SWT.NONE);
124         serverGroup.setText("General");
125         GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(serverGroup);
126         
127         createServerStatusField(serverGroup);
128
129         IntegerFieldEditor port = new IntegerFieldEditor(MapsServerPreferences.P_DEFAULT_PORT, "Tileserver port", serverGroup);
130         addField(port);
131
132         BooleanFieldEditor automatically = new BooleanFieldEditor(MapsServerPreferences.P_START_AUTOMATICALLY, "Start tileserver automatically", serverGroup);
133         addField(automatically);
134         
135         StringFieldEditor serverFolder = new StringFieldEditor(MapsServerPreferences.P_SERVER_FOLDER, "Server folder", serverGroup);
136         serverFolder.setEnabled(false, serverGroup);
137         addField(serverFolder);
138
139         GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(serverGroup);
140     }
141     
142     @Override
143     protected void createFieldEditors() {
144         createGeneralGroup();
145         
146         createStylesGroup();
147         
148         createTilesGroup();
149     }
150
151     private void createStylesGroup() {
152         Group stylesGroup = new Group(getFieldEditorParent(), SWT.NONE);
153         stylesGroup.setText("Styles");
154         GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(stylesGroup);
155         
156         createTM2StylesField(stylesGroup);
157         
158         GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(stylesGroup);
159     }
160     
161     private void createTM2StylesField(Composite parent) {
162         try {
163             List<String> styles = server.listStyles();
164             
165             String[][] namesAndValues = new String[styles.size()][];
166             for (int i = 0; i < styles.size(); i++) {
167                 String style = styles.get(i);
168                 String[] nameAndValue = new String[2];
169                 nameAndValue[0] = style;
170                 nameAndValue[1] = style;
171                 namesAndValues[i] = nameAndValue;
172             }
173             
174             ComboFieldEditor selector = new ComboFieldEditor(MapsServerPreferences.P_CURRENT_TM2STYLE, "Selected Style", namesAndValues, parent);
175             GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(selector.getLabelControl(parent));
176             addField(selector);
177         } catch (IOException e) {
178             e.printStackTrace();
179         }
180     }
181     
182     private void createTilesGroup() {
183         Group tilesGroup = new Group(getFieldEditorParent(), SWT.NONE);
184         tilesGroup.setText("Vector Tiles");
185         GridDataFactory.fillDefaults().grab(true, false).applyTo(tilesGroup);
186         createTilesField(tilesGroup);
187         
188         GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(tilesGroup);
189     }
190
191     private void createTilesField(Composite parent) {
192         try {
193
194             String[][] namesAndValues = computeNamesAndValues();
195             currentTilesSelector = new DynamicComboFieldEditor(MapsServerPreferences.P_CURRENT_MBTILES, "Current Tiles", namesAndValues, parent);
196             
197             GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(currentTilesSelector.getLabelControl(parent));
198             addField(currentTilesSelector);
199
200             Composite newParent = new Composite(parent, SWT.NONE);
201             GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(newParent);
202             GridLayoutFactory.fillDefaults().numColumns(3).applyTo(newParent);
203             
204             addNew = new FileFieldEditor("Add new tiles", "Add new tiles", newParent);
205             //GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(addNew.getTextControl(newParent));
206             //addField(addNew);
207             addNew.setPropertyChangeListener(new IPropertyChangeListener() {
208                 
209                 @Override
210                 public void propertyChange(PropertyChangeEvent event) {
211                     System.out.println(event);
212                 }
213             });
214             
215         } catch (IOException e) {
216             LOGGER.error("Could not create tiles field", e);
217         }
218     }
219     
220     private String[][] computeNamesAndValues() throws IOException {
221         List<String> tiles = server.availableMBTiles();
222         String[][] namesAndValues = new String[tiles.size()][];
223         for (int i = 0; i < tiles.size(); i++) {
224             String style = tiles.get(i);
225             String[] nameAndValue = new String[2];
226             nameAndValue[0] = style;
227             nameAndValue[1] = style;
228             namesAndValues[i] = nameAndValue;
229         }
230         return namesAndValues;
231     }
232
233     @Override
234     protected void performApply() {
235         // Upload new mbtiles file
236         String fileLocation = addNew.getStringValue();
237         if (fileLocation != null && !fileLocation.isEmpty()) {
238             Path p = Paths.get(fileLocation);
239             Path target = server.getDataDirectory().resolve(p.getFileName());
240             try {
241                 Files.copy(p, target);
242                 addNew.setStringValue("");
243             } catch (IOException e) {
244                 String message = "Could not upload " + fileLocation + " to " + target.toAbsolutePath(); 
245                 LOGGER.error(message, e);
246                 setErrorMessage(message);
247             }
248         }
249         try {
250             currentTilesSelector.updateCombo(computeNamesAndValues());
251             currentTilesSelector.load();
252         } catch (IOException e) {
253             e.printStackTrace();
254         }
255         super.performApply();
256     }
257     
258     @Override
259     public boolean performOk() {
260         boolean success = super.performOk();
261         
262         try {
263             server.stop();
264             new TileserverMapnikStartJob(status -> {}).schedule();
265         } catch (Exception e) {
266             LOGGER.error("Could not restart tileserver-mapnik", e);
267         }
268         
269         return success;
270     }
271
272 }