mirror of
https://github.com/octoleo/plantuml.git
synced 2025-04-07 02:31:51 +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>
|
<groupId>net.sourceforge.plantuml</groupId>
|
||||||
<artifactId>plantuml</artifactId>
|
<artifactId>plantuml</artifactId>
|
||||||
<version>1.2018.3-SNAPSHOT</version>
|
<version>1.2018.4-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>PlantUML</name>
|
<name>PlantUML</name>
|
||||||
|
@ -139,6 +139,8 @@ public enum ColorParam {
|
|||||||
nodeBorder(HtmlColorUtils.BLACK, ColorType.LINE),
|
nodeBorder(HtmlColorUtils.BLACK, ColorType.LINE),
|
||||||
rectangleBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
rectangleBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
||||||
rectangleBorder(HtmlColorUtils.BLACK, ColorType.LINE),
|
rectangleBorder(HtmlColorUtils.BLACK, ColorType.LINE),
|
||||||
|
cardBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
||||||
|
cardBorder(HtmlColorUtils.BLACK, ColorType.LINE),
|
||||||
agentBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
agentBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
||||||
agentBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
|
agentBorder(HtmlColorUtils.MY_RED, ColorType.LINE),
|
||||||
storageBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
storageBackground(HtmlColorUtils.MY_YELLOW, true, ColorType.BACK),
|
||||||
|
@ -35,14 +35,21 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml;
|
package net.sourceforge.plantuml;
|
||||||
|
|
||||||
public enum RoundParam {
|
public enum CornerParam {
|
||||||
DEFAULT, diagramBorder, titleBorder, rectangle, component;
|
DEFAULT, diagramBorder, titleBorder, rectangle, component;
|
||||||
|
|
||||||
public String getKey() {
|
public String getRoundKey() {
|
||||||
if (this == DEFAULT) {
|
if (this == DEFAULT) {
|
||||||
return "roundcorner";
|
return "roundcorner";
|
||||||
}
|
}
|
||||||
return name() + "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;
|
final private double height;
|
||||||
|
|
||||||
public Dimension2DDouble(double width, double height) {
|
public Dimension2DDouble(double width, double height) {
|
||||||
|
if (Double.isNaN(width) || Double.isNaN(height)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ public enum FontParam {
|
|||||||
ENTITY(14, Font.PLAIN), //
|
ENTITY(14, Font.PLAIN), //
|
||||||
AGENT(14, Font.PLAIN), //
|
AGENT(14, Font.PLAIN), //
|
||||||
RECTANGLE(14, Font.PLAIN), //
|
RECTANGLE(14, Font.PLAIN), //
|
||||||
|
CARD(14, Font.PLAIN), //
|
||||||
NODE(14, Font.PLAIN), //
|
NODE(14, Font.PLAIN), //
|
||||||
DATABASE(14, Font.PLAIN), //
|
DATABASE(14, Font.PLAIN), //
|
||||||
QUEUE(14, Font.PLAIN), //
|
QUEUE(14, Font.PLAIN), //
|
||||||
@ -107,6 +108,7 @@ public enum FontParam {
|
|||||||
ENTITY_STEREOTYPE(14, Font.ITALIC), //
|
ENTITY_STEREOTYPE(14, Font.ITALIC), //
|
||||||
AGENT_STEREOTYPE(14, Font.ITALIC), //
|
AGENT_STEREOTYPE(14, Font.ITALIC), //
|
||||||
RECTANGLE_STEREOTYPE(14, Font.ITALIC), //
|
RECTANGLE_STEREOTYPE(14, Font.ITALIC), //
|
||||||
|
CARD_STEREOTYPE(14, Font.ITALIC), //
|
||||||
NODE_STEREOTYPE(14, Font.ITALIC), //
|
NODE_STEREOTYPE(14, Font.ITALIC), //
|
||||||
FOLDER_STEREOTYPE(14, Font.ITALIC), //
|
FOLDER_STEREOTYPE(14, Font.ITALIC), //
|
||||||
FILE_STEREOTYPE(14, Font.ITALIC), //
|
FILE_STEREOTYPE(14, Font.ITALIC), //
|
||||||
|
@ -101,7 +101,9 @@ public interface ISkinParam extends ISkinSimple {
|
|||||||
|
|
||||||
public double getRanksep();
|
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();
|
public LineBreakStrategy maxMessageSize();
|
||||||
|
|
||||||
|
@ -49,8 +49,10 @@ import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3;
|
|||||||
import net.sourceforge.plantuml.core.Diagram;
|
import net.sourceforge.plantuml.core.Diagram;
|
||||||
import net.sourceforge.plantuml.core.ImageData;
|
import net.sourceforge.plantuml.core.ImageData;
|
||||||
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
|
import net.sourceforge.plantuml.cucadiagram.CucaDiagram;
|
||||||
|
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||||
import net.sourceforge.plantuml.html.CucaDiagramHtmlMaker;
|
import net.sourceforge.plantuml.html.CucaDiagramHtmlMaker;
|
||||||
import net.sourceforge.plantuml.png.PngSplitter;
|
import net.sourceforge.plantuml.png.PngSplitter;
|
||||||
|
import net.sourceforge.plantuml.project3.GanttDiagram;
|
||||||
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
|
import net.sourceforge.plantuml.sequencediagram.SequenceDiagram;
|
||||||
|
|
||||||
public class PSystemUtils {
|
public class PSystemUtils {
|
||||||
@ -66,6 +68,9 @@ public class PSystemUtils {
|
|||||||
if (system instanceof CucaDiagram) {
|
if (system instanceof CucaDiagram) {
|
||||||
return exportDiagramsCuca((CucaDiagram) system, suggestedFile, fileFormatOption);
|
return exportDiagramsCuca((CucaDiagram) system, suggestedFile, fileFormatOption);
|
||||||
}
|
}
|
||||||
|
if (system instanceof GanttDiagram) {
|
||||||
|
return exportDiagramsGantt2((GanttDiagram) system, suggestedFile, fileFormatOption);
|
||||||
|
}
|
||||||
if (system instanceof ActivityDiagram3) {
|
if (system instanceof ActivityDiagram3) {
|
||||||
return exportDiagramsActivityDiagram3((ActivityDiagram3) system, suggestedFile, fileFormatOption);
|
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)
|
private static List<FileImageData> createFilesHtml(CucaDiagram system, SuggestedFile suggestedFile)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String name = suggestedFile.getName();
|
final String name = suggestedFile.getName();
|
||||||
|
@ -653,23 +653,39 @@ public class SkinParam implements ISkinParam {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getRoundCorner(RoundParam param, Stereotype stereotype) {
|
public double getDiagonalCorner(CornerParam param, Stereotype stereotype) {
|
||||||
Double result = getRoundCornerInternal(param, stereotype);
|
final String key = param.getDiagonalKey();
|
||||||
|
Double result = getCornerInternal(key, param, stereotype);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = getRoundCornerInternal(param, null);
|
result = getCornerInternal(key, param, null);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (param == RoundParam.DEFAULT) {
|
if (param == CornerParam.DEFAULT) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return getRoundCorner(RoundParam.DEFAULT, stereotype);
|
return getDiagonalCorner(CornerParam.DEFAULT, stereotype);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Double getRoundCornerInternal(RoundParam param, Stereotype stereotype) {
|
public double getRoundCorner(CornerParam param, Stereotype stereotype) {
|
||||||
String key = param.getKey();
|
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) {
|
if (stereotype != null) {
|
||||||
key += stereotype.getLabel(false);
|
key += stereotype.getLabel(false);
|
||||||
}
|
}
|
||||||
|
@ -147,10 +147,14 @@ public class SkinParamDelegator implements ISkinParam {
|
|||||||
return skinParam.getRanksep();
|
return skinParam.getRanksep();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getRoundCorner(RoundParam param, Stereotype stereotype) {
|
public double getRoundCorner(CornerParam param, Stereotype stereotype) {
|
||||||
return skinParam.getRoundCorner(param, 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) {
|
public UStroke getThickness(LineParam param, Stereotype stereotype) {
|
||||||
return skinParam.getThickness(param, 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();
|
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) {
|
public void addFieldOrMethod(String s, IEntity leaf) {
|
||||||
if (leaf == null) {
|
if (leaf == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
@ -196,6 +204,9 @@ public class Bodier {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (leaf == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam,
|
final MethodsOrFieldsArea fields = new MethodsOrFieldsArea(getFieldsToDisplay(), fontParam, skinParam,
|
||||||
stereotype, leaf);
|
stereotype, leaf);
|
||||||
if (type == LeafType.OBJECT) {
|
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 List<Url> urls = new ArrayList<Url>();
|
||||||
private final Stereotype stereotype;
|
private final Stereotype stereotype;
|
||||||
private final ILeaf entity;
|
private final ILeaf entity;
|
||||||
|
private final boolean inEllipse;
|
||||||
|
|
||||||
public BodyEnhanced(List<String> rawBody, FontParam fontParam, ISkinParam skinParam, boolean manageModifier,
|
public BodyEnhanced(List<String> rawBody, FontParam fontParam, ISkinParam skinParam, boolean manageModifier,
|
||||||
Stereotype stereotype, ILeaf entity) {
|
Stereotype stereotype, ILeaf entity) {
|
||||||
@ -91,6 +92,7 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
|
|||||||
this.manageHorizontalLine = true;
|
this.manageHorizontalLine = true;
|
||||||
this.manageModifier = manageModifier;
|
this.manageModifier = manageModifier;
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
|
this.inEllipse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BodyEnhanced(Display display, FontParam fontParam, ISkinParam skinParam, HorizontalAlignment align,
|
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.entity = entity;
|
||||||
this.stereotype = stereotype;
|
this.stereotype = stereotype;
|
||||||
this.rawBody = new ArrayList<String>();
|
this.rawBody = new ArrayList<String>();
|
||||||
for (CharSequence s : display) {
|
|
||||||
this.rawBody.add(s.toString());
|
|
||||||
}
|
|
||||||
this.fontParam = fontParam;
|
this.fontParam = fontParam;
|
||||||
this.skinParam = skinParam;
|
this.skinParam = skinParam;
|
||||||
|
|
||||||
@ -109,6 +108,14 @@ public class BodyEnhanced extends AbstractTextBlock implements TextBlock, WithPo
|
|||||||
this.align = skinParam.getDefaultTextAlignment(align);
|
this.align = skinParam.getDefaultTextAlignment(align);
|
||||||
this.manageHorizontalLine = manageHorizontalLine;
|
this.manageHorizontalLine = manageHorizontalLine;
|
||||||
this.manageModifier = manageModifier;
|
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,
|
blocks.add(decorate(stringBounder, new MethodsOrFieldsArea(members, fontParam, skinParam, align, stereotype,
|
||||||
entity), separator, title));
|
entity), separator, title));
|
||||||
|
|
||||||
|
@ -289,6 +289,7 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
|
|||||||
this.horizontalPages = horizontalPages;
|
this.horizontalPages = horizontalPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final public int getVerticalPages() {
|
final public int getVerticalPages() {
|
||||||
return verticalPages;
|
return verticalPages;
|
||||||
}
|
}
|
||||||
@ -297,6 +298,13 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
|
|||||||
this.verticalPages = verticalPages;
|
this.verticalPages = verticalPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNbImages() {
|
||||||
|
return this.horizontalPages * this.verticalPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// final public List<File> createPng2(File pngFile) throws IOException,
|
// final public List<File> createPng2(File pngFile) throws IOException,
|
||||||
// InterruptedException {
|
// InterruptedException {
|
||||||
// final CucaDiagramPngMaker3 maker = new CucaDiagramPngMaker3(this);
|
// 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() {
|
public final Set<VisibilityModifier> getHides() {
|
||||||
return Collections.unmodifiableSet(hides);
|
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,
|
final Link result = new Link(cl2, cl1, getType().getInversed(), label, length, qualifier2, qualifier1,
|
||||||
labeldistance, labelangle, specificColor);
|
labeldistance, labelangle, specificColor);
|
||||||
result.inverted = true;
|
result.inverted = !this.inverted;
|
||||||
result.port1 = this.port2;
|
result.port1 = this.port2;
|
||||||
result.port2 = this.port1;
|
result.port2 = this.port1;
|
||||||
|
result.url = this.url;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ public class EntityFactory {
|
|||||||
final LongCode longCode = getLongCode(code, namespaceSeparator);
|
final LongCode longCode = getLongCode(code, namespaceSeparator);
|
||||||
final EntityImpl result = new EntityImpl(this, code, bodier, parentContainer, entityType, longCode,
|
final EntityImpl result = new EntityImpl(this, code, bodier, parentContainer, entityType, longCode,
|
||||||
namespaceSeparator, rawLayout);
|
namespaceSeparator, rawLayout);
|
||||||
|
bodier.setLeaf(result);
|
||||||
result.setDisplay(display);
|
result.setDisplay(display);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,12 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.webp.VP8Decoder;
|
|
||||||
|
|
||||||
public class Dedication {
|
public class Dedication {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
@ -73,13 +72,21 @@ public class Dedication {
|
|||||||
|
|
||||||
public BufferedImage getBufferedImage(String keepLetter) {
|
public BufferedImage getBufferedImage(String keepLetter) {
|
||||||
try {
|
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 InputStream is = getInputStream(keepLetter);
|
||||||
final ImageInputStream iis = ImageIO.createImageInputStream(is);
|
final ImageInputStream iis = ImageIO.createImageInputStream(is);
|
||||||
final VP8Decoder vp8Decoder = new VP8Decoder();
|
decodeFrame.invoke(vp8Decoder, iis);
|
||||||
vp8Decoder.decodeFrame(iis, false);
|
// vp8Decoder.decodeFrame(iis);
|
||||||
iis.close();
|
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) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ import net.sourceforge.plantuml.cucadiagram.IEntity;
|
|||||||
import net.sourceforge.plantuml.cucadiagram.ILeaf;
|
import net.sourceforge.plantuml.cucadiagram.ILeaf;
|
||||||
import net.sourceforge.plantuml.cucadiagram.LeafType;
|
import net.sourceforge.plantuml.cucadiagram.LeafType;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Link;
|
import net.sourceforge.plantuml.cucadiagram.Link;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.LinkArrow;
|
||||||
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
|
import net.sourceforge.plantuml.cucadiagram.LinkDecor;
|
||||||
import net.sourceforge.plantuml.cucadiagram.LinkType;
|
import net.sourceforge.plantuml.cucadiagram.LinkType;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||||
@ -209,6 +210,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
|
|||||||
private String firstLabel;
|
private String firstLabel;
|
||||||
private String secondLabel;
|
private String secondLabel;
|
||||||
private String labelLink;
|
private String labelLink;
|
||||||
|
private LinkArrow linkArrow = LinkArrow.NONE;
|
||||||
|
|
||||||
Labels(RegexResult arg) {
|
Labels(RegexResult arg) {
|
||||||
firstLabel = arg.get("LABEL1", 0);
|
firstLabel = arg.get("LABEL1", 0);
|
||||||
@ -220,6 +222,27 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
labelLink = StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(labelLink);
|
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(),
|
Link link = new Link(cl1, cl2, linkType, Display.getWithNewlines(labels.labelLink), queue.length(),
|
||||||
labels.firstLabel, labels.secondLabel, diagram.getLabeldistance(), diagram.getLabelangle());
|
labels.firstLabel, labels.secondLabel, diagram.getLabeldistance(), diagram.getLabelangle());
|
||||||
|
link.setLinkArrow(labels.linkArrow);
|
||||||
if (dir == Direction.LEFT || dir == Direction.UP) {
|
if (dir == Direction.LEFT || dir == Direction.UP) {
|
||||||
link = link.getInv();
|
link = link.getInv();
|
||||||
}
|
}
|
||||||
|
@ -364,6 +364,10 @@ public class EpsGraphics {
|
|||||||
appendColor(fillcolor);
|
appendColor(fillcolor);
|
||||||
epsRectangleInternal(x, y, width, height, rx, ry, true);
|
epsRectangleInternal(x, y, width, height, rx, ry, true);
|
||||||
append("closepath eofill", true);
|
append("closepath eofill", true);
|
||||||
|
if (dashSpace != 0 && dashVisible != 0) {
|
||||||
|
append("[] 0 setdash", true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
@ -371,6 +375,9 @@ public class EpsGraphics {
|
|||||||
appendColor(color);
|
appendColor(color);
|
||||||
epsRectangleInternal(x, y, width, height, rx, ry, false);
|
epsRectangleInternal(x, y, width, height, rx, ry, false);
|
||||||
append("closepath stroke", true);
|
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) {
|
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)
|
append(format(width) + " " + format(height) + " " + format(x) + " " + format(y) + " " + format((rx + ry) / 2)
|
||||||
+ " roundrect", true);
|
+ " roundrect", true);
|
||||||
roundrectUsed = true;
|
roundrectUsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void simpleRectangle(double x, double y, double width, double height, boolean fill) {
|
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) {
|
if ((dashSpace == 0 && dashVisible == 0) || fill) {
|
||||||
append(format(width) + " " + format(height) + " " + format(x) + " " + format(y) + " simplerect", true);
|
append(format(width) + " " + format(height) + " " + format(x) + " " + format(y) + " simplerect", true);
|
||||||
simplerectUsed = true;
|
simplerectUsed = true;
|
||||||
} else {
|
// } else {
|
||||||
epsVLine(y, x, x + width);
|
// epsVLine(y, x, x + width);
|
||||||
epsVLine(y + height, x, x + width);
|
// epsVLine(y + height, x, x + width);
|
||||||
epsHLine(x, y, y + height);
|
// epsHLine(x, y, y + height);
|
||||||
epsHLine(x + width, 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",
|
"Fbzrgvzrf jr pbzr ynfg ohg jr qvq bhe orfg",
|
||||||
"Vs lbh frr fbzrguvat, fnl fbzrguvat",
|
"Vs lbh frr fbzrguvat, fnl fbzrguvat",
|
||||||
"Va gurbel gurer vf ab qvssrerapr orgjrra gurbel naq cenpgvpr. Ohg, va cenpgvpr, gurer vf.",
|
"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",
|
"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",
|
"Jr nyy zhfg yrnea sebz fznyy zvfsbeghar, pbhag gur oyrffvatf gung ner erny",
|
||||||
"Cercner Guerr Frnyrq Rairybcrf...",
|
"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",
|
"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.",
|
"Lbh xabj jung fhecevfrq zr gur zbfg? Vg jnfa'g zrrgvat gurz. Vg jnf zrrgvat lbh.",
|
||||||
"Va jne gurer ner ab jvaaref, bayl jvqbjf",
|
"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() {
|
private QuoteUtils() {
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.ColorParam;
|
|||||||
import net.sourceforge.plantuml.FontParam;
|
import net.sourceforge.plantuml.FontParam;
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
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.cucadiagram.Stereotype;
|
||||||
import net.sourceforge.plantuml.svek.RoundedContainer;
|
import net.sourceforge.plantuml.svek.RoundedContainer;
|
||||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
@ -54,7 +54,7 @@ public class SkinParameter {
|
|||||||
|
|
||||||
public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground,
|
public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground,
|
||||||
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
|
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
|
||||||
RoundParam.component);
|
CornerParam.component);
|
||||||
|
|
||||||
public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground,
|
public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground,
|
||||||
ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE);
|
ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE);
|
||||||
@ -76,7 +76,7 @@ public class SkinParameter {
|
|||||||
|
|
||||||
public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground,
|
public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground,
|
||||||
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
|
ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder,
|
||||||
RoundParam.component);
|
CornerParam.component);
|
||||||
|
|
||||||
public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground,
|
public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground,
|
||||||
ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE);
|
ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE);
|
||||||
@ -90,12 +90,12 @@ public class SkinParameter {
|
|||||||
public static final SkinParameter PACKAGE = new SkinParameter("PACKAGE", ColorParam.packageBackground,
|
public static final SkinParameter PACKAGE = new SkinParameter("PACKAGE", ColorParam.packageBackground,
|
||||||
ColorParam.packageBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE);
|
ColorParam.packageBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE);
|
||||||
|
|
||||||
public static final SkinParameter CARD = new SkinParameter("CARD", ColorParam.rectangleBackground,
|
public static final SkinParameter CARD = new SkinParameter("CARD", ColorParam.cardBackground,
|
||||||
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
|
ColorParam.cardBorder, FontParam.CARD, FontParam.CARD_STEREOTYPE);
|
||||||
|
|
||||||
public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground,
|
public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground,
|
||||||
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder,
|
ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder,
|
||||||
RoundParam.rectangle);
|
CornerParam.rectangle);
|
||||||
|
|
||||||
public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground,
|
public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground,
|
||||||
ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
|
ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE);
|
||||||
@ -124,10 +124,10 @@ public class SkinParameter {
|
|||||||
private final FontParam fontParamStereotype;
|
private final FontParam fontParamStereotype;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final LineParam lineParam;
|
private final LineParam lineParam;
|
||||||
private final RoundParam roundParam;
|
private final CornerParam roundParam;
|
||||||
|
|
||||||
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
|
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.name = name;
|
||||||
this.colorParamBack = colorParamBack;
|
this.colorParamBack = colorParamBack;
|
||||||
this.colorParamBorder = colorParamBorder;
|
this.colorParamBorder = colorParamBorder;
|
||||||
@ -139,7 +139,7 @@ public class SkinParameter {
|
|||||||
|
|
||||||
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
|
private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam,
|
||||||
FontParam fontParamStereotype) {
|
FontParam fontParamStereotype) {
|
||||||
this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, RoundParam.DEFAULT);
|
this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, CornerParam.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUpperCaseName() {
|
public String getUpperCaseName() {
|
||||||
@ -169,6 +169,10 @@ public class SkinParameter {
|
|||||||
return skinParam.getRoundCorner(roundParam, stereotype);
|
return skinParam.getRoundCorner(roundParam, stereotype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getDiagonalCorner(ISkinParam skinParam, Stereotype stereotype) {
|
||||||
|
return skinParam.getDiagonalCorner(roundParam, stereotype);
|
||||||
|
}
|
||||||
|
|
||||||
public UStroke getStroke(ISkinParam skinParam, Stereotype stereotype) {
|
public UStroke getStroke(ISkinParam skinParam, Stereotype stereotype) {
|
||||||
UStroke result = null;
|
UStroke result = null;
|
||||||
if (lineParam != null) {
|
if (lineParam != null) {
|
||||||
|
@ -48,18 +48,17 @@ public class SymbolContext {
|
|||||||
private final boolean shadowing;
|
private final boolean shadowing;
|
||||||
private final double deltaShadow;
|
private final double deltaShadow;
|
||||||
private final double roundCorner;
|
private final double roundCorner;
|
||||||
|
private final double diagonalCorner;
|
||||||
|
|
||||||
private SymbolContext(HtmlColor backColor, HtmlColor foreColor, UStroke stroke, boolean shadowing,
|
private SymbolContext(HtmlColor backColor, HtmlColor foreColor, UStroke stroke, boolean shadowing,
|
||||||
double deltaShadow, double roundCorner) {
|
double deltaShadow, double roundCorner, double diagonalCorner) {
|
||||||
this.backColor = backColor;
|
this.backColor = backColor;
|
||||||
this.foreColor = foreColor;
|
this.foreColor = foreColor;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.shadowing = shadowing;
|
this.shadowing = shadowing;
|
||||||
this.deltaShadow = deltaShadow;
|
this.deltaShadow = deltaShadow;
|
||||||
this.roundCorner = roundCorner;
|
this.roundCorner = roundCorner;
|
||||||
// if (backColor instanceof HtmlColorTransparent) {
|
this.diagonalCorner = diagonalCorner;
|
||||||
// throw new UnsupportedOperationException();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,37 +84,37 @@ public class SymbolContext {
|
|||||||
|
|
||||||
public SymbolContext transparentBackColorToNull() {
|
public SymbolContext transparentBackColorToNull() {
|
||||||
if (backColor instanceof HtmlColorTransparent) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SymbolContext(HtmlColor backColor, HtmlColor foreColor) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
public SymbolContext withCorner(double roundCorner, double diagonalCorner) {
|
||||||
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner);
|
return new SymbolContext(backColor, foreColor, stroke, shadowing, deltaShadow, roundCorner, diagonalCorner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HtmlColor getBackColor() {
|
public HtmlColor getBackColor() {
|
||||||
@ -142,4 +141,8 @@ public class SymbolContext {
|
|||||||
return roundCorner;
|
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.Dimension2DDouble;
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
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.cucadiagram.Display;
|
||||||
import net.sourceforge.plantuml.posimo.Positionable;
|
import net.sourceforge.plantuml.posimo.Positionable;
|
||||||
import net.sourceforge.plantuml.posimo.PositionableImpl;
|
import net.sourceforge.plantuml.posimo.PositionableImpl;
|
||||||
@ -82,7 +82,7 @@ public class TextBlockUtils {
|
|||||||
if (borderColor == null) {
|
if (borderColor == null) {
|
||||||
borderColor = HtmlColorUtils.BLACK;
|
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);
|
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 java.awt.geom.Dimension2D;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.Shadowable;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
|
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UPath;
|
||||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
@ -64,14 +66,30 @@ class USymbolRect extends USymbol {
|
|||||||
return skinParameter;
|
return skinParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawRect(UGraphic ug, double width, double height, boolean shadowing, double roundCorner) {
|
private void drawRect(UGraphic ug, double width, double height, boolean shadowing, double roundCorner,
|
||||||
final URectangle shape = new URectangle(width, height, roundCorner, roundCorner);
|
double diagonalCorner) {
|
||||||
|
final Shadowable shape = diagonalCorner > 0 ? getDiagonalShape(width, height, diagonalCorner) : new URectangle(
|
||||||
|
width, height, roundCorner, roundCorner);
|
||||||
if (shadowing) {
|
if (shadowing) {
|
||||||
shape.setDeltaShadow(3.0);
|
shape.setDeltaShadow(3.0);
|
||||||
}
|
}
|
||||||
ug.draw(shape);
|
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() {
|
private Margin getMargin() {
|
||||||
return new Margin(10, 10, 10, 10);
|
return new Margin(10, 10, 10, 10);
|
||||||
}
|
}
|
||||||
@ -86,7 +104,7 @@ class USymbolRect extends USymbol {
|
|||||||
ug = UGraphicStencil.create(ug, getRectangleStencil(dim), new UStroke());
|
ug = UGraphicStencil.create(ug, getRectangleStencil(dim), new UStroke());
|
||||||
ug = symbolContext.apply(ug);
|
ug = symbolContext.apply(ug);
|
||||||
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
|
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
|
||||||
symbolContext.getRoundCorner());
|
symbolContext.getRoundCorner(), symbolContext.getDiagonalCorner());
|
||||||
final Margin margin = getMargin();
|
final Margin margin = getMargin();
|
||||||
final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, stereotypeAlignement);
|
final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, stereotypeAlignement);
|
||||||
tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1())));
|
tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1())));
|
||||||
@ -108,7 +126,7 @@ class USymbolRect extends USymbol {
|
|||||||
final Dimension2D dim = calculateDimension(ug.getStringBounder());
|
final Dimension2D dim = calculateDimension(ug.getStringBounder());
|
||||||
ug = symbolContext.apply(ug);
|
ug = symbolContext.apply(ug);
|
||||||
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
|
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
|
||||||
symbolContext.getRoundCorner());
|
symbolContext.getRoundCorner(), 0);
|
||||||
final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder());
|
final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder());
|
||||||
final double posStereoX;
|
final double posStereoX;
|
||||||
final double posStereoY;
|
final double posStereoY;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.sourceforge.plantuml.jasic;
|
package net.sourceforge.plantuml.jasic;
|
||||||
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -12,101 +11,106 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This defines a single class that contains an entire interpreter for a
|
Jasic uses the MIT License:
|
||||||
* language very similar to the original BASIC. Everything is here (albeit in
|
|
||||||
* very simplified form): tokenizing, parsing, and interpretation. The file is
|
Copyright (c) 2010 Robert Nystrom
|
||||||
* 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
* through the entire process of loading and running a program.
|
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:
|
* Comments start with ' and proceed to the end of the line:
|
||||||
*
|
*
|
||||||
* print "hi there" ' this is a comment
|
* print "hi there" ' this is a comment
|
||||||
*
|
*
|
||||||
* Numbers and strings are supported. Strings should be in "double quotes", and
|
* Numbers and strings are supported. Strings should be in "double quotes", and only positive integers can be parsed
|
||||||
* only positive integers can be parsed (though numbers are double internally).
|
* (though numbers are double internally).
|
||||||
*
|
*
|
||||||
* Variables are identified by name which must start with a letter and can
|
* Variables are identified by name which must start with a letter and can contain letters or numbers. Case is
|
||||||
* contain letters or numbers. Case is significant for names and keywords.
|
* significant for names and keywords.
|
||||||
*
|
*
|
||||||
* Each statement is on its own line. Optionally, a line may have a label before
|
* Each statement is on its own line. Optionally, a line may have a label before the statement. A label is a name that
|
||||||
* the statement. A label is a name that ends with a colon:
|
* ends with a colon:
|
||||||
*
|
*
|
||||||
* foo:
|
* foo:
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* The following statements are supported:
|
* The following statements are supported:
|
||||||
*
|
*
|
||||||
* <name> = <expression>
|
* <name> = <expression> Evaluates the expression and assigns the result to the given named variable. All variables are
|
||||||
* Evaluates the expression and assigns the result to the given named
|
* globally scoped.
|
||||||
* variable. All variables are globally scoped.
|
|
||||||
*
|
*
|
||||||
* pi = (314159 / 10000)
|
* pi = (314159 / 10000)
|
||||||
*
|
*
|
||||||
* print <expression>
|
* print <expression> Evaluates the expression and prints the result.
|
||||||
* Evaluates the expression and prints the result.
|
|
||||||
*
|
*
|
||||||
* print "hello, " + "world"
|
* print "hello, " + "world"
|
||||||
*
|
*
|
||||||
* input <name>
|
* input <name> Reads in a line of input from the user and stores it in the variable with the given name.
|
||||||
* Reads in a line of input from the user and stores it in the variable with
|
|
||||||
* the given name.
|
|
||||||
*
|
*
|
||||||
* input guess
|
* input guess
|
||||||
*
|
*
|
||||||
* goto <label>
|
* goto <label> Jumps to the statement after the label with the given name.
|
||||||
* Jumps to the statement after the label with the given name.
|
|
||||||
*
|
*
|
||||||
* goto loop
|
* goto loop
|
||||||
*
|
*
|
||||||
* if <expression> then <label>
|
* if <expression> then <label> Evaluates the expression. If it evaluates to a non-zero number, then jumps to the
|
||||||
* Evaluates the expression. If it evaluates to a non-zero number, then
|
* statement after the given label.
|
||||||
* jumps to the statement after the given label.
|
|
||||||
*
|
*
|
||||||
* if a < b then dosomething
|
* if a < b then dosomething
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* The following expressions are supported:
|
* The following expressions are supported:
|
||||||
*
|
*
|
||||||
* <expression> = <expression>
|
* <expression> = <expression> Evaluates to 1 if the two expressions are equal, 0 otherwise.
|
||||||
* Evaluates to 1 if the two expressions are equal, 0 otherwise.
|
|
||||||
*
|
*
|
||||||
* <expression> + <expression>
|
* <expression> + <expression> If the left-hand expression is a number, then adds the two expressions, otherwise
|
||||||
* If the left-hand expression is a number, then adds the two expressions,
|
* concatenates the two strings.
|
||||||
* otherwise concatenates the two strings.
|
|
||||||
*
|
*
|
||||||
* <expression> - <expression>
|
* <expression> - <expression> <expression> * <expression> <expression> / <expression> <expression> < <expression>
|
||||||
* <expression> * <expression>
|
* <expression> > <expression> You can figure it out.
|
||||||
* <expression> / <expression>
|
|
||||||
* <expression> < <expression>
|
|
||||||
* <expression> > <expression>
|
|
||||||
* You can figure it out.
|
|
||||||
*
|
*
|
||||||
* <name>
|
* <name> A name in an expression simply returns the value of the variable with that name. If the variable was never
|
||||||
* A name in an expression simply returns the value of the variable with
|
* set, it defaults to 0.
|
||||||
* 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
|
* All binary operators have the same precedence. Sorry, I had to cut corners somewhere.
|
||||||
* somewhere.
|
|
||||||
*
|
*
|
||||||
* To keep things simple, I've omitted some stuff or hacked things a bit. When
|
* To keep things simple, I've omitted some stuff or hacked things a bit. When possible, I'll leave a "HACK" note there
|
||||||
* possible, I'll leave a "HACK" note there explaining what and why. If you
|
* explaining what and why. If you make your own interpreter, you'll want to address those.
|
||||||
* make your own interpreter, you'll want to address those.
|
|
||||||
*
|
*
|
||||||
* @author Bob Nystrom
|
* @author Bob Nystrom
|
||||||
*/
|
*/
|
||||||
public class Jasic {
|
public class Jasic {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the interpreter as a command-line app. Takes one argument: a path
|
* Runs the interpreter as a command-line app. Takes one argument: a path to a script file to load and run. The
|
||||||
* to a script file to load and run. The script should contain one
|
* script should contain one statement per line.
|
||||||
* statement per line.
|
|
||||||
*
|
*
|
||||||
* @param args Command-line arguments.
|
* @param args
|
||||||
|
* Command-line arguments.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Just show the usage and quit if a script wasn't provided.
|
// Just show the usage and quit if a script wasn't provided.
|
||||||
@ -127,9 +131,8 @@ public class Jasic {
|
|||||||
// Tokenizing (lexing) -----------------------------------------------------
|
// Tokenizing (lexing) -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function takes a script as a string of characters and chunks it into
|
* This function takes a script as a string of characters and chunks it into a sequence of tokens. Each token is a
|
||||||
* a sequence of tokens. Each token is a meaningful unit of program, like a
|
* meaningful unit of program, like a variable name, a number, a string, or an operator.
|
||||||
* variable name, a number, a string, or an operator.
|
|
||||||
*/
|
*/
|
||||||
private static List<Token> tokenize(String source) {
|
private static List<Token> tokenize(String source) {
|
||||||
List<Token> tokens = new ArrayList<Token>();
|
List<Token> tokens = new ArrayList<Token>();
|
||||||
@ -139,11 +142,9 @@ public class Jasic {
|
|||||||
|
|
||||||
// Many tokens are a single character, like operators and ().
|
// Many tokens are a single character, like operators and ().
|
||||||
String charTokens = "\n=+-*/<>()";
|
String charTokens = "\n=+-*/<>()";
|
||||||
TokenType[] tokenTypes = { TokenType.LINE, TokenType.EQUALS,
|
TokenType[] tokenTypes = { TokenType.LINE, TokenType.EQUALS, TokenType.OPERATOR, TokenType.OPERATOR,
|
||||||
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR,
|
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR, TokenType.LEFT_PAREN,
|
||||||
TokenType.OPERATOR, TokenType.OPERATOR, TokenType.OPERATOR,
|
TokenType.RIGHT_PAREN };
|
||||||
TokenType.LEFT_PAREN, TokenType.RIGHT_PAREN
|
|
||||||
};
|
|
||||||
|
|
||||||
// Scan through the code one character at a time, building up the list
|
// Scan through the code one character at a time, building up the list
|
||||||
// of tokens.
|
// of tokens.
|
||||||
@ -152,8 +153,7 @@ public class Jasic {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case DEFAULT:
|
case DEFAULT:
|
||||||
if (charTokens.indexOf(c) != -1) {
|
if (charTokens.indexOf(c) != -1) {
|
||||||
tokens.add(new Token(Character.toString(c),
|
tokens.add(new Token(Character.toString(c), tokenTypes[charTokens.indexOf(c)]));
|
||||||
tokenTypes[charTokens.indexOf(c)]));
|
|
||||||
} else if (Character.isLetter(c)) {
|
} else if (Character.isLetter(c)) {
|
||||||
token += c;
|
token += c;
|
||||||
state = TokenizeState.WORD;
|
state = TokenizeState.WORD;
|
||||||
@ -223,22 +223,18 @@ public class Jasic {
|
|||||||
// Token data --------------------------------------------------------------
|
// Token data --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This defines the different kinds of tokens or meaningful chunks of code
|
* This defines the different kinds of tokens or meaningful chunks of code that the parser knows how to consume.
|
||||||
* that the parser knows how to consume. These let us distinguish, for
|
* These let us distinguish, for example, between a string "foo" and a variable named "foo".
|
||||||
* example, between a string "foo" and a variable named "foo".
|
|
||||||
*
|
*
|
||||||
* HACK: A typical tokenizer would actually have unique token types for
|
* HACK: A typical tokenizer would actually have unique token types for each keyword (print, goto, etc.) so that the
|
||||||
* each keyword (print, goto, etc.) so that the parser doesn't have to look
|
* parser doesn't have to look at the names, but Jasic is a little more crude.
|
||||||
* at the names, but Jasic is a little more crude.
|
|
||||||
*/
|
*/
|
||||||
private enum TokenType {
|
private enum TokenType {
|
||||||
WORD, NUMBER, STRING, LABEL, LINE,
|
WORD, NUMBER, STRING, LABEL, LINE, EQUALS, OPERATOR, LEFT_PAREN, RIGHT_PAREN, EOF
|
||||||
EQUALS, OPERATOR, LEFT_PAREN, RIGHT_PAREN, EOF
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a single meaningful chunk of code. It is created by the tokenizer
|
* This is a single meaningful chunk of code. It is created by the tokenizer and consumed by the parser.
|
||||||
* and consumed by the parser.
|
|
||||||
*/
|
*/
|
||||||
private static class Token {
|
private static class Token {
|
||||||
public Token(String text, TokenType type) {
|
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
|
* This defines the different states the tokenizer can be in while it's scanning through the source code. Tokenizers
|
||||||
* scanning through the source code. Tokenizers are state machines, which
|
* are state machines, which means the only data they need to store is where they are in the source code and this
|
||||||
* means the only data they need to store is where they are in the source
|
* one "state" or mode value.
|
||||||
* code and this one "state" or mode value.
|
|
||||||
*
|
*
|
||||||
* One of the main differences between tokenizing and parsing is this
|
* One of the main differences between tokenizing and parsing is this regularity. Because the tokenizer stores only
|
||||||
* regularity. Because the tokenizer stores only this one state value, it
|
* this one state value, it can't handle nesting (which would require also storing a number to identify how deeply
|
||||||
* can't handle nesting (which would require also storing a number to
|
* nested you are). The parser is able to handle that.
|
||||||
* identify how deeply nested you are). The parser is able to handle that.
|
|
||||||
*/
|
*/
|
||||||
private enum TokenizeState {
|
private enum TokenizeState {
|
||||||
DEFAULT, WORD, NUMBER, STRING, COMMENT
|
DEFAULT, WORD, NUMBER, STRING, COMMENT
|
||||||
@ -268,14 +262,13 @@ public class Jasic {
|
|||||||
// Parsing -----------------------------------------------------------------
|
// Parsing -----------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This defines the Jasic parser. The parser takes in a sequence of tokens
|
* This defines the Jasic parser. The parser takes in a sequence of tokens and generates an abstract syntax tree.
|
||||||
* and generates an abstract syntax tree. This is the nested data structure
|
* This is the nested data structure that represents the series of statements, and the expressions (which can nest
|
||||||
* that represents the series of statements, and the expressions (which can
|
* arbitrarily deeply) that they evaluate. In technical terms, what we have is a recursive descent parser, the
|
||||||
* nest arbitrarily deeply) that they evaluate. In technical terms, what we
|
* simplest kind to hand-write.
|
||||||
* 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
|
* As a side-effect, this phase also stores off the line numbers for each label in the program. It's a bit gross,
|
||||||
* label in the program. It's a bit gross, but it works.
|
* but it works.
|
||||||
*/
|
*/
|
||||||
private class Parser {
|
private class Parser {
|
||||||
public Parser(List<Token> tokens) {
|
public Parser(List<Token> tokens) {
|
||||||
@ -284,12 +277,11 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The top-level function to start parsing. This will keep consuming
|
* The top-level function to start parsing. This will keep consuming tokens and routing to the other parse
|
||||||
* tokens and routing to the other parse functions for the different
|
* functions for the different grammar syntax until we run out of code to parse.
|
||||||
* grammar syntax until we run out of code to parse.
|
|
||||||
*
|
*
|
||||||
* @param labels A map of label names to statement indexes. The
|
* @param labels
|
||||||
* parser will fill this in as it scans the code.
|
* 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.
|
* @return The list of parsed statements.
|
||||||
*/
|
*/
|
||||||
public List<Statement> parse(Map<String, Integer> labels) {
|
public List<Statement> parse(Map<String, Integer> labels) {
|
||||||
@ -297,7 +289,8 @@ public class Jasic {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Ignore empty lines.
|
// Ignore empty lines.
|
||||||
while (match(TokenType.LINE));
|
while (match(TokenType.LINE))
|
||||||
|
;
|
||||||
|
|
||||||
if (match(TokenType.LABEL)) {
|
if (match(TokenType.LABEL)) {
|
||||||
// Mark the index of the statement after the label.
|
// Mark the index of the statement after the label.
|
||||||
@ -309,17 +302,16 @@ public class Jasic {
|
|||||||
} else if (match("print")) {
|
} else if (match("print")) {
|
||||||
statements.add(new PrintStatement(expression()));
|
statements.add(new PrintStatement(expression()));
|
||||||
} else if (match("input")) {
|
} else if (match("input")) {
|
||||||
statements.add(new InputStatement(
|
statements.add(new InputStatement(consume(TokenType.WORD).text));
|
||||||
consume(TokenType.WORD).text));
|
|
||||||
} else if (match("goto")) {
|
} else if (match("goto")) {
|
||||||
statements.add(new GotoStatement(
|
statements.add(new GotoStatement(consume(TokenType.WORD).text));
|
||||||
consume(TokenType.WORD).text));
|
|
||||||
} else if (match("if")) {
|
} else if (match("if")) {
|
||||||
Expression condition = expression();
|
Expression condition = expression();
|
||||||
consume("then");
|
consume("then");
|
||||||
String label = consume(TokenType.WORD).text;
|
String label = consume(TokenType.WORD).text;
|
||||||
statements.add(new IfThenStatement(condition, label));
|
statements.add(new IfThenStatement(condition, label));
|
||||||
} else break; // Unexpected token (likely EOF), so end.
|
} else
|
||||||
|
break; // Unexpected token (likely EOF), so end.
|
||||||
}
|
}
|
||||||
|
|
||||||
return statements;
|
return statements;
|
||||||
@ -330,9 +322,8 @@ public class Jasic {
|
|||||||
// noun() and verb().
|
// noun() and verb().
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a single expression. Recursive descent parsers start with the
|
* Parses a single expression. Recursive descent parsers start with the lowest-precedent term and moves towards
|
||||||
* lowest-precedent term and moves towards higher precedence. For Jasic,
|
* higher precedence. For Jasic, binary operators (+, -, etc.) are the lowest.
|
||||||
* binary operators (+, -, etc.) are the lowest.
|
|
||||||
*
|
*
|
||||||
* @return The parsed expression.
|
* @return The parsed expression.
|
||||||
*/
|
*/
|
||||||
@ -341,24 +332,16 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a series of binary operator expressions into a single
|
* Parses a series of binary operator expressions into a single expression. In Jasic, all operators have the
|
||||||
* expression. In Jasic, all operators have the same predecence and
|
* same predecence and associate left-to-right. That means it will interpret: 1 + 2 * 3 - 4 / 5 like: ((((1 + 2)
|
||||||
* associate left-to-right. That means it will interpret:
|
* * 3) - 4) / 5)
|
||||||
* 1 + 2 * 3 - 4 / 5
|
|
||||||
* like:
|
|
||||||
* ((((1 + 2) * 3) - 4) / 5)
|
|
||||||
*
|
*
|
||||||
* It works by building the expression tree one at a time. So, given
|
* It works by building the expression tree one at a time. So, given this code: 1 + 2 * 3, this will:
|
||||||
* this code: 1 + 2 * 3, this will:
|
|
||||||
*
|
*
|
||||||
* 1. Parse (1) as an atomic expression.
|
* 1. Parse (1) as an atomic expression. 2. See the (+) and start a new operator expression. 3. Parse (2) as an
|
||||||
* 2. See the (+) and start a new operator expression.
|
* atomic expression. 4. Build a (1 + 2) expression and replace (1) with it. 5. See the (*) and start a new
|
||||||
* 3. Parse (2) as an atomic expression.
|
* operator expression. 6. Parse (3) as an atomic expression. 7. Build a ((1 + 2) * 3) expression and replace (1
|
||||||
* 4. Build a (1 + 2) expression and replace (1) with it.
|
* + 2) with it. 8. Return the last expression built.
|
||||||
* 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.
|
* @return The parsed expression.
|
||||||
*/
|
*/
|
||||||
@ -366,8 +349,7 @@ public class Jasic {
|
|||||||
Expression expression = atomic();
|
Expression expression = atomic();
|
||||||
|
|
||||||
// Keep building operator expressions as long as we have operators.
|
// Keep building operator expressions as long as we have operators.
|
||||||
while (match(TokenType.OPERATOR) ||
|
while (match(TokenType.OPERATOR) || match(TokenType.EQUALS)) {
|
||||||
match(TokenType.EQUALS)) {
|
|
||||||
char operator = last(1).text.charAt(0);
|
char operator = last(1).text.charAt(0);
|
||||||
Expression right = atomic();
|
Expression right = atomic();
|
||||||
expression = new OperatorExpression(expression, operator, right);
|
expression = new OperatorExpression(expression, operator, right);
|
||||||
@ -377,9 +359,8 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an "atomic" expression. This is the highest level of
|
* Parses an "atomic" expression. This is the highest level of precedence and contains single literal tokens
|
||||||
* precedence and contains single literal tokens like 123 and "foo", as
|
* like 123 and "foo", as well as parenthesized expressions.
|
||||||
* well as parenthesized expressions.
|
|
||||||
*
|
*
|
||||||
* @return The parsed expression.
|
* @return The parsed expression.
|
||||||
*/
|
*/
|
||||||
@ -408,16 +389,19 @@ public class Jasic {
|
|||||||
// the token stream.
|
// the token stream.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes the next two tokens if they are the given type (in order).
|
* Consumes the next two tokens if they are the given type (in order). Consumes no tokens if either check fais.
|
||||||
* Consumes no tokens if either check fais.
|
|
||||||
*
|
*
|
||||||
* @param type1 Expected type of the next token.
|
* @param type1
|
||||||
* @param type2 Expected type of the subsequent token.
|
* Expected type of the next token.
|
||||||
|
* @param type2
|
||||||
|
* Expected type of the subsequent token.
|
||||||
* @return True if tokens were consumed.
|
* @return True if tokens were consumed.
|
||||||
*/
|
*/
|
||||||
private boolean match(TokenType type1, TokenType type2) {
|
private boolean match(TokenType type1, TokenType type2) {
|
||||||
if (get(0).type != type1) return false;
|
if (get(0).type != type1)
|
||||||
if (get(1).type != type2) return false;
|
return false;
|
||||||
|
if (get(1).type != type2)
|
||||||
|
return false;
|
||||||
position += 2;
|
position += 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -425,11 +409,13 @@ public class Jasic {
|
|||||||
/**
|
/**
|
||||||
* Consumes the next token if it's the given type.
|
* 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.
|
* @return True if the token was consumed.
|
||||||
*/
|
*/
|
||||||
private boolean match(TokenType type) {
|
private boolean match(TokenType type) {
|
||||||
if (get(0).type != type) return false;
|
if (get(0).type != type)
|
||||||
|
return false;
|
||||||
position++;
|
position++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -437,47 +423,52 @@ public class Jasic {
|
|||||||
/**
|
/**
|
||||||
* Consumes the next token if it's a word token with the given name.
|
* 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.
|
* @return True if the token was consumed.
|
||||||
*/
|
*/
|
||||||
private boolean match(String name) {
|
private boolean match(String name) {
|
||||||
if (get(0).type != TokenType.WORD) return false;
|
if (get(0).type != TokenType.WORD)
|
||||||
if (!get(0).text.equals(name)) return false;
|
return false;
|
||||||
|
if (!get(0).text.equals(name))
|
||||||
|
return false;
|
||||||
position++;
|
position++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes the next token if it's the given type. If not, throws an
|
* Consumes the next token if it's the given type. If not, throws an exception. This is for cases where the
|
||||||
* exception. This is for cases where the parser demands a token of a
|
* parser demands a token of a certain type in a certain position, for example a matching ) after an opening (.
|
||||||
* 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.
|
* @return The consumed token.
|
||||||
*/
|
*/
|
||||||
private Token consume(TokenType type) {
|
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++);
|
return tokens.get(position++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consumes the next token if it's a word with the given name. If not,
|
* Consumes the next token if it's a word with the given name. If not, throws an exception.
|
||||||
* 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.
|
* @return The consumed token.
|
||||||
*/
|
*/
|
||||||
private Token consume(String name) {
|
private Token consume(String name) {
|
||||||
if (!match(name)) throw new Error("Expected " + name + ".");
|
if (!match(name))
|
||||||
|
throw new Error("Expected " + name + ".");
|
||||||
return last(1);
|
return last(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a previously consumed token, indexing backwards. last(1) will
|
* Gets a previously consumed token, indexing backwards. last(1) will be the token just consumed, last(2) the
|
||||||
* be the token just consumed, last(2) the one before that, etc.
|
* 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.
|
* @return The consumed token.
|
||||||
*/
|
*/
|
||||||
private Token last(int offset) {
|
private Token last(int offset) {
|
||||||
@ -485,10 +476,11 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an unconsumed token, indexing forward. get(0) will be the next
|
* Gets an unconsumed token, indexing forward. get(0) will be the next token to be consumed, get(1) the one
|
||||||
* token to be consumed, get(1) the one after that, etc.
|
* 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.
|
* @return The yet-to-be-consumed token.
|
||||||
*/
|
*/
|
||||||
private Token get(int offset) {
|
private Token get(int offset) {
|
||||||
@ -513,29 +505,25 @@ public class Jasic {
|
|||||||
// separated out so that the AST us just a static data structure.
|
// separated out so that the AST us just a static data structure.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for a Jasic statement. The different supported statement
|
* Base interface for a Jasic statement. The different supported statement types like "print" and "goto" implement
|
||||||
* types like "print" and "goto" implement this.
|
* this.
|
||||||
*/
|
*/
|
||||||
public interface Statement {
|
public interface Statement {
|
||||||
/**
|
/**
|
||||||
* Statements implement this to actually perform whatever behavior the
|
* Statements implement this to actually perform whatever behavior the statement causes. "print" statements will
|
||||||
* statement causes. "print" statements will display text here, "goto"
|
* display text here, "goto" statements will change the current statement, etc.
|
||||||
* statements will change the current statement, etc.
|
|
||||||
*/
|
*/
|
||||||
void execute();
|
void execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for an expression. An expression is like a statement
|
* Base interface for an expression. An expression is like a statement except that it also returns a value when
|
||||||
* except that it also returns a value when executed. Expressions do not
|
* executed. Expressions do not appear at the top level in Jasic programs, but are used in many statements. For
|
||||||
* appear at the top level in Jasic programs, but are used in many
|
* example, the value printed by a "print" statement is an expression. Unlike statements, expressions can nest.
|
||||||
* statements. For example, the value printed by a "print" statement is an
|
|
||||||
* expression. Unlike statements, expressions can nest.
|
|
||||||
*/
|
*/
|
||||||
public interface Expression {
|
public interface Expression {
|
||||||
/**
|
/**
|
||||||
* Expression classes implement this to evaluate the expression and
|
* Expression classes implement this to evaluate the expression and return the value.
|
||||||
* return the value.
|
|
||||||
*
|
*
|
||||||
* @return The value of the calculated expression.
|
* @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
|
* A "print" statement evaluates an expression, converts the result to a string, and displays it to the user.
|
||||||
* string, and displays it to the user.
|
|
||||||
*/
|
*/
|
||||||
public class PrintStatement implements Statement {
|
public class PrintStatement implements Statement {
|
||||||
public PrintStatement(Expression expression) {
|
public PrintStatement(Expression expression) {
|
||||||
@ -559,8 +546,7 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An "input" statement reads input from the user and stores it in a
|
* An "input" statement reads input from the user and stores it in a variable.
|
||||||
* variable.
|
|
||||||
*/
|
*/
|
||||||
public class InputStatement implements Statement {
|
public class InputStatement implements Statement {
|
||||||
public InputStatement(String name) {
|
public InputStatement(String name) {
|
||||||
@ -587,8 +573,7 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An assignment statement evaluates an expression and stores the result in
|
* An assignment statement evaluates an expression and stores the result in a variable.
|
||||||
* a variable.
|
|
||||||
*/
|
*/
|
||||||
public class AssignStatement implements Statement {
|
public class AssignStatement implements Statement {
|
||||||
public AssignStatement(String name, Expression value) {
|
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
|
* An if then statement jumps execution to another place in the program, but only if an expression evaluates to
|
||||||
* only if an expression evaluates to something other than 0.
|
* something other than 0.
|
||||||
*/
|
*/
|
||||||
public class IfThenStatement implements Statement {
|
public class IfThenStatement implements Statement {
|
||||||
public IfThenStatement(Expression condition, String label) {
|
public IfThenStatement(Expression condition, String label) {
|
||||||
@ -645,8 +630,7 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variable expression evaluates to the current value stored in that
|
* A variable expression evaluates to the current value stored in that variable.
|
||||||
* variable.
|
|
||||||
*/
|
*/
|
||||||
public class VariableExpression implements Expression {
|
public class VariableExpression implements Expression {
|
||||||
public VariableExpression(String name) {
|
public VariableExpression(String name) {
|
||||||
@ -664,12 +648,10 @@ public class Jasic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An operator expression evaluates two expressions and then performs some
|
* An operator expression evaluates two expressions and then performs some arithmetic operation on the results.
|
||||||
* arithmetic operation on the results.
|
|
||||||
*/
|
*/
|
||||||
public class OperatorExpression implements Expression {
|
public class OperatorExpression implements Expression {
|
||||||
public OperatorExpression(Expression left, char operator,
|
public OperatorExpression(Expression left, char operator, Expression right) {
|
||||||
Expression right) {
|
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
@ -683,48 +665,37 @@ public class Jasic {
|
|||||||
case '=':
|
case '=':
|
||||||
// Coerce to the left argument's type, then compare.
|
// Coerce to the left argument's type, then compare.
|
||||||
if (leftVal instanceof NumberValue) {
|
if (leftVal instanceof NumberValue) {
|
||||||
return new NumberValue((leftVal.toNumber() ==
|
return new NumberValue((leftVal.toNumber() == rightVal.toNumber()) ? 1 : 0);
|
||||||
rightVal.toNumber()) ? 1 : 0);
|
|
||||||
} else {
|
} else {
|
||||||
return new NumberValue(leftVal.toString().equals(
|
return new NumberValue(leftVal.toString().equals(rightVal.toString()) ? 1 : 0);
|
||||||
rightVal.toString()) ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
case '+':
|
case '+':
|
||||||
// Addition if the left argument is a number, otherwise do
|
// Addition if the left argument is a number, otherwise do
|
||||||
// string concatenation.
|
// string concatenation.
|
||||||
if (leftVal instanceof NumberValue) {
|
if (leftVal instanceof NumberValue) {
|
||||||
return new NumberValue(leftVal.toNumber() +
|
return new NumberValue(leftVal.toNumber() + rightVal.toNumber());
|
||||||
rightVal.toNumber());
|
|
||||||
} else {
|
} else {
|
||||||
return new StringValue(leftVal.toString() +
|
return new StringValue(leftVal.toString() + rightVal.toString());
|
||||||
rightVal.toString());
|
|
||||||
}
|
}
|
||||||
case '-':
|
case '-':
|
||||||
return new NumberValue(leftVal.toNumber() -
|
return new NumberValue(leftVal.toNumber() - rightVal.toNumber());
|
||||||
rightVal.toNumber());
|
|
||||||
case '*':
|
case '*':
|
||||||
return new NumberValue(leftVal.toNumber() *
|
return new NumberValue(leftVal.toNumber() * rightVal.toNumber());
|
||||||
rightVal.toNumber());
|
|
||||||
case '/':
|
case '/':
|
||||||
return new NumberValue(leftVal.toNumber() /
|
return new NumberValue(leftVal.toNumber() / rightVal.toNumber());
|
||||||
rightVal.toNumber());
|
|
||||||
case '<':
|
case '<':
|
||||||
// Coerce to the left argument's type, then compare.
|
// Coerce to the left argument's type, then compare.
|
||||||
if (leftVal instanceof NumberValue) {
|
if (leftVal instanceof NumberValue) {
|
||||||
return new NumberValue((leftVal.toNumber() <
|
return new NumberValue((leftVal.toNumber() < rightVal.toNumber()) ? 1 : 0);
|
||||||
rightVal.toNumber()) ? 1 : 0);
|
|
||||||
} else {
|
} else {
|
||||||
return new NumberValue((leftVal.toString().compareTo(
|
return new NumberValue((leftVal.toString().compareTo(rightVal.toString()) < 0) ? 1 : 0);
|
||||||
rightVal.toString()) < 0) ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
case '>':
|
case '>':
|
||||||
// Coerce to the left argument's type, then compare.
|
// Coerce to the left argument's type, then compare.
|
||||||
if (leftVal instanceof NumberValue) {
|
if (leftVal instanceof NumberValue) {
|
||||||
return new NumberValue((leftVal.toNumber() >
|
return new NumberValue((leftVal.toNumber() > rightVal.toNumber()) ? 1 : 0);
|
||||||
rightVal.toNumber()) ? 1 : 0);
|
|
||||||
} else {
|
} else {
|
||||||
return new NumberValue((leftVal.toString().compareTo(
|
return new NumberValue((leftVal.toString().compareTo(rightVal.toString()) > 0) ? 1 : 0);
|
||||||
rightVal.toString()) > 0) ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error("Unknown operator.");
|
throw new Error("Unknown operator.");
|
||||||
@ -738,30 +709,25 @@ public class Jasic {
|
|||||||
// Value types -------------------------------------------------------------
|
// Value types -------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the base interface for a value. Values are the data that the
|
* This is the base interface for a value. Values are the data that the interpreter processes. They are what gets
|
||||||
* interpreter processes. They are what gets stored in variables, printed,
|
* stored in variables, printed, and operated on.
|
||||||
* and operated on.
|
|
||||||
*
|
*
|
||||||
* There is an implementation of this interface for each of the different
|
* There is an implementation of this interface for each of the different primitive types (really just double and
|
||||||
* primitive types (really just double and string) that Jasic supports.
|
* string) that Jasic supports. Wrapping them in a single Value interface lets Jasic be dynamically-typed and
|
||||||
* Wrapping them in a single Value interface lets Jasic be dynamically-typed
|
* convert between different representations as needed.
|
||||||
* and convert between different representations as needed.
|
|
||||||
*
|
*
|
||||||
* Note that Value extends Expression. This is a bit of a hack, but it lets
|
* Note that Value extends Expression. This is a bit of a hack, but it lets us use values (which are typically only
|
||||||
* us use values (which are typically only ever seen by the interpreter and
|
* ever seen by the interpreter and not the parser) as both runtime values, and as object representing literals in
|
||||||
* not the parser) as both runtime values, and as object representing
|
* code.
|
||||||
* literals in code.
|
|
||||||
*/
|
*/
|
||||||
public interface Value extends Expression {
|
public interface Value extends Expression {
|
||||||
/**
|
/**
|
||||||
* Value types override this to convert themselves to a string
|
* Value types override this to convert themselves to a string representation.
|
||||||
* representation.
|
|
||||||
*/
|
*/
|
||||||
String toString();
|
String toString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value types override this to convert themselves to a numeric
|
* Value types override this to convert themselves to a numeric representation.
|
||||||
* representation.
|
|
||||||
*/
|
*/
|
||||||
double toNumber();
|
double toNumber();
|
||||||
}
|
}
|
||||||
@ -774,9 +740,18 @@ public class Jasic {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() { return Double.toString(value); }
|
@Override
|
||||||
public double toNumber() { return value; }
|
public String toString() {
|
||||||
public Value evaluate() { return this; }
|
return Double.toString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double toNumber() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value evaluate() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private final double value;
|
private final double value;
|
||||||
}
|
}
|
||||||
@ -789,9 +764,18 @@ public class Jasic {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() { return value; }
|
@Override
|
||||||
public double toNumber() { return Double.parseDouble(value); }
|
public String toString() {
|
||||||
public Value evaluate() { return this; }
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double toNumber() {
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value evaluate() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
}
|
}
|
||||||
@ -799,9 +783,8 @@ public class Jasic {
|
|||||||
// Interpreter -------------------------------------------------------------
|
// Interpreter -------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Jasic instance. The instance stores the global state of
|
* Constructs a new Jasic instance. The instance stores the global state of the interpreter such as the values of
|
||||||
* the interpreter such as the values of all of the variables and the
|
* all of the variables and the current statement.
|
||||||
* current statement.
|
|
||||||
*/
|
*/
|
||||||
public Jasic() {
|
public Jasic() {
|
||||||
variables = new HashMap<String, Value>();
|
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
|
* This is where the magic happens. This runs the code through the parsing pipeline to generate the AST. Then it
|
||||||
* pipeline to generate the AST. Then it executes each statement. It keeps
|
* executes each statement. It keeps track of the current line in a member variable that the statement objects have
|
||||||
* track of the current line in a member variable that the statement objects
|
* access to. This lets "goto" and "if then" do flow control by simply setting the index of the current statement.
|
||||||
* 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
|
* In an interpreter that didn't mix the interpretation logic in with the AST node classes, this would be doing a
|
||||||
* AST node classes, this would be doing a lot more work.
|
* lot more work.
|
||||||
*
|
*
|
||||||
* @param source A string containing the source code of a .jas script to
|
* @param source
|
||||||
* interpret.
|
* A string containing the source code of a .jas script to interpret.
|
||||||
*/
|
*/
|
||||||
public void interpret(String source) {
|
public void interpret(String source) {
|
||||||
// Tokenize.
|
// Tokenize.
|
||||||
@ -851,10 +832,10 @@ public class Jasic {
|
|||||||
// Utility stuff -----------------------------------------------------------
|
// Utility stuff -----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the file from the given path and returns its contents as a single
|
* Reads the file from the given path and returns its contents as a single string.
|
||||||
* 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.
|
* @return The contents of the file or null if the load failed.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -863,8 +844,7 @@ public class Jasic {
|
|||||||
FileInputStream stream = new FileInputStream(path);
|
FileInputStream stream = new FileInputStream(path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStreamReader input = new InputStreamReader(stream,
|
InputStreamReader input = new InputStreamReader(stream, Charset.defaultCharset());
|
||||||
Charset.defaultCharset());
|
|
||||||
Reader reader = new BufferedReader(input);
|
Reader reader = new BufferedReader(input);
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
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 class ComplementClose implements ComplementPattern {
|
||||||
|
|
||||||
public IRegex toRegex(String suffix) {
|
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) {
|
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;
|
package net.sourceforge.plantuml.project3;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
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.RegexLeaf;
|
||||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||||
|
|
||||||
public class ComplementSeveralDays implements ComplementPattern {
|
public class ComplementSeveralDays implements ComplementPattern {
|
||||||
|
|
||||||
public IRegex toRegex(String suffix) {
|
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) {
|
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
|
||||||
final String days = arg.get("COMPLEMENT" + suffix, 0);
|
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;
|
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 year;
|
||||||
private final int dayOfMonth;
|
private final int dayOfMonth;
|
||||||
@ -64,6 +64,17 @@ public class DayAsDate implements Complement, Comparable<DayAsDate> {
|
|||||||
return "" + year + "/" + month + "/" + dayOfMonth;
|
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() {
|
public final int getDayOfMonth() {
|
||||||
return dayOfMonth;
|
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 interface GCalendar {
|
||||||
|
|
||||||
// public DayAsDate next(DayAsDate day);
|
|
||||||
|
|
||||||
public DayAsDate toDayAsDate(InstantDay day);
|
public DayAsDate toDayAsDate(InstantDay day);
|
||||||
|
|
||||||
public DayAsDate getStartingDate();
|
public DayAsDate getStartingDate();
|
||||||
|
|
||||||
|
public InstantDay fromDayAsDate(DayAsDate day);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,22 @@ public class GCalendarSimple implements GCalendar {
|
|||||||
|
|
||||||
public DayAsDate toDayAsDate(InstantDay day) {
|
public DayAsDate toDayAsDate(InstantDay day) {
|
||||||
DayAsDate result = start;
|
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();
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ public class GanttArrow implements UDrawable {
|
|||||||
|
|
||||||
private double getX(TaskInstant when, Direction direction) {
|
private double getX(TaskInstant when, Direction direction) {
|
||||||
final double x1 = timeScale.getStartingPosition(when.getInstantTheorical());
|
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) {
|
if (direction == Direction.LEFT) {
|
||||||
return x1;
|
return x1;
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,12 @@ package net.sourceforge.plantuml.project3;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -54,6 +57,7 @@ import net.sourceforge.plantuml.core.ImageData;
|
|||||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||||
|
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||||
import net.sourceforge.plantuml.graphic.HtmlColorSetSimple;
|
import net.sourceforge.plantuml.graphic.HtmlColorSetSimple;
|
||||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||||
import net.sourceforge.plantuml.graphic.IHtmlColorSet;
|
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.graphic.UDrawable;
|
||||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||||
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
|
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
|
|
||||||
public class GanttDiagram extends AbstractPSystem implements Subject {
|
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 Map<String, Task> byShortName = new HashMap<String, Task>();
|
||||||
private final List<GanttConstraint> constraints = new ArrayList<GanttConstraint>();
|
private final List<GanttConstraint> constraints = new ArrayList<GanttConstraint>();
|
||||||
private final IHtmlColorSet colorSet = new HtmlColorSetSimple();
|
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 GCalendar calendar;
|
||||||
|
|
||||||
private final Instant min = new InstantDay(0);
|
private final Instant min = new InstantDay(0);
|
||||||
@ -82,6 +90,34 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
return new DiagramDescription("(Project)");
|
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
|
@Override
|
||||||
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption, long seed)
|
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption, long seed)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@ -129,10 +165,33 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TimeScale getTimeScale() {
|
private TimeScale getTimeScale() {
|
||||||
|
if (calendar == null) {
|
||||||
return new TimeScaleBasic();
|
return new TimeScaleBasic();
|
||||||
|
}
|
||||||
|
return new TimeScaleBasic2(getCalendarSimple());
|
||||||
// return new TimeScaleWithoutWeekEnd(calendar);
|
// 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) {
|
private void drawConstraints(final UGraphic ug, TimeScale timeScale) {
|
||||||
for (GanttConstraint constraint : constraints) {
|
for (GanttConstraint constraint : constraints) {
|
||||||
constraint.getUDrawable(timeScale).drawU(ug);
|
constraint.getUDrawable(timeScale).drawU(ug);
|
||||||
@ -142,10 +201,10 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
|
|
||||||
private void drawTimeHeader(final UGraphic ug, TimeScale timeScale) {
|
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 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)).draw(new ULine(xmax - xmin, 0));
|
||||||
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(0, getHeaderHeight() - 3))
|
ug.apply(new UChangeColor(HtmlColorUtils.LIGHT_GRAY)).apply(new UTranslate(0, getHeaderHeight() - 3))
|
||||||
.draw(new ULine(xmax - xmin, 0));
|
.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) {
|
private final HtmlColor veryLightGray = new HtmlColorSetSimple().getColorIfValid("#E0E8E8");
|
||||||
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 double getHeaderHeight() {
|
private double getHeaderHeight() {
|
||||||
if (calendar != null) {
|
if (calendar != null) {
|
||||||
return 40;
|
return Y_WEEKDAY + Y_NUMDAY;
|
||||||
}
|
}
|
||||||
return 16;
|
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) {
|
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 width = text.calculateDimension(ug.getStringBounder()).getWidth();
|
||||||
final double delta = (x2 - x1) - width;
|
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) {
|
private void drawSimpleDayCounter(final UGraphic ug, TimeScale timeScale, final double yTotal) {
|
||||||
final ULine vbar = new ULine(0, yTotal);
|
final ULine vbar = new ULine(0, yTotal);
|
||||||
for (Instant i = min; i.compareTo(max.increment()) <= 0; i = i.increment()) {
|
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());
|
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
|
||||||
final double x1 = timeScale.getStartingPosition(i);
|
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 width = num.calculateDimension(ug.getStringBounder()).getWidth();
|
||||||
final double delta = (x2 - x1) - width;
|
final double delta = (x2 - x1) - width;
|
||||||
if (i.compareTo(max.increment()) < 0) {
|
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();
|
double y = getHeaderHeight();
|
||||||
for (Task task : tasks.values()) {
|
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);
|
task.setTaskDraw(draw);
|
||||||
y += draw.getHeight();
|
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;
|
return y;
|
||||||
}
|
}
|
||||||
@ -231,6 +327,9 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
// min = tasks.values().iterator().next().getStart();
|
// min = tasks.values().iterator().next().getStart();
|
||||||
max = tasks.values().iterator().next().getEnd();
|
max = tasks.values().iterator().next().getEnd();
|
||||||
for (Task task : tasks.values()) {
|
for (Task task : tasks.values()) {
|
||||||
|
if (task instanceof TaskSeparator) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final Instant start = task.getStart();
|
final Instant start = task.getStart();
|
||||||
final Instant end = task.getEnd();
|
final Instant end = task.getEnd();
|
||||||
// if (min.compareTo(start) > 0) {
|
// if (min.compareTo(start) > 0) {
|
||||||
@ -246,14 +345,20 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
for (Task task : tasks.values()) {
|
for (Task task : tasks.values()) {
|
||||||
final TaskDraw draw = task.getTaskDraw();
|
final TaskDraw draw = task.getTaskDraw();
|
||||||
draw.drawU(ug.apply(new UTranslate(0, draw.getY())));
|
draw.drawU(ug.apply(new UTranslate(0, draw.getY())));
|
||||||
draw.getTitle().drawU(
|
draw.drawTitle(ug.apply(new UTranslate(0, draw.getY())));
|
||||||
ug.apply(new UTranslate(timeScale.getStartingPosition(task.getStart().increment()), draw.getY())));
|
}
|
||||||
|
for (Resource res : resources.values()) {
|
||||||
|
final ResourceDraw draw = res.getResourceDraw();
|
||||||
|
draw.drawU(ug.apply(new UTranslate(0, draw.getY())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FontConfiguration getFontConfiguration() {
|
private FontConfiguration getFontConfiguration(int size) {
|
||||||
final UFont font = UFont.serif(10);
|
UFont font = UFont.serif(size);
|
||||||
return new FontConfiguration(font, HtmlColorUtils.LIGHT_GRAY, HtmlColorUtils.LIGHT_GRAY, false);
|
if (size > 10) {
|
||||||
|
font = font.bold();
|
||||||
|
}
|
||||||
|
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task getExistingTask(String id) {
|
public Task getExistingTask(String id) {
|
||||||
@ -268,7 +373,13 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
return tasks.get(code);
|
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) {
|
if (codeOrShortName == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
@ -283,15 +394,37 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
final TaskCode code = new TaskCode(codeOrShortName);
|
final TaskCode code = new TaskCode(codeOrShortName);
|
||||||
result = tasks.get(code);
|
result = tasks.get(code);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = new TaskImpl(code);
|
Task previous = null;
|
||||||
|
if (linkedToPrevious) {
|
||||||
|
previous = getLastCreatedTask();
|
||||||
|
}
|
||||||
|
result = new TaskImpl(code, getDefaultPlan());
|
||||||
tasks.put(code, result);
|
tasks.put(code, result);
|
||||||
if (byShortName != null) {
|
if (byShortName != null) {
|
||||||
byShortName.put(shortName, result);
|
byShortName.put(shortName, result);
|
||||||
}
|
}
|
||||||
|
if (previous != null) {
|
||||||
|
setTaskOrder(previous, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 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) {
|
private TaskCodeSimpleOrder getCanonicalOrder(int hierarchyHeader) {
|
||||||
final List<TaskCode> codes = new ArrayList<TaskCode>();
|
final List<TaskCode> codes = new ArrayList<TaskCode>();
|
||||||
for (TaskCode code : tasks.keySet()) {
|
for (TaskCode code : tasks.keySet()) {
|
||||||
@ -326,4 +459,44 @@ public class GanttDiagram extends AbstractPSystem implements Subject {
|
|||||||
return this.calendar.getStartingDate();
|
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 {
|
public class GanttDiagramFactory extends UmlDiagramFactory {
|
||||||
|
|
||||||
private List<SubjectPattern> subjects() {
|
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) {
|
public GanttDiagramFactory(DiagramType type) {
|
||||||
@ -68,15 +69,17 @@ public class GanttDiagramFactory extends UmlDiagramFactory {
|
|||||||
cmds.add(cmd);
|
cmds.add(cmd);
|
||||||
}
|
}
|
||||||
cmds.add(new CommandGanttArrow());
|
cmds.add(new CommandGanttArrow());
|
||||||
|
cmds.add(new CommandGanttArrow2());
|
||||||
|
cmds.add(new CommandSeparator());
|
||||||
|
|
||||||
cmds.add(new CommandScale());
|
cmds.add(new CommandScale());
|
||||||
|
cmds.add(new CommandPage());
|
||||||
// cmds.add(new CommandScaleWidthAndHeight());
|
// cmds.add(new CommandScaleWidthAndHeight());
|
||||||
// cmds.add(new CommandScaleWidthOrHeight());
|
// cmds.add(new CommandScaleWidthOrHeight());
|
||||||
// cmds.add(new CommandScaleMaxWidth());
|
// cmds.add(new CommandScaleMaxWidth());
|
||||||
// cmds.add(new CommandScaleMaxHeight());
|
// cmds.add(new CommandScaleMaxHeight());
|
||||||
// cmds.add(new CommandScaleMaxWidthAndHeight());
|
// cmds.add(new CommandScaleMaxWidthAndHeight());
|
||||||
|
|
||||||
|
|
||||||
return cmds;
|
return cmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +37,6 @@ package net.sourceforge.plantuml.project3;
|
|||||||
|
|
||||||
public interface Instant extends Value, Comparable<Instant> {
|
public interface Instant extends Value, Comparable<Instant> {
|
||||||
|
|
||||||
public Instant add(Duration duration);
|
|
||||||
|
|
||||||
public Instant sub(Duration duration);
|
|
||||||
|
|
||||||
public Instant increment();
|
public Instant increment();
|
||||||
|
|
||||||
public Instant decrement();
|
public Instant decrement();
|
||||||
|
@ -48,16 +48,6 @@ public class InstantDay implements Instant {
|
|||||||
return "(day +" + numDay + ")";
|
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() {
|
public InstantDay increment() {
|
||||||
return new InstantDay(numDay + 1);
|
return new InstantDay(numDay + 1);
|
||||||
}
|
}
|
||||||
|
@ -35,21 +35,8 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.project3;
|
package net.sourceforge.plantuml.project3;
|
||||||
|
|
||||||
public class DurationDay implements Duration {
|
public interface Load extends Value, Complement, LoadPlanable {
|
||||||
|
|
||||||
private final int days;
|
int getFullLoad();
|
||||||
|
|
||||||
public DurationDay(int days) {
|
|
||||||
this.days = days;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDays() {
|
|
||||||
return days;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "{" + days + " days}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
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;
|
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;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class Solver {
|
public class Solver3 {
|
||||||
|
|
||||||
private final Map<TaskAttribute, Value> values = new LinkedHashMap<TaskAttribute, Value>();
|
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) {
|
public void setData(TaskAttribute attribute, Value value) {
|
||||||
values.remove(attribute);
|
values.remove(attribute);
|
||||||
values.put(attribute, value);
|
values.put(attribute, value);
|
||||||
@ -69,23 +75,30 @@ public class Solver {
|
|||||||
if (attribute == TaskAttribute.START) {
|
if (attribute == TaskAttribute.START) {
|
||||||
return computeStart();
|
return computeStart();
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException(attribute.toString());
|
return LoadInDays.inDay(1);
|
||||||
|
// throw new UnsupportedOperationException(attribute.toString());
|
||||||
}
|
}
|
||||||
return result;
|
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() {
|
private Instant computeEnd() {
|
||||||
final Instant start = (Instant) values.get(TaskAttribute.START);
|
Instant current = (Instant) values.get(TaskAttribute.START);
|
||||||
final Duration duration = (Duration) values.get(TaskAttribute.DURATION);
|
int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad();
|
||||||
assert start != null && duration != null;
|
while (fullLoad > 0) {
|
||||||
return start.add(duration).decrement();
|
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.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.command.regex.IRegex;
|
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.RegexLeaf;
|
||||||
import net.sourceforge.plantuml.command.regex.RegexResult;
|
import net.sourceforge.plantuml.command.regex.RegexResult;
|
||||||
|
|
||||||
@ -50,17 +52,31 @@ public class SubjectTask implements SubjectPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IRegex toRegex() {
|
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) {
|
public Subject getSubject(GanttDiagram project, RegexResult arg) {
|
||||||
final String s = arg.get("SUBJECT", 0);
|
final String s = arg.get("SUBJECT", 0);
|
||||||
final String shortName = arg.get("SUBJECT", 1);
|
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) {
|
if (result == null) {
|
||||||
throw new IllegalStateException();
|
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 Instant getEnd();
|
||||||
|
|
||||||
public Duration getDuration();
|
public Load getLoad();
|
||||||
|
|
||||||
|
public void setLoad(Load load);
|
||||||
|
|
||||||
public void setStart(Instant start);
|
public void setStart(Instant start);
|
||||||
|
|
||||||
public void setEnd(Instant end);
|
public void setEnd(Instant end);
|
||||||
|
|
||||||
public void setDuration(Duration duration);
|
|
||||||
|
|
||||||
public void setTaskDraw(TaskDraw taskDraw);
|
public void setTaskDraw(TaskDraw taskDraw);
|
||||||
|
|
||||||
public TaskDraw getTaskDraw();
|
public TaskDraw getTaskDraw();
|
||||||
|
|
||||||
public void setColors(ComplementColors colors);
|
public void setColors(ComplementColors colors);
|
||||||
|
|
||||||
|
public void addResource(Resource resource);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
package net.sourceforge.plantuml.project3;
|
package net.sourceforge.plantuml.project3;
|
||||||
|
|
||||||
public enum TaskAttribute {
|
public enum TaskAttribute {
|
||||||
START, END, DURATION;
|
START, END, LOAD;
|
||||||
|
|
||||||
public static TaskAttribute fromString(String value) {
|
public static TaskAttribute fromString(String value) {
|
||||||
return valueOf(value.toUpperCase());
|
return valueOf(value.toUpperCase());
|
||||||
|
@ -81,9 +81,8 @@ public class TaskCode {
|
|||||||
return hierarchy.toString();
|
return hierarchy.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Display getSimpleDisplay() {
|
public String getSimpleDisplay() {
|
||||||
final String last = hierarchy.get(hierarchy.size() - 1);
|
return hierarchy.get(hierarchy.size() - 1);
|
||||||
return Display.getWithNewlines(last);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHierarchySize() {
|
public int getHierarchySize() {
|
||||||
|
@ -36,111 +36,19 @@
|
|||||||
package net.sourceforge.plantuml.project3;
|
package net.sourceforge.plantuml.project3;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.Direction;
|
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.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.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;
|
public void setColors(ComplementColors colors);
|
||||||
private final TimeScale timeScale;
|
|
||||||
private final double y;
|
|
||||||
private ComplementColors colors;
|
|
||||||
|
|
||||||
private final double margin = 2;
|
public double getY();
|
||||||
|
|
||||||
public TaskDraw(Task task, TimeScale timeScale, double y) {
|
public double getY(Direction direction);
|
||||||
this.y = y;
|
|
||||||
this.task = task;
|
|
||||||
this.timeScale = timeScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextBlock getTitle() {
|
public void drawTitle(UGraphic ug);
|
||||||
return task.getCode().getSimpleDisplay()
|
|
||||||
.create(getFontConfiguration(), HorizontalAlignment.LEFT, new SpriteContainerEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
private FontConfiguration getFontConfiguration() {
|
public double getHeight();
|
||||||
final UFont font = UFont.serif(11);
|
|
||||||
return new FontConfiguration(font, HtmlColorUtils.BLACK, HtmlColorUtils.BLACK, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
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 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.code = code;
|
||||||
|
this.defaultPlan = defaultPlan;
|
||||||
|
this.solver = new Solver3(this);
|
||||||
setStart(new InstantDay(0));
|
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
|
@Override
|
||||||
@ -52,7 +117,7 @@ public class TaskImpl implements Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String debug() {
|
public String debug() {
|
||||||
return "" + getStart() + " ---> " + getEnd() + " [" + getDuration() + "]";
|
return "" + getStart() + " ---> " + getEnd() + " [" + getLoad() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskCode getCode() {
|
public TaskCode getCode() {
|
||||||
@ -60,15 +125,23 @@ public class TaskImpl implements Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Instant getStart() {
|
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() {
|
public Instant getEnd() {
|
||||||
return (Instant) solver.getData(TaskAttribute.END);
|
return (Instant) solver.getData(TaskAttribute.END);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Duration getDuration() {
|
public Load getLoad() {
|
||||||
return (Duration) solver.getData(TaskAttribute.DURATION);
|
return (Load) solver.getData(TaskAttribute.LOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoad(Load load) {
|
||||||
|
solver.setData(TaskAttribute.LOAD, load);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStart(Instant start) {
|
public void setStart(Instant start) {
|
||||||
@ -79,10 +152,6 @@ public class TaskImpl implements Task {
|
|||||||
solver.setData(TaskAttribute.END, end);
|
solver.setData(TaskAttribute.END, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDuration(Duration duration) {
|
|
||||||
solver.setData(TaskAttribute.DURATION, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaskDraw taskDraw;
|
private TaskDraw taskDraw;
|
||||||
private ComplementColors colors;
|
private ComplementColors colors;
|
||||||
|
|
||||||
@ -99,4 +168,8 @@ public class TaskImpl implements Task {
|
|||||||
this.colors = colors;
|
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 getStartingPosition(Instant instant);
|
||||||
|
|
||||||
|
public double getEndingPosition(Instant instant);
|
||||||
|
|
||||||
public double getWidth(Instant instant);
|
public double getWidth(Instant instant);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,10 @@ public class TimeScaleBasic implements TimeScale {
|
|||||||
return day * scale;
|
return day * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getEndingPosition(Instant instant) {
|
||||||
|
return getStartingPosition(instant) + getWidth(instant);
|
||||||
|
}
|
||||||
|
|
||||||
public double getWidth(Instant instant) {
|
public double getWidth(Instant instant) {
|
||||||
return scale;
|
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;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getEndingPosition(Instant instant) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,9 @@ public class VerbAre implements VerbPattern {
|
|||||||
return new Verb() {
|
return new Verb() {
|
||||||
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
||||||
final DayOfWeek day = (DayOfWeek) subject;
|
final DayOfWeek day = (DayOfWeek) subject;
|
||||||
|
project.closeDayOfWeek(day);
|
||||||
return CommandExecutionResult.ok();
|
return CommandExecutionResult.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public class VerbHappens implements VerbPattern {
|
|||||||
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
||||||
final Task task = (Task) subject;
|
final Task task = (Task) subject;
|
||||||
final TaskInstant when = (TaskInstant) complement;
|
final TaskInstant when = (TaskInstant) complement;
|
||||||
task.setDuration(new DurationDay(1));
|
task.setLoad(LoadInDays.inDay(1));
|
||||||
task.setStart(when.getInstantTheorical());
|
task.setStart(when.getInstantTheorical());
|
||||||
return CommandExecutionResult.ok();
|
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() {
|
return new Verb() {
|
||||||
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
public CommandExecutionResult execute(Subject subject, Complement complement) {
|
||||||
final Task task = (Task) subject;
|
final Task task = (Task) subject;
|
||||||
final Duration duration = (Duration) complement;
|
final Load duration = (Load) complement;
|
||||||
task.setDuration(duration);
|
task.setLoad(duration);
|
||||||
return CommandExecutionResult.ok();
|
return CommandExecutionResult.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import net.sourceforge.plantuml.FontParam;
|
|||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
import net.sourceforge.plantuml.LineParam;
|
||||||
import net.sourceforge.plantuml.PaddingParam;
|
import net.sourceforge.plantuml.PaddingParam;
|
||||||
import net.sourceforge.plantuml.RoundParam;
|
import net.sourceforge.plantuml.CornerParam;
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
import net.sourceforge.plantuml.SkinParamUtils;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||||
@ -108,7 +108,7 @@ public class Rose implements Skin {
|
|||||||
param.strictUmlStyle() == false, param.responseMessageBelowArrow());
|
param.strictUmlStyle() == false, param.responseMessageBelowArrow());
|
||||||
}
|
}
|
||||||
final double padding = param.getPadding(PaddingParam.PARTICIPANT);
|
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) {
|
if (type == ComponentType.PARTICIPANT_HEAD) {
|
||||||
return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param,
|
return new ComponentRoseParticipant(getSymbolContext(param, ColorParam.participantBorder), getUFont2(param,
|
||||||
FontParam.PARTICIPANT), stringsToDisplay, param, roundCorner, newFontForStereotype, getFontColor(
|
FontParam.PARTICIPANT), stringsToDisplay, param, roundCorner, newFontForStereotype, getFontColor(
|
||||||
|
@ -93,7 +93,7 @@ public class ClusterDecoration {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
final SymbolContext symbolContext = biColor.withShadow(shadowing).withStroke(defaultStroke)
|
final SymbolContext symbolContext = biColor.withShadow(shadowing).withStroke(defaultStroke)
|
||||||
.withRoundCorner(roundCorner);
|
.withCorner(roundCorner, 0);
|
||||||
symbol.asBig(title, titleAlignment, stereo, maxX - minX, maxY - minY, symbolContext).drawU(
|
symbol.asBig(title, titleAlignment, stereo, maxX - minX, maxY - minY, symbolContext).drawU(
|
||||||
ug.apply(new UTranslate(minX, minY)));
|
ug.apply(new UTranslate(minX, minY)));
|
||||||
// return;
|
// return;
|
||||||
|
@ -44,7 +44,7 @@ import net.sourceforge.plantuml.FontParam;
|
|||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineConfigurable;
|
import net.sourceforge.plantuml.LineConfigurable;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
import net.sourceforge.plantuml.LineParam;
|
||||||
import net.sourceforge.plantuml.RoundParam;
|
import net.sourceforge.plantuml.CornerParam;
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
import net.sourceforge.plantuml.SkinParamUtils;
|
||||||
import net.sourceforge.plantuml.Url;
|
import net.sourceforge.plantuml.Url;
|
||||||
import net.sourceforge.plantuml.creole.Stencil;
|
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) {
|
public EntityImageClass(GraphvizVersion version, ILeaf entity, ISkinParam skinParam, PortionShower portionShower) {
|
||||||
super(entity, entity.getColors(skinParam).mute(skinParam));
|
super(entity, entity.getColors(skinParam).mute(skinParam));
|
||||||
this.lineConfig = entity;
|
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)
|
this.shield = version != null && version.useShield() && entity.hasNearDecoration() ? Margins.uniform(16)
|
||||||
: Margins.NONE;
|
: Margins.NONE;
|
||||||
final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity);
|
final boolean showMethods = portionShower.showPortion(EntityPortion.METHOD, entity);
|
||||||
|
@ -87,7 +87,6 @@ public class EntityImageDescription extends AbstractEntityImage {
|
|||||||
private final Collection<Link> links;
|
private final Collection<Link> links;
|
||||||
private final boolean useRankSame;
|
private final boolean useRankSame;
|
||||||
|
|
||||||
|
|
||||||
public EntityImageDescription(ILeaf entity, ISkinParam skinParam, PortionShower portionShower,
|
public EntityImageDescription(ILeaf entity, ISkinParam skinParam, PortionShower portionShower,
|
||||||
Collection<Link> links) {
|
Collection<Link> links) {
|
||||||
super(entity, entity.getColors(skinParam).mute(skinParam));
|
super(entity, entity.getColors(skinParam).mute(skinParam));
|
||||||
@ -116,10 +115,12 @@ public class EntityImageDescription extends AbstractEntityImage {
|
|||||||
assert getStereo() == stereotype;
|
assert getStereo() == stereotype;
|
||||||
final HtmlColor forecolor = SkinParamUtils.getColor(getSkinParam(), symbol.getColorParamBorder(), stereotype);
|
final HtmlColor forecolor = SkinParamUtils.getColor(getSkinParam(), symbol.getColorParamBorder(), stereotype);
|
||||||
final double roundCorner = symbol.getSkinParameter().getRoundCorner(getSkinParam(), 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 UStroke stroke = colors.muteStroke(symbol.getSkinParameter().getStroke(getSkinParam(), stereotype));
|
||||||
|
|
||||||
final SymbolContext ctx = new SymbolContext(backcolor, forecolor).withStroke(stroke)
|
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);
|
stereo = TextBlockUtils.empty(0, 0);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ import net.sourceforge.plantuml.Direction;
|
|||||||
import net.sourceforge.plantuml.FontParam;
|
import net.sourceforge.plantuml.FontParam;
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
import net.sourceforge.plantuml.LineParam;
|
||||||
import net.sourceforge.plantuml.RoundParam;
|
import net.sourceforge.plantuml.CornerParam;
|
||||||
import net.sourceforge.plantuml.SkinParamBackcolored;
|
import net.sourceforge.plantuml.SkinParamBackcolored;
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
import net.sourceforge.plantuml.SkinParamUtils;
|
||||||
import net.sourceforge.plantuml.Url;
|
import net.sourceforge.plantuml.Url;
|
||||||
@ -221,7 +221,7 @@ public class EntityImageNote extends AbstractEntityImage implements Stencil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getRoundCorner() {
|
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) {
|
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.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineConfigurable;
|
import net.sourceforge.plantuml.LineConfigurable;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
import net.sourceforge.plantuml.LineParam;
|
||||||
import net.sourceforge.plantuml.RoundParam;
|
import net.sourceforge.plantuml.CornerParam;
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
import net.sourceforge.plantuml.SkinParamUtils;
|
||||||
import net.sourceforge.plantuml.Url;
|
import net.sourceforge.plantuml.Url;
|
||||||
import net.sourceforge.plantuml.creole.Stencil;
|
import net.sourceforge.plantuml.creole.Stencil;
|
||||||
@ -88,7 +88,7 @@ public class EntityImageObject extends AbstractEntityImage implements Stencil {
|
|||||||
super(entity, skinParam);
|
super(entity, skinParam);
|
||||||
this.lineConfig = entity;
|
this.lineConfig = entity;
|
||||||
final Stereotype stereotype = entity.getStereotype();
|
final Stereotype stereotype = entity.getStereotype();
|
||||||
this.roundCorner = skinParam.getRoundCorner(RoundParam.DEFAULT, null);
|
this.roundCorner = skinParam.getRoundCorner(CornerParam.DEFAULT, null);
|
||||||
this.name = TextBlockUtils.withMargin(
|
this.name = TextBlockUtils.withMargin(
|
||||||
entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.OBJECT, stereotype),
|
entity.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.OBJECT, stereotype),
|
||||||
HorizontalAlignment.CENTER, skinParam), 2, 2);
|
HorizontalAlignment.CENTER, skinParam), 2, 2);
|
||||||
|
@ -110,6 +110,7 @@ public class Footprint {
|
|||||||
drawText(x, y, (UText) shape);
|
drawText(x, y, (UText) shape);
|
||||||
} else if (shape instanceof UHorizontalLine) {
|
} else if (shape instanceof UHorizontalLine) {
|
||||||
// Definitively a Horizontal line
|
// Definitively a Horizontal line
|
||||||
|
// line.drawTitleInternalForFootprint(this, x, y);
|
||||||
} else if (shape instanceof ULine) {
|
} else if (shape instanceof ULine) {
|
||||||
// Probably a Horizontal line
|
// Probably a Horizontal line
|
||||||
} else if (shape instanceof UImage) {
|
} else if (shape instanceof UImage) {
|
||||||
|
@ -104,7 +104,8 @@ public class Histogram implements TimeDrawing {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < changes.size(); i++) {
|
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) {
|
if (i == 0 && initialState == null) {
|
||||||
return Arrays.asList(changes.get(i).getState());
|
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());
|
return Arrays.asList(changes.get(i - 1).getState(), changes.get(i).getState());
|
||||||
}
|
}
|
||||||
if (changes.get(i).getWhen().compareTo(tick) > 0) {
|
if (tickWithCurrentChangeTimeComparisonResult > 0) {
|
||||||
return Collections.singletonList(changes.get(i - 1).getState());
|
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());
|
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.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineParam;
|
import net.sourceforge.plantuml.LineParam;
|
||||||
import net.sourceforge.plantuml.OptionFlags;
|
import net.sourceforge.plantuml.OptionFlags;
|
||||||
import net.sourceforge.plantuml.RoundParam;
|
import net.sourceforge.plantuml.CornerParam;
|
||||||
import net.sourceforge.plantuml.StringUtils;
|
import net.sourceforge.plantuml.StringUtils;
|
||||||
import net.sourceforge.plantuml.Url;
|
import net.sourceforge.plantuml.Url;
|
||||||
import net.sourceforge.plantuml.anim.AffineTransformation;
|
import net.sourceforge.plantuml.anim.AffineTransformation;
|
||||||
@ -143,7 +143,7 @@ public class ImageBuilder {
|
|||||||
final Rose rose = new Rose();
|
final Rose rose = new Rose();
|
||||||
this.borderColor = rose.getHtmlColor(skinParam, ColorParam.diagramBorder);
|
this.borderColor = rose.getHtmlColor(skinParam, ColorParam.diagramBorder);
|
||||||
this.borderStroke = skinParam.getThickness(LineParam.diagramBorder, null);
|
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) {
|
if (borderStroke == null && borderColor != null) {
|
||||||
this.borderStroke = new UStroke();
|
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));
|
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) {
|
public void drawTitleInternal(UGraphic ug, double startingX, double endingX, double y, boolean clearArea) {
|
||||||
if (title == null || blankTitle) {
|
if (title == null || blankTitle) {
|
||||||
return;
|
return;
|
||||||
|
@ -43,7 +43,7 @@ public class Version {
|
|||||||
private static final int MAJOR_SEPARATOR = 1000000;
|
private static final int MAJOR_SEPARATOR = 1000000;
|
||||||
|
|
||||||
public static int version() {
|
public static int version() {
|
||||||
return 1201802;
|
return 1201803;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int versionPatched() {
|
public static int versionPatched() {
|
||||||
@ -88,7 +88,7 @@ public class Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long compileTime() {
|
public static long compileTime() {
|
||||||
return 1520616044801L;
|
return 1522947555139L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String compileTimeString() {
|
public static String compileTimeString() {
|
||||||
|
@ -30,8 +30,9 @@ public class VP8Decoder {
|
|||||||
coefProbs = Globals.getDefaultCoefProbs();
|
coefProbs = Globals.getDefaultCoefProbs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void decodeFrame(ImageInputStream stream, boolean debug)
|
public void decodeFrame(ImageInputStream stream)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
final boolean debug = false;
|
||||||
coefProbs = Globals.getDefaultCoefProbs();
|
coefProbs = Globals.getDefaultCoefProbs();
|
||||||
f = new VP8Frame(stream, coefProbs);
|
f = new VP8Frame(stream, coefProbs);
|
||||||
if (f.decodeFrame(debug)) {
|
if (f.decodeFrame(debug)) {
|
||||||
@ -52,27 +53,9 @@ public class VP8Decoder {
|
|||||||
return f.getWidth();
|
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) {
|
public void writePGMFile(String fileName, VP8Frame frame) {
|
||||||
|
|
||||||
|
|
||||||
FileOutputStream out;
|
FileOutputStream out;
|
||||||
try {
|
try {
|
||||||
int[][] yData = frame.getYBuffer();
|
int[][] yData = frame.getYBuffer();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user