taskjuggler 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (410) hide show
  1. data/CHANGELOG +44 -0
  2. data/bin/tj3webd +4 -0
  3. data/data/css/tjreport.css +14 -5
  4. data/data/tjp.vim +22 -7
  5. data/examples/Fedora-20/reports.tji +2 -4
  6. data/examples/Scrum/Product Burndown.csv +26 -0
  7. data/examples/Scrum/Sprint 1 Burndown.csv +26 -0
  8. data/examples/Scrum/Sprint 2 Burndown.csv +26 -0
  9. data/examples/Scrum/Sprint 3 Burndown.csv +26 -0
  10. data/examples/Scrum/scrum.tjp +141 -0
  11. data/examples/Tutorial/tutorial.tjp +13 -7
  12. data/lib/taskjuggler/Attributes.rb +2 -3
  13. data/lib/taskjuggler/HTMLDocument.rb +25 -18
  14. data/lib/taskjuggler/Journal.rb +85 -65
  15. data/lib/taskjuggler/KeywordDocumentation.rb +25 -13
  16. data/lib/taskjuggler/LeaveList.rb +1 -1
  17. data/lib/taskjuggler/Limits.rb +3 -5
  18. data/lib/taskjuggler/MessageHandler.rb +173 -19
  19. data/lib/taskjuggler/Painter.rb +75 -0
  20. data/lib/taskjuggler/Painter/BasicShapes.rb +76 -0
  21. data/lib/taskjuggler/Painter/Color.rb +273 -0
  22. data/lib/taskjuggler/Painter/Element.rb +56 -0
  23. data/lib/taskjuggler/Painter/FontData.rb +221 -0
  24. data/lib/taskjuggler/Painter/FontMetrics.rb +125 -0
  25. data/lib/taskjuggler/Painter/FontMetricsData.rb +151 -0
  26. data/lib/taskjuggler/Painter/Group.rb +77 -0
  27. data/lib/taskjuggler/Painter/Points.rb +47 -0
  28. data/lib/taskjuggler/Painter/Primitives.rb +100 -0
  29. data/lib/taskjuggler/Painter/SVGSupport.rb +36 -0
  30. data/lib/taskjuggler/Painter/Text.rb +36 -0
  31. data/lib/taskjuggler/Project.rb +46 -29
  32. data/lib/taskjuggler/ProjectFileParser.rb +24 -22
  33. data/lib/taskjuggler/ProjectFileScanner.rb +2 -2
  34. data/lib/taskjuggler/PropertyTreeNode.rb +26 -34
  35. data/lib/taskjuggler/Query.rb +8 -5
  36. data/lib/taskjuggler/RealFormat.rb +3 -0
  37. data/lib/taskjuggler/Resource.rb +3 -5
  38. data/lib/taskjuggler/ResourceScenario.rb +19 -7
  39. data/lib/taskjuggler/RichText.rb +4 -6
  40. data/lib/taskjuggler/RichText/FunctionExample.rb +1 -1
  41. data/lib/taskjuggler/RichText/FunctionHandler.rb +5 -6
  42. data/lib/taskjuggler/RichText/Parser.rb +4 -6
  43. data/lib/taskjuggler/RichText/RTFNavigator.rb +1 -1
  44. data/lib/taskjuggler/RichText/RTFQuery.rb +2 -3
  45. data/lib/taskjuggler/RichText/RTFReport.rb +1 -1
  46. data/lib/taskjuggler/RichText/RTFReportLink.rb +1 -2
  47. data/lib/taskjuggler/RichText/RTFWithQuerySupport.rb +1 -1
  48. data/lib/taskjuggler/RichText/Scanner.rb +6 -6
  49. data/lib/taskjuggler/RichText/Snip.rb +1 -2
  50. data/lib/taskjuggler/RuntimeConfig.rb +9 -6
  51. data/lib/taskjuggler/ScenarioData.rb +4 -3
  52. data/lib/taskjuggler/Scoreboard.rb +6 -0
  53. data/lib/taskjuggler/SheetHandlerBase.rb +25 -8
  54. data/lib/taskjuggler/SimpleQueryExpander.rb +14 -5
  55. data/lib/taskjuggler/SyntaxReference.rb +1 -2
  56. data/lib/taskjuggler/TableColumnSorter.rb +84 -0
  57. data/lib/taskjuggler/Task.rb +3 -5
  58. data/lib/taskjuggler/TaskJuggler.rb +36 -29
  59. data/lib/taskjuggler/TaskScenario.rb +154 -66
  60. data/lib/taskjuggler/TextParser.rb +24 -17
  61. data/lib/taskjuggler/TextParser/Scanner.rb +16 -11
  62. data/lib/taskjuggler/TextParser/SourceFileInfo.rb +20 -15
  63. data/lib/taskjuggler/TimeSheets.rb +6 -12
  64. data/lib/taskjuggler/Tj3AppBase.rb +35 -16
  65. data/lib/taskjuggler/Tj3Config.rb +1 -1
  66. data/lib/taskjuggler/TjpSyntaxRules.rb +239 -49
  67. data/lib/taskjuggler/XMLElement.rb +9 -2
  68. data/lib/taskjuggler/apps/Tj3.rb +43 -37
  69. data/lib/taskjuggler/apps/Tj3Client.rb +62 -112
  70. data/lib/taskjuggler/apps/Tj3Daemon.rb +66 -29
  71. data/lib/taskjuggler/apps/Tj3Man.rb +5 -5
  72. data/lib/taskjuggler/apps/Tj3SsReceiver.rb +10 -13
  73. data/lib/taskjuggler/apps/Tj3SsSender.rb +13 -16
  74. data/lib/taskjuggler/apps/Tj3TsReceiver.rb +10 -13
  75. data/lib/taskjuggler/apps/Tj3TsSender.rb +12 -15
  76. data/lib/taskjuggler/apps/Tj3TsSummary.rb +12 -15
  77. data/lib/taskjuggler/apps/Tj3WebD.rb +99 -0
  78. data/lib/taskjuggler/daemon/Daemon.rb +50 -10
  79. data/lib/taskjuggler/daemon/DaemonConnector.rb +127 -0
  80. data/lib/taskjuggler/daemon/ProcessIntercom.rb +36 -21
  81. data/lib/taskjuggler/daemon/ProjectBroker.rb +122 -112
  82. data/lib/taskjuggler/daemon/ProjectServer.rb +78 -46
  83. data/lib/taskjuggler/daemon/ReportServer.rb +52 -28
  84. data/lib/taskjuggler/daemon/ReportServlet.rb +92 -21
  85. data/lib/taskjuggler/daemon/WebServer.rb +75 -22
  86. data/lib/taskjuggler/daemon/WelcomePage.rb +1 -0
  87. data/lib/taskjuggler/reports/AccountListRE.rb +3 -3
  88. data/lib/taskjuggler/reports/CSVFile.rb +9 -2
  89. data/lib/taskjuggler/reports/ChartPlotter.rb +453 -0
  90. data/lib/taskjuggler/reports/Navigator.rb +1 -0
  91. data/lib/taskjuggler/reports/NikuReport.rb +4 -4
  92. data/lib/taskjuggler/reports/Report.rb +6 -18
  93. data/lib/taskjuggler/reports/ReportBase.rb +9 -9
  94. data/lib/taskjuggler/reports/ReportContext.rb +2 -2
  95. data/lib/taskjuggler/reports/StatusSheetReport.rb +6 -6
  96. data/lib/taskjuggler/reports/TableReport.rb +24 -15
  97. data/lib/taskjuggler/reports/TimeSheetReport.rb +5 -5
  98. data/lib/taskjuggler/reports/TraceReport.rb +251 -0
  99. data/lib/tj3webd.rb +17 -0
  100. data/manual/Day_To_Day_Juggling +10 -3
  101. data/manual/Installation +38 -19
  102. data/manual/Software +25 -19
  103. data/manual/Tutorial +119 -110
  104. data/manual/html/Day_To_Day_Juggling.html +7 -5
  105. data/manual/html/Getting_Started.html +4 -4
  106. data/manual/html/How_To_Contribute.html +4 -4
  107. data/manual/html/Installation.html +19 -11
  108. data/manual/html/Intro.html +4 -4
  109. data/manual/html/Reporting_Bugs.html +4 -4
  110. data/manual/html/Rich_Text_Attributes.html +4 -4
  111. data/manual/html/Software.html +15 -11
  112. data/manual/html/TaskJuggler_2x_Migration.html +4 -4
  113. data/manual/html/TaskJuggler_Internals.html +4 -4
  114. data/manual/html/The_TaskJuggler_Syntax.html +4 -4
  115. data/manual/html/Tutorial.html +41 -32
  116. data/manual/html/account.html +4 -4
  117. data/manual/html/account.task.html +4 -4
  118. data/manual/html/accountprefix.html +4 -4
  119. data/manual/html/accountreport.html +27 -9
  120. data/manual/html/accountroot.html +5 -5
  121. data/manual/html/active.html +4 -4
  122. data/manual/html/adopt.task.html +4 -4
  123. data/manual/html/aggregate.html +4 -4
  124. data/manual/html/alert.html +4 -4
  125. data/manual/html/alertlevels.html +4 -4
  126. data/manual/html/allocate.html +5 -5
  127. data/manual/html/alphabet.html +4 -4
  128. data/manual/html/alternative.html +4 -4
  129. data/manual/html/author.html +4 -4
  130. data/manual/html/balance.html +5 -5
  131. data/manual/html/booking.resource.html +4 -4
  132. data/manual/html/booking.task.html +4 -4
  133. data/manual/html/caption.html +5 -5
  134. data/manual/html/cellcolor.column.html +43 -8
  135. data/manual/html/celltext.column.html +4 -4
  136. data/manual/html/center.html +5 -5
  137. data/manual/html/charge.html +4 -4
  138. data/manual/html/chargeset.html +4 -4
  139. data/manual/html/columnid.html +27 -15
  140. data/manual/html/columns.html +5 -5
  141. data/manual/html/complete.html +4 -4
  142. data/manual/html/copyright.html +4 -4
  143. data/manual/html/credits.html +4 -4
  144. data/manual/html/css/tjreport.css +14 -5
  145. data/manual/html/currency.html +4 -4
  146. data/manual/html/currencyformat.html +5 -5
  147. data/manual/html/dailymax.html +5 -5
  148. data/manual/html/dailymin.html +5 -5
  149. data/manual/html/dailyworkinghours.html +4 -4
  150. data/manual/html/date.extend.html +4 -4
  151. data/manual/html/date.html +5 -5
  152. data/manual/html/definitions.html +4 -4
  153. data/manual/html/depends.html +4 -4
  154. data/manual/html/details.html +4 -4
  155. data/manual/html/disabled.html +4 -4
  156. data/manual/html/duration.html +4 -4
  157. data/manual/html/efficiency.html +4 -4
  158. data/manual/html/effort.html +4 -4
  159. data/manual/html/email.html +4 -4
  160. data/manual/html/enabled.html +4 -4
  161. data/manual/html/end.column.html +4 -4
  162. data/manual/html/end.html +4 -4
  163. data/manual/html/end.limit.html +4 -4
  164. data/manual/html/end.report.html +5 -5
  165. data/manual/html/end.timesheet.html +4 -4
  166. data/manual/html/endcredit.html +4 -4
  167. data/manual/html/epilog.html +5 -5
  168. data/manual/html/export.html +4 -4
  169. data/manual/html/extend.html +4 -4
  170. data/manual/html/fail.html +43 -8
  171. data/manual/html/fdl.html +4 -4
  172. data/manual/html/flags.account.html +4 -4
  173. data/manual/html/flags.html +4 -4
  174. data/manual/html/flags.journalentry.html +4 -4
  175. data/manual/html/flags.report.html +5 -5
  176. data/manual/html/flags.resource.html +4 -4
  177. data/manual/html/flags.statussheet.html +4 -4
  178. data/manual/html/flags.task.html +4 -4
  179. data/manual/html/flags.timesheet.html +4 -4
  180. data/manual/html/fontcolor.column.html +43 -8
  181. data/manual/html/footer.html +5 -5
  182. data/manual/html/formats.html +5 -5
  183. data/manual/html/functions.html +4 -4
  184. data/manual/html/gapduration.html +4 -4
  185. data/manual/html/gaplength.html +4 -4
  186. data/manual/html/halign.center.html +4 -4
  187. data/manual/html/halign.column.html +43 -8
  188. data/manual/html/halign.left.html +4 -4
  189. data/manual/html/halign.right.html +4 -4
  190. data/manual/html/hasalert.html +4 -4
  191. data/manual/html/header.html +5 -5
  192. data/manual/html/headline.html +7 -7
  193. data/manual/html/height.html +72 -0
  194. data/manual/html/hideaccount.html +46 -11
  195. data/manual/html/hidejournalentry.html +5 -5
  196. data/manual/html/hidereport.html +43 -8
  197. data/manual/html/hideresource.html +44 -9
  198. data/manual/html/hidetask.html +44 -9
  199. data/manual/html/icalreport.html +4 -4
  200. data/manual/html/include.macro.html +4 -4
  201. data/manual/html/include.project.html +4 -4
  202. data/manual/html/include.properties.html +4 -4
  203. data/manual/html/index.html +2 -1
  204. data/manual/html/inherit.extend.html +4 -4
  205. data/manual/html/interval1.html +4 -4
  206. data/manual/html/interval2.html +4 -4
  207. data/manual/html/interval3.html +4 -4
  208. data/manual/html/interval4.html +4 -4
  209. data/manual/html/isactive.html +4 -4
  210. data/manual/html/ischildof.html +4 -4
  211. data/manual/html/isdependencyof.html +4 -4
  212. data/manual/html/isdutyof.html +4 -4
  213. data/manual/html/isfeatureof.html +4 -4
  214. data/manual/html/isleaf.html +4 -4
  215. data/manual/html/ismilestone.html +4 -4
  216. data/manual/html/isongoing.html +4 -4
  217. data/manual/html/isresource.html +4 -4
  218. data/manual/html/isresponsibilityof.html +4 -4
  219. data/manual/html/istask.html +4 -4
  220. data/manual/html/journalattributes.html +11 -7
  221. data/manual/html/journalentry.html +4 -4
  222. data/manual/html/journalmode.html +5 -5
  223. data/manual/html/leaveallowance.html +5 -5
  224. data/manual/html/leaves.html +5 -6
  225. data/manual/html/left.html +5 -5
  226. data/manual/html/length.html +4 -4
  227. data/manual/html/limits.allocate.html +4 -4
  228. data/manual/html/limits.html +4 -4
  229. data/manual/html/limits.resource.html +4 -4
  230. data/manual/html/limits.task.html +4 -4
  231. data/manual/html/listitem.column.html +4 -4
  232. data/manual/html/listtype.column.html +4 -4
  233. data/manual/html/loadunit.html +5 -5
  234. data/manual/html/logicalexpression.html +8 -44
  235. data/manual/html/logicalflagexpression.html +4 -4
  236. data/manual/html/macro.html +4 -4
  237. data/manual/html/managers.html +4 -4
  238. data/manual/html/mandatory.html +4 -4
  239. data/manual/html/maxend.html +4 -4
  240. data/manual/html/maximum.html +5 -5
  241. data/manual/html/maxstart.html +4 -4
  242. data/manual/html/milestone.html +4 -4
  243. data/manual/html/minend.html +4 -4
  244. data/manual/html/minimum.html +5 -5
  245. data/manual/html/minstart.html +4 -4
  246. data/manual/html/monthlymax.html +5 -5
  247. data/manual/html/monthlymin.html +5 -5
  248. data/manual/html/navbar.html +10 -4
  249. data/manual/html/navigator.html +4 -4
  250. data/manual/html/newtask.html +4 -4
  251. data/manual/html/nikureport.html +4 -4
  252. data/manual/html/note.task.html +4 -4
  253. data/manual/html/now.html +4 -4
  254. data/manual/html/numberformat.html +5 -5
  255. data/manual/html/onend.html +4 -4
  256. data/manual/html/onstart.html +4 -4
  257. data/manual/html/opennodes.html +5 -5
  258. data/manual/html/overtime.booking.html +4 -4
  259. data/manual/html/period.column.html +4 -4
  260. data/manual/html/period.limit.html +4 -4
  261. data/manual/html/period.report.html +5 -5
  262. data/manual/html/period.task.html +4 -4
  263. data/manual/html/persistent.html +4 -4
  264. data/manual/html/precedes.html +4 -4
  265. data/manual/html/priority.html +4 -4
  266. data/manual/html/priority.timesheet.html +4 -4
  267. data/manual/html/project.html +4 -4
  268. data/manual/html/projectid.html +4 -4
  269. data/manual/html/projectid.task.html +4 -4
  270. data/manual/html/projectids.html +4 -4
  271. data/manual/html/projection.html +5 -7
  272. data/manual/html/prolog.html +5 -5
  273. data/manual/html/properties.html +11 -5
  274. data/manual/html/purge.html +5 -5
  275. data/manual/html/rate.html +4 -4
  276. data/manual/html/rate.resource.html +4 -4
  277. data/manual/html/reference.extend.html +4 -4
  278. data/manual/html/remaining.html +4 -4
  279. data/manual/html/replace.html +4 -4
  280. data/manual/html/reportprefix.html +4 -4
  281. data/manual/html/resource.html +4 -10
  282. data/manual/html/resourceattributes.html +4 -4
  283. data/manual/html/resourceprefix.html +4 -4
  284. data/manual/html/resourcereport.html +28 -10
  285. data/manual/html/resourceroot.html +5 -5
  286. data/manual/html/resources.limit.html +4 -4
  287. data/manual/html/responsible.html +4 -4
  288. data/manual/html/richtext.extend.html +4 -4
  289. data/manual/html/right.html +5 -5
  290. data/manual/html/rollupaccount.html +44 -9
  291. data/manual/html/rollupresource.html +44 -9
  292. data/manual/html/rolluptask.html +44 -9
  293. data/manual/html/scale.column.html +4 -4
  294. data/manual/html/scenario.html +4 -22
  295. data/manual/html/scenario.ical.html +4 -4
  296. data/manual/html/scenarios.export.html +4 -4
  297. data/manual/html/scenarios.html +5 -5
  298. data/manual/html/scenariospecific.extend.html +4 -4
  299. data/manual/html/scheduled.html +4 -4
  300. data/manual/html/scheduling.html +4 -4
  301. data/manual/html/select.html +4 -4
  302. data/manual/html/selfcontained.html +5 -5
  303. data/manual/html/shift.allocate.html +4 -4
  304. data/manual/html/shift.html +4 -4
  305. data/manual/html/shift.resource.html +5 -5
  306. data/manual/html/shift.task.html +4 -4
  307. data/manual/html/shift.timesheet.html +4 -4
  308. data/manual/html/shifts.allocate.html +4 -4
  309. data/manual/html/shifts.resource.html +4 -4
  310. data/manual/html/shifts.task.html +4 -4
  311. data/manual/html/shorttimeformat.html +4 -4
  312. data/manual/html/sloppy.booking.html +4 -4
  313. data/manual/html/sloppy.projection.html +5 -5
  314. data/manual/html/sortaccounts.html +5 -5
  315. data/manual/html/sortjournalentries.html +5 -5
  316. data/manual/html/sortresources.html +5 -5
  317. data/manual/html/sorttasks.html +5 -5
  318. data/manual/html/start.column.html +4 -4
  319. data/manual/html/start.html +4 -4
  320. data/manual/html/start.limit.html +4 -4
  321. data/manual/html/start.report.html +5 -5
  322. data/manual/html/startcredit.html +4 -4
  323. data/manual/html/status.statussheet.html +4 -4
  324. data/manual/html/status.timesheet.html +4 -4
  325. data/manual/html/statussheet.html +4 -4
  326. data/manual/html/statussheetreport.html +4 -4
  327. data/manual/html/strict.projection.html +5 -5
  328. data/manual/html/summary.html +4 -4
  329. data/manual/html/supplement.html +4 -4
  330. data/manual/html/supplement.resource.html +4 -10
  331. data/manual/html/supplement.task.html +4 -28
  332. data/manual/html/tagfile.html +4 -4
  333. data/manual/html/task.html +4 -28
  334. data/manual/html/task.statussheet.html +4 -4
  335. data/manual/html/task.timesheet.html +4 -4
  336. data/manual/html/taskattributes.html +4 -4
  337. data/manual/html/taskprefix.html +4 -4
  338. data/manual/html/taskreport.html +28 -10
  339. data/manual/html/taskroot.html +5 -5
  340. data/manual/html/text.extend.html +4 -4
  341. data/manual/html/textreport.html +27 -9
  342. data/manual/html/timeformat.html +5 -5
  343. data/manual/html/timeoff.nikureport.html +4 -4
  344. data/manual/html/timesheet.html +4 -4
  345. data/manual/html/timesheetreport.html +23 -5
  346. data/manual/html/timezone.export.html +4 -4
  347. data/manual/html/timezone.html +4 -4
  348. data/manual/html/timezone.report.html +5 -5
  349. data/manual/html/timezone.shift.html +4 -4
  350. data/manual/html/timingresolution.html +4 -4
  351. data/manual/html/title.column.html +4 -4
  352. data/manual/html/title.html +5 -5
  353. data/manual/html/toc.html +207 -179
  354. data/manual/html/tooltip.column.html +45 -10
  355. data/manual/html/tracereport.html +405 -0
  356. data/manual/html/trackingscenario.html +6 -6
  357. data/manual/html/treelevel.html +4 -4
  358. data/manual/html/vacation.html +4 -4
  359. data/manual/html/vacation.resource.html +4 -4
  360. data/manual/html/vacation.shift.html +4 -4
  361. data/manual/html/warn.html +43 -8
  362. data/manual/html/weeklymax.html +5 -5
  363. data/manual/html/weeklymin.html +5 -5
  364. data/manual/html/weekstartsmonday.html +4 -4
  365. data/manual/html/weekstartssunday.html +6 -6
  366. data/manual/html/width.column.html +6 -6
  367. data/manual/html/width.html +72 -0
  368. data/manual/html/work.html +4 -4
  369. data/manual/html/workinghours.project.html +4 -4
  370. data/manual/html/workinghours.resource.html +4 -4
  371. data/manual/html/workinghours.shift.html +4 -4
  372. data/manual/html/yearlyworkingdays.html +4 -4
  373. data/spec/Color_spec.rb +60 -0
  374. data/spec/ProjectBroker_spec.rb +3 -2
  375. data/spec/StatusSheets_spec.rb +5 -4
  376. data/spec/TableColumnSorter_spec.rb +78 -0
  377. data/spec/TimeSheets_spec.rb +6 -2
  378. data/spec/Tj3Daemon_spec.rb +2 -2
  379. data/spec/TraceReport_spec.rb +117 -0
  380. data/taskjuggler.gemspec +1 -1
  381. data/test/MessageChecker.rb +3 -1
  382. data/test/ReferenceGenerator.rb +1 -1
  383. data/test/TestSuite/CSV-Reports/Leave.tjp +1 -1
  384. data/test/TestSuite/CSV-Reports/refs/resourcereport_with_tasks.csv +3 -0
  385. data/test/TestSuite/CSV-Reports/refs/taskcounter.csv +9 -0
  386. data/test/TestSuite/CSV-Reports/refs/taskreport_with_resources.csv +19 -16
  387. data/test/TestSuite/CSV-Reports/refs/weekly.csv +1 -0
  388. data/test/TestSuite/Export-Reports/refs/LogicalExpression.tjp +14 -2
  389. data/test/TestSuite/Export-Reports/refs/tutorial.tjp +98 -86
  390. data/test/TestSuite/Scheduler/Correct/Leaves.tjp +25 -0
  391. data/test/TestSuite/Syntax/Correct/Leave.tjp +1 -1
  392. data/test/TestSuite/Syntax/Correct/LogicalExpression.tjp +9 -1
  393. data/test/TestSuite/Syntax/Correct/TraceReport.tjp +10 -0
  394. data/test/TestSuite/Syntax/Correct/tutorial.tjp +10 -4
  395. data/test/test_CSV-Reports.rb +3 -3
  396. data/test/test_Export-Reports.rb +91 -86
  397. data/test/test_Journal.rb +15 -12
  398. data/test/test_Limits.rb +3 -3
  399. data/test/test_Project.rb +1 -2
  400. data/test/test_ProjectFileScanner.rb +1 -1
  401. data/test/test_PropertySet.rb +1 -1
  402. data/test/test_Query.rb +5 -6
  403. data/test/test_ReportGenerator.rb +15 -7
  404. data/test/test_RichText.rb +4 -3
  405. data/test/test_Scheduler.rb +19 -7
  406. data/test/test_ShiftAssignments.rb +2 -2
  407. data/test/test_SimpleQueryExpander.rb +29 -2
  408. data/test/test_Syntax.rb +14 -5
  409. metadata +49 -10
  410. data/lib/taskjuggler/LogFile.rb +0 -73
