Arnaud Roques 2023-11-23 17:50:00 +01:00
parent e4c246750e
commit 8b5a1521e7
45 changed files with 984 additions and 376 deletions

View File

@ -1,4 +1,4 @@
# Warning, "version" should be the same in gradle.properties and Version.java
# Any idea anyone how to magically synchronize those :-) ?
version = 1.2023.13beta2
version = 1.2023.13beta3
org.gradle.workers.max = 3

View File

@ -367,6 +367,11 @@ ganttDiagram {
Margin 5
Padding 5
}
verticalSeparator {
LineThickness 2
LineStyle 2-2
LineColor black
}
timeline {
BackgroundColor transparent
LineColor #C0C0C0

View File

@ -85,83 +85,77 @@ public class OptionPrint {
System.out.println("\t?\tone and only one character but '" + SFile.separator + "'");
System.out.println("\t**\tmeans any characters (used to recurse through directories)");
System.out.println();
System.out.println("where options include:");
System.out.println(" -darkmode\t\tTo use dark mode for diagrams");
System.out.println(" -gui\t\tTo run the graphical user interface");
System.out.println(" -tpng\t\tTo generate images using PNG format (default)");
System.out.println(" -tsvg\t\tTo generate images using SVG format");
System.out.println(" -teps\t\tTo generate images using EPS format");
System.out.println(" -tpdf\t\tTo generate images using PDF format");
System.out.println(" -tvdx\t\tTo generate images using VDX format");
System.out.println(" -txmi\t\tTo generate XMI file for class diagram");
System.out.println(" -tscxml\t\tTo generate SCXML file for state diagram");
System.out.println(" -thtml\t\tTo generate HTML file for class diagram");
System.out.println(" -ttxt\t\tTo generate images with ASCII art");
System.out.println(" -tutxt\t\tTo generate images with ASCII art using Unicode characters");
System.out.println(" -tlatex\t\tTo generate images using LaTeX/Tikz format");
System.out.println(" -tlatex:nopreamble\tTo generate images using LaTeX/Tikz format without preamble");
System.out.println(" -o[utput] \"dir\"\tTo generate images in the specified directory");
System.out.println(" -DVAR1=value\tTo set a preprocessing variable as if '!define VAR1 value' were used");
System.out.println(" -Sparam1=value\tTo set a skin parameter as if 'skinparam param1 value' were used");
System.out.println(" -Ppragma1=value\tTo set pragma as if '!pragma pragma1 value' were used");
// System.out.println(" -config \"file\"\tTo read the provided config file
// before each diagram");
final char separator = SFile.separatorChar;
System.out.println(" -I" + separator + "path" + separator + "to" + separator
+ "file\tTo include file as if '!include file' were used");
System.out.println(
" -I" + separator + "path" + separator + "to" + separator + "*.puml\tTo include files with pattern");
System.out.println(" -theme xxx\t\tTo use a specific theme");
System.out.println(" -charset xxx\tTo use a specific charset (default is " + charset + ")");
System.out.println(" -e[x]clude pattern\tTo exclude files that match the provided pattern");
System.out.println(" -metadata\t\tTo retrieve PlantUML sources from PNG images");
System.out.println(" -nometadata\t\tTo NOT export metadata in PNG/SVG generated files");
System.out.println("where options include:");
System.out.println(" -author[s]\t\tTo print information about PlantUML authors");
System.out.println(" -checkmetadata\t\tSkip PNG files that don't need to be regenerated");
System.out.println(" -version\t\tTo display information about PlantUML and Java versions");
System.out.println(" -v[erbose]\t\tTo have log information");
System.out.println(" -quiet\t\tTo NOT print error message into the console");
System.out.println(" -debugsvek\t\tTo generate intermediate svek files");
System.out.println(" -h[elp]\t\tTo display this help message");
System.out.println(" -testdot\t\tTo test the installation of graphviz");
System.out.println(" -graphvizdot \"exe\"\tTo specify dot executable");
System.out.println(" -p[ipe]\t\tTo use stdin for PlantUML source and stdout for PNG/SVG/EPS generation");
System.out.println(
" -encodesprite 4|8|16[z] \"file\"\tTo encode a sprite at gray level (z for compression) from an image");
System.out.println(" -computeurl|-encodeurl\tTo compute the encoded URL of a PlantUML source file");
System.out.println(" -decodeurl\t\tTo retrieve the PlantUML source from an encoded URL");
System.out.println(" -syntax\t\tTo report any syntax error from standard input without generating images");
System.out.println(" -language\t\tTo print the list of PlantUML keywords");
// System.out.println(" -nosuggestengine\tTo disable the suggest engine when
// errors in diagrams");
System.out.println(" -checkonly\t\tTo check the syntax of files without generating images");
System.out.println(" -charset xxx\tTo use a specific charset (default is " + charset + ")");
System.out.println(" -computeurl|-encodeurl\tTo compute the encoded URL of a PlantUML source file");
// System.out.println(" -config \"file\"\tTo read the provided config file
System.out.println(" -cypher\t\tTo cypher texts of diagrams so that you can share them");
System.out.println(" -DVAR1=value\tTo set a preprocessing variable as if '!define VAR1 value' were used");
System.out.println(" -darkmode\t\tTo use dark mode for diagrams");
System.out.println(" -debugsvek\t\tTo generate intermediate svek files");
System.out.println(" -decodeurl\t\tTo retrieve the PlantUML source from an encoded URL");
System.out.println(" -disablestats\tTo disable statistics computation (default)");
System.out.println(" -duration\t\tTo print the duration of complete diagrams processing");
System.out.println(" -e[x]clude pattern\tTo exclude files that match the provided pattern");
System.out.println(" -enablestats\tTo enable statistics computation");
System.out.println(" -encodesprite 4|8|16[z] \"file\"\tTo encode a sprite at gray level (z for compression) from an image");
System.out.println(" -extractstdlib\tTo extract PlantUML Standard Library into stdlib folder");
System.out.println(" -failfast\t\tTo stop processing as soon as a syntax error in diagram occurs");
System.out.println(" -failfast2\t\tTo do a first syntax check before processing files, to fail even faster");
System.out.println(" -noerror\t\tTo skip images when error in diagrams");
System.out.println(" -duration\t\tTo print the duration of complete diagrams processing");
System.out.println(" -filedir xxx\tTo behave as if the PlantUML source is in this dir (only affects '-pipe' and PicoWeb 'POST /render')");
System.out.println(" -filename \"example.puml\"\tTo override %filename% variable");
System.out.println(" -graphvizdot \"exe\"\tTo specify dot executable");
System.out.println(" -gui\t\tTo run the graphical user interface");
System.out.println(" -h[elp]\t\tTo display this help message");
System.out.println(" -htmlstats\t\tTo output general statistics in file plantuml-stats.html");
System.out.println(" -I" + separator + "path" + separator + "to" + separator + "file\tTo include file as if '!include file' were used");
System.out.println(" -I" + separator + "path" + separator + "to" + separator + "*.puml\tTo include files with pattern");
System.out.println(" -language\t\tTo print the list of PlantUML keywords");
System.out.println(" -loopstats\t\tTo continuously print statistics about usage");
System.out.println(" -metadata\t\tTo retrieve PlantUML sources from PNG images");
System.out.println(" -nbthread N\t\tTo use (N) threads for processing");
System.out.println(" -nbthread auto\tTo use " + Option.defaultNbThreads() + " threads for processing");
System.out
.println(" -timeout N\t\tProcessing timeout in (N) seconds. Defaults to 15 minutes (900 seconds).");
System.out.println(" -author[s]\t\tTo print information about PlantUML authors");
System.out.println(" -noerror\t\tTo skip images when error in diagrams");
System.out.println(" -nometadata\t\tTo NOT export metadata in PNG/SVG generated files");
System.out.println(" -o[utput] \"dir\"\tTo generate images in the specified directory");
System.out.println(" -overwrite\t\tTo allow to overwrite read only files");
System.out.println(" -printfonts\t\tTo print fonts available on your system");
System.out.println(" -enablestats\tTo enable statistics computation");
System.out.println(" -disablestats\tTo disable statistics computation (default)");
System.out.println(" -htmlstats\t\tTo output general statistics in file plantuml-stats.html");
System.out.println(" -xmlstats\t\tTo output general statistics in file plantuml-stats.xml");
System.out.println(" -realtimestats\tTo generate statistics on the fly rather than at the end");
System.out.println(" -loopstats\t\tTo continuously print statistics about usage");
System.out.println(" -splash\t\tTo display a splash screen with some progress bar");
System.out.println(" -progress\t\tTo display a textual progress bar in console");
System.out.println(" -pipeimageindex N\tTo generate the Nth image with pipe option");
System.out.println(" -stdlib\t\tTo print standard library info");
System.out.println(" -extractstdlib\tTo extract PlantUML Standard Library into stdlib folder");
System.out.println(
" -filedir xxx\tTo behave as if the PlantUML source is in this dir (only affects '-pipe' and PicoWeb 'POST /render')");
System.out.println(" -filename \"example.puml\"\tTo override %filename% variable");
System.out.println(" -preproc\t\tTo output preprocessor text of diagrams");
System.out.println(" -cypher\t\tTo cypher texts of diagrams so that you can share them");
System.out.println(" -Ppragma1=value\tTo set pragma as if '!pragma pragma1 value' were used");
System.out.println(" -p[ipe]\t\tTo use stdin for PlantUML source and stdout for PNG/SVG/EPS generation");
System.out.println(" -picoweb\t\tTo start internal HTTP Server. See https://plantuml.com/picoweb");
System.out.println(" -pipeimageindex N\tTo generate the Nth image with pipe option");
System.out.println(" -preproc\t\tTo output preprocessor text of diagrams");
System.out.println(" -printfonts\t\tTo print fonts available on your system");
System.out.println(" -progress\t\tTo display a textual progress bar in console");
System.out.println(" -quiet\t\tTo NOT print error message into the console");
System.out.println(" -realtimestats\tTo generate statistics on the fly rather than at the end");
System.out.println(" -Sparam1=value\tTo set a skin parameter as if 'skinparam param1 value' were used");
System.out.println(" -splash\t\tTo display a splash screen with some progress bar");
System.out.println(" -stdlib\t\tTo print standard library info");
System.out.println(" -syntax\t\tTo report any syntax error from standard input without generating images");
System.out.println(" -testdot\t\tTo test the installation of graphviz");
System.out.println(" -theme xxx\t\tTo use a specific theme");
System.out.println(" -timeout N\t\tProcessing timeout in (N) seconds. Defaults to 15 minutes (900 seconds).");
System.out.println(" -teps\t\tTo generate images using EPS format");
System.out.println(" -testdot\t\tTo test the installation of graphviz");
System.out.println(" -theme xxx\t\tTo use a specific theme");
System.out.println(" -thtml\t\tTo generate HTML file for class diagram");
System.out.println(" -tlatex:nopreamble\tTo generate images using LaTeX/Tikz format without preamble");
System.out.println(" -tlatex\t\tTo generate images using LaTeX/Tikz format");
System.out.println(" -tpdf\t\tTo generate images using PDF format");
System.out.println(" -tpng\t\tTo generate images using PNG format (default)");
System.out.println(" -tscxml\t\tTo generate SCXML file for state diagram");
System.out.println(" -tsvg\t\tTo generate images using SVG format");
System.out.println(" -ttxt\t\tTo generate images with ASCII art");
System.out.println(" -tutxt\t\tTo generate images with ASCII art using Unicode characters");
System.out.println(" -tvdx\t\tTo generate images using VDX format");
System.out.println(" -txmi\t\tTo generate XMI file for class diagram");
System.out.println(" -v[erbose]\t\tTo have log information");
System.out.println(" -version\t\tTo display information about PlantUML and Java versions");
System.out.println(" -xmlstats\t\tTo output general statistics in file plantuml-stats.xml");
System.out.println();
System.out.println("If needed, you can setup the environment variable GRAPHVIZ_DOT.");
exit(0);

View File

@ -53,8 +53,14 @@ public class ConstantPlan implements LoadPlanable {
return new ConstantPlan(load);
}
@Override
public int getLoadAt(Day instant) {
return loadPerInstant;
}
@Override
public Day getLastDayIfAny() {
return null;
}
}

View File

@ -86,6 +86,7 @@ import net.sourceforge.plantuml.project.core.TaskInstant;
import net.sourceforge.plantuml.project.core.TaskSeparator;
import net.sourceforge.plantuml.project.draw.FingerPrint;
import net.sourceforge.plantuml.project.draw.ResourceDraw;
import net.sourceforge.plantuml.project.draw.ResourceDrawVersion2;
import net.sourceforge.plantuml.project.draw.TaskDraw;
import net.sourceforge.plantuml.project.draw.TaskDrawDiamond;
import net.sourceforge.plantuml.project.draw.TaskDrawGroup;
@ -99,6 +100,7 @@ import net.sourceforge.plantuml.project.draw.TimeHeaderSimple;
import net.sourceforge.plantuml.project.draw.TimeHeaderWeekly;
import net.sourceforge.plantuml.project.draw.TimeHeaderYearly;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
import net.sourceforge.plantuml.project.solver.ImpossibleSolvingException;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
@ -149,6 +151,8 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private final RealOrigin origin = RealUtils.createOrigin();
private int defaultCompletion = 100;
public CommandExecutionResult changeLanguage(String lang) {
this.locale = new Locale(lang);
return CommandExecutionResult.ok();
@ -202,6 +206,16 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
return false;
}
@Override
public String checkFinalError() {
try {
initMinMax();
} catch (ImpossibleSolvingException ex) {
return ex.getMessage();
}
return null;
}
@Override
protected TextBlock getTextBlock() {
final FileFormatOption fileFormatOption = new FileFormatOption(FileFormat.PNG);
@ -312,7 +326,8 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private TimeHeaderParameters thParam() {
return new TimeHeaderParameters(colorDays(), getFactorScale(), min, max, getIHtmlColorSet(), getTimelineStyle(),
getClosedStyle(), locale, openClose, colorDaysOfWeek, verticalSeparatorBefore);
getClosedStyle(), locale, openClose, colorDaysOfWeek, verticalSeparatorBefore,
getVerticalSeparatorStyle());
}
private Map<Day, HColor> colorDays() {
@ -330,6 +345,11 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
.getMergedStyle(getCurrentStyleBuilder());
}
private Style getVerticalSeparatorStyle() {
return StyleSignatureBasic.of(SName.root, SName.element, SName.ganttDiagram, SName.verticalSeparator)
.getMergedStyle(getCurrentStyleBuilder());
}
private double getTotalHeight(TimeHeader timeHeader) {
if (showFootbox)
return totalHeightWithoutFooter + timeHeader.getTimeFooterHeight();
@ -457,14 +477,19 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
yy = headerHeight;
} else if (this.hideResourceFoobox == false)
for (Resource res : resources.values()) {
final ResourceDraw draw = new ResourceDraw(this, res, timeScale, yy, min, max);
final ResourceDraw draw = buildResourceDraw(this, res, timeScale, yy, min, max);
res.setTaskDraw(draw);
yy += draw.getHeight();
yy += draw.getHeight(stringBounder);
}
this.totalHeightWithoutFooter = yy;
}
private ResourceDraw buildResourceDraw(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Day min,
Day max) {
return new ResourceDrawVersion2(gantt, res, timeScale, y, min, max);
}
private Collection<GanttConstraint> getConstraints(Task task) {
final List<GanttConstraint> result = new ArrayList<>();
for (GanttConstraint constraint : constraints) {
@ -603,7 +628,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
final OpenClose except = this.openCloseForTask.get(codeOrShortName);
result = new TaskImpl(getSkinParam().getCurrentStyleBuilder(), code, openClose.mutateMe(except),
openClose.getStartingDay());
openClose.getStartingDay(), defaultCompletion);
if (currentGroup != null)
currentGroup.addTask(result);
@ -866,4 +891,19 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
verticalSeparatorBefore.add(day);
}
public void setTaskDefaultCompletion(int defaultCompletion) {
this.defaultCompletion = defaultCompletion;
}
public List<TaskDrawRegular> getAllTasksForResource(Resource res) {
final List<TaskDrawRegular> result = new ArrayList<TaskDrawRegular>();
for (Task task : tasks.values())
if (task.isAssignedTo(res)) {
final TaskDrawRegular draw = (TaskDrawRegular) draws.get(task);
result.add(draw);
}
return Collections.unmodifiableList(result);
}
}

