org.eclipse.e4.core.contexts,
org.eclipse.jface,
org.simantics.scl.osgi,
- org.simantics.district.route.ui;bundle-version="1.0.0",
org.simantics.district.route
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: javax.annotation;version="1.0.0";resolution:=optional,
javax.inject;version="1.0.0"
Bundle-ActivationPolicy: lazy
+Automatic-Module-Name: org.simantics.district.network.ui
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.simantics.db.Resource;
import org.simantics.utils.datastructures.hints.IHintContext.Key;
import org.simantics.utils.datastructures.hints.IHintObservable;
import org.simantics.utils.ui.AdaptionUtils;
+import org.simantics.utils.ui.SWTUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return false;
KeyPressedEvent kpe = (KeyPressedEvent) e;
if (kpe.keyCode == java.awt.event.KeyEvent.VK_ENTER) {
- routeService.persistRoute(route);
+ Route committedRoute = route;
route = null;
+ SWTUtils.asyncExec(Display.getDefault(), () -> {
+ String newName = askRouteName("Confirm Route", committedRoute.getName());
+ if (newName != null) {
+ committedRoute.setName(newName);
+ routeService.persistRoute(committedRoute);
+ } else {
+ routeService.discardRoute(committedRoute);
+ }
+ });
dispose();
}
} else if (e instanceof CommandEvent) {
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());
- }
+ // TODO: still needs key binding contribution for the district diagram editor
+ SWTUtils.asyncExec(Display.getDefault(), () -> {
+ String newName = askRouteName("Rename Route", route.getName());
+ if (newName != null) {
+ route.setName(newName);
+ routeService.refreshRoute(route);
+ }
+ });
}
}
return false;
}
+ private String askRouteName(String dialogTitle, String initialValue) {
+ InputDialog dialog = new InputDialog(
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
+ dialogTitle,
+ "Route name",
+ initialValue,
+ s -> s.trim().length() > 0 ? null : "Name must be non-empty");
+ if (dialog.open() == Window.OK) {
+ return dialog.getValue();
+ }
+ return null;
+ }
+
protected boolean dispose() {
setDirty();
remove();
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
}
public static Collection<DiagramRegion> findRegions(ReadGraph graph, Resource model) throws DatabaseException {
+ if (model == null)
+ return Collections.emptyList();
+
List<Resource> diagrams = QueryIndexUtils.searchByType(graph, model, DiagramResource.getInstance(graph).Diagram);
Set<DiagramRegion> regions = new HashSet<>();
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.simantics.district.route.ui.internal.Activator
Bundle-Vendor: Semantum Oy
-Require-Bundle: org.eclipse.e4.ui.di,
- org.eclipse.e4.ui.model.workbench,
+Require-Bundle: org.eclipse.e4.core.di,
org.eclipse.e4.core.di.annotations,
org.eclipse.e4.core.services,
+ org.eclipse.e4.ui.di,
+ org.eclipse.e4.ui.model.workbench,
+ org.eclipse.e4.ui.services,
+ org.eclipse.e4.ui.workbench,
org.simantics.ui,
org.simantics.district.route,
- org.slf4j.api,
- org.eclipse.e4.ui.workbench,
- org.eclipse.e4.core.di,
- org.eclipse.e4.ui.services
+ org.simantics.district.network.ui;bundle-version="1.0.0",
+ org.slf4j.api
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Automatic-Module-Name: fi.vtt.apros.district.route.ui
Import-Package: javax.annotation;version="1.0.0";resolution:=optional,
-#Properties file for fi.apros.visualization.table
+#Properties file for org.simantics.district.route.ui
view.name = Routes
-command.commandname.1 = Open Routes View
-command.commandname.2 = Select Route on Diagram
<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:commands="http://www.eclipse.org/ui/2010/UIModel/application/commands" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_BxaXACerEeWxCPrV0pAZQQ">
<fragments xsi:type="fragment:StringModelFragment" xmi:id="_n2jsIMq-EeeUz6Cs9kKeKg" featurename="categories" parentElementId="xpath:/"/>
<fragments xsi:type="fragment:StringModelFragment" xmi:id="_4fyr4MqVEeeUz6Cs9kKeKg" featurename="commands" parentElementId="xpath:/">
- <elements xsi:type="commands:Command" xmi:id="_x1nG0H4WEei74IuRct85qQ" elementId="org.simantics.district.route.ui.commands.openRouteView" commandName="%command.commandname.1"/>
- <elements xsi:type="commands:Command" xmi:id="_k63rkP6zEeiBo8tg-6EPYA" elementId="org.simantics.district.route.ui.command.selectRouteOnDiagram" commandName="%command.commandname.2"/>
+ <elements xsi:type="commands:Command" xmi:id="_x1nG0H4WEei74IuRct85qQ" elementId="org.simantics.district.route.ui.commands.openRouteView" commandName="Open Routes View"/>
+ <elements xsi:type="commands:Command" xmi:id="_k63rkP6zEeiBo8tg-6EPYA" elementId="org.simantics.district.route.ui.command.selectRouteOnDiagram" commandName="Select Route on Diagram"/>
+ <elements xsi:type="commands:Command" xmi:id="_bA61IAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.command.discardRoute" commandName="Discard Route"/>
+ <elements xsi:type="commands:Command" xmi:id="_bfN6sAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.command.renameRoute" commandName="Rename Route"/>
</fragments>
<fragments xsi:type="fragment:StringModelFragment" xmi:id="_1Ds_gMqVEeeUz6Cs9kKeKg" featurename="handlers" parentElementId="xpath:/">
<elements xsi:type="commands:Handler" xmi:id="_1G5RYH4WEei74IuRct85qQ" elementId="org.simantics.district.route.ui.handlers.openRouteView" contributionURI="bundleclass://org.simantics.district.route.ui/org.simantics.district.route.ui.OpenRouteView" command="_x1nG0H4WEei74IuRct85qQ"/>
<elements xsi:type="commands:Handler" xmi:id="_O9tbQP60EeiBo8tg-6EPYA" elementId="org.simantics.district.route.ui.handlers.selectRouteOnDiagram" contributionURI="bundleclass://org.simantics.district.route.ui/org.simantics.district.route.ui.handlers.SelectRouteOnDiagram" command="_k63rkP6zEeiBo8tg-6EPYA"/>
+ <elements xsi:type="commands:Handler" xmi:id="_mRg_oAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.handler.discardRoute" contributionURI="bundleclass://org.simantics.district.route.ui/org.simantics.district.route.ui.handlers.DiscardRoute" command="_bA61IAI7EemGocelWS26pQ"/>
+ <elements xsi:type="commands:Handler" xmi:id="_mh_EkAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.handler.renameRoute" contributionURI="bundleclass://org.simantics.district.route.ui/org.simantics.district.route.ui.handlers.RenameRoute" command="_bfN6sAI7EemGocelWS26pQ"/>
</fragments>
<fragments xsi:type="fragment:StringModelFragment" xmi:id="_Fso08MrIEeeUz6Cs9kKeKg" featurename="toolBarContributions" parentElementId="xpath:/"/>
<fragments xsi:type="fragment:StringModelFragment" xmi:id="_WNB8EH4oEei74IuRct85qQ" featurename="trimContributions" parentElementId="xpath:/">
</elements>
<elements xsi:type="menu:MenuContribution" xmi:id="_Y4vWcP6zEeiBo8tg-6EPYA" elementId="org.simantics.district.route.ui.menucontribution.1" parentId="org.simantics.district.route.ui.contextMenu">
<children xsi:type="menu:HandledMenuItem" xmi:id="_fH1V8P6zEeiBo8tg-6EPYA" elementId="org.simantics.district.route.ui.handledmenuitem.selectRouteOnDiagram" command="_k63rkP6zEeiBo8tg-6EPYA"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_2nw1UAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.handledmenuitem.discardRoute" command="_bA61IAI7EemGocelWS26pQ"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_6oh8EAI7EemGocelWS26pQ" elementId="org.simantics.district.route.ui.handledmenuitem.renameRoute" command="_bfN6sAI7EemGocelWS26pQ"/>
</elements>
</fragments>
</fragment:ModelFragments>
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.layout.GridDataFactory;
-import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.TreeViewerEditor;
+import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.osgi.util.NLS;
ESelectionService selectionService;
- private final LocalResourceManager resourceManager;
+ @SuppressWarnings("unused")
+ private LocalResourceManager resourceManager;
private TreeViewer tree;
}
private RouteServiceListener routeServiceListener = e -> {
- System.out.println("Route event: " + e);
+ LOGGER.info("Route event: {}", e);
switch (e.type) {
case RouteEvent.TYPE_ROUTE_DISCARDED:
runUi(() -> tree.refresh());
break;
case RouteEvent.TYPE_ROUTE_SOURCE_CHANGED:
- runUi(() -> tree.setInput(e.service.listRoutes()));
+ runUi(() -> {
+ tree.getTree().setRedraw(false);
+ try {
+ Object[] expanded = tree.getExpandedElements();
+ tree.setInput(e.service.listRoutes());
+ tree.setExpandedElements(expanded);
+ } finally {
+ tree.getTree().setRedraw(true);
+ }
+ });
break;
}
};
private void defaultInitializeUI() {
GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
- GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
-
createTree(this);
}
private void createTree(Composite parent) {
- tree = new TreeViewer(parent, SWT.SINGLE);
+ TreeColumnLayout columnLayout = new TreeColumnLayout(false);
+ parent.setLayout(columnLayout);
+
+ tree = new TreeViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);
tree.setUseHashlookup(true);
GridDataFactory.fillDefaults().grab(true, true).applyTo(tree.getControl());
tree.setContentProvider(new ContentProvider());
tree.setLabelProvider(new LabelProvider());
tree.addSelectionChangedListener(this::treeSelectionChanged);
- //tree.addPostSelectionChangedListener(this::treeSelectionChanged);
- tree.addDoubleClickListener(this::itemDoubleClicked);
- // TODO: add route renaming (F2), DnD reordering support
- }
- private void itemDoubleClicked(DoubleClickEvent e) {
- // TODO: default action, i.e. highlight route?
- LOGGER.info("double click {}", e);
+ TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(tree, new FocusCellOwnerDrawHighlighter(tree));
+ ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(tree) {
+ @Override
+ protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
+ boolean singleSelect = tree.getStructuredSelection().size() == 1;
+ return singleSelect && (
+ (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.F2)
+ || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC
+ );
+ }
+ };
+
+ int feature = ColumnViewerEditor.KEYBOARD_ACTIVATION;
+
+ TreeViewerEditor.create(tree, focusCellManager, actSupport, feature);
+ final TextCellEditor textCellEditor = new TextCellEditor(tree.getTree());
+
+ TreeViewerColumn viewerColumn = new TreeViewerColumn(tree, SWT.LEFT);
+ columnLayout.setColumnData(viewerColumn.getColumn(), new ColumnWeightData(1));
+ viewerColumn.setLabelProvider(new LabelProvider());
+ viewerColumn.setEditingSupport(new EditingSupport(tree) {
+ @Override
+ protected void setValue(Object element, Object value) {
+ LOGGER.info("set value {} for {}", value, element);
+ Route r = (Route) element;
+ r.setName((String) value);
+ Activator.getDefault().getRouteService().persistRoute(r);
+ getViewer().update(element, null);
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ return ((Route) element).getName();
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ return textCellEditor;
+ }
+
+ @Override
+ protected boolean canEdit(Object element) {
+ return element instanceof Route;
+ }
+ });
+
+ // TODO: add DnD reordering support
}
private void treeSelectionChanged(SelectionChangedEvent e) {
selectionService.setSelection(e.getSelection());
- /*
- IStructuredSelection ss = (IStructuredSelection) e.getSelection();
- Object[] arr = ss.toArray();
- if (arr.length == 1) {
- Object o = arr[0];
- if (o instanceof Route) {
- CompletableFuture<List<Resource>> callback = new CompletableFuture<>();
- callback.thenAccept(dnElements -> {
- runUi(() -> selectionService.setSelection(new StructuredSelection(dnElements)));
- });
- new RouteJob((Route) o, callback).schedule();
- } else if (o instanceof Waypoint) {
- selectionService.setSelection(new StructuredSelection(((Waypoint) o).<Object>getObject()));
- }
- }
- */
}
protected void setInput(List<Route> result) {
return tree.getTree();
}
-}
+ public void editCurrentSelection() {
+ IStructuredSelection s = tree.getStructuredSelection();
+ if (s.size() == 1) {
+ tree.editElement(s.getFirstElement(), 0);
+ }
+ }
+
+}
\ No newline at end of file
ui.setFocus();
}
+ public void editCurrentSelection() {
+ ui.editCurrentSelection();
+ }
+
}
\ No newline at end of file
--- /dev/null
+package org.simantics.district.route.ui.handlers;
+
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.district.route.Route;
+import org.simantics.district.route.ui.internal.Activator;
+import org.simantics.utils.ui.ISelectionUtils;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class DiscardRoute {
+
+ @CanExecute
+ public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+ return ISelectionUtils.filterSingleSelection(selection, Route.class) != null;
+ }
+
+ @Execute
+ public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell activeShell,
+ @Named(IServiceConstants.ACTIVE_PART) MPart part,
+ @Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+ // get selected route
+ Route route = ISelectionUtils.filterSingleSelection(selection, Route.class);
+ if (route != null)
+ Activator.getDefault().getRouteService().discardRoute(route);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.district.route.ui.handlers;
+
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.district.route.Route;
+import org.simantics.district.route.ui.RouteView;
+import org.simantics.utils.ui.ISelectionUtils;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class RenameRoute {
+
+ @CanExecute
+ public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+ return ISelectionUtils.filterSingleSelection(selection, Route.class) != null;
+ }
+
+ @Execute
+ public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell activeShell,
+ @Named(IServiceConstants.ACTIVE_PART) MPart part,
+ @Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+ // get selected route
+ Route route = ISelectionUtils.filterSingleSelection(selection, Route.class);
+ if (route != null) {
+ Object obj = part.getObject();
+ if (obj instanceof RouteView) {
+ ((RouteView)obj).editCurrentSelection();
+ }
+ }
+ }
+
+}
\ No newline at end of file
import javax.inject.Named;
+import org.eclipse.e4.core.di.annotations.CanExecute;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.simantics.db.layer0.variable.Variable;
+import org.simantics.Simantics;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.network.ui.DistrictNetworkUIUtil;
import org.simantics.district.route.Route;
import org.simantics.district.route.RouteJob;
import org.simantics.district.route.RouterConfiguration;
import org.simantics.utils.ui.ISelectionUtils;
+import org.simantics.utils.ui.SWTUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @author Tuukka Lehtonen
*/
public class SelectRouteOnDiagram {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SelectRouteOnDiagram.class);
+
+ @CanExecute
+ public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
+ return ISelectionUtils.filterSingleSelection(selection, Route.class) != null;
+ }
+
@Execute
public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell activeShell,
@Named(IServiceConstants.ACTIVE_PART) MPart part,
if (route == null)
return;
- CompletableFuture<List<Variable>> result = new CompletableFuture<>();
+ Display display = activeShell.getDisplay();
+ CompletableFuture<List<Resource>> result = new CompletableFuture<>();
+ result.thenAccept(dnElements -> {
+ try {
+ openDiagram(display, dnElements);
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to open district network diagram with selection {}", dnElements);
+ }
+ });
+
RouterConfiguration config = new RouterConfiguration();
new RouteJob(config, route, result).schedule();
}
+ public static boolean openDiagram(Display display, List<Resource> dnElements) throws DatabaseException {
+ if (dnElements.isEmpty())
+ return false;
+
+ DistrictNetworkUIUtil.Input in = Simantics.getSession().syncRequest(
+ new DistrictNetworkUIUtil.ElementToInput(dnElements.get(0)));
+ if (in == null)
+ return false;
+
+ SWTUtils.asyncExec(display,
+ () -> DistrictNetworkUIUtil.openDNDiagramEditorWithSelection(in, dnElements.toArray()));
+ return true;
+ }
+
}
\ No newline at end of file
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Automatic-Module-Name: fi.vtt.apros.district.route
Bundle-ActivationPolicy: lazy
-Export-Package: org.simantics.district.route
+Export-Package: org.simantics.district.route,
+ org.simantics.district.route.internal;x-friends:="org.simantics.district.route.ui"
import org.eclipse.core.runtime.jobs.Job;
import org.simantics.ObjectIdentitySchedulingRule;
import org.simantics.db.Resource;
-import org.simantics.db.layer0.variable.Variable;
import org.simantics.district.route.internal.Activator;
import org.simantics.district.route.internal.RoutePersistence;
import org.slf4j.Logger;
private RouterConfiguration config;
private List<Resource> waypoints;
- private CompletableFuture<List<Variable>> callback;
+ private CompletableFuture<List<Resource>> callback;
- public RouteJob(RouterConfiguration config, Route route, CompletableFuture<List<Variable>> callback) {
+ public RouteJob(RouterConfiguration config, Route route, CompletableFuture<List<Resource>> callback) {
super("Compute route");
Objects.requireNonNull(callback, "Callback must be non-null");
setUser(true);
List<Router> routers = Activator.getInstance().getRouteService().routers();
for (Router router : routers) {
try {
- List<Variable> path = router.findShortestPath(config, waypoints);
+ List<Resource> path = router.findShortestPath(config, waypoints);
if (!path.isEmpty()) {
callback.complete(path);
return Status.OK_STATUS;
void registerRoute(Route route);
+ void refreshRoute(Route route);
+
CompletableFuture<Route> persistRoute(Route route);
CompletableFuture<?> discardRoute(Route route);
import java.util.List;
import org.simantics.db.Resource;
-import org.simantics.db.layer0.variable.Variable;
/**
* @author Tuukka Lehtonen
/**
* Must be invoked outside of any transaction realm, like a database request or
* experiment thread, preferably from a background job thread.
- *
+ *
+ * @param config reserved for future use, may be <code>null</code>
* @param wayPoints waypoints for the route to find in visiting order. The
* resources must represents district network diagram elements.
* @return the piece-wise shortest path between the specified waypoints as a
* fully baked path of district network diagram element resources
* @throws RoutingException in case of any problems in routing
*/
- List<Variable> findShortestPath(RouterConfiguration config, List<Resource> wayPoints) throws RoutingException;
+ List<Resource> findShortestPath(RouterConfiguration config, List<Resource> wayPoints) throws RoutingException;
}
import java.util.Collections;
import java.util.List;
+import org.simantics.Simantics;
import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.request.Read;
import org.simantics.district.route.Route;
import org.simantics.district.route.RouteEvent;
import org.simantics.district.route.Waypoint;
+import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class RouteImpl implements Route {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RouteImpl.class);
+
private String name;
private Resource model;
private Resource backend;
@Override
public Waypoint createWaypoint(Object backend) {
- if (backend instanceof Resource)
- return new WaypointImpl((Resource) backend, "Point 1");
+ if (backend instanceof Resource) {
+ Resource waypoint = (Resource) backend;
+ WaypointImpl wp = new WaypointImpl(waypoint, "");
+
+ // Read real label in background
+ ThreadUtils.getBlockingWorkExecutor().submit(() -> {
+ try {
+ Waypoint p = Simantics.getSession().syncRequest(
+ (Read<Waypoint>) graph -> RoutePersistence.toWaypoint(graph, waypoint));
+ if (p != null) {
+ wp.setLabel(p.getLabel());
+ rs.fireEvent(RouteEvent.TYPE_ROUTE_MODIFIED, RouteImpl.this);
+ }
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read waypoint {} label", backend, e);
+ }
+ });
+
+ return wp;
+ }
throw new IllegalArgumentException("only Resource type waypoints supported, got " + backend); //$NON-NLS-1$
}
import org.simantics.db.Resource;
import org.simantics.db.WriteGraph;
import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.ResourceRead;
import org.simantics.db.common.request.UniqueRead;
import org.simantics.db.common.utils.ListUtils;
import org.simantics.db.common.utils.NameUtils;
Layer0 L0 = Layer0.getInstance(graph);
String existingLabel = graph.getPossibleRelatedValue(route, L0.HasLabel, Bindings.STRING);
- if (ObjectUtils.objectEquals(existingLabel, label)) {
+ if (!ObjectUtils.objectEquals(existingLabel, label)) {
graph.claimLiteral(route, L0.HasLabel, label, Bindings.STRING);
}
}
public static List<RouteImpl> findRoutes(ReadGraph graph, Resource model) throws DatabaseException {
- Resource rf = getRouteFolder(graph, model);
+ Resource rf = model != null ? getRouteFolder(graph, model) : null;
if (rf == null)
return Collections.emptyList();
return routes;
}
+ public static class ModelRoutesRequest extends ResourceRead<List<RouteImpl>> {
+ public ModelRoutesRequest(Resource model) {
+ super(model);
+ }
+ @Override
+ public List<RouteImpl> perform(ReadGraph graph) throws DatabaseException {
+ return findRoutes(graph, resource);
+ }
+ }
+
public static class ActiveModelRoutesRequest extends UniqueRead<List<RouteImpl>> {
@Override
public List<RouteImpl> perform(ReadGraph graph) throws DatabaseException {
import org.simantics.db.ReadGraph;
import org.simantics.db.Resource;
import org.simantics.db.Session;
-import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.common.procedure.adapter.DisposableListener;
+import org.simantics.db.common.procedure.adapter.DisposableSyncListener;
import org.simantics.db.layer0.request.PossibleActiveModel;
import org.simantics.db.management.ISessionContext;
import org.simantics.db.management.ISessionContextChangedListener;
import org.simantics.db.management.SessionContextChangedEvent;
-import org.simantics.db.procedure.SyncListener;
import org.simantics.district.route.Route;
import org.simantics.district.route.RouteEvent;
import org.simantics.district.route.RouteService;
private List<Router> routers = new ArrayList<>();
private List<Router> unmodifiableRouters = Collections.unmodifiableList(routers);
- private class StoreListener implements SyncListener<Resource> {
- private boolean disposed = false;
-
+ private class StoreRoutesListener extends DisposableListener<List<RouteImpl>> {
@Override
- public void execute(ReadGraph graph, Resource activeModel) {
- try {
- if (activeModel != null) {
- resetRoutes(RoutePersistence.findRoutes(graph, activeModel));
- } else {
- resetRoutes(Collections.emptyList());
- }
- fireEvent(RouteEvent.TYPE_ROUTE_SOURCE_CHANGED, this);
- } catch (DatabaseException e) {
- LOGGER.error("Failed to read routes from model {}", activeModel, e);
- }
+ public void execute(List<RouteImpl> result) {
+ resetRoutes(result);
+ fireEvent(RouteEvent.TYPE_ROUTE_SOURCE_CHANGED, RouteServiceImpl.this);
}
@Override
- public void exception(ReadGraph graph, Throwable t) {
- LOGGER.error("Failed to listen to current route service storage", t);
+ public void exception(Throwable t) {
+ LOGGER.error("Failed to listen to current route store routes", t);
}
+ }
- public void dispose() {
- disposed = true;
+ private class StoreListener extends DisposableSyncListener<Resource> {
+ @Override
+ public void execute(ReadGraph graph, Resource activeModel) {
+ if (activeModel != null) {
+ StoreRoutesListener srl = storeRoutesListener;
+ if (srl != null)
+ srl.dispose();
+ Simantics.getSession().asyncRequest(
+ new RoutePersistence.ModelRoutesRequest(activeModel),
+ storeRoutesListener = new StoreRoutesListener());
+ } else {
+ resetRoutes(Collections.emptyList());
+ fireEvent(RouteEvent.TYPE_ROUTE_SOURCE_CHANGED, RouteServiceImpl.this);
+ }
}
@Override
- public boolean isDisposed() {
- return disposed;
+ public void exception(ReadGraph graph, Throwable t) {
+ LOGGER.error("Failed to listen to current route service storage", t);
}
}
+ private StoreRoutesListener storeRoutesListener;
private StoreListener storeListener;
private synchronized void listenToActiveModels(Session s) {
- StoreListener sl = storeListener;
+ StoreListener sl = storeListener;
if (sl != null)
sl.dispose();
if (s != null) {
fireEvent(RouteEvent.TYPE_ROUTE_REGISTERED, route);
}
+ @Override
+ public void refreshRoute(Route route) {
+ fireEvent(RouteEvent.TYPE_ROUTE_MODIFIED, route);
+ }
+
@Override
public CompletableFuture<Route> persistRoute(Route route) {
fireEvent(RouteEvent.TYPE_ROUTE_PERSISTING, route);