@@ -49,7 +49,7 @@ class TaskJuggler
49
49
  end
50
50
 
51
51
  def to_s
52
- "#{@type} #{@description ? "\"#{@description}\"" : ""} #{@interval}"
52
+ "#{@type} #{@reason ? "\"#{@reason}\"" : ""} #{@interval}"
53
53
  end
54
54
 
55
55
  end
@@ -94,9 +94,7 @@ class TaskJuggler
94
94
  def ok?(index, upper, resource)
95
95
  # if @upper does not match or the provided resource does not match,
96
96
  # we can ignore this limit.
97
- return true if @upper != upper ||
98
- (!@resource.nil? ^ !resource.nil?) ||
99
- (@resource && resource && @resource != resource)
97
+ return true if @upper != upper || (@resource && @resource != resource)
100
98
 
101
99
  if index.nil?
102
100
  # No index given. We need to check all counters.
@@ -109,8 +107,8 @@ class TaskJuggler
109
107
  # anything. Everything is ok.
110
108
  return true if !@interval.contains?(index)
111
109
 
112
- return @upper ? @scoreboard[idxToSbIdx(index)] < @value :
113
- @scoreboard[idxToSbIdx(index)] >= @value
110
+ sbVal = @scoreboard[idxToSbIdx(index)]
111
+ return @upper ? (sbVal < @value) : (sbVal >= @value)
114
112
  end
