![JAR search and dependency download from the Maven repository](/logo.png)
net.sourceforge.plantuml.svek.image.EntityImageNote Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plantuml Show documentation
Show all versions of plantuml Show documentation
PlantUML is a component that allows to quickly write :
* sequence diagram,
* use case diagram,
* class diagram,
* activity diagram,
* component diagram,
* state diagram
* object diagram
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2023, Arnaud Roques
*
* Project Info: http://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* http://plantuml.com/patreon (only 1$ per month!)
* http://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.svek.image;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
import net.sourceforge.plantuml.AlignmentParam;
import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.SkinParamBackcolored;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.UseStyle;
import net.sourceforge.plantuml.awt.geom.Dimension2D;
import net.sourceforge.plantuml.creole.Stencil;
import net.sourceforge.plantuml.cucadiagram.BodyFactory;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.ILeaf;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockEmpty;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.posimo.DotPath;
import net.sourceforge.plantuml.skin.rose.Rose;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.AbstractEntityImage;
import net.sourceforge.plantuml.svek.ShapeType;
import net.sourceforge.plantuml.svek.SvekLine;
import net.sourceforge.plantuml.svek.SvekNode;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
import net.sourceforge.plantuml.ugraphic.UGroupType;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
public class EntityImageNote extends AbstractEntityImage implements Stencil {
private final HColor noteBackgroundColor;
private final HColor borderColor;
private final double shadowing;
private final int marginX1 = 6;
private final int marginX2 = 15;
private final int marginY = 5;
private final boolean withShadow;
private final ISkinParam skinParam;
private final Style style;
private final TextBlock textBlock;
public EntityImageNote(ILeaf entity, ISkinParam skinParam, UmlDiagramType umlDiagramType) {
super(entity, getSkin(getISkinParam(skinParam, entity), entity));
this.skinParam = getISkinParam(skinParam, entity);
this.withShadow = getSkinParam().shadowing(getEntity().getStereotype());
final Display strings = entity.getDisplay();
final Rose rose = new Rose();
final FontConfiguration fontConfiguration;
final HorizontalAlignment horizontalAlignment;
if (UseStyle.useBetaStyle()) {
this.style = getDefaultStyleDefinition(umlDiagramType.getStyleName())
.getMergedStyle(skinParam.getCurrentStyleBuilder());
if (entity.getColors().getColor(ColorType.BACK) == null)
this.noteBackgroundColor = style.value(PName.BackGroundColor).asColor(skinParam.getThemeStyle(),
skinParam.getIHtmlColorSet());
else
this.noteBackgroundColor = entity.getColors().getColor(ColorType.BACK);
this.borderColor = style.value(PName.LineColor).asColor(skinParam.getThemeStyle(),
skinParam.getIHtmlColorSet());
this.shadowing = style.value(PName.Shadowing).asDouble();
fontConfiguration = style.getFontConfiguration(skinParam.getThemeStyle(), skinParam.getIHtmlColorSet());
horizontalAlignment = style.getHorizontalAlignment();
} else {
this.style = null;
this.shadowing = skinParam.shadowing(getEntity().getStereotype()) ? 4 : 0;
if (entity.getColors().getColor(ColorType.BACK) == null)
this.noteBackgroundColor = rose.getHtmlColor(getSkinParam(), ColorParam.noteBackground);
else
this.noteBackgroundColor = entity.getColors().getColor(ColorType.BACK);
this.borderColor = SkinParamUtils.getColor(getSkinParam(), null, ColorParam.noteBorder);
fontConfiguration = FontConfiguration.create(getSkinParam(), FontParam.NOTE, null);
horizontalAlignment = skinParam.getHorizontalAlignment(AlignmentParam.noteTextAlignment, null, false, null);
}
if (strings.size() == 1 && strings.get(0).length() == 0)
textBlock = new TextBlockEmpty();
else
textBlock = BodyFactory.create3(strings, FontParam.NOTE, getSkinParam(), horizontalAlignment,
fontConfiguration, getSkinParam().wrapWidth(), style);
}
private static ISkinParam getISkinParam(ISkinParam skinParam, IEntity entity) {
if (entity.getColors() != null)
return entity.getColors().mute(skinParam);
return skinParam;
}
static ISkinParam getSkin(ISkinParam skinParam, IEntity entity) {
final Stereotype stereotype = entity.getStereotype();
HColor back = entity.getColors().getColor(ColorType.BACK);
if (back != null)
return new SkinParamBackcolored(skinParam, back);
back = getColorStatic(skinParam, ColorParam.noteBackground, stereotype);
if (back != null)
return new SkinParamBackcolored(skinParam, back);
return skinParam;
}
private static HColor getColorStatic(ISkinParam skinParam, ColorParam colorParam, Stereotype stereo) {
final Rose rose = new Rose();
return rose.getHtmlColor(skinParam, stereo, colorParam);
}
final public double getPreferredWidth(StringBounder stringBounder) {
final double result = getTextWidth(stringBounder);
return result;
}
final public double getPreferredHeight(StringBounder stringBounder) {
return getTextHeight(stringBounder);
}
private Dimension2D getSize(StringBounder stringBounder, final TextBlock textBlock) {
return textBlock.calculateDimension(stringBounder);
}
final protected double getTextHeight(StringBounder stringBounder) {
final TextBlock textBlock = getTextBlock();
final Dimension2D size = getSize(stringBounder, textBlock);
return size.getHeight() + 2 * marginY;
}
final protected TextBlock getTextBlock() {
return textBlock;
}
final protected double getPureTextWidth(StringBounder stringBounder) {
final TextBlock textBlock = getTextBlock();
final Dimension2D size = getSize(stringBounder, textBlock);
return size.getWidth();
}
final public double getTextWidth(StringBounder stringBounder) {
return getPureTextWidth(stringBounder) + marginX1 + marginX2;
}
public Dimension2D calculateDimension(StringBounder stringBounder) {
final double height = getPreferredHeight(stringBounder);
final double width = getPreferredWidth(stringBounder);
return new Dimension2DDouble(width, height);
}
private StyleSignatureBasic getDefaultStyleDefinition(SName sname) {
return StyleSignatureBasic.of(SName.root, SName.element, sname, SName.note);
}
final public void drawU(UGraphic ug) {
final Url url = getEntity().getUrl99();
final Map typeIDent = new EnumMap<>(UGroupType.class);
typeIDent.put(UGroupType.CLASS, "elem " + getEntity().getCode() + " selected");
typeIDent.put(UGroupType.ID, "elem_" + getEntity().getCode());
ug.startGroup(typeIDent);
if (url != null)
ug.startUrl(url);
final UGraphic ug2 = UGraphicStencil.create(ug, this, new UStroke());
if (opaleLine == null || opaleLine.isOpale() == false) {
drawNormal(ug2);
} else {
final StringBounder stringBounder = ug.getStringBounder();
DotPath path = opaleLine.getDotPath();
path.moveSvek(-node.getMinX(), -node.getMinY());
Point2D p1 = path.getStartPoint();
Point2D p2 = path.getEndPoint();
final double textWidth = getTextWidth(stringBounder);
final double textHeight = getTextHeight(stringBounder);
final Point2D center = new Point2D.Double(textWidth / 2, textHeight / 2);
if (p1.distance(center) > p2.distance(center)) {
path = path.reverse();
p1 = path.getStartPoint();
// p2 = path.getEndPoint();
}
final Direction strategy = getOpaleStrategy(textWidth, textHeight, p1);
final Point2D pp1 = path.getStartPoint();
final Point2D pp2 = path.getEndPoint();
final Point2D newRefpp2 = move(pp2, node.getMinX(), node.getMinY());
final Point2D projection = move(other.projection(newRefpp2, stringBounder), -node.getMinX(),
-node.getMinY());
final Opale opale = new Opale(shadowing, borderColor, noteBackgroundColor, textBlock, true, getStroke());
opale.setRoundCorner(getRoundCorner());
opale.setOpale(strategy, pp1, projection);
final UGraphic stroked = applyStroke(ug2);
opale.drawU(Colors.applyStroke(stroked, getEntity().getColors()));
}
if (url != null)
ug.closeUrl();
ug.closeGroup();
}
private double getRoundCorner() {
return skinParam.getRoundCorner(CornerParam.DEFAULT, null);
}
private static Point2D move(Point2D pt, double dx, double dy) {
return new Point2D.Double(pt.getX() + dx, pt.getY() + dy);
}
private void drawNormal(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
final UPath polygon = Opale.getPolygonNormal(getTextWidth(stringBounder), getTextHeight(stringBounder),
getRoundCorner());
double shadow = 0;
if (UseStyle.useBetaStyle())
shadow = this.shadowing;
else if (withShadow)
shadow = 4;
polygon.setDeltaShadow(shadow);
ug = ug.apply(noteBackgroundColor.bg()).apply(borderColor);
final UGraphic stroked = applyStroke(ug);
stroked.draw(polygon);
ug.draw(Opale.getCorner(getTextWidth(stringBounder), getRoundCorner()));
getTextBlock().drawU(ug.apply(new UTranslate(marginX1, marginY)));
}
private UGraphic applyStroke(UGraphic ug) {
if (UseStyle.useBetaStyle())
return ug.apply(style.getStroke());
final UStroke stroke = skinParam.getThickness(LineParam.noteBorder, null);
if (stroke == null)
return ug;
return ug.apply(stroke);
}
private UStroke getStroke() {
if (UseStyle.useBetaStyle())
return style.getStroke();
return skinParam.getThickness(LineParam.noteBorder, null);
}
private Direction getOpaleStrategy(double width, double height, Point2D pt) {
final double d1 = getOrthoDistance(new Line2D.Double(width, 0, width, height), pt);
final double d2 = getOrthoDistance(new Line2D.Double(0, height, width, height), pt);
final double d3 = getOrthoDistance(new Line2D.Double(0, 0, 0, height), pt);
final double d4 = getOrthoDistance(new Line2D.Double(0, 0, width, 0), pt);
if (d3 <= d1 && d3 <= d2 && d3 <= d4)
return Direction.LEFT;
if (d1 <= d2 && d1 <= d3 && d1 <= d4)
return Direction.RIGHT;
if (d4 <= d1 && d4 <= d2 && d4 <= d3)
return Direction.UP;
if (d2 <= d1 && d2 <= d3 && d2 <= d4)
return Direction.DOWN;
return null;
}
private static double getOrthoDistance(Line2D.Double seg, Point2D pt) {
if (isHorizontal(seg))
return Math.abs(seg.getP1().getY() - pt.getY());
if (isVertical(seg))
return Math.abs(seg.getP1().getX() - pt.getX());
throw new IllegalArgumentException();
}
private static boolean isHorizontal(Line2D.Double seg) {
return seg.getP1().getY() == seg.getP2().getY();
}
private static boolean isVertical(Line2D.Double seg) {
return seg.getP1().getX() == seg.getP2().getX();
}
public ShapeType getShapeType() {
return ShapeType.RECTANGLE;
}
private SvekLine opaleLine;
private SvekNode node;
private SvekNode other;
public void setOpaleLine(SvekLine line, SvekNode node, SvekNode other) {
this.opaleLine = line;
this.node = node;
this.other = Objects.requireNonNull(other);
}
public double getStartingX(StringBounder stringBounder, double y) {
return 0;
}
public double getEndingX(StringBounder stringBounder, double y) {
return calculateDimension(stringBounder).getWidth();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy