]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java
Add participant for visualizing district finder search results
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / DistrictDiagramViewer.java
1 package org.simantics.district.network.ui;
2
3 import java.awt.Color;
4 import java.awt.geom.AffineTransform;
5 import java.util.Collections;
6 import java.util.Map;
7 import java.util.Objects;
8 import java.util.concurrent.TimeUnit;
9 import java.util.function.Consumer;
10 import java.util.function.Supplier;
11
12 import org.eclipse.e4.core.contexts.IEclipseContext;
13 import org.eclipse.e4.core.services.events.IEventBroker;
14 import org.eclipse.ui.PlatformUI;
15 import org.simantics.datatypes.literal.RGB;
16 import org.simantics.db.ReadGraph;
17 import org.simantics.db.Resource;
18 import org.simantics.db.common.request.PossibleIndexRoot;
19 import org.simantics.db.common.request.UnaryRead;
20 import org.simantics.db.exception.DatabaseException;
21 import org.simantics.db.procedure.Listener;
22 import org.simantics.diagram.ui.DiagramModelHints;
23 import org.simantics.district.network.DistrictNetworkUtil;
24 import org.simantics.district.network.ontology.DistrictNetworkResource;
25 import org.simantics.district.network.ui.internal.Activator;
26 import org.simantics.district.network.ui.nodes.DistrictRenderingPreparationNode;
27 import org.simantics.district.network.ui.nodes.DistrictSelectionNode;
28 import org.simantics.district.network.ui.participants.DNPointerInteractor;
29 import org.simantics.district.network.ui.participants.DistrictFinderVisualisationParticipant;
30 import org.simantics.district.network.ui.participants.DynamicVisualisationContributionsParticipant;
31 import org.simantics.district.network.ui.participants.MapRulerPainter;
32 import org.simantics.district.network.visualisations.DynamicVisualisations;
33 import org.simantics.district.network.visualisations.model.ColorBarOptions;
34 import org.simantics.district.network.visualisations.model.DynamicColorContribution;
35 import org.simantics.district.network.visualisations.model.DynamicSizeContribution;
36 import org.simantics.district.network.visualisations.model.SizeBarOptions;
37 import org.simantics.g2d.canvas.ICanvasContext;
38 import org.simantics.g2d.canvas.impl.CanvasContext;
39 import org.simantics.g2d.diagram.handler.PickRequest.PickFilter;
40 import org.simantics.g2d.diagram.participant.DelayedBatchElementPainter;
41 import org.simantics.g2d.diagram.participant.ElementPainter;
42 import org.simantics.g2d.diagram.participant.ElementPainterConfiguration;
43 import org.simantics.g2d.diagram.participant.Selection;
44 import org.simantics.g2d.diagram.participant.ZOrderHandler;
45 import org.simantics.g2d.participant.BackgroundPainter;
46 import org.simantics.g2d.participant.GridPainter;
47 import org.simantics.g2d.participant.PanZoomRotateHandler;
48 import org.simantics.g2d.participant.RenderingQualityInteractor;
49 import org.simantics.g2d.participant.TransformUtil;
50 import org.simantics.g2d.participant.ZoomToAreaHandler;
51 import org.simantics.g2d.scenegraph.SceneGraphConstants;
52 import org.simantics.maps.MapScalingTransform;
53 import org.simantics.maps.eclipse.MapPainter;
54 import org.simantics.maps.sg.commands.MapCommands;
55 import org.simantics.modeling.ui.diagramEditor.DiagramViewer;
56 import org.simantics.scenegraph.g2d.G2DParentNode;
57 import org.simantics.scenegraph.g2d.events.command.Command;
58 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
59 import org.simantics.scenegraph.g2d.events.command.Commands;
60 import org.simantics.utils.datastructures.hints.IHintContext;
61 import org.simantics.utils.datastructures.hints.IHintContext.Key;
62 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 public class DistrictDiagramViewer extends DiagramViewer {
67
68         private static final Logger LOGGER = LoggerFactory.getLogger(DistrictDiagramViewer.class);
69
70     @Override
71     protected void addDiagramParticipants(ICanvasContext ctx) {
72         ctx.add(new ZOrderHandler());
73         ctx.add(new Selection());
74         ctx.add(new ElementPainter(new ElementPainterConfiguration().selectionNodeClass(DistrictSelectionNode.class)));
75         ctx.add(new DNPointerInteractor());
76         
77         AffineTransform tr = new AffineTransform(MapScalingTransform.INSTANCE);
78         ctx.add(new MapPainter(tr));
79         
80         DynamicVisualisationContributionsParticipant dynamicVisualisationContributionsParticipant = new DynamicVisualisationContributionsParticipant(tr);
81         ctx.add(new NetworkDrawingParticipant(dynamicVisualisationContributionsParticipant, tr));
82         ctx.add(dynamicVisualisationContributionsParticipant);
83         
84         // Optimize AffineTransform memory allocations during district diagram rendering
85         G2DParentNode spatialRoot = (G2DParentNode) ctx.getSceneGraph().lookupNode(SceneGraphConstants.SPATIAL_ROOT_NODE_ID);
86         DistrictRenderingPreparationNode prepNode = new DistrictRenderingPreparationNode();
87         prepNode.setZIndex(Integer.MIN_VALUE / 2);
88         spatialRoot.addNode("districtRenderingPrepareNode", prepNode);
89
90         
91         IEclipseContext workbenchContext = getWorkbenchContext();
92         IEventBroker eventBroker = workbenchContext.get(IEventBroker.class);
93         DistrictFinderVisualisationParticipant districtFinderVisualisationParticipant = new DistrictFinderVisualisationParticipant(eventBroker);
94         ctx.add(districtFinderVisualisationParticipant);
95         
96     }
97
98     public static IEclipseContext getWorkbenchContext(){
99         return PlatformUI.getWorkbench().getService(IEclipseContext.class);
100     }
101
102     protected String getPopupId() {
103         return "#DistrictDiagramPopup";
104     }
105
106     @Override
107     protected void fillInitialDiagramHints(Resource diagram, IHintContext initialHints) throws DatabaseException {
108         super.fillInitialDiagramHints(diagram, initialHints);
109         
110     }
111
112     @Override
113     public void initializeCanvasContext(CanvasContext ctx) {
114         super.initializeCanvasContext(ctx);
115         IHintContext h = ctx.getDefaultHintContext();
116         h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 10000.0);
117         h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 0.01);
118         h.setHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE, diagramResource);
119     }
120
121     @Override
122     protected void addPainterParticipants(ICanvasContext ctx) {
123         ctx.add(new RenderingQualityInteractor());
124         ctx.add(new DelayedBatchElementPainter(PickFilter.FILTER_MONITORS, 500, TimeUnit.MILLISECONDS));
125     }
126     
127     @Override
128     protected void addGridRulerBackgroundParticipants(CanvasContext ctx) {
129         ctx.add(new GridPainter());
130         ctx.add(new MapRulerPainter());
131         ctx.add(new BackgroundPainter());
132     }
133     
134     protected void addViewManipulationParticipants(CanvasContext ctx) {
135         // Let's replace with our special util
136         TransformUtil util = ctx.getAtMostOneItemOfClass(TransformUtil.class);
137         if (util != null)
138             ctx.remove(util);
139         ctx.add(new DistrictTransformUtil());
140         ctx.add(new DistrictPanZoomRotateHandler());
141         //ctx.add(new MousePanZoomInteractor());
142         //ctx.add(new MultitouchPanZoomRotateInteractor());
143         // ctx.add( new OrientationRestorer() );
144         ctx.add(new ZoomToAreaHandler());
145     }
146
147     @Override
148     protected void loadPageSettings(ICanvasContext ctx) {
149         super.loadPageSettings(ctx);
150         // this might be the wrong place to start such listening but at least
151         // super.loadPageSettings() does async-db-operations
152         setupDrawMapEnabled();
153         setupBackgroundColor();
154         setupColoringObjects();
155         setupColorBarOptions();
156         setupSizingObjects();
157         setupSizeBarOptions();
158         setupShowElevationServerBoundingBox();
159         
160         // add listeners
161         DistrictDiagramViewerListener[] listeners = Activator.getInstance().getDistrictDiagramViewerListeners();
162         if (listeners != null) {
163             for (DistrictDiagramViewerListener listener : listeners) {
164                 listener.diagramLoaded(getRuntime(), canvasContext);
165             }
166         }
167     }
168     
169     @Override
170     public void dispose() {
171         DistrictDiagramViewerListener[] listeners = Activator.getInstance().getDistrictDiagramViewerListeners();
172         if (listeners != null) {
173             Resource runtime = getRuntime();
174             for (DistrictDiagramViewerListener listener : listeners) {
175                 listener.diagramDisposed(runtime, canvasContext);
176             }
177         }
178         super.dispose();
179     }
180     
181     private void setupDrawMapEnabled() {
182         sessionContext.getSession().asyncRequest(new DrawMapEnabledRequest(getInputResource()), new DrawMapEnabledListener(
183                 result -> canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), result ? Commands.MAP_ENABLE : Commands.MAP_DISABLE)),
184                 () -> DistrictDiagramViewer.this.isDisposed()));
185     }
186
187     private void setupBackgroundColor() {
188         sessionContext.getSession().asyncRequest(new MapBackgroundColorRequest(getInputResource()), new MapBackgroundColorListener(
189                 result -> queueBackgroundColorChangeEvent(result),
190                 () -> DistrictDiagramViewer.this.isDisposed()));
191     }
192
193     private void queueBackgroundColorChangeEvent(RGB.Integer result) {
194         if (result != null) {
195             Color backgroundColor = new Color(result.red, result.green, result.blue);
196             canvasContext.getDefaultHintContext().setHint(MapCommands.KEY_MAP_BACKGROUND_COLOR, backgroundColor);
197             canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MapCommands.MAP_BACKGROUND_COLOR_CHANGE));
198         }
199     }
200
201     private void setupColoringObjects() {
202         sessionContext.getSession().asyncRequest(new ColoringObjectsRequest(getInputResource()), new ColoringObjectsListener(
203                 result -> queueColoringObjectsChangeEvent(result),
204                 () -> DistrictDiagramViewer.this.isDisposed()));
205     }
206
207     
208     private void setupColorBarOptions() {
209         sessionContext.getSession().asyncRequest(new ColorBarOptionsRequest(getInputResource()), new ColorBarOptionsListener(
210                 result -> queueColorBarOptionsChangeEvent(result),
211                 () -> DistrictDiagramViewer.this.isDisposed()));
212     }
213
214     private void setupSizingObjects() {
215         sessionContext.getSession().asyncRequest(new SizingObjectsRequest(getInputResource()), new SizingObjectsListener(
216                 result -> queueSizingObjectsChangeEvent(result),
217                 () -> DistrictDiagramViewer.this.isDisposed()));
218     }
219
220     private void setupSizeBarOptions() {
221         sessionContext.getSession().asyncRequest(new SizeBarOptionsRequest(getInputResource()), new SizeBarOptionsListener(
222                 result -> queueSizeBarOptionsChangeEvent(result),
223                 () -> DistrictDiagramViewer.this.isDisposed()));
224     }
225
226     private void setupShowElevationServerBoundingBox() {
227         sessionContext.getSession().asyncRequest(new ShowElevationServerRequest(getInputResource()), new ShowElevationServerListener(
228                 result -> queueShowElevationServerChangeEvent(result),
229                 () -> DistrictDiagramViewer.this.isDisposed()));
230     }
231
232     public static final Key KEY_MAP_COLOR_BAR_OPTIONS = new KeyOf(ColorBarOptions.class, "colorBarOptions");
233     public static final Command MAP_COLOR_BAR_OPTIONS_CHANGE = new Command("colorBarOptionsChange");
234     public static final Key KEY_MAP_SIZE_BAR_OPTIONS = new KeyOf(SizeBarOptions.class, "sizeBarOptions");
235     public static final Command MAP_SIZE_BAR_OPTIONS_CHANGE = new Command("sizeBarOptionsChange");
236     
237     public static final Key KEY_MAP_COLORING_OBJECTS = new KeyOf(Map.class, "coloringObjects");
238     public static final Command MAP_COLORING_OBJECTS_CHANGE = new Command("coloringObjectsChange");
239     
240     public static final Key KEY_MAP_SIZING_OBJECTS = new KeyOf(Map.class, "sizingObjects");
241     public static final Command MAP_SIZING_OBJECTS_CHANGE = new Command("sizingObjectsChange");
242
243     public static final Key KEY_SHOW_ELEVATION_SERVER = new KeyOf(Boolean.class, "showElevationServer");
244     public static final Command SHOW_ELEVATION_SERVER_CHANGE = new Command("showElevationServerChange");
245
246     private void queueColoringObjectsChangeEvent(Map<String, DynamicColorContribution> result) {
247         queueEventInternal(KEY_MAP_COLORING_OBJECTS, MAP_COLORING_OBJECTS_CHANGE, result);
248     }
249
250     private void queueColorBarOptionsChangeEvent(ColorBarOptions result) {
251         queueEventInternal(KEY_MAP_COLOR_BAR_OPTIONS, MAP_COLOR_BAR_OPTIONS_CHANGE, result);
252     }
253
254     private void queueSizingObjectsChangeEvent(Map<String, DynamicSizeContribution> result) {
255         queueEventInternal(KEY_MAP_SIZING_OBJECTS, MAP_SIZING_OBJECTS_CHANGE, result);
256     }
257
258     private void queueSizeBarOptionsChangeEvent(SizeBarOptions result) {
259         queueEventInternal(KEY_MAP_SIZE_BAR_OPTIONS, MAP_SIZE_BAR_OPTIONS_CHANGE, result);
260     }
261
262     private void queueShowElevationServerChangeEvent(Boolean result) {
263         queueEventInternal(KEY_SHOW_ELEVATION_SERVER, SHOW_ELEVATION_SERVER_CHANGE, result);
264     }
265
266     private void queueEventInternal(Key key, Command command, Object result) {
267         if (result != null && !canvasContext.isDisposed()) {
268             canvasContext.getThreadAccess().asyncExec(() -> {
269                 canvasContext.getDefaultHintContext().setHint(key, result);
270                 canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), command));
271             });
272         } else {
273             LOGGER.info("Result is either null or canvasContext is disposed", String.valueOf(result));
274         }
275     }
276
277     private static class DrawMapEnabledRequest extends UnaryRead<Resource, Boolean> {
278
279         public DrawMapEnabledRequest(Resource diagram) {
280             super(diagram);
281         }
282
283         @Override
284         public Boolean perform(ReadGraph graph) throws DatabaseException {
285             return DistrictNetworkUtil.drawMapEnabled(graph, parameter);
286         }
287     }
288
289     private static class DrawMapEnabledListener implements Listener<Boolean> {
290
291         private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class);
292
293         private Consumer<Boolean> callback;
294         private Supplier<Boolean> isDisposed;
295         
296         private Boolean lastResult;
297
298         public DrawMapEnabledListener(Consumer<Boolean> callback, Supplier<Boolean> isDisposed) {
299             this.callback = callback;
300             this.isDisposed = isDisposed;
301         }
302
303         @Override
304         public void execute(Boolean result) {
305             // Minor optimization
306             if (!Objects.equals(lastResult, result)) {
307                 lastResult = result;
308                 callback.accept(result);
309             }
310         }
311
312         @Override
313         public void exception(Throwable t) {
314             LOGGER.error("Could not listen if draw map is enabled", t);
315         }
316
317         @Override
318         public boolean isDisposed() {
319             return isDisposed.get();
320         }
321     }
322     
323     private static class MapBackgroundColorRequest extends UnaryRead<Resource, RGB.Integer> {
324
325         public MapBackgroundColorRequest(Resource diagram) {
326             super(diagram);
327         }
328
329         @Override
330         public RGB.Integer perform(ReadGraph graph) throws DatabaseException {
331             return DistrictNetworkUtil.backgroundColor(graph, parameter);
332         }
333     }
334
335     private static class MapBackgroundColorListener implements Listener<RGB.Integer> {
336
337         private static final Logger LOGGER = LoggerFactory.getLogger(MapBackgroundColorListener.class);
338
339         private Consumer<RGB.Integer> callback;
340         private Supplier<Boolean> isDisposed;
341         
342         private RGB.Integer lastResult;
343
344         public MapBackgroundColorListener(Consumer<RGB.Integer> callback, Supplier<Boolean> isDisposed) {
345             this.callback = callback;
346             this.isDisposed = isDisposed;
347         }
348
349         @Override
350         public void execute(RGB.Integer result) {
351             if (!Objects.equals(lastResult, result)) {
352                 lastResult = result;
353                 callback.accept(result);
354             }
355         }
356
357         @Override
358         public void exception(Throwable t) {
359             LOGGER.error("Could not listen map background color", t);
360         }
361
362         @Override
363         public boolean isDisposed() {
364             return isDisposed.get();
365         }
366     }
367
368     private static class ColorBarOptionsRequest extends UnaryRead<Resource, ColorBarOptions> {
369
370         public ColorBarOptionsRequest(Resource diagram) {
371             super(diagram);
372         }
373
374         @Override
375         public ColorBarOptions perform(ReadGraph graph) throws DatabaseException {
376             DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
377             Resource model = graph.syncRequest(new PossibleIndexRoot(parameter));
378             if (model != null) {
379                 Resource vf = DynamicVisualisations.getVisualisationFolder(graph, model);
380                 if (vf != null) {
381                     Resource activeVisualisation = graph.getPossibleObject(vf, DN.Diagram_hasActiveVisualisation);
382                     if (activeVisualisation != null) {
383                         return DynamicVisualisations.colorBarOptions(graph, activeVisualisation);
384                     }
385                 } else {
386                     LOGGER.debug("No visualisation folder available for model {}", model);
387                 }
388             }
389             return ColorBarOptions.useDefault();
390         }
391     }
392
393     private static class ColoringObjectsRequest extends UnaryRead<Resource, Map<String,DynamicColorContribution>> {
394
395         public ColoringObjectsRequest(Resource diagram) {
396             super(diagram);
397         }
398
399         @Override
400         public Map<String, DynamicColorContribution> perform(ReadGraph graph) throws DatabaseException {
401             DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
402             Resource model = graph.syncRequest(new PossibleIndexRoot(parameter));
403             if (model != null) {
404                 Resource vf = DynamicVisualisations.getVisualisationFolder(graph, model);
405                 if (vf != null) {
406                     Resource activeVisualisation = graph.getPossibleObject(vf, DN.Diagram_hasActiveVisualisation);
407                     if (activeVisualisation != null) {
408                         return DynamicVisualisations.colorContributions(graph, activeVisualisation);
409                     }
410                 } else {
411                     LOGGER.debug("No visualisation folder available for model {}", model);
412                 }
413             }
414             return Collections.emptyMap();
415         }
416     }
417     
418     private static class ColoringObjectsListener implements Listener<Map<String,DynamicColorContribution>> {
419
420         private static final Logger LOGGER = LoggerFactory.getLogger(ColoringObjectsListener.class);
421
422         private Consumer<Map<String,DynamicColorContribution>> callback;
423         private Supplier<Boolean> isDisposed;
424         
425         //private Map<String, DynamicColorContribution> lastResult
426
427         public ColoringObjectsListener(Consumer<Map<String,DynamicColorContribution>> callback, Supplier<Boolean> isDisposed) {
428             this.callback = callback;
429             this.isDisposed = isDisposed;
430         }
431
432         @Override
433         public void execute(Map<String,DynamicColorContribution> result) {
434             callback.accept(result);
435         }
436
437         @Override
438         public void exception(Throwable t) {
439             LOGGER.error("Could not listen ColoringObjects", t);
440         }
441
442         @Override
443         public boolean isDisposed() {
444             return isDisposed.get();
445         }
446     }
447     
448     private static class ColorBarOptionsListener implements Listener<ColorBarOptions> {
449
450         private static final Logger LOGGER = LoggerFactory.getLogger(ColorBarOptionsListener.class);
451
452         private Consumer<ColorBarOptions> callback;
453         private Supplier<Boolean> isDisposed;
454
455         public ColorBarOptionsListener(Consumer<ColorBarOptions> callback, Supplier<Boolean> isDisposed) {
456             this.callback = callback;
457             this.isDisposed = isDisposed;
458         }
459
460         @Override
461         public void execute(ColorBarOptions result) {
462             callback.accept(result);
463         }
464
465         @Override
466         public void exception(Throwable t) {
467             LOGGER.error("Could not listen ColorBarOptions", t);
468         }
469
470         @Override
471         public boolean isDisposed() {
472             return isDisposed.get();
473         }
474     }
475     
476     private static class SizeBarOptionsRequest extends UnaryRead<Resource, SizeBarOptions> {
477
478         public SizeBarOptionsRequest(Resource diagram) {
479             super(diagram);
480         }
481
482         @Override
483         public SizeBarOptions perform(ReadGraph graph) throws DatabaseException {
484             DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
485             Resource model = graph.syncRequest(new PossibleIndexRoot(parameter));
486             if (model != null) {
487                 Resource vf = DynamicVisualisations.getVisualisationFolder(graph, model);
488                 if (vf != null) {
489                     Resource activeVisualisation = graph.getPossibleObject(vf, DN.Diagram_hasActiveVisualisation);
490                     if (activeVisualisation != null) {
491                         return DynamicVisualisations.sizeBarOptions(graph, activeVisualisation);
492                     }
493                 } else {
494                     LOGGER.debug("No visualisation folder available for model {}", model);
495                 }
496             }
497             return SizeBarOptions.useDefault();
498         }
499     }
500
501     private static class SizeBarOptionsListener implements Listener<SizeBarOptions> {
502
503         private static final Logger LOGGER = LoggerFactory.getLogger(SizeBarOptionsListener.class);
504
505         private Consumer<SizeBarOptions> callback;
506         private Supplier<Boolean> isDisposed;
507
508         public SizeBarOptionsListener(Consumer<SizeBarOptions> callback, Supplier<Boolean> isDisposed) {
509             this.callback = callback;
510             this.isDisposed = isDisposed;
511         }
512
513         @Override
514         public void execute(SizeBarOptions result) {
515             callback.accept(result);
516         }
517
518         @Override
519         public void exception(Throwable t) {
520             LOGGER.error("Could not listen SizeBarOptions", t);
521         }
522
523         @Override
524         public boolean isDisposed() {
525             return isDisposed.get();
526         }
527     }
528     
529     private static class SizingObjectsRequest extends UnaryRead<Resource, Map<String, DynamicSizeContribution>> {
530
531         public SizingObjectsRequest(Resource diagram) {
532             super(diagram);
533         }
534
535         @Override
536         public Map<String, DynamicSizeContribution> perform(ReadGraph graph) throws DatabaseException {
537             DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
538             Resource model = graph.syncRequest(new PossibleIndexRoot(parameter));
539             if (model != null) {
540                 Resource vf = DynamicVisualisations.getVisualisationFolder(graph, model);
541                 if (vf != null) {
542                     Resource activeVisualisation = graph.getPossibleObject(vf, DN.Diagram_hasActiveVisualisation);
543                     if (activeVisualisation != null) {
544                         return DynamicVisualisations.sizeContributions(graph, activeVisualisation);
545                     }
546                 } else {
547                     LOGGER.debug("No visualisation folder available for model {}", model);
548                 }
549             }
550             return Collections.emptyMap();
551         }
552     }
553     
554     private static class SizingObjectsListener implements Listener<Map<String,DynamicSizeContribution>> {
555
556         private static final Logger LOGGER = LoggerFactory.getLogger(SizingObjectsListener.class);
557
558         private Consumer<Map<String,DynamicSizeContribution>> callback;
559         private Supplier<Boolean> isDisposed;
560
561         public SizingObjectsListener(Consumer<Map<String, DynamicSizeContribution>> callback, Supplier<Boolean> isDisposed) {
562             this.callback = callback;
563             this.isDisposed = isDisposed;
564         }
565
566         @Override
567         public void execute(Map<String, DynamicSizeContribution> result) {
568             callback.accept(result);
569         }
570
571         @Override
572         public void exception(Throwable t) {
573             LOGGER.error("Could not listen SizingObjectsOptions", t);
574         }
575
576         @Override
577         public boolean isDisposed() {
578             return isDisposed.get();
579         }
580     }
581
582     private static class ShowElevationServerRequest extends UnaryRead<Resource, Boolean> {
583
584         public ShowElevationServerRequest(Resource diagram) {
585             super(diagram);
586         }
587
588         @Override
589         public Boolean perform(ReadGraph graph) throws DatabaseException {
590             DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
591             Resource model = graph.syncRequest(new PossibleIndexRoot(parameter));
592             if (model != null) {
593                 Resource vf = DynamicVisualisations.getVisualisationFolder(graph, model);
594                 if (vf != null) {
595                     Resource activeVisualisation = graph.getPossibleObject(vf, DN.Diagram_hasActiveVisualisation);
596                     if (activeVisualisation != null) {
597                         return DynamicVisualisations.showElevationServerBoundingBox(graph, activeVisualisation);
598                     }
599                 } else {
600                     LOGGER.debug("No visualisation folder available for model {}", model);
601                 }
602             }
603             return false;
604         }
605     }
606     
607     private static class ShowElevationServerListener implements Listener<Boolean> {
608
609         private static final Logger LOGGER = LoggerFactory.getLogger(ShowElevationServerListener.class);
610
611         private Consumer<Boolean> callback;
612         private Supplier<Boolean> isDisposed;
613
614         public ShowElevationServerListener(Consumer<Boolean> callback, Supplier<Boolean> isDisposed) {
615             this.callback = callback;
616             this.isDisposed = isDisposed;
617         }
618
619         @Override
620         public void execute(Boolean result) {
621             callback.accept(result);
622         }
623
624         @Override
625         public void exception(Throwable t) {
626             LOGGER.error("Could not listen Show Elevation Server", t);
627         }
628
629         @Override
630         public boolean isDisposed() {
631             return isDisposed.get();
632         }
633     }
634 }