115
113
  end
116
114
 
@@ -15,18 +15,23 @@ if RUBY_VERSION < "1.9.0"
15
15
  require 'rubygems'
16
16
  end
17
17
 
18
+ require 'singleton'
18
19
  require 'term/ansicolor'
19
20
  require 'taskjuggler/TextParser/SourceFileInfo'
20
21
 
21
22
  class TaskJuggler
22
23
 
24
+ class TjRuntimeError < RuntimeError
25
+ end
26
+
23
27
  # The Message object can store several classes of messages that the
24
28
  # application can send out.
25
29
  class Message
26
30
 
27
31
  include Term::ANSIColor
28
32
 
29
- attr_reader :type, :id, :message, :sourceFileInfo, :line
33
+ attr_reader :type, :id, :message, :line
34
+ attr_accessor :sourceFileInfo
30
35
 
31
36
  # Create a new Message object. The _type_ specifies what tpye of message
32
37
  # this is. The following types are supported: fatal, error, warning, info
@@ -68,7 +73,7 @@ class TaskJuggler
68
73
  @scenario = scenario
69
74
  end
70
75
 
71
- # Convert the Message into a String.
76
+ # Convert the Message into a String that can be printed to the console.
72
77
  def to_s
73
78
  str = ""
74
79
  # The SourceFileInfo is printed as <fileName>:line:
