1 package org.simantics.district.network.ui.visualisations;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
8 import java.util.Map.Entry;
9 import java.util.Objects;
10 import java.util.Optional;
11 import java.util.function.Supplier;
12 import java.util.stream.Collectors;
13 import java.util.stream.Stream;
15 import org.eclipse.jface.dialogs.Dialog;
16 import org.eclipse.jface.dialogs.IInputValidator;
17 import org.eclipse.jface.dialogs.InputDialog;
18 import org.eclipse.jface.layout.GridDataFactory;
19 import org.eclipse.jface.layout.GridLayoutFactory;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.FocusAdapter;
22 import org.eclipse.swt.events.FocusEvent;
23 import org.eclipse.swt.events.KeyAdapter;
24 import org.eclipse.swt.events.KeyEvent;
25 import org.eclipse.swt.events.ModifyEvent;
26 import org.eclipse.swt.events.ModifyListener;
27 import org.eclipse.swt.events.SelectionAdapter;
28 import org.eclipse.swt.events.SelectionEvent;
29 import org.eclipse.swt.widgets.Button;
30 import org.eclipse.swt.widgets.Combo;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.swt.widgets.Group;
34 import org.eclipse.swt.widgets.Label;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.swt.widgets.Text;
37 import org.eclipse.swt.widgets.Widget;
38 import org.simantics.Simantics;
39 import org.simantics.db.ReadGraph;
40 import org.simantics.db.Resource;
41 import org.simantics.db.WriteGraph;
42 import org.simantics.db.common.NamedResource;
43 import org.simantics.db.common.request.UniqueRead;
44 import org.simantics.db.common.request.WriteRequest;
45 import org.simantics.db.exception.DatabaseException;
46 import org.simantics.db.layer0.util.RemoverUtil;
47 import org.simantics.db.procedure.Listener;
48 import org.simantics.district.network.DistrictNetworkUtil;
49 import org.simantics.district.network.profile.ActiveDynamicVisualisationsRequest;
50 import org.simantics.district.network.profile.DynamicVisualisationsRequest;
51 import org.simantics.district.network.visualisations.DynamicVisualisationsContributions;
52 import org.simantics.district.network.visualisations.DynamicVisualisationsContributions.DynamicColoringObject;
53 import org.simantics.district.network.visualisations.DynamicVisualisationsContributions.DynamicSizingObject;
54 import org.simantics.district.network.visualisations.model.ColorBarOptions;
55 import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsLocation;
56 import org.simantics.district.network.visualisations.model.ColorBarOptions.ColorBarsSize;
57 import org.simantics.district.network.visualisations.model.DynamicColorContribution;
58 import org.simantics.district.network.visualisations.model.DynamicColorMap;
59 import org.simantics.district.network.visualisations.model.DynamicSizeContribution;
60 import org.simantics.district.network.visualisations.model.DynamicSizeMap;
61 import org.simantics.district.network.visualisations.model.DynamicVisualisation;
62 import org.simantics.district.network.visualisations.model.SizeBarOptions;
63 import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsLocation;
64 import org.simantics.district.network.visualisations.model.SizeBarOptions.SizeBarsSize;
65 import org.simantics.utils.datastructures.Pair;
66 import org.simantics.utils.ui.dialogs.ShowError;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class DynamicVisualisationsUI extends Composite {
72 private static final Logger LOGGER = LoggerFactory.getLogger(DynamicVisualisationsUI.class);
74 private Resource parentResource;
75 private VisualisationListener listener;
76 private DynamicVisualisation visualisation;
78 private Button showSizeButton;
79 private Button sizeTicksButton;
80 private Button sizeGradientButton;
81 private Combo sizeLocationCombo;
82 private Combo sizeSizeCombo;
83 private Button showColorButton;
84 private Button colorTicksButton;
85 private Button colorGradientButton;
86 private Combo colorLocationCombo;
87 private Combo colorSizeCombo;
89 private Combo templateSelectionCombo;
91 private List<Supplier<Pair<String, DynamicColorContribution>>> colorSuppliers;
93 private Button removeVisualisationTemplateButton;
95 public DynamicVisualisationsUI(Composite parent, int style) {
97 // ScrolledComposite scrolledComposite = new ScrolledComposite(this, SWT.V_SCROLL);
98 // scrolledComposite.setLayout(new GridLayout(1, false));
99 // scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
101 // Composite firstContent = new Composite(scrolledComposite, SWT.NONE);
102 // firstContent.setLayout(new GridLayout(1, false));
103 // firstContent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
105 defaultInitializeUI(this);
107 // scrolledComposite.setContent(firstContent);
108 // scrolledComposite.setExpandHorizontal(true);
109 // scrolledComposite.setExpandVertical(true);
110 // scrolledComposite.setMinSize(firstContent.computeSize(SWT.DEFAULT, SWT.DEFAULT));
114 private void defaultInitializeUI(Composite parent) {
116 GridDataFactory.fillDefaults().grab(true, true).applyTo(parent);
117 GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(parent);
119 Composite selectionComposite = new Composite(parent, SWT.NONE);
120 GridDataFactory.fillDefaults().grab(true, false).applyTo(selectionComposite);
121 GridLayoutFactory.fillDefaults().numColumns(2).margins(5, 5).applyTo(selectionComposite);
123 Label templateNameLabel = new Label(selectionComposite, SWT.NONE);
124 templateNameLabel.setText("Visualisation template");
125 templateSelectionCombo = new Combo(selectionComposite, SWT.READ_ONLY);
126 GridDataFactory.fillDefaults().grab(true, false).applyTo(templateSelectionCombo);
127 templateSelectionCombo.addSelectionListener(new SelectionAdapter() {
130 public void widgetSelected(SelectionEvent e) {
131 String item = templateSelectionCombo.getItem(templateSelectionCombo.getSelectionIndex());
132 for (NamedResource template : visualisations) {
133 if (item.equals(template.getName())) {
134 Simantics.getSession().asyncRequest(new WriteRequest() {
137 public void perform(WriteGraph graph) throws DatabaseException {
138 Resource vf = DistrictNetworkUtil.getVisualisationFolder(graph, parentResource);
139 DistrictNetworkUtil.setActiveVisualisation(graph, vf, template.getResource());
148 Composite coloringObjectsComposite = new Composite(parent, SWT.NONE);
149 GridDataFactory.fillDefaults().grab(true, false).applyTo(coloringObjectsComposite);
150 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(coloringObjectsComposite);
151 initializeColoringObjects(coloringObjectsComposite);
153 Composite colorBarsComposite = new Composite(parent, SWT.NONE);
154 GridDataFactory.fillDefaults().grab(true, false).applyTo(colorBarsComposite);
155 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(colorBarsComposite);
156 initializeColorBars(colorBarsComposite);
158 Composite objectSizesComposite = new Composite(parent, SWT.NONE);
159 GridDataFactory.fillDefaults().grab(true, false).applyTo(objectSizesComposite);
160 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(objectSizesComposite);
161 initializeObjectSizes(objectSizesComposite);
163 Composite sizeBarsComposite = new Composite(parent, SWT.NONE);
164 GridDataFactory.fillDefaults().grab(true, false).applyTo(sizeBarsComposite);
165 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(sizeBarsComposite);
166 initializeSizeBars(sizeBarsComposite);
168 Composite buttonBarsComposite = new Composite(parent, SWT.NONE);
169 GridDataFactory.fillDefaults().grab(true, false).applyTo(buttonBarsComposite);
170 GridLayoutFactory.fillDefaults().numColumns(3).applyTo(buttonBarsComposite);
172 Button saveVisualisationTemplateAsButton = new Button(buttonBarsComposite, SWT.NONE);
173 saveVisualisationTemplateAsButton.setText("Save as visualisation template");
174 saveVisualisationTemplateAsButton.addSelectionListener(new SelectionAdapter() {
177 public void widgetSelected(SelectionEvent e) {
178 showSaveVisualisationTemplateDialog(e.widget.getDisplay().getActiveShell());
182 removeVisualisationTemplateButton = new Button(buttonBarsComposite, SWT.NONE);
183 removeVisualisationTemplateButton.setText("Remove");
184 removeVisualisationTemplateButton.setEnabled(visualisation != null && visualisation.getVisualisationResource() != null);
185 removeVisualisationTemplateButton.addSelectionListener(new SelectionAdapter() {
188 public void widgetSelected(SelectionEvent e) {
189 removeVisualisationTemplate(visualisation.getName(), Optional.of(visualisation.getVisualisationResource()));
195 protected void removeVisualisationTemplate(String name, Optional<Resource> of) {
196 if (of.isPresent()) {
197 Resource visualisation = of.get();
198 Simantics.getSession().asyncRequest(new WriteRequest() {
201 public void perform(WriteGraph graph) throws DatabaseException {
202 RemoverUtil.remove(graph, visualisation);
208 private void showSaveVisualisationTemplateDialog(Shell shell) {
210 InputDialog dialog = new InputDialog(shell, "Save visualisation template", "Give template a name", "", new IInputValidator() {
213 public String isValid(String newText) {
214 if (newText == null || newText.isEmpty())
215 return "Name cannot be empty";
220 if (dialog.open() == Dialog.OK) {
221 String name = dialog.getValue();
223 persistVisualisationTemplate(name, Optional.empty());
224 } catch (Exception e) {
225 LOGGER.error("Could not persist visualisation template", e);
226 ShowError.showError("Could not persist visualisation template", e.getMessage(), e);
231 private void persistCurrentVisualisationTemplateIfAvailable() {
232 if (visualisation != null) {
234 persistVisualisationTemplate(visualisation.getName(), Optional.of(visualisation.getVisualisationResource()));
235 } catch (Exception e1) {
236 LOGGER.error("Could not persist visualisation template", e1);
237 ShowError.showError("Could not persist visualisation template", e1.getMessage(), e1);
240 LOGGER.info("No current visualisation template selected for saving");
244 private void persistVisualisationTemplate(String templateName, Optional<Resource> existing) throws Exception {
246 List<Pair<String, DynamicColorContribution>> colorCollect = colorSuppliers.stream().map(s -> s.get()).filter(Objects::nonNull).collect(Collectors.toList());
248 String colorLocation = colorLocationCombo.getItem(colorLocationCombo.getSelectionIndex());
249 String colorSize = colorSizeCombo.getItem(colorSizeCombo.getSelectionIndex());
251 ColorBarOptions colorBarOptions = new ColorBarOptions()
252 .showColorBars(showColorButton.getSelection())
253 .showColorBarsTicks(colorTicksButton.getSelection())
254 .useGradients(colorGradientButton.getSelection())
255 .withLocation(ColorBarsLocation.valueOf(colorLocation))
256 .withSize(ColorBarsSize.valueOf(colorSize));
258 List<Pair<String, DynamicSizeContribution>> sizeCollect = sizeSuppliers.stream().map(s -> s.get()).filter(Objects::nonNull).collect(Collectors.toList());
260 String sizeLocation = sizeLocationCombo.getItem(sizeLocationCombo.getSelectionIndex());
261 String sizeSize = sizeSizeCombo.getItem(sizeSizeCombo.getSelectionIndex());
263 SizeBarOptions sizeBarOptions = new SizeBarOptions()
264 .showSizeBars(showSizeButton.getSelection())
265 .showSizeBarsTicks(sizeTicksButton.getSelection())
266 .useGradients(sizeGradientButton.getSelection())
267 .withLocation(SizeBarsLocation.valueOf(sizeLocation))
268 .withSize(SizeBarsSize.valueOf(sizeSize));
270 Simantics.getSession().asyncRequest(new WriteRequest() {
273 public void perform(WriteGraph graph) throws DatabaseException {
275 if (existing.isPresent()) {
276 exist = existing.get();
278 exist = DistrictNetworkUtil.createVisualisation(graph, parentResource, templateName);
281 DistrictNetworkUtil.setColorContributions(graph, exist, colorCollect);
283 DistrictNetworkUtil.setColorBarOptions(graph, exist, colorBarOptions);
284 DistrictNetworkUtil.setSizeContributions(graph, exist, sizeCollect);
285 DistrictNetworkUtil.setSizeBarOptions(graph, exist, sizeBarOptions);
290 private void initializeColoringObjects(Composite parent) {
291 Group group = new Group(parent, SWT.NONE);
292 group.setText("Coloring Objects");
293 GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
294 GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group);
297 createColoringObjectHeaderRow(group);
299 colorSuppliers = new ArrayList<>();
302 Pair<Collection<DynamicColoringObject>, Map<String, DynamicColorMap>> result = Simantics.getSession().syncRequest(new UniqueRead<Pair<Collection<DynamicColoringObject>, Map<String, DynamicColorMap>>>() {
305 public Pair<Collection<DynamicColoringObject>, Map<String, DynamicColorMap>> perform(ReadGraph graph) throws DatabaseException {
306 Map<String, DynamicColorMap> dynamicColorMaps = DynamicVisualisationsContributions.dynamicColorMaps(graph);
307 return Pair.make(DynamicVisualisationsContributions.dynamicColoringObjects(graph), dynamicColorMaps);
311 for (DynamicColoringObject object : result.first) {
312 colorSuppliers.add(createColoringObjectRow(group, object, result.second));
315 } catch (DatabaseException e) {
316 LOGGER.error("Could not create coloring objecst", e);
321 private void createColoringObjectHeaderRow(Composite parent) {
323 Label label = new Label(parent, SWT.NONE);
324 label.setText("Label");
325 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
327 label = new Label(parent, SWT.NONE);
328 label.setText("Used");
329 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
331 label = new Label(parent, SWT.NONE);
332 label.setText("Variable");
333 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
335 label = new Label(parent, SWT.NONE);
336 label.setText("Min");
337 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
339 label = new Label(parent, SWT.NONE);
340 label.setText("Max");
341 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
343 label = new Label(parent, SWT.NONE);
344 label.setText("Unit");
345 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
347 label = new Label(parent, SWT.NONE);
348 label.setText("ColorMap");
349 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
351 label = new Label(parent, SWT.NONE);
352 label.setText("Default");
353 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
356 private Map<String, ColoringObjectRow> coloringRows = new HashMap<>();
357 private Map<String, SizingObjectRow> sizingRows = new HashMap<>();
359 private VisualisationsListener visualisationsListener;
361 private Collection<NamedResource> visualisations;
363 private List<Supplier<Pair<String, DynamicSizeContribution>>> sizeSuppliers;
365 private static class ColoringObjectRow {
367 private final Label label;
368 private final Button usedButton;
369 private final Combo variableCombo;
370 private final Text minText;
371 private final Text maxText;
372 private final Text unit;
373 private final Combo colorMapCombo;
374 private final Button defaultButton;
376 public ColoringObjectRow(Label label, Button usedButton, Combo variableCombo, Text minText, Text maxText, Text unit,
377 Combo colorMapCombo, Button defaultButton) {
380 this.usedButton = usedButton;
381 this.variableCombo = variableCombo;
382 this.minText = minText;
383 this.maxText = maxText;
385 this.colorMapCombo = colorMapCombo;
386 this.defaultButton = defaultButton;
389 public void update(DynamicColorContribution colorContribution) {
390 String[] items = variableCombo.getItems();
391 for (int i = 0; i < items.length; i++) {
392 if (colorContribution.getLabel().equals(items[i])) {
393 variableCombo.select(i);
397 minText.setText(Double.toString(colorContribution.getDefaultMin()));
398 maxText.setText(Double.toString(colorContribution.getDefaultMax()));
399 unit.setText(colorContribution.getUnit());
401 String[] colorItems = colorMapCombo.getItems();
402 for (int i = 0; i < colorItems.length; i++) {
404 if (colorContribution.getDefaultColorMap().getLabel().equals(colorItems[i])) {
405 colorMapCombo.select(i);
409 usedButton.setSelection(colorContribution.isUsed());
410 defaultButton.setSelection(colorContribution.isUseDefault());
412 minText.setEnabled(!colorContribution.isUseDefault());
413 maxText.setEnabled(!colorContribution.isUseDefault());
414 colorMapCombo.setEnabled(!colorContribution.isUseDefault());
418 private static class SizingObjectRow {
420 private final Label label;
421 private final Button usedButton;
422 private final Combo variableCombo;
423 private final Text minText;
424 private final Text maxText;
425 private final Label unit;
426 private final Combo sizeMapCombo;
427 private final Button defaultButton;
429 public SizingObjectRow(Label label, Button usedButton, Combo variableCombo, Text minText, Text maxText, Label unit,
430 Combo sizeMapCombo, Button defaultButton) {
433 this.usedButton = usedButton;
434 this.variableCombo = variableCombo;
435 this.minText = minText;
436 this.maxText = maxText;
438 this.sizeMapCombo = sizeMapCombo;
439 this.defaultButton = defaultButton;
442 public void update(DynamicSizeContribution sizeContribution) {
443 String[] items = variableCombo.getItems();
444 for (int i = 0; i < items.length; i++) {
445 if (sizeContribution.getLabel().equals(items[i])) {
446 variableCombo.select(i);
450 minText.setText(Double.toString(sizeContribution.getDefaultMin()));
451 maxText.setText(Double.toString(sizeContribution.getDefaultMax()));
452 unit.setText(sizeContribution.getUnit());
454 String[] sizeItems = sizeMapCombo.getItems();
455 for (int i = 0; i < sizeItems.length; i++) {
456 if (sizeContribution.getDefaultSizeMap().getLabel().equals(sizeItems[i])) {
457 sizeMapCombo.select(i);
461 usedButton.setSelection(sizeContribution.isUsed());
462 defaultButton.setSelection(sizeContribution.isUseDefault());
464 minText.setEnabled(!sizeContribution.isUseDefault());
465 maxText.setEnabled(!sizeContribution.isUseDefault());
466 sizeMapCombo.setEnabled(!sizeContribution.isUseDefault());
470 private Supplier<Pair<String, DynamicColorContribution>> createColoringObjectRow(Composite parent, DynamicColoringObject object, Map<String, DynamicColorMap> colorMaps) {
471 Label label = new Label(parent, SWT.NONE);
472 label.setText(object.getColoringObject().getName());
473 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(label);
475 Map<String, DynamicColorContribution> colorContributions = object.getColorContributions();
477 Button usedButton = new Button(parent, SWT.CHECK);
478 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(usedButton);
479 addSelectionListener(usedButton);
481 Combo variableCombo = new Combo(parent, SWT.READ_ONLY);
482 variableCombo.setItems(colorContributions.keySet().toArray(new String[colorContributions.size()]));
483 addSelectionListener(variableCombo);
485 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(variableCombo);
487 Text minText = new Text(parent, SWT.BORDER);
488 GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).align(SWT.CENTER, SWT.CENTER).applyTo(minText);
489 addSelectionListener(minText);
491 Text maxText = new Text(parent, SWT.BORDER);
492 GridDataFactory.fillDefaults().grab(true, false).hint(150, SWT.DEFAULT).align(SWT.CENTER, SWT.CENTER).applyTo(maxText);
493 addSelectionListener(maxText);
495 Text unit = new Text(parent, SWT.READ_ONLY);
496 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(unit);
498 Combo colorMapCombo = new Combo(parent, SWT.READ_ONLY);
499 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(colorMapCombo);
500 colorMapCombo.setItems(colorMaps.keySet().toArray(new String[colorMaps.keySet().size()]));
501 addSelectionListener(colorMapCombo);
503 Button defaultButton = new Button(parent, SWT.CHECK);
504 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(defaultButton);
505 addSelectionListener(defaultButton);
506 defaultButton.addSelectionListener(new SelectionAdapter() {
509 public void widgetSelected(SelectionEvent e) {
510 int index = variableCombo.getSelectionIndex();
512 String key = variableCombo.getItem(index);
513 DynamicColorContribution cont = colorContributions.get(key);
515 minText.setText(Double.toString(cont.getDefaultMin()));
516 minText.setEnabled(!defaultButton.getSelection());
517 maxText.setText(Double.toString(cont.getDefaultMax()));
518 maxText.setEnabled(!defaultButton.getSelection());
519 unit.setText(cont.getUnit());
521 String[] items = colorMapCombo.getItems();
522 for (int i = 0; i < items.length; i++) {
523 String item = items[i];
524 if (item.equals(cont.getDefaultColorMap().getLabel())) {
525 colorMapCombo.select(i);
529 colorMapCombo.setEnabled(!defaultButton.getSelection());
534 variableCombo.addSelectionListener(new SelectionAdapter() {
537 public void widgetSelected(SelectionEvent e) {
538 // handle update for others
539 int index = variableCombo.getSelectionIndex();
541 String key = variableCombo.getItem(index);
542 DynamicColorContribution cont = colorContributions.get(key);
544 if (minText.getText().isEmpty()) {
545 minText.setText(Double.toString(cont.getDefaultMin()));
547 if (maxText.getText().isEmpty()) {
548 maxText.setText(Double.toString(cont.getDefaultMax()));
550 unit.setText(cont.getUnit());
552 String[] items = colorMapCombo.getItems();
553 for (int i = 0; i < items.length; i++) {
554 String item = items[i];
555 if (item.equals(cont.getDefaultColorMap().getLabel())) {
556 colorMapCombo.select(i);
561 defaultButton.setSelection(true);
566 coloringRows.put(object.getColoringObject().getName(), new ColoringObjectRow(label, usedButton, variableCombo, minText, maxText, unit, colorMapCombo, defaultButton));
568 return new Supplier<Pair<String, DynamicColorContribution>>() {
571 public Pair<String, DynamicColorContribution> get() {
572 int selectionIndex = variableCombo.getSelectionIndex();
573 if (selectionIndex >= 0) {
574 String key = variableCombo.getItem(selectionIndex);
575 DynamicColorContribution cont = colorContributions.get(key);
577 String colorMap = colorMapCombo.getItem(colorMapCombo.getSelectionIndex());
579 Map<String, DynamicColorMap> colorMaps = Simantics.getSession().syncRequest(new UniqueRead<Map<String, DynamicColorMap>>() {
582 public Map<String, DynamicColorMap> perform(ReadGraph graph) throws DatabaseException {
583 return DynamicVisualisationsContributions.dynamicColorMaps(graph);
586 DynamicColorMap dColorMap = colorMaps.get(colorMap);
587 String label = variableCombo.getItem(variableCombo.getSelectionIndex());
589 DynamicColorContribution dcc = new DynamicColorContribution(label, cont.getModuleName(), cont.getAttributeName(), unit.getText(), cont.getVariableGain(), cont.getVariableBias(), dColorMap, Double.parseDouble(minText.getText()), Double.parseDouble(maxText.getText()));
590 dcc.setUsed(usedButton.getSelection());
591 dcc.setUseDefault(defaultButton.getSelection());
593 return Pair.make(object.getColoringObject().getName(), dcc);
594 } catch (DatabaseException e) {
595 LOGGER.error("Could not get DynamicColorContribution", e);
604 private void createSizingObjectHeaderRow(Composite parent) {
606 Label label = new Label(parent, SWT.NONE);
607 label.setText("Label");
608 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
610 label = new Label(parent, SWT.NONE);
611 label.setText("Used");
612 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
614 label = new Label(parent, SWT.NONE);
615 label.setText("Variable");
616 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
618 label = new Label(parent, SWT.NONE);
619 label.setText("Min");
620 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
622 label = new Label(parent, SWT.NONE);
623 label.setText("Max");
624 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
626 label = new Label(parent, SWT.NONE);
627 label.setText("Unit");
628 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
630 label = new Label(parent, SWT.NONE);
631 label.setText("SizeMap");
632 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
634 label = new Label(parent, SWT.NONE);
635 label.setText("Default");
636 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(label);
639 private Supplier<Pair<String, DynamicSizeContribution>> createSizingObjectRow(Composite parent, DynamicSizingObject object, Map<String, DynamicSizeMap> sizeMaps) {
640 Label label = new Label(parent, SWT.NONE);
641 label.setText(object.getSizingObject().getName());
642 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(label);
644 Map<String, DynamicSizeContribution> sizeContributions = object.getSizeContributions();
646 Button usedButton = new Button(parent, SWT.CHECK);
647 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(usedButton);
648 addSelectionListener(usedButton);
650 Combo variableCombo = new Combo(parent, SWT.READ_ONLY);
651 variableCombo.setItems(sizeContributions.keySet().toArray(new String[sizeContributions.size()]));
652 addSelectionListener(variableCombo);
654 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(variableCombo);
656 Text minText = new Text(parent, SWT.BORDER);
657 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(minText);
658 addSelectionListener(minText);
660 Text maxText = new Text(parent, SWT.BORDER);
661 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(maxText);
662 addSelectionListener(maxText);
664 Label unit = new Label(parent, SWT.NONE);
665 GridDataFactory.fillDefaults().grab(true, false).align(SWT.CENTER, SWT.CENTER).applyTo(unit);
667 Combo sizeMapCombo = new Combo(parent, SWT.READ_ONLY);
668 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(sizeMapCombo);
669 sizeMapCombo.setItems(sizeMaps.keySet().toArray(new String[sizeMaps.keySet().size()]));
670 addSelectionListener(sizeMapCombo);
672 Button defaultButton = new Button(parent, SWT.CHECK);
673 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).applyTo(defaultButton);
674 addSelectionListener(defaultButton);
675 defaultButton.addSelectionListener(new SelectionAdapter() {
678 public void widgetSelected(SelectionEvent e) {
679 int index = variableCombo.getSelectionIndex();
681 String key = variableCombo.getItem(index);
682 DynamicSizeContribution cont = sizeContributions.get(key);
684 minText.setText(Double.toString(cont.getDefaultMin()));
685 minText.setEnabled(!defaultButton.getSelection());
686 maxText.setText(Double.toString(cont.getDefaultMax()));
687 maxText.setEnabled(!defaultButton.getSelection());
688 unit.setText(cont.getUnit());
690 String[] items = sizeMapCombo.getItems();
691 for (int i = 0; i < items.length; i++) {
692 String item = items[i];
693 if (item.equals(cont.getDefaultSizeMap().getLabel())) {
694 sizeMapCombo.select(i);
698 sizeMapCombo.setEnabled(!defaultButton.getSelection());
703 variableCombo.addSelectionListener(new SelectionAdapter() {
706 public void widgetSelected(SelectionEvent e) {
707 // handle update for others
708 String key = variableCombo.getItem(variableCombo.getSelectionIndex());
709 DynamicSizeContribution cont = sizeContributions.get(key);
711 if (minText.getText().isEmpty()) {
712 minText.setText(Double.toString(cont.getDefaultMin()));
714 if (maxText.getText().isEmpty()) {
715 maxText.setText(Double.toString(cont.getDefaultMax()));
717 unit.setText(cont.getUnit());
719 String[] items = sizeMapCombo.getItems();
720 for (int i = 0; i < items.length; i++) {
721 String item = items[i];
722 if (item.equals(cont.getDefaultSizeMap().getLabel())) {
723 sizeMapCombo.select(i);
728 defaultButton.setSelection(true);
732 sizingRows.put(object.getSizingObject().getName(), new SizingObjectRow(label, usedButton, variableCombo, minText, maxText, unit, sizeMapCombo, defaultButton));
734 return new Supplier<Pair<String, DynamicSizeContribution>>() {
737 public Pair<String, DynamicSizeContribution> get() {
738 int selectionIndex = variableCombo.getSelectionIndex();
739 if (selectionIndex >= 0) {
740 String key = variableCombo.getItem(selectionIndex);
741 DynamicSizeContribution cont = sizeContributions.get(key);
743 String sizeMap = sizeMapCombo.getItem(sizeMapCombo.getSelectionIndex());
745 Map<String, DynamicSizeMap> sizeMaps = Simantics.getSession().syncRequest(new UniqueRead<Map<String, DynamicSizeMap>>() {
748 public Map<String, DynamicSizeMap> perform(ReadGraph graph) throws DatabaseException {
749 return DynamicVisualisationsContributions.dynamicSizeMaps(graph);
752 DynamicSizeMap dColorMap = sizeMaps.get(sizeMap);
753 String label = variableCombo.getItem(variableCombo.getSelectionIndex());
755 DynamicSizeContribution dsc = new DynamicSizeContribution(label, cont.getModuleName(), cont.getAttributeName(), unit.getText(), cont.getVariableGain(), cont.getVariableBias(), dColorMap, Double.parseDouble(minText.getText()), Double.parseDouble(maxText.getText()));
756 dsc.setUsed(usedButton.getSelection());
757 dsc.setUseDefault(defaultButton.getSelection());
759 return Pair.make(object.getSizingObject().getName(), dsc);
760 } catch (DatabaseException e) {
761 LOGGER.error("Could not get DynamicColorContribution", e);
770 private void initializeColorBars(Composite parent) {
771 Group group = new Group(parent, SWT.NONE);
772 group.setText("Color Bars");
773 GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
774 GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group);
776 createColorBars(group);
779 private void createColorBars(Composite parent) {
781 showColorButton = new Button(parent, SWT.CHECK);
782 showColorButton.setText("Show");
783 addSelectionListener(showColorButton);
785 colorTicksButton = new Button(parent, SWT.CHECK);
786 colorTicksButton.setText("Ticks");
787 addSelectionListener(colorTicksButton);
789 colorGradientButton = new Button(parent, SWT.CHECK);
790 colorGradientButton.setText("Gradients");
791 addSelectionListener(colorGradientButton);
793 Label label = new Label(parent, SWT.NONE);
794 label.setText("Location");
795 colorLocationCombo = new Combo(parent, SWT.READ_ONLY);
796 String[] colorLocationItems = Stream.of(ColorBarsLocation.values()).map(size -> size.toString()).toArray(String[]::new);
797 colorLocationCombo.setItems(colorLocationItems);
798 if (colorLocationItems.length > 0) {
799 colorLocationCombo.select(0);
801 addSelectionListener(colorLocationCombo);
803 label = new Label(parent, SWT.NONE);
804 label.setText("Size");
805 colorSizeCombo = new Combo(parent, SWT.READ_ONLY);
806 String[] colorSizeItems = Stream.of(ColorBarsSize.values()).map(size -> size.toString()).toArray(String[]::new);
807 colorSizeCombo.setItems(colorSizeItems);
808 if (colorSizeItems.length > 0) {
809 colorSizeCombo.select(0);
811 addSelectionListener(colorSizeCombo);
814 private void initializeObjectSizes(Composite parent) {
815 Group group = new Group(parent, SWT.NONE);
816 group.setText("Object Sizes");
817 GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
818 GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group);
821 createSizingObjectHeaderRow(group);
822 createObjectSizes(group);
826 private void createObjectSizes(Composite parent) {
828 sizeSuppliers = new ArrayList<>();
830 Pair<Collection<DynamicSizingObject>, Map<String, DynamicSizeMap>> resultSizing = Simantics.getSession().syncRequest(new UniqueRead<Pair<Collection<DynamicSizingObject>, Map<String, DynamicSizeMap>>>() {
833 public Pair<Collection<DynamicSizingObject>, Map<String, DynamicSizeMap>> perform(ReadGraph graph) throws DatabaseException {
834 Map<String, DynamicSizeMap> dynamicSizeMaps = DynamicVisualisationsContributions.dynamicSizeMaps(graph);
835 return Pair.make(DynamicVisualisationsContributions.dynamicSizingObjects(graph), dynamicSizeMaps);
839 for (DynamicSizingObject object : resultSizing.first) {
840 sizeSuppliers.add(createSizingObjectRow(parent, object, resultSizing.second));
842 } catch (DatabaseException e) {
843 LOGGER.error("Could not create object sizes", e);
847 private void initializeSizeBars(Composite parent) {
848 Group group = new Group(parent, SWT.NONE);
849 group.setText("Size Bars");
850 GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
851 GridLayoutFactory.fillDefaults().numColumns(8).margins(5, 5).applyTo(group);
853 createSizeBars(group);
856 private void createSizeBars(Composite parent) {
857 showSizeButton = new Button(parent, SWT.CHECK);
858 showSizeButton.setText("Show");
859 addSelectionListener(showSizeButton);
861 sizeTicksButton = new Button(parent, SWT.CHECK);
862 sizeTicksButton.setText("Ticks");
863 addSelectionListener(sizeTicksButton);
865 sizeGradientButton = new Button(parent, SWT.CHECK);
866 sizeGradientButton.setText("Gradient");
867 addSelectionListener(sizeGradientButton);
869 Label label = new Label(parent, SWT.NONE);
870 label.setText("Location");
871 sizeLocationCombo = new Combo(parent, SWT.READ_ONLY);
872 String[] sizeLocationItems = Stream.of(SizeBarsLocation.values()).map(size -> size.toString()).toArray(String[]::new);
873 sizeLocationCombo.setItems(sizeLocationItems);
874 if (sizeLocationItems.length > 0) {
875 sizeLocationCombo.select(0);
877 addSelectionListener(sizeLocationCombo);
879 label = new Label(parent, SWT.NONE);
880 label.setText("Size");
881 sizeSizeCombo = new Combo(parent, SWT.READ_ONLY);
882 String[] sizeSizeItems = Stream.of(SizeBarsSize.values()).map(size -> size.toString()).toArray(String[]::new);
883 sizeSizeCombo.setItems(sizeSizeItems);
884 if (sizeSizeItems.length > 0) {
885 sizeSizeCombo.select(0);
887 addSelectionListener(sizeSizeCombo);
890 private void addSelectionListener(Widget widget) {
891 if (widget instanceof Button) {
892 ((Button) widget).addSelectionListener(new SelectionAdapter() {
895 public void widgetSelected(SelectionEvent e) {
896 persistCurrentVisualisationTemplateIfAvailable();
899 } else if (widget instanceof Combo) {
900 ((Combo) widget).addSelectionListener(new SelectionAdapter() {
903 public void widgetSelected(SelectionEvent e) {
904 persistCurrentVisualisationTemplateIfAvailable();
907 } else if (widget instanceof Text) {
908 ((Text) widget).addFocusListener(new FocusAdapter() {
911 public void focusLost(FocusEvent e) {
912 persistCurrentVisualisationTemplateIfAvailable();
915 ((Text) widget).addKeyListener(new KeyAdapter() {
918 public void keyReleased(KeyEvent e) {
919 if(e.keyCode == SWT.CR || e.keyCode == SWT.LF) {
920 persistCurrentVisualisationTemplateIfAvailable();
927 public void setParentResource(Resource parentResource) {
928 if (this.parentResource != parentResource) {
929 this.parentResource = parentResource;
934 private void updateListening() {
935 if (visualisationsListener != null)
936 visualisationsListener.dispose();
937 visualisationsListener = new VisualisationsListener(this);
938 Simantics.getSession().asyncRequest(new DynamicVisualisationsRequest(parentResource), visualisationsListener);
940 if (listener != null)
942 listener = new VisualisationListener(this);
943 Simantics.getSession().asyncRequest(new ActiveDynamicVisualisationsRequest(parentResource), listener);
946 private static class VisualisationsListener implements Listener<Collection<NamedResource>> {
948 private static final Logger LOGGER = LoggerFactory.getLogger(VisualisationsListener.class);
950 private boolean disposed;
951 private DynamicVisualisationsUI ui;
953 public VisualisationsListener(DynamicVisualisationsUI ui) {
958 public void execute(Collection<NamedResource> result) {
959 ui.updateVisualisations(result);
963 public void exception(Throwable t) {
964 LOGGER.error("Could not listen visualisation", t);
968 public boolean isDisposed() {
969 return disposed || ui.isDisposed();
972 public void dispose() {
973 this.disposed = true;
977 private static class VisualisationListener implements Listener<DynamicVisualisation> {
979 private static final Logger LOGGER = LoggerFactory.getLogger(VisualisationListener.class);
981 private boolean disposed;
982 private DynamicVisualisationsUI ui;
984 public VisualisationListener(DynamicVisualisationsUI ui) {
989 public void execute(DynamicVisualisation result) {
990 ui.updateVisualisation(result);
994 public void exception(Throwable t) {
995 LOGGER.error("Could not listen visualisation", t);
999 public boolean isDisposed() {
1000 return disposed || ui.isDisposed();
1003 public void dispose() {
1004 this.disposed = true;
1008 public void updateVisualisation(DynamicVisualisation result) {
1009 this.visualisation = result;
1010 Display.getDefault().asyncExec(() -> {
1011 if (getParent().isDisposed())
1014 removeVisualisationTemplateButton.setEnabled(visualisation != null && visualisation.getVisualisationResource() != null);
1016 if (visualisation != null) {
1017 String[] items = templateSelectionCombo.getItems();
1018 for (int i = 0; i < items.length; i++) {
1019 if (visualisation.getName().equals(items[i])) {
1020 templateSelectionCombo.select(i);
1025 Map<String, DynamicColorContribution> colorContributions = visualisation.getColorContributions();
1026 for (Entry<String, DynamicColorContribution> entry : colorContributions.entrySet()) {
1028 ColoringObjectRow coloringObjectRow = coloringRows.get(entry.getKey());
1029 if (coloringObjectRow != null) {
1031 coloringObjectRow.update(entry.getValue());
1034 LOGGER.info("No coloring object visualisation row for key {}", entry.getKey());
1037 ColorBarOptions colorOptions = visualisation.getColorBarOptions();
1038 showColorButton.setSelection(colorOptions.isShowColorBars());
1039 colorTicksButton.setSelection(colorOptions.isShowColorBarsTicks());
1040 colorGradientButton.setSelection(colorOptions.isUseGradients());
1041 for (int i = 0; i < colorLocationCombo.getItems().length; i++) {
1042 String item = colorLocationCombo.getItem(i);
1043 if (item.equals(colorOptions.getLocation().toString())) {
1044 colorLocationCombo.select(i);
1048 for (int i = 0; i < colorSizeCombo.getItems().length; i++) {
1049 String item = colorSizeCombo.getItem(i);
1050 if (item.equals(colorOptions.getSize().toString())) {
1051 colorSizeCombo.select(i);
1056 Map<String, DynamicSizeContribution> sizeContributions = visualisation.getSizeContributions();
1057 for (Entry<String, DynamicSizeContribution> entry : sizeContributions.entrySet()) {
1059 SizingObjectRow sizingObjectRow = sizingRows.get(entry.getKey());
1060 if (sizingObjectRow != null) {
1062 sizingObjectRow.update(entry.getValue());
1065 LOGGER.info("No sizing object visualisation row for key {}", entry.getKey());
1068 SizeBarOptions sizeOptions = visualisation.getSizeBarOptions();
1069 showSizeButton.setSelection(sizeOptions.isShowSizeBars());
1070 sizeTicksButton.setSelection(sizeOptions.isShowSizeBarsTicks());
1071 sizeGradientButton.setSelection(sizeOptions.isUseGradients());
1072 for (int i = 0; i < sizeLocationCombo.getItems().length; i++) {
1073 String item = sizeLocationCombo.getItem(i);
1074 if (item.equals(sizeOptions.getLocation().toString())) {
1075 sizeLocationCombo.select(i);
1079 for (int i = 0; i < sizeSizeCombo.getItems().length; i++) {
1080 String item = sizeSizeCombo.getItem(i);
1081 if (item.equals(sizeOptions.getSize().toString())) {
1082 sizeSizeCombo.select(i);
1090 public void updateVisualisations(Collection<NamedResource> result) {
1091 this.visualisations = result;
1093 Display.getDefault().asyncExec(() -> {
1094 if (getParent().isDisposed())
1096 templateSelectionCombo.setItems(visualisations.stream().map(NamedResource::getName).collect(Collectors.toList()).toArray(new String[visualisations.size()]));
1098 if (visualisation != null) {
1099 String[] items = templateSelectionCombo.getItems();
1100 for (int i = 0; i < items.length; i++) {
1101 if (visualisation.getName().equals(items[i])) {
1102 templateSelectionCombo.select(i);