/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.flow.processrendering.annotations.model; import java.awt.geom.Rectangle2D; import com.rapidminer.gui.flow.processrendering.annotations.AnnotationDrawUtils; import com.rapidminer.gui.flow.processrendering.annotations.style.AnnotationColor; import com.rapidminer.gui.flow.processrendering.annotations.style.AnnotationStyle; import com.rapidminer.gui.flow.processrendering.draw.ProcessDrawer; import com.rapidminer.io.process.ProcessLayoutXMLFilter; import com.rapidminer.operator.ExecutionUnit; import com.rapidminer.operator.Operator; /** * Describes a workflow annotation which is located in an {@link ExecutionUnit}. It can be * positioned freely on the process canvas. * * @author Marco Boeck * @since 6.4.0 * */ public class ProcessAnnotation extends WorkflowAnnotation { /** the minimum width an annotation can have */ public static final int MIN_WIDTH = ProcessDrawer.OPERATOR_WIDTH; /** the minimum height an annotation can have */ public static final int MIN_HEIGHT = 50; /** the default width for an annotation */ public static final int DEFAULT_WIDTH = MIN_WIDTH * 2; /** the default height for an annotation */ public static final int DEFAULT_HEIGHT = 105; /** the maximum width for an annotation */ public static final int MAX_WIDTH = 4000; /** the maximum height for an annotation */ public static final int MAX_HEIGHT = 2000; /** the process this annotation is located in */ private ExecutionUnit process; /** * Creates a new process annotation which can be freely positioned in the process. * * @param comment * the actual annotation as HTML * @param style * the style of the annotation * @param process * the process this annotation is located in * @param wasResized * if the user has ever resized the annotation * @param wasColored * if the user ever manually colored the annotation * @param location * the location of the comment */ public ProcessAnnotation(final String comment, final AnnotationStyle style, final ExecutionUnit process, final boolean wasResized, final boolean wasColored, final Rectangle2D location) { super(comment, style, wasResized, wasColored, location); if (process == null) { throw new IllegalArgumentException("process must not be null!"); } if (location == null) { throw new IllegalArgumentException("location must not be null!"); } this.process = process; } /** * Returns the {@link ExecutionUnit} this annotation is located in. * * @return the process, never {@code null} */ @Override public ExecutionUnit getProcess() { return process; } /** * Sets the {@link ExecutionUnit} this annotation is located in. * * @param process * the process the annotation will be attached to * */ public void setProcess(ExecutionUnit process) { if (process == null) { throw new IllegalArgumentException("process must not be null!"); } this.process = process; } @Override public void fireUpdate() { // dirty hack to force an observer update on the execution unit getProcess().getEnclosingOperator().rename(getProcess().getEnclosingOperator().getName()); } @Override public ProcessAnnotation createProcessAnnotation(ExecutionUnit process) { Rectangle2D frame = getLocation(); return new ProcessAnnotation(getComment(), getStyle().clone(), process, false, wasColored(), new Rectangle2D.Double(frame.getX(), frame.getY(), frame.getWidth(), frame.getHeight())); } @Override public OperatorAnnotation createOperatorAnnotation(Operator attachedTo) { String comment = getComment(); int x = (int) ProcessLayoutXMLFilter.lookupOperatorRectangle(attachedTo).getCenterX() - OperatorAnnotation.DEFAULT_WIDTH / 2; int y = (int) ProcessLayoutXMLFilter.lookupOperatorRectangle(attachedTo).getMaxY() + OperatorAnnotation.Y_OFFSET; int height = AnnotationDrawUtils.getContentHeight(AnnotationDrawUtils.createStyledCommentString(comment, getStyle()), OperatorAnnotation.DEFAULT_WIDTH); boolean overflowing = false; if (height > OperatorAnnotation.MAX_HEIGHT) { height = OperatorAnnotation.MAX_HEIGHT; overflowing = true; } // convert to operator annotation AnnotationStyle style = getStyle().clone(); // default yellow color becomes transparent if (!wasColored()) { style.setAnnotationColor(AnnotationColor.TRANSPARENT); } OperatorAnnotation opAnno = new OperatorAnnotation(getComment(), style, attachedTo, false, wasColored(), x, y, OperatorAnnotation.DEFAULT_WIDTH, Math.max(OperatorAnnotation.MIN_HEIGHT, height)); opAnno.setOverflowing(overflowing); return opAnno; } }