@@ -87,26 +92,81 @@ class TaskJuggler
87
92
  str
88
93
  end
89
94
 
95
+ # Convert the Message into a String that can be stored in a log file.
96
+ def to_log
97
+ str = ""
98
+ # The SourceFileInfo is printed as <fileName>:line:
99
+ if @sourceFileInfo
100
+ str += "#{@sourceFileInfo.fileName}:#{sourceFileInfo.lineNo}: "
101
+ end
102
+ str += "Scenario #{@scenario.id}: " if @scenario
103
+ str += @message
104
+ str
105
+ end
106
+
90
107
  end
91
108
 
92
109
  # The MessageHandler can display and store application messages. Depending
93
110
  # on the type of the message, a TjExeption can be raised (:error), or the
94
111
  # program can be immedidately aborted (:fatal). Other types will just
95
112
  # continue the program flow.
96
- class MessageHandler
113
+ class MessageHandlerInstance
114
+
115
+ include Singleton
97
116
 
98
117
  attr_reader :messages, :errors
99
- attr_accessor :scenario, :abortOnWarning
118
+ attr_accessor :logFile, :appName, :abortOnWarning, :trapSetup, :baselineSFI
100
119
 
101
- # Initialize the MessageHandler. _console_ specifies if the messages
102
- # should be printed to $stderr.
103
- def initialize(console = false)
104
- @messages = []
105
- @console = console
106
- # We count the errors.
107
- @errors = 0
120
+ LogLevels = { :none => 0, :fatal => 1, :error => 2, :critical => 2,
121
+ :warning => 3, :info => 4, :debug => 5 }
122
+
123
+ # Initialize the MessageHandler.
124
+ def initialize
125
+ reset
126
+ end
127
+
128
+ # Reset the MessageHandler to the initial state. All messages will be
129
+ # purged and the error counter set to 0.
130
+ def reset
131
+ # This setting controls what type of messages will be written to the
132
+ # console.
133
+ @outputLevel = 4
134
+ # This setting controls what type of messages will be written to the log
135
+ # file.
136
+ @logLevel = 3
137
+ # The full file name of the log file.
138
+ @logFile = nil
139
+ # The name of the current application
140
+ @appName = 'unknown'
108
141
  # Set to true if program should be exited on warnings.
