mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-25 06:17:33 +00:00
version 1.2018.3
This commit is contained in:
parent
86c9c6d603
commit
e3bdf19745
2
pom.xml
2
pom.xml
@ -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>
|
||||
|
@ -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),
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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), //
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
162
src/net/sourceforge/plantuml/ZSourceFileReader.java
Normal file
162
src/net/sourceforge/plantuml/ZSourceFileReader.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
66
src/net/sourceforge/plantuml/ZSourceFileReader2.java
Normal file
66
src/net/sourceforge/plantuml/ZSourceFileReader2.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
170
src/net/sourceforge/plantuml/ZSourceFileReaderAbstract.java
Normal file
170
src/net/sourceforge/plantuml/ZSourceFileReaderAbstract.java
Normal 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);
|
||||
|
||||
}
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -289,6 +289,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
|
||||
this.horizontalPages = horizontalPages;
|
||||
}
|
||||
|
||||
|
||||
final public int getVerticalPages() {
|
||||
return verticalPages;
|
||||
}
|
||||
@ -297,6 +298,13 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
|
||||
this.verticalPages = verticalPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNbImages() {
|
||||
return this.horizontalPages * this.verticalPages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// final public List<File> createPng2(File pngFile) throws IOException,
|
||||
// InterruptedException {
|
||||
// final CucaDiagramPngMaker3 maker = new CucaDiagramPngMaker3(this);
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.sourceforge.plantuml.jasic;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -12,101 +11,106 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This defines a single class that contains an entire interpreter for a
|
||||
* language very similar to the original BASIC. Everything is here (albeit in
|
||||
* very simplified form): tokenizing, parsing, and interpretation. The file is
|
||||
* organized in phases, with each appearing roughly in the order that they
|
||||
* occur when a program is run. You should be able to read this top-down to walk
|
||||
* through the entire process of loading and running a program.
|
||||
/*
|
||||
Jasic uses the MIT License:
|
||||
|
||||
Copyright (c) 2010 Robert Nystrom
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Jasic language syntax
|
||||
* ---------------------
|
||||
*/
|
||||
/*
|
||||
* This defines a single class that contains an entire interpreter for a language very similar to the original BASIC.
|
||||
* Everything is here (albeit in very simplified form): tokenizing, parsing, and interpretation. The file is organized
|
||||
* in phases, with each appearing roughly in the order that they occur when a program is run. You should be able to read
|
||||
* this top-down to walk through the entire process of loading and running a program.
|
||||
*
|
||||
* Jasic language syntax ---------------------
|
||||
*
|
||||
* Comments start with ' and proceed to the end of the line:
|
||||
*
|
||||
* print "hi there" ' this is a comment
|
||||
*
|
||||
* Numbers and strings are supported. Strings should be in "double quotes", and
|
||||
* only positive integers can be parsed (though numbers are double internally).
|
||||
* Numbers and strings are supported. Strings should be in "double quotes", and only positive integers can be parsed
|
||||
* (though numbers are double internally).
|
||||
*
|
||||
* Variables are identified by name which must start with a letter and can
|
||||
* contain letters or numbers. Case is significant for names and keywords.
|
||||
* Variables are identified by name which must start with a letter and can contain letters or numbers. Case is
|
||||
* significant for names and keywords.
|
||||
*
|
||||
* Each statement is on its own line. Optionally, a line may have a label before
|
||||
* the statement. A label is a name that ends with a colon:
|
||||
* Each statement is on its own line. Optionally, a line may have a label before the statement. A label is a name that
|
||||
* ends with a colon:
|
||||
*
|
||||
* foo:
|
||||
*
|
||||
*
|
||||
* The following statements are supported:
|
||||
*
|
||||
* <name> = <expression>
|
||||
* Evaluates the expression and assigns the result to the given named
|
||||
* variable. All variables are globally scoped.
|
||||
* <name> = <expression> Evaluates the expression and assigns the result to the given named variable. All variables are
|
||||
* globally scoped.
|
||||
*
|
||||
* pi = (314159 / 10000)
|
||||
*
|
||||
* print <expression>
|
||||
* Evaluates the expression and prints the result.
|
||||
* print <expression> Evaluates the expression and prints the result.
|
||||
*
|
||||
* print "hello, " + "world"
|
||||
*
|
||||
* input <name>
|
||||
* Reads in a line of input from the user and stores it in the variable with
|
||||
* the given name.
|
||||
* input <name> Reads in a line of input from the user and stores it in the variable with the given name.
|
||||
*
|
||||
* input guess
|
||||
*
|
||||
* goto <label>
|
||||
* Jumps to the statement after the label with the given name.
|
||||
* goto <label> Jumps to the statement after the label with the given name.
|
||||
*
|
||||
* goto loop
|
||||
*
|
||||
* if <expression> then <label>
|
||||
* Evaluates the expression. If it evaluates to a non-zero number, then
|
||||
* jumps to the statement after the given label.
|
||||
* if <expression> then <label> Evaluates the expression. If it evaluates to a non-zero number, then jumps to the
|
||||
* statement after the given label.
|
||||
*
|
||||
* if a < b then dosomething
|
||||
*
|
||||
*
|
||||
* The following expressions are supported:
|
||||
*
|
||||
* <expression> = <expression>
|
||||
* Evaluates to 1 if the two expressions are equal, 0 otherwise.
|
||||
* <expression> = <expression> Evaluates to 1 if the two expressions are equal, 0 otherwise.
|
||||
*
|
||||
* <expression> + <expression>
|
||||
* If the left-hand expression is a number, then adds the two expressions,
|
||||
* otherwise concatenates the two strings.
|
||||
* <expression> + <expression> If the left-hand expression is a number, then adds the two expressions, otherwise
|
||||
* concatenates the two strings.
|
||||
*
|
||||
* <expression> - <expression>
|
||||
* <expression> * <expression>
|
||||
* <expression> / <expression>
|
||||
* <expression> < <expression>
|
||||
* <expression> > <expression>
|
||||
* You can figure it out.
|
||||
* <expression> - <expression> <expression> * <expression> <expression> / <expression> <expression> < <expression>
|
||||
* <expression> > <expression> You can figure it out.
|
||||
*
|
||||
* <name>
|
||||
* A name in an expression simply returns the value of the variable with
|
||||
* that name. If the variable was never set, it defaults to 0.
|
||||
* <name> A name in an expression simply returns the value of the variable with that name. If the variable was never
|
||||
* set, it defaults to 0.
|
||||
*
|
||||
* All binary operators have the same precedence. Sorry, I had to cut corners
|
||||
* somewhere.
|
||||
* All binary operators have the same precedence. Sorry, I had to cut corners somewhere.
|
||||
*
|
||||
* To keep things simple, I've omitted some stuff or hacked things a bit. When
|
||||
* possible, I'll leave a "HACK" note there explaining what and why. If you
|
||||
* make your own interpreter, you'll want to address those.
|
||||
* To keep things simple, I've omitted some stuff or hacked things a bit. When possible, I'll leave a "HACK" note there
|
||||
* explaining what and why. If you make your own interpreter, you'll want to address those.
|
||||
*
|
||||
* @author Bob Nystrom
|
||||
*/
|
||||
public class Jasic {
|
||||
|
||||
/**
|
||||
* Runs the interpreter as a command-line app. Takes one argument: a path
|
||||
* to a script file to load and run. The script should contain one
|
||||
* statement per line.
|
||||
* Runs the interpreter as a command-line app. Takes one argument: a path to a script file to load and run. The
|
||||
* script should contain one statement per line.
|
||||
*
|
||||
* @param args Command-line arguments.
|
||||
* @param args
|
||||
* Command-line arguments.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// Just show the usage and quit if a script wasn't provided.
|
||||
@ -127,9 +131,8 @@ public class Jasic {
|
||||
// Tokenizing (lexing) -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* This function takes a script as a string of characters and chunks it into
|
||||
* a sequence of tokens. Each token is a meaningful unit of program, like a
|
||||
* variable name, a number, a string, or an operator.
|
||||
* This function takes a script as a string of characters and chunks it into a sequence of tokens. Each token is a
|
||||
* meaningful unit of program, like a variable name, a number, a string, or an operator.
|
||||
*/
|
||||
private static List<Token> tokenize(String source) {
|
||||
List<Token> tokens = new ArrayList<Token>();
|
||||
@ -139,11 +142,9 @@ public class Jasic {
|
||||
|
||||
// Many tokens are a single character, like operators and ().
|
||||
String charTokens = "\n=+-*/<>()";
|
||||
TokenType[] tokenTypes = { TokenType.LINE, TokenType.EQUALS,
|
||||
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR,
|
||||
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR,
|
||||
TokenType.LEFT_PAREN, TokenType.RIGHT_PAREN
|
||||
};
|
||||
TokenType[] tokenTypes = { TokenType.LINE, TokenType.EQUALS, TokenType.OPERATOR, TokenType.OPERATOR,
|
||||
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR, TokenType.LEFT_PAREN,
|
||||
TokenType.RIGHT_PAREN };
|
||||
|
||||
// Scan through the code one character at a time, building up the list
|
||||
// of tokens.
|
||||
@ -152,8 +153,7 @@ public class Jasic {
|
||||
switch (state) {
|
||||
case DEFAULT:
|
||||
if (charTokens.indexOf(c) != -1) {
|
||||
tokens.add(new Token(Character.toString(c),
|
||||
tokenTypes[charTokens.indexOf(c)]));
|
||||
tokens.add(new Token(Character.toString(c), tokenTypes[charTokens.indexOf(c)]));
|
||||
} else if (Character.isLetter(c)) {
|
||||
token += c;
|
||||
state = TokenizeState.WORD;
|
||||
@ -223,22 +223,18 @@ public class Jasic {
|
||||
// Token data --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This defines the different kinds of tokens or meaningful chunks of code
|
||||
* that the parser knows how to consume. These let us distinguish, for
|
||||
* example, between a string "foo" and a variable named "foo".
|
||||
* This defines the different kinds of tokens or meaningful chunks of code that the parser knows how to consume.
|
||||
* These let us distinguish, for example, between a string "foo" and a variable named "foo".
|
||||
*
|
||||
* HACK: A typical tokenizer would actually have unique token types for
|
||||
* each keyword (print, goto, etc.) so that the parser doesn't have to look
|
||||
* at the names, but Jasic is a little more crude.
|
||||
* HACK: A typical tokenizer would actually have unique token types for each keyword (print, goto, etc.) so that the
|
||||
* parser doesn't have to look at the names, but Jasic is a little more crude.
|
||||
*/
|
||||
private enum TokenType {
|
||||
WORD, NUMBER, STRING, LABEL, LINE,
|
||||
EQUALS, OPERATOR, LEFT_PAREN, RIGHT_PAREN, EOF
|
||||
WORD, NUMBER, STRING, LABEL, LINE, EQUALS, OPERATOR, LEFT_PAREN, RIGHT_PAREN, EOF
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a single meaningful chunk of code. It is created by the tokenizer
|
||||
* and consumed by the parser.
|
||||
* This is a single meaningful chunk of code. It is created by the tokenizer and consumed by the parser.
|
||||
*/
|
||||
private static class Token {
|
||||
public Token(String text, TokenType type) {
|
||||
@ -251,15 +247,13 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* This defines the different states the tokenizer can be in while it's
|
||||
* scanning through the source code. Tokenizers are state machines, which
|
||||
* means the only data they need to store is where they are in the source
|
||||
* code and this one "state" or mode value.
|
||||
* This defines the different states the tokenizer can be in while it's scanning through the source code. Tokenizers
|
||||
* are state machines, which means the only data they need to store is where they are in the source code and this
|
||||
* one "state" or mode value.
|
||||
*
|
||||
* One of the main differences between tokenizing and parsing is this
|
||||
* regularity. Because the tokenizer stores only this one state value, it
|
||||
* can't handle nesting (which would require also storing a number to
|
||||
* identify how deeply nested you are). The parser is able to handle that.
|
||||
* One of the main differences between tokenizing and parsing is this regularity. Because the tokenizer stores only
|
||||
* this one state value, it can't handle nesting (which would require also storing a number to identify how deeply
|
||||
* nested you are). The parser is able to handle that.
|
||||
*/
|
||||
private enum TokenizeState {
|
||||
DEFAULT, WORD, NUMBER, STRING, COMMENT
|
||||
@ -268,14 +262,13 @@ public class Jasic {
|
||||
// Parsing -----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This defines the Jasic parser. The parser takes in a sequence of tokens
|
||||
* and generates an abstract syntax tree. This is the nested data structure
|
||||
* that represents the series of statements, and the expressions (which can
|
||||
* nest arbitrarily deeply) that they evaluate. In technical terms, what we
|
||||
* have is a recursive descent parser, the simplest kind to hand-write.
|
||||
* This defines the Jasic parser. The parser takes in a sequence of tokens and generates an abstract syntax tree.
|
||||
* This is the nested data structure that represents the series of statements, and the expressions (which can nest
|
||||
* arbitrarily deeply) that they evaluate. In technical terms, what we have is a recursive descent parser, the
|
||||
* simplest kind to hand-write.
|
||||
*
|
||||
* As a side-effect, this phase also stores off the line numbers for each
|
||||
* label in the program. It's a bit gross, but it works.
|
||||
* As a side-effect, this phase also stores off the line numbers for each label in the program. It's a bit gross,
|
||||
* but it works.
|
||||
*/
|
||||
private class Parser {
|
||||
public Parser(List<Token> tokens) {
|
||||
@ -284,12 +277,11 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* The top-level function to start parsing. This will keep consuming
|
||||
* tokens and routing to the other parse functions for the different
|
||||
* grammar syntax until we run out of code to parse.
|
||||
* The top-level function to start parsing. This will keep consuming tokens and routing to the other parse
|
||||
* functions for the different grammar syntax until we run out of code to parse.
|
||||
*
|
||||
* @param labels A map of label names to statement indexes. The
|
||||
* parser will fill this in as it scans the code.
|
||||
* @param labels
|
||||
* A map of label names to statement indexes. The parser will fill this in as it scans the code.
|
||||
* @return The list of parsed statements.
|
||||
*/
|
||||
public List<Statement> parse(Map<String, Integer> labels) {
|
||||
@ -297,7 +289,8 @@ public class Jasic {
|
||||
|
||||
while (true) {
|
||||
// Ignore empty lines.
|
||||
while (match(TokenType.LINE));
|
||||
while (match(TokenType.LINE))
|
||||
;
|
||||
|
||||
if (match(TokenType.LABEL)) {
|
||||
// Mark the index of the statement after the label.
|
||||
@ -309,17 +302,16 @@ public class Jasic {
|
||||
} else if (match("print")) {
|
||||
statements.add(new PrintStatement(expression()));
|
||||
} else if (match("input")) {
|
||||
statements.add(new InputStatement(
|
||||
consume(TokenType.WORD).text));
|
||||
statements.add(new InputStatement(consume(TokenType.WORD).text));
|
||||
} else if (match("goto")) {
|
||||
statements.add(new GotoStatement(
|
||||
consume(TokenType.WORD).text));
|
||||
statements.add(new GotoStatement(consume(TokenType.WORD).text));
|
||||
} else if (match("if")) {
|
||||
Expression condition = expression();
|
||||
consume("then");
|
||||
String label = consume(TokenType.WORD).text;
|
||||
statements.add(new IfThenStatement(condition, label));
|
||||
} else break; // Unexpected token (likely EOF), so end.
|
||||
} else
|
||||
break; // Unexpected token (likely EOF), so end.
|
||||
}
|
||||
|
||||
return statements;
|
||||
@ -330,9 +322,8 @@ public class Jasic {
|
||||
// noun() and verb().
|
||||
|
||||
/**
|
||||
* Parses a single expression. Recursive descent parsers start with the
|
||||
* lowest-precedent term and moves towards higher precedence. For Jasic,
|
||||
* binary operators (+, -, etc.) are the lowest.
|
||||
* Parses a single expression. Recursive descent parsers start with the lowest-precedent term and moves towards
|
||||
* higher precedence. For Jasic, binary operators (+, -, etc.) are the lowest.
|
||||
*
|
||||
* @return The parsed expression.
|
||||
*/
|
||||
@ -341,24 +332,16 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a series of binary operator expressions into a single
|
||||
* expression. In Jasic, all operators have the same predecence and
|
||||
* associate left-to-right. That means it will interpret:
|
||||
* 1 + 2 * 3 - 4 / 5
|
||||
* like:
|
||||
* ((((1 + 2) * 3) - 4) / 5)
|
||||
* Parses a series of binary operator expressions into a single expression. In Jasic, all operators have the
|
||||
* same predecence and associate left-to-right. That means it will interpret: 1 + 2 * 3 - 4 / 5 like: ((((1 + 2)
|
||||
* * 3) - 4) / 5)
|
||||
*
|
||||
* It works by building the expression tree one at a time. So, given
|
||||
* this code: 1 + 2 * 3, this will:
|
||||
* It works by building the expression tree one at a time. So, given this code: 1 + 2 * 3, this will:
|
||||
*
|
||||
* 1. Parse (1) as an atomic expression.
|
||||
* 2. See the (+) and start a new operator expression.
|
||||
* 3. Parse (2) as an atomic expression.
|
||||
* 4. Build a (1 + 2) expression and replace (1) with it.
|
||||
* 5. See the (*) and start a new operator expression.
|
||||
* 6. Parse (3) as an atomic expression.
|
||||
* 7. Build a ((1 + 2) * 3) expression and replace (1 + 2) with it.
|
||||
* 8. Return the last expression built.
|
||||
* 1. Parse (1) as an atomic expression. 2. See the (+) and start a new operator expression. 3. Parse (2) as an
|
||||
* atomic expression. 4. Build a (1 + 2) expression and replace (1) with it. 5. See the (*) and start a new
|
||||
* operator expression. 6. Parse (3) as an atomic expression. 7. Build a ((1 + 2) * 3) expression and replace (1
|
||||
* + 2) with it. 8. Return the last expression built.
|
||||
*
|
||||
* @return The parsed expression.
|
||||
*/
|
||||
@ -366,8 +349,7 @@ public class Jasic {
|
||||
Expression expression = atomic();
|
||||
|
||||
// Keep building operator expressions as long as we have operators.
|
||||
while (match(TokenType.OPERATOR) ||
|
||||
match(TokenType.EQUALS)) {
|
||||
while (match(TokenType.OPERATOR) || match(TokenType.EQUALS)) {
|
||||
char operator = last(1).text.charAt(0);
|
||||
Expression right = atomic();
|
||||
expression = new OperatorExpression(expression, operator, right);
|
||||
@ -377,9 +359,8 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an "atomic" expression. This is the highest level of
|
||||
* precedence and contains single literal tokens like 123 and "foo", as
|
||||
* well as parenthesized expressions.
|
||||
* Parses an "atomic" expression. This is the highest level of precedence and contains single literal tokens
|
||||
* like 123 and "foo", as well as parenthesized expressions.
|
||||
*
|
||||
* @return The parsed expression.
|
||||
*/
|
||||
@ -408,16 +389,19 @@ public class Jasic {
|
||||
// the token stream.
|
||||
|
||||
/**
|
||||
* Consumes the next two tokens if they are the given type (in order).
|
||||
* Consumes no tokens if either check fais.
|
||||
* Consumes the next two tokens if they are the given type (in order). Consumes no tokens if either check fais.
|
||||
*
|
||||
* @param type1 Expected type of the next token.
|
||||
* @param type2 Expected type of the subsequent token.
|
||||
* @param type1
|
||||
* Expected type of the next token.
|
||||
* @param type2
|
||||
* Expected type of the subsequent token.
|
||||
* @return True if tokens were consumed.
|
||||
*/
|
||||
private boolean match(TokenType type1, TokenType type2) {
|
||||
if (get(0).type != type1) return false;
|
||||
if (get(1).type != type2) return false;
|
||||
if (get(0).type != type1)
|
||||
return false;
|
||||
if (get(1).type != type2)
|
||||
return false;
|
||||
position += 2;
|
||||
return true;
|
||||
}
|
||||
@ -425,11 +409,13 @@ public class Jasic {
|
||||
/**
|
||||
* Consumes the next token if it's the given type.
|
||||
*
|
||||
* @param type Expected type of the next token.
|
||||
* @param type
|
||||
* Expected type of the next token.
|
||||
* @return True if the token was consumed.
|
||||
*/
|
||||
private boolean match(TokenType type) {
|
||||
if (get(0).type != type) return false;
|
||||
if (get(0).type != type)
|
||||
return false;
|
||||
position++;
|
||||
return true;
|
||||
}
|
||||
@ -437,47 +423,52 @@ public class Jasic {
|
||||
/**
|
||||
* Consumes the next token if it's a word token with the given name.
|
||||
*
|
||||
* @param name Expected name of the next word token.
|
||||
* @param name
|
||||
* Expected name of the next word token.
|
||||
* @return True if the token was consumed.
|
||||
*/
|
||||
private boolean match(String name) {
|
||||
if (get(0).type != TokenType.WORD) return false;
|
||||
if (!get(0).text.equals(name)) return false;
|
||||
if (get(0).type != TokenType.WORD)
|
||||
return false;
|
||||
if (!get(0).text.equals(name))
|
||||
return false;
|
||||
position++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the next token if it's the given type. If not, throws an
|
||||
* exception. This is for cases where the parser demands a token of a
|
||||
* certain type in a certain position, for example a matching ) after
|
||||
* an opening (.
|
||||
* Consumes the next token if it's the given type. If not, throws an exception. This is for cases where the
|
||||
* parser demands a token of a certain type in a certain position, for example a matching ) after an opening (.
|
||||
*
|
||||
* @param type Expected type of the next token.
|
||||
* @param type
|
||||
* Expected type of the next token.
|
||||
* @return The consumed token.
|
||||
*/
|
||||
private Token consume(TokenType type) {
|
||||
if (get(0).type != type) throw new Error("Expected " + type + ".");
|
||||
if (get(0).type != type)
|
||||
throw new Error("Expected " + type + ".");
|
||||
return tokens.get(position++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the next token if it's a word with the given name. If not,
|
||||
* throws an exception.
|
||||
* Consumes the next token if it's a word with the given name. If not, throws an exception.
|
||||
*
|
||||
* @param name Expected name of the next word token.
|
||||
* @param name
|
||||
* Expected name of the next word token.
|
||||
* @return The consumed token.
|
||||
*/
|
||||
private Token consume(String name) {
|
||||
if (!match(name)) throw new Error("Expected " + name + ".");
|
||||
if (!match(name))
|
||||
throw new Error("Expected " + name + ".");
|
||||
return last(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a previously consumed token, indexing backwards. last(1) will
|
||||
* be the token just consumed, last(2) the one before that, etc.
|
||||
* Gets a previously consumed token, indexing backwards. last(1) will be the token just consumed, last(2) the
|
||||
* one before that, etc.
|
||||
*
|
||||
* @param offset How far back in the token stream to look.
|
||||
* @param offset
|
||||
* How far back in the token stream to look.
|
||||
* @return The consumed token.
|
||||
*/
|
||||
private Token last(int offset) {
|
||||
@ -485,10 +476,11 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unconsumed token, indexing forward. get(0) will be the next
|
||||
* token to be consumed, get(1) the one after that, etc.
|
||||
* Gets an unconsumed token, indexing forward. get(0) will be the next token to be consumed, get(1) the one
|
||||
* after that, etc.
|
||||
*
|
||||
* @param offset How far forward in the token stream to look.
|
||||
* @param offset
|
||||
* How far forward in the token stream to look.
|
||||
* @return The yet-to-be-consumed token.
|
||||
*/
|
||||
private Token get(int offset) {
|
||||
@ -513,29 +505,25 @@ public class Jasic {
|
||||
// separated out so that the AST us just a static data structure.
|
||||
|
||||
/**
|
||||
* Base interface for a Jasic statement. The different supported statement
|
||||
* types like "print" and "goto" implement this.
|
||||
* Base interface for a Jasic statement. The different supported statement types like "print" and "goto" implement
|
||||
* this.
|
||||
*/
|
||||
public interface Statement {
|
||||
/**
|
||||
* Statements implement this to actually perform whatever behavior the
|
||||
* statement causes. "print" statements will display text here, "goto"
|
||||
* statements will change the current statement, etc.
|
||||
* Statements implement this to actually perform whatever behavior the statement causes. "print" statements will
|
||||
* display text here, "goto" statements will change the current statement, etc.
|
||||
*/
|
||||
void execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base interface for an expression. An expression is like a statement
|
||||
* except that it also returns a value when executed. Expressions do not
|
||||
* appear at the top level in Jasic programs, but are used in many
|
||||
* statements. For example, the value printed by a "print" statement is an
|
||||
* expression. Unlike statements, expressions can nest.
|
||||
* Base interface for an expression. An expression is like a statement except that it also returns a value when
|
||||
* executed. Expressions do not appear at the top level in Jasic programs, but are used in many statements. For
|
||||
* example, the value printed by a "print" statement is an expression. Unlike statements, expressions can nest.
|
||||
*/
|
||||
public interface Expression {
|
||||
/**
|
||||
* Expression classes implement this to evaluate the expression and
|
||||
* return the value.
|
||||
* Expression classes implement this to evaluate the expression and return the value.
|
||||
*
|
||||
* @return The value of the calculated expression.
|
||||
*/
|
||||
@ -543,8 +531,7 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* A "print" statement evaluates an expression, converts the result to a
|
||||
* string, and displays it to the user.
|
||||
* A "print" statement evaluates an expression, converts the result to a string, and displays it to the user.
|
||||
*/
|
||||
public class PrintStatement implements Statement {
|
||||
public PrintStatement(Expression expression) {
|
||||
@ -559,8 +546,7 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* An "input" statement reads input from the user and stores it in a
|
||||
* variable.
|
||||
* An "input" statement reads input from the user and stores it in a variable.
|
||||
*/
|
||||
public class InputStatement implements Statement {
|
||||
public InputStatement(String name) {
|
||||
@ -587,8 +573,7 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* An assignment statement evaluates an expression and stores the result in
|
||||
* a variable.
|
||||
* An assignment statement evaluates an expression and stores the result in a variable.
|
||||
*/
|
||||
public class AssignStatement implements Statement {
|
||||
public AssignStatement(String name, Expression value) {
|
||||
@ -622,8 +607,8 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* An if then statement jumps execution to another place in the program, but
|
||||
* only if an expression evaluates to something other than 0.
|
||||
* An if then statement jumps execution to another place in the program, but only if an expression evaluates to
|
||||
* something other than 0.
|
||||
*/
|
||||
public class IfThenStatement implements Statement {
|
||||
public IfThenStatement(Expression condition, String label) {
|
||||
@ -645,8 +630,7 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable expression evaluates to the current value stored in that
|
||||
* variable.
|
||||
* A variable expression evaluates to the current value stored in that variable.
|
||||
*/
|
||||
public class VariableExpression implements Expression {
|
||||
public VariableExpression(String name) {
|
||||
@ -664,12 +648,10 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* An operator expression evaluates two expressions and then performs some
|
||||
* arithmetic operation on the results.
|
||||
* An operator expression evaluates two expressions and then performs some arithmetic operation on the results.
|
||||
*/
|
||||
public class OperatorExpression implements Expression {
|
||||
public OperatorExpression(Expression left, char operator,
|
||||
Expression right) {
|
||||
public OperatorExpression(Expression left, char operator, Expression right) {
|
||||
this.left = left;
|
||||
this.operator = operator;
|
||||
this.right = right;
|
||||
@ -683,48 +665,37 @@ public class Jasic {
|
||||
case '=':
|
||||
// Coerce to the left argument's type, then compare.
|
||||
if (leftVal instanceof NumberValue) {
|
||||
return new NumberValue((leftVal.toNumber() ==
|
||||
rightVal.toNumber()) ? 1 : 0);
|
||||
return new NumberValue((leftVal.toNumber() == rightVal.toNumber()) ? 1 : 0);
|
||||
} else {
|
||||
return new NumberValue(leftVal.toString().equals(
|
||||
rightVal.toString()) ? 1 : 0);
|
||||
return new NumberValue(leftVal.toString().equals(rightVal.toString()) ? 1 : 0);
|
||||
}
|
||||
case '+':
|
||||
// Addition if the left argument is a number, otherwise do
|
||||
// string concatenation.
|
||||
if (leftVal instanceof NumberValue) {
|
||||
return new NumberValue(leftVal.toNumber() +
|
||||
rightVal.toNumber());
|
||||
return new NumberValue(leftVal.toNumber() + rightVal.toNumber());
|
||||
} else {
|
||||
return new StringValue(leftVal.toString() +
|
||||
rightVal.toString());
|
||||
return new StringValue(leftVal.toString() + rightVal.toString());
|
||||
}
|
||||
case '-':
|
||||
return new NumberValue(leftVal.toNumber() -
|
||||
rightVal.toNumber());
|
||||
return new NumberValue(leftVal.toNumber() - rightVal.toNumber());
|
||||
case '*':
|
||||
return new NumberValue(leftVal.toNumber() *
|
||||
rightVal.toNumber());
|
||||
return new NumberValue(leftVal.toNumber() * rightVal.toNumber());
|
||||
case '/':
|
||||
return new NumberValue(leftVal.toNumber() /
|
||||
rightVal.toNumber());
|
||||
return new NumberValue(leftVal.toNumber() / rightVal.toNumber());
|
||||
case '<':
|
||||
// Coerce to the left argument's type, then compare.
|
||||
if (leftVal instanceof NumberValue) {
|
||||
return new NumberValue((leftVal.toNumber() <
|
||||
rightVal.toNumber()) ? 1 : 0);
|
||||
return new NumberValue((leftVal.toNumber() < rightVal.toNumber()) ? 1 : 0);
|
||||
} else {
|
||||
return new NumberValue((leftVal.toString().compareTo(
|
||||
rightVal.toString()) < 0) ? 1 : 0);
|
||||
return new NumberValue((leftVal.toString().compareTo(rightVal.toString()) < 0) ? 1 : 0);
|
||||
}
|
||||
case '>':
|
||||
// Coerce to the left argument's type, then compare.
|
||||
if (leftVal instanceof NumberValue) {
|
||||
return new NumberValue((leftVal.toNumber() >
|
||||
rightVal.toNumber()) ? 1 : 0);
|
||||
return new NumberValue((leftVal.toNumber() > rightVal.toNumber()) ? 1 : 0);
|
||||
} else {
|
||||
return new NumberValue((leftVal.toString().compareTo(
|
||||
rightVal.toString()) > 0) ? 1 : 0);
|
||||
return new NumberValue((leftVal.toString().compareTo(rightVal.toString()) > 0) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
throw new Error("Unknown operator.");
|
||||
@ -738,30 +709,25 @@ public class Jasic {
|
||||
// Value types -------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This is the base interface for a value. Values are the data that the
|
||||
* interpreter processes. They are what gets stored in variables, printed,
|
||||
* and operated on.
|
||||
* This is the base interface for a value. Values are the data that the interpreter processes. They are what gets
|
||||
* stored in variables, printed, and operated on.
|
||||
*
|
||||
* There is an implementation of this interface for each of the different
|
||||
* primitive types (really just double and string) that Jasic supports.
|
||||
* Wrapping them in a single Value interface lets Jasic be dynamically-typed
|
||||
* and convert between different representations as needed.
|
||||
* There is an implementation of this interface for each of the different primitive types (really just double and
|
||||
* string) that Jasic supports. Wrapping them in a single Value interface lets Jasic be dynamically-typed and
|
||||
* convert between different representations as needed.
|
||||
*
|
||||
* Note that Value extends Expression. This is a bit of a hack, but it lets
|
||||
* us use values (which are typically only ever seen by the interpreter and
|
||||
* not the parser) as both runtime values, and as object representing
|
||||
* literals in code.
|
||||
* Note that Value extends Expression. This is a bit of a hack, but it lets us use values (which are typically only
|
||||
* ever seen by the interpreter and not the parser) as both runtime values, and as object representing literals in
|
||||
* code.
|
||||
*/
|
||||
public interface Value extends Expression {
|
||||
/**
|
||||
* Value types override this to convert themselves to a string
|
||||
* representation.
|
||||
* Value types override this to convert themselves to a string representation.
|
||||
*/
|
||||
String toString();
|
||||
|
||||
/**
|
||||
* Value types override this to convert themselves to a numeric
|
||||
* representation.
|
||||
* Value types override this to convert themselves to a numeric representation.
|
||||
*/
|
||||
double toNumber();
|
||||
}
|
||||
@ -774,9 +740,18 @@ public class Jasic {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override public String toString() { return Double.toString(value); }
|
||||
public double toNumber() { return value; }
|
||||
public Value evaluate() { return this; }
|
||||
@Override
|
||||
public String toString() {
|
||||
return Double.toString(value);
|
||||
}
|
||||
|
||||
public double toNumber() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Value evaluate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private final double value;
|
||||
}
|
||||
@ -789,9 +764,18 @@ public class Jasic {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override public String toString() { return value; }
|
||||
public double toNumber() { return Double.parseDouble(value); }
|
||||
public Value evaluate() { return this; }
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public double toNumber() {
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
public Value evaluate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
private final String value;
|
||||
}
|
||||
@ -799,9 +783,8 @@ public class Jasic {
|
||||
// Interpreter -------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new Jasic instance. The instance stores the global state of
|
||||
* the interpreter such as the values of all of the variables and the
|
||||
* current statement.
|
||||
* Constructs a new Jasic instance. The instance stores the global state of the interpreter such as the values of
|
||||
* all of the variables and the current statement.
|
||||
*/
|
||||
public Jasic() {
|
||||
variables = new HashMap<String, Value>();
|
||||
@ -812,17 +795,15 @@ public class Jasic {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where the magic happens. This runs the code through the parsing
|
||||
* pipeline to generate the AST. Then it executes each statement. It keeps
|
||||
* track of the current line in a member variable that the statement objects
|
||||
* have access to. This lets "goto" and "if then" do flow control by simply
|
||||
* setting the index of the current statement.
|
||||
* This is where the magic happens. This runs the code through the parsing pipeline to generate the AST. Then it
|
||||
* executes each statement. It keeps track of the current line in a member variable that the statement objects have
|
||||
* access to. This lets "goto" and "if then" do flow control by simply setting the index of the current statement.
|
||||
*
|
||||
* In an interpreter that didn't mix the interpretation logic in with the
|
||||
* AST node classes, this would be doing a lot more work.
|
||||
* In an interpreter that didn't mix the interpretation logic in with the AST node classes, this would be doing a
|
||||
* lot more work.
|
||||
*
|
||||
* @param source A string containing the source code of a .jas script to
|
||||
* interpret.
|
||||
* @param source
|
||||
* A string containing the source code of a .jas script to interpret.
|
||||
*/
|
||||
public void interpret(String source) {
|
||||
// Tokenize.
|
||||
@ -851,10 +832,10 @@ public class Jasic {
|
||||
// Utility stuff -----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Reads the file from the given path and returns its contents as a single
|
||||
* string.
|
||||
* Reads the file from the given path and returns its contents as a single string.
|
||||
*
|
||||
* @param path Path to the text file to read.
|
||||
* @param path
|
||||
* Path to the text file to read.
|
||||
* @return The contents of the file or null if the load failed.
|
||||
* @throws IOException
|
||||
*/
|
||||
@ -863,8 +844,7 @@ public class Jasic {
|
||||
FileInputStream stream = new FileInputStream(path);
|
||||
|
||||
try {
|
||||
InputStreamReader input = new InputStreamReader(stream,
|
||||
Charset.defaultCharset());
|
||||
InputStreamReader input = new InputStreamReader(stream, Charset.defaultCharset());
|
||||
Reader reader = new BufferedReader(input);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
63
src/net/sourceforge/plantuml/project3/CommandPage.java
Normal file
63
src/net/sourceforge/plantuml/project3/CommandPage.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
65
src/net/sourceforge/plantuml/project3/CommandSeparator.java
Normal file
65
src/net/sourceforge/plantuml/project3/CommandSeparator.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
91
src/net/sourceforge/plantuml/project3/ComplementDates.java
Normal file
91
src/net/sourceforge/plantuml/project3/ComplementDates.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
58
src/net/sourceforge/plantuml/project3/ConstantPlan.java
Normal file
58
src/net/sourceforge/plantuml/project3/ConstantPlan.java
Normal 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;
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
78
src/net/sourceforge/plantuml/project3/DaysAsDates.java
Normal file
78
src/net/sourceforge/plantuml/project3/DaysAsDates.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
@ -68,15 +69,17 @@ public class GanttDiagramFactory extends UmlDiagramFactory {
|
||||
cmds.add(cmd);
|
||||
}
|
||||
cmds.add(new CommandGanttArrow());
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
}
|
65
src/net/sourceforge/plantuml/project3/LoadInDays.java
Normal file
65
src/net/sourceforge/plantuml/project3/LoadInDays.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -35,6 +35,7 @@
|
||||
*/
|
||||
package net.sourceforge.plantuml.project3;
|
||||
|
||||
public interface Duration extends Value, Complement {
|
||||
public interface LoadPlanable {
|
||||
|
||||
public int getLoadAt(Instant instant);
|
||||
}
|
52
src/net/sourceforge/plantuml/project3/PlanUtils.java
Normal file
52
src/net/sourceforge/plantuml/project3/PlanUtils.java
Normal 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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
91
src/net/sourceforge/plantuml/project3/Resource.java
Normal file
91
src/net/sourceforge/plantuml/project3/Resource.java
Normal 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);
|
||||
}
|
||||
}
|
118
src/net/sourceforge/plantuml/project3/ResourceDraw.java
Normal file
118
src/net/sourceforge/plantuml/project3/ResourceDraw.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
53
src/net/sourceforge/plantuml/project3/Resources.java
Normal file
53
src/net/sourceforge/plantuml/project3/Resources.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
56
src/net/sourceforge/plantuml/project3/Solver2.java
Normal file
56
src/net/sourceforge/plantuml/project3/Solver2.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
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();
|
||||
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 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();
|
||||
}
|
||||
|
||||
}
|
68
src/net/sourceforge/plantuml/project3/SubjectDayAsDate.java
Normal file
68
src/net/sourceforge/plantuml/project3/SubjectDayAsDate.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
63
src/net/sourceforge/plantuml/project3/SubjectResource.java
Normal file
63
src/net/sourceforge/plantuml/project3/SubjectResource.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
return result;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
174
src/net/sourceforge/plantuml/project3/TaskDrawRegular.java
Normal file
174
src/net/sourceforge/plantuml/project3/TaskDrawRegular.java
Normal 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;
|
||||
}
|
||||
}
|
128
src/net/sourceforge/plantuml/project3/TaskDrawSeparator.java
Normal file
128
src/net/sourceforge/plantuml/project3/TaskDrawSeparator.java
Normal 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) {
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
99
src/net/sourceforge/plantuml/project3/TaskSeparator.java
Normal file
99
src/net/sourceforge/plantuml/project3/TaskSeparator.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -39,6 +39,8 @@ public interface TimeScale {
|
||||
|
||||
public double getStartingPosition(Instant instant);
|
||||
|
||||
public double getEndingPosition(Instant instant);
|
||||
|
||||
public double getWidth(Instant instant);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
79
src/net/sourceforge/plantuml/project3/TimeScaleBasic2.java
Normal file
79
src/net/sourceforge/plantuml/project3/TimeScaleBasic2.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@ -66,4 +66,8 @@ public class TimeScaleWithoutWeekEnd implements TimeScale {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public double getEndingPosition(Instant instant) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
73
src/net/sourceforge/plantuml/project3/VerbIs.java
Normal file
73
src/net/sourceforge/plantuml/project3/VerbIs.java
Normal 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
74
src/net/sourceforge/plantuml/project3/VerbIsOff.java
Normal file
74
src/net/sourceforge/plantuml/project3/VerbIsOff.java
Normal 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();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user