All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openbp.cockpit.modeler.figures.process.SocketFigure Maven / Gradle / Ivy

The newest version!
/*
 *   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.openbp.cockpit.modeler.figures.process;

import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import org.openbp.cockpit.itemeditor.NodeItemEditor;
import org.openbp.cockpit.modeler.Modeler;
import org.openbp.cockpit.modeler.ModelerColors;
import org.openbp.cockpit.modeler.ModelerGraphics;
import org.openbp.cockpit.modeler.ViewModeMgr;
import org.openbp.cockpit.modeler.drawing.DrawingEditorPlugin;
import org.openbp.cockpit.modeler.drawing.WorkspaceDrawingView;
import org.openbp.cockpit.modeler.figures.VisualElement;
import org.openbp.cockpit.modeler.figures.VisualElementEvent;
import org.openbp.cockpit.modeler.figures.generic.Colorizable;
import org.openbp.cockpit.modeler.figures.generic.GeometryException;
import org.openbp.cockpit.modeler.figures.generic.GeometryUtil;
import org.openbp.cockpit.modeler.figures.generic.MoveableTitleFigure;
import org.openbp.cockpit.modeler.figures.tag.AbstractTagFigure;
import org.openbp.cockpit.modeler.figures.tag.HorizontalRotatingTagFigure;
import org.openbp.cockpit.modeler.figures.tag.TagConnector;
import org.openbp.cockpit.modeler.paramvaluewizard.ParamValueWizard;
import org.openbp.cockpit.modeler.skins.Skin;
import org.openbp.cockpit.modeler.util.ModelerFlavors;
import org.openbp.common.util.ToStringHelper;
import org.openbp.core.CoreConstants;
import org.openbp.core.model.ModelObject;
import org.openbp.core.model.item.process.DataLink;
import org.openbp.core.model.item.process.FinalNode;
import org.openbp.core.model.item.process.InitialNode;
import org.openbp.core.model.item.process.Node;
import org.openbp.core.model.item.process.NodeParam;
import org.openbp.core.model.item.process.NodeSocket;
import org.openbp.core.model.item.process.Param;
import org.openbp.core.model.item.process.ProcessObject;
import org.openbp.core.model.item.process.ProcessVariable;
import org.openbp.core.model.item.type.DataTypeItem;
import org.openbp.guiclient.util.ClientFlavors;
import org.openbp.jaspira.gui.interaction.Importer;
import org.openbp.jaspira.gui.interaction.ViewDropRegion;
import org.openbp.swing.SwingUtil;
import org.openbp.swing.components.JMsgBox;

import CH.ifa.draw.framework.Connector;
import CH.ifa.draw.framework.Figure;
import CH.ifa.draw.framework.FigureEnumeration;
import CH.ifa.draw.standard.TextHolder;

/**
 * Socket figure.
 *
 * @author Stephan Moritz
 */