109
142
  @abortOnWarning = false
143
+ # A SourceFileInfo object that will be used to baseline the provided
144
+ # source file infos of the messages.
145
+ @baselineSFI = nil
146
+ # If this is set the true, we only throw a TjRuntimeError instead of
147
+ # using exit().
148
+ @trapSetup = false
149
+
150
+ clear
151
+ end
152
+
153
+ # Clear the error log.
154
+ def clear
155
+ # A counter for messages of type error.
156
+ @errors = 0
157
+ # A list of all generated messages.
158
+ @messages = []
159
+ end
160
+
161
+
162
+ # Set the console output level.
163
+ def outputLevel=(level)
164
+ @outputLevel = checkLevel(level)
165
+ end
166
+
167
+ # Set the log output level.
168
+ def logLevel=(level)
169
+ @logLevel = checkLevel(level)
110
170
  end
111
171
 
112
172
  # Generate a fatal message that will abort the application.
@@ -142,19 +202,70 @@ class TaskJuggler
142
202
  # Generate a debug message.
143
203
  def debug(id, message, sourceFileInfo = nil, line = nil, data = nil,
144
204
  scenario = nil)
145
- addMessage(:info, id, message, sourceFileInfo, line, data, scenario)
205
+ addMessage(:debug, id, message, sourceFileInfo, line, data, scenario)
206
+ end
207
+
208
+ # Convert all messages into a single String.
209
+ def to_s
210
+ text = ''
211
+ @messages.each { |msg| text += msg.to_s }
212
+ text
213
+ end
214
+
215
+ private
216
+
217
+ def checkLevel(level)
218
+ if level.is_a?(Fixnum)
219
+ if level < 0 || level > 5
220
+ raise ArgumentError, "Unsupported level #{level}"
221
+ end
222
+ else
223
+ unless (level = LogLevels[level])
224
+ raise ArgumentError, "Unsupported level #{level}"
225
+ end
226
+ end
227
+
228
+ level
229
+ end
230
+
231
+ def log(type, message)
232
+ return unless @logFile
233
+
234
+ timeStamp = Time.new.strftime("%Y-%m-%d %H:%M:%S")
235
+ begin
236
+ @logFile.untaint
237
+ File.open(@logFile, 'a') do |f|
238
+ f.write("#{timeStamp} #{type} #{@appName}[#{Process.pid}]: " +
239
+ "#{message}\n")
240
+ end
241
+ rescue
242
+ $stderr.puts "Cannot write to log file #{@logFile}: #{$!}"
243
+ end
146
244
  end
147
245
 
148
246
  # Generate a message by specifying the _type_.
149
247
  def addMessage(type, id, message, sourceFileInfo = nil, line = nil,
150
248
  data = nil, scenario = nil)
