1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-12-25 20:11:18 +00:00

version 1.2018.3

This commit is contained in:
Arnaud Roques 2018-04-06 22:36:30 +02:00
parent 86c9c6d603
commit e3bdf19745
84 changed files with 3641 additions and 1159 deletions

View File

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

View File

@ -139,6 +139,8 @@ public enum ColorParam {
nodeBorder(HtmlColorUtils.BLACK, ColorType.LINE),
rectangleBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
rectangleBorder(HtmlColorUtils.BLACK, ColorType.LINE),
cardBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
cardBorder(HtmlColorUtils.BLACK, ColorType.LINE),
agentBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
agentBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
storageBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),

View File

@ -35,14 +35,21 @@
*/
package net.sourceforge.plantuml;
public enum RoundParam {
public enum CornerParam {
DEFAULT, diagramBorder, titleBorder, rectangle, component;
public String getKey() {
public String getRoundKey() {
if (this == DEFAULT) {
return "roundcorner";
}
return name() + "roundcorner";
}
public String getDiagonalKey() {
if (this == DEFAULT) {
return "diagonalcorner";
}
return name() + "diagonalcorner";
}
}

View File

@ -45,6 +45,9 @@ public class Dimension2DDouble extends Dimension2D {
final private double height;
public Dimension2DDouble(double width, double height) {
if (Double.isNaN(width) || Double.isNaN(height)) {
throw new IllegalArgumentException();
}
this.width = width;
this.height = height;
}

View File

@ -76,6 +76,7 @@ public enum FontParam {
ENTITY(14, Font.PLAIN), //
AGENT(14, Font.PLAIN), //
RECTANGLE(14, Font.PLAIN), //
CARD(14, Font.PLAIN), //
NODE(14, Font.PLAIN), //
DATABASE(14, Font.PLAIN), //
QUEUE(14, Font.PLAIN), //
@ -107,6 +108,7 @@ public enum FontParam {
ENTITY_STEREOTYPE(14, Font.ITALIC), //
AGENT_STEREOTYPE(14, Font.ITALIC), //
RECTANGLE_STEREOTYPE(14, Font.ITALIC), //
CARD_STEREOTYPE(14, Font.ITALIC), //
NODE_STEREOTYPE(14, Font.ITALIC), //
FOLDER_STEREOTYPE(14, Font.ITALIC), //
FILE_STEREOTYPE(14, Font.ITALIC), //

View File

@ -101,7 +101,9 @@ public interface ISkinParam extends ISkinSimple {
public double getRanksep();
public double getRoundCorner(RoundParam param, Stereotype stereotype);
public double getRoundCorner(CornerParam param, Stereotype stereotype);
public double getDiagonalCorner(CornerParam param, Stereotype stereotype);
public LineBreakStrategy maxMessageSize();

View File

@ -49,8 +49,10 @@ import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3;
import net.sourceforge.plantuml.core.Diagram;
import net.sourceforge.plantuml.core.ImageData;
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.html.CucaDiagramHtmlMaker;
import net.sourceforge.plantuml.png.PngSplitter;
import net.sourceforge.plantuml.project3.GanttDiagram;
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
public class PSystemUtils {
@ -66,6 +68,9 @@ public class PSystemUtils {
if (system instanceof CucaDiagram) {
return exportDiagramsCuca((CucaDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof GanttDiagram) {
return exportDiagramsGantt2((GanttDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof ActivityDiagram3) {
return exportDiagramsActivityDiagram3((ActivityDiagram3) system, suggestedFile, fileFormatOption);
}
@ -230,6 +235,62 @@ public class PSystemUtils {
}
// static private List<FileImageData> exportDiagramsGantt1(GanttDiagram system, SuggestedFile suggestedFile,
// FileFormatOption fileFormat) throws IOException {
// if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
// throw new IllegalArgumentException("File is a directory " + suggestedFile);
// }
// OutputStream os = null;
// ImageData imageData = null;
// try {
// if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
// return Collections.emptyList();
// }
// os = new BufferedOutputStream(new FileOutputStream(suggestedFile.getFile(0)));
// imageData = system.exportDiagram(os, 0, fileFormat);
// } finally {
// if (os != null) {
// os.close();
// }
// }
// return Arrays.asList(new FileImageData(suggestedFile.getFile(0), imageData));
// }
static private List<FileImageData> exportDiagramsGantt2(GanttDiagram system, SuggestedFile suggestedFile,
FileFormatOption fileFormat) throws IOException {
if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
throw new IllegalArgumentException("File is a directory " + suggestedFile);
}
ImageData cmap = null;
OutputStream os = null;
try {
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
return Collections.emptyList();
}
os = new NamedOutputStream(suggestedFile.getFile(0));
cmap = system.exportDiagram(os, 0, fileFormat);
} finally {
if (os != null) {
os.close();
}
}
List<File> result = Arrays.asList(suggestedFile.getFile(0));
if (fileFormat.getFileFormat() == FileFormat.PNG) {
final SplitParam splitParam = new SplitParam(HtmlColorUtils.BLACK, null, 5);
result = new PngSplitter(suggestedFile, system.getHorizontalPages(), system.getVerticalPages(),
system.getMetadata(), system.getDpi(fileFormat), fileFormat.isWithMetadata(), splitParam)
.getFiles();
}
final List<FileImageData> result2 = new ArrayList<FileImageData>();
for (File f : result) {
result2.add(new FileImageData(f, cmap));
}
return result2;
}
private static List<FileImageData> createFilesHtml(CucaDiagram system, SuggestedFile suggestedFile)
throws IOException {
final String name = suggestedFile.getName();

View File

@ -653,23 +653,39 @@ public class SkinParam implements ISkinParam {
return 0;
}
public double getRoundCorner(RoundParam param, Stereotype stereotype) {
Double result = getRoundCornerInternal(param, stereotype);
public double getDiagonalCorner(CornerParam param, Stereotype stereotype) {
final String key = param.getDiagonalKey();
Double result = getCornerInternal(key, param, stereotype);
if (result != null) {
return result;
}
result = getRoundCornerInternal(param, null);
result = getCornerInternal(key, param, null);
if (result != null) {
return result;
}
if (param == RoundParam.DEFAULT) {
if (param == CornerParam.DEFAULT) {
return 0;
}
return getRoundCorner(RoundParam.DEFAULT, stereotype);
return getDiagonalCorner(CornerParam.DEFAULT, stereotype);
}
private Double getRoundCornerInternal(RoundParam param, Stereotype stereotype) {
String key = param.getKey();
public double getRoundCorner(CornerParam param, Stereotype stereotype) {
final String key = param.getRoundKey();
Double result = getCornerInternal(key, param, stereotype);
if (result != null) {
return result;
}
result = getCornerInternal(key, param, null);
if (result != null) {
return result;
}
if (param == CornerParam.DEFAULT) {
return 0;
}
return getRoundCorner(CornerParam.DEFAULT, stereotype);
}
private Double getCornerInternal(String key, CornerParam param, Stereotype stereotype) {
if (stereotype != null) {
key += stereotype.getLabel(false);
}

View File

@ -147,10 +147,14 @@ public class SkinParamDelegator implements ISkinParam {
return skinParam.getRanksep();
}
public double getRoundCorner(RoundParam param, Stereotype stereotype) {
public double getRoundCorner(CornerParam param, Stereotype stereotype) {
return skinParam.getRoundCorner(param, stereotype);
}
public double getDiagonalCorner(CornerParam param, Stereotype stereotype) {
return skinParam.getDiagonalCorner(param, stereotype);
}
public UStroke getThickness(LineParam param, Stereotype stereotype) {
return skinParam.getThickness(param, stereotype);
}

View File

@ -0,0 +1,162 @@
/* ========================================================================
* 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;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import net.sourceforge.plantuml.preproc.Defines;
public class ZSourceFileReader extends ZSourceFileReaderAbstract implements ISourceFileReader {
public ZSourceFileReader(File file) throws IOException {
this(file, file.getAbsoluteFile().getParentFile());
}
public ZSourceFileReader(File file, File outputDirectory, String charset) throws IOException {
this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), charset,
new FileFormatOption(FileFormat.PNG));
}
public ZSourceFileReader(final File file, File outputDirectory) throws IOException {
this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), null,
new FileFormatOption(FileFormat.PNG));
}
public ZSourceFileReader(final File file, File outputDirectory, FileFormatOption fileFormatOption)
throws IOException {
this(Defines.createWithFileName(file), file, outputDirectory, Collections.<String> emptyList(), null,
fileFormatOption);
}
public ZSourceFileReader(Defines defines, final File file, File outputDirectory, List<String> config,
String charset, FileFormatOption fileFormatOption) throws IOException {
this.file = file;
this.fileFormatOption = fileFormatOption;
if (file.exists() == false) {
throw new IllegalArgumentException();
}
FileSystem.getInstance().setCurrentDir(file.getAbsoluteFile().getParentFile());
if (outputDirectory == null) {
outputDirectory = file.getAbsoluteFile().getParentFile();
} else if (outputDirectory.isAbsolute() == false) {
outputDirectory = FileSystem.getInstance().getFile(outputDirectory.getPath());
}
if (outputDirectory.exists() == false) {
outputDirectory.mkdirs();
}
this.outputDirectory = outputDirectory;
builder = new BlockUmlBuilder(config, charset, defines, getReader(charset), file.getAbsoluteFile()
.getParentFile(), file.getAbsolutePath());
}
private File getDirIfDirectory(String newName) {
Log.info("Checking=" + newName);
if (endsWithSlashOrAntislash(newName)) {
Log.info("It ends with / so it looks like a directory");
newName = newName.substring(0, newName.length() - 1);
File f = new File(newName);
Log.info("f=" + f);
if (f.isAbsolute() == false) {
Log.info("It's relative, so let's change it");
f = new File(outputDirectory, newName);
Log.info("f=" + f);
}
if (f.exists() == false) {
Log.info("It does not exist: let's create it");
try {
f.mkdirs();
} catch (Exception e) {
Log.info("Error " + e);
}
if (f.exists() && f.isDirectory()) {
Log.info("Creation ok");
return f;
}
Log.info("We cannot create it");
} else if (f.isDirectory() == false) {
Log.info("It exists, but is not a directory: we ignore it");
return null;
}
return f;
}
File f = new File(newName);
Log.info("f=" + f);
if (f.isAbsolute() == false) {
Log.info("Relative, so let's change it");
f = new File(outputDirectory, newName);
Log.info("f=" + f);
}
if (f.exists() && f.isDirectory()) {
Log.info("It's an existing directory");
return f;
}
Log.info("It's not a directory");
return null;
}
@Override
protected SuggestedFile getSuggestedFile(BlockUml blockUml) {
final String newName = blockUml.getFileOrDirname();
SuggestedFile suggested = null;
if (newName != null) {
Log.info("name from block=" + newName);
final File dir = getDirIfDirectory(newName);
if (dir == null) {
Log.info(newName + " is not taken as a directory");
suggested = SuggestedFile.fromOutputFile(new File(outputDirectory, newName),
fileFormatOption.getFileFormat(), 0);
} else {
Log.info("We are going to create files in directory " + dir);
suggested = SuggestedFile.fromOutputFile(new File(dir, file.getName()),
fileFormatOption.getFileFormat(), 0);
}
Log.info("We are going to put data in " + suggested);
}
if (suggested == null) {
suggested = SuggestedFile.fromOutputFile(new File(outputDirectory, file.getName()),
fileFormatOption.getFileFormat(), cpt++);
}
suggested.getParentFile().mkdirs();
return suggested;
}
}

View File

@ -0,0 +1,66 @@
/* ========================================================================
* 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;
import java.io.File;
import java.io.IOException;
import java.util.List;
import net.sourceforge.plantuml.preproc.Defines;
public class ZSourceFileReader2 extends ZSourceFileReaderAbstract implements ISourceFileReader {
public ZSourceFileReader2(Defines defines, final File file, File outputFile, List<String> config, String charset,
FileFormatOption fileFormatOption) throws IOException {
this.file = file;
this.fileFormatOption = fileFormatOption;
this.outputFile = outputFile;
if (file.exists() == false) {
throw new IllegalArgumentException();
}
FileSystem.getInstance().setCurrentDir(file.getAbsoluteFile().getParentFile());
builder = new BlockUmlBuilder(config, charset, defines, getReader(charset), file.getAbsoluteFile()
.getParentFile(), file.getAbsolutePath());
}
@Override
protected SuggestedFile getSuggestedFile(BlockUml blockUml) {
final SuggestedFile suggested = SuggestedFile.fromOutputFile(outputFile, fileFormatOption.getFileFormat());
return suggested;
}
}

View File

@ -0,0 +1,170 @@
/* ========================================================================
* 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;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import net.sourceforge.plantuml.core.Diagram;
import net.sourceforge.plantuml.preproc.FileWithSuffix;
public abstract class ZSourceFileReaderAbstract {
protected File file;
protected File outputDirectory;
protected File outputFile;
protected BlockUmlBuilder builder;
protected FileFormatOption fileFormatOption;
public boolean hasError() {
for (final BlockUml b : builder.getBlockUmls()) {
if (b.getDiagram() instanceof PSystemError) {
return true;
}
}
return false;
}
public List<BlockUml> getBlocks() {
return builder.getBlockUmls();
}
protected Reader getReader(String charset) throws FileNotFoundException, UnsupportedEncodingException {
if (charset == null) {
Log.info("Using default charset");
return new InputStreamReader(new FileInputStream(file));
}
Log.info("Using charset " + charset);
return new InputStreamReader(new FileInputStream(file), charset);
}
public final Set<FileWithSuffix> getIncludedFiles() {
return builder.getIncludedFiles();
}
public final void setFileFormatOption(FileFormatOption fileFormatOption) {
this.fileFormatOption = fileFormatOption;
}
protected boolean endsWithSlashOrAntislash(String newName) {
return newName.endsWith("/") || newName.endsWith("\\");
}
protected List<GeneratedImage> getCrashedImage(BlockUml blockUml, Throwable t, File outputFile) throws IOException {
final GeneratedImage image = new GeneratedImageImpl(outputFile, "Crash Error", blockUml);
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(outputFile));
UmlDiagram.exportDiagramError(os, t, fileFormatOption, 42, null, blockUml.getFlashData(),
UmlDiagram.getFailureText2(t, blockUml.getFlashData()));
} finally {
if (os != null) {
os.close();
}
}
return Collections.singletonList(image);
}
protected void exportWarnOrErrIfWord(final File f, final Diagram system) throws FileNotFoundException {
if (OptionFlags.getInstance().isWord()) {
final String warnOrError = system.getWarningOrError();
if (warnOrError != null) {
final String name = f.getName().substring(0, f.getName().length() - 4) + ".err";
final File errorFile = new File(f.getParentFile(), name);
final PrintStream ps = new PrintStream(new FileOutputStream(errorFile));
ps.print(warnOrError);
ps.close();
}
}
}
protected int cpt;
final public List<GeneratedImage> getGeneratedImages() throws IOException {
Log.info("Reading file: " + file);
cpt = 0;
final List<GeneratedImage> result = new ArrayList<GeneratedImage>();
for (BlockUml blockUml : builder.getBlockUmls()) {
SuggestedFile suggested = getSuggestedFile(blockUml);
final Diagram system;
try {
system = blockUml.getDiagram();
} catch (Throwable t) {
return getCrashedImage(blockUml, t, suggested.getFile(0));
}
OptionFlags.getInstance().logData(file, system);
final List<FileImageData> exportDiagrams = PSystemUtils.exportDiagrams(system, suggested, fileFormatOption);
if (exportDiagrams.size() > 1) {
cpt += exportDiagrams.size() - 1;
}
for (FileImageData fdata : exportDiagrams) {
final String desc = "[" + file.getName() + "] " + system.getDescription();
final File f = fdata.getFile();
exportWarnOrErrIfWord(f, system);
final GeneratedImage generatedImage = new GeneratedImageImpl(f, desc, blockUml);
result.add(generatedImage);
}
}
Log.info("Number of image(s): " + result.size());
return Collections.unmodifiableList(result);
}
abstract protected SuggestedFile getSuggestedFile(BlockUml blockUml);
}

View File

@ -71,6 +71,14 @@ public class Bodier {
this.manageModifier = type == null ? false : type.manageModifier();
}
public void setLeaf(ILeaf leaf) {
if (leaf == null) {
throw new IllegalArgumentException();
}
this.leaf = leaf;
}
public void addFieldOrMethod(String s, IEntity leaf) {
if (leaf == null) {
throw new IllegalArgumentException();
@ -196,6 +204,9 @@ public class Bodier {
}
return null;
}
if (leaf == null) {
throw new IllegalStateException();
}
final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam,
stereotype, leaf);
if (type == LeafType.OBJECT) {

View File

@ -77,6 +77,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
private final List<Url> urls = new ArrayList<Url>();
private final Stereotype stereotype;
private final ILeaf entity;
private final boolean inEllipse;
public BodyEnhanced(List<String> rawBody, FontParam fontParam, ISkinParam skinParam, boolean manageModifier,
Stereotype stereotype, ILeaf entity) {
@ -91,6 +92,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
this.manageHorizontalLine = true;
this.manageModifier = manageModifier;
this.entity = entity;
this.inEllipse = false;
}
public BodyEnhanced(Display display, FontParam fontParam, ISkinParam skinParam, HorizontalAlignment align,
@ -98,9 +100,6 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
this.entity = entity;
this.stereotype = stereotype;
this.rawBody = new ArrayList<String>();
for (CharSequence s : display) {
this.rawBody.add(s.toString());
}
this.fontParam = fontParam;
this.skinParam = skinParam;
@ -109,6 +108,14 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
this.align = skinParam.getDefaultTextAlignment(align);
this.manageHorizontalLine = manageHorizontalLine;
this.manageModifier = manageModifier;
this.inEllipse = fontParam == FontParam.USECASE;
if (manageHorizontalLine && inEllipse && display.size() > 0 && isBlockSeparator(display.get(0).toString())) {
this.rawBody.add("");
}
for (CharSequence s : display) {
this.rawBody.add(s.toString());
}
}
@ -166,6 +173,9 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
}
}
}
if (inEllipse && members.size() == 0) {
members.add(new MemberImpl("", false, false));
}
blocks.add(decorate(stringBounder, new MethodsOrFieldsArea(members, fontParam, skinParam, align, stereotype,
entity), separator, title));

View File

@ -289,6 +289,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
this.horizontalPages = horizontalPages;
}
final public int getVerticalPages() {
return verticalPages;
}
@ -296,6 +297,13 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
final public void setVerticalPages(int verticalPages) {
this.verticalPages = verticalPages;
}
@Override
public int getNbImages() {
return this.horizontalPages * this.verticalPages;
}
// final public List<File> createPng2(File pngFile) throws IOException,
// InterruptedException {
@ -569,11 +577,6 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
}
}
@Override
public int getNbImages() {
return this.horizontalPages * this.verticalPages;
}
public final Set<VisibilityModifier> getHides() {
return Collections.unmodifiableSet(hides);
}

View File

@ -160,9 +160,10 @@ public class Link implements Hideable, Removeable {
// }
final Link result = new Link(cl2, cl1, getType().getInversed(), label, length, qualifier2, qualifier1,
labeldistance, labelangle, specificColor);
result.inverted = true;
result.inverted = !this.inverted;
result.port1 = this.port2;
result.port2 = this.port1;
result.url = this.url;
return result;
}

View File

@ -99,6 +99,7 @@ public class EntityFactory {
final LongCode longCode = getLongCode(code, namespaceSeparator);
final EntityImpl result = new EntityImpl(this, code, bodier, parentContainer, entityType, longCode,
namespaceSeparator, rawLayout);
bodier.setLeaf(result);
result.setDisplay(display);
return result;
}

View File

@ -40,13 +40,12 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.math.BigInteger;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import net.sourceforge.plantuml.webp.VP8Decoder;
public class Dedication {
private final String name;
@ -73,13 +72,21 @@ public class Dedication {
public BufferedImage getBufferedImage(String keepLetter) {
try {
final Class<?> clVP8Decoder = Class.forName("net.sourceforge.plantuml.webp.VP8Decoder");
final Object vp8Decoder = clVP8Decoder.newInstance();
// final VP8Decoder vp8Decoder = new VP8Decoder();
final Method decodeFrame = clVP8Decoder.getMethod("decodeFrame", ImageInputStream.class);
final InputStream is = getInputStream(keepLetter);
final ImageInputStream iis = ImageIO.createImageInputStream(is);
final VP8Decoder vp8Decoder = new VP8Decoder();
vp8Decoder.decodeFrame(iis, false);
decodeFrame.invoke(vp8Decoder, iis);
// vp8Decoder.decodeFrame(iis);
iis.close();
return vp8Decoder.getFrame().getBufferedImage();
final Object frame = clVP8Decoder.getMethod("getFrame").invoke(vp8Decoder);
return (BufferedImage) frame.getClass().getMethod("getBufferedImage").invoke(frame);
// final VP8Frame frame = vp8Decoder.getFrame();
// return frame.getBufferedImage();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

View File

@ -52,6 +52,7 @@ import net.sourceforge.plantuml.cucadiagram.IEntity;
import net.sourceforge.plantuml.cucadiagram.ILeaf;
import net.sourceforge.plantuml.cucadiagram.LeafType;
import net.sourceforge.plantuml.cucadiagram.Link;
import net.sourceforge.plantuml.cucadiagram.LinkArrow;
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
import net.sourceforge.plantuml.cucadiagram.LinkType;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
@ -209,6 +210,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
private String firstLabel;
private String secondLabel;
private String labelLink;
private LinkArrow linkArrow = LinkArrow.NONE;
Labels(RegexResult arg) {
firstLabel = arg.get("LABEL1", 0);
@ -220,6 +222,27 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
init();
}
labelLink = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(labelLink);
if ("<".equals(labelLink)) {
linkArrow = LinkArrow.BACKWARD;
labelLink = null;
} else if (">".equals(labelLink)) {
linkArrow = LinkArrow.DIRECT_NORMAL;
labelLink = null;
} else if (labelLink != null && labelLink.startsWith("< ")) {
linkArrow = LinkArrow.BACKWARD;
labelLink = StringUtils.trin(labelLink.substring(2));
} else if (labelLink != null && labelLink.startsWith("> ")) {
linkArrow = LinkArrow.DIRECT_NORMAL;
labelLink = StringUtils.trin(labelLink.substring(2));
} else if (labelLink != null && labelLink.endsWith(" >")) {
linkArrow = LinkArrow.DIRECT_NORMAL;
labelLink = StringUtils.trin(labelLink.substring(0, labelLink.length() - 2));
} else if (labelLink != null && labelLink.endsWith(" <")) {
linkArrow = LinkArrow.BACKWARD;
labelLink = StringUtils.trin(labelLink.substring(0, labelLink.length() - 2));
}
}
}
@ -289,7 +312,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
Link link = new Link(cl1, cl2, linkType, Display.getWithNewlines(labels.labelLink), queue.length(),
labels.firstLabel, labels.secondLabel, diagram.getLabeldistance(), diagram.getLabelangle());
link.setLinkArrow(labels.linkArrow);
if (dir == Direction.LEFT || dir == Direction.UP) {
link = link.getInv();
}

View File

@ -364,6 +364,10 @@ public class EpsGraphics {
appendColor(fillcolor);
epsRectangleInternal(x, y, width, height, rx, ry, true);
append("closepath eofill", true);
if (dashSpace != 0 && dashVisible != 0) {
append("[] 0 setdash", true);
}
}
if (color != null) {
@ -371,6 +375,9 @@ public class EpsGraphics {
appendColor(color);
epsRectangleInternal(x, y, width, height, rx, ry, false);
append("closepath stroke", true);
if (dashSpace != 0 && dashVisible != 0) {
append("[] 0 setdash", true);
}
}
}
@ -441,20 +448,26 @@ public class EpsGraphics {
}
private void roundRectangle(double x, double y, double width, double height, double rx, double ry) {
if (dashSpace != 0 && dashVisible != 0) {
append("[" + (int) dashSpace + " " + (int) dashVisible + "] 0 setdash", true);
}
append(format(width) + " " + format(height) + " " + format(x) + " " + format(y) + " " + format((rx + ry) / 2)
+ " roundrect", true);
roundrectUsed = true;
}
private void simpleRectangle(double x, double y, double width, double height, boolean fill) {
if (dashSpace != 0 && dashVisible != 0) {
append("[" + (int) dashSpace + " " + (int) dashVisible + "] 0 setdash", true);
}
if ((dashSpace == 0 && dashVisible == 0) || fill) {
append(format(width) + " " + format(height) + " " + format(x) + " " + format(y) + " simplerect", true);
simplerectUsed = true;
} else {
epsVLine(y, x, x + width);
epsVLine(y + height, x, x + width);
epsHLine(x, y, y + height);
epsHLine(x + width, y, y + height);
// } else {
// epsVLine(y, x, x + width);
// epsVLine(y + height, x, x + width);
// epsHLine(x, y, y + height);
// epsHLine(x + width, y, y + height);
}
}

View File

@ -177,7 +177,6 @@ public class QuoteUtils {
"Fbzrgvzrf jr pbzr ynfg ohg jr qvq bhe orfg",
"Vs lbh frr fbzrguvat, fnl fbzrguvat",
"Va gurbel gurer vf ab qvssrerapr orgjrra gurbel naq cenpgvpr. Ohg, va cenpgvpr, gurer vf.",
"Qnlyvtug, V zhfg jnvg sbe gur fhaevfr. V zhfg guvax bs n arj yvsr. Naq V zhfga'g tvir va.",
"Vs V pnaabg oevat lbh pbzsbeg gura ng yrnfg V oevat lbh ubcr",
"Jr nyy zhfg yrnea sebz fznyy zvfsbeghar, pbhag gur oyrffvatf gung ner erny",
"Cercner Guerr Frnyrq Rairybcrf...",
@ -254,7 +253,11 @@ public class QuoteUtils {
"Nyy lbhe onfr ner orybat gb hf", "Znqr ba Rnegu ol uhznaf", "Jvaaref Qba'g Hfr Qehtf",
"Lbh xabj jung fhecevfrq zr gur zbfg? Vg jnfa'g zrrgvat gurz. Vg jnf zrrgvat lbh.",
"Va jne gurer ner ab jvaaref, bayl jvqbjf",
"Vs lbh guvax guvf Havirefr vf onq, lbh fubhyq frr fbzr bs gur bguref");
"Vs lbh guvax guvf Havirefr vf onq, lbh fubhyq frr fbzr bs gur bguref", "Cnp-Zna'f n onq thl?",
"Zl ernyvgl vf whfg qvssrerag guna lbhef",
"Uvfgbel vf n avtugzner sebz juvpu V nz gelvat gb njnxr",
"L'ra n dh'bag rffnlr, vyf bag rh qrf ceboyrzrf",
"Gb ree vf uhzna, ohg gb ernyyl sbhy guvatf hc erdhverf n pbzchgre.");
private QuoteUtils() {
}

View File

@ -39,7 +39,7 @@ import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
import net.sourceforge.plantuml.svek.RoundedContainer;
import net.sourceforge.plantuml.ugraphic.UStroke;
@ -54,7 +54,7 @@ public class SkinParameter {
public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground,
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
RoundParam.component);
CornerParam.component);
public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground,
ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE);
@ -76,7 +76,7 @@ public class SkinParameter {
public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground,
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
RoundParam.component);
CornerParam.component);
public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground,
ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE);
@ -90,12 +90,12 @@ public class SkinParameter {
public static final SkinParameter PACKAGE = new SkinParameter("PACKAGE", ColorParam.packageBackground,
ColorParam.packageBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE);
public static final SkinParameter CARD = new SkinParameter("CARD", ColorParam.rectangleBackground,
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
public static final SkinParameter CARD = new SkinParameter("CARD", ColorParam.cardBackground,
ColorParam.cardBorder, FontParam.CARD, FontParam.CARD_STEREOTYPE);
public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground,
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder,
RoundParam.rectangle);
CornerParam.rectangle);
public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground,
ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
@ -124,10 +124,10 @@ public class SkinParameter {
private final FontParam fontParamStereotype;
private final String name;
private final LineParam lineParam;
private final RoundParam roundParam;
private final CornerParam roundParam;
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
FontParam fontParamStereotype, LineParam lineParam, RoundParam roundParam) {
FontParam fontParamStereotype, LineParam lineParam, CornerParam roundParam) {
this.name = name;
this.colorParamBack = colorParamBack;
this.colorParamBorder = colorParamBorder;
@ -139,7 +139,7 @@ public class SkinParameter {
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
FontParam fontParamStereotype) {
this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, RoundParam.DEFAULT);
this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, CornerParam.DEFAULT);
}
public String getUpperCaseName() {
@ -169,6 +169,10 @@ public class SkinParameter {
return skinParam.getRoundCorner(roundParam, stereotype);
}
public double getDiagonalCorner(ISkinParam skinParam, Stereotype stereotype) {
return skinParam.getDiagonalCorner(roundParam, stereotype);
}
public UStroke getStroke(ISkinParam skinParam, Stereotype stereotype) {
UStroke result = null;
if (lineParam != null) {

View File

@ -48,18 +48,17 @@ public class SymbolContext {
private final boolean shadowing;
private final double deltaShadow;
private final double roundCorner;
private final double diagonalCorner;
private SymbolContext(HtmlColor backColor, HtmlColor foreColor, UStroke stroke, boolean shadowing,
double deltaShadow, double roundCorner) {
double deltaShadow, double roundCorner, double diagonalCorner) {
this.backColor = backColor;
this.foreColor = foreColor;
this.stroke = stroke;
this.shadowing = shadowing;
this.deltaShadow = deltaShadow;
this.roundCorner = roundCorner;
// if (backColor instanceof HtmlColorTransparent) {
// throw new UnsupportedOperationException();
// }
this.diagonalCorner = diagonalCorner;
}
@Override
@ -85,37 +84,37 @@ public class SymbolContext {
public SymbolContext transparentBackColorToNull() {
if (backColor instanceof HtmlColorTransparent) {
return new SymbolContext(null, foreColor, stroke, shadowing, deltaShadow, roundCorner);
return new SymbolContext(null, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
return this;
}
public SymbolContext(HtmlColor backColor, HtmlColor foreColor) {
this(backColor, foreColor, new UStroke(), false, 0, 0);
this(backColor, foreColor, new UStroke(), false, 0, 0, 0);
}
public SymbolContext withShadow(boolean newShadow) {
return new SymbolContext(backColor, foreColor, stroke, newShadow, deltaShadow, roundCorner);
return new SymbolContext(backColor, foreColor, stroke, newShadow, deltaShadow, roundCorner, diagonalCorner);
}
public SymbolContext withDeltaShadow(double deltaShadow) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
public SymbolContext withStroke(UStroke newStroke) {
return new SymbolContext(backColor, foreColor, newStroke, shadowing, deltaShadow, roundCorner);
return new SymbolContext(backColor, foreColor, newStroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
public SymbolContext withBackColor(HtmlColor backColor) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
public SymbolContext withForeColor(HtmlColor foreColor) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
public SymbolContext withRoundCorner(double roundCorner) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
public SymbolContext withCorner(double roundCorner, double diagonalCorner) {
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
}
public HtmlColor getBackColor() {
@ -142,4 +141,8 @@ public class SymbolContext {
return roundCorner;
}
public double getDiagonalCorner() {
return diagonalCorner;
}
}

View File

@ -49,7 +49,7 @@ import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.posimo.Positionable;
import net.sourceforge.plantuml.posimo.PositionableImpl;
@ -82,7 +82,7 @@ public class TextBlockUtils {
if (borderColor == null) {
borderColor = HtmlColorUtils.BLACK;
}
final double corner = skinParam.getRoundCorner(RoundParam.titleBorder, null);
final double corner = skinParam.getRoundCorner(CornerParam.titleBorder, null);
return withMargin(bordered(result, stroke, borderColor, backgroundColor, corner), 2, 2);
}

View File

@ -38,8 +38,10 @@ package net.sourceforge.plantuml.graphic;
import java.awt.geom.Dimension2D;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.ugraphic.Shadowable;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
@ -64,14 +66,30 @@ class USymbolRect extends USymbol {
return skinParameter;
}
private void drawRect(UGraphic ug, double width, double height, boolean shadowing, double roundCorner) {
final URectangle shape = new URectangle(width, height, roundCorner, roundCorner);
private void drawRect(UGraphic ug, double width, double height, boolean shadowing, double roundCorner,
double diagonalCorner) {
final Shadowable shape = diagonalCorner > 0 ? getDiagonalShape(width, height, diagonalCorner) : new URectangle(
width, height, roundCorner, roundCorner);
if (shadowing) {
shape.setDeltaShadow(3.0);
}
ug.draw(shape);
}
private Shadowable getDiagonalShape(double width, double height, double diagonalCorner) {
final UPath result = new UPath();
result.moveTo(diagonalCorner, 0);
result.lineTo(width - diagonalCorner, 0);
result.lineTo(width, diagonalCorner);
result.lineTo(width, height - diagonalCorner);
result.lineTo(width - diagonalCorner, height);
result.lineTo(diagonalCorner, height);
result.lineTo(0, height - diagonalCorner);
result.lineTo(0, diagonalCorner);
result.lineTo(diagonalCorner, 0);
return result;
}
private Margin getMargin() {
return new Margin(10, 10, 10, 10);
}
@ -86,7 +104,7 @@ class USymbolRect extends USymbol {
ug = UGraphicStencil.create(ug, getRectangleStencil(dim), new UStroke());
ug = symbolContext.apply(ug);
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
symbolContext.getRoundCorner());
symbolContext.getRoundCorner(), symbolContext.getDiagonalCorner());
final Margin margin = getMargin();
final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, stereotypeAlignement);
tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1())));
@ -108,7 +126,7 @@ class USymbolRect extends USymbol {
final Dimension2D dim = calculateDimension(ug.getStringBounder());
ug = symbolContext.apply(ug);
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
symbolContext.getRoundCorner());
symbolContext.getRoundCorner(), 0);
final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder());
final double posStereoX;
final double posStereoY;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
/* ========================================================================
* 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.project3;
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 CommandGanttArrow2 extends SingleLineCommand2<GanttDiagram> {
public CommandGanttArrow2() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("TASK1", "\\[([^\\[\\]]+?)\\]"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("ARROW", "(-+)\\>"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("TASK2", "\\[([^\\[\\]]+?)\\]"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("$"));
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, RegexResult arg) {
final String name1 = arg.get("TASK1", 0);
final String name2 = arg.get("TASK2", 0);
final Task task1 = diagram.getOrCreateTask(name1, null, false);
final Task task2 = diagram.getOrCreateTask(name2, null, false);
diagram.setTaskOrder(task1, task2);
return CommandExecutionResult.ok();
}
}

View File

@ -0,0 +1,63 @@
/* ========================================================================
* 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.project3;
import java.util.List;
import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand;
public class CommandPage extends SingleLineCommand<GanttDiagram> {
public CommandPage() {
super("(?i)^page[%s]+(\\d+)[%s]*x[%s]*(\\d+)$");
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, List<String> arg) {
final int horizontal = Integer.parseInt(arg.get(0));
final int vertical = Integer.parseInt(arg.get(1));
if (horizontal <= 0 || vertical <= 0) {
return CommandExecutionResult.error("Argument must be positive");
}
diagram.setHorizontalPages(horizontal);
diagram.setVerticalPages(vertical);
return CommandExecutionResult.ok();
}
}

View File

@ -0,0 +1,65 @@
/* ========================================================================
* 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.project3;
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 CommandSeparator extends SingleLineCommand2<GanttDiagram> {
public CommandSeparator() {
super(getRegexConcat());
}
static RegexConcat getRegexConcat() {
return new RegexConcat(new RegexLeaf("^"), //
new RegexLeaf("--"), //
new RegexLeaf("[%s]*"), //
new RegexLeaf("COMMENT", "((.+?)[%s]*--)?"), //
new RegexLeaf("$"));
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, RegexResult arg) {
final String comment = arg.get("COMMENT", 1);
diagram.addSeparator(comment);
return CommandExecutionResult.ok();
}
}

View File

@ -42,7 +42,7 @@ import net.sourceforge.plantuml.command.regex.RegexResult;
public class ComplementClose implements ComplementPattern {
public IRegex toRegex(String suffix) {
return new RegexLeaf("ADAY" + suffix, "(closed?)");
return new RegexLeaf("CLOSED" + suffix, "(closed?)");
}
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {

View File

@ -0,0 +1,91 @@
/* ========================================================================
* 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.project3;
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.RegexOr;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class ComplementDates implements ComplementPattern {
public IRegex toRegex(String suffix) {
return new RegexConcat( //
new RegexLeaf("YEAR1" + suffix, "([\\d]{4})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("MONTH1" + suffix, "([\\d]{1,2})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("DAY1" + suffix, "([\\d]{1,2})"), //
new RegexLeaf("[%s]+to[%s]+"), //
new RegexLeaf("YEAR2" + suffix, "([\\d]{4})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("MONTH2" + suffix, "([\\d]{1,2})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("DAY2" + suffix, "([\\d]{1,2})") //
);
}
public Subject getSubject(GanttDiagram project, RegexResult arg) {
final DayAsDate date1 = getDate(arg, "1");
final DayAsDate date2 = getDate(arg, "2");
return new DaysAsDates(date1, date2);
}
private DayAsDate getDate(RegexResult arg, String suffix) {
final int day = Integer.parseInt(arg.get("DAY" + suffix, 0));
final int month = Integer.parseInt(arg.get("MONTH" + suffix, 0));
final int year = Integer.parseInt(arg.get("YEAR" + suffix, 0));
return DayAsDate.create(year, month, day);
}
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
final int day1 = Integer.parseInt(arg.get("DAY1" + suffix, 0));
final int month1 = Integer.parseInt(arg.get("MONTH1" + suffix, 0));
final int year1 = Integer.parseInt(arg.get("YEAR1" + suffix, 0));
final DayAsDate date1 = DayAsDate.create(year1, month1, day1);
final int day2 = Integer.parseInt(arg.get("DAY2" + suffix, 0));
final int month2 = Integer.parseInt(arg.get("MONTH2" + suffix, 0));
final int year2 = Integer.parseInt(arg.get("YEAR2" + suffix, 0));
final DayAsDate date2 = DayAsDate.create(year2, month2, day2);
return Failable.<Complement> ok(new DaysAsDates(date1, date2));
}
}

View File

@ -36,17 +36,24 @@
package net.sourceforge.plantuml.project3;
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;
public class ComplementSeveralDays implements ComplementPattern {
public IRegex toRegex(String suffix) {
return new RegexLeaf("COMPLEMENT" + suffix, "(\\d+)[%s]+days?");
return new RegexConcat( //
new RegexLeaf("COMPLEMENT" + suffix, "(\\d+)[%s]+days?"), //
new RegexLeaf("LOAD" + suffix, "([%s]+at[%s]+(\\d+)%)?"));
}
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
final String days = arg.get("COMPLEMENT" + suffix, 0);
return Failable.<Complement> ok(new DurationDay(Integer.parseInt(days)));
final String load = arg.get("LOAD" + suffix, 1);
if (load == null) {
return Failable.<Complement> ok(LoadInDays.inDay(Integer.parseInt(days)));
}
return Failable.<Complement> ok(LoadInDays.inDayWithLoad(Integer.parseInt(days), Integer.parseInt(load)));
}
}

View File

@ -0,0 +1,58 @@
/* ========================================================================
* 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.project3;
public class ConstantPlan implements LoadPlanable {
private final int loadPerInstant;
private ConstantPlan(int loadPerInstant) {
this.loadPerInstant = loadPerInstant;
}
public static LoadPlanable normal() {
return new ConstantPlan(100);
}
public static LoadPlanable partial(int load) {
return new ConstantPlan(load);
}
public int getLoadAt(Instant instant) {
return loadPerInstant;
}
}

View File

@ -35,7 +35,7 @@
*/
package net.sourceforge.plantuml.project3;
public class DayAsDate implements Complement, Comparable<DayAsDate> {
public class DayAsDate implements Complement, Comparable<DayAsDate>, Subject {
private final int year;
private final int dayOfMonth;
@ -64,6 +64,17 @@ public class DayAsDate implements Complement, Comparable<DayAsDate> {
return "" + year + "/" + month + "/" + dayOfMonth;
}
@Override
public int hashCode() {
return year * 113 + dayOfMonth * 17 + month.hashCode();
}
@Override
public boolean equals(Object obj) {
final DayAsDate other = (DayAsDate) obj;
return other.internalNumber() == this.internalNumber();
}
public final int getDayOfMonth() {
return dayOfMonth;
}

View File

@ -0,0 +1,78 @@
/* ========================================================================
* 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.project3;
import java.util.Iterator;
public class DaysAsDates implements Subject, Complement, Iterable<DayAsDate> {
private final DayAsDate date1;
private final DayAsDate date2;
public DaysAsDates(DayAsDate date1, DayAsDate date2) {
this.date1 = date1;
this.date2 = date2;
}
class MyIterator implements Iterator<DayAsDate> {
private DayAsDate current;
public MyIterator(DayAsDate current) {
this.current = current;
}
public boolean hasNext() {
return current.compareTo(date2) <= 0;
}
public DayAsDate next() {
final DayAsDate result = current;
current = current.next();
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public Iterator<DayAsDate> iterator() {
return new MyIterator(date1);
}
}

View File

@ -37,10 +37,10 @@ package net.sourceforge.plantuml.project3;
public interface GCalendar {
// public DayAsDate next(DayAsDate day);
public DayAsDate toDayAsDate(InstantDay day);
public DayAsDate getStartingDate();
public InstantDay fromDayAsDate(DayAsDate day);
}

View File

@ -45,8 +45,22 @@ public class GCalendarSimple implements GCalendar {
public DayAsDate toDayAsDate(InstantDay day) {
DayAsDate result = start;
for (int i = 0; i < day.getNumDay(); i++) {
final int target = day.getNumDay();
int work = 0;
while (work < target) {
result = result.next();
work++;
}
return result;
}
public InstantDay fromDayAsDate(DayAsDate day) {
if (day.compareTo(start) < 0) {
throw new IllegalArgumentException();
}
InstantDay result = new InstantDay(0);
while (toDayAsDate(result).equals(day) == false) {
result = result.increment();
}
return result;
}

View File

@ -125,7 +125,7 @@ public class GanttArrow implements UDrawable {
private double getX(TaskInstant when, Direction direction) {
final double x1 = timeScale.getStartingPosition(when.getInstantTheorical());
final double x2 = timeScale.getStartingPosition(when.getInstantTheorical().increment());
final double x2 = timeScale.getEndingPosition(when.getInstantTheorical());
if (direction == Direction.LEFT) {
return x1;
}

View File

@ -38,9 +38,12 @@ package net.sourceforge.plantuml.project3;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -54,6 +57,7 @@ import net.sourceforge.plantuml.core.ImageData;
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.HtmlColorSetSimple;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.IHtmlColorSet;
@ -61,10 +65,12 @@ import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class GanttDiagram extends AbstractPSystem implements Subject {
@ -73,6 +79,8 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
private final Map<String, Task> byShortName = new HashMap<String, Task>();
private final List<GanttConstraint> constraints = new ArrayList<GanttConstraint>();
private final IHtmlColorSet colorSet = new HtmlColorSetSimple();
private final Collection<DayOfWeek> closedDayOfWeek = EnumSet.noneOf(DayOfWeek.class);
private final Collection<DayAsDate> closedDayAsDate = new HashSet<DayAsDate>();
private GCalendar calendar;
private final Instant min = new InstantDay(0);
@ -82,6 +90,34 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
return new DiagramDescription("(Project)");
}
private int horizontalPages = 1;
private int verticalPages = 1;
final public int getHorizontalPages() {
return horizontalPages;
}
final public void setHorizontalPages(int horizontalPages) {
this.horizontalPages = horizontalPages;
}
final public int getVerticalPages() {
return verticalPages;
}
final public void setVerticalPages(int verticalPages) {
this.verticalPages = verticalPages;
}
@Override
public int getNbImages() {
return this.horizontalPages * this.verticalPages;
}
public final int getDpi(FileFormatOption fileFormatOption) {
return 96;
}
@Override
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption, long seed)
throws IOException {
@ -129,10 +165,33 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
}
private TimeScale getTimeScale() {
return new TimeScaleBasic();
if (calendar == null) {
return new TimeScaleBasic();
}
return new TimeScaleBasic2(getCalendarSimple());
// return new TimeScaleWithoutWeekEnd(calendar);
}
private GCalendarSimple getCalendarSimple() {
return (GCalendarSimple) calendar;
}
public LoadPlanable getDefaultPlan() {
return new LoadPlanable() {
public int getLoadAt(Instant instant) {
if (calendar == null) {
return 100;
}
final DayAsDate day = getCalendarSimple().toDayAsDate((InstantDay) instant);
final DayOfWeek dayOfWeek = day.getDayOfWeek();
if (closedDayOfWeek.contains(dayOfWeek) || closedDayAsDate.contains(day)) {
return 0;
}
return 100;
}
};
}
private void drawConstraints(final UGraphic ug, TimeScale timeScale) {
for (GanttConstraint constraint : constraints) {
constraint.getUDrawable(timeScale).drawU(ug);
@ -142,10 +201,10 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
private void drawTimeHeader(final UGraphic ug, TimeScale timeScale) {
final double yTotal = initTaskDraws(timeScale);
final double yTotal = initTaskAndResourceDraws(timeScale);
final double xmin = timeScale.getStartingPosition(min);
final double xmax = timeScale.getStartingPosition(max.increment());
final double xmax = timeScale.getEndingPosition(max);
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).draw(new ULine(xmax - xmin, 0));
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(0, getHeaderHeight() - 3))
.draw(new ULine(xmax - xmin, 0));
@ -157,41 +216,66 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
}
private void drawCalendar(final UGraphic ug, TimeScale timeScale, final double yTotal) {
final int magic = 12;
final ULine vbar = new ULine(0, yTotal - magic);
Month lastMonth = null;
for (Instant i = min; i.compareTo(max.increment()) <= 0; i = i.increment()) {
final DayAsDate day = calendar.toDayAsDate((InstantDay) i);
final String d1 = "" + day.getDayOfMonth();
final TextBlock num = Display.getWithNewlines(d1).create(getFontConfiguration(), HorizontalAlignment.LEFT,
new SpriteContainerEmpty());
final double x1 = timeScale.getStartingPosition(i);
final double x2 = timeScale.getStartingPosition(i.increment());
if (i.compareTo(max.increment()) < 0) {
final TextBlock weekDay = Display.getWithNewlines(day.getDayOfWeek().shortName()).create(
getFontConfiguration(), HorizontalAlignment.LEFT, new SpriteContainerEmpty());
drawCenter(ug.apply(new UTranslate(0, magic * 2)), num, x1, x2);
drawCenter(ug.apply(new UTranslate(0, magic)), weekDay, x1, x2);
if (lastMonth != day.getMonth()) {
final TextBlock month = Display.getWithNewlines(day.getMonth().name()).create(
getFontConfiguration(), HorizontalAlignment.LEFT, new SpriteContainerEmpty());
month.drawU(ug.apply(new UTranslate(x1, 0)));
}
lastMonth = day.getMonth();
}
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(x1, magic)).draw(vbar);
}
}
private final HtmlColor veryLightGray = new HtmlColorSetSimple().getColorIfValid("#E0E8E8");
private double getHeaderHeight() {
if (calendar != null) {
return 40;
return Y_WEEKDAY + Y_NUMDAY;
}
return 16;
}
private static final int Y_WEEKDAY = 16;
private static final int Y_NUMDAY = 28;
private void drawCalendar(final UGraphic ug, TimeScale timeScale, final double yTotal) {
timeScale = new TimeScaleBasic();
final ULine vbar = new ULine(0, yTotal - Y_WEEKDAY);
Month lastMonth = null;
final GCalendarSimple calendarAll = getCalendarSimple();
final Instant max2 = calendarAll.fromDayAsDate(calendar.toDayAsDate((InstantDay) max));
for (Instant i = min; i.compareTo(max2.increment()) <= 0; i = i.increment()) {
final DayAsDate day = calendarAll.toDayAsDate((InstantDay) i);
final DayOfWeek dayOfWeek = day.getDayOfWeek();
final boolean isWorkingDay = getDefaultPlan().getLoadAt(i) > 0;
final String d1 = "" + day.getDayOfMonth();
final TextBlock num = getTextBlock(d1, 10);
final double x1 = timeScale.getStartingPosition(i);
final double x2 = timeScale.getEndingPosition(i);
if (i.compareTo(max2.increment()) < 0) {
final TextBlock weekDay = getTextBlock(dayOfWeek.shortName(), 10);
if (isWorkingDay) {
drawCenter(ug.apply(new UTranslate(0, Y_NUMDAY)), num, x1, x2);
drawCenter(ug.apply(new UTranslate(0, Y_WEEKDAY)), weekDay, x1, x2);
} else {
final URectangle rect = new URectangle(x2 - x1 - 1, yTotal - Y_WEEKDAY);
ug.apply(new UChangeColor(null)).apply(new UChangeBackColor(veryLightGray))
.apply(new UTranslate(x1 + 1, Y_WEEKDAY)).draw(rect);
}
if (lastMonth != day.getMonth()) {
final int delta = 5;
if (lastMonth != null) {
final TextBlock lastMonthBlock = getTextBlock(lastMonth.name(), 12);
lastMonthBlock.drawU(ug.apply(new UTranslate(x1
- lastMonthBlock.calculateDimension(ug.getStringBounder()).getWidth() - delta, 0)));
}
final TextBlock month = getTextBlock(day.getMonth().name(), 12);
month.drawU(ug.apply(new UTranslate(x1 + delta, 0)));
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(x1, 0))
.draw(new ULine(0, Y_WEEKDAY));
}
lastMonth = day.getMonth();
}
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(x1, Y_WEEKDAY)).draw(vbar);
}
}
private TextBlock getTextBlock(final String text, int size) {
return Display.getWithNewlines(text).create(getFontConfiguration(size), HorizontalAlignment.LEFT,
new SpriteContainerEmpty());
}
private void drawCenter(final UGraphic ug, final TextBlock text, final double x1, final double x2) {
final double width = text.calculateDimension(ug.getStringBounder()).getWidth();
final double delta = (x2 - x1) - width;
@ -204,10 +288,10 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
private void drawSimpleDayCounter(final UGraphic ug, TimeScale timeScale, final double yTotal) {
final ULine vbar = new ULine(0, yTotal);
for (Instant i = min; i.compareTo(max.increment()) <= 0; i = i.increment()) {
final TextBlock num = Display.getWithNewlines(i.toShortString()).create(getFontConfiguration(),
final TextBlock num = Display.getWithNewlines(i.toShortString()).create(getFontConfiguration(10),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
final double x1 = timeScale.getStartingPosition(i);
final double x2 = timeScale.getStartingPosition(i.increment());
final double x2 = timeScale.getEndingPosition(i);
final double width = num.calculateDimension(ug.getStringBounder()).getWidth();
final double delta = (x2 - x1) - width;
if (i.compareTo(max.increment()) < 0) {
@ -217,12 +301,24 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
}
}
private double initTaskDraws(TimeScale timeScale) {
private double initTaskAndResourceDraws(TimeScale timeScale) {
double y = getHeaderHeight();
for (Task task : tasks.values()) {
final TaskDraw draw = new TaskDraw(task, timeScale, y);
final TaskDraw draw;
if (task instanceof TaskSeparator) {
draw = new TaskDrawSeparator((TaskSeparator) task, timeScale, y, min, max);
} else {
draw = new TaskDrawRegular((TaskImpl) task, timeScale, y);
}
task.setTaskDraw(draw);
y += draw.getHeight();
}
for (Resource res : resources.values()) {
final ResourceDraw draw = new ResourceDraw(this, res, timeScale, y, min, max);
res.setTaskDraw(draw);
y += draw.getHeight();
}
return y;
}
@ -231,6 +327,9 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
// min = tasks.values().iterator().next().getStart();
max = tasks.values().iterator().next().getEnd();
for (Task task : tasks.values()) {
if (task instanceof TaskSeparator) {
continue;
}
final Instant start = task.getStart();
final Instant end = task.getEnd();
// if (min.compareTo(start) > 0) {
@ -246,14 +345,20 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
for (Task task : tasks.values()) {
final TaskDraw draw = task.getTaskDraw();
draw.drawU(ug.apply(new UTranslate(0, draw.getY())));
draw.getTitle().drawU(
ug.apply(new UTranslate(timeScale.getStartingPosition(task.getStart().increment()), draw.getY())));
draw.drawTitle(ug.apply(new UTranslate(0, draw.getY())));
}
for (Resource res : resources.values()) {
final ResourceDraw draw = res.getResourceDraw();
draw.drawU(ug.apply(new UTranslate(0, draw.getY())));
}
}
private FontConfiguration getFontConfiguration() {
final UFont font = UFont.serif(10);
return new FontConfiguration(font, HtmlColorUtils.LIGHT_GRAY, HtmlColorUtils.LIGHT_GRAY, false);
private FontConfiguration getFontConfiguration(int size) {
UFont font = UFont.serif(size);
if (size > 10) {
font = font.bold();
}
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
}
public Task getExistingTask(String id) {
@ -268,7 +373,13 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
return tasks.get(code);
}
public Task getOrCreateTask(String codeOrShortName, String shortName) {
public void setTaskOrder(final Task task1, final Task task2) {
final TaskInstant end1 = new TaskInstant(task1, TaskAttribute.END);
task2.setStart(end1.getInstantPrecise());
addContraint(new GanttConstraint(end1, new TaskInstant(task2, TaskAttribute.START)));
}
public Task getOrCreateTask(String codeOrShortName, String shortName, boolean linkedToPrevious) {
if (codeOrShortName == null) {
throw new IllegalArgumentException();
}
@ -283,15 +394,37 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
final TaskCode code = new TaskCode(codeOrShortName);
result = tasks.get(code);
if (result == null) {
result = new TaskImpl(code);
Task previous = null;
if (linkedToPrevious) {
previous = getLastCreatedTask();
}
result = new TaskImpl(code, getDefaultPlan());
tasks.put(code, result);
if (byShortName != null) {
byShortName.put(shortName, result);
}
if (previous != null) {
setTaskOrder(previous, result);
}
}
return result;
}
private Task getLastCreatedTask() {
final List<Task> all = new ArrayList<Task>(tasks.values());
for (int i = all.size() - 1; i >= 0; i--) {
if (all.get(i) instanceof TaskImpl) {
return all.get(i);
}
}
return null;
}
public void addSeparator(String comment) {
TaskSeparator separator = new TaskSeparator(comment, tasks.size());
tasks.put(separator.getCode(), separator);
}
private TaskCodeSimpleOrder getCanonicalOrder(int hierarchyHeader) {
final List<TaskCode> codes = new ArrayList<TaskCode>();
for (TaskCode code : tasks.keySet()) {
@ -326,4 +459,44 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
return this.calendar.getStartingDate();
}
public void closeDayOfWeek(DayOfWeek day) {
closedDayOfWeek.add(day);
}
public void closeDayAsDate(DayAsDate day) {
closedDayAsDate.add(day);
}
public Instant convert(DayAsDate day) {
return calendar.fromDayAsDate(day);
}
private final Map<String, Resource> resources = new LinkedHashMap<String, Resource>();
public void affectResource(Task result, String resourceName) {
Resource resource = getResource(resourceName);
result.addResource(resource);
}
public Resource getResource(String resourceName) {
Resource resource = resources.get(resourceName);
if (resource == null) {
resource = new Resource(resourceName, getDefaultPlan());
}
resources.put(resourceName, resource);
return resource;
}
public int getLoadForResource(Resource res, Instant i) {
int result = 0;
for (Task task : tasks.values()) {
if (task instanceof TaskSeparator) {
continue;
}
final TaskImpl task2 = (TaskImpl) task;
result += task2.loadForResource(res, i);
}
return result;
}
}

View File

@ -50,7 +50,8 @@ import net.sourceforge.plantuml.core.DiagramType;
public class GanttDiagramFactory extends UmlDiagramFactory {
private List<SubjectPattern> subjects() {
return Arrays.<SubjectPattern> asList(new SubjectTask(), new SubjectProject(), new SubjectDayOfWeek());
return Arrays.<SubjectPattern> asList(new SubjectTask(), new SubjectProject(), new SubjectDayOfWeek(),
new SubjectDayAsDate(), new SubjectDaysAsDates(), new SubjectResource());
}
public GanttDiagramFactory(DiagramType type) {
@ -60,23 +61,25 @@ public class GanttDiagramFactory extends UmlDiagramFactory {
@Override
protected List<Command> createCommands() {
final List<Command> cmds = new ArrayList<Command>();
//addCommonCommands(cmds);
// addCommonCommands(cmds);
cmds.add(new CommandNope());
// cmds.add(new CommandComment());
// cmds.add(new CommandMultilinesComment());
// cmds.add(new CommandComment());
// cmds.add(new CommandMultilinesComment());
for (Command cmd : getLanguageCommands()) {
cmds.add(cmd);
}
cmds.add(new CommandGanttArrow());
cmds.add(new CommandScale());
// cmds.add(new CommandScaleWidthAndHeight());
// cmds.add(new CommandScaleWidthOrHeight());
// cmds.add(new CommandScaleMaxWidth());
// cmds.add(new CommandScaleMaxHeight());
// cmds.add(new CommandScaleMaxWidthAndHeight());
cmds.add(new CommandGanttArrow2());
cmds.add(new CommandSeparator());
cmds.add(new CommandScale());
cmds.add(new CommandPage());
// cmds.add(new CommandScaleWidthAndHeight());
// cmds.add(new CommandScaleWidthOrHeight());
// cmds.add(new CommandScaleMaxWidth());
// cmds.add(new CommandScaleMaxHeight());
// cmds.add(new CommandScaleMaxWidthAndHeight());
return cmds;
}

View File

@ -37,10 +37,6 @@ package net.sourceforge.plantuml.project3;
public interface Instant extends Value, Comparable<Instant> {
public Instant add(Duration duration);
public Instant sub(Duration duration);
public Instant increment();
public Instant decrement();

View File

@ -48,16 +48,6 @@ public class InstantDay implements Instant {
return "(day +" + numDay + ")";
}
public InstantDay add(Duration duration) {
final int nbdays = ((DurationDay) duration).getDays();
return new InstantDay(numDay + nbdays);
}
public InstantDay sub(Duration duration) {
final int nbdays = ((DurationDay) duration).getDays();
return new InstantDay(numDay - nbdays);
}
public InstantDay increment() {
return new InstantDay(numDay + 1);
}

View File

@ -35,21 +35,8 @@
*/
package net.sourceforge.plantuml.project3;
public class DurationDay implements Duration {
public interface Load extends Value, Complement, LoadPlanable {
private final int days;
public DurationDay(int days) {
this.days = days;
}
public int getDays() {
return days;
}
@Override
public String toString() {
return "{" + days + " days}";
}
int getFullLoad();
}

View File

@ -0,0 +1,65 @@
/* ========================================================================
* 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.project3;
public class LoadInDays implements Load {
private final int days;
private final int loadPerDay;
private LoadInDays(int days, int loadPerDay) {
this.days = days;
this.loadPerDay = loadPerDay;
}
public static LoadInDays inDay(int days) {
return new LoadInDays(days, 100);
}
public static Complement inDayWithLoad(int days, int loadPerDay) {
final int tmp = (int) Math.ceil(days * 100.0 / loadPerDay);
return new LoadInDays(tmp, loadPerDay);
}
public int getFullLoad() {
return days * loadPerDay;
}
public int getLoadAt(Instant instant) {
return loadPerDay;
}
}

View File

@ -35,6 +35,7 @@
*/
package net.sourceforge.plantuml.project3;
public interface Duration extends Value, Complement {
public interface LoadPlanable {
public int getLoadAt(Instant instant);
}

View File

@ -0,0 +1,52 @@
/* ========================================================================
* 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.project3;
public class PlanUtils {
private PlanUtils() {
}
public static LoadPlanable minOf(final LoadPlanable p1, final LoadPlanable p2) {
return new LoadPlanable() {
public int getLoadAt(Instant instant) {
return Math.min(p1.getLoadAt(instant), p2.getLoadAt(instant));
}
};
}
}

View File

@ -0,0 +1,91 @@
/* ========================================================================
* 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.project3;
import java.util.Set;
import java.util.TreeSet;
public class Resource implements Subject, LoadPlanable {
private final String name;
private ResourceDraw draw;
private final LoadPlanable loadPlanable;
private Set<Instant> closed = new TreeSet<Instant>();
public Resource(String name, LoadPlanable loadPlanable) {
this.name = name;
this.loadPlanable = loadPlanable;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
final Resource other = (Resource) obj;
return this.name.equals(other.name);
}
@Override
public String toString() {
return name;
}
public String getName() {
return name;
}
public ResourceDraw getResourceDraw() {
return draw;
}
public void setTaskDraw(ResourceDraw draw) {
this.draw = draw;
}
public int getLoadAt(Instant instant) {
if (this.closed.contains(instant)) {
return 0;
}
return loadPlanable.getLoadAt(instant);
}
public void addCloseDay(Instant instant) {
this.closed.add(instant);
}
}

View File

@ -0,0 +1,118 @@
/* ========================================================================
* 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.project3;
import net.sourceforge.plantuml.SpriteContainerEmpty;
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.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class ResourceDraw implements UDrawable {
private final Resource res;
private final TimeScale timeScale;
private final double y;
private final Instant min;
private final Instant max;
private final GanttDiagram gantt;
public ResourceDraw(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Instant min, Instant max) {
this.res = res;
this.timeScale = timeScale;
this.y = y;
this.min = min;
this.max = max;
this.gantt = gantt;
}
public void drawU(UGraphic ug) {
final TextBlock title = Display.getWithNewlines(res.getName()).create(getFontConfiguration(13),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
title.drawU(ug);
final ULine line = new ULine(timeScale.getEndingPosition(max) - timeScale.getStartingPosition(min), 0);
ug.apply(new UChangeColor(HtmlColorUtils.BLACK))
.apply(new UTranslate(0, title.calculateDimension(ug.getStringBounder()).getHeight())).draw(line);
for (Instant i = min; i.compareTo(max) <= 0; i = i.increment()) {
final int load = gantt.getLoadForResource(res, i);
if (load > 0) {
final FontConfiguration fontConfiguration = getFontConfiguration(9, load > 100 ? HtmlColorUtils.RED
: HtmlColorUtils.BLACK);
final TextBlock value = Display.getWithNewlines("" + load).create(fontConfiguration,
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
final double start = (timeScale.getStartingPosition(i) + timeScale.getEndingPosition(i)) / 2
- value.calculateDimension(ug.getStringBounder()).getWidth() / 2;
value.drawU(ug.apply(new UTranslate(start, 16)));
}
}
}
private FontConfiguration getFontConfiguration(int size) {
return getFontConfiguration(size, HtmlColorUtils.BLACK);
}
private FontConfiguration getFontConfiguration(int size, HtmlColor color) {
final UFont font = UFont.serif(size);
return new FontConfiguration(font, color, color, false);
}
// public void setColors(ComplementColors colors);
//
// public double getY();
//
// public double getY(Direction direction);
//
// public void drawTitle(UGraphic ug);
public double getHeight() {
return 16 * 2;
}
public double getY() {
return y;
}
}

View File

@ -0,0 +1,53 @@
/* ========================================================================
* 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.project3;
import java.util.LinkedHashSet;
import java.util.Set;
public class Resources implements LoadPlanable {
private final Set<Resource> all = new LinkedHashSet<Resource>();
public int getLoadAt(Instant instant) {
int result = 0;
for (Resource res : all) {
result += res.getLoadAt(instant);
}
return result;
}
}

View File

@ -0,0 +1,56 @@
/* ========================================================================
* 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.project3;
public class Solver2 {
public Instant solveEnd(Instant start, int fullLoad, LoadPlanable plan) {
while (fullLoad > 0) {
fullLoad -= plan.getLoadAt(start);
start = start.increment();
}
return start;
}
public Instant solveStart(Instant end, int fullLoad, LoadPlanable plan) {
while (fullLoad > 0) {
fullLoad -= plan.getLoadAt(end);
end = end.decrement();
}
return end;
}
}

View File

@ -40,10 +40,16 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
public class Solver {
public class Solver3 {
private final Map<TaskAttribute, Value> values = new LinkedHashMap<TaskAttribute, Value>();
private final LoadPlanable loadPlanable;
public Solver3(LoadPlanable loadPlanable) {
this.loadPlanable = loadPlanable;
}
public void setData(TaskAttribute attribute, Value value) {
values.remove(attribute);
values.put(attribute, value);
@ -69,23 +75,30 @@ public class Solver {
if (attribute == TaskAttribute.START) {
return computeStart();
}
throw new UnsupportedOperationException(attribute.toString());
return LoadInDays.inDay(1);
// throw new UnsupportedOperationException(attribute.toString());
}
return result;
}
private Instant computeStart() {
final Instant end = (Instant) values.get(TaskAttribute.END);
final Duration duration = (Duration) values.get(TaskAttribute.DURATION);
assert end != null && duration != null;
return end.sub(duration).increment();
private Instant computeEnd() {
Instant current = (Instant) values.get(TaskAttribute.START);
int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad();
while (fullLoad > 0) {
fullLoad -= loadPlanable.getLoadAt(current);
current = current.increment();
}
return current.decrement();
}
private Instant computeEnd() {
final Instant start = (Instant) values.get(TaskAttribute.START);
final Duration duration = (Duration) values.get(TaskAttribute.DURATION);
assert start != null && duration != null;
return start.add(duration).decrement();
private Instant computeStart() {
Instant current = (Instant) values.get(TaskAttribute.END);
int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad();
while (fullLoad > 0) {
fullLoad -= loadPlanable.getLoadAt(current);
current = current.decrement();
}
return current.increment();
}
}

View File

@ -0,0 +1,68 @@
/* ========================================================================
* 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.project3;
import java.util.Arrays;
import java.util.Collection;
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;
public class SubjectDayAsDate implements SubjectPattern {
public Collection<VerbPattern> getVerbs() {
return Arrays.<VerbPattern> asList(new VerbIs());
}
public IRegex toRegex() {
return new RegexConcat( //
new RegexLeaf("YEAR", "([\\d]{4})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("MONTH", "([\\d]{1,2})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("DAY", "([\\d]{1,2})"));
}
public Subject getSubject(GanttDiagram project, RegexResult arg) {
final int day = Integer.parseInt(arg.get("DAY", 0));
final int month = Integer.parseInt(arg.get("MONTH", 0));
final int year = Integer.parseInt(arg.get("YEAR", 0));
return DayAsDate.create(year, month, day);
}
}

View File

@ -0,0 +1,82 @@
/* ========================================================================
* 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.project3;
import java.util.Arrays;
import java.util.Collection;
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;
public class SubjectDaysAsDates implements SubjectPattern {
public Collection<VerbPattern> getVerbs() {
return Arrays.<VerbPattern> asList(new VerbIs());
}
public IRegex toRegex() {
return new RegexConcat( //
new RegexLeaf("YEAR1", "([\\d]{4})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("MONTH1", "([\\d]{1,2})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("DAY1", "([\\d]{1,2})"), //
new RegexLeaf("[%s]+to[%s]+"), //
new RegexLeaf("YEAR2", "([\\d]{4})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("MONTH2", "([\\d]{1,2})"), //
new RegexLeaf("\\D"), //
new RegexLeaf("DAY2", "([\\d]{1,2})") //
);
}
public Subject getSubject(GanttDiagram project, RegexResult arg) {
final DayAsDate date1 = getDate(arg, "1");
final DayAsDate date2 = getDate(arg, "2");
return new DaysAsDates(date1, date2);
}
private DayAsDate getDate(RegexResult arg, String suffix) {
final int day = Integer.parseInt(arg.get("DAY" + suffix, 0));
final int month = Integer.parseInt(arg.get("MONTH" + suffix, 0));
final int year = Integer.parseInt(arg.get("YEAR" + suffix, 0));
return DayAsDate.create(year, month, day);
}
}

View File

@ -0,0 +1,63 @@
/* ========================================================================
* 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.project3;
import java.util.Arrays;
import java.util.Collection;
import java.util.StringTokenizer;
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;
public class SubjectResource implements SubjectPattern {
public Collection<VerbPattern> getVerbs() {
return Arrays.<VerbPattern> asList(new VerbIsOff());
}
public IRegex toRegex() {
return new RegexConcat( //
new RegexLeaf("RESOURCE", "\\{([^{}]+)\\}") //
);
}
public Subject getSubject(GanttDiagram project, RegexResult arg) {
final String s = arg.get("RESOURCE", 0);
return project.getResource(s);
}
}

View File

@ -37,8 +37,10 @@ package net.sourceforge.plantuml.project3;
import java.util.Arrays;
import java.util.Collection;
import java.util.StringTokenizer;
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;
@ -50,17 +52,31 @@ public class SubjectTask implements SubjectPattern {
}
public IRegex toRegex() {
return new RegexLeaf("SUBJECT", "\\[([^\\[\\]]+?)\\](?:[%s]+as[%s]+\\[([^\\[\\]]+?)\\])?");
return new RegexConcat( //
new RegexLeaf("THEN", "(then[%s]+)?"), //
new RegexLeaf("SUBJECT", "\\[([^\\[\\]]+?)\\](?:[%s]+as[%s]+\\[([^\\[\\]]+?)\\])?"), //
new RegexLeaf("RESOURCE", "(?:[%s]+on[%s]+((?:\\{[^{}]+\\}[%s]*)+))?") //
);
}
public Subject getSubject(GanttDiagram project, RegexResult arg) {
final String s = arg.get("SUBJECT", 0);
final String shortName = arg.get("SUBJECT", 1);
final Task result = project.getOrCreateTask(s, shortName);
final String then = arg.get("THEN", 0);
final String resource = arg.get("RESOURCE", 0);
final Task result = project.getOrCreateTask(s, shortName, then != null);
if (result == null) {
throw new IllegalStateException();
}
if (resource != null) {
for (final StringTokenizer st = new StringTokenizer(resource, "{}"); st.hasMoreTokens();) {
final String part = st.nextToken().trim();
if (part.length() > 0) {
project.affectResource(result, part);
}
}
}
return result;
}
}

View File

@ -43,18 +43,20 @@ public interface Task extends Subject {
public Instant getEnd();
public Duration getDuration();
public Load getLoad();
public void setLoad(Load load);
public void setStart(Instant start);
public void setEnd(Instant end);
public void setDuration(Duration duration);
public void setTaskDraw(TaskDraw taskDraw);
public TaskDraw getTaskDraw();
public void setColors(ComplementColors colors);
public void addResource(Resource resource);
}

View File

@ -36,7 +36,7 @@
package net.sourceforge.plantuml.project3;
public enum TaskAttribute {
START, END, DURATION;
START, END, LOAD;
public static TaskAttribute fromString(String value) {
return valueOf(value.toUpperCase());

View File

@ -81,9 +81,8 @@ public class TaskCode {
return hierarchy.toString();
}
public Display getSimpleDisplay() {
final String last = hierarchy.get(hierarchy.size() - 1);
return Display.getWithNewlines(last);
public String getSimpleDisplay() {
return hierarchy.get(hierarchy.size() - 1);
}
public int getHierarchySize() {

View File

@ -36,111 +36,19 @@
package net.sourceforge.plantuml.project3;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.SpriteContainerEmpty;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPolygon;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UShape;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class TaskDraw implements UDrawable {
public interface TaskDraw extends UDrawable {
private final Task task;
private final TimeScale timeScale;
private final double y;
private ComplementColors colors;
public void setColors(ComplementColors colors);
private final double margin = 2;
public double getY();
public TaskDraw(Task task, TimeScale timeScale, double y) {
this.y = y;
this.task = task;
this.timeScale = timeScale;
}
public double getY(Direction direction);
public TextBlock getTitle() {
return task.getCode().getSimpleDisplay()
.create(getFontConfiguration(), HorizontalAlignment.LEFT, new SpriteContainerEmpty());
}
public void drawTitle(UGraphic ug);
private FontConfiguration getFontConfiguration() {
final UFont font = UFont.serif(11);
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
}
public double getHeight();
public void drawU(UGraphic ug) {
final double start = timeScale.getStartingPosition(task.getStart());
final UShape rect = getShape();
ug = applyColors(ug);
ug.apply(new UTranslate(start + margin, margin)).draw(rect);
}
private UGraphic applyColors(UGraphic ug) {
if (colors != null && colors.isOk()) {
return colors.apply(ug);
}
if (isDiamond()) {
return ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(new UChangeBackColor(HtmlColorUtils.BLACK));
}
return ug.apply(new UChangeColor(HtmlColorUtils.BLUE)).apply(new UChangeBackColor(HtmlColorUtils.COL_84BE84));
}
private UShape getShape() {
if (isDiamond()) {
return getDiamond();
}
final Instant instantStart = task.getStart();
final Instant instantEnd = task.getEnd();
final double start = timeScale.getStartingPosition(instantStart);
final double end = timeScale.getStartingPosition(instantEnd.increment());
return new URectangle(end - start - 2 * margin, getHeight() - 2 * margin, 8, 8);
}
private boolean isDiamond() {
final Instant instantStart = task.getStart();
final Instant instantEnd = task.getEnd();
return instantStart.compareTo(instantEnd) == 0;
}
private UShape getDiamond() {
final double h = getHeight() - 2 * margin;
final UPolygon result = new UPolygon();
result.addPoint(h / 2, 0);
result.addPoint(h, h / 2);
result.addPoint(h / 2, h);
result.addPoint(0, h / 2);
return result;
// return result.translate(2, 2);
}
public double getHeight() {
return 16;
}
public double getY() {
return y;
}
public double getY(Direction direction) {
if (direction == Direction.UP) {
return y;
}
if (direction == Direction.DOWN) {
return y + getHeight();
}
return y + getHeight() / 2;
}
public void setColors(ComplementColors colors) {
this.colors = colors;
}
}

View File

@ -0,0 +1,174 @@
/* ========================================================================
* 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.project3;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.SpriteContainerEmpty;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPolygon;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UShape;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class TaskDrawRegular implements TaskDraw {
private final TaskImpl task;
private final TimeScale timeScale;
private final double y;
private ComplementColors colors;
private final double margin = 2;
public TaskDrawRegular(TaskImpl task, TimeScale timeScale, double y) {
this.y = y;
this.task = task;
this.timeScale = timeScale;
}
public void drawTitle(UGraphic ug) {
final TextBlock title = Display.getWithNewlines(task.getPrettyDisplay()).create(getFontConfiguration(),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
title.drawU(ug.apply(new UTranslate(timeScale.getEndingPosition(task.getStart()), 0)));
}
private FontConfiguration getFontConfiguration() {
final UFont font = UFont.serif(11);
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
}
public void drawU(UGraphic ug1) {
final double start = timeScale.getStartingPosition(task.getStart());
ug1 = applyColors(ug1);
UGraphic ug2 = ug1.apply(new UTranslate(start + margin, margin));
// final int load = 42; // task.getLoad();
final UShape shapeFull = getShape(100);
if (shapeFull instanceof UPolygon) {
ug2.draw(shapeFull);
} else {
final double fullHeight = ((URectangle) shapeFull).getHeight();
ug2.apply(new UChangeBackColor(HtmlColorUtils.WHITE)).apply(new UChangeColor(HtmlColorUtils.WHITE))
.draw(shapeFull);
drawInside(ug1, fullHeight);
ug2.apply(new UChangeBackColor(null)).draw(shapeFull);
}
}
private void drawInside(UGraphic ug, double fullHeight) {
for (Instant i = task.getStart(); i.compareTo(task.getEnd()) <= 0; i = i.increment()) {
final int load = task.getLoadAt(i);
final URectangle shapeLoad = getShapeInside(load, i);
final double diffHeight = fullHeight - shapeLoad.getHeight();
final double start = timeScale.getStartingPosition(i);
ug.apply(new UChangeColor(null)).apply(new UTranslate(start, diffHeight + margin)).draw(shapeLoad);
}
}
private UGraphic applyColors(UGraphic ug) {
if (colors != null && colors.isOk()) {
return colors.apply(ug);
}
if (isDiamond()) {
return ug.apply(new UChangeColor(HtmlColorUtils.BLACK)).apply(new UChangeBackColor(HtmlColorUtils.BLACK));
}
return ug.apply(new UChangeColor(HtmlColorUtils.BLUE)).apply(new UChangeBackColor(HtmlColorUtils.COL_84BE84));
}
private URectangle getShapeInside(int load, Instant instant) {
final double start = timeScale.getStartingPosition(instant);
final double end = timeScale.getEndingPosition(instant);
final double height = (getHeight() - 2 * margin) * load / 100.0;
return new URectangle(end - start, height);
}
private UShape getShape(int load) {
if (isDiamond()) {
return getDiamond();
}
final Instant instantStart = task.getStart();
final Instant instantEnd = task.getEnd();
final double start = timeScale.getStartingPosition(instantStart);
final double end = timeScale.getEndingPosition(instantEnd);
final double height = (getHeight() - 2 * margin) * load / 100.0;
return new URectangle(end - start - 2 * margin, height, 8, 8);
}
private boolean isDiamond() {
final Instant instantStart = task.getStart();
final Instant instantEnd = task.getEnd();
return instantStart.compareTo(instantEnd) == 0;
}
private UShape getDiamond() {
final double h = getHeight() - 2 * margin;
final UPolygon result = new UPolygon();
result.addPoint(h / 2, 0);
result.addPoint(h, h / 2);
result.addPoint(h / 2, h);
result.addPoint(0, h / 2);
return result;
// return result.translate(2, 2);
}
public double getHeight() {
return 16;
}
public double getY() {
return y;
}
public double getY(Direction direction) {
if (direction == Direction.UP) {
return y;
}
if (direction == Direction.DOWN) {
return y + getHeight();
}
return y + getHeight() / 2;
}
public void setColors(ComplementColors colors) {
this.colors = colors;
}
}

View File

@ -0,0 +1,128 @@
/* ========================================================================
* 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.project3;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.SpriteContainerEmpty;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.graphic.TextBlockUtils;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UTranslate;
public class TaskDrawSeparator implements TaskDraw {
private final TimeScale timeScale;
private final double y;
private final Instant min;
private final Instant max;
private final String name;
public TaskDrawSeparator(TaskSeparator task, TimeScale timeScale, double y, Instant min, Instant max) {
this.name = task.getName();
this.y = y;
this.timeScale = timeScale;
this.min = min;
this.max = max;
}
public void drawTitle(UGraphic ug) {
getTitle().drawU(ug.apply(new UTranslate(MARGIN1, 0)));
}
private TextBlock getTitle() {
if (name == null) {
return TextBlockUtils.empty(0, 0);
}
return Display.getWithNewlines(this.name).create(getFontConfiguration(), HorizontalAlignment.LEFT,
new SpriteContainerEmpty());
}
private FontConfiguration getFontConfiguration() {
final UFont font = UFont.serif(11);
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
}
private final static double MARGIN1 = 10;
private final static double MARGIN2 = 2;
public void drawU(UGraphic ug) {
final double widthTitle = getTitle().calculateDimension(ug.getStringBounder()).getWidth();
final double start = timeScale.getStartingPosition(min) + widthTitle;
final double end = timeScale.getEndingPosition(max);
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
ug = ug.apply(new UTranslate(0, getHeight() / 2));
if (widthTitle == 0) {
final ULine line = new ULine(end - start, 0);
ug.draw(line);
} else {
final ULine line1 = new ULine(MARGIN1 - MARGIN2, 0);
final ULine line2 = new ULine(end - start - MARGIN1 - MARGIN2, 0);
ug.draw(line1);
ug.apply(new UTranslate(widthTitle + MARGIN1 + MARGIN2, 0)).draw(line2);
}
}
public double getHeight() {
return 16;
}
public double getY() {
return y;
}
public double getY(Direction direction) {
if (direction == Direction.UP) {
return y;
}
if (direction == Direction.DOWN) {
return y + getHeight();
}
return y + getHeight() / 2;
}
public void setColors(ComplementColors colors) {
}
}

View File

@ -35,15 +35,80 @@
*/
package net.sourceforge.plantuml.project3;
public class TaskImpl implements Task {
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class TaskImpl implements Task, LoadPlanable {
private final TaskCode code;
private final Solver solver = new Solver();
private final Solver3 solver;
private final Set<Resource> resources = new LinkedHashSet<Resource>();
private final LoadPlanable defaultPlan;
public TaskImpl(TaskCode code) {
public TaskImpl(TaskCode code, LoadPlanable defaultPlan) {
this.code = code;
this.defaultPlan = defaultPlan;
this.solver = new Solver3(this);
setStart(new InstantDay(0));
setDuration(new DurationDay(1));
setLoad(LoadInDays.inDay(1));
}
public int getLoadAt(Instant instant) {
LoadPlanable plan1 = defaultPlan;
if (resources.size() > 0) {
plan1 = PlanUtils.minOf(plan1, getRessourcePlan());
}
return PlanUtils.minOf(getLoad(), plan1).getLoadAt(instant);
}
public int loadForResource(Resource res, Instant i) {
if (resources.contains(res) && i.compareTo(getStart()) >= 0 && i.compareTo(getEnd()) <= 0) {
if (res.getLoadAt(i) == 0) {
return 0;
}
int size = 0;
for (Resource r : resources) {
if (r.getLoadAt(i) > 0) {
size++;
}
}
return getLoadAt(i) / size;
}
return 0;
}
private LoadPlanable getRessourcePlan() {
if (resources.size() == 0) {
throw new IllegalStateException();
}
return new LoadPlanable() {
public int getLoadAt(Instant instant) {
int result = 0;
for (Resource res : resources) {
result += res.getLoadAt(instant);
}
return result;
}
};
}
public String getPrettyDisplay() {
if (resources.size() > 0) {
final StringBuilder result = new StringBuilder(code.getSimpleDisplay());
result.append(" ");
for (Iterator<Resource> it = resources.iterator(); it.hasNext();) {
result.append("{");
result.append(it.next().getName());
result.append("}");
if (it.hasNext()) {
result.append(" ");
}
}
return result.toString();
}
return code.getSimpleDisplay();
}
@Override
@ -52,7 +117,7 @@ public class TaskImpl implements Task {
}
public String debug() {
return "" + getStart() + " ---> " + getEnd() + " [" + getDuration() + "]";
return "" + getStart() + " ---> " + getEnd() + " [" + getLoad() + "]";
}
public TaskCode getCode() {
@ -60,15 +125,23 @@ public class TaskImpl implements Task {
}
public Instant getStart() {
return (Instant) solver.getData(TaskAttribute.START);
Instant result = (Instant) solver.getData(TaskAttribute.START);
while (getLoadAt(result) == 0) {
result = result.increment();
}
return result;
}
public Instant getEnd() {
return (Instant) solver.getData(TaskAttribute.END);
}
public Duration getDuration() {
return (Duration) solver.getData(TaskAttribute.DURATION);
public Load getLoad() {
return (Load) solver.getData(TaskAttribute.LOAD);
}
public void setLoad(Load load) {
solver.setData(TaskAttribute.LOAD, load);
}
public void setStart(Instant start) {
@ -79,10 +152,6 @@ public class TaskImpl implements Task {
solver.setData(TaskAttribute.END, end);
}
public void setDuration(Duration duration) {
solver.setData(TaskAttribute.DURATION, duration);
}
private TaskDraw taskDraw;
private ComplementColors colors;
@ -99,4 +168,8 @@ public class TaskImpl implements Task {
this.colors = colors;
}
public void addResource(Resource resource) {
this.resources.add(resource);
}
}

View File

@ -0,0 +1,99 @@
/* ========================================================================
* 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.project3;
public class TaskSeparator implements Task {
// public static final double SPACE = 15;
private final TaskCode code;
private final String comment;
private TaskDraw taskDraw;
public TaskSeparator(String comment, int id) {
this.code = new TaskCode("##" + id);
this.comment = comment;
}
public TaskCode getCode() {
return code;
}
public Instant getStart() {
throw new UnsupportedOperationException();
}
public Instant getEnd() {
throw new UnsupportedOperationException();
}
public void setStart(Instant start) {
throw new UnsupportedOperationException();
}
public void setEnd(Instant end) {
throw new UnsupportedOperationException();
}
public void setTaskDraw(TaskDraw taskDraw) {
this.taskDraw = taskDraw;
}
public TaskDraw getTaskDraw() {
return taskDraw;
}
public void setColors(ComplementColors colors) {
throw new UnsupportedOperationException();
}
public String getName() {
return comment;
}
public void addResource(Resource resource) {
throw new UnsupportedOperationException();
}
public Load getLoad() {
throw new UnsupportedOperationException();
}
public void setLoad(Load load) {
throw new UnsupportedOperationException();
}
}

View File

@ -39,6 +39,8 @@ public interface TimeScale {
public double getStartingPosition(Instant instant);
public double getEndingPosition(Instant instant);
public double getWidth(Instant instant);
}

View File

@ -44,6 +44,10 @@ public class TimeScaleBasic implements TimeScale {
return day * scale;
}
public double getEndingPosition(Instant instant) {
return getStartingPosition(instant) + getWidth(instant);
}
public double getWidth(Instant instant) {
return scale;
}

View File

@ -0,0 +1,79 @@
/* ========================================================================
* 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.project3;
import java.util.Map;
import java.util.TreeMap;
public class TimeScaleBasic2 implements TimeScale {
private final GCalendar calendar;
private final GCalendar calendarAllOpen;
private final TimeScaleBasic basic = new TimeScaleBasic();
private final Map<Instant, Instant> cache = new TreeMap<Instant, Instant>();
public TimeScaleBasic2(GCalendarSimple calendar) {
this.calendar = calendar;
this.calendarAllOpen = calendar;
}
private Instant changeInstantSlow(Instant instant) {
final DayAsDate day = calendar.toDayAsDate((InstantDay) instant);
return calendarAllOpen.fromDayAsDate(day);
}
private Instant changeInstant(Instant instant) {
Instant result = cache.get(instant);
if (result == null) {
result = changeInstantSlow(instant);
cache.put(instant, result);
}
return result;
}
public double getStartingPosition(Instant instant) {
return basic.getStartingPosition(changeInstant(instant));
}
public double getEndingPosition(Instant instant) {
return basic.getEndingPosition(changeInstant(instant));
}
public double getWidth(Instant instant) {
return basic.getWidth(changeInstant(instant));
}
}

View File

@ -66,4 +66,8 @@ public class TimeScaleWithoutWeekEnd implements TimeScale {
return scale;
}
public double getEndingPosition(Instant instant) {
throw new UnsupportedOperationException();
}
}

View File

@ -57,9 +57,9 @@ public class VerbAre implements VerbPattern {
return new Verb() {
public CommandExecutionResult execute(Subject subject, Complement complement) {
final DayOfWeek day = (DayOfWeek) subject;
project.closeDayOfWeek(day);
return CommandExecutionResult.ok();
}
};
}
}

View File

@ -58,7 +58,7 @@ public class VerbHappens implements VerbPattern {
public CommandExecutionResult execute(Subject subject, Complement complement) {
final Task task = (Task) subject;
final TaskInstant when = (TaskInstant) complement;
task.setDuration(new DurationDay(1));
task.setLoad(LoadInDays.inDay(1));
task.setStart(when.getInstantTheorical());
return CommandExecutionResult.ok();
}

View File

@ -0,0 +1,73 @@
/* ========================================================================
* 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.project3;
import java.util.Arrays;
import java.util.Collection;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class VerbIs implements VerbPattern {
public Collection<ComplementPattern> getComplements() {
return Arrays.<ComplementPattern> asList(new ComplementClose());
}
public IRegex toRegex() {
return new RegexLeaf("is");
}
public Verb getVerb(final GanttDiagram project, RegexResult arg) {
return new Verb() {
public CommandExecutionResult execute(Subject subject, Complement complement) {
if (subject instanceof DayAsDate) {
final DayAsDate day = (DayAsDate) subject;
project.closeDayAsDate(day);
}
if (subject instanceof DaysAsDates) {
final DaysAsDates days = (DaysAsDates) subject;
for (DayAsDate d : days) {
project.closeDayAsDate(d);
}
}
return CommandExecutionResult.ok();
}
};
}
}

View File

@ -0,0 +1,74 @@
/* ========================================================================
* 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.project3;
import java.util.Arrays;
import java.util.Collection;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class VerbIsOff implements VerbPattern {
public Collection<ComplementPattern> getComplements() {
return Arrays.<ComplementPattern> asList(new ComplementDate(), new ComplementDates());
}
public IRegex toRegex() {
return new RegexLeaf("is off on");
}
public Verb getVerb(final GanttDiagram project, RegexResult arg) {
return new Verb() {
public CommandExecutionResult execute(Subject subject, Complement complement) {
final Resource resource = (Resource) subject;
if (complement instanceof DaysAsDates) {
for (DayAsDate when : (DaysAsDates) complement) {
resource.addCloseDay(project.convert(when));
}
} else {
final DayAsDate when = (DayAsDate) complement;
resource.addCloseDay(project.convert(when));
}
return CommandExecutionResult.ok();
}
};
}
}

View File

@ -57,8 +57,8 @@ public class VerbLasts implements VerbPattern {
return new Verb() {
public CommandExecutionResult execute(Subject subject, Complement complement) {
final Task task = (Task) subject;
final Duration duration = (Duration) complement;
task.setDuration(duration);
final Load duration = (Load) complement;
task.setLoad(duration);
return CommandExecutionResult.ok();
}

View File

@ -41,7 +41,7 @@ import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.PaddingParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.cucadiagram.Stereotype;
@ -108,7 +108,7 @@ public class Rose implements Skin {
param.strictUmlStyle() == false, param.responseMessageBelowArrow());
}
final double padding = param.getPadding(PaddingParam.PARTICIPANT);
final double roundCorner = param.getRoundCorner(RoundParam.DEFAULT, null);
final double roundCorner = param.getRoundCorner(CornerParam.DEFAULT, null);
if (type == ComponentType.PARTICIPANT_HEAD) {
return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param,
FontParam.PARTICIPANT), stringsToDisplay, param, roundCorner, newFontForStereotype, getFontColor(

View File

@ -93,7 +93,7 @@ public class ClusterDecoration {
throw new UnsupportedOperationException();
}
final SymbolContext symbolContext = biColor.withShadow(shadowing).withStroke(defaultStroke)
.withRoundCorner(roundCorner);
.withCorner(roundCorner, 0);
symbol.asBig(title, titleAlignment, stereo, maxX - minX, maxY - minY, symbolContext).drawU(
ug.apply(new UTranslate(minX, minY)));
// return;

View File

@ -44,7 +44,7 @@ import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineConfigurable;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.creole.Stencil;
@ -85,7 +85,7 @@ public class EntityImageClass extends AbstractEntityImage implements Stencil, Wi
public EntityImageClass(GraphvizVersion version, ILeaf entity, ISkinParam skinParam, PortionShower portionShower) {
super(entity, entity.getColors(skinParam).mute(skinParam));
this.lineConfig = entity;
this.roundCorner = getSkinParam().getRoundCorner(RoundParam.DEFAULT, null);
this.roundCorner = getSkinParam().getRoundCorner(CornerParam.DEFAULT, null);
this.shield = version != null && version.useShield() && entity.hasNearDecoration() ? Margins.uniform(16)
: Margins.NONE;
final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity);

View File

@ -87,7 +87,6 @@ public class EntityImageDescription extends AbstractEntityImage {
private final Collection<Link> links;
private final boolean useRankSame;
public EntityImageDescription(ILeaf entity, ISkinParam skinParam, PortionShower portionShower,
Collection<Link> links) {
super(entity, entity.getColors(skinParam).mute(skinParam));
@ -116,10 +115,12 @@ public class EntityImageDescription extends AbstractEntityImage {
assert getStereo() == stereotype;
final HtmlColor forecolor = SkinParamUtils.getColor(getSkinParam(), symbol.getColorParamBorder(), stereotype);
final double roundCorner = symbol.getSkinParameter().getRoundCorner(getSkinParam(), stereotype);
final double diagonalCorner = symbol.getSkinParameter().getDiagonalCorner(getSkinParam(), stereotype);
final UStroke stroke = colors.muteStroke(symbol.getSkinParameter().getStroke(getSkinParam(), stereotype));
final SymbolContext ctx = new SymbolContext(backcolor, forecolor).withStroke(stroke)
.withShadow(getSkinParam().shadowing2(symbol.getSkinParameter())).withRoundCorner(roundCorner);
.withShadow(getSkinParam().shadowing2(symbol.getSkinParameter()))
.withCorner(roundCorner, diagonalCorner);
stereo = TextBlockUtils.empty(0, 0);

View File

@ -45,7 +45,7 @@ import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.SkinParamBackcolored;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.Url;
@ -221,7 +221,7 @@ public class EntityImageNote extends AbstractEntityImage implements Stencil {
}
private double getRoundCorner() {
return skinParam.getRoundCorner(RoundParam.DEFAULT, null);
return skinParam.getRoundCorner(CornerParam.DEFAULT, null);
}
private static Point2D move(Point2D pt, double dx, double dy) {

View File

@ -43,7 +43,7 @@ import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineConfigurable;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.creole.Stencil;
@ -88,7 +88,7 @@ public class EntityImageObject extends AbstractEntityImage implements Stencil {
super(entity, skinParam);
this.lineConfig = entity;
final Stereotype stereotype = entity.getStereotype();
this.roundCorner = skinParam.getRoundCorner(RoundParam.DEFAULT, null);
this.roundCorner = skinParam.getRoundCorner(CornerParam.DEFAULT, null);
this.name = TextBlockUtils.withMargin(
entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.OBJECT, stereotype),
HorizontalAlignment.CENTER, skinParam), 2, 2);

View File

@ -110,6 +110,7 @@ public class Footprint {
drawText(x, y, (UText) shape);
} else if (shape instanceof UHorizontalLine) {
// Definitively a Horizontal line
// line.drawTitleInternalForFootprint(this, x, y);
} else if (shape instanceof ULine) {
// Probably a Horizontal line
} else if (shape instanceof UImage) {

View File

@ -5,12 +5,12 @@
* (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
@ -104,7 +104,8 @@ public class Histogram implements TimeDrawing {
return Collections.emptyList();
}
for (int i = 0; i < changes.size(); i++) {
if (changes.get(i).getWhen().compareTo(tick) == 0) {
final int tickWithCurrentChangeTimeComparisonResult = changes.get(i).getWhen().compareTo(tick);
if (tickWithCurrentChangeTimeComparisonResult == 0) {
if (i == 0 && initialState == null) {
return Arrays.asList(changes.get(i).getState());
}
@ -113,8 +114,16 @@ public class Histogram implements TimeDrawing {
}
return Arrays.asList(changes.get(i - 1).getState(), changes.get(i).getState());
}
if (changes.get(i).getWhen().compareTo(tick) > 0) {
return Collections.singletonList(changes.get(i - 1).getState());
if (tickWithCurrentChangeTimeComparisonResult > 0) {
final int changeIndex;
if (i == 0) {
// if this time tick was not yet defined in any place, and is less then the first one,
// assume it's the leftmost
changeIndex = 0;
} else {
changeIndex = i - 1;
}
return Collections.singletonList(changes.get(changeIndex).getState());
}
}
return Collections.singletonList(changes.get(changes.size() - 1).getState());
@ -254,7 +263,7 @@ public class Histogram implements TimeDrawing {
}
return new Dimension2DDouble(width, getFullDeltaY());
}
public MinMax getMinMax(StringBounder stringBounder) {
throw new UnsupportedOperationException();
}

View File

@ -63,7 +63,7 @@ import net.sourceforge.plantuml.FileUtils;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.OptionFlags;
import net.sourceforge.plantuml.RoundParam;
import net.sourceforge.plantuml.CornerParam;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.anim.AffineTransformation;
@ -143,7 +143,7 @@ public class ImageBuilder {
final Rose rose = new Rose();
this.borderColor = rose.getHtmlColor(skinParam, ColorParam.diagramBorder);
this.borderStroke = skinParam.getThickness(LineParam.diagramBorder, null);
this.borderCorner = skinParam.getRoundCorner(RoundParam.diagramBorder, null);
this.borderCorner = skinParam.getRoundCorner(CornerParam.diagramBorder, null);
if (borderStroke == null && borderColor != null) {
this.borderStroke = new UStroke();
}

View File

@ -144,6 +144,15 @@ public class UHorizontalLine implements UShape {
ug.apply(new UTranslate(startingX, y)).draw(new ULine(endingX - startingX, 0));
}
// public void drawTitleInternalForFootprint(UGraphic ug, double x, double y) {
// if (title == null || blankTitle) {
// return;
// }
// final Dimension2D dimTitle = title.calculateDimension(ug.getStringBounder());
// final double y1 = y - dimTitle.getHeight() / 2 - 0.5;
// title.drawU(ug.apply(new UTranslate(skipAtStart, y1)));
// }
public void drawTitleInternal(UGraphic ug, double startingX, double endingX, double y, boolean clearArea) {
if (title == null || blankTitle) {
return;

View File

@ -43,7 +43,7 @@ public class Version {
private static final int MAJOR_SEPARATOR = 1000000;
public static int version() {
return 1201802;
return 1201803;
}
public static int versionPatched() {
@ -88,7 +88,7 @@ public class Version {
}
public static long compileTime() {
return 1520616044801L;
return 1522947555139L;
}
public static String compileTimeString() {

View File

@ -30,8 +30,9 @@ public class VP8Decoder {
coefProbs = Globals.getDefaultCoefProbs();
}
public void decodeFrame(ImageInputStream stream, boolean debug)
public void decodeFrame(ImageInputStream stream)
throws IOException {
final boolean debug = false;
coefProbs = Globals.getDefaultCoefProbs();
f = new VP8Frame(stream, coefProbs);
if (f.decodeFrame(debug)) {
@ -52,27 +53,9 @@ public class VP8Decoder {
return f.getWidth();
}
@SuppressWarnings("unused")
private void writeFile(int[][] data) {
FileOutputStream out;
try {
out = new FileOutputStream("outagain.raw");
for (int y = 0; y < data[0].length; y++)
for (int x = 0; x < data.length; x++) {
out.write(data[x][y]);
out.write(data[x][y]);
out.write(data[x][y]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writePGMFile(String fileName, VP8Frame frame) {
FileOutputStream out;
try {
int[][] yData = frame.getYBuffer();