public class SocketFigure extends HorizontalRotatingTagFigure
	implements ProcessElementContainer, TextHolder, Colorizable
{
	/** Drop region id for color region */
	public static final String REGION_COLOR = "color";

	/** Drop region id for param by type region */
	public static final String REGION_PARAM_BY_TYPE = "paramByType";

	/** Drop region id for param by other param region */
	public static final String REGION_PARAM_BY_VARIABLE = "paramByParay";

	/** Socket represented by this tag */
	protected NodeSocket socket;

	/** List of all param figures contained in this tag */
	List paramList;

	/** Title figure */
	private MoveableTitleFigure titleFigure;

	/** List of all flow connections to / from this point (contains {@link FlowConnection} objects) */
	private LinkedList flowConnections;

	/**
	 * Default constructor.
	 *
	 * @param parent Parent node figure
	 * @param socket Socket the figure refers to
	 */
	public SocketFigure(NodeFigure parent, NodeSocket socket)
	{
		super(parent, socket);

		// Due to complex layouting, call layout once more
		moveBy(0, 0);
		layoutTag();
	}

	/**
	 * Creates the content of this tag.
	 *
	 * @param modelObject Model object this tag represents or null
	 */
	protected void initContent(Object modelObject)
	{
		// Add the spacer figure
		super.initContent(modelObject);

		Skin skin = getDrawing().getProcessSkin();

		// Connect the model object to this tag
		this.socket = (NodeSocket) modelObject;
		socket.setRepresentation(this);

		// Create title figure holding the name of the Socket.
		// This will return the node name in case of entry or final node sockets.
		titleFigure = new MoveableTitleFigure(getReferredProcessElement());
		titleFigure.setTitleFormat(skin.getSocketTitleFormat());
		titleFigure.setVerboseDisplay(true);
		addContent(titleFigure, CONTENT_TEXT);

		// Add the socket parameters
		initParams();

		contentState = CONTENT_TEXT | ViewModeMgr.getInstance().getTagState(this);
		if (paramList == null)
			contentState &= ~ CONTENT_DATA;

		decodeGeometry();
	}

	/**
	 * Sets up the parameters of the socket.
	 */
	private void initParams()
	{
		// Show all parameters if we display the node in the node editor (i. e. if it belongs to the node editor dummy process)
		boolean showAllParams = socket.getProcess().getName().equals(NodeItemEditor.NODEEDITOR_PROCESS_NAME);

		// Add all visible parameters of the socket to the parameter list and the tag content
		for (Iterator it = socket.getParams(); it.hasNext();)
		{
			NodeParam param = (NodeParam) it.next();

			// Add the parameter if we display all parameters or if it is a parameter that is currently visible
			if (showAllParams || param.isVisible())
			{
				ParamFigure paramFigure = new ParamFigure(this, param, new Point(0, 0));
				if (paramList == null)
					paramList = new ArrayList();
				paramList.add(paramFigure);
				addContent(paramFigure, CONTENT_DATA);
			}
		}
	}

	/**
	 * Reinitializes the parameter list of the socket.
	 *
	 * @param showAllParams
	 * true: Show visible and hidden parameters
* false: Show hidden parameters only if the socket belongs to the node editor dummy process */ public void reinitParams(boolean showAllParams) { // Show all parameters if we display the node in the node editor (i. e. if it belongs to the node editor dummy process) if (socket.getProcess().getName().equals(NodeItemEditor.NODEEDITOR_PROCESS_NAME)) { showAllParams = true; } // We must not rebuild the params completely in order not to loose the data links connected to the parameters. // Instead we have to add or remove the invisible parameters, i. e. // updateFigure the socket figure's parameter list and content list with the socket's parameter list. invalidate(); // Add invisible parameters int paramFigureIndex = 0; for (Iterator it = socket.getParams(); it.hasNext();) { NodeParam param = (NodeParam) it.next(); if (param.isVisible() || showAllParams) { // Display this parameter if (param.getRepresentation() == null) { // Parameter not present as figure, add it addParam(param, paramFigureIndex + 1); } ++paramFigureIndex; } } if (! showAllParams) { // Remove invisible parameters for (Iterator it = content.iterator(); it.hasNext();) { TagContent content = (TagContent) it.next(); if (content.getFigure() instanceof ParamFigure) { ParamFigure paramFigure = (ParamFigure) content.getFigure(); NodeParam param = paramFigure.getNodeParam(); if (! param.isVisible()) { // Remove the invisible parameter from the content list it.remove(); // Remove the parameter figure from the parameter figure list paramList.remove(paramFigure); // Remove the link from the parameter to the representation param.setRepresentation(null); } } } } // Add all visible content to the socket applyContentState(); invalidate(); } private static class HiddenSocketInfo { public static final int VISIBLE_WHEN_LINKED = (1 << 0); public static final int VISIBLE_WHEN_NOT_LINKED = (1 << 1); /** Name of the node/socket */ public String name; /** Object type ({@link Node} or {@link Socket}) */ public Class objectType; /** Control link constraint */ public int constraint; /** * Constructor. * * @param name Name of the node/socket * @param objectType Object type ({@link Node} or {@link Socket}) * @param constraint Control link constraint */ public HiddenSocketInfo(String name, Class objectType, int constraint) { this.name = name; this.objectType = objectType; this.constraint = constraint; } } private static HiddenSocketInfo[] hiddenSockets = new HiddenSocketInfo[] { new HiddenSocketInfo(CoreConstants.SOCKET_OUT, NodeSocket.class, HiddenSocketInfo.VISIBLE_WHEN_NOT_LINKED), new HiddenSocketInfo(CoreConstants.SOCKET_IN, NodeSocket.class, HiddenSocketInfo.VISIBLE_WHEN_NOT_LINKED), new HiddenSocketInfo(CoreConstants.SOCKET_TASK_PUBLISHED, NodeSocket.class, HiddenSocketInfo.VISIBLE_WHEN_LINKED), new HiddenSocketInfo(CoreConstants.DEFAULT_INITIAL_NODE_NAME, Node.class, HiddenSocketInfo.VISIBLE_WHEN_NOT_LINKED), new HiddenSocketInfo(CoreConstants.DEFAULT_FINAL_NODE_NAME, Node.class, HiddenSocketInfo.VISIBLE_WHEN_NOT_LINKED), }; /** * Override that applies for hiding standard in/out names. * When reinitializing the contents of the socket, the text information may be hidden if the name of the * underlying process element is 'In' or 'Out' and the skin tells us to do so. */ public void applyContentState() { ProcessObject pe = getReferredProcessElement(); String name = pe.getName(); boolean anchorVisible = ViewModeMgr.getInstance().isControlAnchorVisible(this) || getDrawing().isDisplayAll(); boolean hideText = false; // When control anchors are hidden, we also hide the socket name // if it is a standard socket name ('In' or 'Out'). if (! anchorVisible) { for (int i = 0; i < hiddenSockets.length; ++i) { HiddenSocketInfo info = hiddenSockets[i]; if (! matchSocketName(name, info.name)) continue; if (! info.objectType.isInstance(pe)) continue; boolean linked = socket.hasControlLinks(); if ((info.constraint & HiddenSocketInfo.VISIBLE_WHEN_NOT_LINKED) != 0 && ! linked) continue; if ((info.constraint & HiddenSocketInfo.VISIBLE_WHEN_LINKED) != 0 && linked) continue; hideText = true; break; } if (pe instanceof FinalNode) { if (((FinalNode) pe).getJumpTarget() != null) { hideText = false; } } } if (hideText) { contentState &= ~ CONTENT_TEXT; } else { contentState |= CONTENT_TEXT; } super.applyContentState(); } /** * Checks if the given name starts with the pattern and consists of remaining digits only. */ private boolean matchSocketName(String name, String pattern) { if (! name.startsWith(pattern)) return false; String remainder = name.substring(pattern.length()); int l = remainder.length(); for (int i = 0; i < l; ++i) { char c = remainder.charAt(i); if (! Character.isDigit(c)) return false; } return true; } /** * Returns a string representation of this object. */ public String toString() { return ToStringHelper.toString(this, "nodeSocket"); } ////////////////////////////////////////////////// // @@ Associated object access ////////////////////////////////////////////////// /** * Gets the socket represented by this tag. */ public NodeSocket getNodeSocket() { return socket; } /** * Determines if this socket figure represents an entry socket. * * @return * true: The figure represents an entry socket.
* false: The figure represents an exit socket. */ public boolean isEntrySocket() { return socket.isEntrySocket(); } ////////////////////////////////////////////////// // @@ Flow connections ////////////////////////////////////////////////// /** * Gets the list of all flow connections to / from this point. */ public List getFlowConnections() { return flowConnections; } /** * Adds a flow connection. * * @param connection Connection to add */ public void addFlowConnection(FlowConnection connection) { if (flowConnections == null) { flowConnections = new LinkedList(); } else { if (flowConnections.contains(connection)) // Already present return; } flowConnections.add(connection); } /** * Removes a flow connection. * * @param connection Connection to remove */ public void removeFlowConnection(FlowConnection connection) { if (flowConnections != null) { flowConnections.remove(connection); // TODO FIXME Call release? if (flowConnections.isEmpty()) flowConnections = null; } } ////////////////////////////////////////////////// // @@ Parameter management ////////////////////////////////////////////////// /** * Gets the list of all param figures contained in this tag. */ public List getParamList() { return paramList; } /** * Adds a figure for the given param to the socket figure. * * @param param Param to add * @param pos Position to add the parameter at (starting with 1) or -1 to add it to the end of the parameter list * @return The new param figure */ public ParamFigure addParam(NodeParam param, int pos) { ParamFigure paramFigure = new ParamFigure(this, param, new Point(0, 0)); if (pos < 0) { pos = getContent().size(); } if (paramList == null) paramList = new ArrayList(); paramList.add(pos - 1, paramFigure); addContentAt(paramFigure, pos, CONTENT_DATA); // Setting the content state will also layout the tag setContentState(getContentState() | CONTENT_DATA); // Provide the current angle to the new child figure, so the layouters work correctly paramFigure.setAngle(getAngle()); return paramFigure; } /** * Removes the parameter from this socket. * * @param paramFigure Parameter to remove */ public void removeParam(ParamFigure paramFigure) { willChange(); socket.removeParam(paramFigure.getNodeParam()); for (Iterator it = content.iterator(); it.hasNext();) { TagContent content = (TagContent) it.next(); if (content.getFigure() == paramFigure) { if (paramList != null) { paramList.remove(content.getFigure()); if (paramList.isEmpty()) paramList = null; } it.remove(); break; } } applyContentState(); changed(); } /** * Moves the parameter with the given index so that it assumes the new * index. Replaced parameters have their indices increased by one. */ public void moveParameter(int oldIndex, int newIndex) { if (oldIndex == newIndex) // No moving necessary return; if (oldIndex < newIndex) { newIndex--; } // 3 steps necessary... // 1. Move of the actual figure component paramList.add(newIndex, paramList.remove(oldIndex)); // 2. Move the parameter in the underlaying socket List socketParams = socket.getParamList(); socketParams.add(newIndex, socketParams.remove(oldIndex)); moveContent(oldIndex + 1, newIndex + 1); getDrawing().getEditor().view().clearSelection(); getDrawing().setModified(); } /** * Removes all connections from/to this figure. */ protected void removeConnections() { // Remove data links if (paramList != null) { for (Iterator it = paramList.iterator(); it.hasNext();) { ((ParamFigure) it.next()).removeConnections(); } } // Remove control links while (flowConnections != null && ! flowConnections.isEmpty()) { FlowConnection connection = (FlowConnection) flowConnections.getFirst(); getDrawing().remove(connection); connection.release(); } } /* private Iterator paramFigureIterator() { return new ParamFigureIterator(false); } private Iterator reverseParamFigureIterator() { return new ParamFigureIterator(true); } private class ParamFigureIterator implements Iterator { int index; boolean reverse; public ParamFigureIterator(boolean reverse) { this.reverse = reverse; findNext(reverse ? getNumberOfContents() - 1 : 0); } public boolean hasNext() { return index >= 0; } public Object next() { if (index < 0) return null; Object ret = getContentFigureAt(index); int nextIndex = reverse ? index - 1 : index + 1; findNext(nextIndex); return ret; } private void findNext(int i) { if (i >= 0) { for (;;) { if (i >= getNumberOfContents()) { index = -1; break; } if (getContentFigureAt(i) instanceof ParamFigure) { index = i; break; } if (reverse) --i; else ++i; } } } public void remove() { throw new UnsupportedOperationException("remove not supported by ParamFigureIterator"); } } */ ////////////////////////////////////////////////// // @@ Figure overrides ////////////////////////////////////////////////// public void basicSetAngle(double angle) { super.basicSetAngle(angle); for (Iterator it = content.iterator(); it.hasNext();) { TagContent next = (TagContent) it.next(); if (next.getFigure() instanceof AbstractTagFigure) { ((AbstractTagFigure) next.getFigure()).setAngle(angle); } } } public Connector connectorAt(int x, int y) { return new TagConnector(this); } public boolean canConnect() { if (isEntrySocket()) // We can always connect to an entry socket return true; if (flowConnections == null || flowConnections.isEmpty()) // We can connect to an exit socket if there is no control link attached to it return true; if (socket.getNode().isMultiExitLinkNode()) // We can connect to an exit socket if it belongs to a node that support multiple exit links on a socket at a time return true; return false; } public boolean containsPoint(int x, int y) { if (presentationFigure.containsPoint(x, y)) return true; for (FigureEnumeration fe = figures(); fe.hasMoreElements();) { if (fe.nextFigure().containsPoint(x, y)) return true; } return false; } public void release() { // Remove the connections to/from our parameter and flow access point removeConnections(); // We remove ourselves. if (getParent() instanceof MultiSocketNodeFigure) { ((MultiSocketNodeFigure) getParent()).removeSocket(this); } super.release(); } ////////////////////////////////////////////////// // @@ Geometry serialization support ////////////////////////////////////////////////// public void decodeGeometry() { String geometry = socket.getGeometry(); if (geometry == null) return; for (StringTokenizer tok = new StringTokenizer(geometry, "|"); tok.hasMoreTokens();) { decodeParameter(tok.nextToken()); } } protected void decodeParameter(String parameter) { String errIdent = socket.getQualifier().toUntypedString(); StringTokenizer st = new StringTokenizer(parameter, ":"); // Note: Until V 1.2, the 'state' property was saved. In order to prevent conflicts with processes saved // with these version, do not use a property named 'state' here! String paramName = st.nextToken(); if (paramName.equals("angle")) { setAngle(GeometryUtil.parseAngle(st, paramName, errIdent)); } else if (paramName.equals("fillcolor")) { setFillColor(GeometryUtil.parseColor(st, paramName, errIdent)); } else { throw new GeometryException("Unknown paramter '" + paramName + "'.", errIdent); } } /** * Stores geometric information in the socket object. */ public void encodeGeometry() { String geometry = "angle:" + GeometryUtil.printAngle(angle); Color c = getFillColor(); if (c != null) { geometry += "|fillcolor:" + c.getRed() + ":" + c.getGreen() + ":" + c.getBlue(); } socket.setGeometry(geometry); if (paramList != null) { for (Iterator it = paramList.iterator(); it.hasNext();) { ((ParamFigure) it.next()).encodeGeometry(); } } } ////////////////////////////////////////////////// // @@ ProcessElementContainer implementation ////////////////////////////////////////////////// public ProcessObject getProcessElement() { return socket; } public ProcessObject getReferredProcessElement() { Node node = socket.getNode(); if (node instanceof InitialNode || node instanceof FinalNode) // Entry and final node socket figures return their parent node as referred object. return node; // All other socket figures return the socket. return socket; } /** * select node on deletion. */ public Figure selectionOnDelete() { return parent; } ////////////////////////////////////////////////// // @@ TextHolder implementation ////////////////////////////////////////////////// public Rectangle textDisplayBox() { if (titleFigure != null) return titleFigure.displayBox(); return displayBox(); } public String getText() { return getProcessElement().getName(); } public void setText(String newText) { getProcessElement().setName(newText); } public boolean acceptsTyping() { return true; } public int overlayColumns() { String text = getText(); int columns = 20; if (text != null && text.length() > 17) columns = text.length() + 3; return columns; } public void connect(Figure connectedFigure) { } public void disconnect(Figure disconnectFigure) { } public Font getFont() { return ModelerGraphics.getStandardTextFont(); } ////////////////////////////////////////////////// // @@ VisualElement overrides ////////////////////////////////////////////////// public boolean handleEvent(VisualElementEvent event) { boolean checkState = false; if (event.type == VisualElementEvent.UPDATE_STATE) { // Element was selected or deselected, we might need to rebuild the socket contents. checkState = true; } else if (event.type == VisualElementEvent.SET_DND_PARTICIPANT) { // Element is participating in a drag and drop operation, we might need to rebuild the socket contents. checkState = true; visualStatus |= VisualElement.VISUAL_DND_PARTICIPANT; } else if (event.type == VisualElementEvent.UNSET_DND_PARTICIPANT) { // Element is not participating in a drag and drop operation any more, we might need to rebuild the socket contents. checkState = true; visualStatus &= ~ VisualElement.VISUAL_DND_PARTICIPANT; } else if (event.type == VisualElementEvent.DOUBLE_CLICK) { DrawingEditorPlugin editor = getDrawing().getEditor(); if (editor instanceof Modeler) { // Display parameter value wizard if appropriate ParamValueWizard.displayParameterValueWizard((Modeler) editor, (NodeFigure) getParent(), socket.getName(), null); return true; } } // If control anchors are to be hidden, we might need to rebuild the socket contents. if (checkState && ! ViewModeMgr.getInstance().isControlAnchorVisible(this)) { checkDecoratedContentState(); return true; } return false; } public void updatePresentationFigure() { presentationFigure.willChange(); // Re-set the origin and layout the tag origin = new Point(parent.center()); encodeGeometry(); // Reinitialize figure initPresentationFigure(); decodeGeometry(); layoutTag(); presentationFigure.changed(); } ////////////////////////////////////////////////// // @@ Colorizable implementation ////////////////////////////////////////////////// public Color getDefaultFillColor() { return presentationFigure.getDefaultFillColor(); } ///////////////////////////////////////////////////////////////////////// // @@ InteractionClient implementation ///////////////////////////////////////////////////////////////////////// public void dragStarted(Transferable transferable) { if (transferable.isDataFlavorSupported(ModelerFlavors.COLOR) || transferable.isDataFlavorSupported(ClientFlavors.TYPE_ITEM)) { handleEvent(new VisualElementEvent(VisualElementEvent.SET_DND_PARTICIPANT, getDrawing().getEditor())); } super.dragStarted(transferable); } public void dragEnded(Transferable transferable) { if (transferable.isDataFlavorSupported(ModelerFlavors.COLOR) || transferable.isDataFlavorSupported(ClientFlavors.TYPE_ITEM)) { handleEvent(new VisualElementEvent(VisualElementEvent.UNSET_DND_PARTICIPANT, getDrawing().getEditor())); } super.dragEnded(transferable); } public List getDropRegions(List flavors, Transferable data, MouseEvent mouseEvent) { WorkspaceDrawingView view = getDrawing().getView(); if (flavors.contains(ModelerFlavors.COLOR)) { // Use the whole section as target Rectangle r = presentationFigure.displayBox(); r = view.applyScale(r, false); return Collections.singletonList(new ViewDropRegion(REGION_COLOR, this, r, view)); } String regionId = null; if (flavors.contains(ClientFlavors.TYPE_ITEM)) { regionId = REGION_PARAM_BY_TYPE; } else if (flavors.contains(ClientFlavors.PROCESS_VARIABLE)) { regionId = REGION_PARAM_BY_VARIABLE; } if (regionId != null) { if (mouseEvent == null || ! mouseEvent.isControlDown()) { // Accept type items only if the CTRL button is not pressed to prevent overlaying the region // exposed by the ParamFigure in this case. Rectangle[] bounds = getParamRegions(); if (bounds.length > 1) { List result = new ArrayList(); for (int i = 0; i < bounds.length; i++) { // Add a green drop region with a small black border around each parameter Rectangle r = view.applyScale(bounds[i], false); ViewDropRegion region = new ViewDropRegion(regionId + ":" + i, this, r, view); region.setPaint(ModelerColors.DROP_REGION); region.setFrameColor(Color.BLACK); result.add(region); } return result; } // Params are not shown, so we need only a single region. // Use the whole section as target Rectangle r = presentationFigure.displayBox(); r = view.applyScale(r, false); ViewDropRegion region = new ViewDropRegion(regionId, this, r, view); region.setPaint(ModelerColors.DROP_REGION); return Collections.singletonList(region); } } return null; } /** * Returns an array of Rectangles containing the coordinates of the regions * between the parameters. The size of the returned list is (number of * parameters) + 1. * @return An array of Rectangles */ public Rectangle[] getParamRegions() { int nParams = paramList != null ? paramList.size() : 0; if ((getContentState() & AbstractTagFigure.CONTENT_DATA) == 0) { // No parameter displayed nParams = 0; } Rectangle[] result = new Rectangle[nParams + 1]; if (nParams > 0) { // Generate a region for each segment of the tag. // Each segment has the height of the tag itself and a // horizontal reach from the center of bordering params // or the edge of the socket itself respectively. // counter for the left side of the actual region Rectangle db = presentationFigure.displayBox(); if (isVerticalOrientation()) { // Orient according to position... if (angle >= Math.PI) { int y = db.y; // North if (paramList != null) { // we are in the top half, i.e. reverse for (int i = nParams; i > 0; i--) { ParamFigure paramFigure = (ParamFigure) paramList.get(i - 1); Rectangle r = new Rectangle(db.x, y, db.width, 0); y = (int) paramFigure.displayBox().getCenterY(); r.add(db.x, y); result[i] = r; } } // Create the last (bottom) region. Rectangle r = new Rectangle(db.x, y, db.width, 0); r.add(db.x, db.y + db.height); result[0] = r; } else { int y = db.y; // South if (paramList != null) { for (int i = 0; i < nParams; i++) { ParamFigure paramFigure = (ParamFigure) paramList.get(i); Rectangle r = new Rectangle(db.x, y, db.width, 0); y = (int) paramFigure.displayBox().getCenterY(); r.add(db.x, y); result[i] = r; } } // Create the last (top) region. Rectangle r = new Rectangle(db.x, y, db.width, 0); r.add(db.x, db.y + db.height); result[nParams] = r; } } else { // Orient according to position... if (angle >= Math.PI / 2 && angle < 3 * Math.PI / 2) { int x = db.x; // West if (paramList != null) { // we are in the left half, i.e. reverse for (int i = nParams; i > 0; i--) { ParamFigure paramFigure = (ParamFigure) paramList.get(i - 1); Rectangle r = new Rectangle(x, db.y, 0, db.height); x = (int) paramFigure.displayBox().getCenterX(); r.add(x, db.y); result[i] = r; } } // Create the last (leftmost) region. Rectangle r = new Rectangle(x, db.y, 0, db.height); r.add(db.x + db.width, db.y); result[0] = r; } else { int x = db.x; // East if (paramList != null) { for (int i = 0; i < nParams; i++) { ParamFigure paramFigure = (ParamFigure) paramList.get(i); Rectangle r = new Rectangle(x, db.y, 0, db.height); x = (int) paramFigure.displayBox().getCenterX(); r.add(x, db.y); result[i] = r; } } // Create the last (rightmost) region. Rectangle r = new Rectangle(x, db.y, 0, db.height); r.add(db.x + db.width, db.y); result[nParams] = r; } } } else { // params are not shown, so we need only a single region. // Use the whole section as target result[0] = presentationFigure.displayBox(); } return result; } public boolean importData(Object regionId, Transferable data, Point p) { try { if (REGION_COLOR.equals(regionId)) { // Set the color Color color = (Color) data.getTransferData(ModelerFlavors.COLOR); getDrawing().getEditor().startUndo("Set Color"); setFillColor(color); invalidate(); getDrawing().getEditor().endUndo(); } else { String regionStr = (String) regionId; String paramName = null; DataTypeItem paramType = null; ProcessVariable processVariable = null; if (regionStr.startsWith(REGION_PARAM_BY_TYPE)) { paramType = (DataTypeItem) data.getTransferData(ClientFlavors.TYPE_ITEM); paramName = paramType.getName(); } else if (regionStr.startsWith(REGION_PARAM_BY_VARIABLE)) { processVariable = (ProcessVariable) data.getTransferData(ClientFlavors.PROCESS_VARIABLE); paramType = processVariable.getDataType(); paramName = processVariable.getName(); if (socket.getParamByName(paramName) != null) { String msg = "The socket already has a parameter named '" + paramName + "'.\nPlease connect the process variable to the existing parameter."; JMsgBox.show(null, msg, JMsgBox.ICON_ERROR); return true; } } int pos = getContent().size(); int sepIndex = regionStr.indexOf(':'); if (sepIndex > 0) { // We need to add 1 to skip the label pos = Integer.parseInt(regionStr.substring(sepIndex + 1)) + 1; } getDrawing().getEditor().startUndo("Add Parameter"); NodeParam param = socket.createParam(paramName); param.setDataType(paramType); // Add the param to the socket socket.addParam(param, pos - 1); param.maintainReferences(ModelObject.SYNC_GLOBAL_REFNAMES | ModelObject.SYNC_LOCAL_REFNAMES); // Add the parameter figure to the socket figure ParamFigure paramFigure = addParam(param, pos); ((WorkspaceDrawingView) getDrawing().getEditor().view()).singleSelect(paramFigure); if (processVariable != null) { // Link the process variable to the new parameter DataLink dataLink = getDrawing().getProcess().createDataLink(); // Determine source and target parameter depending if we have an in- our outgoing global link Param sourceParam; Param targetParam; if (socket.isEntrySocket()) { sourceParam = processVariable; targetParam = param; } else { sourceParam = param; targetParam = processVariable; } // Link the global to the node parameter dataLink.link(sourceParam, targetParam); getDrawing().getProcess().addDataLink(dataLink); paramFigure.setProcessVariableConnection(processVariable, dataLink); } getDrawing().getEditor().endUndo(); getDrawing().getEditor().fireEvent("modeler.drawing.paramadded", paramFigure); ViewModeMgr.getInstance().setDataLinkVisible(true); } } catch (UnsupportedFlavorException e) { return false; } catch (IOException e) { return false; } return true; } public List getImportersAt(Point p) { WorkspaceDrawingView view = getDrawing().getView(); Point docPoint = SwingUtil.convertFromGlassCoords(p, view); if (presentationFigure.containsPoint(docPoint.x, docPoint.y)) return Collections.singletonList(new Importer(socket.getQualifier(), this, new DataFlavor[] { ClientFlavors.TYPE_ITEM, ModelerFlavors.COLOR })); return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy