BrightSide Workbench Full Report + Source Code
Gantt.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2011 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 package org.turro.zkoss.svg;
19 
20 import org.turro.string.Strings;
21 import org.turro.i18n.I_;
22 
27 public class Gantt extends Svg {
28 
29  static final private int
30  RULE_SPAN = 40,
31  RULE_HEIGHT = 10,
32  ITEM_INIT = 40,
33  ITEM_HEIGHT = 20,
34  ITEM_SPAN = 30;
35 
36  private GanttData data;
37  private int taskPanelWidth = 300, hoursPanelWidth;
38  private GanttMeasure measure;
39 
40  public GanttData getData() {
41  return data;
42  }
43 
44  public void setData(GanttData data) {
45  this.data = data;
46  }
47 
48  public void rule(int units) {
49  String nunit = I_.byKey(measure.toString());
50  setForceStyle("font-size:10px");
51  text(nunit, taskPanelWidth - (nunit.length() * GanttData.CHAR_PIXELS) - 5, RULE_HEIGHT + 6);
52  line(taskPanelWidth, 15, taskPanelWidth + (units * RULE_SPAN), 15, "#000", "1px");
53  for(int i = 0; i <= units; i++) {
54  line(taskPanelWidth + (i * RULE_SPAN), 15, taskPanelWidth + (i * RULE_SPAN), 20, "#000", "1px");
55  setForceStyle("font-size:10px");
56  text("" + i, taskPanelWidth + (i * RULE_SPAN) - 5, RULE_HEIGHT);
57  }
58  }
59 
60  @Override
61  public void startComposing(String onUserEvent, String width, String height, double scale) {
63  taskPanelWidth = data.getMaxNameLenght() * GanttData.CHAR_PIXELS;
64  int maxUnits = (int) Math.ceil(measure.convert(data.getMaxHoursLenght()));
65  hoursPanelWidth = maxUnits * RULE_SPAN;
66 
67  if(width == null) {
68  width = "" + ((taskPanelWidth + (maxUnits * RULE_SPAN) + 20) * scale);
69  }
70  if(height == null) {
71  height = "" + (((data.size() * ITEM_SPAN) + RULE_HEIGHT + 20) * scale);
72  }
73  super.startComposing(onUserEvent, width, height, scale);
74 
75  startTag("n:g", new String[] {
76  "style='stroke:none'",
77  "font-size='13px'",
78  "font-style='normal'",
79  "font-family='Ubuntu'"
80  });
81 
82  rule(maxUnits);
83 
84  int count = 0;
85  for(GanttItem gi : data) {
86  count++;
87  gi.setPosition(count);
88  int x1 = (int) (taskPanelWidth + (measure.convert(gi.getStart()) * RULE_SPAN));
89  int dx2a = (int) (RULE_SPAN * measure.convert(gi.getHours()));
90  int dx2b = (int) (RULE_SPAN * measure.convert(gi.getDone()));
91  int y1 = (ITEM_SPAN * (gi.getPosition() - 1)) + ITEM_INIT;
92  int dy2 = ITEM_HEIGHT;
93  if(!Strings.isBlank(gi.getUniqueId())) {
94  setForceStyle("cursor:pointer;");
95  setClickElementData(gi.getUniqueId());
96  text(Strings.truncateAndWarn(gi.getName(), GanttData.MAX_NAME_LENGTH), 15, y1 + 15, gi.getName());
97  setForceStyle("cursor:pointer;");
98  setClickElementData(gi.getUniqueId());
99  if(gi.isFinished()) {
100  shadowedRoundRectangle(x1, y1, dx2a, dy2, "#55ff55", 1, gi.getName());
101  } else {
102  shadowedRoundRectangle(x1, y1, dx2a, dy2, "#5555ff", 1, gi.getName());
103  }
104  setForceStyle("cursor:pointer;");
105  setClickElementData(gi.getUniqueId());
106  shadowedRoundRectangle(x1, y1 + 5, dx2b, dy2 - 10, "#ff5555", 1, gi.getName());
107  if(gi.isMilestone()) {
108  int x = (int) Math.max(x1 + dx2a, x1 + dx2b) +5;
109  int y = (ITEM_SPAN * (count - 1)) + ITEM_INIT + 5;
110  int square = (int) (ITEM_HEIGHT * 0.6);
111  setForceTransform("rotate(45," + (x + square/2) + "," + (y + square/2) + ")");
113  x,
114  y,
115  square,
116  square, "#000000", 1);
117  }
118  } else {
119  setForceStyle("fill:#888899");
120  text(Strings.truncateAndWarn(gi.getName(), GanttData.MAX_NAME_LENGTH), 5, (ITEM_SPAN * count) - 14 + ITEM_INIT, gi.getName());
121  shadowedRoundSpan(x1 - 5, y1, dx2a + 10, dy2 - 10, "#aaaabb", 1);
122  }
123  line(5, y1 + ITEM_HEIGHT + ((ITEM_SPAN - ITEM_HEIGHT) / 2),
124  5 + taskPanelWidth + hoursPanelWidth, y1 + ITEM_HEIGHT + ((ITEM_SPAN - ITEM_HEIGHT) / 2),
125  "#aca", "1px");
126  }
127  for(GanttItem gi : data) {
128  int x1 = (int) (taskPanelWidth + (measure.convert(gi.getStart()) * RULE_SPAN));
129  int y1 = (ITEM_SPAN * (gi.getPosition() - 1)) + ITEM_INIT;
130  for(GanttPredecessor gp : gi.getPredecessors()) {
131  GanttItem predecessor = data.getItem(gp.getIndex());
132  int px1 = (int) (taskPanelWidth + (measure.convert(predecessor.getStart()) * RULE_SPAN));
133  int pdx2 = (int) (RULE_SPAN * measure.convert(predecessor.getMaxHours()));
134  int py1 = (ITEM_SPAN * (predecessor.getPosition() - 1)) + ITEM_INIT;
135  String lineColor= gp.isSameSpace() ? "#333" : "#F33";
136  if(gp.getMode() == GanttPredecessor.GANTT_START_TO_START) {
137  circle(x1, y1 + ITEM_HEIGHT / 2, 4, lineColor, "1px", lineColor, 1);
138  //line(x1 - 1, y1 + ITEM_HEIGHT / 2, x1 + 3, y1 + ITEM_HEIGHT / 2, "#333", "2px");
139  line(x1, y1 + ITEM_HEIGHT / 2, px1, py1 + ITEM_HEIGHT / 2, lineColor, "2px");
140  line(px1 - 1, py1 + ITEM_HEIGHT / 2, px1 + 3, py1 + ITEM_HEIGHT / 2, lineColor, "2px");
141  } else {
142  circle(x1, y1 + ITEM_HEIGHT / 2, 4, lineColor, "1px", lineColor, 1);
143  line(x1, y1 + ITEM_HEIGHT / 2, px1 + pdx2, py1 + ITEM_HEIGHT / 2, lineColor, "2px");
144  line(px1 + pdx2 + 1, py1 + ITEM_HEIGHT / 2, px1 + pdx2 - 3, py1 + ITEM_HEIGHT / 2, lineColor, "2px");
145  }
146  }
147  }
148  }
149 }
static String byKey(String key)
Definition: I_.java:83
static final int MAX_NAME_LENGTH
Definition: GanttData.java:30
GanttData getData()
Definition: Gantt.java:40
void setData(GanttData data)
Definition: Gantt.java:44
void rule(int units)
Definition: Gantt.java:48
void startComposing(String onUserEvent, String width, String height, double scale)
Definition: Gantt.java:61
void shadowedRoundSpan(int x, int y, int width, int height, String fill, double opacity)
Definition: Svg.java:246
void shadowedRoundRectangle(int x, int y, int width, int height, String fill, double opacity, String tooltip)
Definition: Svg.java:275
void circle(int x, int y, int r)
Definition: Svg.java:82
void setForceStyle(String forceStyle)
Definition: Svg.java:282
HTMLGenerator startTag(String tag, String[] attributes)
Definition: Svg.java:310
void setClickElementData(String clickElementData)
Definition: Svg.java:290
void line(int x1, int y1, int x2, int y2, String stroke, String strokeWidth)
Definition: Svg.java:108
void setForceTransform(String forceTransform)
Definition: Svg.java:286
void text(String text, int x, int y)
Definition: Svg.java:198
void shadowedRectangle(int x, int y, int width, int height, String fill, double opacity)
Definition: Svg.java:268
static GanttMeasure chooseMeasure(double hours)
double convert(double hours)