View File

@ -59,6 +59,7 @@ import net.sourceforge.plantuml.project.command.CommandNoteBottom;
import net.sourceforge.plantuml.project.command.CommandPrintBetween;
import net.sourceforge.plantuml.project.command.CommandPrintScale;
import net.sourceforge.plantuml.project.command.CommandSeparator;
import net.sourceforge.plantuml.project.command.CommandTaskCompleteDefault;
import net.sourceforge.plantuml.project.command.CommandWeekNumberStrategy;
import net.sourceforge.plantuml.project.command.NaturalCommand;
import net.sourceforge.plantuml.project.lang.SentenceAnd;
@ -115,6 +116,7 @@ public class GanttDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandLabelOnColumn());
cmds.add(new CommandHideResourceName());
cmds.add(new CommandHideResourceFootbox());
cmds.add(new CommandTaskCompleteDefault());
}
private void addLanguageCommands(List<Command> cmd) {

View File

@ -40,4 +40,6 @@ import net.sourceforge.plantuml.project.time.Day;
public interface LoadPlanable {
public int getLoadAt(Day instant);
public Day getLastDayIfAny();
}

View File

@ -49,6 +49,8 @@ public class OpenClose implements Histogram, LoadPlanable {
private final Map<DayOfWeek, DayStatus> weekdayStatus = new EnumMap<>(DayOfWeek.class);
private final Map<Day, DayStatus> dayStatus = new HashMap<>();
private Day startingDay;
private Day offBefore;
private Day offAfter;
public int daysInWeek() {
int result = 7;
@ -89,6 +91,11 @@ public class OpenClose implements Histogram, LoadPlanable {
}
private DayStatus getLocalStatus(Day day) {
if (offBefore != null && day.compareTo(offBefore) < 0)
return DayStatus.CLOSE;
if (offAfter != null && day.compareTo(offAfter) > 0)
return DayStatus.CLOSE;
final DayStatus status1 = dayStatus.get(day);
if (status1 != null)
return status1;
@ -174,6 +181,14 @@ public class OpenClose implements Histogram, LoadPlanable {
return getLoatAtInternal(day);
}
public void setOffBeforeDate(Day day) {
this.offBefore = day;
}
public void setOffAfterDate(Day day) {
this.offAfter = day;
}
private int getLoatAtInternal(Day day) {
if (isClosed(day))
return 0;
@ -193,8 +208,18 @@ public class OpenClose implements Histogram, LoadPlanable {
return 100;
return OpenClose.this.getLoadAt(instant);
}
@Override
public Day getLastDayIfAny() {
return offAfter;
}
};
return this;
}
@Override
public Day getLastDayIfAny() {
return offAfter;
}
}

View File

@ -48,6 +48,10 @@ public class PlanUtils {
public int getLoadAt(Day instant) {
return Math.min(p1.getLoadAt(instant), p2.getLoadAt(instant));
}
public Day getLastDayIfAny() {
return lastOf(p1.getLastDayIfAny(), p2.getLastDayIfAny());
}
};
}
@ -56,7 +60,21 @@ public class PlanUtils {
public int getLoadAt(Day instant) {
return p1.getLoadAt(instant) * p2.getLoadAt(instant) / 100;
}
public Day getLastDayIfAny() {
return lastOf(p1.getLastDayIfAny(), p2.getLastDayIfAny());
}
};
}
private static Day lastOf(Day day1, Day day2) {
if (day1 == null)
return day2;
if (day2 == null)
return day1;
if (day1.compareTo(day2) > 0)
return day1;
return day2;
}
}

