Add some Gantt improvement

This commit is contained in:
Arnaud Roques 2021-04-07 20:02:23 +02:00
parent 623df3e323
commit f69cfcd011
41 changed files with 629 additions and 366 deletions

View File

@ -273,10 +273,23 @@ milestone {
}
ganttDiagram {
arrow {
LineThickness 1.5
}
note {
FontSize 9
Shadowing 0.0
}
separator {
FontSize 11
FontStyle plain
BackGroundColor transparent
Margin 5
Padding 5
}
timeline {
BackgroundColor transparent
}
}

View File

@ -69,28 +69,28 @@ public class PSystemDonors extends PlainDiagram {
private static final int COLS = 6;
private static final int FREE_LINES = 6;
public static final String DONORS = "6neD0AmFkBap0wp4H6CjU-RENbb-8cPf4i7oFA4uiOZJNK3y0UwT7lSRwI-YAxltJJEYrckJSaPHV13q"
+ "W7UtXVQXzBy-27EYV0Z-tGWU80D4ITH6ZIpt9Djjcof3Il3lEr_v9UWTth51ehbAgiMHwq-_8GFlEsFp"
+ "x3GsNZsQe2y2FmRsrPzVStLjuA5OdYSeWP8k4zg9ecxlNzf8nq_W_vEaQXTjwOuqQQIX0ZigyDXNVjMr"
+ "yr6ZoQeOCKMAhnNIyEcD2GqvwNs2RD2Wy4Fz4Dvihh2KSIOGHniYT7szjcFRYE4NIdpOvGwnm93074Wv"
+ "qXTHzDnGK70BOAYRnMniIUN8anHGP4CBUVE7UbBnI3bpEbmKF1u0WSypg42aDMhGXBFvmu2A8zcYmn9N"
+ "dHatbkPnM9xIHjBmD6BXOK4he8OW_uCkyBHOuwEfirqDZgIU9hbtMudwiztRkJOh-aRN9WdhQ-kbMMnS"
+ "KSeIgQvjV8xscaS0xfPQEUBBw2EK0pJxpQkAh7wqGFm8T5zDs98_otwma0bXRSC-KDUv-l2OHJWcGwQ9"
+ "TVnkjhsclT35TZOWOGLOfFVahpDDS50BNOay0ZoXLSnbdGyKqjBg_QB7mzfzmZN54lU6HEzzXANqtw_w"
+ "C3CK1-X0cLdGJHCidT6qQY-s889wX8uEk2aaLyAvkox7xkCYVUGd0DvKUa0E6pkD4CylKsaw2g4QqdLD"
+ "cXN0v6cbBGfUInYKQnDqCwe4GsMrskDqTQOl6nFtIHyyRpKO8t5CPwelB7UlYhGmB5QDPcspTe3c55pX"
+ "upYlUizShWAqjl0UyS4z_yY0dkcLWKYH8VTj6_wHfLc5nIpMN3UhqbtL3suUkld0NIoQnOmoUSXKQ1nA"
+ "H4lzIkId9SFV76HLVwqkzWusf-kC46567DnUcbnJasCARjDPZeCDGcIenIjESSBv1NjOLf8jR0gLPwmU"
+ "XOJyZlaa8bNwGcd0hk6km3EIHq4UpdjWrR9wRIh91LIHpGH1QS6gbYgEzBL01iQQzCoqHcn_Mc31MDfZ"
+ "T2mx5BrYegtA3JAcm4mJwXS6aIWrr4lfPKuI4VYVFtUf9yrraECxO_Xa74Jsa4I0AkJkZ1DLJztjw3QC"
+ "zH9_lrxApKVmvrzxjCcfqUxvQOBGEeWAG0ylu5Bk5thmDF3Ns30JS8WLLFGYuSfLIuy32GisuvrTrBbb"
+ "HkCc9ikDoKMlo0zL_5lS2XVJ8JRek0YcE5eigTBBpMfGSRPlVjVX8eUEVuagGoAvhDKo6GaUXLcScsDV"
+ "RHYQjd834bH7RG9hT_rsckMkCUSha9g6oq2-tP1JgHQXXMfgMjuN0gl5sD_Rj9zoMlmd0_quhRNZgXuQ"
+ "3d9qVRk9XczRsDiPFOdX8cP3XFwLEISSUFZ6Zxoe5ah3qhOPTgvWXVm6NiOB2OViu0EJMbwbh793Zhw5"
+ "x1tLA3y1H3N1WGmiLkYQn48fnmCfae8vPyjeXfI3Fk2idW2Sec1_Vsz1E2tH_8ncxUqPXMGksznDPX3n"
+ "S7u6YPfCsUgH0_jYvhBDAt8xQf4EE_Rj-8xpxO-ecmSHo84e9i5hTQ4FD_QQfM5JVAxJu3ukS_DcyWku"
+ "5EqyPM1hc6n1bh8Pg7WIWDX1faBvrVwh-OWjvnJvztvZAWmquNdYDBhnN0is8rjjH4eQq7AHXT_wViTD"
+ "JWvCd1BPydFDONPw64xHwHK0";
public static final String DONORS = "6sWD0AmFkBap0wp4H6CjU-RENbb-8cPf4i7oFA4uiOZJNK3y0UwT7lSRwI-YAxltJJEYrckJSaPHV13q"
+ "W7UtXVQXzBy-27EYV0Z-tGWU80D4ITH6jIptfDXjcof3Il3lEr_v9UWTth51eZbAgyMHwq-_8GFlEsFp"
+ "x3GsNZsQe2y2FmRsrVzTJelBGo7Cqcm5Hc3KQOHRtMF_7mLLrwXs9rN3JZ-cKxagXgkYAh7PzgQ8LjBS"
+ "CIlKjVDHeyb5CMafKjoja8RRw4neoCdi4sI31eqVweVmPdE5fOmpWJZQ4A7hwxqT-quilr3YWyWHOe7X"
+ "WJcGSbWMKUBSKD1m262ecqKrjgHopnCZAFpGGjxyeP5KF5BEd0uN3QS7GE3s32gGz44Dcd1sw6v0nP5i"
+ "qM69gwwC6qlpTLYUoXv9myt4mic2La0DGVu7NU3fiSP7KsVR38wadYPvdROIzMVYxRJD1NsZQvE4zRMr"
+ "QQQFAqLP8jMrZS_HNlC8mDrIAw_uCkQ8vm3DVlEg8giVBP0VWUwh2LloPzdlB2GXh6tO1-ewLnyULOHZ"
+ "CcIQMCVlPjjhsIzq1IORaB02BEdlXgyhJN2mXQvS7W6Uq2gcMUS3XRIqUh_eyMNjFk6QOebxuwBtCS9I"
+ "-kzNVPWPYWDqeCmiw9e5Yt8rhTgBBOXWZz2f0JU5P2ESLzVbkFguI1_v2O2ta16GmuRG2F7yaahNKGZL"
+ "aQbhqbm0p9zMsgBXieH1kNP1DwDAB5HMgprELsVwiZ5td_J1yrQ3COfZEgcniDozAjB3i5WrchDtQqTf"
+ "Ji4p-JZEgzvpC5S1hYsyHtnmppyo46TwPI1ISiXZtuT_PEbMOJ6BDjVDgdHNzOE3Xsu-S3UBPZ6ZJ1wo"
+ "B1WSJqHB_KhafoN3tq78PlbhTR5Fi3bTfuO8CxBWzjBacfeSqt2OpdAix2A4HorUSIeeN4ImbwKbsSAc"
+ "K7d6wb58oE-OJo9IMHPA0zQMkmBFf7iKvE6y1rOjgrjJIIwWYcmcY4aBLhLKSQIl1J9mhQ9dfdLY-zC2"
+ "2-hI7cFY38VYAoRQgjoGWIamCqJuXK4afW-afVIIaqG4_kVFNUgbrphuyPqnV38EaZqa4L15ndJgYMgc"
+ "xdOC6yPwYRzVB-Nc8_ZphptQvDHez_mCGRGE4W8mmWkubFk54JmD_7Ksz08EiKA8DXAkNBNqB92mO3FU"
+ "kObwS9jHlOd9ScDoqIloGnN_DfMeS38swBY8fJXQBAdIoyrgK0Ljt_okmqqEYh-BAaCYkUpDpcGaR1Ig"
+ "E3V7RcqOch4P0tXG7RK9jDtrsscMLuqvNv5K6Pu6vDiDEPNg4LfOKzFoiH1OBSRjlQNzbDFZFnde5zGw"
+ "-zYhXuQ3N5tVRgBXMnUadp6I62vITaJGMsfEBF3mJGHvKIsKZgLjC-pimGhv3RoC5n8EsS47abfUfQno"
+ "GmxTGlQEQfIVAAA6i40kB5ReAcAXbEE154d1dDKoaI7be2_OrnE0KnGSx-yj29UTQ7v6i_RsZ48obsxk"
+ "9XL4DfoVHMAJagqUER2VbhbiyuhSZbgamuvzExxZVFiZwkQB2382CIq9NgiBVNTZbraQDjEUwpGuZilS"
+ "F9Zy0dP5EqyPs1ecMv2bR0OgdWGWTiYWmenNyglvY6lE1VBl_KOf33JXUU8qkl5S2rQHhJOY9GrekSaI"
+ "klRzZfkS72YSM6nmOOcvqSC4YawlKsq_QRCiWqeKBXLVsCEiPbEgV6JOGNFPQkVLzWG0";
/*
* Special thanks to our sponsors and donors:

View File

@ -51,21 +51,21 @@ class USymbolPerson extends USymbol {
return SkinParameter.PERSON;
}
private void drawRect(UGraphic ug, double width, double height, boolean shadowing, double roundCorner,
double diagonalCorner) {
final UEllipse head = new UEllipse(headSize(), headSize());
final URectangle body = new URectangle(width, height - headSize()).rounded(headSize());
private void drawHeadAndBody(UGraphic ug, boolean shadowing, Dimension2D dimBody, double headSize) {
final UEllipse head = new UEllipse(headSize, headSize);
final URectangle body = new URectangle(dimBody).rounded(headSize);
if (shadowing) {
body.setDeltaShadow(3.0);
head.setDeltaShadow(1.0);
}
final double posx = (width - headSize()) / 2;
final double posx = (dimBody.getWidth() - headSize) / 2;
ug.apply(UTranslate.dx(posx)).draw(head);
ug.apply(UTranslate.dy(headSize())).draw(body);
ug.apply(UTranslate.dy(headSize)).draw(body);
}
private double headSize() {
return 20;
private double headSize(Dimension2D dimBody) {
final double surface = dimBody.getWidth() * dimBody.getHeight();
return Math.sqrt(surface) * .42;
}
private Margin getMargin() {
@ -78,21 +78,26 @@ class USymbolPerson extends USymbol {
return new AbstractTextBlock() {
public void drawU(UGraphic ug) {
final Dimension2D dim = calculateDimension(ug.getStringBounder());
ug = UGraphicStencil.create(ug, dim);
final Dimension2D dimFull = calculateDimension(ug.getStringBounder());
final Dimension2D dimBody = bodyDimension(ug.getStringBounder());
ug = UGraphicStencil.create(ug, dimFull);
ug = symbolContext.apply(ug);
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
symbolContext.getRoundCorner(), symbolContext.getDiagonalCorner());
final Margin margin = getMargin();
final double headSize = headSize(dimBody);
drawHeadAndBody(ug, symbolContext.isShadowing(), dimBody, headSize);
final TextBlock tb = TextBlockUtils.mergeTB(stereotype, label, stereoAlignment);
tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1() + headSize())));
final Margin margin = getMargin();
tb.drawU(ug.apply(new UTranslate(margin.getX1(), margin.getY1() + headSize)));
}
public Dimension2D calculateDimension(StringBounder stringBounder) {
final Dimension2D body = bodyDimension(stringBounder);
return Dimension2DDouble.delta(body, 0, headSize(body));
}
private Dimension2D bodyDimension(StringBounder stringBounder) {
final Dimension2D dimLabel = label.calculateDimension(stringBounder);
final Dimension2D dimStereo = stereotype.calculateDimension(stringBounder);
return Dimension2DDouble.delta(getMargin().addDimension(Dimension2DDouble.mergeTB(dimStereo, dimLabel)),
0, headSize());
return getMargin().addDimension(Dimension2DDouble.mergeTB(dimStereo, dimLabel));
}
};
}
@ -101,39 +106,7 @@ class USymbolPerson extends USymbol {
public TextBlock asBig(final TextBlock title, final HorizontalAlignment labelAlignment, final TextBlock stereotype,
final double width, final double height, final SymbolContext symbolContext,
final HorizontalAlignment stereoAlignment) {
return new AbstractTextBlock() {
public void drawU(UGraphic ug) {
final Dimension2D dim = calculateDimension(ug.getStringBounder());
ug = symbolContext.apply(ug);
drawRect(ug, dim.getWidth(), dim.getHeight(), symbolContext.isShadowing(),
symbolContext.getRoundCorner(), 0);
final Dimension2D dimStereo = stereotype.calculateDimension(ug.getStringBounder());
final double posStereoX;
final double posStereoY;
if (stereoAlignment == HorizontalAlignment.RIGHT) {
posStereoX = width - dimStereo.getWidth() - getMargin().getX1() / 2;
posStereoY = getMargin().getY1() / 2;
} else {
posStereoX = (width - dimStereo.getWidth()) / 2;
posStereoY = 2;
}
stereotype.drawU(ug.apply(new UTranslate(posStereoX, posStereoY)));
final Dimension2D dimTitle = title.calculateDimension(ug.getStringBounder());
final double posTitle;
if (labelAlignment == HorizontalAlignment.LEFT) {
posTitle = 3;
} else if (labelAlignment == HorizontalAlignment.RIGHT) {
posTitle = width - dimTitle.getWidth() - 3;
} else {
posTitle = (width - dimTitle.getWidth()) / 2;
}
title.drawU(ug.apply(new UTranslate(posTitle, 2 + dimStereo.getHeight())));
}
public Dimension2D calculateDimension(StringBounder stringBounder) {
return new Dimension2DDouble(width, height);
}
};
throw new UnsupportedOperationException();
}
}

View File

@ -35,6 +35,8 @@
*/
package net.sourceforge.plantuml.oregon;
import static net.sourceforge.plantuml.graphic.GraphicStrings.createGreenOnBlackMonospaced;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@ -44,8 +46,7 @@ import net.sourceforge.plantuml.PlainDiagram;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.core.DiagramDescription;
import net.sourceforge.plantuml.graphic.UDrawable;
import static net.sourceforge.plantuml.graphic.GraphicStrings.createGreenOnBlackMonospaced;
import net.sourceforge.plantuml.ugraphic.ImageBuilder;
public class PSystemOregon extends PlainDiagram {
@ -65,6 +66,11 @@ public class PSystemOregon extends PlainDiagram {
}
}
@Override
public ImageBuilder createImageBuilder(FileFormatOption fileFormatOption) throws IOException {
return super.createImageBuilder(fileFormatOption).blackBackcolor();
}
public PSystemOregon() {
this.inputs = new ArrayList<String>();
}

View File

@ -36,18 +36,20 @@
package net.sourceforge.plantuml.project;
import net.sourceforge.plantuml.Direction;
import net.sourceforge.plantuml.cucadiagram.LinkType;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.graphic.UDrawable;
import net.sourceforge.plantuml.project.core.Task;
import net.sourceforge.plantuml.project.core.TaskAttribute;
import net.sourceforge.plantuml.project.core.TaskInstant;
import net.sourceforge.plantuml.project.draw.TaskDraw;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public class GanttArrow implements UDrawable {
@ -56,15 +58,16 @@ public class GanttArrow implements UDrawable {
private final TaskInstant source;
private final Direction atEnd;
private final TaskInstant dest;
private final HColor color;
private final LinkType style;
private final HColorSet colorSet;
private final Style style;
private final ToTaskDraw toTaskDraw;
public GanttArrow(TimeScale timeScale, TaskInstant source, TaskInstant dest, HColor color, LinkType style,
public GanttArrow(HColorSet colorSet, Style style, TimeScale timeScale, TaskInstant source, TaskInstant dest,
ToTaskDraw toTaskDraw) {
this.toTaskDraw = toTaskDraw;
this.style = style;
this.color = color;
this.colorSet = colorSet;
this.timeScale = timeScale;
this.source = source;
this.dest = dest;
@ -94,17 +97,19 @@ public class GanttArrow implements UDrawable {
}
public void drawU(UGraphic ug) {
// ug = ug.apply(color.bg()).apply(color).apply(new UStroke(1.5));
ug = ug.apply(color.bg()).apply(color).apply(style.getStroke3(new UStroke(1.5)));
ug = style.applyStrokeAndLineColor(ug, colorSet);
// ug = ug.apply(color.bg()).apply(color).apply(style.getStroke3(new
// UStroke(1.5)));
double x1 = getX(source.withDelta(0), atStart);
double y1 = getSource().getY(atStart);
final StringBounder stringBounder = ug.getStringBounder();
double y1 = getSource().getY(stringBounder, atStart);
final double x2 = getX(dest, atEnd.getInv());
final double y2 = getDestination().getY(atEnd);
final double y2 = getDestination().getY(stringBounder, atEnd);
if (atStart == Direction.DOWN && y2 < y1) {
y1 = getSource().getY(atStart.getInv());
y1 = getSource().getY(stringBounder, atStart.getInv());
}
if (this.atStart == Direction.DOWN && this.atEnd == Direction.RIGHT) {
@ -115,7 +120,7 @@ public class GanttArrow implements UDrawable {
drawLine(ug, x1, y1, x1, y2, x2, y2);
} else {
x1 = getX(source.withDelta(0), Direction.RIGHT);
y1 = getSource().getY(Direction.RIGHT);
y1 = getSource().getY(stringBounder, Direction.RIGHT);
drawLine(ug, x1, y1, x1 + 6, y1, x1 + 6, y1 + 8, x2 - 8, y1 + 8, x2 - 8, y2, x2, y2);
}
} else if (this.atStart == Direction.RIGHT && this.atEnd == Direction.LEFT) {
@ -130,7 +135,7 @@ public class GanttArrow implements UDrawable {
throw new IllegalArgumentException();
}
ug = ug.apply(new UStroke(1.5));
ug = ug.apply(new UStroke(1.5)).apply(style.value(PName.LineColor).asColor(colorSet).bg());
ug.apply(new UTranslate(x2, y2)).draw(Arrows.asTo(atEnd));
}

View File

@ -44,20 +44,35 @@ import net.sourceforge.plantuml.project.core.TaskAttribute;
import net.sourceforge.plantuml.project.core.TaskInstant;
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.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public class GanttConstraint extends WithLinkType {
private final TaskInstant source;
private final TaskInstant dest;
private final StyleBuilder styleBuilder;
private final HColorSet colorSet;
public GanttConstraint(TaskInstant source, TaskInstant dest, HColor forcedColor) {
public GanttConstraint(HColorSet colorSet, StyleBuilder styleBuilder, TaskInstant source, TaskInstant dest,
HColor forcedColor) {
this.styleBuilder = styleBuilder;
this.colorSet = colorSet;
this.source = source;
this.dest = dest;
this.type = new LinkType(LinkDecor.NONE, LinkDecor.NONE);
this.setSpecificColor(forcedColor);
}
public GanttConstraint(HColorSet colorSet, StyleBuilder styleBuilder, TaskInstant source, TaskInstant dest) {
this(colorSet, styleBuilder, source, dest, null);
}
public boolean isOn(Task task) {
return source.getMoment() == task || dest.getMoment() == task;
}
@ -73,20 +88,20 @@ public class GanttConstraint extends WithLinkType {
return false;
}
public GanttConstraint(TaskInstant source, TaskInstant dest) {
this(source, dest, null);
}
@Override
public String toString() {
return source.toString() + " --> " + dest.toString();
}
public UDrawable getUDrawable(TimeScale timeScale, HColor color, ToTaskDraw toTaskDraw) {
if (getSpecificColor() == null) {
return new GanttArrow(timeScale, source, dest, color, getType(), toTaskDraw);
}
return new GanttArrow(timeScale, source, dest, getSpecificColor(), getType(), toTaskDraw);
final public StyleSignature getStyleSignature() {
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.arrow);
}
public UDrawable getUDrawable(TimeScale timeScale, ToTaskDraw toTaskDraw) {
Style style = styleBuilder.getMergedStyle(getStyleSignature()).eventuallyOverride(PName.LineColor,
getSpecificColor());
style = style.eventuallyOverride(getType().getStroke3(style.getStroke()));
return new GanttArrow(colorSet, style, timeScale, source, dest, toTaskDraw);
}
public boolean isHidden(Day min, Day max) {

View File

@ -86,6 +86,7 @@ import net.sourceforge.plantuml.project.draw.TimeHeaderYearly;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft;
import net.sourceforge.plantuml.style.PName;
@ -95,6 +96,7 @@ import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
@ -115,8 +117,12 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private final Map<DayOfWeek, HColor> colorDaysOfWeek = new HashMap<DayOfWeek, HColor>();
private final Map<Day, String> nameDays = new HashMap<Day, String>();
// Let's follow ISO-8601 rules
private WeekNumberStrategy weekNumberStrategy = new WeekNumberStrategy(DayOfWeek.MONDAY, 4);
private PrintScale printScale = PrintScale.DAILY;
private Integer compress;
private double factorScale = 1.0;
private Day today;
private double totalHeightWithoutFooter;
private Day min = Day.create(0);
@ -125,12 +131,14 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private Day printStart;
private Day printEnd;
private HColor linksColor = null;
public DiagramDescription getDescription() {
return new DiagramDescription("(Project)");
}
public void setWeekNumberStrategy(DayOfWeek firstDayOfWeek, int minimalDaysInFirstWeek) {
this.weekNumberStrategy = new WeekNumberStrategy(firstDayOfWeek, minimalDaysInFirstWeek);
}
public GanttDiagram() {
super(UmlDiagramType.GANTT);
}
@ -167,24 +175,19 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
protected ImageData exportDiagramNow(OutputStream os, int index, FileFormatOption fileFormatOption)
throws IOException {
final StringBounder stringBounder = fileFormatOption.getDefaultStringBounder(getSkinParam());
return createImageBuilder(fileFormatOption)
.drawable(getTextBlock(stringBounder))
.write(os);
return createImageBuilder(fileFormatOption).drawable(getTextBlock(stringBounder)).write(os);
}
public void setPrintScale(PrintScale printScale) {
this.printScale = printScale;
}
public void setCompress(int compress) {
this.compress = compress;
public void setFactorScale(double factorScale) {
this.factorScale = factorScale;
}
private int getCompress() {
if (this.compress != null) {
return this.compress;
}
return printScale.getCompress();
private double getFactorScale() {
return this.printScale.getDefaultScale() * this.factorScale;
}
private boolean isHidden(Task task) {
@ -212,7 +215,22 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
return new TextBlockBackcolored() {
public void drawU(UGraphic ug) {
final Style timelineStyle = StyleSignature
.of(SName.root, SName.element, SName.ganttDiagram, SName.timeline)
.getMergedStyle(getCurrentStyleBuilder());
final HColor back = timelineStyle.value(PName.BackGroundColor).asColor(getIHtmlColorSet());
if (HColorUtils.isTransparent(back) == false) {
final URectangle rect1 = new URectangle(calculateDimension(ug.getStringBounder()).getWidth(),
timeHeader.getTimeHeaderHeight());
final URectangle rect2 = new URectangle(calculateDimension(ug.getStringBounder()).getWidth(),
timeHeader.getTimeFooterHeight());
ug.apply(back.bg()).draw(rect1);
ug.apply(back.bg()).apply(UTranslate.dy(totalHeightWithoutFooter)).draw(rect2);
}
timeHeader.drawTimeHeader(ug, totalHeightWithoutFooter);
drawConstraints(ug, timeHeader.getTimeScale());
drawTasksRect(ug);
drawTasksTitle(ug);
@ -246,17 +264,17 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
if (openClose.getCalendar() == null) {
return new TimeHeaderSimple(min, max);
} else if (printScale == PrintScale.WEEKLY) {
return new TimeHeaderWeekly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
getCompress());
return new TimeHeaderWeekly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
colorDaysOfWeek, weekNumberStrategy);
} else if (printScale == PrintScale.MONTHLY) {
return new TimeHeaderMonthly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
getCompress());
return new TimeHeaderMonthly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
colorDaysOfWeek);
} else if (printScale == PrintScale.QUARTERLY) {
return new TimeHeaderQuarterly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
getCompress());
return new TimeHeaderQuarterly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
colorDaysOfWeek);
} else if (printScale == PrintScale.YEARLY) {
return new TimeHeaderYearly(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
getCompress());
return new TimeHeaderYearly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
colorDaysOfWeek);
} else {
return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
nameDays, printStart, printEnd);
@ -276,7 +294,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
continue;
}
final TaskDraw draw = draws.get(task);
final UTranslate move = UTranslate.dy(draw.getY());
final UTranslate move = UTranslate.dy(draw.getY(ug.getStringBounder()));
draw.drawU(ug.apply(move));
}
}
@ -286,19 +304,11 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
if (printStart != null && constraint.isHidden(min, max)) {
continue;
}
constraint.getUDrawable(timeScale, getLinkColor(), this).drawU(ug);
constraint.getUDrawable(timeScale, this).drawU(ug);
}
}
private HColor getLinkColor() {
if (linksColor == null) {
final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(getCurrentStyleBuilder());
return styleArrow.value(PName.LineColor).asColor(colorSet);
}
return linksColor;
}
public StyleSignature getDefaultStyleDefinitionArrow() {
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.arrow);
}
@ -309,7 +319,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
continue;
}
final TaskDraw draw = draws.get(task);
final UTranslate move = UTranslate.dy(draw.getY());
final UTranslate move = UTranslate.dy(draw.getY(ug1.getStringBounder()));
draw.drawTitle(ug1.apply(move));
}
}
@ -339,22 +349,24 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
for (Task task : tasks.values()) {
final TaskDraw draw;
if (task instanceof TaskSeparator) {
draw = new TaskDrawSeparator(((TaskSeparator) task).getName(), timeScale, y, min, max);
draw = new TaskDrawSeparator(((TaskSeparator) task).getName(), timeScale, y, min, max,
task.getStyleBuilder(), getSkinParam().getIHtmlColorSet());
} else {
final TaskImpl tmp = (TaskImpl) task;
if (tmp.isDiamond()) {
draw = new TaskDrawDiamond(timeScale, y, tmp.getPrettyDisplay(), getStart(tmp), getSkinParam(),
task, this);
task, this, task.getStyleBuilder(), getSkinParam().getIHtmlColorSet());
} else {
final boolean oddStart = printStart != null && min.compareTo(getStart(tmp)) == 0;
final boolean oddEnd = printStart != null && max.compareTo(getEnd(tmp)) == 0;
draw = new TaskDrawRegular(timeScale, y, tmp.getPrettyDisplay(), getStart(tmp), getEnd(tmp),
oddStart, oddEnd, getSkinParam(), task, this, getConstraints(task));
oddStart, oddEnd, getSkinParam(), task, this, getConstraints(task), task.getStyleBuilder(),
getSkinParam().getIHtmlColorSet());
}
draw.setColorsAndCompletion(tmp.getColors(), tmp.getCompletion(), tmp.getUrl(), tmp.getNote());
}
if (task.getRow() == null) {
y += draw.getHeightTask();
y += draw.getHeightTask(stringBounder);
}
draws.put(task, draw);
}
@ -385,7 +397,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private double lastY(StringBounder stringBounder) {
double result = 0;
for (TaskDraw td : draws.values()) {
result = Math.max(result, td.getY() + td.getHeightMax(stringBounder));
result = Math.max(result, td.getY(stringBounder) + td.getHeightMax(stringBounder));
}
return result;
}
@ -393,7 +405,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
private boolean magicPushOnce(StringBounder stringBounder) {
final List<FingerPrint> notes = new ArrayList<FingerPrint>();
for (TaskDraw td : draws.values()) {
final FingerPrint taskPrint = td.getFingerPrint();
final FingerPrint taskPrint = td.getFingerPrint(stringBounder);
for (FingerPrint note : notes) {
final double deltaY = note.overlap(taskPrint);
if (deltaY > 0) {
@ -504,7 +516,8 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
public GanttConstraint forceTaskOrder(Task task1, Task task2) {
final TaskInstant end1 = new TaskInstant(task1, TaskAttribute.END);
task2.setStart(end1.getInstantPrecise());
final GanttConstraint result = new GanttConstraint(end1, new TaskInstant(task2, TaskAttribute.START));
final GanttConstraint result = new GanttConstraint(this.getIHtmlColorSet(),
getSkinParam().getCurrentStyleBuilder(), end1, new TaskInstant(task2, TaskAttribute.START));
addContraint(result);
return result;
}
@ -528,7 +541,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
if (linkedToPrevious) {
previous = getLastCreatedTask();
}
result = new TaskImpl(code, openClose);
result = new TaskImpl(getSkinParam().getCurrentStyleBuilder(), code, openClose);
tasks.put(code, result);
if (byShortName != null) {
byShortName.put(shortName, result);
@ -551,7 +564,7 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
}
public void addSeparator(String comment) {
TaskSeparator separator = new TaskSeparator(comment, tasks.size());
TaskSeparator separator = new TaskSeparator(getSkinParam().getCurrentStyleBuilder(), comment, tasks.size());
tasks.put(separator.getCode(), separator);
}
@ -699,10 +712,6 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
this.printEnd = end;
}
public void setLinksColor(HColor color) {
this.linksColor = color;
}
public TaskDraw getTaskDraw(Task task) {
return draws.get(task);
}
@ -733,4 +742,5 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
public ClockwiseTopRightBottomLeft getDefaultMargins() {
return ClockwiseTopRightBottomLeft.none();
}
}

View File

@ -53,6 +53,7 @@ import net.sourceforge.plantuml.project.command.CommandPage;
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.CommandWeekNumberStrategy;
import net.sourceforge.plantuml.project.command.NaturalCommand;
import net.sourceforge.plantuml.project.lang.SentenceAnd;
import net.sourceforge.plantuml.project.lang.SentenceAndAnd;
@ -61,7 +62,6 @@ import net.sourceforge.plantuml.project.lang.Subject;
import net.sourceforge.plantuml.project.lang.SubjectDayAsDate;
import net.sourceforge.plantuml.project.lang.SubjectDayOfWeek;
import net.sourceforge.plantuml.project.lang.SubjectDaysAsDates;
import net.sourceforge.plantuml.project.lang.SubjectLinks;
import net.sourceforge.plantuml.project.lang.SubjectProject;
import net.sourceforge.plantuml.project.lang.SubjectResource;
import net.sourceforge.plantuml.project.lang.SubjectTask;
@ -73,8 +73,7 @@ public class GanttDiagramFactory extends PSystemCommandFactory {
static private final List<Subject> subjects() {
return Arrays.<Subject>asList(new SubjectTask(), new SubjectProject(), new SubjectDayOfWeek(),
new SubjectDayAsDate(), new SubjectDaysAsDates(), new SubjectResource(), new SubjectToday(),
new SubjectLinks());
new SubjectDayAsDate(), new SubjectDaysAsDates(), new SubjectResource(), new SubjectToday());
}
public GanttDiagramFactory(DiagramType type) {
@ -99,6 +98,7 @@ public class GanttDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandGanttArrow2());
cmds.add(new CommandColorTask());
cmds.add(new CommandSeparator());
cmds.add(new CommandWeekNumberStrategy());
cmds.add(new CommandPrintScale());
cmds.add(new CommandPrintBetween());

View File

@ -43,7 +43,6 @@ import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexOptional;
import net.sourceforge.plantuml.command.regex.RegexOr;
import net.sourceforge.plantuml.command.regex.RegexPartialMatch;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.core.PrintScale;
@ -68,9 +67,9 @@ public class CommandPrintScale extends SingleLineCommand2<GanttDiagram> {
new RegexLeaf("weekly")), //
new RegexOptional(new RegexConcat( //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("compress"), //
new RegexLeaf("zoom"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("COMPRESS", "(\\d+)"))), //
new RegexLeaf("ZOOM", "([.\\d]+)"))), //
RegexLeaf.end()); //
}
@ -80,9 +79,9 @@ public class CommandPrintScale extends SingleLineCommand2<GanttDiagram> {
final PrintScale scale = PrintScale.fromString(scaleString);
diagram.setPrintScale(scale);
final RegexPartialMatch compress = arg.get("COMPRESS");
if (compress.size() > 0 && compress.get(0) != null) {
diagram.setCompress(Integer.parseInt(compress.get(0)));
final String zoom = arg.get("ZOOM", 0);
if (zoom != null) {
diagram.setFactorScale(Double.parseDouble(zoom));
}
return CommandExecutionResult.ok();
}

View File

@ -0,0 +1,78 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, 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.project.command;
import net.sourceforge.plantuml.LineLocation;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
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;
import net.sourceforge.plantuml.project.GanttDiagram;
import net.sourceforge.plantuml.project.time.DayOfWeek;
public class CommandWeekNumberStrategy extends SingleLineCommand2<GanttDiagram> {
public CommandWeekNumberStrategy() {
super(getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandWeekNumberStrategy.class.getName(), RegexLeaf.start(), //
new RegexLeaf("weeks?"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("starts?"), //
new RegexLeaf("[^0-9]*?"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("WEEKDAY", "(" + DayOfWeek.getRegexString() + ")"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("[^0-9]*?"), //
new RegexLeaf("NUM", "([0-9]+)"), //
new RegexLeaf("[^0-9]*?"), //
RegexLeaf.end());
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, LineLocation location, RegexResult arg) {
final DayOfWeek weekDay = DayOfWeek.fromString(arg.get("WEEKDAY", 0));
final String num = arg.get("NUM", 0);
diagram.setWeekNumberStrategy(weekDay, Integer.parseInt(num));
return CommandExecutionResult.ok();
}
}

View File

@ -35,12 +35,17 @@
*/
package net.sourceforge.plantuml.project.core;
import net.sourceforge.plantuml.style.StyleBuilder;
public abstract class AbstractTask implements Task {
protected final TaskCode code;
private final TaskCode code;
private final StyleBuilder styleBuilder;
private Task row;
protected AbstractTask(TaskCode code) {
protected AbstractTask(StyleBuilder styleBuilder, TaskCode code) {
this.styleBuilder = styleBuilder;
this.code = code;
}
@ -52,4 +57,12 @@ public abstract class AbstractTask implements Task {
return row;
}
public final TaskCode getCode() {
return code;
}
public final StyleBuilder getStyleBuilder() {
return styleBuilder;
}
}

View File

@ -36,16 +36,16 @@
package net.sourceforge.plantuml.project.core;
public enum PrintScale {
DAILY(1), WEEKLY(4), MONTHLY(15), QUARTERLY(40), YEARLY(150);
DAILY(1), WEEKLY(4), MONTHLY(15), QUARTERLY(40), YEARLY(60);
private final int compress;
private final double defaultScale;
private PrintScale(int compress) {
this.compress = compress;
this.defaultScale = 1.0 / compress;
}
public int getCompress() {
return compress;
public final double getDefaultScale() {
return defaultScale;
}
static public PrintScale fromString(String value) {
@ -63,4 +63,5 @@ public enum PrintScale {
}
return DAILY;
}
}

View File

@ -41,6 +41,7 @@ import net.sourceforge.plantuml.project.Load;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.style.StyleBuilder;
public interface Task extends Moment {
@ -76,4 +77,6 @@ public interface Task extends Moment {
public void setNote(Display note);
public StyleBuilder getStyleBuilder();
}

View File

@ -56,6 +56,7 @@ import net.sourceforge.plantuml.project.solver.Solver;
import net.sourceforge.plantuml.project.solver.SolverImpl;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.style.StyleBuilder;
public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
@ -76,8 +77,8 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
this.url = url;
}
public TaskImpl(TaskCode code, OpenClose openClose) {
super(code);
public TaskImpl(StyleBuilder styleBuilder, TaskCode code, OpenClose openClose) {
super(styleBuilder, code);
this.defaultPlan = openClose;
this.solver = new SolverImpl(this);
if (openClose.getCalendar() == null) {
@ -153,7 +154,7 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
public String getPrettyDisplay() {
if (resources.size() > 0) {
final StringBuilder result = new StringBuilder(code.getSimpleDisplay());
final StringBuilder result = new StringBuilder(getCode().getSimpleDisplay());
result.append(" ");
for (Iterator<Map.Entry<Resource, Integer>> it = resources.entrySet().iterator(); it.hasNext();) {
final Map.Entry<Resource, Integer> ent = it.next();
@ -170,22 +171,18 @@ public class TaskImpl extends AbstractTask implements Task, LoadPlanable {
}
return result.toString();
}
return code.getSimpleDisplay();
return getCode().getSimpleDisplay();
}
@Override
public String toString() {
return code.toString();
return getCode().toString();
}
public String debug() {
return "" + getStart() + " ---> " + getEnd() + " [" + getLoad() + "]";
}
public TaskCode getCode() {
return code;
}
public Day getStart() {
Day result = (Day) solver.getData(TaskAttribute.START);
while (getLoadAt(result) == 0) {

View File

@ -41,20 +41,17 @@ import net.sourceforge.plantuml.project.Load;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.style.StyleBuilder;
public class TaskSeparator extends AbstractTask implements Task {
private final String comment;
public TaskSeparator(String comment, int id) {
super(new TaskCode("##" + id));
public TaskSeparator(StyleBuilder styleBuilder, String comment, int id) {
super(styleBuilder, new TaskCode("##" + id));
this.comment = comment;
}
public TaskCode getCode() {
return code;
}
public Day getStart() {
throw new UnsupportedOperationException();
}

View File

@ -40,6 +40,7 @@ import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.cucadiagram.Display;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.project.ToTaskDraw;
import net.sourceforge.plantuml.project.core.Task;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
@ -47,7 +48,10 @@ 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;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public abstract class AbstractTaskDraw implements TaskDraw {
@ -59,7 +63,8 @@ public abstract class AbstractTaskDraw implements TaskDraw {
private double y;
protected final String prettyDisplay;
protected final Day start;
protected final ISkinParam skinParam;
private final StyleBuilder styleBuilder;
private final HColorSet colorSet;
private final Task task;
private final ToTaskDraw toTaskDraw;
@ -78,35 +83,40 @@ public abstract class AbstractTaskDraw implements TaskDraw {
}
public AbstractTaskDraw(TimeScale timeScale, double y, String prettyDisplay, Day start, ISkinParam skinParam,
Task task, ToTaskDraw toTaskDraw) {
Task task, ToTaskDraw toTaskDraw, StyleBuilder styleBuilder, HColorSet colorSet) {
this.y = y;
this.colorSet = colorSet;
this.styleBuilder = styleBuilder;
this.toTaskDraw = toTaskDraw;
this.start = start;
this.prettyDisplay = prettyDisplay;
this.timeScale = timeScale;
this.skinParam = skinParam;
this.task = task;
}
abstract StyleSignature getStyleSignature();
final protected HColor getLineColor() {
return getStyle().value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());
return getStyle().value(PName.LineColor).asColor(colorSet);
}
final protected HColor getBackgroundColor() {
return getStyle().value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet());
return getStyle().value(PName.BackGroundColor).asColor(colorSet);
}
final protected FontConfiguration getFontConfiguration() {
return getStyle().getFontConfiguration(skinParam.getIHtmlColorSet());
return getStyle().getFontConfiguration(colorSet);
}
abstract protected Style getStyle();
final protected double getShapeHeight() {
return getHeightTask() - 2 * margin;
final protected Style getStyle() {
return getStyleSignature().getMergedStyle(styleBuilder);
}
final public double getHeightTask() {
final protected double getShapeHeight(StringBounder stringBounder) {
return getHeightTask(stringBounder) - 2 * margin;
}
final public double getHeightTask(StringBounder stringBounder) {
return getFontConfiguration().getFont().getSize2D() + 5;
}
@ -114,11 +124,11 @@ public abstract class AbstractTaskDraw implements TaskDraw {
return toTaskDraw.getTaskDraw(task.getRow());
}
final public double getY() {
final public double getY(StringBounder stringBounder) {
if (task.getRow() == null) {
return y;
}
return getTrueRow().getY();
return getTrueRow().getY(stringBounder);
}
public void pushMe(double deltaY) {
@ -131,14 +141,22 @@ public abstract class AbstractTaskDraw implements TaskDraw {
return task;
}
public final double getY(Direction direction) {
public final double getY(StringBounder stringBounder, Direction direction) {
if (direction == Direction.UP) {
return getY();
return getY(stringBounder);
}
if (direction == Direction.DOWN) {
return getY() + getHeightTask();
return getY(stringBounder) + getHeightTask(stringBounder);
}
return getY() + getHeightTask() / 2;
return getY(stringBounder) + getHeightTask(stringBounder) / 2;
}
protected final StyleBuilder getStyleBuilder() {
return styleBuilder;
}
protected final HColorSet getColorSet() {
return colorSet;
}
}

View File

@ -50,21 +50,21 @@ public interface TaskDraw extends UDrawable {
public void setColorsAndCompletion(CenterBorderColor colors, int completion, Url url, Display note);
public double getY();
public double getY(StringBounder stringBounder);
public double getY(Direction direction);
public double getY(StringBounder stringBounder, Direction direction);
public void pushMe(double deltaY);
public void drawTitle(UGraphic ug);
public double getHeightTask();
public double getHeightTask(StringBounder stringBounder);
public double getHeightMax(StringBounder stringBounder);
public Task getTask();
public FingerPrint getFingerPrint();
public FingerPrint getFingerPrint(StringBounder stringBounder);
public FingerPrint getFingerPrintNote(StringBounder stringBounder);

View File

@ -46,29 +46,28 @@ import net.sourceforge.plantuml.project.core.Task;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UPolygon;
import net.sourceforge.plantuml.ugraphic.UShape;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public class TaskDrawDiamond extends AbstractTaskDraw {
public TaskDrawDiamond(TimeScale timeScale, double y, String prettyDisplay, Day start, ISkinParam skinParam,
Task task, ToTaskDraw toTaskDraw) {
super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw);
Task task, ToTaskDraw toTaskDraw, StyleBuilder styleBuilder, HColorSet colorSet) {
super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw, styleBuilder, colorSet);
}
@Override
protected Style getStyle() {
final Style style = StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.milestone)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
return style;
StyleSignature getStyleSignature() {
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.milestone);
}
public double getHeightMax(StringBounder stringBounder) {
return getHeightTask();
return getHeightTask(stringBounder);
}
// final UFont font = UFont.serif(11);
@ -77,9 +76,10 @@ public class TaskDrawDiamond extends AbstractTaskDraw {
final public void drawTitle(UGraphic ug) {
final TextBlock title = Display.getWithNewlines(prettyDisplay).create(getFontConfiguration(),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
final double titleHeight = title.calculateDimension(ug.getStringBounder()).getHeight();
final double h = (margin + getShapeHeight() - titleHeight) / 2;
final double endingPosition = timeScale.getStartingPosition(start) + getHeightTask();
final StringBounder stringBounder = ug.getStringBounder();
final double titleHeight = title.calculateDimension(stringBounder).getHeight();
final double h = (margin + getShapeHeight(stringBounder) - titleHeight) / 2;
final double endingPosition = timeScale.getStartingPosition(start) + getHeightTask(stringBounder);
title.drawU(ug.apply(new UTranslate(endingPosition, h)));
}
@ -98,21 +98,21 @@ public class TaskDrawDiamond extends AbstractTaskDraw {
}
private void drawShape(UGraphic ug) {
ug.draw(getDiamond());
ug.draw(getDiamond(ug.getStringBounder()));
}
public FingerPrint getFingerPrintNote(StringBounder stringBounder) {
return null;
}
public FingerPrint getFingerPrint() {
final double h = getHeightTask();
public FingerPrint getFingerPrint(StringBounder stringBounder) {
final double h = getHeightTask(stringBounder);
final double startPos = timeScale.getStartingPosition(start);
return new FingerPrint(startPos, getY(), startPos + h, getY() + h);
return new FingerPrint(startPos, getY(stringBounder), startPos + h, getY(stringBounder) + h);
}
private UShape getDiamond() {
final double h = getHeightTask() - 2 * margin;
private UShape getDiamond(StringBounder stringBounder) {
final double h = getHeightTask(stringBounder) - 2 * margin;
final UPolygon result = new UPolygon();
result.addPoint(h / 2, 0);
result.addPoint(h, h / 2);

View File

@ -60,6 +60,7 @@ import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.svek.image.Opale;
import net.sourceforge.plantuml.ugraphic.UGraphic;
@ -69,6 +70,7 @@ import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorNone;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TaskDrawRegular extends AbstractTaskDraw {
@ -78,13 +80,15 @@ public class TaskDrawRegular extends AbstractTaskDraw {
private final boolean oddEnd;
private final Collection<Day> paused;
private final Collection<GanttConstraint> constraints;
private final ISkinParam skinParam;
private final double margin = 2;
public TaskDrawRegular(TimeScale timeScale, double y, String prettyDisplay, Day start, Day end, boolean oddStart,
boolean oddEnd, ISkinParam skinParam, Task task, ToTaskDraw toTaskDraw,
Collection<GanttConstraint> constraints) {
super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw);
Collection<GanttConstraint> constraints, StyleBuilder styleBuilder, HColorSet colorSet) {
super(timeScale, y, prettyDisplay, start, skinParam, task, toTaskDraw, styleBuilder, colorSet);
this.skinParam = skinParam;
this.constraints = constraints;
this.end = end;
this.oddStart = oddStart;
@ -102,8 +106,9 @@ public class TaskDrawRegular extends AbstractTaskDraw {
public void drawTitle(UGraphic ug) {
final TextBlock title = Display.getWithNewlines(prettyDisplay).create(getFontConfiguration(),
HorizontalAlignment.LEFT, new SpriteContainerEmpty());
final Dimension2D dim = title.calculateDimension(ug.getStringBounder());
final double h = (margin + getShapeHeight() - dim.getHeight()) / 2;
final StringBounder stringBounder = ug.getStringBounder();
final Dimension2D dim = title.calculateDimension(stringBounder);
final double h = (margin + getShapeHeight(stringBounder) - dim.getHeight()) / 2;
final double pos1 = timeScale.getStartingPosition(start) + 6;
final double pos2 = timeScale.getEndingPosition(end) - 6;
final double pos;
@ -130,26 +135,21 @@ public class TaskDrawRegular extends AbstractTaskDraw {
return false;
}
// final UFont font = UFont.serif(11);
// return new FontConfiguration(font, HColorUtils.BLACK, HColorUtils.BLACK, false);
@Override
protected Style getStyle() {
final Style style = StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.task)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
return style;
StyleSignature getStyleSignature() {
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.task);
}
public void drawU(UGraphic ug) {
final double startPos = timeScale.getStartingPosition(start);
drawNote(ug.apply((new UTranslate(startPos + margin, getYNotePosition()))));
drawNote(ug.apply((new UTranslate(startPos + margin, getYNotePosition(ug.getStringBounder())))));
ug = applyColors(ug).apply(new UTranslate(margin, margin));
drawShape(ug);
}
private double getYNotePosition() {
return getShapeHeight() + margin * 3;
private double getYNotePosition(StringBounder stringBounder) {
return getShapeHeight(stringBounder) + margin * 3;
}
private void drawNote(UGraphic ug) {
@ -162,34 +162,34 @@ public class TaskDrawRegular extends AbstractTaskDraw {
public double getHeightMax(StringBounder stringBounder) {
if (note == null) {
return getHeightTask();
return getHeightTask(stringBounder);
}
return getYNotePosition() + getOpaleNote().calculateDimension(stringBounder).getHeight();
return getYNotePosition(stringBounder) + getOpaleNote().calculateDimension(stringBounder).getHeight();
}
private Opale getOpaleNote() {
final Style style = StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.note)
.getMergedStyle(skinParam.getCurrentStyleBuilder());
FontConfiguration fc = new FontConfiguration(skinParam, style);
.getMergedStyle(getStyleBuilder());
final Sheet sheet = Parser
.build(fc, skinParam.getDefaultTextAlignment(HorizontalAlignment.LEFT), skinParam, CreoleMode.FULL)
.createSheet(note);
final SheetBlock1 sheet1 = new SheetBlock1(sheet, LineBreakStrategy.NONE, skinParam.getPadding());
final FontConfiguration fc = style.getFontConfiguration(getColorSet());
final HColor noteBackgroundColor = style.value(PName.BackGroundColor).asColor(skinParam.getIHtmlColorSet());
final HColor borderColor = style.value(PName.LineColor).asColor(skinParam.getIHtmlColorSet());
final HorizontalAlignment horizontalAlignment = style.value(PName.HorizontalAlignment).asHorizontalAlignment();
final Sheet sheet = Parser.build(fc, horizontalAlignment, skinParam, CreoleMode.FULL).createSheet(note);
final double padding = style.value(PName.Padding).asDouble();
final SheetBlock1 sheet1 = new SheetBlock1(sheet, LineBreakStrategy.NONE, padding);
final HColor noteBackgroundColor = style.value(PName.BackGroundColor).asColor(getColorSet());
final HColor borderColor = style.value(PName.LineColor).asColor(getColorSet());
final double shadowing = style.value(PName.Shadowing).asDouble();
Opale opale = new Opale(shadowing, borderColor, noteBackgroundColor, sheet1, false);
return opale;
return new Opale(shadowing, borderColor, noteBackgroundColor, sheet1, false);
}
public FingerPrint getFingerPrint() {
final double h = getHeightTask();
public FingerPrint getFingerPrint(StringBounder stringBounder) {
final double h = getHeightTask(stringBounder);
final double startPos = timeScale.getStartingPosition(start);
final double endPos = timeScale.getEndingPosition(end);
return new FingerPrint(startPos, getY(), endPos - startPos, h);
return new FingerPrint(startPos, getY(stringBounder), endPos - startPos, h);
}
public FingerPrint getFingerPrintNote(StringBounder stringBounder) {
@ -199,7 +199,8 @@ public class TaskDrawRegular extends AbstractTaskDraw {
final Dimension2D dim = getOpaleNote().calculateDimension(stringBounder);
final double startPos = timeScale.getStartingPosition(start);
// final double endPos = timeScale.getEndingPosition(end);
return new FingerPrint(startPos, getY() + getYNotePosition(), dim.getWidth(), dim.getHeight());
return new FingerPrint(startPos, getY(stringBounder) + getYNotePosition(stringBounder), dim.getWidth(),
dim.getHeight());
}
private UGraphic applyColors(UGraphic ug) {
@ -220,23 +221,24 @@ public class TaskDrawRegular extends AbstractTaskDraw {
if (url != null) {
ug.startUrl(url);
}
final StringBounder stringBounder = ug.getStringBounder();
if (oddStart && !oddEnd) {
ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoRight(fullLength, getShapeHeight()));
ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoRight(fullLength, getShapeHeight(stringBounder)));
} else if (!oddStart && oddEnd) {
ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoLeft(fullLength, getShapeHeight()));
ug.apply(UTranslate.dx(startPos)).draw(PathUtils.UtoLeft(fullLength, getShapeHeight(stringBounder)));
} else {
final URectangle full = new URectangle(fullLength, getShapeHeight()).rounded(8);
final URectangle full = new URectangle(fullLength, getShapeHeight(stringBounder)).rounded(8);
if (completion == 100) {
ug.apply(UTranslate.dx(startPos)).draw(full);
} else {
final double partialLength = fullLength * completion / 100.;
ug.apply(UTranslate.dx(startPos)).apply(HColorUtils.WHITE).apply(HColorUtils.WHITE.bg()).draw(full);
if (partialLength > 2) {
final URectangle partial = new URectangle(partialLength, getShapeHeight()).rounded(8);
final URectangle partial = new URectangle(partialLength, getShapeHeight(stringBounder)).rounded(8);
ug.apply(UTranslate.dx(startPos)).apply(new HColorNone()).draw(partial);
}
if (partialLength > 10 && partialLength < fullLength - 10) {
final URectangle patch = new URectangle(8, getShapeHeight());
final URectangle patch = new URectangle(8, getShapeHeight(stringBounder));
ug.apply(UTranslate.dx(startPos)).apply(new HColorNone()).apply(UTranslate.dx(partialLength - 8))
.draw(patch);
}
@ -264,13 +266,14 @@ public class TaskDrawRegular extends AbstractTaskDraw {
private void drawPause(UGraphic ug, Day start1, Day end) {
final double x1 = timeScale.getStartingPosition(start1);
final double x2 = timeScale.getEndingPosition(end);
final URectangle small = new URectangle(x2 - x1 - 1, getShapeHeight() + 1);
final StringBounder stringBounder = ug.getStringBounder();
final URectangle small = new URectangle(x2 - x1 - 1, getShapeHeight(stringBounder) + 1);
final ULine line = ULine.hline(x2 - x1 - 1);
ug = ug.apply(UTranslate.dx(x1 - 1));
ug.apply(HColorUtils.WHITE).apply(HColorUtils.WHITE.bg()).draw(small);
final UGraphic ugLine = ug.apply(new UStroke(2, 3, 1));
ugLine.draw(line);
ugLine.apply(UTranslate.dy(getShapeHeight())).draw(line);
ugLine.apply(UTranslate.dy(getShapeHeight(stringBounder))).draw(line);
}
}

View File

@ -48,10 +48,18 @@ import net.sourceforge.plantuml.project.core.Task;
import net.sourceforge.plantuml.project.lang.CenterBorderColor;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.timescale.TimeScale;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignature;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TaskDrawSeparator implements TaskDraw {
@ -61,8 +69,13 @@ public class TaskDrawSeparator implements TaskDraw {
private final Day min;
private final Day max;
private final String name;
private final StyleBuilder styleBuilder;
private final HColorSet colorSet;
public TaskDrawSeparator(String name, TimeScale timeScale, double y, Day min, Day max) {
public TaskDrawSeparator(String name, TimeScale timeScale, double y, Day min, Day max, StyleBuilder styleBuilder,
HColorSet colorSet) {
this.styleBuilder = styleBuilder;
this.colorSet = colorSet;
this.name = name;
this.y = y;
this.timeScale = timeScale;
@ -71,7 +84,19 @@ public class TaskDrawSeparator implements TaskDraw {
}
public void drawTitle(UGraphic ug) {
getTitle().drawU(ug.apply(UTranslate.dx(MARGIN1)));
final ClockwiseTopRightBottomLeft padding = getStyle().getPadding();
final ClockwiseTopRightBottomLeft margin = getStyle().getMargin();
final double dx = margin.getLeft() + padding.getLeft();
final double dy = margin.getTop() + padding.getTop();
getTitle().drawU(ug.apply(new UTranslate(dx, dy)));
}
private StyleSignature getStyleSignature() {
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.separator);
}
private Style getStyle() {
return getStyleSignature().getMergedStyle(styleBuilder);
}
private TextBlock getTitle() {
@ -83,43 +108,67 @@ public class TaskDrawSeparator implements TaskDraw {
}
private FontConfiguration getFontConfiguration() {
final UFont font = UFont.serif(11);
return new FontConfiguration(font, HColorUtils.BLACK, HColorUtils.BLACK, false);
return getStyle().getFontConfiguration(colorSet);
}
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 StringBounder stringBounder = ug.getStringBounder();
final double widthTitle = getTitle().calculateDimension(stringBounder).getWidth();
final double start = timeScale.getStartingPosition(min);
// final double start2 = start1 + widthTitle;
final double end = timeScale.getEndingPosition(max);
ug = ug.apply(HColorUtils.BLACK);
ug = ug.apply(UTranslate.dy(getHeightTask() / 2));
final ClockwiseTopRightBottomLeft padding = getStyle().getPadding();
final ClockwiseTopRightBottomLeft margin = getStyle().getMargin();
ug = ug.apply(new UTranslate(0, margin.getTop()));
final HColor backColor = getStyle().value(PName.BackGroundColor).asColor(colorSet);
if (HColorUtils.isTransparent(backColor) == false) {
final double height = padding.getTop() + getTextHeight(stringBounder) + padding.getBottom();
if (height > 0) {
final URectangle rect = new URectangle(end - start, height);
ug.apply(backColor.bg()).draw(rect);
}
}
final HColor lineColor = getStyle().value(PName.LineColor).asColor(colorSet);
ug = ug.apply(lineColor);
ug = ug.apply(UTranslate.dy(padding.getTop() + getTextHeight(stringBounder) / 2));
if (widthTitle == 0) {
final ULine line = ULine.hline(end - start);
ug.draw(line);
} else {
final ULine line1 = ULine.hline(MARGIN1 - MARGIN2);
final ULine line2 = ULine.hline(end - start - MARGIN1 - MARGIN2);
ug.draw(line1);
ug.apply(UTranslate.dx(widthTitle + MARGIN1 + MARGIN2)).draw(line2);
if (padding.getLeft() > 1) {
final ULine line1 = ULine.hline(padding.getLeft());
ug.draw(line1);
}
final double x1 = padding.getLeft() + margin.getLeft() + widthTitle + margin.getRight();
final double x2 = end - 1;
final ULine line2 = ULine.hline(x2 - x1);
ug.apply(UTranslate.dx(x1)).draw(line2);
}
}
public FingerPrint getFingerPrint() {
final double h = getHeightTask();
public FingerPrint getFingerPrint(StringBounder stringBounder) {
final double h = getHeightTask(stringBounder);
final double end = timeScale.getEndingPosition(max);
return new FingerPrint(0, y, end, y + h);
}
public double getHeightTask() {
return 16;
public double getHeightTask(StringBounder stringBounder) {
final ClockwiseTopRightBottomLeft padding = getStyle().getPadding();
final ClockwiseTopRightBottomLeft margin = getStyle().getMargin();
return margin.getTop() + padding.getTop() + getTextHeight(stringBounder) + padding.getBottom()
+ margin.getBottom();
}
public double getY() {
private double getTextHeight(StringBounder stringBounder) {
return getTitle().calculateDimension(stringBounder).getHeight();
}
public double getY(StringBounder stringBounder) {
return y;
}
@ -138,7 +187,7 @@ public class TaskDrawSeparator implements TaskDraw {
throw new UnsupportedOperationException();
}
public double getY(Direction direction) {
public double getY(StringBounder stringBounder, Direction direction) {
throw new UnsupportedOperationException();
}
@ -147,7 +196,7 @@ public class TaskDrawSeparator implements TaskDraw {
}
public double getHeightMax(StringBounder stringBounder) {
return getHeightTask();
return getHeightTask(stringBounder);
}
}

View File

@ -75,7 +75,7 @@ public abstract class TimeHeader {
this.max = max;
}
protected abstract double getTimeHeaderHeight();
public abstract double getTimeHeaderHeight();
public abstract double getTimeFooterHeight();
@ -116,12 +116,13 @@ public abstract class TimeHeader {
text.drawU(ug.apply(UTranslate.dx(start + diff / 2)));
}
protected final void printCentered(UGraphic ug, double start, double end, TextBlock... texts) {
protected final void printCentered(UGraphic ug, boolean hideIfTooBig, double start, double end,
TextBlock... texts) {
final double available = end - start;
for (int i = texts.length - 1; i >= 0; i--) {
final TextBlock text = texts[i];
final double width = text.calculateDimension(ug.getStringBounder()).getWidth();
if (i == 0 || width <= available) {
if ((i == 0 && hideIfTooBig == false) || width <= available) {
final double diff = Math.max(0, available - width);
text.drawU(ug.apply(UTranslate.dx(start + diff / 2)));
return;

View File

@ -51,7 +51,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderDaily extends TimeHeaderCalendar {
protected double getTimeHeaderHeight() {
public double getTimeHeaderHeight() {
return Y_POS_ROW28() + 13;
}
@ -153,7 +153,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
final TextBlock tiny = getTextBlock(monthYear.shortName(), 12, true, HColorUtils.BLACK);
final TextBlock small = getTextBlock(monthYear.longName(), 12, true, HColorUtils.BLACK);
final TextBlock big = getTextBlock(monthYear.longNameYYYY(), 12, true, HColorUtils.BLACK);
printCentered(ug, start, end, tiny, small, big);
printCentered(ug, false, start, end, tiny, small, big);
}
private void drawVbar(UGraphic ug, double x, double y1, double y2) {

View File

@ -39,7 +39,6 @@ import java.util.Map;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.LoadPlanable;
import net.sourceforge.plantuml.project.core.PrintScale;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
@ -52,7 +51,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderMonthly extends TimeHeaderCalendar {
protected double getTimeHeaderHeight() {
public double getTimeHeaderHeight() {
return 16 + 13;
}
@ -60,10 +59,10 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
return 16 + 13 - 1;
}
public TimeHeaderMonthly(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek, int compress) {
public TimeHeaderMonthly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
new TimeScaleCompressed(calendar, compress));
new TimeScaleCompressed(calendar, scale));
}
@Override
@ -130,13 +129,13 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock("" + monthYear.year(), 12, true, HColorUtils.BLACK);
printCentered(ug, start, end, small);
printCentered(ug, false, start, end, small);
}
private void printMonth(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock(monthYear.shortName(), 10, false, HColorUtils.BLACK);
final TextBlock big = getTextBlock(monthYear.longName(), 10, false, HColorUtils.BLACK);
printCentered(ug, start, end, small, big);
printCentered(ug, false, start, end, small, big);
}
private void drawVbar(UGraphic ug, double x, double y1, double y2) {

View File

@ -39,7 +39,6 @@ import java.util.Map;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.LoadPlanable;
import net.sourceforge.plantuml.project.core.PrintScale;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
@ -52,7 +51,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderQuarterly extends TimeHeaderCalendar {
protected double getTimeHeaderHeight() {
public double getTimeHeaderHeight() {
return 16 + 13;
}
@ -60,10 +59,10 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
return 16 + 13 - 1;
}
public TimeHeaderQuarterly(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek, int compress) {
public TimeHeaderQuarterly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
new TimeScaleCompressed(calendar, compress));
new TimeScaleCompressed(calendar, scale));
}
@Override
@ -134,12 +133,12 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock("" + monthYear.year(), 12, true, HColorUtils.BLACK);
printCentered(ug, start, end, small);
printCentered(ug, false, start, end, small);
}
private void printQuarter(UGraphic ug, String quarter, double start, double end) {
final TextBlock small = getTextBlock(quarter, 10, false, HColorUtils.BLACK);
printCentered(ug, start, end, small);
printCentered(ug, false, start, end, small);
}
private void drawVbar(UGraphic ug, double x, double y1, double y2) {

View File

@ -54,7 +54,7 @@ public class TimeHeaderSimple extends TimeHeader {
return getTimeHeaderHeight() + getHeaderNameDayHeight();
}
protected double getTimeHeaderHeight() {
public double getTimeHeaderHeight() {
return 16;
}

View File

@ -39,10 +39,10 @@ import java.util.Map;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.LoadPlanable;
import net.sourceforge.plantuml.project.core.PrintScale;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
@ -52,7 +52,9 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderWeekly extends TimeHeaderCalendar {
protected double getTimeHeaderHeight() {
private final WeekNumberStrategy weekNumberStrategy;
public double getTimeHeaderHeight() {
return 16 + 13;
}
@ -60,10 +62,10 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
return 16;
}
public TimeHeaderWeekly(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek, int compress) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
new TimeScaleCompressed(calendar, compress));
public TimeHeaderWeekly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek, WeekNumberStrategy weekNumberStrategy) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
this.weekNumberStrategy = weekNumberStrategy;
}
@Override
@ -111,7 +113,7 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
private void printSmallVbars(final UGraphic ug, double totalHeightWithoutFooter) {
for (Day wink = min; wink.compareTo(max) <= 0; wink = wink.increment()) {
if (wink.getDayOfWeek() == DayOfWeek.MONDAY) {
if (wink.getDayOfWeek() == weekNumberStrategy.getFirstDayOfWeek()) {
drawVbar(ug, getTimeScale().getStartingPosition(wink), Y_POS_ROW16(), totalHeightWithoutFooter);
}
}
@ -120,9 +122,11 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
private void printDaysOfMonth(final UGraphic ug) {
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
if (wink.getDayOfWeek() == DayOfWeek.MONDAY) {
printLeft(ug.apply(UTranslate.dy(Y_POS_ROW16())),
getTextBlock("" + wink.getDayOfMonth(), 10, false, HColorUtils.BLACK),
if (wink.getDayOfWeek() == weekNumberStrategy.getFirstDayOfWeek()) {
final String num = "" + wink.getWeekOfYear(weekNumberStrategy);
// final String num = "" + wink.getDayOfMonth();
final TextBlock textBlock = getTextBlock(num, 10, false, HColorUtils.BLACK);
printLeft(ug.apply(UTranslate.dy(Y_POS_ROW16())), textBlock,
getTimeScale().getStartingPosition(wink) + 5);
}
}
@ -131,7 +135,7 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
private void printMonth(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock(monthYear.shortName(), 12, true, HColorUtils.BLACK);
final TextBlock big = getTextBlock(monthYear.shortNameYYYY(), 12, true, HColorUtils.BLACK);
printCentered(ug, start, end, small, big);
printCentered(ug, false, start, end, small, big);
}
private void drawVbar(UGraphic ug, double x, double y1, double y2) {

View File

@ -39,7 +39,6 @@ import java.util.Map;
import net.sourceforge.plantuml.graphic.TextBlock;
import net.sourceforge.plantuml.project.LoadPlanable;
import net.sourceforge.plantuml.project.core.PrintScale;
import net.sourceforge.plantuml.project.time.Day;
import net.sourceforge.plantuml.project.time.DayOfWeek;
import net.sourceforge.plantuml.project.time.MonthYear;
@ -52,18 +51,17 @@ import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
public class TimeHeaderYearly extends TimeHeaderCalendar {
protected double getTimeHeaderHeight() {
return 16 + 13;
public double getTimeHeaderHeight() {
return 20;
}
public double getTimeFooterHeight() {
return 16 + 13 - 1;
return 20 - 1;
}
public TimeHeaderYearly(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
Map<DayOfWeek, HColor> colorDaysOfWeek, int compress) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
new TimeScaleCompressed(calendar, compress));
public TimeHeaderYearly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek) {
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
}
@Override
@ -88,7 +86,7 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (last == null || wink.monthYear().year() != last.year()) {
drawVbar(ug, x1, 0, 15);
drawVbar(ug, x1, 0, 19);
if (last != null) {
printYear(ug, last, lastChange, x1);
}
@ -100,39 +98,12 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
if (x1 > lastChange) {
printYear(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 15);
}
private void drawMonths(UGraphic ug) {
MonthYear last = null;
double lastChange = -1;
for (Day wink = min; wink.compareTo(max) < 0; wink = wink.increment()) {
final double x1 = getTimeScale().getStartingPosition(wink);
if (wink.monthYear().equals(last) == false) {
drawVbar(ug, x1, 0, 12);
if (last != null) {
printMonth(ug, last, lastChange, x1);
}
lastChange = x1;
last = wink.monthYear();
}
}
final double x1 = getTimeScale().getStartingPosition(max.increment());
if (x1 > lastChange) {
printMonth(ug, last, lastChange, x1);
}
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12);
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 19);
}
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock("" + monthYear.year(), 12, true, HColorUtils.BLACK);
printCentered(ug, start, end, small);
}
private void printMonth(UGraphic ug, MonthYear monthYear, double start, double end) {
final TextBlock small = getTextBlock(monthYear.shortName(), 10, false, HColorUtils.BLACK);
final TextBlock big = getTextBlock(monthYear.longName(), 10, false, HColorUtils.BLACK);
printCentered(ug, start, end, small, big);
final TextBlock small = getTextBlock("" + monthYear.year(), 14, true, HColorUtils.BLACK);
printCentered(ug, true, start, end, small);
}
private void drawVbar(UGraphic ug, double x, double y1, double y2) {
@ -140,10 +111,6 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
ug.apply(HColorUtils.LIGHT_GRAY).apply(new UTranslate(x, y1)).draw(vbar);
}
private void printLeft(UGraphic ug, TextBlock text, double start) {
text.drawU(ug.apply(UTranslate.dx(start)));
}
@Override
public double getFullHeaderHeight() {
return getTimeHeaderHeight();

View File

@ -53,7 +53,8 @@ public class SentenceEnds extends SentenceSimple {
final Task task = (Task) subject;
final TaskInstant when = (TaskInstant) complement;
task.setEnd(when.getInstantPrecise().decrement());
project.addContraint(new GanttConstraint(when, new TaskInstant(task, TaskAttribute.END)));
project.addContraint(new GanttConstraint(project.getIHtmlColorSet(), project.getCurrentStyleBuilder(), when,
new TaskInstant(task, TaskAttribute.END)));
return CommandExecutionResult.ok();
}

View File

@ -64,10 +64,10 @@ public class SentenceOccurs extends SentenceSimple {
}
task.setStart(from.getEnd());
task.setEnd(to.getEnd());
project.addContraint(new GanttConstraint(new TaskInstant(from, TaskAttribute.START),
new TaskInstant(task, TaskAttribute.START)));
project.addContraint(
new GanttConstraint(new TaskInstant(to, TaskAttribute.END), new TaskInstant(task, TaskAttribute.END)));
project.addContraint(new GanttConstraint(project.getIHtmlColorSet(), project.getCurrentStyleBuilder(),
new TaskInstant(from, TaskAttribute.START), new TaskInstant(task, TaskAttribute.START)));
project.addContraint(new GanttConstraint(project.getIHtmlColorSet(), project.getCurrentStyleBuilder(),
new TaskInstant(to, TaskAttribute.END), new TaskInstant(task, TaskAttribute.END)));
return CommandExecutionResult.ok();
}

View File

@ -57,7 +57,8 @@ public class SentenceTaskStarts extends SentenceSimple {
when = (TaskInstant) complement;
task.setStart(when.getInstantPrecise());
if (when.isTask()) {
project.addContraint(new GanttConstraint(when, new TaskInstant(task, TaskAttribute.START), color));
project.addContraint(new GanttConstraint(project.getIHtmlColorSet(), project.getCurrentStyleBuilder(), when,
new TaskInstant(task, TaskAttribute.START), color));
}
return CommandExecutionResult.ok();

View File

@ -62,7 +62,8 @@ public class SentenceTaskStartsWithColor extends SentenceSimple {
task.setStart(when.getInstantPrecise());
if (when.isTask()) {
final HColor color = complement22.getCenter();
final GanttConstraint link = new GanttConstraint(when, new TaskInstant(task, TaskAttribute.START), color);
final GanttConstraint link = new GanttConstraint(project.getIHtmlColorSet(),
project.getCurrentStyleBuilder(), when, new TaskInstant(task, TaskAttribute.START), color);
link.applyStyle(complement22.getStyle());
project.addContraint(link);
}

View File

@ -45,6 +45,7 @@ import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.project.Failable;
import net.sourceforge.plantuml.project.GanttDiagram;
// Removed
public class SubjectLinks implements Subject {
public IRegex toRegex() {
@ -68,7 +69,7 @@ public class SubjectLinks implements Subject {
@Override
public CommandExecutionResult execute(GanttDiagram project, Object subject, Object complement) {
final CenterBorderColor colors = (CenterBorderColor) complement;
project.setLinksColor(colors.getCenter());
// project.setLinksColor(colors.getCenter());
return CommandExecutionResult.ok();
}

View File

@ -65,6 +65,16 @@ public class Day implements Comparable<Day>, Value {
return create(System.currentTimeMillis());
}
public int getWeekOfYear(WeekNumberStrategy strategy) {
synchronized (gmt) {
gmt.clear();
gmt.setTimeInMillis(ms1);
gmt.setFirstDayOfWeek(strategy.getFirstDayOfWeekAsLegacyInt());
gmt.setMinimalDaysInFirstWeek(strategy.getMinimalDaysInFirstWeek());
return gmt.get(Calendar.WEEK_OF_YEAR);
}
}
private Day(int year, Month month, int dayOfMonth) {
this.dayOfMonth = dayOfMonth;
this.monthYear = MonthYear.create(year, month);

View File

@ -44,7 +44,8 @@ import net.sourceforge.plantuml.StringUtils;
public enum DayOfWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
MONDAY(Calendar.MONDAY), TUESDAY(Calendar.TUESDAY), WEDNESDAY(Calendar.WEDNESDAY), THURSDAY(Calendar.THURSDAY),
FRIDAY(Calendar.FRIDAY), SATURDAY(Calendar.SATURDAY), SUNDAY(Calendar.SUNDAY);
static final private Calendar gmt = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
static final private SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS", Locale.US);
@ -52,6 +53,16 @@ public enum DayOfWeek {
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
}
private final int legacy;
private DayOfWeek(int legacy) {
this.legacy = legacy;
}
public int getLegacyJavaValue() {
return legacy;
}
public static synchronized DayOfWeek fromTime(long time) {
gmt.setTimeInMillis(time);
final int result = gmt.get(Calendar.DAY_OF_WEEK);

View File

@ -0,0 +1,61 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, 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.project.time;
public class WeekNumberStrategy {
private final DayOfWeek firstDayOfWeek;
private final int minimalDaysInFirstWeek;
public WeekNumberStrategy(DayOfWeek firstDayOfWeek, int minimalDaysInFirstWeek) {
this.firstDayOfWeek = firstDayOfWeek;
this.minimalDaysInFirstWeek = minimalDaysInFirstWeek;
}
public final int getFirstDayOfWeekAsLegacyInt() {
return firstDayOfWeek.getLegacyJavaValue();
}
public final int getMinimalDaysInFirstWeek() {
return minimalDaysInFirstWeek;
}
public final DayOfWeek getFirstDayOfWeek() {
return firstDayOfWeek;
}
}

View File

@ -40,24 +40,24 @@ import net.sourceforge.plantuml.project.time.DayOfWeek;
public class TimeScaleCompressed implements TimeScale {
private final int compress;
private final double scale;
private final TimeScale daily;
public TimeScaleCompressed(Day calendar, int compress) {
public TimeScaleCompressed(Day calendar, double scale) {
this.daily = new TimeScaleDaily(calendar, null);
this.compress = compress;
this.scale = scale;
}
public double getStartingPosition(Day instant) {
return daily.getStartingPosition(instant) / compress;
return daily.getStartingPosition(instant) * scale;
}
public double getEndingPosition(Day instant) {
return daily.getEndingPosition(instant) / compress;
return daily.getEndingPosition(instant) * scale;
}
public double getWidth(Day instant) {
return daily.getWidth(instant) / compress;
return daily.getWidth(instant) * scale;
}
public boolean isBreaking(Day instant) {

View File

@ -107,6 +107,7 @@ public enum SName {
storage, //
swimlane, //
task, //
timeline, //
title, //
usecase, //
wbsDiagram, //

View File

@ -114,6 +114,16 @@ public class Style {
return new Style(this.signature, result);
}
public Style eventuallyOverride(PName param, double value) {
return eventuallyOverride(param, "" + value);
}
public Style eventuallyOverride(PName param, String value) {
final EnumMap<PName, Value> result = new EnumMap<PName, Value>(this.map);
result.put(param, new ValueImpl(value, Integer.MAX_VALUE));
return new Style(this.signature, result);
}
public Style eventuallyOverride(Colors colors) {
Style result = this;
if (colors != null) {
@ -169,6 +179,17 @@ public class Style {
return new SymbolContext(backColor, foreColor).withStroke(getStroke()).withDeltaShadow(deltaShadowing);
}
public Style eventuallyOverride(UStroke stroke) {
if (stroke == null) {
return this;
}
Style result = this.eventuallyOverride(PName.LineThickness, stroke.getThickness());
final double space = stroke.getDashSpace();
final double visible = stroke.getDashVisible();
result = result.eventuallyOverride(PName.LineStyle, "" + visible + ";" + space);
return result;
}
public UStroke getStroke() {
final double thickness = value(PName.LineThickness).asDouble();
final String dash = value(PName.LineStyle).asString();

View File

@ -55,6 +55,11 @@ public class ValueImpl implements Value {
this.priority = counter.getNextInt();
}
public ValueImpl(String value, int priority) {
this.value = value;
this.priority = priority;
}
@Override
public String toString() {
return value + " (" + priority + ")";

View File

@ -80,7 +80,7 @@ public class Version {
}
public static int beta() {
final int beta = 0;
final int beta = 3;
return beta;
}

View File

@ -73,7 +73,7 @@ RECTANGLE:
backcolor: ffe0e8e8
TEXT:
text: 19
text: 43
position: [ 21.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []
@ -81,7 +81,7 @@ TEXT:
extendedColor: NULL_COLOR
TEXT:
text: 26
text: 44
position: [ 49.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []
@ -89,7 +89,7 @@ TEXT:
extendedColor: NULL_COLOR
TEXT:
text: 2
text: 45
position: [ 77.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []
@ -97,7 +97,7 @@ TEXT:
extendedColor: NULL_COLOR
TEXT:
text: 9
text: 46
position: [ 105.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []
@ -105,7 +105,7 @@ TEXT:
extendedColor: NULL_COLOR
TEXT:
text: 16
text: 47
position: [ 133.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []
@ -113,7 +113,7 @@ TEXT:
extendedColor: NULL_COLOR
TEXT:
text: 23
text: 48
position: [ 161.0000 ; 23.7778 ]
orientation: 0
font: Serif.plain/10 []