249
+ # If we have a SourceFileInfo and a baseline SFI, we correct the
250
+ # sourceFileInfo accordingly.
251
+ if sourceFileInfo && @baselineSFI
252
+ sourceFileInfo = TextParser::SourceFileInfo.new(
253
+ @baselineSFI.fileName,
254
+ sourceFileInfo.lineNo + @baselineSFI.lineNo - 1,
255
+ sourceFileInfo.columnNo)
256
+ end
257
+
151
258
  # Treat criticals like errors but without generating another
152
259
  # exception.
153
260
  msg = Message.new(type == :critical ? :error : type, id, message,
154
261
  sourceFileInfo, line, data, scenario)
155
262
  @messages << msg
263
+
264
+ # Append the message to the log file if requested by the user.
265
+ log(type, msg.to_log) if @logLevel >= LogLevels[type]
266
+
156
267
  # Print the message to $stderr if requested by the user.
157
- $stderr.puts msg.to_s if @console
268
+ $stderr.puts msg.to_s if @outputLevel >= LogLevels[type]
158
269
 
159
270
  case type
160
271
  when :warning
@@ -165,17 +276,60 @@ class TaskJuggler
165
276
  when :error
166
277
  # Increase the error counter.
167
278
  @errors += 1
168
- raise TjException.new, ''
279
+ if @trapSetup
280
+ raise TjRuntimeError
281
+ else
282
+ exit 1
283
+ end
169
284
  when :fatal
170
285
  raise RuntimeError
171
286
  end
172
287
  end
173
288
 
174
- # Convert all messages into a single String.
175
- def to_s
176
- text = ''
177
- @messages.each { |msg| text += msg.to_s }
178
- text
289
+ end
290
+
291
+ module MessageHandler
292
+
293
+ # Generate a fatal message that will abort the application.
294
+ def fatal(id, message, sourceFileInfo = nil, line = nil, data = nil,
295
+ scenario = nil)
296
+ MessageHandlerInstance.instance.fatal(id, message, sourceFileInfo, line,
297
+ data, scenario)
298
+ end
299
+
300
+ # Generate an error message.
301
+ def error(id, message, sourceFileInfo = nil, line = nil, data = nil,
302
+ scenario = nil)
303
+ MessageHandlerInstance.instance.error(id, message, sourceFileInfo, line,
304
+ data, scenario)
305
+ end
306
+
307
+ # Generate an critical message.
308
+ def critical(id, message, sourceFileInfo = nil, line = nil, data = nil,
309
+ scenario = nil)
310
+ MessageHandlerInstance.instance.critical(id, message, sourceFileInfo,
311
+ line, data, scenario)
312
+ end
313
+
314
+ # Generate a warning.
315
+ def warning(id, message, sourceFileInfo = nil, line = nil, data = nil,
316
+ scenario = nil)
317
+ MessageHandlerInstance.instance.warning(id, message, sourceFileInfo,
318
+ line, data, scenario)
319
+ end
320
+
321
+ # Generate an info message.
322
+ def info(id, message, sourceFileInfo = nil, line = nil, data = nil,
323
+ scenario = nil)
324
+ MessageHandlerInstance.instance.info(id, message, sourceFileInfo, line,
325
+ data, scenario)
326
+ end
327
+
328
+ # Generate a debug message.
329
+ def debug(id, message, sourceFileInfo = nil, line = nil, data = nil,
330
+ scenario = nil)
331
+ MessageHandlerInstance.instance.debug(id, message, sourceFileInfo, line,
332
+ data, scenario)
179
333
  end
180
334
 