View File

@ -39,10 +39,13 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import net.sourceforge.plantuml.klimt.UStroke;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColorSet;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
public class TimeHeaderParameters {
@ -54,6 +57,7 @@ public class TimeHeaderParameters {
private final HColorSet colorSet;
private final Style timelineStyle;
private final Style closedStyle;
private final Style verticalSeparatorStyle;
private final Locale locale;
private final OpenClose openClose;
private final Map<DayOfWeek, HColor> colorDaysOfWeek;
@ -61,7 +65,7 @@ public class TimeHeaderParameters {
public TimeHeaderParameters(Map<Day, HColor> colorDays, double scale, Day min, Day max, HColorSet colorSet,
Style timelineStyle, Style closedStyle, Locale locale, OpenClose openClose,
Map<DayOfWeek, HColor> colorDaysOfWeek, Set<Day> verticalSeparatorBefore) {
Map<DayOfWeek, HColor> colorDaysOfWeek, Set<Day> verticalSeparatorBefore, Style verticalSeparatorStyle) {
this.colorDays = colorDays;
this.scale = scale;
this.min = min;
@ -73,6 +77,7 @@ public class TimeHeaderParameters {
this.openClose = openClose;
this.colorDaysOfWeek = colorDaysOfWeek;
this.verticalSeparatorBefore = verticalSeparatorBefore;
this.verticalSeparatorStyle = verticalSeparatorStyle;
}
public HColor getColor(Day wink) {
@ -123,4 +128,10 @@ public class TimeHeaderParameters {
return verticalSeparatorBefore;
}
public final UGraphic forVerticalSeparator(UGraphic ug) {
final HColor color = verticalSeparatorStyle.value(PName.LineColor).asColor(getColorSet());
final UStroke stroke = verticalSeparatorStyle.getStroke();
return ug.apply(color).apply(stroke);
}
}

View File

@ -48,7 +48,7 @@ import net.sourceforge.plantuml.utils.LineLocation;
public class CommandPrintBetween extends SingleLineCommand2<GanttDiagram> {
private static final ComplementDate pattern = new ComplementDate();
private static final ComplementDate pattern = ComplementDate.any();
public CommandPrintBetween() {
super(getRegexConcat());

View File

@ -0,0 +1,84 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://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.project.command;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.klimt.color.NoSuchColorException;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.regex.IRegex;
import net.sourceforge.plantuml.regex.RegexConcat;
import net.sourceforge.plantuml.regex.RegexLeaf;
import net.sourceforge.plantuml.regex.RegexOr;
import net.sourceforge.plantuml.regex.RegexResult;
import net.sourceforge.plantuml.utils.LineLocation;
public class CommandTaskCompleteDefault extends SingleLineCommand2<GanttDiagram> {
public CommandTaskCompleteDefault() {
super(getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandTaskCompleteDefault.class.getName(), RegexLeaf.start(), //
new RegexLeaf("task"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexLeaf("default[%s]+completion"), //
new RegexLeaf("completion[%s]+default")), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("to"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("VALUE", "(\\d+)"), //
new RegexLeaf(".*"), //
RegexLeaf.spaceZeroOrMore(), //
RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, LineLocation location, RegexResult arg)
throws NoSuchColorException {
final int value = Integer.parseInt(arg.get("VALUE", 0));
if (value > 100)
return CommandExecutionResult.error("Completetion must between 0 and 100");
diagram.setTaskDefaultCompletion(value);
return CommandExecutionResult.ok();
}
}

View File

@ -94,4 +94,17 @@ public class Resource {
public void addCloseDay(DayOfWeek day) {
openClose.close(day);
}
public void setOffBeforeDate(Day day) {
openClose.setOffBeforeDate(day);
}
public void setOffAfterDate(Day day) {
openClose.setOffAfterDate(day);
}
public Day getLastDayIfAny() {
return openClose.getLastDayIfAny();
}
}

View File

@ -79,4 +79,6 @@ public interface Task extends Moment {
public StyleBuilder getStyleBuilder();
public boolean isAssignedTo(Resource res);
}

View File

@ -56,6 +56,7 @@ public class TaskGroup extends AbstractTask implements Task {
this.parent = parent;
}
@Override
public Day getStart() {
Day min = null;
for (Task child : children)
@ -68,6 +69,7 @@ public class TaskGroup extends AbstractTask implements Task {
throw new UnsupportedOperationException();
}
@Override
public Day getEnd() {
Day max = null;
for (Task child : children)
@ -80,54 +82,67 @@ public class TaskGroup extends AbstractTask implements Task {
throw new UnsupportedOperationException();
}
@Override
public void setStart(Day start) {
throw new UnsupportedOperationException();
}
@Override
public void setEnd(Day end) {
throw new UnsupportedOperationException();
}
@Override
public void setColors(CenterBorderColor... colors) {
throw new UnsupportedOperationException();
}
@Override
public void addResource(Resource resource, int percentage) {
throw new UnsupportedOperationException();
}
@Override
public Load getLoad() {
throw new UnsupportedOperationException();
}
@Override
public void setLoad(Load load) {
throw new UnsupportedOperationException();
}
@Override
public void setDiamond(boolean diamond) {
throw new UnsupportedOperationException();
}
@Override
public boolean isDiamond() {
throw new UnsupportedOperationException();
}
@Override
public void setCompletion(int completion) {
throw new UnsupportedOperationException();
}
@Override
public void setUrl(Url url) {
throw new UnsupportedOperationException();
}
@Override
public void addPause(Day pause) {
throw new UnsupportedOperationException();
}
@Override
public void addPause(DayOfWeek pause) {
throw new UnsupportedOperationException();
}
@Override
public void setNote(Display note) {
}
@ -139,4 +154,9 @@ public class TaskGroup extends AbstractTask implements Task {
return parent;
}
@Override
public boolean isAssignedTo(Resource res) {
return false;
}
}

View File

@ -66,7 +66,7 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
private final LoadPlanable defaultPlan;
private boolean diamond;
private int completion = 100;
private int completion;
private Display note;
private Url url;
@ -76,8 +76,9 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
this.url = url;
}
public TaskImpl(StyleBuilder styleBuilder, TaskCode code, LoadPlanable plan, Day startingDay) {
public TaskImpl(StyleBuilder styleBuilder, TaskCode code, LoadPlanable plan, Day startingDay, int completion) {
super(styleBuilder, code);
this.completion = completion;
this.defaultPlan = plan;
this.solver = new SolverImpl(this);
if (startingDay == null)
@ -88,6 +89,7 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
setLoad(Load.inWinks(1));
}
@Override
public int getLoadAt(Day instant) {
if (isPaused(instant))
return 0;
@ -131,10 +133,12 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
return 0;
}
@Override
public void addPause(Day pause) {
this.pausedDay.add(pause);
}
@Override
public void addPause(DayOfWeek pause) {
this.pausedDayOfWeek.add(pause);
}
@ -156,9 +160,29 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
}
return result;
}
@Override
public Day getLastDayIfAny() {
return TaskImpl.this.getLastDayIfAny();
}
};
}
@Override
public Day getLastDayIfAny() {
Day result = null;
for (Resource res : resources.keySet()) {
if (res.getLastDayIfAny() == null)
return null;
if (result == null || result.compareTo(res.getLastDayIfAny()) < 0)
result = res.getLastDayIfAny();
}
return result;
}
public String getPrettyDisplay() {
if (resources.size() > 0) {
final StringBuilder result = new StringBuilder(getCode().getSimpleDisplay());
@ -190,6 +214,7 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
return "" + getStart() + " ---> " + getEnd() + " [" + getLoad() + "]";
}
@Override
public Day getStart() {
Day result = (Day) solver.getData(TaskAttribute.START);
if (diamond == false)
@ -199,42 +224,52 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
return result;
}
@Override
public Day getEnd() {
return (Day) solver.getData(TaskAttribute.END);
}
@Override
public Load getLoad() {
return (Load) solver.getData(TaskAttribute.LOAD);
}
@Override
public void setLoad(Load load) {
solver.setData(TaskAttribute.LOAD, load);
}
@Override
public void setStart(Day start) {
solver.setData(TaskAttribute.START, start);
}
@Override
public void setEnd(Day end) {
solver.setData(TaskAttribute.END, end);
}
@Override
public void setColors(CenterBorderColor... colors) {
this.colors = colors;
}
@Override
public void addResource(Resource resource, int percentage) {
this.resources.put(resource, percentage);
}
@Override
public void setDiamond(boolean diamond) {
this.diamond = diamond;
}
@Override
public boolean isDiamond() {
return this.diamond;
}
@Override
public void setCompletion(int completion) {
this.completion = completion;
}
@ -274,6 +309,7 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
}
@Override
public void setNote(Display note) {
this.note = note;
}
@ -286,4 +322,9 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
return defaultPlan;
}
@Override
public boolean isAssignedTo(Resource res) {
return resources.containsKey(res);
}
}

View File

@ -52,22 +52,27 @@ public class TaskSeparator extends AbstractTask implements Task {
this.comment = comment;
}
@Override
public Day getStart() {
throw new UnsupportedOperationException();
}
@Override
public Day getEnd() {
throw new UnsupportedOperationException();
}
@Override
public void setStart(Day start) {
throw new UnsupportedOperationException();
}
@Override
public void setEnd(Day end) {
throw new UnsupportedOperationException();
}
@Override
public void setColors(CenterBorderColor... colors) {
throw new UnsupportedOperationException();
}
@ -76,10 +81,12 @@ public class TaskSeparator extends AbstractTask implements Task {
return comment;
}
@Override
public void addResource(Resource resource, int percentage) {
throw new UnsupportedOperationException();
}
@Override
public Load getLoad() {
throw new UnsupportedOperationException();
}
@ -88,31 +95,43 @@ public class TaskSeparator extends AbstractTask implements Task {
throw new UnsupportedOperationException();
}
@Override
public void setDiamond(boolean diamond) {
throw new UnsupportedOperationException();
}
@Override
public boolean isDiamond() {
throw new UnsupportedOperationException();
}
@Override
public void setCompletion(int completion) {
throw new UnsupportedOperationException();
}
@Override
public void setUrl(Url url) {
throw new UnsupportedOperationException();
}
@Override
public void addPause(Day pause) {
throw new UnsupportedOperationException();
}
@Override
public void addPause(DayOfWeek pause) {
throw new UnsupportedOperationException();
}
@Override
public void setNote(Display note) {
}
@Override
public boolean isAssignedTo(Resource res) {
return false;
}
}

View File

@ -35,96 +35,13 @@
*/
package net.sourceforge.plantuml.project.draw;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColors;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.UFont;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.shape.UDrawable;
import net.sourceforge.plantuml.klimt.shape.ULine;
import net.sourceforge.plantuml.klimt.sprite.SpriteContainerEmpty;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.core.Resource;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
public class ResourceDraw implements UDrawable {
public interface ResourceDraw extends UDrawable {
private final Resource res;
private final TimeScale timeScale;
private final double y;
private final Day min;
private final Day max;
private final GanttDiagram gantt;
public double getHeight(StringBounder stringBounder);
public ResourceDraw(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Day min, Day 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 = ULine.hline(timeScale.getEndingPosition(max) - timeScale.getStartingPosition(min));
ug.apply(HColors.BLACK).apply(UTranslate.dy(title.calculateDimension(ug.getStringBounder()).getHeight()))
.draw(line);
double startingPosition = -1;
int totalLoad = 0;
int totalLimit = 0;
for (Day i = min; i.compareTo(max) <= 0; i = i.increment()) {
final boolean isBreaking = timeScale.isBreaking(i);
totalLoad += gantt.getLoadForResource(res, i);
totalLimit += 100;
if (isBreaking) {
if (totalLoad > 0) {
final boolean over = totalLoad > totalLimit;
final FontConfiguration fontConfiguration = getFontConfiguration(9,
over ? HColors.RED : HColors.BLACK);
final TextBlock value = Display.getWithNewlines("" + totalLoad).create(fontConfiguration,
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
if (startingPosition == -1)
startingPosition = timeScale.getStartingPosition(i);
final double endingPosition = timeScale.getEndingPosition(i);
final double start = (startingPosition + endingPosition) / 2
- value.calculateDimension(ug.getStringBounder()).getWidth() / 2;
value.drawU(ug.apply(new UTranslate(start, 16)));
}
startingPosition = -1;
totalLoad = 0;
totalLimit = 0;
} else {
if (startingPosition == -1)
startingPosition = timeScale.getStartingPosition(i);
}
}
}
private FontConfiguration getFontConfiguration(int size) {
return getFontConfiguration(size, HColors.BLACK);
}
private FontConfiguration getFontConfiguration(int size, HColor color) {
final UFont font = UFont.serif(size);
return FontConfiguration.create(font, color, color, null);
}
public double getHeight() {
return 16 * 2;
}
public final double getY() {
return y;
}
public double getY();
}

View File

@ -0,0 +1,132 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://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.project.draw;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColors;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.font.UFont;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.klimt.shape.ULine;
import net.sourceforge.plantuml.klimt.sprite.SpriteContainerEmpty;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.core.Resource;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
public class ResourceDrawBasicImpl implements ResourceDraw {
private final Resource res;
private final TimeScale timeScale;
private final double y;
private final Day min;
private final Day max;
private final GanttDiagram gantt;
public ResourceDrawBasicImpl(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Day min, Day 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 = ULine.hline(timeScale.getEndingPosition(max) - timeScale.getStartingPosition(min));
ug.apply(HColors.BLACK).apply(UTranslate.dy(title.calculateDimension(ug.getStringBounder()).getHeight()))
.draw(line);
double startingPosition = -1;
int totalLoad = 0;
int totalLimit = 0;
for (Day i = min; i.compareTo(max) <= 0; i = i.increment()) {
final boolean isBreaking = timeScale.isBreaking(i);
totalLoad += gantt.getLoadForResource(res, i);
totalLimit += 100;
if (isBreaking) {
if (totalLoad > 0) {
final boolean over = totalLoad > totalLimit;
final FontConfiguration fontConfiguration = getFontConfiguration(9,
over ? HColors.RED : HColors.BLACK);
final TextBlock value = Display.getWithNewlines("" + totalLoad).create(fontConfiguration,
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
if (startingPosition == -1)
startingPosition = timeScale.getStartingPosition(i);
final double endingPosition = timeScale.getEndingPosition(i);
final double start = (startingPosition + endingPosition) / 2
- value.calculateDimension(ug.getStringBounder()).getWidth() / 2;
value.drawU(ug.apply(new UTranslate(start, 16)));
}
startingPosition = -1;
totalLoad = 0;
totalLimit = 0;
} else {
if (startingPosition == -1)
startingPosition = timeScale.getStartingPosition(i);
}
}
}
private FontConfiguration getFontConfiguration(int size) {
return getFontConfiguration(size, HColors.BLACK);
}
private FontConfiguration getFontConfiguration(int size, HColor color) {
final UFont font = UFont.serif(size);
return FontConfiguration.create(font, color, color, null);
}
@Override
public double getHeight(StringBounder stringBounder) {
return 16 * 2;
}
@Override
public final double getY() {
return y;
}
}

View File

@ -0,0 +1,138 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://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.project.draw;
import net.sourceforge.plantuml.klimt.UShape;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColors;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.font.UFont;
import net.sourceforge.plantuml.klimt.geom.HorizontalAlignment;
import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.klimt.shape.ULine;
import net.sourceforge.plantuml.klimt.shape.URectangle;
import net.sourceforge.plantuml.klimt.sprite.SpriteContainerEmpty;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.LabelPosition;
import net.sourceforge.plantuml.project.LabelStrategy;
import net.sourceforge.plantuml.project.core.Resource;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
public class ResourceDrawVersion2 implements ResourceDraw {
private final Resource res;
private final TimeScale timeScale;
private final double y;
private final Day min;
private final Day max;
private final GanttDiagram gantt;
public ResourceDrawVersion2(GanttDiagram gantt, Resource res, TimeScale timeScale, double y, Day min, Day 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 StringBounder stringBounder = ug.getStringBounder();
double ypos = 16;
final double tmpHeight = getHeight(stringBounder) - ypos;
for (Day wink = gantt.getStartingDate(); wink.compareTo(gantt.getEndingDate()) <= 0; wink = wink.increment()) {
final double start = timeScale.getStartingPosition(wink);
final double end = timeScale.getEndingPosition(wink);
final UShape rect = URectangle.build(end - start, tmpHeight);
if (res.isClosedAt(wink))
ug.apply(HColors.LIGHT_GRAY.bg()).apply(new UTranslate(start, ypos)).draw(rect);
}
final TextBlock title = Display.getWithNewlines(res.getName()).create(getFontConfiguration(13),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
title.drawU(ug);
final ULine line = ULine.hline(timeScale.getEndingPosition(max) - timeScale.getStartingPosition(min));
ug.apply(HColors.BLACK).apply(UTranslate.dy(title.calculateDimension(ug.getStringBounder()).getHeight()))
.draw(line);
final LabelStrategy labelStrategy = new LabelStrategy(LabelPosition.LEGACY, HorizontalAlignment.LEFT);
for (TaskDrawRegular draw : gantt.getAllTasksForResource(res)) {
draw.drawShape(ug.apply(UTranslate.dy(ypos + getTopMarginBetweenTask())));
draw.drawTitle(ug.apply(UTranslate.dy(ypos + getTopMarginBetweenTask())), labelStrategy, 10, 100);
ypos += draw.getShapeHeight(stringBounder) + getMarginBetweenTask();
}
}
@Override
public double getHeight(StringBounder stringBounder) {
double ypos = 16;
for (TaskDrawRegular draw : gantt.getAllTasksForResource(res))
ypos += draw.getShapeHeight(stringBounder) + getMarginBetweenTask();
return ypos + 8;
}
private double getTopMarginBetweenTask() {
return 2;
}
private double getMarginBetweenTask() {
return 4;
}
private FontConfiguration getFontConfiguration(int size) {
return getFontConfiguration(size, HColors.BLACK);
}
private FontConfiguration getFontConfiguration(int size, HColor color) {
final UFont font = UFont.serif(size);
return FontConfiguration.create(font, color, color, null);
}
@Override
public final double getY() {
return y;
}
}

View File

@ -101,7 +101,7 @@ public class TaskDrawRegular extends AbstractTaskDraw {
}
@Override
protected double getShapeHeight(StringBounder stringBounder) {
public double getShapeHeight(StringBounder stringBounder) {
final Style style = getStyle();
final ClockwiseTopRightBottomLeft padding = style.getPadding();
return padding.getTop() + getTitle().calculateDimension(stringBounder).getHeight() + padding.getBottom();
@ -170,7 +170,6 @@ public class TaskDrawRegular extends AbstractTaskDraw {
final double startPos = timeScale.getStartingPosition(start);
drawNote(ug.apply((new UTranslate(startPos, getYNotePosition(ug.getStringBounder())))));
ug = applyColors(ug);
drawShape(ug);
}
@ -256,7 +255,8 @@ public class TaskDrawRegular extends AbstractTaskDraw {
return endPos;
}
private void drawShape(UGraphic ug) {
public void drawShape(UGraphic ug) {
ug = applyColors(ug);
final Style style = getStyleSignature().getMergedStyle(getStyleBuilder());
final ClockwiseTopRightBottomLeft margin = style.getMargin();

View File

@ -35,12 +35,8 @@
*/
package net.sourceforge.plantuml.project.draw;
import java.util.Objects;
import net.sourceforge.plantuml.klimt.UStroke;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColorSet;
import net.sourceforge.plantuml.klimt.color.HColors;
import net.sourceforge.plantuml.klimt.creole.Display;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
@ -51,13 +47,13 @@ import net.sourceforge.plantuml.klimt.shape.TextBlock;
import net.sourceforge.plantuml.klimt.shape.ULine;
import net.sourceforge.plantuml.klimt.shape.URectangle;
import net.sourceforge.plantuml.klimt.sprite.SpriteContainerEmpty;
import net.sourceforge.plantuml.project.TimeHeaderParameters;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
public abstract class TimeHeader {
// ::remove folder when __HAXE__
// ::remove folder when __HAXE__
protected final double Y_POS_ROW16() {
return 16;
@ -68,38 +64,40 @@ public abstract class TimeHeader {
}
private final TimeScale timeScale;
private final Style closedStyle;
private final Style timelineStyle;
private final HColorSet colorSet;
protected final TimeHeaderParameters thParam;
protected final Day min;
protected final Day max;
public TimeHeader(Style timelineStyle, Style closedStyle, Day min, Day max, TimeScale timeScale,
HColorSet colorSet) {
public TimeHeader(TimeHeaderParameters thParam, TimeScale timeScale) {
this.thParam = thParam;
this.timeScale = timeScale;
this.min = min;
this.max = max;
this.closedStyle = Objects.requireNonNull(closedStyle);
this.timelineStyle = Objects.requireNonNull(timelineStyle);
this.colorSet = colorSet;
}
protected final boolean isBold2(Day wink) {
return thParam.getVerticalSeparatorBefore().contains(wink);
}
protected final Day getMin() {
return thParam.getMin();
}
protected final Day getMax() {
return thParam.getMax();
}
protected final HColor closedBackgroundColor() {
return closedStyle.value(PName.BackGroundColor).asColor(colorSet);
return thParam.getClosedStyle().value(PName.BackGroundColor).asColor(thParam.getColorSet());
}
protected final HColor closedFontColor() {
return closedStyle.value(PName.FontColor).asColor(colorSet);
return thParam.getClosedStyle().value(PName.FontColor).asColor(thParam.getColorSet());
}
protected final HColor openFontColor() {
return timelineStyle.value(PName.FontColor).asColor(colorSet);
return thParam.getTimelineStyle().value(PName.FontColor).asColor(thParam.getColorSet());
}
protected final HColor getBarColor() {
return timelineStyle.value(PName.LineColor).asColor(colorSet);
protected final HColor getLineColor() {
return thParam.getTimelineStyle().value(PName.LineColor).asColor(thParam.getColorSet());
}
public abstract double getTimeHeaderHeight();
@ -113,18 +111,14 @@ public abstract class TimeHeader {
public abstract double getFullHeaderHeight();
protected final void drawHline(UGraphic ug, double y) {
final double xmin = getTimeScale().getStartingPosition(min);
final double xmax = getTimeScale().getEndingPosition(max);
final double xmin = getTimeScale().getStartingPosition(thParam.getMin());
final double xmax = getTimeScale().getEndingPosition(thParam.getMax());
final ULine hline = ULine.hline(xmax - xmin);
ug.apply(getBarColor()).apply(UTranslate.dy(y)).draw(hline);
ug.apply(getLineColor()).apply(UTranslate.dy(y)).draw(hline);
}
protected final void drawVbar(UGraphic ug, double x, double y1, double y2, boolean bold) {
protected final void drawVline(UGraphic ug, double x, double y1, double y2) {
final ULine vbar = ULine.vline(y2 - y1);
if (bold)
ug = goBold(ug);
else
ug = ug.apply(getBarColor());
ug.apply(new UTranslate(x, y1)).draw(vbar);
}
@ -175,8 +169,12 @@ public abstract class TimeHeader {
ug.draw(URectangle.build(x2 - x1, height));
}
protected final UGraphic goBold(UGraphic ug) {
return ug.apply(HColors.BLACK).apply(UStroke.withThickness(2));
protected void printVerticalSeparators(UGraphic ug, double totalHeightWithoutFooter) {
ug = thParam.forVerticalSeparator(ug);
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment())
if (isBold2(wink))
drawVline(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(),
totalHeightWithoutFooter);
}
}

View File

@ -45,16 +45,8 @@ import net.sourceforge.plantuml.project.timescale.TimeScale;
public abstract class TimeHeaderCalendar extends TimeHeader {
private final TimeHeaderParameters thParam;
public TimeHeaderCalendar(TimeHeaderParameters thParam, TimeScale timeScale) {
super(thParam.getTimelineStyle(), thParam.getClosedStyle(), thParam.getMin(), thParam.getMax(), timeScale,
thParam.getColorSet());
this.thParam = thParam;
}
protected final boolean isBold(Day wink) {
return thParam.getVerticalSeparatorBefore().contains(wink);
super(thParam, timeScale);
}
protected final Locale locale() {
@ -64,7 +56,7 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
protected final int getLoadAt(Day instant) {
return thParam.getLoadPlanable().getLoadAt(instant);
}
// Duplicate in TimeHeaderSimple
class Pending {
final double x1;
@ -87,7 +79,7 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
final double height = totalHeightWithoutFooter - getFullHeaderHeight();
Pending pending = null;
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
final double x2 = getTimeScale().getEndingPosition(wink);
HColor back = thParam.getColor(wink);

View File

@ -70,7 +70,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
drawTextsDayOfWeek(ug.apply(UTranslate.dy(Y_POS_ROW16())));
drawTextDayOfMonth(ug.apply(UTranslate.dy(Y_POS_ROW28())));
drawMonths(ug);
printSmallVbars(ug, totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
printNamedDays(ug);
@ -78,12 +78,20 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
drawHline(ug, totalHeightWithoutFooter);
}
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
drawVbar(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(), totalHeightWithoutFooter,
isBold(wink));
@Override
protected void printVerticalSeparators(final UGraphic ug, double totalHeightWithoutFooter) {
final UGraphic ugVerticalSeparator = thParam.forVerticalSeparator(ug);
final UGraphic ugLineColor = ug.apply(getLineColor());
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment())
if (isBold2(wink))
drawVline(ugVerticalSeparator, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(),
totalHeightWithoutFooter);
else
drawVline(ugLineColor, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(),
totalHeightWithoutFooter);
drawVbar(ug, getTimeScale().getEndingPosition(max), getFullHeaderHeight(), totalHeightWithoutFooter, false);
drawVline(ugLineColor, getTimeScale().getEndingPosition(getMax()), getFullHeaderHeight(),
totalHeightWithoutFooter);
}
@Override
@ -94,7 +102,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
}
private void drawTextsDayOfWeek(UGraphic ug) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
final double x2 = getTimeScale().getEndingPosition(wink);
final HColor textColor = getTextBackColor(wink);
@ -103,7 +111,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
}
private void drawTextDayOfMonth(UGraphic ug) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
final double x2 = getTimeScale().getEndingPosition(wink);
final HColor textColor = getTextBackColor(wink);
@ -121,7 +129,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
private void drawMonths(final UGraphic ug) {
MonthYear last = null;
double lastChangeMonth = -1;
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (wink.monthYear().equals(last) == false) {
if (last != null)
@ -131,7 +139,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChangeMonth)
printMonth(ug, last, lastChangeMonth, x1);
@ -147,7 +155,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
private void printNamedDays(final UGraphic ug) {
if (nameDays.size() > 0) {
String last = null;
for (Day wink = min; wink.compareTo(max.increment()) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax().increment()) <= 0; wink = wink.increment()) {
final String name = nameDays.get(wink);
if (name != null && name.equals(last) == false) {
final double x1 = getTimeScale().getStartingPosition(wink);

View File

@ -62,19 +62,12 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
drawTextsBackground(ug, totalHeightWithoutFooter);
drawYears(ug);
drawMonths(ug.apply(UTranslate.dy(16)));
printSmallVbars(ug, totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
drawHline(ug, 0);
drawHline(ug, 16);
drawHline(ug, getFullHeaderHeight());
}
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
if (isBold(wink))
drawVbar(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(), totalHeightWithoutFooter,
isBold(wink));
}
@Override
public void drawTimeFooter(UGraphic ug) {
ug = ug.apply(UTranslate.dy(3));
@ -88,43 +81,43 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
private void drawYears(final UGraphic ug) {
MonthYear last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (last == null || wink.monthYear().year() != last.year()) {
drawVbar(ug, x1, 0, 15, false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, 0, 15);
if (last != null)
printYear(ug, last, lastChange, x1);
}
lastChange = x1;
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChange)
printYear(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 15, false);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, (double) 15);
}
private void drawMonths(UGraphic ug) {
MonthYear last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (wink.monthYear().equals(last) == false) {
drawVbar(ug, x1, 0, 12, false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, (double) 0, (double) 12);
if (last != null)
printMonth(ug, last, lastChange, x1);
}
lastChange = x1;
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChange)
printMonth(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12, false);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, (double) 12);
}
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {

View File

@ -62,19 +62,12 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
drawTextsBackground(ug, totalHeightWithoutFooter);
drawYears(ug);
drawQuarters(ug.apply(UTranslate.dy(16)));
printSmallVbars(ug, totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
drawHline(ug, 0);
drawHline(ug, 16);
drawHline(ug, getFullHeaderHeight());
}
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
if (isBold(wink))
drawVbar(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(), totalHeightWithoutFooter,
isBold(wink));
}
@Override
public void drawTimeFooter(UGraphic ug) {
ug = ug.apply(UTranslate.dy(3));
@ -88,43 +81,43 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
private void drawYears(final UGraphic ug) {
MonthYear last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (last == null || wink.monthYear().year() != last.year()) {
drawVbar(ug, x1, 0, 15, false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, (double) 0, (double) 15);
if (last != null)
printYear(ug, last, lastChange, x1);
}
lastChange = x1;
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChange)
printYear(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 15, false);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, (double) 15);
}
private void drawQuarters(UGraphic ug) {
String last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (quarter(wink).equals(last) == false) {
drawVbar(ug, x1, 0, 12, false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, (double) 0, (double) 12);
if (last != null)
printQuarter(ug, last, lastChange, x1);
}
lastChange = x1;
last = quarter(wink);
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChange)
printQuarter(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12, false);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, (double) 12);
}
private String quarter(Day day) {

View File

@ -35,8 +35,6 @@
*/
package net.sourceforge.plantuml.project.draw;
import java.util.Set;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.creole.Display;
@ -53,9 +51,7 @@ import net.sourceforge.plantuml.project.timescale.TimeScaleWink;
public class TimeHeaderSimple extends TimeHeader {
private final TimeHeaderParameters colorDays;
private final PrintScale printScale;
private final Set<Day> verticalSeparators;
@Override
public double getFullHeaderHeight() {
@ -75,37 +71,21 @@ public class TimeHeaderSimple extends TimeHeader {
}
public TimeHeaderSimple(TimeHeaderParameters thParam, PrintScale printScale) {
super(thParam.getTimelineStyle(), thParam.getClosedStyle(), thParam.getMin(), thParam.getMax(),
new TimeScaleWink(thParam.getScale(), printScale), thParam.getColorSet());
this.colorDays = thParam;
super(thParam, new TimeScaleWink(thParam.getScale(), printScale));
this.printScale = printScale;
this.verticalSeparators = thParam.getVerticalSeparatorBefore();
}
private boolean isBold(Day wink) {
return verticalSeparators.contains(wink);
}
private void drawSeparatorsDay(UGraphic ug, TimeScale timeScale, double totalHeightWithoutFooter) {
final ULine vbar = ULine.vline(totalHeightWithoutFooter - getFullHeaderHeight() + 2);
ug = goBold(ug).apply(UTranslate.dy(getFullHeaderHeight() - 1));
for (Day i = min; i.compareTo(max.increment()) <= 0; i = i.increment(printScale))
if (isBold(i)) {
final double x1 = timeScale.getStartingPosition(i);
ug.apply(UTranslate.dx(x1)).draw(vbar);
}
}
private void drawSmallVlinesDay(UGraphic ug, TimeScale timeScale, double totalHeightWithoutFooter) {
ug = ug.apply(getLineColor());
final ULine vbar = ULine.vline(totalHeightWithoutFooter);
for (Day i = min; i.compareTo(max.increment()) <= 0; i = i.increment(printScale)) {
for (Day i = getMin(); i.compareTo(getMax().increment()) <= 0; i = i.increment(printScale)) {
final double x1 = timeScale.getStartingPosition(i);
ug.apply(getBarColor()).apply(UTranslate.dx(x1)).draw(vbar);
ug.apply(UTranslate.dx(x1)).draw(vbar);
}
}
private void drawSimpleDayCounter(UGraphic ug, TimeScale timeScale) {
for (Day i = min; i.compareTo(max.increment()) <= 0; i = i.increment(printScale)) {
for (Day i = getMin(); i.compareTo(getMax().increment()) <= 0; i = i.increment(printScale)) {
final int value;
if (printScale == PrintScale.WEEKLY)
value = i.getAbsoluteDayNum() / 7 + 1;
@ -122,33 +102,34 @@ public class TimeHeaderSimple extends TimeHeader {
x2 = timeScale.getEndingPosition(i);
final double width = num.calculateDimension(ug.getStringBounder()).getWidth();
final double delta = (x2 - x1) - width;
if (i.compareTo(max.increment()) < 0)
if (i.compareTo(getMax().increment()) < 0)
num.drawU(ug.apply(UTranslate.dx(x1 + delta / 2)));
}
}
@Override
public void drawTimeHeader(final UGraphic ug, double totalHeightWithoutFooter) {
public void drawTimeHeader(UGraphic ug, double totalHeightWithoutFooter) {
drawTextsBackground(ug.apply(UTranslate.dy(-3)), totalHeightWithoutFooter + 6);
final double xmin = getTimeScale().getStartingPosition(min);
final double xmax = getTimeScale().getEndingPosition(max);
final double xmin = getTimeScale().getStartingPosition(getMin());
final double xmax = getTimeScale().getEndingPosition(getMax());
drawSmallVlinesDay(ug, getTimeScale(), totalHeightWithoutFooter + 2);
drawSeparatorsDay(ug, getTimeScale(), totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
drawSimpleDayCounter(ug, getTimeScale());
ug.apply(getBarColor()).draw(ULine.hline(xmax - xmin));
ug.apply(getBarColor()).apply(UTranslate.dy(getFullHeaderHeight() - 3)).draw(ULine.hline(xmax - xmin));
ug = ug.apply(getLineColor());
ug.draw(ULine.hline(xmax - xmin));
ug.apply(UTranslate.dy(getFullHeaderHeight() - 3)).draw(ULine.hline(xmax - xmin));
}
@Override
public void drawTimeFooter(UGraphic ug) {
final double xmin = getTimeScale().getStartingPosition(min);
final double xmax = getTimeScale().getEndingPosition(max);
final double xmin = getTimeScale().getStartingPosition(getMin());
final double xmax = getTimeScale().getEndingPosition(getMax());
ug = ug.apply(UTranslate.dy(3));
drawSmallVlinesDay(ug, getTimeScale(), getTimeFooterHeight() - 3);
drawSimpleDayCounter(ug, getTimeScale());
ug.apply(getBarColor()).draw(ULine.hline(xmax - xmin));
ug.apply(getLineColor()).draw(ULine.hline(xmax - xmin));
}
// Duplicate in TimeHeaderDaily
@ -173,10 +154,10 @@ public class TimeHeaderSimple extends TimeHeader {
final double height = totalHeightWithoutFooter - getFullHeaderHeight();
Pending pending = null;
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
final double x2 = getTimeScale().getEndingPosition(wink);
HColor back = colorDays.getColor(wink);
HColor back = thParam.getColor(wink);
// // Day of week should be stronger than period of time (back color).
// final HColor backDoW = colorDaysOfWeek.get(wink.getDayOfWeek());
// if (backDoW != null) {

View File

@ -82,47 +82,43 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
private void drawCalendar(final UGraphic ug, double totalHeightWithoutFooter) {
printDaysOfMonth(ug);
printSmallVbars(ug, totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
printMonths(ug);
}
private void printMonths(final UGraphic ug) {
MonthYear last = null;
double lastChangeMonth = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (wink.monthYear().equals(last) == false) {
drawVbar(ug, x1, 0, Y_POS_ROW16(), false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, (double) 0, Y_POS_ROW16());
if (last != null)
printMonth(ug, last, lastChangeMonth, x1);
}
lastChangeMonth = x1;
last = wink.monthYear();
}
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, Y_POS_ROW16(), false);
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChangeMonth) {
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, Y_POS_ROW16());
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChangeMonth)
printMonth(ug, last, lastChangeMonth, x1);
}
}
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
@Override
protected void printVerticalSeparators(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = getMin(); wink.compareTo(getMax()) <= 0; wink = wink.increment())
if (wink.getDayOfWeek() == weekNumberStrategy.getFirstDayOfWeek())
drawVbar(ug, getTimeScale().getStartingPosition(wink), Y_POS_ROW16(), totalHeightWithoutFooter, false);
drawVbar(ug, getTimeScale().getEndingPosition(max), Y_POS_ROW16(), totalHeightWithoutFooter, false);
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
if (isBold(wink))
drawVbar(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(), totalHeightWithoutFooter,
isBold(wink));
drawVline(ug.apply(getLineColor()), getTimeScale().getStartingPosition(wink), Y_POS_ROW16(), totalHeightWithoutFooter);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), Y_POS_ROW16(), totalHeightWithoutFooter);
super.printVerticalSeparators(ug, totalHeightWithoutFooter);
}
private void printDaysOfMonth(final UGraphic ug) {
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
if (wink.getDayOfWeek() == weekNumberStrategy.getFirstDayOfWeek()) {
final String num;
if (withCalendarDate)

View File

@ -61,18 +61,11 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
public void drawTimeHeader(final UGraphic ug, double totalHeightWithoutFooter) {
drawTextsBackground(ug, totalHeightWithoutFooter);
drawYears(ug);
printSmallVbars(ug, totalHeightWithoutFooter);
printVerticalSeparators(ug, totalHeightWithoutFooter);
drawHline(ug, 0);
drawHline(ug, getFullHeaderHeight());
}
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment())
if (isBold(wink))
drawVbar(ug, getTimeScale().getStartingPosition(wink), getFullHeaderHeight(), totalHeightWithoutFooter,
isBold(wink));
}
@Override
public void drawTimeFooter(UGraphic ug) {
ug = ug.apply(UTranslate.dy(3));
@ -84,22 +77,22 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
private void drawYears(final UGraphic ug) {
MonthYear last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
for (Day wink = getMin(); wink.compareTo(getMax()) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (last == null || wink.monthYear().year() != last.year()) {
drawVbar(ug, x1, 0, 19, false);
if (last != null) {
drawVline(ug.apply(getLineColor()), x1, (double) 0, (double) 19);
if (last != null)
printYear(ug, last, lastChange, x1);
}
lastChange = x1;
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
final double x1 = getTimeScale().getStartingPosition(getMax().increment());
if (x1 > lastChange)
printYear(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 19, false);
drawVline(ug.apply(getLineColor()), getTimeScale().getEndingPosition(getMax()), (double) 0, (double) 19);
}
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {

View File

@ -47,7 +47,35 @@ import net.sourceforge.plantuml.regex.RegexResult;
public class ComplementDate implements Something {
private final Type type;
static enum Type {
ANY, ONLY_RELATIVE, ONLY_ABSOLUTE;
}
private ComplementDate(Type type) {
this.type = type;
}
public static ComplementDate any() {
return new ComplementDate(Type.ANY);
}
public static ComplementDate onlyRelative() {
return new ComplementDate(Type.ONLY_RELATIVE);
}
public static ComplementDate onlyAbsolute() {
return new ComplementDate(Type.ONLY_ABSOLUTE);
}
public IRegex toRegex(String suffix) {
switch (type) {
case ONLY_ABSOLUTE:
return new RegexOr(toRegexA(suffix), toRegexB(suffix), toRegexC(suffix));
case ONLY_RELATIVE:
return new RegexOr(toRegexD(suffix), toRegexE(suffix));
}
return new RegexOr(toRegexA(suffix), toRegexB(suffix), toRegexC(suffix), toRegexD(suffix), toRegexE(suffix));
}
@ -98,21 +126,21 @@ public class ComplementDate implements Something {
}
public Failable<Day> getMe(GanttDiagram system, RegexResult arg, String suffix) {
if (arg.get("ADAY" + suffix, 0) != null) {
if (arg.get("ADAY" + suffix, 0) != null)
return Failable.ok(resultA(arg, suffix));
}
if (arg.get("BDAY" + suffix, 0) != null) {
if (arg.get("BDAY" + suffix, 0) != null)
return Failable.ok(resultB(arg, suffix));
}
if (arg.get("CDAY" + suffix, 0) != null) {
if (arg.get("CDAY" + suffix, 0) != null)
return Failable.ok(resultC(arg, suffix));
}
if (arg.get("DCOUNT" + suffix, 0) != null) {
if (arg.get("DCOUNT" + suffix, 0) != null)
return Failable.ok(resultD(system, arg, suffix));
}
if (arg.get("ECOUNT" + suffix, 0) != null) {
if (arg.get("ECOUNT" + suffix, 0) != null)
return Failable.ok(resultE(system, arg, suffix));
}
throw new IllegalStateException();
}

View File

@ -44,7 +44,7 @@ import net.sourceforge.plantuml.project.time.Day;
public class SentenceHappensDate extends SentenceSimple {
public SentenceHappensDate() {
super(SubjectTask.ME, Verbs.happens, new ComplementDate());
super(SubjectTask.ME, Verbs.happens, ComplementDate.any());
}
@Override

View File

@ -43,7 +43,7 @@ import net.sourceforge.plantuml.project.time.Day;
public class SentencePausesDate extends SentenceSimple {
public SentencePausesDate() {
super(SubjectTask.ME, Verbs.pauses, new ComplementDate());
super(SubjectTask.ME, Verbs.pauses, ComplementDate.any());
}
@Override

View File

@ -43,7 +43,7 @@ import net.sourceforge.plantuml.project.time.Day;
public class SentenceTaskEndsAbsolute extends SentenceSimple {
public SentenceTaskEndsAbsolute() {
super(SubjectTask.ME, Verbs.ends2, new ComplementDate());
super(SubjectTask.ME, Verbs.ends2, ComplementDate.any());
}
@Override

View File

@ -43,7 +43,7 @@ import net.sourceforge.plantuml.project.time.Day;
public class SentenceTaskStartsAbsolute extends SentenceSimple {
public SentenceTaskStartsAbsolute() {
super(SubjectTask.ME, Verbs.starts3, new ComplementDate());
super(SubjectTask.ME, Verbs.starts3, ComplementDate.any());
}
@Override
@ -52,7 +52,7 @@ public class SentenceTaskStartsAbsolute extends SentenceSimple {
final Day start = (Day) complement;
final Day startingDate = project.getStartingDate();
if (startingDate.getAbsoluteDayNum() == 0)
project.setProjectStartingDate(start);
return CommandExecutionResult.error("No starting date for the project");
task.setStart(start);
return CommandExecutionResult.ok();

View File

@ -0,0 +1,58 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://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.project.lang;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.core.Task;
import net.sourceforge.plantuml.project.time.Day;
public class SentenceTaskStartsOnlyRelative extends SentenceSimple {
public SentenceTaskStartsOnlyRelative() {
super(SubjectTask.ME, Verbs.starts3, ComplementDate.onlyRelative());
}
@Override
public CommandExecutionResult execute(GanttDiagram project, Object subject, Object complement) {
final Task task = (Task) subject;
final Day start = (Day) complement;
task.setStart(start);
return CommandExecutionResult.ok();
}
}

View File

@ -68,7 +68,7 @@ public class SubjectProject implements Subject {
class Starts extends SentenceSimple {
public Starts() {
super(SubjectProject.this, Verbs.starts, new ComplementDate());
super(SubjectProject.this, Verbs.starts, ComplementDate.onlyAbsolute());
}
@Override

View File

@ -63,7 +63,8 @@ public class SubjectResource implements Subject {
}
public Collection<? extends SentenceSimple> getSentences() {
return Arrays.asList(new IsOffDate(), new IsOffDates(), new IsOffDayOfWeek(), new IsOnDate(), new IsOnDates());
return Arrays.asList(new IsOffDate(), new IsOffDates(), new IsOffDayOfWeek(), new IsOnDate(), new IsOnDates(),
new IsOffBeforeDate(), new IsOffAfterDate());
}
public IRegex toRegex() {
@ -72,10 +73,42 @@ public class SubjectResource implements Subject {
);
}
public class IsOffBeforeDate extends SentenceSimple {
public IsOffBeforeDate() {
super(SubjectResource.this, Verbs.isOffBefore, ComplementDate.any());
}
@Override
public CommandExecutionResult execute(GanttDiagram project, Object subject, Object complement) {
final Resource resource = (Resource) subject;
final Day when = (Day) complement;
resource.setOffBeforeDate(when);
return CommandExecutionResult.ok();
}
}
public class IsOffAfterDate extends SentenceSimple {
public IsOffAfterDate() {
super(SubjectResource.this, Verbs.isOffAfter, ComplementDate.any());
}
@Override
public CommandExecutionResult execute(GanttDiagram project, Object subject, Object complement) {
final Resource resource = (Resource) subject;
final Day when = (Day) complement;
resource.setOffAfterDate(when);
return CommandExecutionResult.ok();
}
}
public class IsOffDate extends SentenceSimple {
public IsOffDate() {
super(SubjectResource.this, Verbs.isOff, new ComplementDate());
super(SubjectResource.this, Verbs.isOff, ComplementDate.any());
}
@Override
@ -123,7 +156,7 @@ public class SubjectResource implements Subject {
public class IsOnDate extends SentenceSimple {
public IsOnDate() {
super(SubjectResource.this, Verbs.isOn, new ComplementDate());
super(SubjectResource.this, Verbs.isOn, ComplementDate.any());
}
@Override

View File

@ -69,7 +69,7 @@ public class SubjectSeparator implements Subject {
class JustBefore extends SentenceSimple {
public JustBefore() {
super(SubjectSeparator.this, Verbs.justBefore, new ComplementDate());
super(SubjectSeparator.this, Verbs.justBefore, ComplementDate.any());
}
@Override
@ -85,7 +85,7 @@ public class SubjectSeparator implements Subject {
class JustAfter extends SentenceSimple {
public JustAfter() {
super(SubjectSeparator.this, Verbs.justAfter, new ComplementDate());
super(SubjectSeparator.this, Verbs.justAfter, ComplementDate.any());
}
@Override

View File

@ -81,11 +81,11 @@ public class SubjectTask implements Subject {
public Collection<? extends SentenceSimple> getSentences() {
return Arrays.asList(new SentenceLasts(), new SentenceTaskStarts(), new SentenceTaskStartsWithColor(),
new SentenceTaskStartsAbsolute(), new SentenceHappens(), new SentenceHappensDate(), new SentenceEnds(),
new SentenceTaskEndsAbsolute(), new SentenceIsColored(), new SentenceIsColoredForCompletion(),
new SentenceIsDeleted(), new SentenceIsForTask(), new SentenceLinksTo(), new SentenceOccurs(),
new SentenceDisplayOnSameRowAs(), new SentencePausesDate(), new SentencePausesDates(),
new SentencePausesDayOfWeek());
new SentenceTaskStartsOnlyRelative(), new SentenceTaskStartsAbsolute(), new SentenceHappens(),
new SentenceHappensDate(), new SentenceEnds(), new SentenceTaskEndsAbsolute(), new SentenceIsColored(),
new SentenceIsColoredForCompletion(), new SentenceIsDeleted(), new SentenceIsForTask(),
new SentenceLinksTo(), new SentenceOccurs(), new SentenceDisplayOnSameRowAs(), new SentencePausesDate(),
new SentencePausesDates(), new SentencePausesDayOfWeek());
}
public IRegex toRegex() {

View File

@ -90,7 +90,7 @@ public class SubjectToday implements Subject {
class IsDate extends SentenceSimple {
public IsDate() {
super(SubjectToday.this, Verbs.is, new ComplementDate());
super(SubjectToday.this, Verbs.is, ComplementDate.any());
}
@Override

View File

@ -70,17 +70,33 @@ public class Verbs {
new RegexLeaf("off"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexLeaf("from"), //
new RegexLeaf("on"), //
new RegexLeaf("for"), //
new RegexLeaf("the"), //
new RegexLeaf("at") //
));
public static IRegex isOffBefore = new RegexConcat(new RegexLeaf("is"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("off"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("before") //
);
public static IRegex isOffAfter = new RegexConcat(new RegexLeaf("is"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("off"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("after") //
);
public static IRegex isOn = new RegexConcat(new RegexLeaf("is"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("on"), //
RegexLeaf.spaceOneOrMore(), //
new RegexOr(//
new RegexLeaf("from"), //
new RegexLeaf("on"), //
new RegexLeaf("for"), //
new RegexLeaf("the"), //

View File

@ -0,0 +1,44 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://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.project.solver;
public class ImpossibleSolvingException extends RuntimeException {
public ImpossibleSolvingException(String message) {
super(message);
}
}

View File

@ -41,7 +41,7 @@ import net.sourceforge.plantuml.project.core.TaskAttribute;
import net.sourceforge.plantuml.project.time.Day;
public class SolverImpl extends AbstractSolver implements Solver {
// ::remove folder when __HAXE__
// ::remove folder when __HAXE__
private final LoadPlanable loadPlanable;
@ -54,12 +54,17 @@ public class SolverImpl extends AbstractSolver implements Solver {
Day current = (Day) values.get(TaskAttribute.START);
int fullLoad = ((Load) values.get(TaskAttribute.LOAD)).getFullLoad();
int cpt = 0;
final Day lastDayIfAny = loadPlanable.getLastDayIfAny();
while (fullLoad > 0) {
fullLoad -= loadPlanable.getLoadAt(current);
current = current.increment();
if (lastDayIfAny != null && current.compareTo(lastDayIfAny) > 0)
throw new ImpossibleSolvingException(
"Because all resources will be off at some point, we cannot compute any end date for "
+ loadPlanable);
cpt++;
if (cpt > 100000)
throw new IllegalStateException();
throw new ImpossibleSolvingException("There is an issue in planning your tasks!");
}
return current.decrement();
@ -78,7 +83,7 @@ public class SolverImpl extends AbstractSolver implements Solver {
cpt++;
if (cpt > 100000)
throw new IllegalStateException();
throw new ImpossibleSolvingException("There is an issue in planning your tasks!");
}
return current.increment();

View File

@ -138,7 +138,8 @@ public enum SName {
undone, //
unstarted, //
usecase, //
verticalSeparator, //
visibilityIcon, //
private_, //
protected_, //

View File

@ -46,7 +46,7 @@ public class Version {
// Warning, "version" should be the same in gradle.properties and Version.java
// Any idea anyone how to magically synchronize those :-) ?
private static final String version = "1.2023.13beta2";
private static final String version = "1.2023.13beta3";
public static String versionString() {
return version;