taskjuggler 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+