| /********************************************************************* |
| * Copyright (c) 2005, 2019 SAP SE |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * SAP SE - initial API, implementation and documentation |
| * Benjamin Schmeling - mwenz - Bug 367483 - Support composite connections |
| * mlypik - Bug 401792 - Disable starting reconnection |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| **********************************************************************/ |
| package org.eclipse.graphiti.ui.internal.policy; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.draw2d.ConnectionLocator; |
| import org.eclipse.draw2d.Graphics; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.Shape; |
| import org.eclipse.gef.ConnectionEditPart; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.GraphicalEditPart; |
| import org.eclipse.gef.Handle; |
| import org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy; |
| import org.eclipse.graphiti.features.IReconnectionFeature; |
| import org.eclipse.graphiti.features.context.impl.ReconnectionContext; |
| import org.eclipse.graphiti.mm.algorithms.styles.LineStyle; |
| import org.eclipse.graphiti.mm.pictograms.Connection; |
| import org.eclipse.graphiti.tb.ISelectionInfo; |
| import org.eclipse.graphiti.tb.IToolBehaviorProvider; |
| import org.eclipse.graphiti.ui.internal.config.IConfigurationProviderInternal; |
| import org.eclipse.graphiti.ui.internal.figures.GFPolylineConnection; |
| import org.eclipse.graphiti.ui.internal.parts.CompositeConnectionEditPart; |
| import org.eclipse.graphiti.ui.internal.parts.IConnectionEditPart; |
| import org.eclipse.graphiti.ui.internal.util.DataTypeTransformation; |
| import org.eclipse.graphiti.ui.internal.util.draw2d.GFColorConstants; |
| import org.eclipse.graphiti.ui.internal.util.draw2d.GFConnectionEndpointHandle; |
| import org.eclipse.graphiti.util.IColorConstant; |
| import org.eclipse.swt.graphics.Color; |
| |
| /** |
| * An EditPolicy, which gives feedback for if a ConnectionEditPart is selected. |
| * This includes the connection-handles at the start/end of the connection. It |
| * does not create any commands. |
| * |
| * @see org.eclipse.graphiti.ui.internal.policy.IEditPolicyFactory#createConnectionHighlightEditPolicy() |
| * @noinstantiate This class is not intended to be instantiated by clients. |
| * @noextend This class is not intended to be subclassed by clients. |
| */ |
| public class ConnectionHighlightEditPolicy extends ConnectionEndpointEditPolicy { |
| |
| private Map<IFigure, Color> figureToColor = new HashMap<IFigure, Color>(); |
| |
| private Map<Shape, Integer> shapeToLineStyle = new HashMap<Shape, Integer>(); |
| |
| private IConfigurationProviderInternal configurationProvider; |
| |
| /** |
| * Creates a new ConnectionHighlightEditPolicy. |
| * |
| * @param configurationProvider |
| * The IConfigurationProviderInternal. |
| */ |
| protected ConnectionHighlightEditPolicy(IConfigurationProviderInternal configurationProvider) { |
| setConfigurationProvider(configurationProvider); |
| } |
| |
| protected final IConfigurationProviderInternal getConfigurationProvider() { |
| return configurationProvider; |
| } |
| |
| /** |
| * Is called when the ConnectionEditPart is 'selected'. It then highlights |
| * the selected ConnectionEditPart. |
| * |
| * @see org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy#addSelectionHandles() |
| */ |
| @Override |
| protected void addSelectionHandles() { |
| if (checkReconnectionFeature()) { |
| super.addSelectionHandles(); |
| } |
| showHighlight(); |
| } |
| |
| private boolean checkReconnectionFeature() { |
| return true; |
| // return (null != getConfigurationProvider().getFeatureProvider().getReconnectionFeature(new ReconnectionContext(null, null, |
| // null))); |
| } |
| |
| /** |
| * Is called when the previously 'selected' ConnectionEditPart is |
| * 'deselected'. It then disables the highlight of the selected |
| * ConnectionEditPart. |
| * |
| * @see org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy#removeSelectionHandles() |
| */ |
| @Override |
| protected void removeSelectionHandles() { |
| super.removeSelectionHandles(); |
| |
| removeHighlight(); |
| } |
| |
| protected void showHighlight() { |
| // remove previous highlight |
| removeHighlight(); |
| |
| // determine new highlight-values |
| Color newForeground = GFColorConstants.HANDLE_BG; |
| int newLineStyle = Graphics.LINE_DASH; |
| |
| if (getHost() != null && getHost().getModel() instanceof Connection) { |
| Connection connection = (Connection) getHost().getModel(); |
| IToolBehaviorProvider tbp = getConfigurationProvider().getDiagramTypeProvider().getCurrentToolBehaviorProvider(); |
| ISelectionInfo selectionInfo = tbp.getSelectionInfoForConnection(connection); |
| if (selectionInfo != null) { |
| IColorConstant selectionColor = selectionInfo.getColor(); |
| if (selectionColor != null) { |
| newForeground = DataTypeTransformation.toSwtColor(getConfigurationProvider().getResourceRegistry(), |
| selectionColor); |
| } |
| LineStyle selectionLineStyle = selectionInfo.getLineStyle(); |
| if (selectionLineStyle != null) { |
| newLineStyle = DataTypeTransformation.toDraw2dLineStyle(selectionLineStyle); |
| } |
| } |
| } |
| |
| // store old highlight-values and set new highlight-values |
| // important: get old colors via getLocalForeGround() to ignore parent |
| Collection<Shape> connectionFigures = getConnectionFigures(); |
| for (Shape connectionFigure : connectionFigures) { |
| figureToColor.put(connectionFigure, connectionFigure.getLocalForegroundColor()); |
| connectionFigure.setForegroundColor(newForeground); |
| shapeToLineStyle.put(connectionFigure, connectionFigure.getLineStyle()); |
| connectionFigure.setLineStyle(newLineStyle); |
| |
| if (connectionFigure instanceof GFPolylineConnection) { |
| GFPolylineConnection polylineConnection = (GFPolylineConnection) connectionFigure; |
| List<IFigure> allDecorations = polylineConnection.getAllDecorations(); |
| for (IFigure decoration : allDecorations) { |
| if (decoration != null) { |
| figureToColor.put(decoration, decoration.getLocalForegroundColor()); |
| decoration.setForegroundColor(newForeground); |
| if (decoration instanceof Shape) { |
| Shape decorationShape = (Shape) decoration; |
| shapeToLineStyle.put(decorationShape, new Integer(decorationShape.getLineStyle())); |
| decorationShape.setLineStyle(newLineStyle); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| protected void removeHighlight() { |
| Set<IFigure> colorFigures = figureToColor.keySet(); |
| for (IFigure colorFigure : colorFigures) { |
| Color oldColor = figureToColor.get(colorFigure); |
| colorFigure.setForegroundColor(oldColor); |
| } |
| |
| Set<Shape> lineStyleShapes = shapeToLineStyle.keySet(); |
| for (Shape lineStyleShape : lineStyleShapes) { |
| int lineStyle = shapeToLineStyle.get(lineStyleShape); |
| lineStyleShape.setLineStyle(lineStyle); |
| } |
| |
| figureToColor.clear(); |
| shapeToLineStyle.clear(); |
| } |
| |
| // ===================== private helper methods =========================== |
| |
| private Collection<Shape> getConnectionFigures() { |
| EditPart host = getHost(); |
| Collection<Shape> shapes = new ArrayList<Shape>(); |
| if (host instanceof CompositeConnectionEditPart) { |
| Collection<ConnectionEditPart> editParts = ((CompositeConnectionEditPart) host).getEditParts(); |
| for (ConnectionEditPart editPart : editParts) { |
| shapes.add((Shape) editPart.getFigure()); |
| } |
| } else { |
| shapes.add((Shape) ((GraphicalEditPart) getHost()).getFigure()); |
| } |
| return shapes; |
| } |
| |
| @Override |
| protected void hideSelection() { |
| super.hideSelection(); |
| if (getHost() instanceof IConnectionEditPart) { |
| IConnectionEditPart cep = (IConnectionEditPart) getHost(); |
| cep.forceVisualRefresh(); |
| } |
| } |
| |
| private void setConfigurationProvider(IConfigurationProviderInternal configurationProvider) { |
| this.configurationProvider = configurationProvider; |
| } |
| |
| @Override |
| protected List<Handle> createSelectionHandles() { |
| List<Handle> list = new ArrayList<Handle>(); |
| Connection connection = (Connection) getHost().getModel(); |
| ReconnectionContext sourceCtx = new ReconnectionContext(connection, connection.getStart(), null, null); |
| ReconnectionContext targetCtx = new ReconnectionContext(connection, connection.getEnd(), null, null); |
| IReconnectionFeature sourceReconnectionFeature = getConfigurationProvider().getFeatureProvider() |
| .getReconnectionFeature(sourceCtx); |
| IReconnectionFeature targetReconnectionFeature = getConfigurationProvider().getFeatureProvider() |
| .getReconnectionFeature(targetCtx); |
| // add endpoint handles only if they can start reconnect |
| if (sourceReconnectionFeature == null || sourceReconnectionFeature.canStartReconnect(sourceCtx)) { |
| list.add(new GFConnectionEndpointHandle((ConnectionEditPart) getHost(), ConnectionLocator.SOURCE)); |
| } |
| if (targetReconnectionFeature == null || targetReconnectionFeature.canStartReconnect(targetCtx)) { |
| list.add(new GFConnectionEndpointHandle((ConnectionEditPart) getHost(), ConnectionLocator.TARGET)); |
| } |
| return list; |
| } |
| } |