1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-11-22 04:55:10 +00:00

version 1.2018.0

This commit is contained in:
Arnaud Roques 2018-01-04 23:32:45 +01:00
parent 6ede577f01
commit 0be8ee2e6f
36 changed files with 1497 additions and 94 deletions

View File

@ -35,7 +35,7 @@
<groupId>net.sourceforge.plantuml</groupId> <groupId>net.sourceforge.plantuml</groupId>
<artifactId>plantuml</artifactId> <artifactId>plantuml</artifactId>
<version>1.2017.21-SNAPSHOT</version> <version>1.2018.1-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>PlantUML</name> <name>PlantUML</name>

View File

@ -109,15 +109,29 @@ public class CharSequence2Impl implements CharSequence2 {
if (trim.startsWith("/'")) { if (trim.startsWith("/'")) {
final int idx = string.indexOf("'/"); final int idx = string.indexOf("'/");
if (idx != -1) { if (idx != -1) {
return new CharSequence2Impl(s.subSequence(idx + 2, s.length()), location, preprocessorError); return new CharSequence2Impl(removeSpecialInnerComment(s.subSequence(idx + 2, s.length())), location,
preprocessorError);
} }
} }
if (trim.endsWith("'/")) { if (trim.endsWith("'/")) {
final int idx = string.lastIndexOf("/'"); final int idx = string.lastIndexOf("/'");
if (idx != -1) { if (idx != -1) {
return new CharSequence2Impl(s.subSequence(0, idx), location, preprocessorError); return new CharSequence2Impl(removeSpecialInnerComment(s.subSequence(0, idx)), location,
preprocessorError);
} }
} }
if (trim.contains("/'''") && trim.contains("'''/")) {
return new CharSequence2Impl(removeSpecialInnerComment(s), location, preprocessorError);
}
return this; return this;
} }
private CharSequence removeSpecialInnerComment(CharSequence cs) {
final String s = cs.toString();
if (s.contains("/'''") && s.contains("'''/")) {
return s.replaceAll("/'''[-\\w]*'''/", "");
}
return cs;
}
} }

View File

@ -54,7 +54,8 @@ public enum LineParam {
activityBorder, activityBorder,
titleBorder, titleBorder,
diagramBorder, diagramBorder,
rectangleBorder; rectangleBorder,
componentBorder;
// sequenceBoxBorder(0.1); // sequenceBoxBorder(0.1);
} }

View File

@ -421,7 +421,15 @@ public class Option {
final Defines result = Defines.createWithFileName(f); final Defines result = Defines.createWithFileName(f);
for (Map.Entry<String, String> ent : defines.entrySet()) { for (Map.Entry<String, String> ent : defines.entrySet()) {
result.define(ent.getKey(), Arrays.asList(ent.getValue()), false); result.define(ent.getKey(), Arrays.asList(ent.getValue()), false);
}
return result;
}
public Defines getDefaultDefines() {
final Defines result = Defines.createEmpty();
result.overrideFilename(filename);
for (Map.Entry<String, String> ent : defines.entrySet()) {
result.define(ent.getKey(), Arrays.asList(ent.getValue()), false);
} }
return result; return result;
} }
@ -557,10 +565,6 @@ public class Option {
return imageIndex; return imageIndex;
} }
public String getFilename() {
return filename;
}
public final void setFilename(String filename) { public final void setFilename(String filename) {
this.filename = filename; this.filename = filename;
} }

View File

