X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Futils%2FTopologicalSelectionExpander.java;h=f9b121ad4ed187346432e2c0177534830eb3127d;hb=68ce0966a57f5153b133c6283fdbae10f683b745;hp=55f2ce1fb09bf9d55b18539ef8b6f42af15c5afe;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/TopologicalSelectionExpander.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/TopologicalSelectionExpander.java
index 55f2ce1fb..f9b121ad4 100644
--- a/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/TopologicalSelectionExpander.java
+++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/utils/TopologicalSelectionExpander.java
@@ -1,252 +1,252 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
- * in Industry THTH ry.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- *******************************************************************************/
-package org.simantics.g2d.utils;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.Queue;
-import java.util.Set;
-
-import org.simantics.g2d.connection.ConnectionEntity;
-import org.simantics.g2d.diagram.IDiagram;
-import org.simantics.g2d.diagram.handler.DataElementMap;
-import org.simantics.g2d.diagram.handler.RelationshipHandler;
-import org.simantics.g2d.diagram.handler.RelationshipHandler.Relation;
-import org.simantics.g2d.diagram.handler.Topology;
-import org.simantics.g2d.diagram.handler.Topology.Connection;
-import org.simantics.g2d.diagram.handler.Topology.Terminal;
-import org.simantics.g2d.element.ElementHints;
-import org.simantics.g2d.element.IElement;
-import org.simantics.g2d.element.handler.TerminalTopology;
-import org.simantics.g2d.elementclass.FlagHandler;
-
-/**
- * This class tries to expand the selection provided by the specified elements
- * by a single expansion step. Its purpose is to provide a way for the user to
- * easily select a larger range of elements based on the diagram connectivity.
- * This can be useful e.g. when preparing for a copy-paste operation or simply
- * for visualizing the connectivity of a diagram.
- *
- *
- * The expansion logic is as follows:
- *
- *
- * - If connections are included in the current selection, make sure that no
- * connection entity is only partly selected. If only partly selected connection
- * entities are found, complete those and stop there. Otherwise continue to the
- * next step.
- * - Expand the current selection by one step. For connections this means
- * selecting all nodes that are attached by the connection but not yet in the
- * current selection. For nodes this means expanding the selection to all the
- * connections reachable from that particular node.
- *
- *
- * @author Tuukka Lehtonen
- */
-public class TopologicalSelectionExpander {
-
- public static final boolean DEBUG = false;
-
- IDiagram diagram;
- Set startSelection;
- Set resultSelection;
- Set processedConnections = new HashSet();
-
- Topology topology;
- DataElementMap dem;
-
- public static Set expandSelection(IDiagram diagram, Set elements) {
- return new TopologicalSelectionExpander(diagram, elements).expanded();
- }
-
- public TopologicalSelectionExpander(IDiagram diagram, Set startSelection) {
- assert diagram != null;
-
- this.diagram = diagram;
- this.startSelection = startSelection;
- this.resultSelection = new HashSet(startSelection);
-
- this.topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);
- this.dem = diagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);
- }
-
- /**
- * @return null
if the selection did not change in the
- * expansion, another set of elements otherwise
- */
- public Set expandedIfChanged() {
- Set result = expanded();
- if (DEBUG)
- System.out.println("result selection: " + result);
- if (result.equals(startSelection))
- return null;
- if (DEBUG)
- System.out.println("setting new selection");
- return result;
- }
-
- /**
- * @return
- */
- public Set expanded() {
- if (topology == null || dem == null || startSelection.isEmpty())
- return startSelection;
-
- if (DEBUG)
- System.out.println("expand start selection: " + startSelection);
-
- Deque work = new ArrayDeque(startSelection.size() + 4);
- work.addAll(startSelection);
-
- // 1. Iterate the start selection to see if there are any partly
- // selected connection entities. If so, then only complete the
- // selection of those entities before expanding the selection in
- // any other way.
- boolean connectionPartsSelected = false;
- for (IElement e : work) {
- IElement connection = getConnectionOfConnectionPart(e);
- if (connection != null) {
- // There was a mere connection part selection among the selection.
- Set connectionParts = getAllConnectionEntityParts(e);
- if (!connectionParts.isEmpty()) {
- if (DEBUG)
- System.out.println("\tconnection part selected: " + e + ", replacing with connection " + connection);
- resultSelection.add(connection);
- resultSelection.removeAll(connectionParts);
- connectionPartsSelected = true;
- }
- }
- }
-
- if (!connectionPartsSelected) {
- // No connection entities were partly selected. Go ahead with
- // the normal selection expansion procedure.
- while (!work.isEmpty()) {
- IElement e = work.poll();
- if (DEBUG)
- System.out.println("\texpanding at element: " + e);
- @SuppressWarnings("unused")
- boolean expanded = expandConnection(e, work) || expandNode(e, work);
- }
- }
-
- if (DEBUG)
- System.out.println("expanded selection: " + resultSelection);
- return resultSelection;
- }
-
- boolean expandConnection(IElement connection, Queue workQueue) {
- ConnectionEntity ce = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- if (ce == null)
- return false;
-
- if (!processedConnections.add(ce))
- return true;
-
- // Expand the selection to all the nodes attached to this connection.
- if (DEBUG)
- System.out.println("\texpanding at connection " + ce);
- Collection terminals = new ArrayList();
- ce.getTerminalConnections(terminals);
- if (DEBUG)
- System.out.println("\t\tfound " + terminals.size() + " terminal connections: " + terminals);
- for (Connection terminal : terminals) {
- if (resultSelection.add(terminal.node)) {
- if (DEBUG)
- System.out.println("\t\t\tadding node '" + terminal.node + "' at terminal '" + terminal.terminal + "'");
- }
- }
- return true;
- }
-
- boolean expandNode(IElement e, Queue workQueue) {
- // This is a node.
- TerminalTopology tt = e.getElementClass().getAtMostOneItemOfClass(TerminalTopology.class);
- if (tt == null)
- return false;
- if (DEBUG)
- System.out.println("\texpanding selection to node terminal connections: " + e);
-
- Collection terminals = new ArrayList();
- tt.getTerminals(e, terminals);
- Collection connections = new ArrayList();
- for (Terminal terminal : terminals) {
- topology.getConnections(e, terminal, connections);
- }
- if (DEBUG)
- System.out.println("\t\tfound " + connections.size() + " connected terminals: " + connections);
- for (Connection connection : connections) {
- IElement conn = getConnectionEntityConnection(connection.edge);
- if (conn != null) {
- if (DEBUG)
- System.out.println("\t\t\tadding connection: " + conn);
- resultSelection.add(conn);
- }
- }
-
- boolean expanded = !connections.isEmpty();
-
- // We want to:
- // * expand selection to monitors and other related "sub-elements" of the selection
- // We don't want to:
- // * expand selection through flags
- FlagHandler fh = e.getElementClass().getAtMostOneItemOfClass(FlagHandler.class);
- if (fh == null) {
- RelationshipHandler rh = diagram.getDiagramClass().getAtMostOneItemOfClass(RelationshipHandler.class);
- if (rh != null) {
- for(Relation rel : rh.getRelations(diagram, e, new ArrayList())) {
- if(rel.getSubject() instanceof IElement) {
- expanded |= resultSelection.add((IElement)rel.getSubject());
- }
- if(rel.getObject() instanceof IElement) {
- expanded |= resultSelection.add((IElement)rel.getObject());
- }
- }
- }
- }
-
- return expanded;
- }
-
- static IElement getConnectionOfConnectionPart(IElement e) {
- ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- if (ce == null)
- return null;
- IElement c = ce.getConnection();
- if (c == e)
- return null;
- return c;
- }
-
- static IElement getConnectionEntityConnection(IElement e) {
- ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- if (ce == null)
- return null;
- return ce.getConnection();
- }
-
- static Set getAllConnectionEntityParts(IElement e) {
- ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- if (ce == null)
- return Collections.emptySet();
- Set result = new HashSet();
- result.add(e);
- ce.getBranchPoints(result);
- ce.getSegments(result);
- return result;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g2d.utils;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Queue;
+import java.util.Set;
+
+import org.simantics.g2d.connection.ConnectionEntity;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.DataElementMap;
+import org.simantics.g2d.diagram.handler.RelationshipHandler;
+import org.simantics.g2d.diagram.handler.RelationshipHandler.Relation;
+import org.simantics.g2d.diagram.handler.Topology;
+import org.simantics.g2d.diagram.handler.Topology.Connection;
+import org.simantics.g2d.diagram.handler.Topology.Terminal;
+import org.simantics.g2d.element.ElementHints;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.handler.TerminalTopology;
+import org.simantics.g2d.elementclass.FlagHandler;
+
+/**
+ * This class tries to expand the selection provided by the specified elements
+ * by a single expansion step. Its purpose is to provide a way for the user to
+ * easily select a larger range of elements based on the diagram connectivity.
+ * This can be useful e.g. when preparing for a copy-paste operation or simply
+ * for visualizing the connectivity of a diagram.
+ *
+ *
+ * The expansion logic is as follows:
+ *
+ *
+ * - If connections are included in the current selection, make sure that no
+ * connection entity is only partly selected. If only partly selected connection
+ * entities are found, complete those and stop there. Otherwise continue to the
+ * next step.
+ * - Expand the current selection by one step. For connections this means
+ * selecting all nodes that are attached by the connection but not yet in the
+ * current selection. For nodes this means expanding the selection to all the
+ * connections reachable from that particular node.
+ *
+ *
+ * @author Tuukka Lehtonen
+ */
+public class TopologicalSelectionExpander {
+
+ public static final boolean DEBUG = false;
+
+ IDiagram diagram;
+ Set startSelection;
+ Set resultSelection;
+ Set processedConnections = new HashSet();
+
+ Topology topology;
+ DataElementMap dem;
+
+ public static Set expandSelection(IDiagram diagram, Set elements) {
+ return new TopologicalSelectionExpander(diagram, elements).expanded();
+ }
+
+ public TopologicalSelectionExpander(IDiagram diagram, Set startSelection) {
+ assert diagram != null;
+
+ this.diagram = diagram;
+ this.startSelection = startSelection;
+ this.resultSelection = new HashSet(startSelection);
+
+ this.topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);
+ this.dem = diagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);
+ }
+
+ /**
+ * @return null
if the selection did not change in the
+ * expansion, another set of elements otherwise
+ */
+ public Set expandedIfChanged() {
+ Set result = expanded();
+ if (DEBUG)
+ System.out.println("result selection: " + result);
+ if (result.equals(startSelection))
+ return null;
+ if (DEBUG)
+ System.out.println("setting new selection");
+ return result;
+ }
+
+ /**
+ * @return
+ */
+ public Set expanded() {
+ if (topology == null || dem == null || startSelection.isEmpty())
+ return startSelection;
+
+ if (DEBUG)
+ System.out.println("expand start selection: " + startSelection);
+
+ Deque work = new ArrayDeque(startSelection.size() + 4);
+ work.addAll(startSelection);
+
+ // 1. Iterate the start selection to see if there are any partly
+ // selected connection entities. If so, then only complete the
+ // selection of those entities before expanding the selection in
+ // any other way.
+ boolean connectionPartsSelected = false;
+ for (IElement e : work) {
+ IElement connection = getConnectionOfConnectionPart(e);
+ if (connection != null) {
+ // There was a mere connection part selection among the selection.
+ Set connectionParts = getAllConnectionEntityParts(e);
+ if (!connectionParts.isEmpty()) {
+ if (DEBUG)
+ System.out.println("\tconnection part selected: " + e + ", replacing with connection " + connection);
+ resultSelection.add(connection);
+ resultSelection.removeAll(connectionParts);
+ connectionPartsSelected = true;
+ }
+ }
+ }
+
+ if (!connectionPartsSelected) {
+ // No connection entities were partly selected. Go ahead with
+ // the normal selection expansion procedure.
+ while (!work.isEmpty()) {
+ IElement e = work.poll();
+ if (DEBUG)
+ System.out.println("\texpanding at element: " + e);
+ @SuppressWarnings("unused")
+ boolean expanded = expandConnection(e, work) || expandNode(e, work);
+ }
+ }
+
+ if (DEBUG)
+ System.out.println("expanded selection: " + resultSelection);
+ return resultSelection;
+ }
+
+ boolean expandConnection(IElement connection, Queue workQueue) {
+ ConnectionEntity ce = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);
+ if (ce == null)
+ return false;
+
+ if (!processedConnections.add(ce))
+ return true;
+
+ // Expand the selection to all the nodes attached to this connection.
+ if (DEBUG)
+ System.out.println("\texpanding at connection " + ce);
+ Collection terminals = new ArrayList();
+ ce.getTerminalConnections(terminals);
+ if (DEBUG)
+ System.out.println("\t\tfound " + terminals.size() + " terminal connections: " + terminals);
+ for (Connection terminal : terminals) {
+ if (resultSelection.add(terminal.node)) {
+ if (DEBUG)
+ System.out.println("\t\t\tadding node '" + terminal.node + "' at terminal '" + terminal.terminal + "'");
+ }
+ }
+ return true;
+ }
+
+ boolean expandNode(IElement e, Queue workQueue) {
+ // This is a node.
+ TerminalTopology tt = e.getElementClass().getAtMostOneItemOfClass(TerminalTopology.class);
+ if (tt == null)
+ return false;
+ if (DEBUG)
+ System.out.println("\texpanding selection to node terminal connections: " + e);
+
+ Collection terminals = new ArrayList();
+ tt.getTerminals(e, terminals);
+ Collection connections = new ArrayList();
+ for (Terminal terminal : terminals) {
+ topology.getConnections(e, terminal, connections);
+ }
+ if (DEBUG)
+ System.out.println("\t\tfound " + connections.size() + " connected terminals: " + connections);
+ for (Connection connection : connections) {
+ IElement conn = getConnectionEntityConnection(connection.edge);
+ if (conn != null) {
+ if (DEBUG)
+ System.out.println("\t\t\tadding connection: " + conn);
+ resultSelection.add(conn);
+ }
+ }
+
+ boolean expanded = !connections.isEmpty();
+
+ // We want to:
+ // * expand selection to monitors and other related "sub-elements" of the selection
+ // We don't want to:
+ // * expand selection through flags
+ FlagHandler fh = e.getElementClass().getAtMostOneItemOfClass(FlagHandler.class);
+ if (fh == null) {
+ RelationshipHandler rh = diagram.getDiagramClass().getAtMostOneItemOfClass(RelationshipHandler.class);
+ if (rh != null) {
+ for(Relation rel : rh.getRelations(diagram, e, new ArrayList())) {
+ if(rel.getSubject() instanceof IElement) {
+ expanded |= resultSelection.add((IElement)rel.getSubject());
+ }
+ if(rel.getObject() instanceof IElement) {
+ expanded |= resultSelection.add((IElement)rel.getObject());
+ }
+ }
+ }
+ }
+
+ return expanded;
+ }
+
+ static IElement getConnectionOfConnectionPart(IElement e) {
+ ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
+ if (ce == null)
+ return null;
+ IElement c = ce.getConnection();
+ if (c == e)
+ return null;
+ return c;
+ }
+
+ static IElement getConnectionEntityConnection(IElement e) {
+ ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
+ if (ce == null)
+ return null;
+ return ce.getConnection();
+ }
+
+ static Set getAllConnectionEntityParts(IElement e) {
+ ConnectionEntity ce = e.getHint(ElementHints.KEY_CONNECTION_ENTITY);
+ if (ce == null)
+ return Collections.emptySet();
+ Set result = new HashSet();
+ result.add(e);
+ ce.getBranchPoints(result);
+ ce.getSegments(result);
+ return result;
+ }
+
+}