package org.simantics.district.network.ui; import java.awt.Color; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Supplier; import org.simantics.datatypes.literal.RGB; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.diagram.ui.DiagramModelHints; import org.simantics.district.network.DistrictNetworkUtil; import org.simantics.district.network.ui.participants.DNPointerInteractor; import org.simantics.district.network.ui.participants.MapRulerPainter; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.CanvasContext; import org.simantics.g2d.diagram.handler.PickRequest.PickFilter; import org.simantics.g2d.diagram.participant.DelayedBatchElementPainter; import org.simantics.g2d.diagram.participant.ElementPainter; import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.diagram.participant.ZOrderHandler; import org.simantics.g2d.participant.BackgroundPainter; import org.simantics.g2d.participant.GridPainter; import org.simantics.g2d.participant.PanZoomRotateHandler; import org.simantics.g2d.participant.RenderingQualityInteractor; import org.simantics.g2d.participant.ZoomToAreaHandler; import org.simantics.maps.MapScalingTransform; import org.simantics.maps.eclipse.MapPainter; import org.simantics.maps.sg.commands.MapCommands; import org.simantics.modeling.ui.diagramEditor.DiagramViewer; import org.simantics.scenegraph.g2d.events.command.CommandEvent; import org.simantics.scenegraph.g2d.events.command.Commands; import org.simantics.utils.datastructures.hints.IHintContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DistrictDiagramViewer extends DiagramViewer { private static final Logger LOGGER = LoggerFactory.getLogger(DistrictDiagramViewer.class); @Override protected void addDiagramParticipants(ICanvasContext ctx) { ctx.add(new ZOrderHandler()); ctx.add(new Selection()); ctx.add(new ElementPainter()); ctx.add(new DNPointerInteractor()); ctx.add(new MapPainter(MapScalingTransform.INSTANCE)); ctx.add(new NetworkDrawingParticipant(MapScalingTransform.INSTANCE)); } protected String getPopupId() { return "#DistrictDiagramPopup"; } @Override public void initializeCanvasContext(CanvasContext ctx) { super.initializeCanvasContext(ctx); IHintContext h = ctx.getDefaultHintContext(); h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 10000.0); h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 0.01); h.setHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE, diagramResource); } @Override protected void addPainterParticipants(ICanvasContext ctx) { ctx.add(new RenderingQualityInteractor()); ctx.add(new DelayedBatchElementPainter(PickFilter.FILTER_MONITORS, 500, TimeUnit.MILLISECONDS)); } @Override protected void addGridRulerBackgroundParticipants(CanvasContext ctx) { ctx.add(new GridPainter()); ctx.add(new MapRulerPainter()); ctx.add(new BackgroundPainter()); } protected void addViewManipulationParticipants(CanvasContext ctx) { ctx.add(new DistrictPanZoomRotateHandler()); //ctx.add(new MousePanZoomInteractor()); //ctx.add(new MultitouchPanZoomRotateInteractor()); // ctx.add( new OrientationRestorer() ); ctx.add(new ZoomToAreaHandler()); } @Override protected void loadPageSettings(ICanvasContext ctx) { super.loadPageSettings(ctx); // this might be the wrong place to start such listening but at least // super.loadPageSettings() does async-db-operations setupDrawMapEnabled(); setupBackgroundColor(); } private void setupDrawMapEnabled() { sessionContext.getSession().asyncRequest(new DrawMapEnabledRequest(getInputResource()), new DrawMapEnabledListener( result -> canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), result ? Commands.MAP_ENABLE : Commands.MAP_DISABLE)), () -> DistrictDiagramViewer.this.isDisposed())); } private void setupBackgroundColor() { sessionContext.getSession().asyncRequest(new MapBackgroundColorRequest(getInputResource()), new MapBackgroundColorListener( result -> queueBackgroundColorChangeEvent(result), () -> DistrictDiagramViewer.this.isDisposed())); } private void queueBackgroundColorChangeEvent(RGB.Integer result) { if (result != null) { Color backgroundColor = new Color(result.red, result.green, result.blue); canvasContext.getDefaultHintContext().setHint(MapCommands.KEY_MAP_BACKGROUND_COLOR, backgroundColor); canvasContext.getEventQueue().queueEvent(new CommandEvent(canvasContext, System.currentTimeMillis(), MapCommands.MAP_BACKGROUND_COLOR_CHANGE)); } } private static class DrawMapEnabledRequest extends UnaryRead { public DrawMapEnabledRequest(Resource diagram) { super(diagram); } @Override public Boolean perform(ReadGraph graph) throws DatabaseException { return DistrictNetworkUtil.drawMapEnabled(graph, parameter); } } private static class DrawMapEnabledListener implements Listener { private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); private Consumer callback; private Supplier isDisposed; public DrawMapEnabledListener(Consumer callback, Supplier isDisposed) { this.callback = callback; this.isDisposed = isDisposed; } @Override public void execute(Boolean result) { callback.accept(result); } @Override public void exception(Throwable t) { LOGGER.error("Could not listen if draw map is enabled", t); } @Override public boolean isDisposed() { return isDisposed.get(); } } private static class MapBackgroundColorRequest extends UnaryRead { public MapBackgroundColorRequest(Resource diagram) { super(diagram); } @Override public RGB.Integer perform(ReadGraph graph) throws DatabaseException { return DistrictNetworkUtil.backgroundColor(graph, parameter); } } private static class MapBackgroundColorListener implements Listener { private static final Logger LOGGER = LoggerFactory.getLogger(DrawMapEnabledListener.class); private Consumer callback; private Supplier isDisposed; public MapBackgroundColorListener(Consumer callback, Supplier isDisposed) { this.callback = callback; this.isDisposed = isDisposed; } @Override public void execute(RGB.Integer result) { callback.accept(result); } @Override public void exception(Throwable t) { LOGGER.error("Could not listen map background color", t); } @Override public boolean isDisposed() { return isDisposed.get(); } } }