181
335
  end
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Painter.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ require 'taskjuggler/XMLElement'
15
+ require 'taskjuggler/Painter/Primitives'
16
+ require 'taskjuggler/Painter/Group'
17
+ require 'taskjuggler/Painter/BasicShapes'
18
+ require 'taskjuggler/Painter/Text'
19
+ require 'taskjuggler/Painter/FontMetrics'
20
+
21
+ class TaskJuggler
22
+
23
+ # This is a vector drawing class. It can describe a canvas with lines,
24
+ # rectangles, circles, ellipses and text elements on it. The elements can be
25
+ # grouped. It currently only supports rendering as an SVG output.
26
+ class Painter
27
+
28
+ include Primitives
29
+
30
+ # Create a canvas of dimension _width_ times _height_. The block can be
31
+ # used to add elements to the drawing. If the block has an argument, the
32
+ # block content is evaluated within the current context. If no argument is
33
+ # provided, the newly created object will be the evaluation context of the
34
+ # block. This will make instance variables of the caller inaccessible.
35
+ # Methods of the caller will still be available.
36
+ def initialize(width, height, &block)
37
+ @width = width
38
+ @height = height
39
+
40
+ @elements = []
41
+ if block
42
+ if block.arity == 1
43
+ # This is the traditional case where self is passed to the block.
44
+ # All Primitives methods now must be prefixed with the block
45
+ # variable to call them.
46
+ yield self
47
+ else
48
+ # In order to have the primitives easily available in the block, we
49
+ # use instance_eval to switch self to this object. But this makes the
50
+ # methods of the original self no longer accessible. We work around
51
+ # this by saving the original self and using method_missing to
52
+ # delegate the method call to the original self.
53
+ @originalSelf = eval('self', block.binding)
54
+ instance_eval(&block)
55
+ end
56
+ end
57
+ end
58
+
59
+ # Delegator to @originalSelf.
60
+ def method_missing(method, *args, &block)
61
+ @originalSelf.send(method, *args, &block)
62
+ end
63
+
64
+ # Render the canvas as SVG output (tree of XMLElement objects).
65
+ def to_svg
66
+ XMLElement.new('svg', 'width' => "#{@width}px",
67
+ 'height' => "#{@height}px") do
68
+ @elements.map { |el| el.to_svg }
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = BasicShapes.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ require 'taskjuggler/XMLElement'
15
+ require 'taskjuggler/Painter/Element'
16
+
17
+ class TaskJuggler
18
+
19
+ class Painter
20
+
21
+ # A circle element.
22
+ class Circle < Element
23
+
24
+ # Create a circle with center at cx, cy and radius r.
25
+ def initialize(attrs)
26
+ super('circle', [ :cx, :cy, :r ] + FillAndStrokeAttrs, attrs)
27
+ end
28
+
29
+ end
30
+
31
+ # An ellipse element.
32
+ class Ellipse < Element
33
+
34
+ # Create an ellipse with center at cx, cy and radiuses rx and ry.
35
+ def initialize(attrs)
36
+ super('ellipse', [ :cx, :cy, :rx, :ry ] + FillAndStrokeAttrs, attrs)
37
+ end
38
+
39
+ end
40
+
41
+ # A line element.
42
+ class Line < Element
43
+
44
+ # Create a line from x1, y1, to x2, y2.
45
+ def initialize(attrs)
46
+ super('line', [ :x1, :y1, :x2, :y2 ] + StrokeAttrs, attrs)
47
+ end
48
+
49
+ end
50
+
51
+ # A Rectangle element.
52
+ class Rect < Element
53
+
54
+ # Create a rectangle at x, y with width and height.
55
+ def initialize(attrs)
56
+ super('rect', [ :x, :y, :width, :height, :rx, :ry ] +
57
+ FillAndStrokeAttrs, attrs)
58
+ end
59
+
60
+ end
61
+
62
+ # A Polygon line element.
63
+ class PolyLine < Element
64
+
65
+ # Create a polygon line with the provided Points.
66
+ def initialize(attrs)
67
+ super('polyline', [ :points ] + FillAndStrokeAttrs, attrs)
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = Color.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ class TaskJuggler
15
+
16
+ class Painter
17
+
18
+ # A description of the color. The color is stored internally as an RGB
19
+ # value. Common names are provided for many popular colors.
20
+ class Color
21
+
22
+ NamedColors = {
23
+ :aliceblue => [ 240, 248, 255 ],
24
+ :antiquewhite => [ 250, 235, 215 ],
25
+ :aqua => [ 0, 255, 255 ],
26
+ :aquamarine => [ 127, 255, 212 ],
27
+ :azure => [ 240, 255, 255 ],
28
+ :beige => [ 245, 245, 220 ],
29
+ :bisque => [ 255, 228, 196 ],
30
+ :black => [ 0, 0, 0 ],
31
+ :blanchedalmond => [ 255, 235, 205 ],
32
+ :blue => [ 0, 0, 255 ],
33
+ :blueviolet => [ 138, 43, 226 ],
34
+ :brown => [ 165, 42, 42 ],
35
+ :burlywood => [ 222, 184, 135 ],
36
+ :cadetblue => [ 95, 158, 160 ],
37
+ :chartreuse => [ 127, 255, 0 ],
38
+ :chocolate => [ 210, 105, 30 ],
39
+ :coral => [ 255, 127, 80 ],
40
+ :cornflowerblue => [ 100, 149, 237 ],
41
+ :cornsilk => [ 255, 248, 220 ],
42
+ :crimson => [ 220, 20, 60 ],
43
+ :cyan => [ 0, 255, 255 ],
44
+ :darkblue => [ 0, 0, 139 ],
45
+ :darkcyan => [ 0, 139, 139 ],
46
+ :darkgoldenrod => [ 184, 134, 11 ],
47
+ :darkgray => [ 169, 169, 169 ],
48
+ :darkgreen => [ 0, 100, 0 ],
49
+ :darkgrey => [ 169, 169, 169 ],
50
+ :darkkhaki => [ 189, 183, 107 ],
51
+ :darkmagenta => [ 139, 0, 139 ],
52
+ :darkolivegreen => [ 85, 107, 47 ],
53
+ :darkorange => [ 255, 140, 0 ],
54
+ :darkorchid => [ 153, 50, 204 ],
55
+ :darkred => [ 139, 0, 0 ],
56
+ :darksalmon => [ 233, 150, 122 ],
57
+ :darkseagreen => [ 143, 188, 143 ],
58
+ :darkslateblue => [ 72, 61, 139 ],
59
+ :darkslategray => [ 47, 79, 79 ],
60
+ :darkslategrey => [ 47, 79, 79 ],
61
+ :darkturquoise => [ 0, 206, 209 ],
62
+ :darkviolet => [ 148, 0, 211 ],
63
+ :deeppink => [ 255, 20, 147 ],
64
+ :deepskyblue => [ 0, 191, 255 ],
65
+ :dimgray => [ 105, 105, 105 ],
66
+ :dimgrey => [ 105, 105, 105 ],
67
+ :dodgerblue => [ 30, 144, 255 ],
68
+ :firebrick => [ 178, 34, 34 ],
69
+ :floralwhite => [ 255, 250, 240 ],
70
+ :forestgreen => [ 34, 139, 34 ],
71
+ :fuchsia => [ 255, 0, 255 ],
72
+ :gainsboro => [ 220, 220, 220 ],
73
+ :ghostwhite => [ 248, 248, 255 ],
74
+ :gold => [ 255, 215, 0 ],
75
+ :goldenrod => [ 218, 165, 32 ],
76
+ :gray => [ 128, 128, 128 ],
77
+ :grey => [ 128, 128, 128 ],
78
+ :green => [ 0, 128, 0 ],
79
+ :greenyellow => [ 173, 255, 47 ],
80
+ :honeydew => [ 240, 255, 240 ],
81
+ :hotpink => [ 255, 105, 180 ],
82
+ :indianred => [ 205, 92, 92 ],
83
+ :indigo => [ 75, 0, 130 ],
84
+ :ivory => [ 255, 255, 240 ],
85
+ :khaki => [ 240, 230, 140 ],
86
+ :lavender => [ 230, 230, 250 ],
87
+ :lavenderblush => [ 255, 240, 245 ],
88
+ :lawngreen => [ 124, 252, 0 ],
89
+ :lemonchiffon => [ 255, 250, 205 ],
90
+ :lightblue => [ 173, 216, 230 ],
91
+ :lightcoral => [ 240, 128, 128 ],
92
+ :lightcyan => [ 224, 255, 255 ],
93
+ :lightgoldenrodyellow => [ 250, 250, 210 ],
94
+ :lightgray => [ 211, 211, 211 ],
95
+ :lightgreen => [ 144, 238, 144 ],
96
+ :lightgrey => [ 211, 211, 211 ],
97
+ :lightpink => [ 255, 182, 193 ],
98
+ :lightsalmon => [ 255, 160, 122 ],
99
+ :lightseagreen => [ 32, 178, 170 ],
100
+ :lightskyblue => [ 135, 206, 250 ],
101
+ :lightslategray => [ 119, 136, 153 ],
102
+ :lightslategrey => [ 119, 136, 153 ],
103
+ :lightsteelblue => [ 176, 196, 222 ],
104
+ :lightyellow => [ 255, 255, 224 ],
105
+ :lime => [ 0, 255, 0 ],
106
+ :limegreen => [ 50, 205, 50 ],
107
+ :linen => [ 250, 240, 230 ],
108
+ :magenta => [ 255, 0, 255 ],
109
+ :maroon => [ 128, 0, 0 ],
110
+ :mediumaquamarine => [ 102, 205, 170 ],
111
+ :mediumblue => [ 0, 0, 205 ],
112
+ :mediumorchid => [ 186, 85, 211 ],
113
+ :mediumpurple => [ 147, 112, 219 ],
114
+ :mediumseagreen => [ 60, 179, 113 ],
115
+ :mediumslateblue => [ 123, 104, 238 ],
116
+ :mediumspringgreen => [ 0, 250, 154 ],
117
+ :mediumturquoise => [ 72, 209, 204 ],
118
+ :mediumvioletred => [ 199, 21, 133 ],
119
+ :midnightblue => [ 25, 25, 112 ],
120
+ :mintcream => [ 245, 255, 250 ],
121
+ :mistyrose => [ 255, 228, 225 ],
122
+ :moccasin => [ 255, 228, 181 ],
123
+ :navajowhite => [ 255, 222, 173 ],
124
+ :navy => [ 0, 0, 128 ],
125
+ :oldlace => [ 253, 245, 230 ],
126
+ :olive => [ 128, 128, 0 ],
127
+ :olivedrab => [ 107, 142, 35 ],
128
+ :orange => [ 255, 165, 0 ],
129
+ :orangered => [ 255, 69, 0 ],
130
+ :orchid => [ 218, 112, 214 ],
131
+ :palegoldenrod => [ 238, 232, 170 ],
132
+ :palegreen => [ 152, 251, 152 ],
133
+ :paleturquoise => [ 175, 238, 238 ],
134
+ :palevioletred => [ 219, 112, 147 ],
135
+ :papayawhip => [ 255, 239, 213 ],
136
+ :peachpuff => [ 255, 218, 185 ],
137
+ :peru => [ 205, 133, 63 ],
138
+ :pink => [ 255, 192, 203 ],
139
+ :plum => [ 221, 160, 221 ],
140
+ :powderblue => [ 176, 224, 230 ],
141
+ :purple => [ 128, 0, 128 ],
142
+ :red => [ 255, 0, 0 ],
143
+ :rosybrown => [ 188, 143, 143 ],
144
+ :royalblue => [ 65, 105, 225 ],
145
+ :saddlebrown => [ 139, 69, 19 ],
146
+ :salmon => [ 250, 128, 114 ],
147
+ :sandybrown => [ 244, 164, 96 ],
148
+ :seagreen => [ 46, 139, 87 ],
149
+ :seashell => [ 255, 245, 238 ],
150
+ :sienna => [ 160, 82, 45 ],
151
+ :silver => [ 192, 192, 192 ],
152
+ :skyblue => [ 135, 206, 235 ],
153
+ :slateblue => [ 106, 90, 205 ],
154
+ :slategray => [ 112, 128, 144 ],
155
+ :slategrey => [ 112, 128, 144 ],
156
+ :snow => [ 255, 250, 250 ],
157
+ :springgreen => [ 0, 255, 127 ],
158
+ :steelblue => [ 70, 130, 180 ],
159
+ :tan => [ 210, 180, 140 ],
160
+ :teal => [ 0, 128, 128 ],
161
+ :thistle => [ 216, 191, 216 ],
162
+ :tomato => [ 255, 99, 71 ],
163
+ :turquoise => [ 64, 224, 208 ],
164
+ :violet => [ 238, 130, 238 ],
165
+ :wheat => [ 245, 222, 179 ],
166
+ :white => [ 255, 255, 255 ],
167
+ :whitesmoke => [ 245, 245, 245 ],
168
+ :yellow => [ 255, 255, 0 ],
169
+ :yellowgreen => [ 154, 205, 50 ]
170
+ }
171
+
172
+ # Create a new Color object.
173
+ def initialize(*args)
174
+ if args.length == 1
175
+ unless NamedColors.include?(args[0])
176
+ raise "Unknown color name #{args[0]}"
177
+ end
178
+
179
+ @r, @g, @b = NamedColors[args[0]]
180
+ elsif args.length == 3
181
+ args.each do |v|
182
+ unless v >= 0 && v < 256
183
+ raise ArgumentError, "RGB values (#{args.join(', ')}) must " +
184
+ "be between 0 and 255."
185
+ end
186
+ end
187
+
188
+ @r, @g, @b = args
189
+ elsif args.length == 4
190
+ unless args[0] >= 0 && args[0] < 360
191
+ raise ArgumentError, "Hue value must be between 0 and 360"
192
+ end
193
+ unless args[1] >= 0 && args[1] <= 255
194
+ raise ArgumentError, "Saturation value (#{args[1]}) must be " +
195
+ "between 0 and 255"
196
+ end
197
+ unless args[2] >= 0 && args[2] <= 255
198
+ raise ArgumentError, "Color value (#{args[2]}) must be " +
199
+ "between 0 and 255"
200
+ end
201
+ @r, @g, @b = hsvToRgb(*args[0..2])
202
+ else
203
+ raise ArgumentError
204
+ end
205
+ end
206
+
207
+ def to_rgb
208
+ [ @r, @g, @b ]
209
+ end
210
+
211
+ def to_hsv
212
+ rgbToHsv(@r, @g, @b)
213
+ end
214
+
215
+ # Convert the RGB value into a String format that is used in HTML.
216
+ def to_s
217
+ format("#%02x%02x%02x", @r, @g, @b)
218
+ end
219
+
220
+ private
221
+
222
+ def hsvToRgb(h, s, v)
223
+ hi = (h / 60.0).floor % 6
224
+ f = (h / 60.0) - (h / 60.0).floor
225
+ p = (v * (1.0 - s / 255.0)).to_i
226
+ q = (v * (1.0 - (f * s / 255.0))).to_i
227
+ t = (v * (1.0 - ((1.0 - f) * s / 255.0))).to_i
228
+ [ [ v, t, p ],
229
+ [ q, v, p ],
230
+ [ p, v, t ],
231
+ [ p, q, v ],
232
+ [ t, p, v ],
233
+ [ v, p, q ] ][hi]
234
+ end
235
+
236
+ def rgbToHsv(*rgb)
237
+ max = rgb.max
238
+ min = rgb.min
239
+ chroma = (max - min).to_f
240
+ v = max
241
+
242
+ if (max != 0.0)
243
+ s = chroma / max * 255.0
244
+ else
245
+ s = 0.0
246
+ end
247
+
248
+ r, g, b = rgb
249
+ if (s == 0.0)
250
+ h = 0.0
251
+ else
252
+ if (r == max)
253
+ h = (g - b) / chroma
254
+ elsif (g == max)
255
+ h = 2.0 + (b - r) / chroma
256
+ elsif (b == max)
257
+ h = 4.0 + (r - g) / chroma
258
+ end
259
+
260
+ h *= 60.0
261
+
262
+ h += 360.0 if h < 0.0
263
+ end
264
+
265
+ [ h.to_i, s.to_i, v.to_i ]
266
+ end
267
+
268
+ end
269
+
270
+ end
271
+
272
+ end
273
+