package org.simantics.district.network.ui.participants; import java.awt.AlphaComposite; import java.awt.Cursor; import java.util.Collection; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.simantics.db.Resource; import org.simantics.diagram.ui.DiagramModelHints; import org.simantics.district.network.ui.internal.Activator; import org.simantics.district.route.Route; import org.simantics.district.route.RouteService; import org.simantics.district.route.Waypoint; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.IMouseCursorContext; import org.simantics.g2d.canvas.IMouseCursorHandle; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.canvas.impl.HintReflection.HintListener; import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup; import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; import org.simantics.g2d.diagram.handler.PickContext; import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.diagram.participant.pointertool.AbstractMode; import org.simantics.g2d.element.ElementUtils; import org.simantics.g2d.element.IElement; import org.simantics.g2d.participant.TransformUtil; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.events.Event; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent; import org.simantics.scenegraph.g2d.events.command.Command; import org.simantics.scenegraph.g2d.events.command.CommandEvent; import org.simantics.scenegraph.g2d.events.command.Commands; import org.simantics.scenegraph.g2d.nodes.SingleElementNode; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintObservable; import org.simantics.utils.ui.AdaptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This participant creates routes on district network diagrams using * {@link RouteService}. * * @author Tuukka Lehtonen * @since 6.09 */ public class RoutingMode extends AbstractMode { private static final Logger LOGGER = LoggerFactory.getLogger(RoutingMode.class); @Dependency protected TransformUtil util; @Dependency protected PickContext pickContext; @Dependency protected Selection selection; protected IMouseCursorHandle cursor; private RouteService routeService; private Route route; /** * The node under which the mutated diagram is ghosted in the scene graph. */ protected G2DParentNode parent; /** * This stays null until the translated diagram parts have been initialized * into the scene graph. After that, only the translations of the nodes in * the scene graph are modified. */ protected SingleElementNode node = null; public RoutingMode(int mouseId) { super(mouseId); } @Override public void addedToContext(ICanvasContext ctx) { super.addedToContext(ctx); IMouseCursorContext mcc = getContext().getMouseCursorContext(); cursor = mcc == null ? null : mcc.setCursor(mouseId, new Cursor(Cursor.CROSSHAIR_CURSOR)); routeService = Activator.getInstance().getRouteService(); if (routeService != null) { Resource diagramResource = getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE); LOGGER.info("Diagram resource: " + diagramResource); route = routeService.createRoute("Current", diagramResource); routeService.registerRoute(route); } } @Override public void removedFromContext(ICanvasContext ctx) { if (cursor != null) { cursor.remove(); cursor = null; } // Discard route if it hasn't been persisted before this if (route != null) { routeService.discardRoute(route); route = null; routeService = null; } super.removedFromContext(ctx); } @HintListener(Class = Selection.class, Field = "SELECTION0") public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { Collection elements = AdaptionUtils.adaptToCollection(newValue, IElement.class); for (IElement element : elements) { addRoutePoint(element); } } private void addRoutePoint(IElement element) { if (route == null) return; Object o = ElementUtils.getObject(element); if (o instanceof Resource) { Waypoint wp = route.createWaypoint(o); route.addWaypoint(wp); } } @SGInit public void initSG(G2DParentNode parent) { this.parent = parent; node = parent.addNode("route highlight", SingleElementNode.class); node.setZIndex(1000); node.setVisible(Boolean.TRUE); node.setComposite(AlphaComposite.SrcOver.derive(0.75f)); } @SGCleanup public void cleanupSG() { if (node != null) { node.remove(); node = null; } parent = null; } @EventHandler(priority = 30) public boolean handleEvent(Event e) { if (e instanceof KeyPressedEvent) { if (route == null) return false; KeyPressedEvent kpe = (KeyPressedEvent) e; if (kpe.keyCode == java.awt.event.KeyEvent.VK_ENTER) { routeService.persistRoute(route); route = null; dispose(); } } else if (e instanceof CommandEvent) { Command cmd = ((CommandEvent) e).command; if (cmd.equals(Commands.CANCEL)) { return dispose(); } else if (cmd.equals(Commands.RENAME)) { InputDialog dialog = new InputDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Rename Route", "Route name", route.getName(), s -> s.trim().length() > 0 ? null : "Name must be non-empty"); if (dialog.open() == Window.OK) { route.setName(dialog.getValue()); } } } return false; } protected boolean dispose() { setDirty(); remove(); return false; } static class RenameDialog extends InputDialog { public RenameDialog(Shell parent, String title, String message, String initialValue, IInputValidator validator) { super(parent, title, message, initialValue, validator); } @Override protected IDialogSettings getDialogBoundsSettings() { String sectionName = getClass().getName() + "_dialogBounds"; //$NON-NLS-1$ IDialogSettings settings= Activator.getInstance().getDialogSettings(); IDialogSettings section= settings.getSection(sectionName); if (section == null) section= settings.addNewSection(sectionName); return section; } @Override protected int getDialogBoundsStrategy() { return DIALOG_PERSISTLOCATION; } } }