Skip to content
Snippets Groups Projects
Commit 120ca20f authored by Georgetta Igna's avatar Georgetta Igna
Browse files

added new compositors for connections - major improvements in the usability of...

added new compositors for connections - major improvements in the usability of creating connections between HierarchicalElements and Connectors.
refs 421,1375
parent f72311b6
No related branches found
No related tags found
No related merge requests found
/*--------------------------------------------------------------------------+
$Id: codetemplates.xml 1 2011-01-01 00:00:01Z hoelzl $
| |
| Copyright 2013 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.compose;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.fortiss.tooling.base.model.base.EntryConnectorBase;
import org.fortiss.tooling.base.model.base.ExitConnectorBase;
import org.fortiss.tooling.base.model.element.IConnection;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.ui.dnd.gef.ConnectionDragContext;
import org.fortiss.tooling.base.ui.dnd.gef.ElementDropContext;
import org.fortiss.tooling.kernel.extension.IConnectionCompositor;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.model.INamedElement;
import org.fortiss.tooling.kernel.service.IElementCompositorService;
/**
* Base class for all connection compositors.
*
* @author igna
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating RED Hash:
*/
abstract class ConnectionCompositorBase<HE extends IHierarchicElement, S extends EObject, T extends EObject>
implements IConnectionCompositor<HE, S, T> {
/** Creates the application specific {@link IConnection} model element. */
protected abstract IConnection createConnection();
/** Creates a connection and adds it to the parent element */
protected IConnection createConnection(IConnector source, IConnector target, HE parent,
ITopLevelElement topElement) {
IConnection connection = createConnection();
if(topElement != null) {
topElement.prepareIDs(connection);
}
parent.getConnectionsList().add(connection);
boolean swap = false;
if(source instanceof EntryConnectorBase) {
if(target instanceof EntryConnectorBase) {
if(source.eContainer() != target.eContainer().eContainer()) {
swap = true;
}
} else if(target instanceof ExitConnectorBase) {
swap = true;
}
} else if(source instanceof ExitConnectorBase) {
if(target instanceof ExitConnectorBase) {
if(source.eContainer() == target.eContainer().eContainer()) {
swap = true;
}
}
}
if(swap) {
connection.setSource(target);
connection.setTarget(source);
} else {
connection.setSource(source);
connection.setTarget(target);
}
return connection;
}
/** {@inheritDoc} */
@Override
public boolean reconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
/** {@inheritDoc} */
@Override
public boolean canReconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
/** {@inheritDoc} */
@Override
public boolean canDisconnect(EObject connection) {
return true;
}
/** {@inheritDoc} */
@Override
public boolean disconnect(EObject connection) {
if(connection instanceof IConnection) {
// since an IConnection object contains no element, it can be safe deleted directly.
EcoreUtil.delete(connection);
return true;
}
return false;
}
/**
* Determines whether connectors of the component may be connected
* internally. The default value is <code>false</code>.
*/
protected boolean canConnectInterally() {
return false;
}
/** Creates a new drop context */
protected void createNewDropContext(IHierarchicElement element,
IConnectionCompositionContext context, IConnector connector) {
ElementDropContext drop =
context instanceof ConnectionDragContext ? ((ConnectionDragContext)context)
.getSourceDropContext() : null;
IElementCompositorService.INSTANCE.compose(element, connector, drop);
}
/**
* Returns true if the connector and the element to which the connection should be created have
* the same parent.
*/
protected boolean sameParent(IHierarchicElement hierarchicalElement, IConnector connector) {
return hierarchicalElement.eContainer() == connector.eContainer();
}
/** Alters connector name if duplicate name already exists. */
void avoidDuplicateConnectorName(IHierarchicElement container, IConnector connector) {
String orig = ((INamedElement)connector).getName();
int num;
if(sameName(container, connector, orig)) {
num = 1;
while(sameName(container, connector, orig + num)) {
num++;
}
((INamedElement)connector).setName(orig + num);
} else
((INamedElement)connector).setName(orig);
}
/** Checks whether the hierarchical element has connectors with a given name. */
private boolean sameName(IHierarchicElement container, IConnector connector, String name) {
for(IConnector sibling : container.getConnectorsList()) {
if(sibling != connector && ((INamedElement)sibling).getName().equals(name)) {
return true;
}
}
return false;
}
}
......@@ -18,18 +18,14 @@ $Id$
package org.fortiss.tooling.base.ui.compose;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.fortiss.tooling.base.model.base.ConnectionSegmentBase;
import org.fortiss.tooling.base.model.base.ConnectorBase;
import org.fortiss.tooling.base.model.base.EntryConnectorBase;
import org.fortiss.tooling.base.model.base.ExitConnectorBase;
import org.fortiss.tooling.base.model.base.HierarchicElementBase;
import org.fortiss.tooling.base.model.element.IConnection;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.ui.dnd.gef.ConnectionDragContext;
import org.fortiss.tooling.base.ui.editpart.FreeConnectorEditPartBase;
import org.fortiss.tooling.kernel.extension.IConnectionCompositor;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
......@@ -43,7 +39,7 @@ import org.fortiss.tooling.kernel.service.IPersistencyService;
* @ConQAT.Rating GREEN Hash: 217EFCC38EC9814ED93D8FC3A4B1CC0B
*/
public abstract class ConnectorConnectionCompositorBase<HE extends IHierarchicElement, S extends IConnector, T extends IConnector>
implements IConnectionCompositor<HE, S, T> {
extends ConnectionCompositorBase<HE, S, T> {
/** {@inheritDoc} */
@Override
......@@ -133,9 +129,7 @@ public abstract class ConnectorConnectionCompositorBase<HE extends IHierarchicEl
.getSource() == source) || allowOneToMany();
}
/**
* Checks incoming connections of target port.
*/
/** Checks incoming connections of target port. */
private boolean checkTargetIn(ConnectorBase target, EObject connection) {
// target has no incoming connection, is already connected, or allows
// multiple connections.
......@@ -144,71 +138,15 @@ public abstract class ConnectorConnectionCompositorBase<HE extends IHierarchicEl
.getTarget() == target) || allowManyToOne();
}
/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
@Override
public boolean connect(S source, T target, HE parent, IConnectionCompositionContext context) {
ConnectionSegmentBase conn = createConnection(source, target, context);
// If we are working in a connected model, deal with IDs
ITopLevelElement modelContext = IPersistencyService.INSTANCE.getTopLevelElementFor(source);
if(modelContext != null) {
modelContext.prepareIDs(conn);
}
boolean swap = false;
if(source instanceof EntryConnectorBase) {
if(target instanceof EntryConnectorBase) {
if(source.eContainer() == target.eContainer().eContainer()) {
((HierarchicElementBase)source.eContainer()).getConnectionsList().add(conn);
} else {
// source.eContainer().eContainer() ==
// target.eContainer()
((HierarchicElementBase)target.eContainer()).getConnectionsList().add(conn);
swap = true;
}
} else if(target instanceof ExitConnectorBase) {
((HierarchicElementBase)source.eContainer().eContainer()).getConnectionsList().add(
conn);
swap = true;
}
} else if(source instanceof ExitConnectorBase) {
if(target instanceof EntryConnectorBase) {
((HierarchicElementBase)source.eContainer().eContainer()).getConnectionsList().add(
conn);
} else if(target instanceof ExitConnectorBase) {
if(source.eContainer() == target.eContainer().eContainer()) {
((HierarchicElementBase)source.eContainer()).getConnectionsList().add(conn);
swap = true;
} else {
// source.eContainer().eContainer() ==
// target.eContainer()
((HierarchicElementBase)target.eContainer()).getConnectionsList().add(conn);
}
}
}
createConnection(source, target, parent, modelContext);
if(swap) {
conn.setSource(target);
conn.setTarget(source);
} else {
conn.setSource(source);
conn.setTarget(target);
}
return true;
}
/**
* Creates a new {@link ConnectionSegmentBase}. The {@link IConnector}s are
* provided to make use of their names when naming the connection. However
* they should not be used for connecting.
*/
protected abstract ConnectionSegmentBase createConnection(S source, T target,
IConnectionCompositionContext context);
/**
* Configures multiple connection behavior for 1-to-many connections. The
* default is allow.
......@@ -225,51 +163,8 @@ public abstract class ConnectorConnectionCompositorBase<HE extends IHierarchicEl
return true;
}
/**
* Allows internal feedback connection. The default is disallow.
*/
/** Allows internal feedback connection. The default is disallow. */
protected boolean allowInternalFeedback() {
return false;
}
/** {@inheritDoc} */
@Override
public boolean canDisconnect(EObject connection) {
if(!canDisconnectSpecific(connection)) {
return false;
}
return true;
}
/** Base implementation returns true by default */
public abstract boolean canDisconnectSpecific(EObject connection);
/** {@inheritDoc} */
@Override
public boolean disconnect(EObject connection) {
if(connection instanceof IConnection) {
// since an IConnection object contains no element, it can be safe deleted directly.
EcoreUtil.delete(connection);
return true;
}
return false;
}
/** {@inheritDoc} */
@Override
public boolean canReconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
/** {@inheritDoc} */
@Override
public boolean reconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
}
/*--------------------------------------------------------------------------+
$Id: codetemplates.xml 1 2011-01-01 00:00:01Z hoelzl $
| |
| Copyright 2013 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.compose;
import org.eclipse.gef.RootEditPart;
import org.fortiss.tooling.base.model.base.EntryConnectorBase;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.ui.dnd.gef.ConnectionDragContext;
import org.fortiss.tooling.base.ui.editpart.FreeConnectorEditPartBase;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
/**
* TODO
*
* @author igna
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating RED Hash:
*/
public abstract class ConnectorHierarchicElementConnectionCompositorBase<HE extends IHierarchicElement, S extends IConnector, T extends IHierarchicElement>
extends ConnectionCompositorBase<HE, S, T> {
/** {@inheritDoc} */
@Override
public boolean canConnect(S source, T target, HE parent, IConnectionCompositionContext context) {
if(context instanceof ConnectionDragContext) {
ConnectionDragContext dc = (ConnectionDragContext)context;
if(dc.getSource() instanceof FreeConnectorEditPartBase &&
dc.getTarget() instanceof RootEditPart) {
return canConnectInterally();
}
}
return true;
}
/** Creates the application specific source {@link IConnector} model element. */
protected abstract IConnector createEntryConnector();
/** Creates the application specific target {@link IConnector} model element. */
protected abstract IConnector createExitConnector();
/** {@inheritDoc} */
@Override
public boolean connect(S source, T target, HE parent, IConnectionCompositionContext context) {
ITopLevelElement topElement = IPersistencyService.INSTANCE.getTopLevelElementFor(parent);
IConnector targetConnector = null;
if(sameParent(target, source)) {
if(source instanceof EntryConnectorBase) {
targetConnector = createEntryConnector();
} else {
targetConnector = createExitConnector();
}
} else {
if(source instanceof EntryConnectorBase) {
targetConnector = createExitConnector();
} else {
targetConnector = createEntryConnector();
}
}
avoidDuplicateConnectorName(target, targetConnector);
if(topElement != null) {
topElement.prepareIDs(targetConnector);
}
createNewDropContext(target, context, targetConnector);
createConnection(source, targetConnector, parent, topElement);
return true;
}
}
......@@ -17,36 +17,18 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.compose;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.RootEditPart;
import org.fortiss.tooling.base.model.element.IConnection;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.ui.dnd.gef.ConnectionDragContext;
import org.fortiss.tooling.base.ui.dnd.gef.ElementDropContext;
import org.fortiss.tooling.base.ui.editpart.DiagramEditPartBase;
import org.fortiss.tooling.kernel.extension.IConnectionCompositor;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IElementCompositorService;
import org.fortiss.tooling.kernel.service.IPersistencyService;
/**
* Base implementation for supporting direct connection of two {@link IHierarchicElement}s.
*
* <p>
* Sub-classes must implement:
* <UL>
* <LI>
* {@link #createConnection(IHierarchicElement, IHierarchicElement, IConnectionCompositionContext)}
* <LI>
* {@link #createSourceConnector(IHierarchicElement, IHierarchicElement, IConnectionCompositionContext)}
* <LI>
* {@link #createTargetConnector(IHierarchicElement, IHierarchicElement, IConnectionCompositionContext)}
* </UL>
* These methods are called in order to create specific model elements.
*
* <p>
* Sub-classes may implement {@link #canConnectInterally()} to support internal connections. By
* default connectors of the parent element cannot be connected in internal view of the element.
*
......@@ -56,31 +38,17 @@ import org.fortiss.tooling.kernel.service.IPersistencyService;
* @ConQAT.Rating GREEN Hash: 7BC4EFA965F734D39E64361677CD9956
*/
public abstract class HierarchicElementConnectionCompositorBase<HE extends IHierarchicElement, S extends IHierarchicElement, T extends IHierarchicElement>
implements IConnectionCompositor<HE, S, T> {
/**
* Determines whether connectors of the component may be connected
* internally. The default value is <code>false</code>.
*/
protected boolean canConnectInterally() {
return false;
}
/** Creates the application specific {@link IConnection} model element. */
protected abstract IConnection createConnection(S source, T target,
IConnectionCompositionContext context);
extends ConnectionCompositorBase<HE, S, T> {
/**
* Creates the application specific source {@link IConnector} model element.
*/
protected abstract IConnector createSourceConnector(S source, T target,
IConnectionCompositionContext context);
protected abstract IConnector createEntryConnector();
/**
* Creates the application specific target {@link IConnector} model element.
*/
protected abstract IConnector createTargetConnector(S source, T target,
IConnectionCompositionContext context);
protected abstract IConnector createExitConnector();
/** {@inheritDoc} */
@Override
......@@ -100,63 +68,22 @@ public abstract class HierarchicElementConnectionCompositorBase<HE extends IHier
/** {@inheritDoc} */
@Override
public boolean connect(S source, T target, HE parent, IConnectionCompositionContext context) {
IConnector sourceConnector = createEntryConnector();
avoidDuplicateConnectorName(source, sourceConnector);
// create application specific connection
IConnection connection = createConnection(source, target, context);
ITopLevelElement topElement = IPersistencyService.INSTANCE.getTopLevelElementFor(parent);
if(topElement != null) {
topElement.prepareIDs(connection);
}
parent.getConnectionsList().add(connection);
IConnector targetConnector = createExitConnector();
avoidDuplicateConnectorName(target, targetConnector);
// create application specific connectors
IConnector sourceConnector = createSourceConnector(source, target, context);
IConnector targetConnector = createTargetConnector(source, target, context);
ITopLevelElement topElement = IPersistencyService.INSTANCE.getTopLevelElementFor(parent);
if(topElement != null) {
topElement.prepareIDs(sourceConnector);
topElement.prepareIDs(targetConnector);
}
createNewDropContext(source, context, sourceConnector);
createNewDropContext(target, context, targetConnector);
// drop source connector
ElementDropContext sourceDrop =
context instanceof ConnectionDragContext ? ((ConnectionDragContext)context)
.getSourceDropContext() : null;
IElementCompositorService.INSTANCE.compose(source, sourceConnector, sourceDrop);
// drop target target connector
ElementDropContext targetDrop =
context instanceof ConnectionDragContext ? ((ConnectionDragContext)context)
.getTargetDropContext() : null;
IElementCompositorService.INSTANCE.compose(target, targetConnector, targetDrop);
// link connection to connectors
connection.setSource(sourceConnector);
connection.setTarget(targetConnector);
createConnection(targetConnector, sourceConnector, parent, topElement);
return true;
}
/** {@inheritDoc} */
@Override
public boolean canDisconnect(EObject connection) {
return true;
}
/** {@inheritDoc} */
@Override
public boolean canReconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
/** {@inheritDoc} */
@Override
public boolean reconnect(EObject connection, S source, T target,
IConnectionCompositionContext context) {
// TODO (FH): https://af3.fortiss.org/issues/390
// implement reconnect
return false;
}
}
/*--------------------------------------------------------------------------+
$Id: codetemplates.xml 1 2011-01-01 00:00:01Z hoelzl $
| |
| Copyright 2013 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.compose;
import org.eclipse.gef.RootEditPart;
import org.fortiss.tooling.base.model.base.EntryConnectorBase;
import org.fortiss.tooling.base.model.element.IConnector;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.ui.dnd.gef.ConnectionDragContext;
import org.fortiss.tooling.base.ui.editpart.FreeConnectorEditPartBase;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
/**
* Compositor base class for connections between hierarchical elements and connectors.
*
* @author igna
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating RED Hash:
*/
public abstract class HierarchicElementConnectorConnectionCompositorBase<HE extends IHierarchicElement, S extends IHierarchicElement, T extends IConnector>
extends ConnectionCompositorBase<HE, S, T> {
/** Creates the application specific source {@link IConnector} model element. */
protected abstract IConnector createEntryConnector();
/** Creates the application specific target {@link IConnector} model element. */
protected abstract IConnector createExitConnector();
/** {@inheritDoc} */
@Override
public boolean canConnect(S source, T target, HE parent, IConnectionCompositionContext context) {
if(context instanceof ConnectionDragContext) {
ConnectionDragContext dc = (ConnectionDragContext)context;
if(dc.getTarget() instanceof FreeConnectorEditPartBase &&
dc.getSource() instanceof RootEditPart) {
return canConnectInterally();
}
}
return true;
}
/** {@inheritDoc} */
@Override
public boolean connect(S source, T target, HE parent, IConnectionCompositionContext context) {
ITopLevelElement topElement = IPersistencyService.INSTANCE.getTopLevelElementFor(parent);
IConnector sourceConnector = null;
if(sameParent(source, target)) {
if(target instanceof EntryConnectorBase) {
sourceConnector = createEntryConnector();
} else {
sourceConnector = createExitConnector();
}
} else {
if(target instanceof EntryConnectorBase) {
sourceConnector = createExitConnector();
} else {
sourceConnector = createEntryConnector();
}
}
avoidDuplicateConnectorName(source, sourceConnector);
if(topElement != null) {
topElement.prepareIDs(sourceConnector);
}
createNewDropContext(source, context, sourceConnector);
createConnection(sourceConnector, target, parent, topElement);
return true;
}
}
......@@ -69,8 +69,26 @@ public class ConnectCommand extends Command {
/** {@inheritDoc} */
@Override
public void execute() {
EObject parent = (EObject)context.getSource().getParent().getModel();
EObject sourceParent = (EObject)context.getSource().getParent().getModel();
EObject targetParent = (EObject)context.getTarget().getParent().getModel();
EObject commonParent = findCommonParent(sourceParent, targetParent);
IConnectionCompositorService.INSTANCE.connect((EObject)context.getSource().getModel(),
(EObject)context.getTarget().getModel(), parent, context);
(EObject)context.getTarget().getModel(), commonParent, context);
}
/** Finds the common parent of two elements. */
private EObject findCommonParent(EObject sourceParent, EObject targetParent) {
if(sourceParent == targetParent) {
return sourceParent;
}
if(sourceParent.eContainer() == targetParent) {
return targetParent;
}
if(sourceParent == targetParent.eContainer())
return sourceParent;
return sourceParent.eContainer();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment