From 9ad84822fad038b42bfe70d0e59ff786034d5989 Mon Sep 17 00:00:00 2001 From: Benjamin Davies Date: Thu, 16 Nov 2023 18:49:00 +1300 Subject: [PATCH] Introduce CHEN_CIRCLE entity type --- .../sourceforge/plantuml/abel/LeafType.java | 2 +- .../cheneer/command/CommandMultiSubclass.java | 3 +- .../plantuml/svek/GeneralImageBuilder.java | 4 + .../svek/image/EntityImageChenCircle.java | 175 ++++++++++++++++++ 4 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java diff --git a/src/net/sourceforge/plantuml/abel/LeafType.java b/src/net/sourceforge/plantuml/abel/LeafType.java index 4c67360de..34c7a2de4 100644 --- a/src/net/sourceforge/plantuml/abel/LeafType.java +++ b/src/net/sourceforge/plantuml/abel/LeafType.java @@ -62,7 +62,7 @@ public enum LeafType { PORTIN, PORTOUT, - CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, + CHEN_ENTITY, CHEN_RELATIONSHIP, CHEN_ATTRIBUTE, CHEN_CIRCLE, STILL_UNKNOWN; diff --git a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java index d24e35d6e..b05ece9ff 100644 --- a/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java +++ b/src/net/sourceforge/plantuml/cheneer/command/CommandMultiSubclass.java @@ -92,8 +92,7 @@ public class CommandMultiSubclass extends SingleLineCommand2 { final String symbol = arg.get("SYMBOL", 0); final Quark centerQuark = diagram.quarkInContext(false, superclass + "/" + symbol + subclasses + "/center"); - // TODO: Custom LeafType - final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.USECASE, null); + final Entity centerEntity = diagram.reallyCreateLeaf(centerQuark, Display.create(symbol), LeafType.CHEN_CIRCLE, null); final Quark superclassQuark = diagram.quarkInContext(true, superclass); final Entity superclassEntity = superclassQuark.getData(); diff --git a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java index 4a18f2783..175478e73 100644 --- a/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java +++ b/src/net/sourceforge/plantuml/svek/GeneralImageBuilder.java @@ -100,6 +100,7 @@ import net.sourceforge.plantuml.svek.image.EntityImageAssociation; import net.sourceforge.plantuml.svek.image.EntityImageAssociationPoint; import net.sourceforge.plantuml.svek.image.EntityImageBranch; import net.sourceforge.plantuml.svek.image.EntityImageChenAttribute; +import net.sourceforge.plantuml.svek.image.EntityImageChenCircle; import net.sourceforge.plantuml.svek.image.EntityImageChenEntity; import net.sourceforge.plantuml.svek.image.EntityImageChenRelationship; import net.sourceforge.plantuml.svek.image.EntityImageCircleEnd; @@ -266,6 +267,9 @@ public final class GeneralImageBuilder { if (leaf.getLeafType() == LeafType.CHEN_ATTRIBUTE) return new EntityImageChenAttribute(leaf, skinParam); + if (leaf.getLeafType() == LeafType.CHEN_CIRCLE) + return new EntityImageChenCircle(leaf, skinParam); + // TODO Clean if (leaf.getLeafType() == LeafType.DOMAIN && leaf.getStereotype() != null && leaf.getStereotype().isMachineOrSpecification()) diff --git a/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java b/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java new file mode 100644 index 000000000..0badab72e --- /dev/null +++ b/src/net/sourceforge/plantuml/svek/image/EntityImageChenCircle.java @@ -0,0 +1,175 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2024, Arnaud Roques + * + * Project Info: https://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * https://plantuml.com/patreon (only 1$ per month!) + * https://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.util.Collections; + +import net.sourceforge.plantuml.abel.Entity; +import net.sourceforge.plantuml.klimt.UGroupType; +import net.sourceforge.plantuml.klimt.UShape; +import net.sourceforge.plantuml.klimt.UStroke; +import net.sourceforge.plantuml.klimt.UTranslate; +import net.sourceforge.plantuml.klimt.color.ColorType; +import net.sourceforge.plantuml.klimt.color.Colors; +import net.sourceforge.plantuml.klimt.color.HColor; +import net.sourceforge.plantuml.klimt.creole.CreoleMode; +import net.sourceforge.plantuml.klimt.drawing.UGraphic; +import net.sourceforge.plantuml.klimt.font.FontConfiguration; +import net.sourceforge.plantuml.klimt.font.StringBounder; +import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment; +import net.sourceforge.plantuml.klimt.geom.XDimension2D; +import net.sourceforge.plantuml.klimt.shape.TextBlock; +import net.sourceforge.plantuml.klimt.shape.TextBlockInEllipse; +import net.sourceforge.plantuml.klimt.shape.UEllipse; +import net.sourceforge.plantuml.style.ISkinParam; +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.url.Url; + +public class EntityImageChenCircle extends AbstractEntityImage { + + final static private int MARGIN = 6; + + final private boolean isKey; + final private boolean isMulti; + final private boolean isDerived; + + final private TextBlock title; + final private Url url; + + public EntityImageChenCircle(Entity entity, ISkinParam skinParam) { + super(entity, skinParam); + + isKey = hasStereotype("<>"); + isMulti = hasStereotype("<>"); + isDerived = hasStereotype("<>"); + + FontConfiguration titleFontConfiguration = getStyleTitle(entity, skinParam) + .getFontConfiguration(getSkinParam().getIHtmlColorSet(), entity.getColors()); + if (isKey) { + titleFontConfiguration = titleFontConfiguration.underline(); + } + + title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, + getStyle().wrapWidth()); + + url = entity.getUrl99(); + } + + private boolean hasStereotype(String stereotype) { + return getEntity().getStereotype() != null && getEntity().getStereotype().toString().contains(stereotype); + } + + private Style getStyle() { + return getStyle(getEntity(), getSkinParam()); + } + + private static Style getStyle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.circle) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + private static Style getStyleTitle(Entity group, ISkinParam skinParam) { + return StyleSignatureBasic.of(SName.root, SName.element, SName.chenEerDiagram, SName.circle, SName.title) + .withTOBECHANGED(group.getStereotype()).getMergedStyle(skinParam.getCurrentStyleBuilder()); + } + + @Override + public ShapeType getShapeType() { + return ShapeType.OVAL; + } + + @Override + public XDimension2D calculateDimension(StringBounder stringBounder) { + return new XDimension2D(25, 25); + } + + @Override + public void drawU(UGraphic ug) { + ug.startGroup(Collections.singletonMap(UGroupType.ID, getEntity().getQuark().toStringPoint())); + if (url != null) + ug.startUrl(url); + + final XDimension2D dimTotal = calculateDimension(ug.getStringBounder()); + final XDimension2D dimTitle = title.calculateDimension(ug.getStringBounder()); + + UStroke stroke = getStyle().getStroke(getEntity().getColors()); + if (isDerived) { + stroke = new UStroke(10, 10, stroke.getThickness()); + } + + ug = applyColor(ug); + ug = ug.apply(stroke); + ug.draw(getShape(dimTotal)); + if (isMulti) { + ug.apply(new UTranslate(3, 3)).draw(getShape(dimTotal.delta(-6))); + } + + final double xTitle = (dimTotal.getWidth() - dimTitle.getWidth()) / 2; + final double yTitle = (dimTotal.getHeight() - dimTitle.getHeight()) / 2; + title.drawU(ug.apply(new UTranslate(xTitle, yTitle))); + + if (url != null) + ug.closeUrl(); + + ug.closeGroup(); + } + + final protected UGraphic applyColor(UGraphic ug) { + Colors colors = getEntity().getColors(); + + HColor border = colors.getColor(ColorType.LINE); + if (border == null) + border = getStyle().value(PName.LineColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(border); + + HColor backcolor = colors.getColor(ColorType.BACK); + if (backcolor == null) + backcolor = getStyle().value(PName.BackGroundColor).asColor(getSkinParam().getIHtmlColorSet()); + ug = ug.apply(backcolor.bg()); + + return ug; + } + + private UShape getShape(XDimension2D dimTotal) { + return UEllipse.build(dimTotal.getWidth(), dimTotal.getHeight()); + } + +}