1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-11-25 06:17:33 +00:00

Version 1.2023.0

This commit is contained in:
Arnaud Roques 2023-01-09 20:13:37 +01:00
parent 0ed5f14c32
commit a5d39f6dda
75 changed files with 1450 additions and 444 deletions

View File

@ -394,7 +394,7 @@ yamlDiagram,jsonDiagram {
LineColor black
arrow {
LineThickness 1
LineStyle 3;3
LineStyle 3-3
}
node {
LineThickness 1.5
@ -462,7 +462,7 @@ timingDiagram {
highlight {
BackgroundColor #e
LineThickness 2
LineStyle 4;4
LineStyle 4-4
}
}

View File

@ -460,7 +460,7 @@ yamlDiagram,jsonDiagram {
LineColor black
arrow {
LineThickness 1
LineStyle 3;3
LineStyle 3-3
}
node {
LineThickness 1.5
@ -517,7 +517,7 @@ timingDiagram {
highlight {
BackgroundColor #e
LineThickness 2
LineStyle 4;4
LineStyle 4-4
}
}

View File

@ -114,8 +114,6 @@ public interface ISkinParam extends ISkinSimple {
public LineBreakStrategy maxMessageSize();
public LineBreakStrategy wrapWidth();
public LineBreakStrategy swimlaneWrapTitleWidth();
public boolean strictUmlStyle();

View File

@ -59,8 +59,6 @@ public interface ISkinSimple extends SpriteContainer {
public int getDpi();
public LineBreakStrategy wrapWidth();
public void copyAllFrom(Map<String, String> other);
public SheetBuilder sheet(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,

View File

@ -81,6 +81,7 @@ import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleLoader;
import net.sourceforge.plantuml.style.parser.StyleParser;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.svek.ConditionEndStyle;
import net.sourceforge.plantuml.svek.ConditionStyle;
import net.sourceforge.plantuml.svek.PackageStyle;
@ -111,6 +112,8 @@ public class SkinParam implements ISkinParam {
if (styleBuilder == null)
try {
this.styleBuilder = getCurrentStyleBuilderInternal();
} catch (StyleParsingException e) {
Logme.error(e);
} catch (IOException e) {
Logme.error(e);
}
@ -133,7 +136,7 @@ public class SkinParam implements ISkinParam {
this.skin = newSkin;
}
public StyleBuilder getCurrentStyleBuilderInternal() throws IOException {
public StyleBuilder getCurrentStyleBuilderInternal() throws IOException, StyleParsingException {
final StyleLoader tmp = new StyleLoader(this);
StyleBuilder result = tmp.loadSkin(this.getDefaultSkin());
if (result == null)
@ -183,6 +186,8 @@ public class SkinParam implements ISkinParam {
for (Style modifiedStyle : StyleParser.parse(lines, styleBuilder))
this.muteStyle(modifiedStyle);
} catch (StyleParsingException e) {
Logme.error(e);
} catch (IOException e) {
Logme.error(e);
}
@ -894,12 +899,6 @@ public class SkinParam implements ISkinParam {
return new LineBreakStrategy(value);
}
@Override
public LineBreakStrategy wrapWidth() {
final String value = getValue("wrapwidth");
return new LineBreakStrategy(value);
}
@Override
public LineBreakStrategy swimlaneWrapTitleWidth() {
final String value = getValue("swimlanewraptitlewidth");

View File

@ -187,11 +187,6 @@ public class SkinParamDelegator implements ISkinParam {
return skinParam.maxMessageSize();
}
@Override
public LineBreakStrategy wrapWidth() {
return skinParam.wrapWidth();
}
@Override
public boolean strictUmlStyle() {
return skinParam.strictUmlStyle();

View File

@ -90,11 +90,6 @@ public class SpriteContainerEmpty implements SpriteContainer, ISkinSimple {
return 96;
}
@Override
public LineBreakStrategy wrapWidth() {
return LineBreakStrategy.NONE;
}
@Override
public void copyAllFrom(Map<String, String> other) {
throw new UnsupportedOperationException();

View File

@ -50,6 +50,7 @@ import net.sourceforge.plantuml.activitydiagram3.command.CommandCase;
import net.sourceforge.plantuml.activitydiagram3.command.CommandCircleSpot3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElse3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf2;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseLegacy1;
import net.sourceforge.plantuml.activitydiagram3.command.CommandEnd3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandEndPartition3;
@ -111,6 +112,7 @@ public class ActivityDiagramFactory3 extends PSystemCommandFactory {
cmds.add(new CommandIf2());
cmds.add(CommandDecoratorMultine.create(new CommandIf2(), 50));
cmds.add(new CommandIfLegacy1());
cmds.add(new CommandElseIf3());
cmds.add(new CommandElseIf2());
cmds.add(new CommandElse3());
cmds.add(CommandDecoratorMultine.create(new CommandElse3(), 50));

View File

@ -0,0 +1,121 @@
/* ========================================================================
* 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.activitydiagram3.command;
import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3;
import net.sourceforge.plantuml.activitydiagram3.LinkRendering;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexOptional;
import net.sourceforge.plantuml.command.regex.RegexOr;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.descdiagram.command.CommandLinkElement;
import net.sourceforge.plantuml.graphic.color.ColorParser;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
import net.sourceforge.plantuml.utils.LineLocation;
public class CommandElseIf3 extends SingleLineCommand2<ActivityDiagram3> {
public CommandElseIf3() {
super(getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandElseIf3.class.getName(), RegexLeaf.start(), //
ColorParser.exp4(), //
RegexLeaf.spaceZeroOrMore(), //
new RegexOptional(new RegexConcat( //
new RegexLeaf("\\("), //
new RegexOptional(new RegexOr(//
new RegexLeaf("->"), //
new RegexLeaf("INCOMING_COLOR", CommandLinkElement.STYLE_COLORS_MULTIPLES))), //
new RegexLeaf("INCOMING", "(.*?)"), //
new RegexLeaf("\\)"))), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("else"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("if"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("\\("), //
new RegexLeaf("TEST", "(.*?)"), //
new RegexLeaf("\\)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("(is|equals?)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("\\("), //
new RegexLeaf("WHEN", "(.+?)"), //
new RegexLeaf("\\)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexOptional( //
new RegexConcat( //
new RegexLeaf("then"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexOptional(new RegexConcat( //
new RegexLeaf("\\("), //
new RegexOptional(new RegexOr(//
new RegexLeaf("->"), //
new RegexLeaf("WHEN_COLOR",
CommandLinkElement.STYLE_COLORS_MULTIPLES))), //
new RegexLeaf("\\)"))) //
)), //
new RegexLeaf(";?"), //
RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
final String s = arg.get("COLOR", 0);
final HColor color = s == null ? null
: diagram.getSkinParam().getIHtmlColorSet().getColor(s);
String test = arg.get("TEST", 0);
if (test.length() == 0) {
test = null;
}
final LinkRendering incoming = CommandBackward3.getBackRendering(diagram, arg, "INCOMING");
final LinkRendering when = CommandBackward3.getBackRendering(diagram, arg, "WHEN");
return diagram.elseIf(incoming, Display.getWithNewlines(test), when, color);
}
}

View File

@ -266,7 +266,7 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock, Styleable
private LineBreakStrategy getWrap() {
LineBreakStrategy wrap = skinParam.swimlaneWrapTitleWidth();
if (wrap == LineBreakStrategy.NONE)
wrap = skinParam.wrapWidth();
wrap = style.wrapWidth();
return wrap;
}

View File

@ -97,6 +97,4 @@ public class FtileFactoryDelegatorAssembly extends FtileFactoryDelegator {
return result;
}
private final Rose rose = new Rose();
}

View File

@ -106,7 +106,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
throw new UnsupportedOperationException();
}
public /*protected*/ Plasma getPlasma() {
public /* protected */ Plasma getPlasma() {
throw new UnsupportedOperationException();
}
@ -305,13 +305,27 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return Collections.unmodifiableCollection(result);
}
final public void gotoGroup(Ident ident, Code code, Display display, GroupType type, IGroup parent,
NamespaceStrategy strategy) {
if (this.V1972()) {
gotoGroupInternalWithNamespace(ident, code, display, code, type, parent);
return;
private NamespaceStrategy lastNamespaceStrategy;
final public CommandExecutionResult gotoGroup(Ident ident, Code code, Display display, GroupType type,
IGroup parent, NamespaceStrategy strategy) {
if (type == GroupType.TOGETHER) {
IGroup result = entityFactory.createGroup(ident, code, display, null, type, parent, getHides(),
getNamespaceSeparator());
entityFactory.addGroup(result);
currentGroup = result;
return CommandExecutionResult.ok();
}
if (this.V1972()) {
gotoGroupInternalWithNamespace(ident, code, display, code, type, parent);
return CommandExecutionResult.ok();
}
if (this.lastNamespaceStrategy != null && strategy != this.lastNamespaceStrategy)
return CommandExecutionResult.error("Cannot mix packages and namespaces");
this.lastNamespaceStrategy = strategy;
if (strategy == NamespaceStrategy.MULTIPLE) {
if (getNamespaceSeparator() != null)
code = getFullyQualifiedCode1972(code);
@ -324,6 +338,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
} else {
throw new IllegalArgumentException();
}
return CommandExecutionResult.ok();
}
protected final String getNamespace1972(Code fullyCode, String separator) {
@ -373,6 +388,12 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
}
public void endGroup() {
if (currentGroup.getGroupType() == GroupType.TOGETHER) {
currentGroup = currentGroup.getParentContainer();
return;
}
if (stacks2.size() > 0) {
// Thread.dumpStack();
stacks2.remove(stacks2.size() - 1);
@ -672,6 +693,9 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
}
public boolean isAutarkic(IGroup g) {
if (g.getGroupType() == GroupType.TOGETHER)
return false;
if (g.getGroupType() == GroupType.PACKAGE)
return false;

View File

@ -131,7 +131,8 @@ public final class EntityFactory implements IEntityFactory {
final Collection<IGroup> children = parent.getChildren();
if (leafs == 0 && children.size() == 1) {
final IGroup g = children.iterator().next();
if (g.getLeafsDirect().size() == 0 && g.getChildren().size() == 0 && g.getGroupType() == GroupType.PACKAGE)
if (g.getLeafsDirect().size() == 0 && g.getChildren().size() == 0
&& (g.getGroupType() == GroupType.PACKAGE || g.getGroupType() == GroupType.TOGETHER))
return null;
for (Link link : this.getLinks())
@ -192,20 +193,24 @@ public final class EntityFactory implements IEntityFactory {
return result;
}
private IEntity isNoteWithSingleLinkAttachedTo(ILeaf leaf) {
if (leaf.getLeafType() != LeafType.NOTE)
private IEntity isNoteWithSingleLinkAttachedTo(ILeaf note) {
if (note.getLeafType() != LeafType.NOTE)
return null;
IEntity result = null;
assert note.getLeafType() == LeafType.NOTE;
IEntity other = null;
for (Link link : this.getLinks()) {
if (link.getType().isInvisible())
continue;
if (link.contains(leaf)) {
if (result != null)
return result;
result = link.getOther(leaf);
if (link.contains(note) == false)
continue;
if (other != null)
return null;
other = link.getOther(note);
if (other.getLeafType() == LeafType.NOTE)
return null;
}
}
return result;
return other;
}

View File

@ -171,8 +171,8 @@ final public class EntityImp implements ILeaf, IGroup {
this.rawLayout = rawLayout;
}
public EntityImp(Ident ident, Code code, EntityFactory entityFactory, Bodier bodier,
IGroup parentContainer, LeafType leafType, String namespaceSeparator, int rawLayout) {
public EntityImp(Ident ident, Code code, EntityFactory entityFactory, Bodier bodier, IGroup parentContainer,
LeafType leafType, String namespaceSeparator, int rawLayout) {
this(Objects.requireNonNull(ident), entityFactory, code, bodier, parentContainer, namespaceSeparator,
rawLayout);
// System.err.println("ID for leaf=" + code + " " + ident);
@ -782,6 +782,7 @@ final public class EntityImp implements ILeaf, IGroup {
public void setThisIsTogether() {
this.together = true;
setUSymbol(USymbols.TOGETHER);
}
public String getCodeLine() {

View File

@ -76,6 +76,7 @@ import net.sourceforge.plantuml.descdiagram.command.CommandCreateElementMultilin
import net.sourceforge.plantuml.descdiagram.command.CommandCreateElementParenthesis;
import net.sourceforge.plantuml.descdiagram.command.CommandNewpage;
import net.sourceforge.plantuml.descdiagram.command.CommandPackageWithUSymbol;
import net.sourceforge.plantuml.descdiagram.command.CommandTogether;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObject;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateEntityObjectMultilines;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJson;
@ -118,6 +119,7 @@ public class ClassDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandEndPackage());
cmds.add(new CommandPackageEmpty());
cmds.add(new CommandPackageWithUSymbol());
cmds.add(new CommandTogether());
cmds.add(new CommandCreateElementFull2(Mode.NORMAL_KEYWORD));
cmds.add(new CommandCreateElementFull2(Mode.WITH_MIX_PREFIX));

View File

@ -106,12 +106,14 @@ public class CommandNamespace extends SingleLineCommand2<ClassDiagram> {
currentPackage = diagram.getCurrentGroup();
display = Display.getWithNewlines(code);
}
diagram.gotoGroup(idNewLong, code, display, GroupType.PACKAGE, currentPackage, NamespaceStrategy.MULTIPLE);
final CommandExecutionResult status = diagram.gotoGroup(idNewLong, code, display, GroupType.PACKAGE,
currentPackage, NamespaceStrategy.MULTIPLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
final String stereotype = arg.get("STEREOTYPE", 0);
if (stereotype != null) {
if (stereotype != null)
p.setStereotype(Stereotype.build(stereotype));
}
final String urlString = arg.get("URL", 0);
if (urlString != null) {
@ -121,9 +123,9 @@ public class CommandNamespace extends SingleLineCommand2<ClassDiagram> {
}
final String color = arg.get("COLOR", 0);
if (color != null) {
if (color != null)
p.setSpecificColorTOBEREMOVED(ColorType.BACK, diagram.getSkinParam().getIHtmlColorSet().getColor(color));
}
return CommandExecutionResult.ok();
}

View File

@ -94,12 +94,14 @@ public class CommandNamespace2 extends SingleLineCommand2<ClassDiagram> {
final IGroup currentPackage = diagram.getCurrentGroup();
final String disp = arg.getLazzy("DISPLAY", 0);
final Display display = Display.getWithNewlines(disp);
diagram.gotoGroup(ident, code, display, GroupType.PACKAGE, currentPackage, NamespaceStrategy.MULTIPLE);
final CommandExecutionResult status = diagram.gotoGroup(ident, code, display, GroupType.PACKAGE,
currentPackage, NamespaceStrategy.MULTIPLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
final String stereotype = arg.get("STEREOTYPE", 0);
if (stereotype != null) {
if (stereotype != null)
p.setStereotype(Stereotype.build(stereotype));
}
final String urlString = arg.get("URL", 0);
if (urlString != null) {
@ -109,9 +111,9 @@ public class CommandNamespace2 extends SingleLineCommand2<ClassDiagram> {
}
final String color = arg.get("COLOR", 0);
if (color != null) {
if (color != null)
p.setSpecificColorTOBEREMOVED(ColorType.BACK, diagram.getSkinParam().getIHtmlColorSet().getColor(color));
}
return CommandExecutionResult.ok();
}

View File

@ -88,12 +88,14 @@ public class CommandNamespaceEmpty extends SingleLineCommand2<ClassDiagram> {
final Code code = diagram.V1972() ? idNewLong : diagram.buildCode(idShort);
final IGroup currentPackage = diagram.getCurrentGroup();
final Display display = Display.getWithNewlines(code);
diagram.gotoGroup(idNewLong, code, display, GroupType.PACKAGE, currentPackage, NamespaceStrategy.MULTIPLE);
final CommandExecutionResult status = diagram.gotoGroup(idNewLong, code, display, GroupType.PACKAGE,
currentPackage, NamespaceStrategy.MULTIPLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
final String stereotype = arg.get("STEREOTYPE", 0);
if (stereotype != null) {
if (stereotype != null)
p.setStereotype(Stereotype.build(stereotype));
}
final String urlString = arg.get("URL", 0);
if (urlString != null) {
@ -103,9 +105,9 @@ public class CommandNamespaceEmpty extends SingleLineCommand2<ClassDiagram> {
}
final String color = arg.get("COLOR", 0);
if (color != null) {
if (color != null)
p.setSpecificColorTOBEREMOVED(ColorType.BACK, diagram.getSkinParam().getIHtmlColorSet().getColor(color));
}
diagram.endGroup();
return CommandExecutionResult.ok();
}

View File

@ -140,9 +140,10 @@ public class CommandPackage extends SingleLineCommand2<AbstractEntityDiagram> {
display = ident.getLast();
}
final IGroup currentPackage = diagram.getCurrentGroup();
diagram.gotoGroup(ident, code, Display.getWithNewlines(display), GroupType.PACKAGE, currentPackage,
NamespaceStrategy.SINGLE);
final CommandExecutionResult status = diagram.gotoGroup(ident, code, Display.getWithNewlines(display),
GroupType.PACKAGE, currentPackage, NamespaceStrategy.SINGLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();

View File

@ -100,14 +100,15 @@ public class CommandPackageEmpty extends SingleLineCommand2<AbstractEntityDiagra
final IGroup currentPackage = diagram.getCurrentGroup();
final Ident ident = diagram.buildLeafIdent(idShort);
final Code code = diagram.V1972() ? ident : diagram.buildCode(idShort);
diagram.gotoGroup(ident, code, Display.getWithNewlines(display), GroupType.PACKAGE, currentPackage,
NamespaceStrategy.SINGLE);
final CommandExecutionResult status = diagram.gotoGroup(ident, code, Display.getWithNewlines(display),
GroupType.PACKAGE, currentPackage, NamespaceStrategy.SINGLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
final String color = arg.get("COLOR", 0);
if (color != null) {
p.setSpecificColorTOBEREMOVED(ColorType.BACK,
diagram.getSkinParam().getIHtmlColorSet().getColor(color));
}
if (color != null)
p.setSpecificColorTOBEREMOVED(ColorType.BACK, diagram.getSkinParam().getIHtmlColorSet().getColor(color));
diagram.endGroup();
return CommandExecutionResult.ok();
}

View File

@ -78,13 +78,12 @@ public class CommandCreatePackageBlock extends SingleLineCommand2<CompositeDiagr
String display = arg.get("DISPLAY", 0);
final String idShort = arg.get("CODE", 0);
final Code code = diagram.buildCode(idShort);
if (display == null) {
if (display == null)
display = code.getName();
}
final Ident idNewLong = diagram.buildLeafIdent(idShort);
diagram.gotoGroup(idNewLong, code, Display.getWithNewlines(display), GroupType.PACKAGE, currentPackage,
return diagram.gotoGroup(idNewLong, code, Display.getWithNewlines(display), GroupType.PACKAGE, currentPackage,
NamespaceStrategy.SINGLE);
return CommandExecutionResult.ok();
}
}

View File

@ -513,11 +513,6 @@ public class Display implements Iterable<CharSequence> {
return create7(fontConfiguration, horizontalAlignment, spriteContainer, CreoleMode.FULL);
}
public TextBlock createWithNiceCreoleMode(FontConfiguration fontConfiguration,
HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer) {
return create7(fontConfiguration, horizontalAlignment, spriteContainer, defaultCreoleMode);
}
public TextBlock create7(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
ISkinSimple spriteContainer, CreoleMode creoleMode) {
return create0(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode,

View File

@ -37,6 +37,6 @@ package net.sourceforge.plantuml.cucadiagram;
public enum GroupType {
PACKAGE, STATE, CONCURRENT_STATE, INNER_ACTIVITY, CONCURRENT_ACTIVITY, DOMAIN, REQUIREMENT
PACKAGE, TOGETHER, STATE, CONCURRENT_STATE, INNER_ACTIVITY, CONCURRENT_ACTIVITY, DOMAIN, REQUIREMENT
}

View File

@ -242,7 +242,7 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlock,
config = config.underline();
TextBlock bloc = Display.getWithNewlines(s).create8(config, align, skinParam, CreoleMode.SIMPLE_LINE,
skinParam.wrapWidth());
style.wrapWidth());
bloc = TextBlockUtils.fullInnerPosition(bloc, m.getDisplay(false));
return new TextBlockTracer(m, bloc);
}
@ -251,7 +251,7 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlock,
// return ((EmbeddedDiagram) cs).asDraw(skinParam);
return Display.getWithNewlines(cs.toString()).create8(config, align, skinParam, CreoleMode.SIMPLE_LINE,
skinParam.wrapWidth());
style.wrapWidth());
}

View File

@ -61,6 +61,7 @@ import net.sourceforge.plantuml.descdiagram.command.CommandCreateElementMultilin
import net.sourceforge.plantuml.descdiagram.command.CommandLinkElement;
import net.sourceforge.plantuml.descdiagram.command.CommandNewpage;
import net.sourceforge.plantuml.descdiagram.command.CommandPackageWithUSymbol;
import net.sourceforge.plantuml.descdiagram.command.CommandTogether;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJson;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateJsonSingleLine;
import net.sourceforge.plantuml.objectdiagram.command.CommandCreateMap;
@ -83,8 +84,10 @@ public class DescriptionDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandLinkElement());
cmds.add(new CommandHideShow2());
cmds.add(new CommandRemoveRestore());
//
cmds.add(new CommandPackageWithUSymbol());
cmds.add(new CommandTogether());
cmds.add(new CommandEndPackage());
final CommandFactoryNote factoryNoteCommand = new CommandFactoryNote();
cmds.add(factoryNoteCommand.createMultiLine(false));

View File

@ -74,7 +74,7 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2<AbstractEntity
private static IRegex getRegexConcat() {
return RegexConcat.build(CommandPackageWithUSymbol.class.getName(), RegexLeaf.start(), //
new RegexLeaf("SYMBOL",
"(package|rectangle|hexagon|node|artifact|folder|file|frame|cloud|database|storage|component|card|together|queue|stack)"), //
"(package|rectangle|hexagon|node|artifact|folder|file|frame|cloud|database|storage|component|card|queue|stack)"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexConcat( //
@ -156,12 +156,12 @@ public class CommandPackageWithUSymbol extends SingleLineCommand2<AbstractEntity
final Ident ident = diagram.buildLeafIdent(idShort);
final Code code = diagram.V1972() ? ident : diagram.buildCode(idShort);
final IGroup currentPackage = diagram.getCurrentGroup();
diagram.gotoGroup(ident, code, Display.getWithNewlines(display), GroupType.PACKAGE, currentPackage,
NamespaceStrategy.SINGLE);
final CommandExecutionResult status = diagram.gotoGroup(ident, code, Display.getWithNewlines(display),
GroupType.PACKAGE, currentPackage, NamespaceStrategy.SINGLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
final String symbol = arg.get("SYMBOL", 0);
if ("together".equalsIgnoreCase(symbol))
p.setThisIsTogether();
p.setUSymbol(USymbols.fromString(symbol, diagram.getSkinParam().actorStyle(),
diagram.getSkinParam().componentStyle(), diagram.getSkinParam().packageStyle()));

View File

@ -0,0 +1,85 @@
/* ========================================================================
* 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.descdiagram.command;
import net.sourceforge.plantuml.baraye.IEntity;
import net.sourceforge.plantuml.baraye.IGroup;
import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.cucadiagram.Code;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.GroupType;
import net.sourceforge.plantuml.cucadiagram.Ident;
import net.sourceforge.plantuml.cucadiagram.NamespaceStrategy;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
import net.sourceforge.plantuml.utils.LineLocation;
public class CommandTogether extends SingleLineCommand2<AbstractEntityDiagram> {
public CommandTogether() {
super(getRegexConcat());
}
private static IRegex getRegexConcat() {
return RegexConcat.build(CommandTogether.class.getName(), RegexLeaf.start(), //
new RegexLeaf("together"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("\\{"), RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(AbstractEntityDiagram diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
final String idShort = diagram.getUniqueSequence("##");
final Ident ident = diagram.buildLeafIdent(idShort);
final Code code = diagram.V1972() ? ident : diagram.buildCode(idShort);
final IGroup currentPackage = diagram.getCurrentGroup();
final CommandExecutionResult status = diagram.gotoGroup(ident, code, Display.NULL, GroupType.TOGETHER,
currentPackage, NamespaceStrategy.SINGLE);
if (status.isOk() == false)
return status;
final IEntity p = diagram.getCurrentGroup();
p.setThisIsTogether();
return CommandExecutionResult.ok();
}
}

View File

@ -71,31 +71,30 @@ public class PSystemDonors extends PlainDiagram {
private static final int COLS = 6;
private static final int FREE_LINES = 6;
public static final String DONORS = "6miF03mSRygAr4-2sU91UhPs3uiVqvmG9uBbUK9nOX6dku3u0zmxFUutqbz4LtRlcsP4hTScvGoY-Y3e"
+ "0Uzk2-r3wNzz4EOiUH7ScH9SG0g8ukWI-P5kP3jzKcL82TvyX-vlcQmzsJek5ZMV4u6h02gHaD6SOhkN"
+ "YNczGYgb-FoLZz1Fu6tww3nt6aMZ_XEuUTJsKUnzpVzDdMNdeH1cwMu5Hc1KD49rth77-FyKGOKes3bK"
+ "mOubntGghLeELNICUL_N0dLCkbPDauygDQjYN5MaM4Od3Oj89jJbOl8nyg9F6h_Kc_3XkYeauzu1dMrr"
+ "T7tJspRFnFppHH-2ZC4t53Km0jOZQHFDpqCF6aOE66fsuSOM5OuyYOT46hIGN_vGc48loTaLSDCmgG24"
+ "nJjGWIG7rQdXRCTXG8KbjcYpyAYB_S7Ik2uhfp9TQNWYiJ4nKGkeKkH_q0tTKUjuD7NtC3WYFIKQOSjH"
+ "FWjifHrMzFbPIWGBWCwOnVehH3cLr7GSpzg_Soq0kwNbLGzZ2dzEe2bBA9JnYGNgLw7Rve8jUkzoi906"
+ "KH-7R_g8S-MXkWX7P4fPhQENiPrhcJzqsOBrINWABEGzxakn1HniYgigDO0lj0ffgVC992tpxwN7ot_V"
+ "4wufb6IlNxGHhf3qquznCaCXGFkcCHkwYGABiIfMhSKMHB17wT00hOLa4CwHTjb7_99-vIS0tbn2T9kD"
+ "G3tuzvUc31svI0C9NPN62c3rQKNTDCmUmQ1KKz7rHCMNtiQFhqnhx6EbiMfPjCdpHeCnyfjqcc9ZkK95"
+ "XXaMwc7DcU_KbcYNucxfWrUz9tjT1RYKUG-vSUyN6V1p3nce59pkUCz7Rbc62OjPF7EzJEcPdqnk7hhn"
+ "m5qiciQCClMGPS1WVoAgzP6eRnOZl-sGpSXh9Re7iBuA90SFCoh1woScLrHpJCDeaqLqR14YsToyufHT"
+ "kRPWCozFagEYHChDLWz3Gdv7-YAYLT96gSFcV9VW6PAZ82_dtR7gCN-xOUe2AbCdWKzQi6PBQD-pBf21"
+ "jOkUgPR4wVy-iI3lVJampL1y9Oas7jn0CGLcXd0V65WY6SXAnKkR617ulZ_kZXxnEjJZRvzECGwIRf8O"
+ "g8A4arzGJTHPHuGJwpN-_wPFIrpuywyzRPDJlJtx7e9eCuWBG9WNw8gS5q8y1RusDam1dC8I5vqaNBbi"
+ "xPL0b8ADzC4kwlPbHld6JvORaPlMNZzKuKzJZ0h7_K2s2r_HtkUIAjCNqwW6-yEx3XSv6FubgWo8vB8t"
+ "CoiZKIR1nN4VfxKDpLWwG0tcG9q4djtzsMAXeR7sAvGgmmcGhpSabHfbMbWTqzBO2AoK4_jxQqxA6VNP"
+ "6SJF7klCULKFTPCKrrECA7o7ISXJmiJC8d4YWjtYEIb13z_i8rzK2oMnjAdDpX2iaF--7yCR2GVia0SQ"
+ "zOHIdcb13jkaUziiy4U2zn0ba8N5Cjr5B9JAU215KZ2NMyOpfA-q6QVs1j0f2iR_zmQKoqmqFwBPfNTr"
+ "ahd2rdRY82h3_PubjYZPQf61VLVDPUkNvRRDJMROaV-17plV_AYwVX41DKHN9NZDQUJ3ZSrgQjYY_cOE"
+ "zt6PhPl9p-DIj7DK0vlqPAE6iXaev2I4I0T2XVHL-5Nz2LlEEVBfVQeK1cfu7hiDFNYk1kR8LXfU9Gse"
+ "NcHnR7s_uIPF3XHEJBR-LQUnqyEO7gqmrAQRDcl8e1AvIyLNZc1sSqcLjoecbJAyy-FUKBCajFQTxUZq"
+ "JcuXbzTpFBqnWqlzakWpmJa6ch9U7CY41cGHMK4ZYAwI_Q8LPyYeBAl4HwfWc3ZQ4kxGQ3DOk3lMfw5i"
+ "NZ5RuziaFZ126vR-nWNSUuP4pmKD8zkS06nO52cKX6OetMCGEs57p2vkUISVW_BMtW00";
public static final String DONORS = "6r8F0AoFktsyGOBPua5wjfPR-fZcX3WHBCyJYiF0HZpT1SGVuDxfSR-H_YAwqhrlcZ5glPofDGbvnfSS"
+ "iFHQuIQCt_d2eyvUFWIVD0A61iW0SLF_nZdioMcw8rM6bE3DT-Z-bidQawtZOb7pEH6u2g0IqPnYkvU9"
+ "URr2AgNu_9MFq4yWcuBESwPH96fUuEQexQVO-vhxdpexbp1BToim0gEY4QhylkPOUxarxw9QL8c2dQ0A"
+ "TepbL5gr7AgeZ2tBoCS-CD6QGpwgrAoACHUHOXYTD0mY4QZBnUXZvCMOL7wfD-73TLL8Hjq1dMqDT7tJ"
+ "sZRFnFJpHH-XqWRVOAJ025YEn4sqV1v6KD5oG52pYsniKUN8apXGf48B_kKFXQcCafnT0JKLdGP067m7"
+ "AeXafperd6qw3AYmn1Pj5guwrzzO6k_BybIc2mrF83Ow9bg1LOBy3xh1EsiTZqIrXq4HwIdH6BOSvNCe"
+ "M-c75NrkrX910g1Jit1_-IYdahgEurdxTwu5uB2qVDV37CET4sZA4gh8-6X1nXNehBKWYzwx72oaGDZ7"
+ "uPinTAuyj2p2DfvI5clxPMnxBVE7hhJ1-iGy1HR-FVPBhWKSQj9LaXR05rg5TEjyef2M-VVIuzj_tnEk"
+ "AUIurotw25T8-kt7sCnO2D2-PKX3Dq4W2TobLMkn1H7g4TetG6iX6OHpf5ts4R-aZ_m4m5kM4CDX4qez"
+ "-FDBKQQENAW93rsLnWfWQR6YRIfwZs1GgYdeObHnPRJnuolJEljODfOiYpvvNcem9dvDfoWsbYjKP8PX"
+ "eHxHdFcsjfLs2MwNCNZLVM9b5T1QuJtanhrVP22VUyX49EyCnti-SiioJKZCufZhPKhF-cHoyz2D2yxi"
+ "fYSpofH3bW6TtSberaUiiLbCVpF8PkIridWCO7mDHLlmCACOl7uqEQQQOofQcooYOeiGITRc5RkOS1P1"
+ "dfOZoL5HGkKMgriX8RzjOn6HAd6Zr65pkZFm3EzHb9VppbdrcB_TIie2AbERm2KjIAkbOj-pBf2XUoSz"
+ "Kos9C_vzOi6sz-M1mQ7qYecM7jm0c4AIBZ8F128HEWgbz58cXWM-xhUxrUDp7TBnjq-d68T83qa2L073"
+ "sLvGZTJPHeIDzHh_VzEd9Ixy-TUwRPDJlRtttONGE4WMW0WlDAIS4q8y1JutDam6dCAIB3f9k7BMqek1"
+ "o8ADZC4kwcoPqNRZ9ykDo4rlBn-gyAUhN5JOwGTqNBXIx7qkgJ9zCOEAsRxnZSL53W7_4bL6PNBlAgDP"
+ "OIJYA6HnxCVfRKFJ5pf8mHgeJU3OtUyj5XgQQxyYgJGSW7oo8QdKhD2YQarBOoEmKaxixwquAMVMPsUY"
+ "7zCwSrxLGzqaPzTJZ2Xy-oaqzmWJqqNSX8LmJyv934Rune9yKIsMnDAo3ZjDi8B_-tuCRoHiieCF5Ee9"
+ "fJpJWXnXa-nzgoZ-8DvTn40M5ijq9x5Ool58YgHmhcoPd25zfKyufMyGWw9m_7ylGRZCHFCLaYwzgvFC"
+ "vRTMamoYEDJF9Ab5obQB3EoRIovRl2AtRMtIOTl-1txYVFaZwkAR220GpONWDQUX3pVMgwbX2_ARETp7"
+ "PRPk9Z-FIz7EKGbirYSRDS1cgE991647e49u3VrL_GbRpcNus_DKAepKyDnH3JruhWQMaQqql4WQrBp8"
+ "OjhwVifDdXn8d00TKAawZPqUneneXKCjlscp98DAuauL_ti6qjqbLTwgc3JAaAXwWysIs3hlpD3fdDmg"
+ "N5xFyVJ632dr2-eBWZs6kbpF3NW20meXhW05oLNpljMACsHKbbNZmoeKHWws5JKqsWmMsHtZqr0shvYj"
+ "yUpO5i08L0pzWmjxZuP6JgXesUQ4CXiH1ObIQ0ieiySejc6VaYvkEJMTj_PENUY7pPDDDVeMbUB0EZoZ" + "yWe1";
/*
* Special thanks to our sponsors and donors:
*

View File

@ -99,7 +99,7 @@ public class EbnfExpression implements TextBlockable {
tokens.add(new Token(Symbol.REPETITION_OPEN, null));
} else if (ch == '}' && it.peek(1) == '-') {
tokens.add(new Token(Symbol.REPETITION_MINUS_CLOSE, null));
it.next();
it.jump();
} else if (ch == '}') {
tokens.add(new Token(Symbol.REPETITION_CLOSE, null));
} else if (ch == ';' || ch == 0) {
@ -118,7 +118,7 @@ public class EbnfExpression implements TextBlockable {
tokens.clear();
return;
}
it.next();
it.jump();
continue;
}
}
@ -213,14 +213,14 @@ public class EbnfExpression implements TextBlockable {
private String readString(CharInspector it) {
final char separator = it.peek(0);
it.next();
it.jump();
final StringBuilder sb = new StringBuilder();
while (true) {
final char ch = it.peek(0);
if (ch == separator)
return sb.toString();
sb.append(ch);
it.next();
it.jump();
}
}
@ -231,25 +231,25 @@ public class EbnfExpression implements TextBlockable {
if (isLetterOrDigit(ch) == false)
return sb.toString();
sb.append(ch);
it.next();
it.jump();
}
}
private String readComment(CharInspector it) {
final StringBuilder sb = new StringBuilder();
it.next();
it.next();
it.jump();
it.jump();
while (true) {
final char ch = it.peek(0);
if (ch == '\0')
return sb.toString();
if (ch == '*' && it.peek(1) == ')') {
it.next();
it.next();
it.jump();
it.jump();
return sb.toString();
}
sb.append(ch);
it.next();
it.jump();
}
}

View File

@ -45,9 +45,9 @@ public class EggUtils {
final StringBuilder sb = new StringBuilder();
for (byte b : data) {
final String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
if (hex.length() == 1)
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
@ -55,9 +55,9 @@ public class EggUtils {
public static byte[] toByteArrays(String s) {
final byte[] result = new byte[s.length() / 2];
for (int i = 0; i < result.length; i++) {
for (int i = 0; i < result.length; i++)
result[i] = (byte) Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16);
}
return result;
}
@ -71,7 +71,6 @@ public class EggUtils {
if (num != -1) {
result = result.multiply(twentySix);
result = result.add(BigInteger.valueOf(num));
}
}
return result;
@ -80,9 +79,8 @@ public class EggUtils {
private static int convertChar(char c) {
c = StringUtils.goLowerCase(c);
if (c >= 'a' && c <= 'z') {
if (c >= 'a' && c <= 'z')
return c - 'a';
}
return -1;
}
@ -91,11 +89,9 @@ public class EggUtils {
int pos = 0;
for (int i = 0; i < result.length; i++) {
result[i] = (byte) (data[i] ^ key[pos++]);
if (pos == key.length) {
if (pos == key.length)
pos = 0;
}
}
return result;
}

View File

@ -49,6 +49,7 @@ import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.jsondiagram.JsonDiagram;
import net.sourceforge.plantuml.jsondiagram.StyleExtractor;
import net.sourceforge.plantuml.log.Logme;
import net.sourceforge.plantuml.yaml.Highlighted;
public class HclDiagramFactory extends PSystemAbstractFactory {
@ -58,7 +59,7 @@ public class HclDiagramFactory extends PSystemAbstractFactory {
@Override
public Diagram createSystem(UmlSource source, Map<String, String> skinParam) {
final List<String> highlighted = new ArrayList<>();
final List<Highlighted> highlighted = new ArrayList<>();
JsonValue data = null;
StyleExtractor styleExtractor = null;
try {

View File

@ -62,14 +62,15 @@ import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.hand.UGraphicHandwritten;
import net.sourceforge.plantuml.yaml.Highlighted;
public class JsonDiagram extends TitledDiagram {
private final JsonValue root;
private final List<String> highlighted;
private final List<Highlighted> highlighted;
private final boolean handwritten;
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<String> highlighted,
public JsonDiagram(UmlSource source, UmlDiagramType type, JsonValue json, List<Highlighted> highlighted,
StyleExtractor styleExtractor) {
super(source, type, null);
this.handwritten = styleExtractor.isHandwritten();

View File

@ -49,6 +49,9 @@ import net.sourceforge.plantuml.core.UmlSource;
import net.sourceforge.plantuml.json.Json;
import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.json.ParseException;
import net.sourceforge.plantuml.log.Logme;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.yaml.Highlighted;
public class JsonDiagramFactory extends PSystemAbstractFactory {
@ -58,7 +61,7 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
@Override
public Diagram createSystem(UmlSource source, Map<String, String> skinParam) {
final List<String> highlighted = new ArrayList<>();
final List<Highlighted> highlighted = new ArrayList<>();
StyleExtractor styleExtractor = null;
JsonValue json;
try {
@ -72,8 +75,8 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
break;
if (line.startsWith("#")) {
if (line.startsWith("#highlight ")) {
highlighted.add(line.substring("#highlight ".length()).trim());
if (Highlighted.matchesDefinition(line)) {
highlighted.add(Highlighted.build(line));
continue;
}
} else {
@ -87,7 +90,11 @@ public class JsonDiagramFactory extends PSystemAbstractFactory {
}
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.JSON, json, highlighted, styleExtractor);
if (styleExtractor != null)
try {
styleExtractor.applyStyles(result.getSkinParam());
} catch (StyleParsingException e) {
Logme.error(e);
}
return result;
}

View File

@ -63,6 +63,7 @@ import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.yaml.Highlighted;
import smetana.core.CString;
import smetana.core.Macro;
import smetana.core.Z;
@ -125,24 +126,8 @@ public class SmetanaForJson {
.getMergedStyle(skinParam.getCurrentStyleBuilder());
}
private Style getStyleNodeHeader() {
return StyleSignatureBasic.of(SName.root, SName.element, getDiagramType(), SName.header, SName.node)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
}
private Style getStyleNodeHighlight() {
return StyleSignatureBasic.of(SName.root, SName.element, getDiagramType(), SName.node, SName.highlight)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
}
private Style getStyleNodeHeaderHighlight() {
return StyleSignatureBasic.of(SName.root, SName.element, getDiagramType(), SName.header, SName.node, SName.highlight)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
}
private ST_Agnode_s manageOneNode(JsonValue current, List<String> highlighted) {
final TextBlockJson block = new TextBlockJson(skinParam, current, highlighted, getStyleNode(),
getStyleNodeHighlight(), getStyleNodeHeader(), getStyleNodeHeaderHighlight());
private ST_Agnode_s manageOneNode(JsonValue current, List<Highlighted> highlighted) {
final TextBlockJson block = new TextBlockJson(skinParam, current, highlighted);
final ST_Agnode_s node1 = createNode(block.calculateDimension(stringBounder), block.size(), current.isArray(),
(int) block.getWidthColA(stringBounder), (int) block.getWidthColB(stringBounder));
nodes.add(new InternalNode(block, node1));
@ -151,7 +136,7 @@ public class SmetanaForJson {
for (int i = 0; i < children.size(); i++) {
final JsonValue tmp = children.get(i);
if (tmp != null) {
final ST_Agnode_s childBloc = manageOneNode(tmp, removeOneLevel(keys.get(i), highlighted));
final ST_Agnode_s childBloc = manageOneNode(tmp, upOneLevel(keys.get(i), highlighted));
final ST_Agedge_s edge = createEdge(node1, childBloc, i);
edges.add(edge);
}
@ -160,49 +145,41 @@ public class SmetanaForJson {
}
private List<String> removeOneLevel(String key, List<String> list) {
final List<String> result = new ArrayList<>();
for (String tmp : list) {
if (tmp.startsWith("\"" + key + "\"") == false) {
continue;
}
tmp = tmp.trim().replaceFirst("\"([^\"]+)\"", "").trim();
if (tmp.length() > 0) {
tmp = tmp.substring(1).trim();
result.add(tmp);
}
private List<Highlighted> upOneLevel(String key, List<Highlighted> list) {
final List<Highlighted> result = new ArrayList<>();
for (Highlighted tmp : list) {
final Highlighted parent = tmp.upOneLevel(key);
if (parent != null)
result.add(parent);
}
return Collections.unmodifiableList(result);
}
public void drawMe(JsonValue root, List<String> highlighted) {
public void drawMe(JsonValue root, List<Highlighted> highlighted) {
initGraph(root, highlighted);
double max = 0;
for (InternalNode node : nodes) {
for (InternalNode node : nodes)
max = Math.max(max, node.getMaxX());
}
xMirror = new Mirror(max);
for (InternalNode node : nodes) {
node.block.drawU(
getStyleNode().applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet())
for (InternalNode node : nodes)
node.block.drawU(getStyleNode().applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet())
.apply(getPosition(node.node)));
}
final HColor color = getStyleArrow().value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());
for (ST_Agedge_s edge : edges) {
final JsonCurve curve = getCurve(edge, 13);
curve.drawCurve(color, getStyleArrow().applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet()));
curve.drawSpot(
getStyleArrow().applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet())
.apply(color.bg()));
curve.drawSpot(getStyleArrow().applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet()).apply(color.bg()));
}
}
private void initGraph(JsonValue root, List<String> highlighted) {
if (g != null) {
private void initGraph(JsonValue root, List<Highlighted> highlighted) {
if (g != null)
return;
}
Z.open();
try {
@ -268,9 +245,8 @@ public class SmetanaForJson {
final int lineHeight = 0;
final String dotLabel = getDotLabel(size, isArray, colAwidth - 8, colBwidth - 8, lineHeight);
if (size > 0) {
if (size > 0)
agsafeset(node, new CString("label"), new CString(dotLabel), new CString(""));
}
StringBuilder sb = new StringBuilder();
sb.append("N" + node.UID + " [");
@ -284,19 +260,17 @@ public class SmetanaForJson {
private String getDotLabel(int size, boolean isArray, int widthA, int widthB, int height) {
final StringBuilder sb = new StringBuilder("");
if (isArray == false) {
// "+height+"
if (isArray == false)
sb.append("{_dim_" + height + "_" + widthA + "_|{");
}
for (int i = 0; i < size; i++) {
sb.append("<P" + i + ">");
sb.append("_dim_" + height + "_" + widthB + "_");
if (i < size - 1)
sb.append("|");
}
if (isArray == false) {
if (isArray == false)
sb.append("}}");
}
return sb.toString();
}

View File

@ -43,6 +43,7 @@ import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.parser.StyleParser;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.utils.BlocLines;
import net.sourceforge.plantuml.utils.StringLocated;
@ -108,15 +109,14 @@ public class StyleExtractor {
return line.getString().trim().equals("</style>");
}
public void applyStyles(ISkinParam skinParam) {
public void applyStyles(ISkinParam skinParam) throws StyleParsingException {
if (style.size() > 0) {
final StyleBuilder styleBuilder = skinParam.getCurrentStyleBuilder();
final BlocLines blocLines = BlocLines.from(style);
for (Style modifiedStyle : StyleParser.parse(blocLines.subExtract(1, 1), styleBuilder)) {
for (Style modifiedStyle : StyleParser.parse(blocLines.subExtract(1, 1), styleBuilder))
skinParam.muteStyle(modifiedStyle);
}
}
}
public Iterator<String> getIterator() {
return list.iterator();

View File

@ -41,6 +41,7 @@ import java.util.List;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineBreakStrategy;
import net.sourceforge.plantuml.UmlDiagramType;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.Display;
@ -57,38 +58,41 @@ import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.yaml.Highlighted;
//See TextBlockMap
public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcolored {
private final List<Line> lines = new ArrayList<>();
private final Style styleNode;
private final Style styleNodeHightlight;
private final Style styleNodeHeader;
private final Style styleNodeHeaderHighlight;
private final ISkinParam skinParam;
private double totalWidth;
private final JsonValue root;
private final StyleBuilder styleBuilder;
private final SName diagramType;
static class Line {
final TextBlock b1;
final TextBlock b2;
final boolean highlighted;
final Highlighted highlighted;
Line(TextBlock b1, TextBlock b2, boolean highlighted) {
Line(TextBlock b1, TextBlock b2, Highlighted highlighted) {
this.b1 = b1;
this.b2 = b2;
this.highlighted = highlighted;
}
Line(TextBlock b1, boolean highlighted) {
Line(TextBlock b1, Highlighted highlighted) {
this(b1, null, highlighted);
}
@ -102,24 +106,18 @@ public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcol
}
private HColor getBackColor() {
return styleNodeHightlight.value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet());
}
TextBlockJson(ISkinParam skinParam, JsonValue root, List<String> allHighlighteds, Style styleNode,
Style styleNodeHightlight, Style styleNodeHeader, Style styleNodeHeaderHighlight) {
TextBlockJson(ISkinParam skinParam, JsonValue root, List<Highlighted> allHighlighteds) {
this.styleBuilder = skinParam.getCurrentStyleBuilder();
this.diagramType = skinParam.getUmlDiagramType() == UmlDiagramType.JSON ? SName.jsonDiagram : SName.yamlDiagram;
this.skinParam = skinParam;
this.styleNode = styleNode;
this.styleNodeHeaderHighlight = styleNodeHeaderHighlight;
this.styleNodeHightlight = styleNodeHightlight;
this.styleNodeHeader = styleNodeHeader;
this.root = root;
if (root instanceof JsonObject)
for (Member member : (JsonObject) root) {
final String key = member.getName();
final String value = getShortString(member.getValue());
final boolean highlighted = isHighlighted(key, allHighlighteds);
final Highlighted highlighted = isHighlighted(key, allHighlighteds);
final TextBlock block1 = getTextBlock(getStyleToUse(true, highlighted), key);
final TextBlock block2 = getTextBlock(getStyleToUse(false, highlighted), value);
this.lines.add(new Line(block1, block2, highlighted));
@ -127,7 +125,7 @@ public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcol
if (root instanceof JsonArray) {
int i = 0;
for (JsonValue value : (JsonArray) root) {
final boolean highlighted = isHighlighted("" + i, allHighlighteds);
final Highlighted highlighted = isHighlighted("" + i, allHighlighteds);
final TextBlock block2 = getTextBlock(getStyleToUse(false, highlighted), getShortString(value));
this.lines.add(new Line(block2, highlighted));
i++;
@ -135,25 +133,29 @@ public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcol
}
}
private Style getStyleToUse(boolean header, boolean highlighted) {
if (header && highlighted)
return styleNodeHeaderHighlight;
private Style getStyleToUse(boolean header, Highlighted highlighted) {
final StyleSignature signature;
if (header && highlighted != null)
signature = StyleSignatureBasic
.of(SName.root, SName.element, diagramType, SName.header, SName.node, SName.highlight)
.withTOBECHANGED(highlighted.getStereotype());
else if (highlighted != null)
signature = StyleSignatureBasic.of(SName.root, SName.element, diagramType, SName.node, SName.highlight)
.withTOBECHANGED(highlighted.getStereotype());
else if (header)
signature = StyleSignatureBasic.of(SName.root, SName.element, diagramType, SName.header, SName.node);
else
signature = StyleSignatureBasic.of(SName.root, SName.element, diagramType, SName.node);
if (highlighted)
return styleNodeHightlight;
if (header)
return styleNodeHeader;
return styleNode;
return signature.getMergedStyle(styleBuilder);
}
private boolean isHighlighted(String key, List<String> highlighted) {
for (String tmp : highlighted)
if (tmp.trim().equals("\"" + key + "\""))
return true;
private Highlighted isHighlighted(String key, List<Highlighted> highlighted) {
for (Highlighted tmp : highlighted)
if (tmp.isKeyHighlight(key))
return tmp;
return false;
return null;
}
public int size() {
@ -260,6 +262,8 @@ public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcol
final double widthColB = getWidthColB(stringBounder);
double y = 0;
final Style styleNode = StyleSignatureBasic.of(SName.root, SName.element, diagramType, SName.node)
.getMergedStyle(styleBuilder);
final UGraphic ugNode = styleNode.applyStrokeAndLineColor(ug, skinParam.getIHtmlColorSet());
for (Line line : lines) {
final double heightOfRow = line.getHeightOfRow(stringBounder);
@ -283,9 +287,14 @@ public class TextBlockJson extends AbstractTextBlock implements TextBlockBackcol
for (Line line : lines) {
final UGraphic ugline = ugSeparator.apply(UTranslate.dy(y));
final double heightOfRow = line.getHeightOfRow(stringBounder);
if (line.highlighted) {
if (line.highlighted != null) {
final URectangle back = new URectangle(trueWidth - 2, heightOfRow).rounded(4);
ugline.apply(getBackColor()).apply(getBackColor().bg()).apply(new UTranslate(1.5, 0)).draw(back);
final Style styleNodeHighlight = StyleSignatureBasic
.of(SName.root, SName.element, diagramType, SName.node, SName.highlight)
.withTOBECHANGED(line.highlighted.getStereotype()).getMergedStyle(styleBuilder);
final HColor cellBackColor = styleNodeHighlight.value(PName.BackGroundColor)
.asColor(skinParam.getIHtmlColorSet());
ugline.apply(cellBackColor).apply(cellBackColor.bg()).apply(new UTranslate(1.5, 0)).draw(back);
}
if (y > 0)

View File

@ -57,6 +57,8 @@ import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.PackageStyle;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.NoSuchColorException;
public class NServer {
@ -65,6 +67,7 @@ public class NServer {
private USymbol shape = USymbols.RECTANGLE;
private final String name;
private String description;
private String backcolor;
private final NBar bar;
private boolean printFirstLink = true;
@ -110,14 +113,19 @@ public class NServer {
public LinkedElement getLinkedElement(double topMargin, Map<Network, String> conns, List<Network> networks,
ISkinParam skinParam) {
final StyleBuilder styleBuilder = skinParam.getCurrentStyleBuilder();
final SymbolContext symbolContext = getStyleDefinition(SName.server).getMergedStyle(styleBuilder)
SymbolContext symbolContext = getStyleDefinition(SName.server).getMergedStyle(styleBuilder)
.getSymbolContext(skinParam.getIHtmlColorSet());
if (backcolor != null)
try {
final HColor back = skinParam.getIHtmlColorSet().getColor(backcolor);
symbolContext = symbolContext.withBackColor(back);
} catch (NoSuchColorException e) {
}
final Map<Network, TextBlock> conns2 = new LinkedHashMap<Network, TextBlock>();
for (Entry<Network, String> ent : conns.entrySet())
conns2.put(ent.getKey(), toTextBlock(ent.getValue(), skinParam, SName.arrow));
final TextBlock desc = toTextBlock(getDescription(), skinParam, SName.server);
final TextBlock box = getShape().asSmall(TextBlockUtils.empty(0, 0), desc, TextBlockUtils.empty(0, 0),
symbolContext, HorizontalAlignment.CENTER);
@ -142,13 +150,17 @@ public class NServer {
}
public void updateProperties(Map<String, String> props) {
final String description = props.get("description");
if (description != null)
this.setDescription(description);
if (props.get("description") != null)
this.description = props.get("description");
this.backcolor = props.get("color");
final String shape = props.get("shape");
if (shape != null)
this.setShape(shape);
if (shape != null) {
final USymbol shapeFromString = USymbols.fromString(shape, ActorStyle.STICKMAN, ComponentStyle.RECTANGLE,
PackageStyle.RECTANGLE);
if (shapeFromString != null)
this.shape = shapeFromString;
}
}
@ -171,22 +183,10 @@ public class NServer {
return description;
}
public final void setDescription(String description) {
this.description = description;
}
public final String getName() {
return name;
}
public final void setShape(String shapeName) {
final USymbol shapeFromString = USymbols.fromString(shapeName, ActorStyle.STICKMAN, ComponentStyle.RECTANGLE,
PackageStyle.RECTANGLE);
if (shapeFromString != null) {
this.shape = shapeFromString;
}
}
public final USymbol getShape() {
return shape;
}

View File

@ -54,11 +54,11 @@ public class RegexExpression {
result.add(new ReToken(ReTokenType.ANCHOR, s));
} else if (isEscapedChar(it)) {
result.add(new ReToken(ReTokenType.ESCAPED_CHAR, "" + it.peek(1)));
it.next();
it.next();
it.jump();
it.jump();
} else if (current == '|') {
result.add(new ReToken(ReTokenType.ALTERNATIVE, "|"));
it.next();
it.jump();
} else if (current == '[') {
final String s = readGroup(it);
result.add(new ReToken(ReTokenType.GROUP, s));
@ -67,7 +67,7 @@ public class RegexExpression {
result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, s));
} else if (current == ')') {
result.add(new ReToken(ReTokenType.PARENTHESIS_CLOSE, ")"));
it.next();
it.jump();
} else if (isStartQuantifier(it)) {
final String s = readQuantifier(it);
result.add(new ReToken(ReTokenType.QUANTIFIER, s));
@ -76,7 +76,7 @@ public class RegexExpression {
result.add(new ReToken(ReTokenType.CLASS, s));
} else if (isSimpleLetter(current)) {
result.add(new ReToken(ReTokenType.SIMPLE_CHAR, "" + current));
it.next();
it.jump();
} else {
throw new IllegalStateException();
}
@ -95,17 +95,17 @@ public class RegexExpression {
private static String readOpenParenthesis(CharInspector it) {
final char current0 = it.peek(0);
it.next();
it.jump();
final StringBuilder result = new StringBuilder();
result.append(current0);
if (it.peek(0) == '?' && it.peek(1) == ':') {
it.next();
it.next();
it.jump();
it.jump();
result.append("?:");
}
if (it.peek(0) == '?' && it.peek(1) == '!') {
it.next();
it.next();
it.jump();
it.jump();
result.append("?!");
}
return result.toString();
@ -120,20 +120,20 @@ public class RegexExpression {
private static String readQuantifier(CharInspector it) {
final char current0 = it.peek(0);
it.next();
it.jump();
final StringBuilder result = new StringBuilder();
result.append(current0);
if (current0 == '{')
while (it.peek(0) != 0) {
final char ch = it.peek(0);
result.append(ch);
it.next();
it.jump();
if (ch == '}')
break;
}
if (it.peek(0) == '?') {
result.append('?');
it.next();
it.jump();
}
return result.toString();
}
@ -154,17 +154,17 @@ public class RegexExpression {
final char current0 = it.peek(0);
if (current0 != '[')
throw new IllegalStateException();
it.next();
it.jump();
final StringBuilder result = new StringBuilder();
while (it.peek(0) != 0) {
char ch = it.peek(0);
it.next();
it.jump();
if (ch == ']')
break;
result.append(ch);
if (ch == '\\') {
ch = it.peek(0);
it.next();
it.jump();
result.append(ch);
}
@ -175,13 +175,13 @@ public class RegexExpression {
private static String readClass(CharInspector it) {
final char current0 = it.peek(0);
if (current0 == '.') {
it.next();
it.jump();
return "" + current0;
}
if (current0 == '\\') {
it.next();
it.jump();
final String result = "" + current0 + it.peek(0);
it.next();
it.jump();
return result;
}
throw new IllegalStateException();
@ -218,13 +218,13 @@ public class RegexExpression {
private static String readAnchor(CharInspector it) {
final char current0 = it.peek(0);
if (current0 == '^' || current0 == '$') {
it.next();
it.jump();
return "" + current0;
}
if (current0 == '\\') {
it.next();
it.jump();
final String result = "" + current0 + it.peek(0);
it.next();
it.jump();
return result;
}
throw new IllegalStateException();

View File

@ -41,7 +41,6 @@ import java.util.Objects;
import net.sourceforge.plantuml.Guillemet;
import net.sourceforge.plantuml.ISkinSimple;
import net.sourceforge.plantuml.LineBreakStrategy;
import net.sourceforge.plantuml.SpriteContainer;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.creole.Parser;
@ -115,11 +114,6 @@ public class Dictionary implements SpriteContainer, ISkinSimple {
}
@Override
public LineBreakStrategy wrapWidth() {
return LineBreakStrategy.NONE;
}
@Override
public void copyAllFrom(Map<String, String> other) {
throw new UnsupportedOperationException();

View File

@ -62,7 +62,6 @@ import h.ST_Agrec_s;
import h.ST_GVC_s;
import h.ST_boxf;
import net.sourceforge.plantuml.FileFormatOption;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.UmlDiagram;
@ -87,6 +86,9 @@ import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.log.Logme;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.svek.Bibliotekon;
import net.sourceforge.plantuml.svek.Cluster;
import net.sourceforge.plantuml.svek.ClusterHeader;
@ -435,10 +437,17 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker {
this.exportGroups(cluster1, group);
}
private Style getStyle() {
return StyleSignatureBasic
.of(SName.root, SName.element, diagram.getUmlDiagramType().getStyleName(), SName.arrow)
.getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder());
}
private TextBlock getLabel(Link link) {
final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1;
ISkinParam skinParam = diagram.getSkinParam();
final FontConfiguration labelFont = FontConfiguration.create(skinParam, FontParam.ARROW, null);
final Style style = getStyle();
final FontConfiguration labelFont = style.getFontConfiguration(skinParam.getIHtmlColorSet());
final TextBlock label = link.getLabel().create(labelFont,
skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam);
if (TextBlockUtils.isEmpty(label, stringBounder))
@ -454,7 +463,8 @@ public class CucaDiagramFileMakerSmetana implements CucaDiagramFileMaker {
final double marginLabel = 1; // startUid.equals(endUid) ? 6 : 1;
ISkinParam skinParam = diagram.getSkinParam();
final FontConfiguration labelFont = FontConfiguration.create(skinParam, FontParam.ARROW, null);
final Style style = getStyle();
final FontConfiguration labelFont = style.getFontConfiguration(skinParam.getIHtmlColorSet());
final TextBlock label = Display.getWithNewlines(tmp).create(labelFont,
skinParam.getDefaultTextAlignment(HorizontalAlignment.CENTER), skinParam);
if (TextBlockUtils.isEmpty(label, stringBounder))

View File

@ -42,6 +42,7 @@ import h.ST_pointf;
import h.ST_splines;
import h.ST_textlabel_t;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.awt.geom.XPoint2D;
import net.sourceforge.plantuml.cucadiagram.ICucaDiagram;
import net.sourceforge.plantuml.cucadiagram.Link;
@ -50,9 +51,9 @@ import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.graphic.color.ColorType;
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.extremity.ExtremityFactory;
import net.sourceforge.plantuml.ugraphic.UEllipse;
@ -73,7 +74,6 @@ public class SmetanaPath implements UDrawable {
private final TextBlock label;
private final TextBlock headLabel;
private final TextBlock tailLabel;
private final Rose rose = new Rose();
public SmetanaPath(Link link, ST_Agedge_s edge, YMirror ymirror, ICucaDiagram diagram, TextBlock label,
TextBlock tailLabel, TextBlock headLabel) {
@ -91,10 +91,7 @@ public class SmetanaPath implements UDrawable {
if (link.isHidden())
return;
HColor color = StyleSignatureBasic
.of(SName.root, SName.element, diagram.getUmlDiagramType().getStyleName(), SName.arrow)
.getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()).value(PName.LineColor)
.asColor(diagram.getSkinParam().getIHtmlColorSet());
HColor color = getStyle().value(PName.LineColor).asColor(diagram.getSkinParam().getIHtmlColorSet());
if (this.link.getColors() != null) {
final HColor newColor = this.link.getColors().getColor(ColorType.ARROW, ColorType.LINE);
@ -113,9 +110,17 @@ public class SmetanaPath implements UDrawable {
if (link.getColors() != null && link.getColors().getSpecificLineStroke() != null)
stroke = link.getColors().getSpecificLineStroke();
final Url url = link.getUrl();
if (url != null)
ug.startUrl(url);
ug.apply(stroke).apply(color).draw(dotPath);
printExtremityAtStart(ug.apply(color));
printExtremityAtEnd(ug.apply(color));
if (url != null)
ug.closeUrl();
}
if (getLabelRectangleTranslate("label") != null)
label.drawU(ug.apply(getLabelRectangleTranslate("label")));
@ -130,6 +135,12 @@ public class SmetanaPath implements UDrawable {
}
private Style getStyle() {
return StyleSignatureBasic
.of(SName.root, SName.element, diagram.getUmlDiagramType().getStyleName(), SName.arrow)
.getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder());
}
private void printExtremityAtStart(UGraphic ug) {
final ExtremityFactory extremityFactory2 = link.getType().getDecor2()
.getExtremityFactoryComplete(diagram.getSkinParam().getBackgroundColor());

View File

@ -64,7 +64,7 @@ final public class ComponentRoseNote extends AbstractTextualComponent implements
public ComponentRoseNote(Style style, Display strings, double paddingX, double paddingY,
ISkinSimple spriteContainer, HorizontalAlignment textAlignment, HorizontalAlignment position,
Colors colors) {
super(style, spriteContainer.wrapWidth(), textAlignment == HorizontalAlignment.CENTER ? 15 : 6, 15, 5,
super(style, style.wrapWidth(), textAlignment == HorizontalAlignment.CENTER ? 15 : 6, 15, 5,
spriteContainer, strings, true);
this.paddingX = paddingX;
this.paddingY = paddingY;

View File

@ -55,7 +55,7 @@ final public class ComponentRoseNoteBox extends AbstractTextualComponent {
private final double roundCorner;
public ComponentRoseNoteBox(Style style, Display strings, ISkinSimple spriteContainer, Colors colors) {
super(style, spriteContainer.wrapWidth(), 4, 4, 4, spriteContainer, strings, false);
super(style, style.wrapWidth(), 4, 4, 4, spriteContainer, strings, false);
this.symbolContext = style.getSymbolContext(getIHtmlColorSet(), colors);
this.roundCorner = style.value(PName.RoundCorner).asInt(false);

View File

@ -54,7 +54,7 @@ final public class ComponentRoseNoteHexagonal extends AbstractTextualComponent {
private final SymbolContext symbolContext;
public ComponentRoseNoteHexagonal(Style style, Display strings, ISkinSimple spriteContainer, Colors colors) {
super(style, spriteContainer.wrapWidth(), 12, 12, 4, spriteContainer, strings, false);
super(style, style.wrapWidth(), 12, 12, 4, spriteContainer, strings, false);
this.symbolContext = style.getSymbolContext(getIHtmlColorSet(), colors);

View File

@ -48,6 +48,7 @@ import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.security.SFile;
import net.sourceforge.plantuml.style.parser.StyleParser;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.utils.BlocLines;
import net.sourceforge.plantuml.utils.LineLocation;
@ -84,17 +85,19 @@ public class CommandStyleImport extends SingleLineCommand2<TitledDiagram> {
lines = BlocLines.load(f, location);
} else {
final InputStream internalIs = StyleLoader.class.getResourceAsStream("/skin/" + path);
if (internalIs != null) {
if (internalIs != null)
lines = BlocLines.load(internalIs, location);
}
}
if (lines == null) {
if (lines == null)
return CommandExecutionResult.error("Cannot read: " + path);
}
final StyleBuilder styleBuilder = diagram.getSkinParam().getCurrentStyleBuilder();
for (Style modifiedStyle : StyleParser.parse(lines, styleBuilder)) {
for (Style modifiedStyle : StyleParser.parse(lines, styleBuilder))
diagram.getSkinParam().muteStyle(modifiedStyle);
}
} catch (StyleParsingException e) {
return CommandExecutionResult.error("Error in style definition: " + e.getMessage());
} catch (IOException e) {
return CommandExecutionResult.error("Cannot read: " + path);
}

View File

@ -45,6 +45,7 @@ import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.style.parser.StyleParser;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.utils.BlocLines;
public class CommandStyleMultilinesCSS extends CommandMultilines2<TitledDiagram> {
@ -57,7 +58,7 @@ public class CommandStyleMultilinesCSS extends CommandMultilines2<TitledDiagram>
@Override
public String getPatternEnd() {
return "^[%s]*\\</style\\>[%s]*$";
return "^[%s]*\\</?style\\>[%s]*$";
}
private static IRegex getRegexConcat() {
@ -75,6 +76,8 @@ public class CommandStyleMultilinesCSS extends CommandMultilines2<TitledDiagram>
((SkinParam) diagram.getSkinParam()).applyPendingStyleMigration();
return CommandExecutionResult.ok();
} catch (StyleParsingException e) {
return CommandExecutionResult.error("Error in style definition: " + e.getMessage());
} catch (NoStyleAvailableException e) {
// Logme.error(e);
return CommandExecutionResult.error("General failure: no style available.");

View File

@ -235,6 +235,9 @@ public class FromSkinparamToStyle {
// addConvert("sequenceStereotypeFontName", PName.FontName, SName.stereotype);
addConvert("lifelineStrategy", PName.LineStyle, SName.lifeLine);
addConvert("wrapWidth", PName.MaximumWidth, SName.element);
addConvert("HyperlinkUnderline", PName.HyperlinkUnderlineThickness, SName.element);
}
@ -282,6 +285,9 @@ public class FromSkinparamToStyle {
} else if (key.equals("lifelinestrategy")) {
if (value.equalsIgnoreCase("solid"))
value = "0";
} else if (key.equals("hyperlinkunderline")) {
if (value.equalsIgnoreCase("false"))
value = "0";
}
if (value.equalsIgnoreCase("right:right"))

View File

@ -227,7 +227,7 @@ public class Style {
Style result = this.eventuallyOverride(PName.LineThickness, stroke.getThickness());
final double space = stroke.getDashSpace();
final double visible = stroke.getDashVisible();
result = result.eventuallyOverride(PName.LineStyle, "" + visible + ";" + space);
result = result.eventuallyOverride(PName.LineStyle, "" + visible + "-" + space);
return result;
}

View File

@ -45,6 +45,7 @@ import net.sourceforge.plantuml.FileSystem;
import net.sourceforge.plantuml.SkinParam;
import net.sourceforge.plantuml.security.SFile;
import net.sourceforge.plantuml.style.parser.StyleParser;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
import net.sourceforge.plantuml.utils.BlocLines;
import net.sourceforge.plantuml.utils.LineLocationImpl;
import net.sourceforge.plantuml.utils.Log;
@ -59,7 +60,7 @@ public class StyleLoader {
private StyleBuilder styleBuilder;
public StyleBuilder loadSkin(String filename) throws IOException {
public StyleBuilder loadSkin(String filename) throws IOException, StyleParsingException {
this.styleBuilder = new StyleBuilder(skinParam);
final InputStream internalIs = getInputStreamForStyle(filename);
@ -101,7 +102,7 @@ public class StyleLoader {
return internalIs;
}
private void loadSkinInternal(final BlocLines lines) {
private void loadSkinInternal(final BlocLines lines) throws StyleParsingException {
for (Style newStyle : StyleParser.parse(lines, styleBuilder))
this.styleBuilder.loadInternal(newStyle.getSignature(), newStyle);
}

View File

@ -38,29 +38,38 @@ package net.sourceforge.plantuml.style.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleLoader;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.style.Value;
class Context {
private final List<String> data = new ArrayList<String>();
private final Map<PName, Value> map = new EnumMap<>(PName.class);
private Context parent;
public Context push(String newString) {
if (newString.startsWith(":"))
newString = newString.substring(1);
final Context result = new Context();
result.data.addAll(this.data);
result.data.add(newString);
result.parent = this;
return result;
}
public Context pop() {
if (size() == 0)
throw new IllegalStateException();
final Context result = new Context();
result.data.addAll(this.data.subList(0, this.data.size() - 1));
return result;
return this.parent;
}
@Override
@ -98,4 +107,22 @@ class Context {
return Collections.unmodifiableCollection(results);
}
public void putInContext(PName key, Value value) {
map.put(key, value);
}
public Collection<Style> toStyles() {
final Collection<Style> result = new ArrayList<>();
final Collection<StyleSignatureBasic> signatures = toSignatures();
for (StyleSignatureBasic signature : signatures) {
Map<PName, Value> tmp = map;
if (signature.isWithDot())
tmp = StyleLoader.addPriorityForStereotype(tmp);
if (tmp.size() > 0)
result.add(new Style(signature, tmp));
}
return result;
}
}

View File

@ -40,7 +40,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CssVariables {
class CssVariables {
private final Map<String, String> variables = new HashMap<>();
@ -53,6 +53,12 @@ public class CssVariables {
variables.put(m.group(1), m.group(2));
}
public void learn(String var, String value) {
if (var.startsWith("--"))
var = var.substring(2);
variables.put(var, value);
}
public String value(String v) {
if (v.startsWith("var(")) {
final Matcher m = retrieve.matcher(v);

View File

@ -38,118 +38,283 @@ package net.sourceforge.plantuml.style.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.plantuml.command.regex.Matcher2;
import net.sourceforge.plantuml.command.regex.MyPattern;
import net.sourceforge.plantuml.command.regex.Pattern2;
import net.sourceforge.plantuml.style.AutomaticCounter;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleLoader;
import net.sourceforge.plantuml.style.StyleScheme;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.style.Value;
import net.sourceforge.plantuml.style.ValueImpl;
import net.sourceforge.plantuml.utils.BlocLines;
import net.sourceforge.plantuml.utils.StringLocated;
import net.sourceforge.plantuml.utils.CharInspector;
import net.sourceforge.plantuml.utils.Inspector;
import net.sourceforge.plantuml.utils.InspectorUtils;
public class StyleParser {
private final static String KEYNAMES = "[-.\\w(), ]+?";
private final static Pattern2 keyName = MyPattern.cmpile("^[:]?(" + KEYNAMES + ")([%s]+\\*)?[%s]*\\{$");
private final static Pattern2 propertyAndValue = MyPattern.cmpile("^([\\w]+):?[%s]+(.*?);?$");
private final static Pattern2 closeBracket = MyPattern.cmpile("^\\}$");
public static Collection<Style> parse(BlocLines lines, AutomaticCounter counter) throws StyleParsingException {
if (lines.size() == 0)
return Collections.emptyList();
final List<StyleToken> tokens = parse(lines.inspectorWithNewlines());
public static Collection<Style> parse(BlocLines lines, AutomaticCounter counter) {
lines = lines.eventuallyMoveAllEmptyBracket();
final List<Style> result = new ArrayList<>();
final CssVariables variables = new CssVariables();
StyleScheme scheme = StyleScheme.REGULAR;
Context context = new Context();
final List<Map<PName, Value>> maps = new ArrayList<Map<PName, Value>>();
boolean inComment = false;
for (StringLocated s : lines) {
String trimmed = s.getTrimmed().getString();
if (trimmed.startsWith("/*") || trimmed.endsWith("*/"))
// System.err.println("tokens=" + tokens.size());
// if (tokens.size() < 100)
// for (StyleToken t : tokens)
// System.err.println(t);
for (Inspector<StyleToken> ins = InspectorUtils.inspector(tokens); ins.peek(0) != null;) {
final StyleToken token = ins.peek(0);
ins.jump();
if (token.getType() == StyleTokenType.NEWLINE)
continue;
if (trimmed.startsWith("/'") || trimmed.endsWith("'/"))
if (token.getType() == StyleTokenType.SEMICOLON)
continue;
if (trimmed.startsWith("/*") || trimmed.startsWith("/'")) {
inComment = true;
if (ins.peek(0).getType() == StyleTokenType.COMMA) {
final String full = token.getData() + readWithComma(ins);
skipNewLines(ins);
if (ins.peek(0).getType() == StyleTokenType.OPEN_BRACKET) {
context = context.push(full);
ins.jump();
continue;
}
if (trimmed.endsWith("*/") || trimmed.endsWith("'/")) {
inComment = false;
throw new IllegalStateException();
}
if (token.getType() == StyleTokenType.STRING) {
String full = token.getData();
if (ins.peek(0).getType() == StyleTokenType.STAR) {
ins.jump();
full += "*";
}
skipNewLines(ins);
if (ins.peek(0).getType() == StyleTokenType.OPEN_BRACKET) {
context = context.push(full);
ins.jump();
continue;
}
if (inComment)
continue;
skipColon(ins);
if (token.getData().startsWith("--")) {
variables.learn(token.getData(), readValue(ins));
} else if (ins.peek(0).getType() == StyleTokenType.STRING) {
final String valueString = variables.value(readValue(ins));
final String keyString = token.getData();
final PName key = PName.getFromName(keyString, scheme);
if (key == null) {
// System.err.println("Error with key " + keyString);
} else {
final Value value = scheme == StyleScheme.REGULAR ? //
ValueImpl.regular(valueString, counter) : ValueImpl.dark(valueString, counter);
context.putInContext(key, value);
}
} else {
throw new StyleParsingException("parsing");
}
if (trimmed.matches("@media.*dark.*\\{")) {
} else if (token.getType() == StyleTokenType.CLOSE_BRACKET) {
for (Style st : context.toStyles())
result.add(st);
if (context.size() > 0)
context = context.pop();
} else if (token.getType() == StyleTokenType.AROBASE_MEDIA) {
scheme = StyleScheme.DARK;
continue;
}
if (trimmed.startsWith("--")) {
variables.learn(trimmed);
} else if (token.getType() == StyleTokenType.COLON && ins.peek(0).getType() == StyleTokenType.STRING
&& ins.peek(1).getType() == StyleTokenType.OPEN_BRACKET) {
final String full = token.getData() + ins.peek(0).getData();
context = context.push(full);
ins.jump();
ins.jump();
continue;
}
final int x = trimmed.lastIndexOf("//");
if (x != -1)
trimmed = trimmed.substring(0, x).trim();
final Matcher2 mKeyNames = keyName.matcher(trimmed);
if (mKeyNames.find()) {
String names = mKeyNames.group(1);
final boolean isRecurse = mKeyNames.group(2) != null;
if (isRecurse)
names += "*";
context = context.push(names);
maps.add(new EnumMap<PName, Value>(PName.class));
} else if (token.getType() == StyleTokenType.COLON && ins.peek(0).getType() == StyleTokenType.STRING
&& ins.peek(1).getType() == StyleTokenType.STAR
&& ins.peek(2).getType() == StyleTokenType.OPEN_BRACKET) {
final String full = token.getData() + ins.peek(0).getData() + ins.peek(1).getData();
context = context.push(full);
ins.jump();
ins.jump();
ins.jump();
continue;
}
final Matcher2 mPropertyAndValue = propertyAndValue.matcher(trimmed);
if (mPropertyAndValue.find()) {
final PName key = PName.getFromName(mPropertyAndValue.group(1), scheme);
final String value = variables.value(mPropertyAndValue.group(2));
if (key != null && maps.size() > 0)
maps.get(maps.size() - 1).put(key, //
scheme == StyleScheme.REGULAR ? //
ValueImpl.regular(value, counter) : ValueImpl.dark(value, counter));
continue;
}
final Matcher2 mCloseBracket = closeBracket.matcher(trimmed);
if (mCloseBracket.find()) {
if (context.size() > 0) {
final Collection<StyleSignatureBasic> signatures = context.toSignatures();
for (StyleSignatureBasic signature : signatures) {
Map<PName, Value> tmp = maps.get(maps.size() - 1);
if (signature.isWithDot())
tmp = StyleLoader.addPriorityForStereotype(tmp);
if (tmp.size() > 0) {
final Style style = new Style(signature, tmp);
result.add(style);
}
}
context = context.pop();
maps.remove(maps.size() - 1);
} else if (token.getType() == StyleTokenType.OPEN_BRACKET) {
throw new StyleParsingException("Invalid open bracket");
} else {
scheme = StyleScheme.REGULAR;
throw new IllegalStateException(token.toString());
}
}
}
return Collections.unmodifiableList(result);
}
private static String readWithComma(Inspector<StyleToken> ins) {
final StringBuilder result = new StringBuilder();
while (ins.peek(0) != null) {
final StyleToken current = ins.peek(0);
if (current.getType() != StyleTokenType.STRING && current.getType() != StyleTokenType.COMMA)
return result.toString();
result.append(current.getData());
ins.jump();
}
return result.toString();
}
private static String readValue(Inspector<StyleToken> ins) throws StyleParsingException {
final StringBuilder result = new StringBuilder();
while (ins.peek(0) != null) {
final StyleToken current = ins.peek(0);
if (current.getType() == StyleTokenType.NEWLINE || current.getType() == StyleTokenType.SEMICOLON
|| current.getType() == StyleTokenType.CLOSE_BRACKET)
return result.toString();
if (current.getType() == StyleTokenType.STRING) {
if (result.length() > 0)
result.append(' ');
result.append(current.getData());
ins.jump();
} else if (current.getType() == StyleTokenType.COLON) {
result.append(current.getData());
ins.jump();
if (ins.peek(0).getType() == StyleTokenType.STRING) {
result.append(ins.peek(0).getData());
ins.jump();
} else
throw new StyleParsingException("bad definition");
} else
throw new StyleParsingException("bad definition");
}
return result.toString();
}
private static void skipNewLines(Inspector<StyleToken> ins) {
while (true) {
final StyleToken token = ins.peek(0);
if (token == null || token.getType() != StyleTokenType.NEWLINE)
return;
ins.jump();
}
}
private static void skipColon(Inspector<StyleToken> ins) {
while (true) {
final StyleToken token = ins.peek(0);
if (token == null || token.getType() != StyleTokenType.COLON)
return;
ins.jump();
}
}
private static List<StyleToken> parse(CharInspector ins) throws StyleParsingException {
final List<StyleToken> result = new ArrayList<>();
while (true) {
final char current = ins.peek(0);
if (current == '\0')
break;
// System.err.println("current=" + current);
if (current == ' ' || current == '\t') {
ins.jump();
// Skipping
} else if (current == '/' && ins.peek(1) == '/') {
jumpUntil(ins, '\n');
} else if (current == '/' && ins.peek(1) == '\'') {
jumpUntil(ins, '\'', '/');
} else if (current == '/' && ins.peek(1) == '*') {
jumpUntil(ins, '*', '/');
} else if (current == ',') {
result.add(new StyleToken(StyleTokenType.COMMA, ","));
ins.jump();
} else if (current == ';') {
result.add(new StyleToken(StyleTokenType.SEMICOLON, ";"));
ins.jump();
} else if (current == '\n' || current == '\r') {
result.add(new StyleToken(StyleTokenType.NEWLINE, "NEWLINE"));
ins.jump();
} else if (current == '*') {
result.add(new StyleToken(StyleTokenType.STAR, "*"));
ins.jump();
} else if (current == ':') {
result.add(new StyleToken(StyleTokenType.COLON, ":"));
ins.jump();
} else if (current == '{') {
result.add(new StyleToken(StyleTokenType.OPEN_BRACKET, "{"));
ins.jump();
} else if (current == '}') {
result.add(new StyleToken(StyleTokenType.CLOSE_BRACKET, "}"));
ins.jump();
} else if (current == '@') {
result.add(new StyleToken(StyleTokenType.AROBASE_MEDIA, readArobaseMedia(ins)));
} else {
final String s = readString(ins);
if (s.startsWith("<"))
throw new StyleParsingException("Cannot understand <");
result.add(new StyleToken(StyleTokenType.STRING, s));
}
}
return result;
}
private static void jumpUntil(CharInspector ins, char ch1) {
while (ins.peek(0) != 0) {
if (ins.peek(0) == ch1) {
ins.jump();
return;
}
ins.jump();
}
}
private static void jumpUntil(CharInspector ins, char ch1, char ch2) {
while (ins.peek(0) != 0) {
if (ins.peek(0) == ch1 && ins.peek(1) == ch2) {
ins.jump();
ins.jump();
return;
}
ins.jump();
}
}
private static String readArobaseMedia(CharInspector ins) {
final char current0 = ins.peek(0);
if (current0 != '@')
throw new IllegalStateException();
ins.jump();
final StringBuilder result = new StringBuilder();
while (ins.peek(0) != 0) {
char ch = ins.peek(0);
ins.jump();
if (ch == '{' || ch == '}' || ch == ';')
break;
result.append(ch);
}
return result.toString();
}
private static String readString(CharInspector ins) {
final StringBuilder result = new StringBuilder();
while (ins.peek(0) != 0) {
char ch = ins.peek(0);
if (ch == '\n' || ch == '\r')
break;
if (ch == ' ' && result.charAt(0) != '.')
break;
if (ch == '{' || ch == '}' || ch == ';' || ch == ',' || ch == ':' || ch == '\t')
break;
ins.jump();
// System.err.println("ch=" + ch);
result.append(ch);
}
if (result.charAt(0) == '.')
return result.toString().trim();
return result.toString();
}
}

View File

@ -0,0 +1,177 @@
/* ========================================================================
* 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.style.parser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.plantuml.command.regex.Matcher2;
import net.sourceforge.plantuml.command.regex.MyPattern;
import net.sourceforge.plantuml.command.regex.Pattern2;
import net.sourceforge.plantuml.style.AutomaticCounter;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleLoader;
import net.sourceforge.plantuml.style.StyleScheme;
import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.style.Value;
import net.sourceforge.plantuml.style.ValueImpl;
import net.sourceforge.plantuml.utils.BlocLines;
import net.sourceforge.plantuml.utils.StringLocated;
public class StyleParserLegacy {
private final static String KEYNAMES = "[-.\\w(), ]+?";
private final static Pattern2 keyName = MyPattern.cmpile("^[:]?(" + KEYNAMES + ")([%s]+\\*)?[%s]*\\{$");
private final static Pattern2 propertyAndValue = MyPattern.cmpile("^([\\w]+):?[%s]+(.*?);?$");
private final static Pattern2 closeBracket = MyPattern.cmpile("^\\}$");
public static Collection<Style> parse(BlocLines lines, AutomaticCounter counter) throws StyleParsingException {
final Collection<Style> foo = StyleParser.parse(lines, counter);
lines = lines.eventuallyMoveAllEmptyBracket();
final List<Style> result = new ArrayList<>();
final CssVariables variables = new CssVariables();
StyleScheme scheme = StyleScheme.REGULAR;
Context context = new Context();
final List<Map<PName, Value>> maps = new ArrayList<Map<PName, Value>>();
boolean inComment = false;
for (StringLocated s : lines) {
String trimmed = s.getTrimmed().getString();
if (trimmed.startsWith("/*") || trimmed.endsWith("*/"))
continue;
if (trimmed.startsWith("/'") || trimmed.endsWith("'/"))
continue;
if (trimmed.startsWith("/*") || trimmed.startsWith("/'")) {
inComment = true;
continue;
}
if (trimmed.endsWith("*/") || trimmed.endsWith("'/")) {
inComment = false;
continue;
}
if (inComment)
continue;
if (trimmed.matches("@media.*dark.*\\{")) {
scheme = StyleScheme.DARK;
continue;
}
if (trimmed.startsWith("--")) {
variables.learn(trimmed);
continue;
}
final int x = trimmed.lastIndexOf("//");
if (x != -1)
trimmed = trimmed.substring(0, x).trim();
final Matcher2 mKeyNames = keyName.matcher(trimmed);
if (mKeyNames.find()) {
String names = mKeyNames.group(1);
final boolean isRecurse = mKeyNames.group(2) != null;
if (isRecurse)
names += "*";
context = context.push(names);
maps.add(new EnumMap<PName, Value>(PName.class));
continue;
}
final Matcher2 mPropertyAndValue = propertyAndValue.matcher(trimmed);
if (mPropertyAndValue.find()) {
final PName key = PName.getFromName(mPropertyAndValue.group(1), scheme);
final String value = variables.value(mPropertyAndValue.group(2));
if (key != null && maps.size() > 0)
maps.get(maps.size() - 1).put(key, //
scheme == StyleScheme.REGULAR ? //
ValueImpl.regular(value, counter) : ValueImpl.dark(value, counter));
continue;
}
final Matcher2 mCloseBracket = closeBracket.matcher(trimmed);
if (mCloseBracket.find()) {
if (context.size() > 0) {
final Collection<StyleSignatureBasic> signatures = context.toSignatures();
for (StyleSignatureBasic signature : signatures) {
Map<PName, Value> tmp = maps.get(maps.size() - 1);
if (signature.isWithDot())
tmp = StyleLoader.addPriorityForStereotype(tmp);
if (tmp.size() > 0) {
final Style style = new Style(signature, tmp);
result.add(style);
}
}
context = context.pop();
maps.remove(maps.size() - 1);
} else {
scheme = StyleScheme.REGULAR;
}
}
}
System.err.println("foo1=" + foo.size());
System.err.println("result=" + result.size());
if (foo.size() != result.size() || foo.size() < 10) {
print_debug(foo);
print_debug(result);
}
// return Collections.unmodifiableList(result);
return Collections.unmodifiableCollection(foo);
}
private static void print_debug(Collection<Style> list) {
System.err.println("=====================");
int i = 0;
for (Style style : list) {
System.err.println("style=" + i + " " + style.getSignature());
i++;
}
System.err.println("=====================");
}
}

View File

@ -0,0 +1,44 @@
/* ========================================================================
* 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.style.parser;
public class StyleParsingException extends Exception {
public StyleParsingException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,61 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, 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.style.parser;
public class StyleToken {
private final StyleTokenType type;
private final String data;
public StyleToken(StyleTokenType type, String data) {
this.type = type;
this.data = data;
}
@Override
public String toString() {
return type.toString() + "[" + data + "]";
}
public final StyleTokenType getType() {
return type;
}
public final String getData() {
return data;
}
}

View File

@ -0,0 +1,48 @@
/* ========================================================================
* 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.style.parser;
enum StyleTokenType {
OPEN_BRACKET, //
CLOSE_BRACKET, //
STRING, //
COMMA, //
STAR, //
NEWLINE, //
SEMICOLON, //
COLON, //
AROBASE_MEDIA, //
}

View File

@ -323,7 +323,17 @@ public final class GeneralImageBuilder {
if (strictUmlStyle)
return false;
return entity.isGroup() == false && entity.getLeafType() == LeafType.NOTE && onlyOneLink(entity);
if (entity.isGroup())
return false;
if (entity.getLeafType() != LeafType.NOTE)
return false;
final Link single = onlyOneLink(entity);
if (single == null)
return false;
return single.getOther(entity).getLeafType() != LeafType.NOTE;
}
static class EntityImageSimpleEmpty implements IEntityImage {
@ -482,20 +492,19 @@ public final class GeneralImageBuilder {
return null;
}
private boolean onlyOneLink(IEntity ent) {
int nb = 0;
private Link onlyOneLink(IEntity ent) {
Link single = null;
for (Link link : dotData.getLinks()) {
if (link.isInvis())
continue;
if (link.contains(ent) == false)
continue;
if (link.contains(ent))
nb++;
if (nb > 1)
return false;
if (single != null)
return null;
single = link;
}
return nb == 1;
return single;
}
private IEntityImage error(File dotExe) {
@ -584,7 +593,8 @@ public final class GeneralImageBuilder {
if (g.isRemoved())
continue;
if (dotData.isEmpty(g) && g.getGroupType() == GroupType.PACKAGE) {
if (dotData.isEmpty(g)
&& (g.getGroupType() == GroupType.PACKAGE || g.getGroupType() == GroupType.TOGETHER)) {
final ISkinParam skinParam = dotData.getSkinParam();
final ILeaf folder = entityFactory.createLeafForEmptyGroup(g, skinParam);
printEntity(dotStringFactory, folder);

View File

@ -41,6 +41,7 @@ import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.awt.geom.XDimension2D;
import net.sourceforge.plantuml.baraye.ILeaf;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.EntityPortion;
import net.sourceforge.plantuml.cucadiagram.LeafType;
@ -95,7 +96,8 @@ public class EntityImageClassHeader extends AbstractEntityImage {
if (displayGenericWithOldFashion && entity.getGeneric() != null)
display = display.addGeneric(entity.getGeneric());
TextBlock name = display.createWithNiceCreoleMode(fontConfigurationName, HorizontalAlignment.CENTER, skinParam);
TextBlock name = display.create8(fontConfigurationName, HorizontalAlignment.CENTER, skinParam,
CreoleMode.FULL_BUT_UNDERSCORE, style.wrapWidth());
final VisibilityModifier modifier = entity.getVisibilityModifier();
if (modifier == null) {
name = TextBlockUtils.withMargin(name, 3, 3, 0, 0);
@ -127,12 +129,6 @@ public class EntityImageClassHeader extends AbstractEntityImage {
HorizontalAlignment.CENTER, skinParam);
genericBlock = TextBlockUtils.withMargin(genericBlock, 1, 1);
// final HColor classBackground = SkinParamUtils.getColor(getSkinParam(), stereotype, ColorParam.background);
// final HColor classBorder = SkinParamUtils.getFontColor(getSkinParam(), FontParam.CLASS_STEREOTYPE,
// stereotype);
// final HColor classBackground = style.value(PName.BackGroundColor).asColor(skinParam.getThemeStyle(),
// skinParam.getIHtmlColorSet());
final HColor classBackground = skinParam.getBackgroundColor();
final HColor classBorder = style.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());

View File

@ -167,7 +167,7 @@ public class EntityImageDescription extends AbstractEntityImage {
desc = TextBlockUtils.empty(style.value(PName.MinimumWidth).asDouble(), 0);
else
desc = BodyFactory.create3(entity.getDisplay(), getSkinParam(), defaultAlign, fcTitle,
getSkinParam().wrapWidth(), styleTitle);
style.wrapWidth(), styleTitle);
stereo = TextBlockUtils.empty(0, 0);

View File

@ -118,7 +118,7 @@ public class EntityImageNote extends AbstractEntityImage implements Stencil {
textBlock = new TextBlockEmpty();
else
textBlock = BodyFactory.create3(strings, getSkinParam(), horizontalAlignment, fontConfiguration,
getSkinParam().wrapWidth(), style);
style.wrapWidth(), style);
}

View File

@ -80,7 +80,7 @@ public class EntityImageState extends EntityImageStateCommon {
.getFontConfiguration(getSkinParam().getIHtmlColorSet());
this.fields = list.create8(fieldsFontConfiguration, HorizontalAlignment.LEFT, skinParam, CreoleMode.FULL,
skinParam.wrapWidth());
getStyleState().wrapWidth());
}

View File

@ -72,7 +72,7 @@ public abstract class EntityImageStateCommon extends AbstractEntityImage {
getSkinParam().getIHtmlColorSet(), entity.getColors());
this.title = entity.getDisplay().create8(titleFontConfiguration, HorizontalAlignment.CENTER, skinParam,
CreoleMode.FULL, skinParam.wrapWidth());
CreoleMode.FULL, getStyleState().wrapWidth());
this.url = entity.getUrl99();
}

View File

@ -177,7 +177,7 @@ public class EntityImageTips extends AbstractEntityImage {
final UStroke stroke = style.getStroke();
final TextBlock textBlock = BodyFactory.create3(display, skinParam, HorizontalAlignment.LEFT, fc,
skinParam.wrapWidth(), style);
style.wrapWidth(), style);
return new Opale(shadowing, borderColor, noteBackgroundColor, textBlock, true, stroke);
}

View File

@ -369,7 +369,11 @@ public class BlocLines implements Iterable<StringLocated> {
}
public CharInspector inspector() {
return new CharInspectorImpl(this);
return new CharInspectorImpl(this, false);
}
public CharInspector inspectorWithNewlines() {
return new CharInspectorImpl(this, true);
}
}

View File

@ -38,5 +38,5 @@ package net.sourceforge.plantuml.utils;
public interface CharInspector {
char peek(int ahead);
void next();
void jump();
}

View File

@ -38,11 +38,13 @@ package net.sourceforge.plantuml.utils;
public class CharInspectorImpl implements CharInspector {
final private BlocLines data;
final private boolean insertNewlines;
private int line = 0;
private int pos = 0;
CharInspectorImpl(BlocLines input) {
data = input;
CharInspectorImpl(BlocLines input, boolean insertNewlines) {
this.data = input;
this.insertNewlines = insertNewlines;
}
@Override
@ -56,11 +58,13 @@ public class CharInspectorImpl implements CharInspector {
}
private String getCurrentLine() {
if (insertNewlines)
return data.getAt(line).getTrimmed().getString() + "\n";
return data.getAt(line).getTrimmed().getString();
}
@Override
public void next() {
public void jump() {
if (line == -1)
throw new IllegalStateException();
pos++;

View File

@ -0,0 +1,42 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, 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.utils;
public interface Inspector<O> {
O peek(int ahead);
void jump();
}

View File

@ -0,0 +1,65 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, 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.utils;
import java.util.List;
public abstract class InspectorUtils {
private InspectorUtils() {
}
public static <O> Inspector<O> inspector(final List<O> list) {
return new Inspector<O>() {
private int pos = 0;
@Override
public O peek(int ahead) {
final int tmp = pos + ahead;
if (tmp < list.size())
return list.get(tmp);
return null;
}
@Override
public void jump() {
pos++;
}
};
}
}

View File

@ -45,7 +45,7 @@ public class Version {
private static final int MAJOR_SEPARATOR = 1000000;
public static int version() {
return 1202214;
return 1202300;
}
public static int versionPatched() {
@ -81,7 +81,7 @@ public class Version {
}
public static int beta() {
final int beta = 6;
final int beta = 0;
return beta;
}
@ -94,7 +94,7 @@ public class Version {
}
public static long compileTime() {
return 1670351053526L;
return 1673289094677L;
}
public static String compileTimeString() {

View File

@ -57,9 +57,9 @@ public final class WindowsDotArchive {
}
public final synchronized static WindowsDotArchive getInstance() {
if (singleton == null) {
if (singleton == null)
singleton = new WindowsDotArchive();
}
return singleton;
}
@ -92,14 +92,19 @@ public final class WindowsDotArchive {
if (name.length() == 0)
break;
final int size = readNumber(is);
try (final OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(dir, name)))) {
for (int i = 0; i < size; i++) {
final File fileout = new File(dir, name);
if (fileout.exists())
for (int i = 0; i < size; i++)
is.read();
else
try (final OutputStream fos = new BufferedOutputStream(new FileOutputStream(fileout))) {
for (int i = 0; i < size; i++)
fos.write(is.read());
}
}
}
}
}
public synchronized boolean isThereArchive() {
if (isThereArchive == null)
@ -112,18 +117,19 @@ public final class WindowsDotArchive {
}
public synchronized File getWindowsExeLite() {
if (isThereArchive() == false) {
if (isThereArchive() == false)
return null;
}
if (exe == null)
try {
if (exe == null) {
final File tmp = new File(System.getProperty("java.io.tmpdir"), "_graphviz");
try {
tmp.mkdirs();
extract(tmp);
exe = new File(tmp, "dot.exe");
} catch (IOException e) {
Logme.error(e);
}
exe = new File(tmp, "dot.exe");
}
return exe;
}

View File

@ -0,0 +1,107 @@
/* ========================================================================
* 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.yaml;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
public class Highlighted {
public static final String HIGHLIGHTED = "#highlight ";
private final static Pattern pattern = Pattern.compile("^([^<>]+)(\\<\\<.*\\>\\>)?$");
private final List<String> paths;
private final Stereotype stereotype;
private Highlighted(List<String> paths, Stereotype stereotype) {
this.paths = paths;
this.stereotype = stereotype;
}
public static boolean matchesDefinition(String line) {
return line.startsWith(Highlighted.HIGHLIGHTED);
}
public static Highlighted build(String line) {
if (matchesDefinition(line) == false)
throw new IllegalStateException();
line = line.substring(HIGHLIGHTED.length()).trim();
final Matcher matcher = pattern.matcher(line);
if (matcher.matches() == false)
throw new IllegalStateException();
final String paths = matcher.group(1).trim();
final Stereotype stereotype = matcher.group(2) == null ? null : Stereotype.build(matcher.group(2));
return new Highlighted(toList(paths), stereotype);
}
private static List<String> toList(String paths) {
final List<String> result = new ArrayList<>();
for (String s : paths.split("/"))
result.add(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(s.trim(), "\""));
return result;
}
public Highlighted upOneLevel(String key) {
if (paths.size() <= 1)
return null;
final String first = paths.get(0);
if ("**".equals(first))
return new Highlighted(paths, stereotype);
if ("*".equals(first) || first.equals(key))
return new Highlighted(paths.subList(1, paths.size()), stereotype);
return null;
}
public boolean isKeyHighlight(String key) {
if (paths.size() == 2 && paths.get(0).equals("**") && paths.get(1).equals(key))
return true;
return paths.size() == 1 && paths.get(0).equals(key);
}
public final Stereotype getStereotype() {
return stereotype;
}
}

View File

@ -53,6 +53,7 @@ import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.jsondiagram.JsonDiagram;
import net.sourceforge.plantuml.jsondiagram.StyleExtractor;
import net.sourceforge.plantuml.log.Logme;
import net.sourceforge.plantuml.style.parser.StyleParsingException;
public class YamlDiagramFactory extends PSystemAbstractFactory {
@ -62,7 +63,7 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
@Override
public Diagram createSystem(UmlSource source, Map<String, String> skinParam) {
final List<String> highlighted = new ArrayList<>();
final List<Highlighted> highlighted = new ArrayList<>();
JsonValue yaml = null;
StyleExtractor styleExtractor = null;
try {
@ -75,8 +76,8 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
if (it.hasNext() == false)
break;
if (line.startsWith("#highlight ")) {
highlighted.add(line.substring("#highlight ".length()).trim());
if (Highlighted.matchesDefinition(line)) {
highlighted.add(Highlighted.build(line));
continue;
}
list.add(line);
@ -87,7 +88,11 @@ public class YamlDiagramFactory extends PSystemAbstractFactory {
}
final JsonDiagram result = new JsonDiagram(source, UmlDiagramType.YAML, yaml, highlighted, styleExtractor);
if (styleExtractor != null) {
try {
styleExtractor.applyStyles(result.getSkinParam());
} catch (StyleParsingException e) {
Logme.error(e);
}
final String title = styleExtractor.getTitle();
if (title != null)
result.setTitle(DisplayPositioned.single(Display.getWithNewlines(title), HorizontalAlignment.CENTER,

Binary file not shown.

Binary file not shown.

View File

@ -258,10 +258,6 @@ class SkinParamTest {
assertThat(skinParam.useSwimlanes(umlDiagramType)).isFalse();
assertThat(skinParam.useUnderlineForHyperlink()).isNotNull();
final LineBreakStrategy wrapWidth = skinParam.wrapWidth();
assertThat(wrapWidth.isAuto()).isFalse();
assertThat(wrapWidth.getMaxWidth()).isZero();
}
@Test