@ -69,8 +69,8 @@ public class Pipe {
ps.flush(); ps.flush();
return error; return error;
} }
final SourceStringReader sourceStringReader = new SourceStringReader(Defines.createEmpty(option final Defines defines = option.getDefaultDefines();
.getFilename()), source, option.getConfig()); final SourceStringReader sourceStringReader = new SourceStringReader(defines, source, option.getConfig());
if (option.isComputeurl()) { if (option.isComputeurl()) {
for (BlockUml s : sourceStringReader.getBlocks()) { for (BlockUml s : sourceStringReader.getBlocks()) {
ps.println(s.getEncodedUrl()); ps.println(s.getEncodedUrl());

View File

@ -62,7 +62,7 @@ import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory;
import net.sourceforge.plantuml.ftp.FtpServer; import net.sourceforge.plantuml.ftp.FtpServer;
import net.sourceforge.plantuml.objectdiagram.ObjectDiagramFactory; import net.sourceforge.plantuml.objectdiagram.ObjectDiagramFactory;
import net.sourceforge.plantuml.png.MetadataTag; import net.sourceforge.plantuml.png.MetadataTag;
import net.sourceforge.plantuml.preproc.Stdlib; import net.sourceforge.plantuml.preproc.StdlibOld;
import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory; import net.sourceforge.plantuml.sequencediagram.SequenceDiagramFactory;
import net.sourceforge.plantuml.statediagram.StateDiagramFactory; import net.sourceforge.plantuml.statediagram.StateDiagramFactory;
import net.sourceforge.plantuml.stats.StatsUtils; import net.sourceforge.plantuml.stats.StatsUtils;
@ -79,7 +79,7 @@ public class Run {
final Option option = new Option(argsArray); final Option option = new Option(argsArray);
ProgressBar.setEnable(option.isTextProgressBar()); ProgressBar.setEnable(option.isTextProgressBar());
if (OptionFlags.getInstance().getExtractStdLib()) { if (OptionFlags.getInstance().getExtractStdLib()) {
Stdlib.extractStdLib(); StdlibOld.extractStdLib();
return; return;
} }
if (OptionFlags.getInstance().isDumpStats()) { if (OptionFlags.getInstance().isDumpStats()) {

View File

@ -115,6 +115,13 @@ public class ActivityDiagram3 extends UmlDiagram {
} }
} }
public void addSpot(String spot) {
final InstructionSpot ins = new InstructionSpot(spot, nextLinkRenderer(), swinlanes.getCurrentSwimlane());
current().add(ins);
setNextLinkRendererInternal(LinkRendering.none());
manageSwimlaneStrategy();
}
public CommandExecutionResult addGoto(String name) { public CommandExecutionResult addGoto(String name) {
final InstructionGoto ins = new InstructionGoto(swinlanes.getCurrentSwimlane(), name); final InstructionGoto ins = new InstructionGoto(swinlanes.getCurrentSwimlane(), name);
current().add(ins); current().add(ins);

View File

@ -45,6 +45,7 @@ import net.sourceforge.plantuml.activitydiagram3.command.CommandArrow3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandArrowLong3; import net.sourceforge.plantuml.activitydiagram3.command.CommandArrowLong3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandBackward3; import net.sourceforge.plantuml.activitydiagram3.command.CommandBackward3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandBreak; import net.sourceforge.plantuml.activitydiagram3.command.CommandBreak;
import net.sourceforge.plantuml.activitydiagram3.command.CommandCircleSpot3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElse3; import net.sourceforge.plantuml.activitydiagram3.command.CommandElse3;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf2; import net.sourceforge.plantuml.activitydiagram3.command.CommandElseIf2;
import net.sourceforge.plantuml.activitydiagram3.command.CommandElseLegacy1; import net.sourceforge.plantuml.activitydiagram3.command.CommandElseLegacy1;
@ -126,6 +127,7 @@ public class ActivityDiagramFactory3 extends UmlDiagramFactory {
// cmds.add(new CommandGroupEnd3()); // cmds.add(new CommandGroupEnd3());
cmds.add(new CommandStart3()); cmds.add(new CommandStart3());
cmds.add(new CommandStop3()); cmds.add(new CommandStop3());
cmds.add(new CommandCircleSpot3());
cmds.add(new CommandBreak()); cmds.add(new CommandBreak());
cmds.add(new CommandEnd3()); cmds.add(new CommandEnd3());
cmds.add(new CommandKill3()); cmds.add(new CommandKill3());

View File

@ -0,0 +1,80 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileKilled;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
public class InstructionSpot extends MonoSwimable implements Instruction {
private boolean killed = false;
private final LinkRendering inlinkRendering;
private final String spot;
public InstructionSpot(String spot, LinkRendering inlinkRendering, Swimlane swimlane) {
super(swimlane);
this.spot = spot;
this.inlinkRendering = inlinkRendering;
if (inlinkRendering == null) {
throw new IllegalArgumentException();
}
}
public Ftile createFtile(FtileFactory factory) {
Ftile result = factory.spot(getSwimlaneIn(), spot);
result = eventuallyAddNote(factory, result, result.getSwimlaneIn());
if (killed) {
return new FtileKilled(result);
}
return result;
}
public void add(Instruction other) {
throw new UnsupportedOperationException();
}
final public boolean kill() {
this.killed = true;
return true;
}
public LinkRendering getInLinkRendering() {
return inlinkRendering;
}
}

View File

@ -0,0 +1,64 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandCircleSpot3 extends SingleLineCommand2<ActivityDiagram3> {
public CommandCircleSpot3() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(//
new RegexLeaf("^"), //
new RegexLeaf("SPOT", "\\((\\S)\\)"), //
new RegexLeaf(";?$"));
}
@Override
protected CommandExecutionResult executeArg(ActivityDiagram3 diagram, RegexResult arg) {
diagram.addSpot(arg.get("SPOT", 0));
return CommandExecutionResult.ok();
}
}

View File

@ -62,6 +62,8 @@ public interface FtileFactory {
public Ftile end(Swimlane swimlane); public Ftile end(Swimlane swimlane);
public Ftile spot(Swimlane swimlane, String spot);
public Ftile activity(Display label, Swimlane swimlane, BoxStyle style, Colors colors); public Ftile activity(Display label, Swimlane swimlane, BoxStyle style, Colors colors);
public Ftile addNote(Ftile ftile, Swimlane swimlane, Collection<PositionedNote> notes); public Ftile addNote(Ftile ftile, Swimlane swimlane, Collection<PositionedNote> notes);
@ -74,8 +76,9 @@ public interface FtileFactory {
public Ftile assembly(Ftile tile1, Ftile tile2); public Ftile assembly(Ftile tile1, Ftile tile2);
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test,
Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward, boolean noOut); Display yes, Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward,
boolean noOut);
public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out, public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out,
LinkRendering afterEndwhile, HtmlColor color, Instruction specialOut); LinkRendering afterEndwhile, HtmlColor color, Instruction specialOut);

View File

@ -111,6 +111,10 @@ public class FtileFactoryDelegator implements FtileFactory {
return factory.stop(swimlane); return factory.stop(swimlane);
} }
public Ftile spot(Swimlane swimlane, String spot) {
return factory.spot(swimlane, spot);
}
public Ftile activity(Display label, Swimlane swimlane, BoxStyle style, Colors colors) { public Ftile activity(Display label, Swimlane swimlane, BoxStyle style, Colors colors) {
return factory.activity(label, swimlane, style, colors); return factory.activity(label, swimlane, style, colors);
} }
@ -141,10 +145,11 @@ public class FtileFactoryDelegator implements FtileFactory {
return factory.assembly(tile1, tile2); return factory.assembly(tile1, tile2);
} }
public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test, Display yes, public Ftile repeat(Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, Display test,
Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward, boolean noOut) { Display yes, Display out, HtmlColor color, LinkRendering backRepeatLinkRendering, Ftile backward,
return factory.repeat(swimlane, swimlaneOut, startLabel, repeat, test, yes, out, color, backRepeatLinkRendering, boolean noOut) {
backward, noOut); return factory.repeat(swimlane, swimlaneOut, startLabel, repeat, test, yes, out, color,
backRepeatLinkRendering, backward, noOut);
} }
public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out, public Ftile createWhile(Swimlane swimlane, Ftile whileBlock, Display test, Display yes, Display out,
@ -181,4 +186,5 @@ public class FtileFactoryDelegator implements FtileFactory {
protected FtileFactory getFactory() { protected FtileFactory getFactory() {
return factory; return factory;
} }
} }

View File

@ -55,6 +55,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileBox; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileBox;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleEnd; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleEnd;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleSpot;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleStart; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleStart;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleStop; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileCircleStop;
import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileDecorateIn; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileDecorateIn;
@ -91,6 +92,12 @@ public class VCompactFactory implements FtileFactory {
return new FtileCircleStop(skinParam(), color, swimlane); return new FtileCircleStop(skinParam(), color, swimlane);
} }
public Ftile spot(Swimlane swimlane, String spot) {
// final HtmlColor color = rose.getHtmlColor(skinParam, ColorParam.activityBackground);
final UFont font = skinParam.getFont(null, false, FontParam.ACTIVITY);
return new FtileCircleSpot(skinParam(), swimlane, spot, font);
}
public Ftile end(Swimlane swimlane) { public Ftile end(Swimlane swimlane) {
final HtmlColor color = rose.getHtmlColor(skinParam, ColorParam.activityEnd); final HtmlColor color = rose.getHtmlColor(skinParam, ColorParam.activityEnd);
return new FtileCircleEnd(skinParam(), color, swimlane); return new FtileCircleEnd(skinParam(), color, swimlane);
@ -163,5 +170,4 @@ public class VCompactFactory implements FtileFactory {
public ISkinParam skinParam() { public ISkinParam skinParam() {
return skinParam; return skinParam;
} }
} }

View File

@ -82,7 +82,7 @@ public class FtileBox extends AbstractFtile {
private final LinkRendering inRenreding; private final LinkRendering inRenreding;
private final Swimlane swimlane; private final Swimlane swimlane;
private final BoxStyle style; private final BoxStyle style;
private final ISkinParam skinParam; // private final ISkinParam skinParam;
final public LinkRendering getInLinkRendering() { final public LinkRendering getInLinkRendering() {
return inRenreding; return inRenreding;
@ -119,7 +119,7 @@ public class FtileBox extends AbstractFtile {
public FtileBox(ISkinParam skinParam, Display label, UFont font, Swimlane swimlane, BoxStyle style) { public FtileBox(ISkinParam skinParam, Display label, UFont font, Swimlane swimlane, BoxStyle style) {
super(skinParam); super(skinParam);
this.style = style; this.style = style;
this.skinParam = skinParam; // this.skinParam = skinParam;
this.swimlane = swimlane; this.swimlane = swimlane;
this.inRenreding = new LinkRendering(HtmlColorAndStyle.build(skinParam)); this.inRenreding = new LinkRendering(HtmlColorAndStyle.build(skinParam));
final FontConfiguration fc = new FontConfiguration(skinParam, FontParam.ACTIVITY, null); final FontConfiguration fc = new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
@ -142,8 +142,8 @@ public class FtileBox extends AbstractFtile {
final double heightTotal = dimTotal.getHeight(); final double heightTotal = dimTotal.getHeight();
final UDrawable rect = style.getUDrawable(widthTotal, heightTotal, skinParam().shadowing()); final UDrawable rect = style.getUDrawable(widthTotal, heightTotal, skinParam().shadowing());
final HtmlColor borderColor = SkinParamUtils.getColor(skinParam, ColorParam.activityBorder, null); final HtmlColor borderColor = SkinParamUtils.getColor(skinParam(), ColorParam.activityBorder, null);
final HtmlColor backColor = SkinParamUtils.getColor(skinParam, ColorParam.activityBackground, null); final HtmlColor backColor = SkinParamUtils.getColor(skinParam(), ColorParam.activityBackground, null);
ug = ug.apply(new UChangeColor(borderColor)).apply(new UChangeBackColor(backColor)).apply(getThickness()); ug = ug.apply(new UChangeColor(borderColor)).apply(new UChangeBackColor(backColor)).apply(getThickness());
rect.drawU(ug); rect.drawU(ug);

View File

@ -0,0 +1,119 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.ftile.vertical;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile;
import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile;
import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry;
import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.ugraphic.UCenteredCharacter;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UEllipse;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class FtileCircleSpot extends AbstractFtile {
private static final int SIZE = 20;
private final Swimlane swimlane;
private final String spot;
private final FontConfiguration fc;
public FtileCircleSpot(ISkinParam skinParam, Swimlane swimlane, String spot, UFont font) {
super(skinParam);
this.spot = spot;
this.swimlane = swimlane;
// this.font = font;
this.fc = new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
}
@Override
public Collection<Ftile> getMyChildren() {
return Collections.emptyList();
}
public Set<Swimlane> getSwimlanes() {
if (swimlane == null) {
return Collections.emptySet();
}
return Collections.singleton(swimlane);
}
public Swimlane getSwimlaneIn() {
return swimlane;
}
public Swimlane getSwimlaneOut() {
return swimlane;
}
public void drawU(UGraphic ug) {
final HtmlColor borderColor = SkinParamUtils.getColor(skinParam(), ColorParam.activityBorder, null);
final HtmlColor backColor = SkinParamUtils.getColor(skinParam(), ColorParam.activityBackground, null);
final UEllipse circle = new UEllipse(SIZE, SIZE);
if (skinParam().shadowing()) {
circle.setDeltaShadow(3);
}
ug.apply(new UChangeColor(borderColor)).apply(new UChangeBackColor(backColor)).apply(getThickness())
.draw(circle);
ug.apply(new UChangeColor(fc.getColor())).apply(new UTranslate(SIZE / 2, SIZE / 2))
.draw(new UCenteredCharacter(spot.charAt(0), fc.getFont()));
}
@Override
protected FtileGeometry calculateDimensionFtile(StringBounder stringBounder) {
return new FtileGeometry(SIZE, SIZE, SIZE / 2, 0, SIZE);
}
}

View File

@ -39,7 +39,7 @@ import java.io.IOException;
public class TranscoderSmart implements Transcoder { public class TranscoderSmart implements Transcoder {
// private final Transcoder oldOne = new TranscoderImpl(new AsciiEncoder(), new CompressionHuffman()); private final Transcoder oldOne = new TranscoderImpl(new AsciiEncoder(), new CompressionHuffman());
private final Transcoder zlib = new TranscoderImpl(new AsciiEncoder(), new CompressionZlib()); private final Transcoder zlib = new TranscoderImpl(new AsciiEncoder(), new CompressionZlib());
private final Transcoder brotli = new TranscoderImpl(new AsciiEncoder(), new CompressionBrotli()); private final Transcoder brotli = new TranscoderImpl(new AsciiEncoder(), new CompressionBrotli());
@ -47,7 +47,12 @@ public class TranscoderSmart implements Transcoder {
if (code.startsWith("0")) { if (code.startsWith("0")) {
return brotli.decode(code.substring(1)); return brotli.decode(code.substring(1));
} }
return zlib.decode(code); try {
return zlib.decode(code);
} catch (Exception ex) {
return oldOne.decode(code);
}
// return zlib.decode(code);
} }
public String encode(String text) throws IOException { public String encode(String text) throws IOException {

View File

@ -41,6 +41,10 @@ import net.sourceforge.plantuml.cucadiagram.Rankdir;
public enum Position { public enum Position {
RIGHT, LEFT, BOTTOM, TOP; RIGHT, LEFT, BOTTOM, TOP;
public static Position fromString(String s) {
return Position.valueOf(s.toUpperCase());
}
public Position withRankdir(Rankdir rankdir) { public Position withRankdir(Rankdir rankdir) {
if (rankdir == null) { if (rankdir == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();

View File

@ -51,7 +51,7 @@ public class SkinParameter {
ColorParam.artifactBorder, FontParam.ARTIFACT, FontParam.ARTIFACT_STEREOTYPE); ColorParam.artifactBorder, FontParam.ARTIFACT, FontParam.ARTIFACT_STEREOTYPE);
public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground, public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground,
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE); ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder);
public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground, public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground,
ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE); ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE);
@ -72,7 +72,7 @@ public class SkinParameter {
ColorParam.frameBorder, FontParam.FRAME, FontParam.FRAME_STEREOTYPE); ColorParam.frameBorder, FontParam.FRAME, FontParam.FRAME_STEREOTYPE);
public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground, public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground,
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE); ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder);
public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground, public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground,
ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE); ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE);
@ -90,7 +90,7 @@ public class SkinParameter {
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE); ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground, public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground,
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE); ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder);
public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground, public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground,
ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE); ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
@ -115,14 +115,21 @@ public class SkinParameter {
private final FontParam fontParam; private final FontParam fontParam;
private final FontParam fontParamStereotype; private final FontParam fontParamStereotype;
private final String name; private final String name;
private final LineParam lineParam;
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam, private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
FontParam fontParamStereotype) { FontParam fontParamStereotype, LineParam lineParam) {
this.name = name; this.name = name;
this.colorParamBack = colorParamBack; this.colorParamBack = colorParamBack;
this.colorParamBorder = colorParamBorder; this.colorParamBorder = colorParamBorder;
this.fontParam = fontParam; this.fontParam = fontParam;
this.fontParamStereotype = fontParamStereotype; this.fontParamStereotype = fontParamStereotype;
this.lineParam = lineParam;
}
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
FontParam fontParamStereotype) {
this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null);
} }
public String getUpperCaseName() { public String getUpperCaseName() {
@ -154,8 +161,8 @@ public class SkinParameter {
public UStroke getStroke(ISkinParam skinParam, Stereotype stereotype) { public UStroke getStroke(ISkinParam skinParam, Stereotype stereotype) {
UStroke result = null; UStroke result = null;
if (name.equals("RECTANGLE")) { if (lineParam != null) {
result = skinParam.getThickness(LineParam.rectangleBorder, stereotype); result = skinParam.getThickness(lineParam, stereotype);
} }
if (result == null) { if (result == null) {
result = new UStroke(1.5); result = new UStroke(1.5);

View File

@ -67,20 +67,14 @@ public class Defines implements Truth {
} }
public static Defines createEmpty() { public static Defines createEmpty() {
return createEmpty(null); return new Defines();
}
public static Defines createEmpty(String filename) {
final Defines result = new Defines();
if (filename != null) {
result.overrideFilename(filename);
}
return result;
} }
public void overrideFilename(String filename) { public void overrideFilename(String filename) {
environment.put("filename", filename); if (filename != null) {
environment.put("filenameNoExtension", nameNoExtension(filename)); environment.put("filename", filename);
environment.put("filenameNoExtension", nameNoExtension(filename));
}
} }
public void importFrom(Defines other) { public void importFrom(Defines other) {
@ -98,7 +92,8 @@ public class Defines implements Truth {
if (file == null) { if (file == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
final Defines result = createEmpty(file.getName()); final Defines result = createEmpty();
result.overrideFilename(file.getName());
result.environment.put("filedate", new Date(file.lastModified()).toString()); result.environment.put("filedate", new Date(file.lastModified()).toString());
// result.environment.put("filename", file.getName()); // result.environment.put("filename", file.getName());
// result.environment.put("filenameNoExtension", nameNoExtension(file)); // result.environment.put("filenameNoExtension", nameNoExtension(file));

View File

@ -266,7 +266,7 @@ public class PreprocessorInclude implements ReadLine {
} }
private InputStream getStdlibInputStream(String filename) { private InputStream getStdlibInputStream(String filename) {
return Stdlib.getResourceAsStream(filename); return StdlibOld.getResourceAsStream(filename);
} }
private InputStream getStdlibInputStreamOld(String filename) { private InputStream getStdlibInputStreamOld(String filename) {

View File

@ -0,0 +1,266 @@
package net.sourceforge.plantuml.preproc;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.plantuml.Log;
import org.brotli.dec.BrotliInputStream;
public class Stdlib6 {
static private final Map<String, Stdlib6> all = new ConcurrentHashMap<String, Stdlib6>();
private static final String SEPARATOR = "\uF8FF";
private final Map<String, List<String>> raw = new HashMap<String, List<String>>();
// private final Map<String, SoftReference<byte[]>> cache = new ConcurrentHashMap<String, SoftReference<byte[]>>();
private final String name;
private final Map<String, String> info = new HashMap<String, String>();
public static InputStream getResourceAsStream(String fullname) {
fullname = fullname.toLowerCase().replace(".puml", "");
final int last = fullname.indexOf('/');
if (last == -1) {
return null;
}
try {
final Stdlib6 folder = retrieve(fullname.substring(0, last));
if (folder == null || folder.raw.size() == 0) {
return null;
}
final byte[] data = folder.getData(fullname.substring(last + 1));
if (data == null) {
return null;
}
return new ByteArrayInputStream(data);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static InputStream getInternalInputStream(String fullname, String extension) {
final String res = "/stdlib/" + fullname + extension;
return Stdlib6.class.getResourceAsStream(res);
}
private static Stdlib6 retrieve(final String name) throws IOException {
Stdlib6 result = all.get(name);
if (result == null) {
result = new Stdlib6(name);
all.put(name, result);
}
return result;
}
private final Pattern sizePattern = Pattern.compile("\\[(\\d+)x(\\d+)/16\\]");
private Stdlib6(String name) throws IOException {
this.name = name;
Log.info("Opening archive " + name);
final DataInputStream dataStream = getDataStream();
if (dataStream == null) {
return;
}
fillMap(dataStream.readUTF());
// final InputStream spriteStream = getSpriteStream();
int pos = 0;
while (true) {
final String filename = dataStream.readUTF();
// System.err.println("filename=" + filename);
if (filename.equals(SEPARATOR)) {
break;
}
final List<String> text = new ArrayList<String>();
while (true) {
final String s = dataStream.readUTF();
if (s.equals(SEPARATOR)) {
break;
}
text.add(s);
if (isSpriteLine(s)) {
final Matcher m = sizePattern.matcher(s);
final boolean ok = m.find();
if (ok == false) {
throw new IOException(s);
}
final int width = Integer.parseInt(m.group(1));
final int height = Integer.parseInt(m.group(2));
text.add("" + pos);
pos += spriteSize(width, height);
// System.err.println("Sprite! " + width + " " + height + " " + s);
text.add("}");
}
}
raw.put(filename.toLowerCase(), text);
// System.err.println("data=" + text.size());
// final int len = is.readInt();
// this.data.put(filename.toLowerCase(), new Portion(pos, len));
// pos += len;
}
dataStream.close();
}
private int spriteSize(int width, int height) {
final int nbLines = (height + 1) / 2;
return width * nbLines;
}
private String readSprite(int width, int height, InputStream inputStream) throws IOException {
final StringBuilder result = new StringBuilder();
final int nbLines = (height + 1) / 2;
int line = 0;
for (int j = 0; j < nbLines; j++) {
final StringBuilder sb1 = new StringBuilder();
final StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < width; i++) {
final int b = inputStream.read();
final int b1 = (b & 0xF0) >> 4;
final int b2 = (b & 0x0F);
sb1.append(toHexString(b1));
sb2.append(toHexString(b2));
}
result.append(sb1.toString());
result.append("\n");
line++;
if (line < height) {
result.append(sb2.toString());
result.append("\n");
line++;
}
}
return result.toString();
}
private String toHexString(final int b) {
return Integer.toHexString(b).toUpperCase();
}
private boolean isSpriteLine(String s) {
return s.trim().startsWith("sprite") && s.trim().endsWith("{");
}
private void fillMap(String infoString) {
for (String s : infoString.split("\n")) {
if (s.contains("=")) {
final String data[] = s.split("=");
this.info.put(data[0], data[1]);
}
}
}
private DataInputStream getDataStream() throws IOException {
final InputStream raw = getInternalInputStream(name, "-dat2.repx");
if (raw == null) {
return null;
}
return new DataInputStream(new BrotliInputStream(raw));
}
private InputStream getSpriteStream() throws IOException {
final InputStream raw = getInternalInputStream(name, "-spr.repx");
if (raw == null) {
return null;
}
return new BrotliInputStream(raw);
}
private byte[] getData(String filename) throws IOException {
final List<String> result = raw.get(filename);
if (result == null) {
return null;
}
final StringBuilder sb = new StringBuilder();
for (Iterator<String> it = result.iterator(); it.hasNext();) {
final String s = it.next();
sb.append(s);
sb.append("\n");
if (isSpriteLine(s)) {
final Matcher m = sizePattern.matcher(s);
final boolean ok = m.find();
if (ok == false) {
throw new IOException(s);
}
final int width = Integer.parseInt(m.group(1));
final int height = Integer.parseInt(m.group(2));
final InputStream spriteStream = getSpriteStream();
final int pos = Integer.parseInt(it.next());
// System.err.println("pos=" + pos);
spriteStream.skip(pos);
sb.append(readSprite(width, height, spriteStream));
sb.append("\n");
spriteStream.close();
}
}
return sb.toString().getBytes("UTF-8");
}
public static void extractStdLib() throws IOException {
// for (String name : getAll()) {
// final Stdlib6 folder = new Stdlib6(name);
// folder.extractMeFull(new File("stdlib", name));
// }
}
private static List<String> getAll() throws IOException {
final List<String> result = new ArrayList<String>();
final InputStream home = getInternalInputStream("home", ".repx");
final BufferedReader br = new BufferedReader(new InputStreamReader(home));
String name;
while ((name = br.readLine()) != null) {
result.add(name);
}
return Collections.unmodifiableList(result);
}
// private void extractMeFull(File dir) throws IOException {
// final DataInputStream idx = getDataIndex();
// final DataInputStream txt = getFullTexts();
// final String infoString = idx.readUTF();
// while (true) {
// final String filename = idx.readUTF();
// if (filename.length() == 0) {
// idx.close();
// txt.close();
// return;
// }
// final int len = idx.readInt();
// final File f = new File("stdlib/" + name + "/" + filename + ".puml");
// f.getParentFile().mkdirs();
// final FileOutputStream fos = new FileOutputStream(f);
// final byte data[] = new byte[len];
// txt.readFully(data);
// fos.write(data);
// fos.close();
// }
// }
public static void addInfoVersion(List<String> strings) {
try {
for (String name : getAll()) {
final Stdlib6 folder = new Stdlib6(name);
strings.add("* " + name + " (Version " + folder.getVersion() + ")");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private String getVersion() {
return info.get("VERSION");
}
}

View File

@ -20,9 +20,9 @@ import net.sourceforge.plantuml.Log;
import org.brotli.dec.BrotliInputStream; import org.brotli.dec.BrotliInputStream;
public class Stdlib { public class StdlibOld {
static private final Map<String, Stdlib> all = new ConcurrentHashMap<String, Stdlib>(); static private final Map<String, StdlibOld> all = new ConcurrentHashMap<String, StdlibOld>();
static class Portion { static class Portion {
int position; int position;
@ -54,7 +54,7 @@ public class Stdlib {
return null; return null;
} }
try { try {
final Stdlib folder = retrieve(fullname.substring(0, last)); final StdlibOld folder = retrieve(fullname.substring(0, last));
if (folder == null) { if (folder == null) {
return null; return null;
} }
@ -71,19 +71,19 @@ public class Stdlib {
private static InputStream getInternalInputStream(String fullname, String extension) { private static InputStream getInternalInputStream(String fullname, String extension) {
final String res = "/stdlib/" + fullname + extension; final String res = "/stdlib/" + fullname + extension;
return Stdlib.class.getResourceAsStream(res); return StdlibOld.class.getResourceAsStream(res);
} }
private static Stdlib retrieve(final String name) throws IOException { private static StdlibOld retrieve(final String name) throws IOException {
Stdlib result = all.get(name); StdlibOld result = all.get(name);
if (result == null) { if (result == null) {
result = new Stdlib(name); result = new StdlibOld(name);
all.put(name, result); all.put(name, result);
} }
return result; return result;
} }
private Stdlib(String name) throws IOException { private StdlibOld(String name) throws IOException {
this.name = name; this.name = name;
Log.info("Opening archive " + name); Log.info("Opening archive " + name);
int pos = 0; int pos = 0;
@ -147,7 +147,7 @@ public class Stdlib {
public static void extractStdLib() throws IOException { public static void extractStdLib() throws IOException {
for (String name : getAll()) { for (String name : getAll()) {
final Stdlib folder = new Stdlib(name); final StdlibOld folder = new StdlibOld(name);
folder.extractMeFull(new File("stdlib", name)); folder.extractMeFull(new File("stdlib", name));
} }
} }
@ -188,7 +188,7 @@ public class Stdlib {
public static void addInfoVersion(List<String> strings) { public static void addInfoVersion(List<String> strings) {
try { try {
for (String name : getAll()) { for (String name : getAll()) {
final Stdlib folder = new Stdlib(name); final StdlibOld folder = new StdlibOld(name);
strings.add("* " + name + " (Version " + folder.getVersion() + ")"); strings.add("* " + name + " (Version " + folder.getVersion() + ")");
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -58,7 +58,7 @@ public class PSystemSaltFactory extends PSystemBasicFactory<PSystemSalt> {
@Override @Override
public PSystemSalt executeLine(PSystemSalt system, String line) { public PSystemSalt executeLine(PSystemSalt system, String line) {
if (system == null && line.equals("salt")) { if (system == null && line.replace('\t', ' ').trim().equals("salt")) {
return new PSystemSalt(); return new PSystemSalt();
} }
if (system == null) { if (system == null) {

View File

@ -0,0 +1,76 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.timingdiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.Position;
import net.sourceforge.plantuml.command.SingleLineCommand2;
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.Display;
public class CommandNote extends SingleLineCommand2<TimingDiagram> {
public CommandNote() {
super(getRegexConcat());
}
private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("[%s]*note[%s]+"), //
new RegexLeaf("POSITION", "(top|bottom)[%s]+of[%s]+"), //
new RegexLeaf("CODE", CommandTimeMessage.PLAYER_CODE), //
new RegexLeaf("[%s]*:[%s]*"), //
new RegexLeaf("NOTE", "(.+)"), //
new RegexLeaf("[%s]*$"));
}
@Override
final protected CommandExecutionResult executeArg(TimingDiagram diagram, RegexResult arg) {
final String code = arg.get("CODE", 0);
final Player player = diagram.getPlayer(code);
if (player == null) {
return CommandExecutionResult.error("Unkown \"" + code + "\"");
}
final Display note = Display.getWithNewlines(arg.get("NOTE", 0));
final TimeTick now = diagram.getNow();
// final Colors colors = color().getColor(arg, diagram.getSkinParam().getIHtmlColorSet());
player.addNote(now, note, Position.fromString(arg.get("POSITION", 0)));
return CommandExecutionResult.ok();
}
}

View File

@ -0,0 +1,84 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.timingdiagram;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.command.BlocLines;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.CommandMultilines2;
import net.sourceforge.plantuml.command.MultilinesStrategy;
import net.sourceforge.plantuml.command.Position;
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.Display;
public class CommandNoteLong extends CommandMultilines2<TimingDiagram> {
public CommandNoteLong() {
super(getRegexConcat(), MultilinesStrategy.REMOVE_STARTING_QUOTE);
}
public String getPatternEnd() {
return "(?i)^end[%s]?note$";
}
public CommandExecutionResult executeNow(final TimingDiagram diagram, BlocLines lines) {
final RegexResult line0 = getStartingPattern().matcher(StringUtils.trin(lines.getFirst499()));
lines = lines.subExtract(1, 1);
lines = lines.removeEmptyColumns();
final String code = line0.get("CODE", 0);
final Player player = diagram.getPlayer(code);
if (player == null) {
return CommandExecutionResult.error("Unkown \"" + code + "\"");
}
final Display note = lines.toDisplay();
final TimeTick now = diagram.getNow();
// final Colors colors = color().getColor(arg, diagram.getSkinParam().getIHtmlColorSet());
player.addNote(now, note, Position.fromString(line0.get("POSITION", 0)));
return CommandExecutionResult.ok();
}
private static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("[%s]*note[%s]+"), //
new RegexLeaf("POSITION", "(top|bottom)[%s]+of[%s]+"), //
new RegexLeaf("CODE", CommandTimeMessage.PLAYER_CODE), //
new RegexLeaf("[%s]*$"));
}
}

View File

@ -227,7 +227,7 @@ public class Histogram implements TimeDrawing {
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
} }
public double getHeight() { public double getHeight(StringBounder stringBounder) {
return stepHeight * allStates.size() + 10; return stepHeight * allStates.size() + 10;
} }

View File

@ -44,6 +44,7 @@ import java.util.TreeSet;
import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.command.Position;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
@ -70,6 +71,7 @@ public class Player implements TextBlock, TimeProjected {
private final Set<ChangeState> changes = new TreeSet<ChangeState>(); private final Set<ChangeState> changes = new TreeSet<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>(); private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
private final List<TimingNote> notes = new ArrayList<TimingNote>();
public Player(String code, String full, TimingStyle type, ISkinParam skinParam, TimingRuler ruler) { public Player(String code, String full, TimingStyle type, ISkinParam skinParam, TimingRuler ruler) {
this.code = code; this.code = code;
@ -139,7 +141,7 @@ public class Player implements TextBlock, TimeProjected {
private TimeDrawing computeTimeDrawing() { private TimeDrawing computeTimeDrawing() {
final TimeDrawing result; final TimeDrawing result;
if (type == TimingStyle.CONCISE) { if (type == TimingStyle.CONCISE) {
result = new Ribbon(ruler, skinParam); result = new Ribbon(ruler, skinParam, notes);
} else if (type == TimingStyle.ROBUST) { } else if (type == TimingStyle.ROBUST) {
result = new Histogram(ruler, skinParam); result = new Histogram(ruler, skinParam);
} else { } else {
@ -158,17 +160,16 @@ public class Player implements TextBlock, TimeProjected {
public Dimension2D calculateDimension(StringBounder stringBounder) { public Dimension2D calculateDimension(StringBounder stringBounder) {
final TextBlock title = getTitle(); final TextBlock title = getTitle();
final double width = ruler.getWidth(); final double width = ruler.getWidth();
final double zoneHeight = getZoneHeight(); final double zoneHeight = getZoneHeight(stringBounder);
return new Dimension2DDouble(width, title.calculateDimension(stringBounder).getHeight() * 2 + zoneHeight); return new Dimension2DDouble(width, title.calculateDimension(stringBounder).getHeight() * 2 + zoneHeight);
} }
public MinMax getMinMax(StringBounder stringBounder) { public MinMax getMinMax(StringBounder stringBounder) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
private double getZoneHeight(StringBounder stringBounder) {
private double getZoneHeight() { return getTimeDrawing().getHeight(stringBounder);
return getTimeDrawing().getHeight();
} }
public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) { public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) {
@ -201,4 +202,8 @@ public class Player implements TextBlock, TimeProjected {
this.constraints.add(new TimeConstraint(tick1, tick2, message)); this.constraints.add(new TimeConstraint(tick1, tick2, message));
} }
public void addNote(TimeTick now, Display note, Position position) {
this.notes.add(new TimingNote(now, this, note, position, skinParam));
}
} }

View File

@ -41,6 +41,7 @@ import java.util.List;
import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.command.Position;
import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration; import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.HorizontalAlignment;
@ -64,10 +65,12 @@ public class Ribbon implements TimeDrawing {
private final TimingRuler ruler; private final TimingRuler ruler;
private String initialState; private String initialState;
private Colors initialColors; private Colors initialColors;
private final List<TimingNote> notes;
public Ribbon(TimingRuler ruler, ISkinParam skinParam) { public Ribbon(TimingRuler ruler, ISkinParam skinParam, List<TimingNote> notes) {
this.ruler = ruler; this.ruler = ruler;
this.skinParam = skinParam; this.skinParam = skinParam;
this.notes = notes;
} }
public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) { public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) {
@ -93,23 +96,28 @@ public class Ribbon implements TimeDrawing {
return new FontConfiguration(skinParam, FontParam.ACTIVITY, null); return new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
} }
private TextBlock getTextBlock(String value) { private TextBlock createTextBlock(String value) {
final Display display = Display.getWithNewlines(value); final Display display = Display.getWithNewlines(value);
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam); return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
} }
public void drawU(UGraphic ug) { public void drawU(UGraphic ug) {
UGraphic ugDown = ug.apply(new UTranslate(0, getHeightForConstraints())); final StringBounder stringBounder = ug.getStringBounder();
final double halfDelta = delta / 2;
drawNotes(ug.apply(new UTranslate(0, -delta)), Position.TOP);
final TextBlock inital; final double ribbonHeight = getRibbonHeight();
final StringBounder stringBounder = ugDown.getStringBounder(); UGraphic ugDown = ug.apply(new UTranslate(0, getHeightForConstraints()
+ getHeightForNotes(stringBounder, Position.TOP)));
final TextBlock initial;
if (initialState == null) { if (initialState == null) {
inital = null; initial = null;
} else { } else {
inital = getTextBlock(initialState); initial = createTextBlock(initialState);
final double a = getPosInPixel(changes.get(0)); final double a = getPosInPixel(changes.get(0));
drawPentaA(ugDown.apply(new UTranslate(-getInitialWidth(stringBounder), -delta / 2)), drawPentaA(ugDown.apply(new UTranslate(-getInitialWidth(stringBounder), -halfDelta)),
getInitialWidth(stringBounder) + a, changes.get(0)); getInitialWidth(stringBounder) + a, changes.get(0));
} }
@ -118,28 +126,28 @@ public class Ribbon implements TimeDrawing {
final double b = getPosInPixel(changes.get(i + 1)); final double b = getPosInPixel(changes.get(i + 1));
assert b > a; assert b > a;
if (changes.get(i).isCompletelyHidden() == false) { if (changes.get(i).isCompletelyHidden() == false) {
drawHexa(ugDown.apply(new UTranslate(a, -delta / 2)), b - a, changes.get(i)); drawHexa(ugDown.apply(new UTranslate(a, -halfDelta)), b - a, changes.get(i));
} }
} }
if (changes.size() >= 1) { if (changes.size() >= 1) {
final ChangeState last = changes.get(changes.size() - 1); final ChangeState last = changes.get(changes.size() - 1);
final double a = getPosInPixel(last); final double a = getPosInPixel(last);
if (last.isCompletelyHidden() == false) { if (last.isCompletelyHidden() == false) {
drawPentaB(ugDown.apply(new UTranslate(a, -delta / 2)), ruler.getWidth() - a, last); drawPentaB(ugDown.apply(new UTranslate(a, -halfDelta)), ruler.getWidth() - a, last);
} }
} }
ugDown = ugDown.apply(new UTranslate(0, delta / 2)); ugDown = ugDown.apply(new UTranslate(0, halfDelta));
if (inital != null) { if (initial != null) {
final Dimension2D dimInital = inital.calculateDimension(stringBounder); final Dimension2D dimInital = initial.calculateDimension(stringBounder);
inital.drawU(ugDown.apply(new UTranslate(-getDelta() - dimInital.getWidth(), -dimInital.getHeight() / 2))); initial.drawU(ugDown.apply(new UTranslate(-getDelta() - dimInital.getWidth(), -dimInital.getHeight() / 2)));
} }
for (int i = 0; i < changes.size(); i++) { for (int i = 0; i < changes.size(); i++) {
final ChangeState change = changes.get(i); final ChangeState change = changes.get(i);
final double x = ruler.getPosInPixel(change.getWhen()); final double x = ruler.getPosInPixel(change.getWhen());
if (change.isBlank() == false && change.isCompletelyHidden() == false) { if (change.isBlank() == false && change.isCompletelyHidden() == false) {
final TextBlock state = getTextBlock(change.getState()); final TextBlock state = createTextBlock(change.getState());
final Dimension2D dim = state.calculateDimension(stringBounder); final Dimension2D dim = state.calculateDimension(stringBounder);
final double xtext; final double xtext;
if (i == changes.size() - 1) { if (i == changes.size() - 1) {
@ -152,29 +160,46 @@ public class Ribbon implements TimeDrawing {
} }
final String commentString = change.getComment(); final String commentString = change.getComment();
if (commentString != null) { if (commentString != null) {
final TextBlock comment = getTextBlock(commentString); final TextBlock comment = createTextBlock(commentString);
final Dimension2D dimComment = comment.calculateDimension(stringBounder); final Dimension2D dimComment = comment.calculateDimension(stringBounder);
comment.drawU(ugDown.apply(new UTranslate(x + getDelta(), -delta - dimComment.getHeight()))); comment.drawU(ugDown.apply(new UTranslate(x + getDelta(), -delta - dimComment.getHeight())));
} }
} }
for (TimeConstraint constraint : constraints) { for (TimeConstraint constraint : constraints) {
constraint.drawU(ug.apply(new UTranslate(0, 15)), ruler, skinParam); constraint.drawU(ug.apply(new UTranslate(0, getHeightForConstraints() / 2)), ruler, skinParam);
} }
drawNotes(
ug.apply(new UTranslate(0, getHeightForConstraints() + getHeightForNotes(stringBounder, Position.TOP)
+ ribbonHeight)), Position.BOTTOM);
}
private void drawNotes(UGraphic ug, final Position position) {
for (TimingNote note : notes) {
if (note.getPosition() == position) {
final double x = ruler.getPosInPixel(note.getWhen());
note.drawU(ug.apply(new UTranslate(x, 0)));
}
}
} }
private double getInitialWidth(final StringBounder stringBounder) { private double getInitialWidth(final StringBounder stringBounder) {
return getTextBlock(initialState).calculateDimension(stringBounder).getWidth() + 2 * delta; return createTextBlock(initialState).calculateDimension(stringBounder).getWidth() + getRibbonHeight();
} }
private void drawHexa(UGraphic ug, double len, ChangeState change) { private void drawHexa(UGraphic ug, double len, ChangeState change) {
final HexaShape shape = HexaShape.create(len, 2 * delta, change.getContext()); final HexaShape shape = HexaShape.create(len, getRibbonHeight(), change.getContext());
shape.drawU(ug); shape.drawU(ug);
} }
private double getRibbonHeight() {
return 2 * delta;
}
private void drawPentaB(UGraphic ug, double len, ChangeState change) { private void drawPentaB(UGraphic ug, double len, ChangeState change) {
final PentaBShape shape = PentaBShape.create(len, 2 * delta, change.getContext()); final PentaBShape shape = PentaBShape.create(len, getRibbonHeight(), change.getContext());
shape.drawU(ug); shape.drawU(ug);
} }
@ -184,7 +209,7 @@ public class Ribbon implements TimeDrawing {
if (back != null) { if (back != null) {
context = context.withBackColor(back); context = context.withBackColor(back);
} }
final PentaAShape shape = PentaAShape.create(len, 2 * delta, context); final PentaAShape shape = PentaAShape.create(len, getRibbonHeight(), context);
shape.drawU(ug); shape.drawU(ug);
} }
@ -195,8 +220,19 @@ public class Ribbon implements TimeDrawing {
return 30; return 30;
} }
public double getHeight() { public double getHeight(StringBounder stringBounder) {
return 3 * delta + getHeightForConstraints(); return 3 * delta + getHeightForConstraints() + getHeightForNotes(stringBounder, Position.TOP)
+ getHeightForNotes(stringBounder, Position.BOTTOM);
}
private double getHeightForNotes(StringBounder stringBounder, Position position) {
double height = 0;
for (TimingNote note : notes) {
if (note.getPosition() == position) {
height = Math.max(height, note.getHeight(stringBounder));
}
}
return height;
} }
public double getDelta() { public double getDelta() {
@ -205,7 +241,7 @@ public class Ribbon implements TimeDrawing {
public TextBlock getWidthHeader(StringBounder stringBounder) { public TextBlock getWidthHeader(StringBounder stringBounder) {
if (initialState != null) { if (initialState != null) {
return TextBlockUtils.empty(getInitialWidth(stringBounder), 2 * delta); return TextBlockUtils.empty(getInitialWidth(stringBounder), getRibbonHeight());
} }
return TextBlockUtils.empty(0, 0); return TextBlockUtils.empty(0, 0);
} }

View File

@ -0,0 +1,244 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.timingdiagram;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class RibbonNew implements TimeDrawing {
private final List<ChangeState> changes = new ArrayList<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
private final double delta = 12;
private final ISkinParam skinParam;
private final TimingRuler ruler;
private String initialState;
private Colors initialColors;
private final List<TimingNote> notes;
public RibbonNew(TimingRuler ruler, ISkinParam skinParam, List<TimingNote> notes) {
this.ruler = ruler;
this.skinParam = skinParam;
this.notes = notes;
}
public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) {
final double x = ruler.getPosInPixel(tick);
final double y = delta * 0.5 + getHeightForConstraints();
for (ChangeState change : changes) {
if (change.getWhen().compareTo(tick) == 0) {
return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y));
}
}
return new IntricatedPoint(new Point2D.Double(x, y - delta), new Point2D.Double(x, y + delta));
}
public void addChange(ChangeState change) {
this.changes.add(change);
}
private double getPosInPixel(ChangeState change) {
return ruler.getPosInPixel(change.getWhen());
}
private FontConfiguration getFontConfiguration() {
return new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
}
private TextBlock createTextBlock(String value) {
final Display display = Display.getWithNewlines(value);
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
}
public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
final double ribbonHeight = getRibbonHeight(stringBounder);
UGraphic ugDown = ug.apply(new UTranslate(0, getHeightForConstraints()));
final TextBlock inital;
if (initialState == null) {
inital = null;
} else {
inital = createTextBlock(initialState);
final double a = getPosInPixel(changes.get(0));
drawPentaA(ribbonHeight, ugDown.apply(new UTranslate(-getInitialWidth(stringBounder), -delta / 2)),
getInitialWidth(stringBounder) + a, changes.get(0));
}
for (int i = 0; i < changes.size() - 1; i++) {
final double a = getPosInPixel(changes.get(i));
final double b = getPosInPixel(changes.get(i + 1));
assert b > a;
if (changes.get(i).isCompletelyHidden() == false) {
drawHexa(ribbonHeight, ugDown.apply(new UTranslate(a, -delta / 2)), b - a, changes.get(i));
}
}
if (changes.size() >= 1) {
final ChangeState last = changes.get(changes.size() - 1);
final double a = getPosInPixel(last);
if (last.isCompletelyHidden() == false) {
drawPentaB(ribbonHeight, ugDown.apply(new UTranslate(a, -delta / 2)), ruler.getWidth() - a, last);
}
}
ugDown = ugDown.apply(new UTranslate(0, delta / 2));
if (inital != null) {
final Dimension2D dimInital = inital.calculateDimension(stringBounder);
inital.drawU(ugDown.apply(new UTranslate(-getDelta() - dimInital.getWidth(), -dimInital.getHeight() / 2)));
}
for (int i = 0; i < changes.size(); i++) {
final ChangeState change = changes.get(i);
final double x = ruler.getPosInPixel(change.getWhen());
if (change.isBlank() == false && change.isCompletelyHidden() == false) {
final TextBlock state = createTextBlock(change.getState());
final Dimension2D dim = state.calculateDimension(stringBounder);
final double xtext;
if (i == changes.size() - 1) {
xtext = x + getDelta();
} else {
final double x2 = ruler.getPosInPixel(changes.get(i + 1).getWhen());
xtext = (x + x2) / 2 - dim.getWidth() / 2;
}
state.drawU(ugDown.apply(new UTranslate(xtext, -dim.getHeight() / 2)));
}
final String commentString = change.getComment();
if (commentString != null) {
final TextBlock comment = createTextBlock(commentString);
final Dimension2D dimComment = comment.calculateDimension(stringBounder);
comment.drawU(ugDown.apply(new UTranslate(x + getDelta(), -delta - dimComment.getHeight())));
}
}
for (TimeConstraint constraint : constraints) {
constraint.drawU(ug.apply(new UTranslate(0, ribbonHeight / 2)), ruler, skinParam);
}
for (TimingNote note : notes) {
final double x = ruler.getPosInPixel(note.getWhen());
note.drawU(ug.apply(new UTranslate(x, ribbonHeight)));
}
}
private double getInitialWidth(final StringBounder stringBounder) {
return createTextBlock(initialState).calculateDimension(stringBounder).getWidth() + 2 * delta;
}
private void drawHexa(double ribbonHeight, UGraphic ug, double len, ChangeState change) {
final HexaShape shape = HexaShape.create(len, ribbonHeight, change.getContext());
shape.drawU(ug);
}
private void drawPentaB(double ribbonHeight, UGraphic ug, double len, ChangeState change) {
final PentaBShape shape = PentaBShape.create(len, ribbonHeight, change.getContext());
shape.drawU(ug);
}
private void drawPentaA(double ribbonHeight, UGraphic ug, double len, ChangeState change) {
SymbolContext context = change.getContext();
final HtmlColor back = initialColors.getColor(ColorType.BACK);
if (back != null) {
context = context.withBackColor(back);
}
final PentaAShape shape = PentaAShape.create(len, ribbonHeight, context);
shape.drawU(ug);
}
private double getHeightForConstraints() {
if (constraints.size() == 0) {
return 0;
}
return 30;
}
public double getHeight(StringBounder stringBounder) {
return getHeightForConstraints() + getRibbonHeight(stringBounder) + getHeightForNotes(stringBounder);
}
private double getRibbonHeight(StringBounder stringBounder) {
double height = 24;
return height;
}
private double getHeightForNotes(StringBounder stringBounder) {
double height = 0;
for (TimingNote note : notes) {
height = Math.max(height, note.getHeight(stringBounder));
}
return height;
}
public double getDelta() {
return delta;
}
public TextBlock getWidthHeader(StringBounder stringBounder) {
if (initialState != null) {
return TextBlockUtils.empty(getInitialWidth(stringBounder), getRibbonHeight(stringBounder));
}
return TextBlockUtils.empty(0, 0);
}
public void setInitialState(String initialState, Colors initialColors) {
this.initialState = initialState;
this.initialColors = initialColors;
}
public void addConstraint(TimeConstraint constraint) {
this.constraints.add(constraint);
}
}

View File

@ -0,0 +1,226 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.timingdiagram;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.SymbolContext;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.graphic.color.ColorType;
import net.sourceforge.plantuml.graphic.color.Colors;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class RibbonOld implements TimeDrawing {
private final List<ChangeState> changes = new ArrayList<ChangeState>();
private final List<TimeConstraint> constraints = new ArrayList<TimeConstraint>();
private final double delta = 12;
private final ISkinParam skinParam;
private final TimingRuler ruler;
private String initialState;
private Colors initialColors;
public RibbonOld(TimingRuler ruler, ISkinParam skinParam) {
this.ruler = ruler;
this.skinParam = skinParam;
}
public IntricatedPoint getTimeProjection(StringBounder stringBounder, TimeTick tick) {
final double x = ruler.getPosInPixel(tick);
final double y = delta * 0.5 + getHeightForConstraints();
for (ChangeState change : changes) {
if (change.getWhen().compareTo(tick) == 0) {
return new IntricatedPoint(new Point2D.Double(x, y), new Point2D.Double(x, y));
}
}
return new IntricatedPoint(new Point2D.Double(x, y - delta), new Point2D.Double(x, y + delta));
}
public void addChange(ChangeState change) {
this.changes.add(change);
}
private double getPosInPixel(ChangeState change) {
return ruler.getPosInPixel(change.getWhen());
}
private FontConfiguration getFontConfiguration() {
return new FontConfiguration(skinParam, FontParam.ACTIVITY, null);
}
private TextBlock getTextBlock(String value) {
final Display display = Display.getWithNewlines(value);
return display.create(getFontConfiguration(), HorizontalAlignment.LEFT, skinParam);
}
public void drawU(UGraphic ug) {
UGraphic ugDown = ug.apply(new UTranslate(0, getHeightForConstraints()));
final TextBlock inital;
final StringBounder stringBounder = ugDown.getStringBounder();
if (initialState == null) {
inital = null;
} else {
inital = getTextBlock(initialState);
final double a = getPosInPixel(changes.get(0));
drawPentaA(ugDown.apply(new UTranslate(-getInitialWidth(stringBounder), -delta / 2)),
getInitialWidth(stringBounder) + a, changes.get(0));
}
for (int i = 0; i < changes.size() - 1; i++) {
final double a = getPosInPixel(changes.get(i));
final double b = getPosInPixel(changes.get(i + 1));
assert b > a;
if (changes.get(i).isCompletelyHidden() == false) {
drawHexa(ugDown.apply(new UTranslate(a, -delta / 2)), b - a, changes.get(i));
}
}
if (changes.size() >= 1) {
final ChangeState last = changes.get(changes.size() - 1);
final double a = getPosInPixel(last);
if (last.isCompletelyHidden() == false) {
drawPentaB(ugDown.apply(new UTranslate(a, -delta / 2)), ruler.getWidth() - a, last);
}
}
ugDown = ugDown.apply(new UTranslate(0, delta / 2));
if (inital != null) {
final Dimension2D dimInital = inital.calculateDimension(stringBounder);
inital.drawU(ugDown.apply(new UTranslate(-getDelta() - dimInital.getWidth(), -dimInital.getHeight() / 2)));
}
for (int i = 0; i < changes.size(); i++) {
final ChangeState change = changes.get(i);
final double x = ruler.getPosInPixel(change.getWhen());
if (change.isBlank() == false && change.isCompletelyHidden() == false) {
final TextBlock state = getTextBlock(change.getState());
final Dimension2D dim = state.calculateDimension(stringBounder);
final double xtext;
if (i == changes.size() - 1) {
xtext = x + getDelta();
} else {
final double x2 = ruler.getPosInPixel(changes.get(i + 1).getWhen());
xtext = (x + x2) / 2 - dim.getWidth() / 2;
}
state.drawU(ugDown.apply(new UTranslate(xtext, -dim.getHeight() / 2)));
}
final String commentString = change.getComment();
if (commentString != null) {
final TextBlock comment = getTextBlock(commentString);
final Dimension2D dimComment = comment.calculateDimension(stringBounder);
comment.drawU(ugDown.apply(new UTranslate(x + getDelta(), -delta - dimComment.getHeight())));
}
}
for (TimeConstraint constraint : constraints) {
constraint.drawU(ug.apply(new UTranslate(0, 15)), ruler, skinParam);
}
}
private double getInitialWidth(final StringBounder stringBounder) {
return getTextBlock(initialState).calculateDimension(stringBounder).getWidth() + getRibonHeight();
}
private void drawHexa(UGraphic ug, double len, ChangeState change) {
final HexaShape shape = HexaShape.create(len, getRibonHeight(), change.getContext());
shape.drawU(ug);
}
private double getRibonHeight() {
return 2 * delta;
}
private void drawPentaB(UGraphic ug, double len, ChangeState change) {
final PentaBShape shape = PentaBShape.create(len, getRibonHeight(), change.getContext());
shape.drawU(ug);
}
private void drawPentaA(UGraphic ug, double len, ChangeState change) {
SymbolContext context = change.getContext();
final HtmlColor back = initialColors.getColor(ColorType.BACK);
if (back != null) {
context = context.withBackColor(back);
}
final PentaAShape shape = PentaAShape.create(len, getRibonHeight(), context);
shape.drawU(ug);
}
private double getHeightForConstraints() {
if (constraints.size() == 0) {
return 0;
}
return 30;
}
public double getHeight(StringBounder stringBounder) {
return 3 * delta + getHeightForConstraints();
}
public double getDelta() {
return delta;
}
public TextBlock getWidthHeader(StringBounder stringBounder) {
if (initialState != null) {
return TextBlockUtils.empty(getInitialWidth(stringBounder), getRibonHeight());
}
return TextBlockUtils.empty(0, 0);
}
public void setInitialState(String initialState, Colors initialColors) {
this.initialState = initialState;
this.initialColors = initialColors;
}
public void addConstraint(TimeConstraint constraint) {
this.constraints.add(constraint);
}
}

View File

@ -41,7 +41,7 @@ import net.sourceforge.plantuml.graphic.color.Colors;
public interface TimeDrawing extends TimeProjected, UDrawable { public interface TimeDrawing extends TimeProjected, UDrawable {
public double getHeight(); public double getHeight(StringBounder stringBounder);
public void addChange(ChangeState change); public void addChange(ChangeState change);

View File

@ -61,6 +61,8 @@ public class TimingDiagramFactory extends UmlDiagramFactory {
cmds.add(new CommandAtTime()); cmds.add(new CommandAtTime());
cmds.add(new CommandAtPlayer()); cmds.add(new CommandAtPlayer());
cmds.add(new CommandTimeMessage()); cmds.add(new CommandTimeMessage());
cmds.add(new CommandNote());
cmds.add(new CommandNoteLong());
cmds.add(new CommandConstraint()); cmds.add(new CommandConstraint());
cmds.add(new CommandScalePixel()); cmds.add(new CommandScalePixel());

View File

@ -0,0 +1,103 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2017, 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.timingdiagram;
import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineBreakStrategy;
import net.sourceforge.plantuml.command.Position;
import net.sourceforge.plantuml.creole.CreoleMode;
import net.sourceforge.plantuml.creole.CreoleParser;
import net.sourceforge.plantuml.creole.Sheet;
import net.sourceforge.plantuml.creole.SheetBlock1;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.skin.rose.Rose;
import net.sourceforge.plantuml.svek.image.Opale;
import net.sourceforge.plantuml.ugraphic.UGraphic;
public class TimingNote {
private final TimeTick when;
private final Player player;
private final Display note;
private final Position position;
private final ISkinParam skinParam;
public TimingNote(TimeTick when, Player player, Display note, Position position, ISkinParam skinParam) {
this.note = note;
this.player = player;
this.when = when;
this.skinParam = skinParam;
this.position = position;
}
public void drawU(UGraphic ug) {
final Opale opale = createOpale();
opale.drawU(ug);
}
private Opale createOpale() {
final FontConfiguration fc = new FontConfiguration(skinParam, FontParam.NOTE, null);
final Rose rose = new Rose();
final HtmlColor noteBackgroundColor = rose.getHtmlColor(skinParam, ColorParam.noteBackground);
final HtmlColor borderColor = rose.getHtmlColor(skinParam, ColorParam.noteBorder);
final Sheet sheet = new CreoleParser(fc, skinParam.getDefaultTextAlignment(HorizontalAlignment.LEFT),
skinParam, CreoleMode.FULL).createSheet(note);
final SheetBlock1 sheet1 = new SheetBlock1(sheet, LineBreakStrategy.NONE, skinParam.getPadding());
final Opale opale = new Opale(borderColor, noteBackgroundColor, sheet1, skinParam.shadowing(), false);
return opale;
}
public double getHeight(StringBounder stringBounder) {
return createOpale().calculateDimension(stringBounder).getHeight();
}
public TimeTick getWhen() {
return when;
}
public final Position getPosition() {
return position;
}
}

View File

@ -57,7 +57,7 @@ public class SpriteMonochrome implements Sprite {
private final int grayLevel; private final int grayLevel;
private final int pixels[][]; private final int pixels[][];
SpriteMonochrome(int width, int height, int grayLevel) { public SpriteMonochrome(int width, int height, int grayLevel) {
if (grayLevel != 2 && grayLevel != 4 && grayLevel != 8 && grayLevel != 16) { if (grayLevel != 2 && grayLevel != 4 && grayLevel != 8 && grayLevel != 16) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@ -67,7 +67,41 @@ public class SpriteMonochrome implements Sprite {
this.pixels = new int[height][width]; this.pixels = new int[height][width];
} }
void setPixel(int x, int y, int level) { public SpriteMonochrome xSymetric() {
final SpriteMonochrome result = new SpriteMonochrome(width, height, grayLevel);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
result.setPixel(i, j, this.getPixel(i, j));
}
}
for (int j = 0; j < height; j++) {
for (int i = 0; i < width / 2; i++) {
final int i2 = width - 1 - i;
final int level = result.getPixel(i, j) ^ result.getPixel(i2, j);
result.setPixel(i2, j, level);
}
}
return result;
}
public SpriteMonochrome ySymetric() {
final SpriteMonochrome result = new SpriteMonochrome(width, height, grayLevel);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
result.setPixel(i, j, this.getPixel(i, j));
}
}
for (int i = 0; i < width; i++) {
for (int j = 0; j < height / 2; j++) {
final int j2 = height - 1 - j;
final int level = result.getPixel(i, j) ^ result.getPixel(i, j2);
result.setPixel(i, j2, level);
}
}
return result;
}
public void setPixel(int x, int y, int level) {
if (x < 0 || x >= width) { if (x < 0 || x >= width) {
return; return;
} }
@ -80,11 +114,21 @@ public class SpriteMonochrome implements Sprite {
pixels[y][x] = level; pixels[y][x] = level;
} }
public int getPixel(int x, int y) {
if (x >= width) {
throw new IllegalArgumentException("x=" + x + " width=" + width);
}
if (y >= height) {
throw new IllegalArgumentException("y=" + y + " height=" + height);
}
return pixels[y][x];
}
public int getHeight() { public int getHeight() {
return height; return height;
} }
int getWidth() { public int getWidth() {
return width; return width;
} }

View File

@ -63,7 +63,7 @@ import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
import net.sourceforge.plantuml.graphic.GraphicPosition; import net.sourceforge.plantuml.graphic.GraphicPosition;
import net.sourceforge.plantuml.graphic.GraphicStrings; import net.sourceforge.plantuml.graphic.GraphicStrings;
import net.sourceforge.plantuml.preproc.PreprocessorInclude; import net.sourceforge.plantuml.preproc.PreprocessorInclude;
import net.sourceforge.plantuml.preproc.Stdlib; import net.sourceforge.plantuml.preproc.StdlibOld;
import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity; import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.ImageBuilder;
@ -174,7 +174,7 @@ public class PSystemVersion extends AbstractPSystem {
} }
strings.add(" "); strings.add(" ");
strings.add("<b>Stdlib:"); strings.add("<b>Stdlib:");
Stdlib.addInfoVersion(strings); StdlibOld.addInfoVersion(strings);
strings.add(" "); strings.add(" ");
strings.addAll(GraphvizUtils.getTestDotStrings(true)); strings.addAll(GraphvizUtils.getTestDotStrings(true));

View File

@ -43,7 +43,7 @@ public class Version {
private static final int MAJOR_SEPARATOR = 1000000; private static final int MAJOR_SEPARATOR = 1000000;
public static int version() { public static int version() {
return 1201720; return 1201800;
} }
public static int versionPatched() { public static int versionPatched() {
@ -88,7 +88,7 @@ public class Version {
} }
public static long compileTime() { public static long compileTime() {
return 1513011425649L; return 1515094976440L;
} }
public static String compileTimeString() { public static String compileTimeString() {