You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SimplePlanDrawer.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.plan;
  19. import java.text.DateFormat;
  20. import java.util.Calendar;
  21. import java.util.Date;
  22. import java.util.HashMap;
  23. import org.w3c.dom.DOMImplementation;
  24. import org.w3c.dom.Document;
  25. import org.w3c.dom.Element;
  26. import org.apache.batik.dom.svg.SVGDOMImplementation;
  27. import org.apache.fop.svg.SVGUtilities;
  28. /**
  29. * Simple plan drawer implementation.
  30. */
  31. public class SimplePlanDrawer implements PlanDrawer {
  32. private static final String SVG_NAMESPACE = SVGDOMImplementation.SVG_NAMESPACE_URI;
  33. private float fontSize;
  34. private HashMap hints;
  35. private java.awt.Font font = null;
  36. private boolean bord = false;
  37. private float lSpace = 15;
  38. private float width;
  39. private float height;
  40. private float topEdge;
  41. private float rightEdge;
  42. private String[] colours;
  43. private String[] darkcolours;
  44. private Date startDate;
  45. private Date endDate;
  46. /**
  47. * Sets the start date.
  48. * @param sd start date
  49. */
  50. public void setStartDate(Date sd) {
  51. startDate = sd;
  52. }
  53. /**
  54. * Sets the end date.
  55. * @param ed end date
  56. */
  57. public void setEndDate(Date ed) {
  58. endDate = ed;
  59. }
  60. /**
  61. * @see org.apache.fop.plan.PlanDrawer#createDocument(EventList, float, float, HashMap)
  62. */
  63. public Document createDocument(EventList data, float w, float h,
  64. HashMap hints) {
  65. this.width = w;
  66. this.height = h;
  67. this.hints = hints;
  68. fontSize = ((Float) hints.get(PlanHints.FONT_SIZE)).floatValue();
  69. bord = ((Boolean) hints.get(PlanHints.PLAN_BORDER)).booleanValue();
  70. String title = "";
  71. DOMImplementation impl
  72. = SVGDOMImplementation.getDOMImplementation();
  73. Document doc = impl.createDocument(SVG_NAMESPACE, "svg", null);
  74. Element svgRoot = doc.getDocumentElement();
  75. svgRoot.setAttributeNS(null, "width", Float.toString(width));
  76. svgRoot.setAttributeNS(null, "height", Float.toString(height));
  77. svgRoot.setAttributeNS(null, "viewBox",
  78. "0 0 " + Float.toString(width) + " " + Float.toString(height));
  79. svgRoot.setAttributeNS(null, "style",
  80. "font-size:" + 8
  81. + ";font-family:"
  82. + hints.get(PlanHints.FONT_FAMILY));
  83. font = new java.awt.Font((String)hints.get(PlanHints.FONT_FAMILY),
  84. java.awt.Font.PLAIN, (int)fontSize);
  85. if (bord) {
  86. Element border
  87. = SVGUtilities.createRect(doc, 0, 0, width, height);
  88. border.setAttributeNS(null, "style", "stroke:black;fill:none");
  89. svgRoot.appendChild(border);
  90. }
  91. float strwidth = SVGUtilities.getStringWidth(title, font);
  92. Element text;
  93. float pos = (float)(80 - strwidth / 2.0);
  94. if (pos < 5) {
  95. pos = 5;
  96. }
  97. text = SVGUtilities.createText(doc, pos, 18, title);
  98. text.setAttributeNS(null, "style", "font-size:14");
  99. svgRoot.appendChild(text);
  100. topEdge = SVGUtilities.getStringHeight(title, font) + 5;
  101. // add the actual pie chart
  102. addPlan(doc, svgRoot, data);
  103. //addLegend(doc, svgRoot, data);
  104. return doc;
  105. }
  106. protected void addPlan(Document doc, Element svgRoot, EventList data) {
  107. Date currentDate = new Date();
  108. Date lastWeek = startDate;
  109. Date future = endDate;
  110. Calendar lw = Calendar.getInstance();
  111. if (lastWeek == null || future == null) {
  112. int dow = lw.get(Calendar.DAY_OF_WEEK);
  113. lw.add(Calendar.DATE, -dow - 6);
  114. lastWeek = lw.getTime();
  115. lw.add(Calendar.DATE, 5 * 7);
  116. future = lw.getTime();
  117. }
  118. long totalDays = (long)((future.getTime() - lastWeek.getTime() + 43200000) / 86400000);
  119. lw.setTime(lastWeek);
  120. int startDay = lw.get(Calendar.DAY_OF_WEEK);
  121. float graphTop = topEdge;
  122. Element g;
  123. Element line;
  124. line = SVGUtilities.createLine(doc, 0, topEdge, width, topEdge);
  125. line.setAttributeNS(null, "style", "fill:none;stroke:black");
  126. svgRoot.appendChild(line);
  127. Element clip1 = SVGUtilities.createClip(doc,
  128. SVGUtilities.createPath(doc,
  129. "m0 0l126 0l0 " + height + "l-126 0z"), "clip1");
  130. Element clip2 = SVGUtilities.createClip(doc,
  131. SVGUtilities.createPath(doc,
  132. "m130 0l66 0l0 " + height + "l-66 0z"), "clip2");
  133. Element clip3 = SVGUtilities.createClip(doc,
  134. SVGUtilities.createPath(doc,
  135. "m200 0l" + (width - 200) + " 0l0 " + height + "l-"
  136. + (width - 200) + " 0z"), "clip3");
  137. svgRoot.appendChild(clip1);
  138. svgRoot.appendChild(clip2);
  139. svgRoot.appendChild(clip3);
  140. DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
  141. Element text;
  142. text = SVGUtilities.createText(doc, 201, topEdge - 1,
  143. df.format(lastWeek));
  144. svgRoot.appendChild(text);
  145. text = SVGUtilities.createText(doc, width, topEdge - 1,
  146. df.format(future));
  147. text.setAttributeNS(null, "text-anchor", "end");
  148. svgRoot.appendChild(text);
  149. line = SVGUtilities.createLine(doc, 128, topEdge, 128, height);
  150. line.setAttributeNS(null, "style", "fill:none;stroke:rgb(150,150,150)");
  151. svgRoot.appendChild(line);
  152. int offset = 0;
  153. for (int count = startDay; count < startDay + totalDays - 1; count++) {
  154. offset++;
  155. if (count % 7 == 0 || count % 7 == 1) {
  156. Element rect = SVGUtilities.createRect(doc,
  157. 200 + (offset - 1) * (width - 200) / (totalDays - 2),
  158. (float)(topEdge + 0.5),
  159. (width - 200) / (totalDays - 3),
  160. height - 1 - topEdge);
  161. rect.setAttributeNS(null, "style", "stroke:none;fill:rgb(230,230,230)");
  162. svgRoot.appendChild(rect);
  163. }
  164. line = SVGUtilities.createLine(doc,
  165. 200 + (offset - 1) * (width - 200) / (totalDays - 2),
  166. (float)(topEdge + 0.5),
  167. 200 + (offset - 1) * (width - 200) / (totalDays - 2),
  168. (float)(height - 0.5));
  169. line.setAttributeNS(null, "style", "fill:none;stroke:rgb(200,200,200)");
  170. svgRoot.appendChild(line);
  171. }
  172. for (int count = 0; count < data.getSize(); count++) {
  173. GroupInfo gi = data.getGroupInfo(count);
  174. g = SVGUtilities.createG(doc);
  175. text = SVGUtilities.createText(doc, 1, topEdge + 12,
  176. gi.getName());
  177. text.setAttributeNS(null, "style", "clip-path:url(#clip1)");
  178. g.appendChild(text);
  179. if (count > 0) {
  180. line = SVGUtilities.createLine(doc, 0, topEdge + 2,
  181. width, topEdge + 2);
  182. line.setAttributeNS(null, "style", "fill:none;stroke:rgb(100,100,100)");
  183. g.appendChild(line);
  184. }
  185. float lastTop = topEdge;
  186. topEdge += 14;
  187. boolean showing = false;
  188. for (int count1 = 0; count1 < gi.getSize(); count1++) {
  189. ActionInfo act = gi.getActionInfo(count1);
  190. String name = act.getOwner();
  191. String label = act.getLabel();
  192. text = SVGUtilities.createText(doc, 8, topEdge + 12, label);
  193. text.setAttributeNS(null, "style", "clip-path:url(#clip1)");
  194. g.appendChild(text);
  195. text = SVGUtilities.createText(doc, 130, topEdge + 12,
  196. name);
  197. text.setAttributeNS(null, "style", "clip-path:url(#clip2)");
  198. g.appendChild(text);
  199. int type = act.getType();
  200. Date start = act.getStartDate();
  201. Date end = act.getEndDate();
  202. if (end.after(lastWeek) && start.before(future)) {
  203. showing = true;
  204. int left = 200;
  205. int right = 500;
  206. int daysToStart = (int)((start.getTime()
  207. - lastWeek.getTime() + 43200000) / 86400000);
  208. int days = (int)((end.getTime() - start.getTime()
  209. + 43200000) / 86400000);
  210. int daysFromEnd =
  211. (int)((future.getTime() - end.getTime()
  212. + 43200000) / 86400000);
  213. Element taskGraphic;
  214. switch (type) {
  215. case ActionInfo.TASK:
  216. taskGraphic = SVGUtilities.createRect(doc,
  217. left + daysToStart * 300 / (totalDays - 2),
  218. topEdge + 2, days * 300 / (totalDays - 2), 10);
  219. taskGraphic.setAttributeNS(null,
  220. "style",
  221. "stroke:black;fill:blue;stroke-width:1;clip-path:url(#clip3)");
  222. g.appendChild(taskGraphic);
  223. break;
  224. case ActionInfo.MILESTONE:
  225. taskGraphic = SVGUtilities.createPath(doc,
  226. "m " + (left
  227. + daysToStart * 300 / (totalDays - 2) - 6)
  228. + " " + (topEdge + 6) + "l6 6l6-6l-6-6z");
  229. taskGraphic.setAttributeNS(null,
  230. "style",
  231. "stroke:black;fill:black;stroke-width:1;clip-path:url(#clip3)");
  232. g.appendChild(taskGraphic);
  233. text = SVGUtilities.createText(doc,
  234. left + daysToStart * 300 / (totalDays - 2) + 8,
  235. topEdge + 9, df.format(start));
  236. g.appendChild(text);
  237. break;
  238. case ActionInfo.GROUPING:
  239. taskGraphic = SVGUtilities.createPath(doc,
  240. "m " + (left
  241. + daysToStart * 300 / (totalDays - 2) - 6)
  242. + " " + (topEdge + 6) + "l6 -6l"
  243. + (days * 300 / (totalDays - 2))
  244. + " 0l6 6l-6 6l-4-4l"
  245. + -(days * 300 / (totalDays - 2) - 8)
  246. + " 0l-4 4l-6-6z");
  247. taskGraphic.setAttributeNS(null,
  248. "style",
  249. "stroke:black;fill:black;stroke-width:1;clip-path:url(#clip3)");
  250. g.appendChild(taskGraphic);
  251. break;
  252. default:
  253. break;
  254. }
  255. }
  256. topEdge += 14;
  257. }
  258. if (showing) {
  259. svgRoot.appendChild(g);
  260. } else {
  261. topEdge = lastTop;
  262. }
  263. }
  264. int currentDays =
  265. (int)((currentDate.getTime() - lastWeek.getTime()
  266. + 43200000) / 86400000);
  267. text = SVGUtilities.createText(doc,
  268. (float)(200 + (currentDays + 0.5) * 300 / 35),
  269. graphTop - 1, df.format(currentDate));
  270. text.setAttributeNS(null, "text-anchor", "middle");
  271. text.setAttributeNS(null, "style", "stroke:rgb(100,100,100)");
  272. svgRoot.appendChild(text);
  273. line = SVGUtilities.createLine(doc,
  274. (float)(200 + (currentDays + 0.5) * 300 / 35), graphTop,
  275. (float)(200 + (currentDays + 0.5) * 300 / 35), height);
  276. line.setAttributeNS(null, "style", "fill:none;stroke:rgb(200,50,50);stroke-dasharray:5,5");
  277. svgRoot.appendChild(line);
  278. }
  279. }