whirled_peas 0.5.0 → 0.9.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 (291) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +31 -0
  5. data/README.md +748 -137
  6. data/Rakefile +4 -32
  7. data/bin/easing +33 -0
  8. data/bin/reset_cursor +11 -0
  9. data/bin/screen_test +68 -0
  10. data/examples/graph.rb +54 -0
  11. data/examples/intro.rb +52 -0
  12. data/examples/scrolling.rb +54 -0
  13. data/lib/whirled_peas.rb +4 -12
  14. data/lib/whirled_peas/animator.rb +5 -0
  15. data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
  16. data/lib/whirled_peas/animator/easing.rb +72 -0
  17. data/lib/whirled_peas/animator/frame.rb +5 -0
  18. data/lib/whirled_peas/animator/frameset.rb +33 -0
  19. data/lib/whirled_peas/animator/producer.rb +35 -0
  20. data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
  21. data/lib/whirled_peas/command.rb +5 -0
  22. data/lib/whirled_peas/command/base.rb +86 -0
  23. data/lib/whirled_peas/command/config_command.rb +44 -0
  24. data/lib/whirled_peas/command/debug.rb +21 -0
  25. data/lib/whirled_peas/command/fonts.rb +22 -0
  26. data/lib/whirled_peas/command/frame_command.rb +34 -0
  27. data/lib/whirled_peas/command/frames.rb +24 -0
  28. data/lib/whirled_peas/command/help.rb +38 -0
  29. data/lib/whirled_peas/command/play.rb +108 -0
  30. data/lib/whirled_peas/command/record.rb +57 -0
  31. data/lib/whirled_peas/command/still.rb +29 -0
  32. data/lib/whirled_peas/command_line.rb +22 -220
  33. data/lib/whirled_peas/config.rb +56 -6
  34. data/lib/whirled_peas/device.rb +5 -0
  35. data/lib/whirled_peas/device/null_device.rb +8 -0
  36. data/lib/whirled_peas/device/output_file.rb +19 -0
  37. data/lib/whirled_peas/device/screen.rb +26 -0
  38. data/lib/whirled_peas/graphics.rb +14 -0
  39. data/lib/whirled_peas/graphics/box_painter.rb +48 -47
  40. data/lib/whirled_peas/graphics/canvas.rb +22 -11
  41. data/lib/whirled_peas/graphics/composer.rb +98 -0
  42. data/lib/whirled_peas/graphics/container_coords.rb +24 -13
  43. data/lib/whirled_peas/graphics/container_dimensions.rb +37 -9
  44. data/lib/whirled_peas/graphics/container_painter.rb +283 -36
  45. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  46. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  47. data/lib/whirled_peas/graphics/debugger.rb +10 -1
  48. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  49. data/lib/whirled_peas/graphics/graph_painter.rb +95 -0
  50. data/lib/whirled_peas/graphics/grid_painter.rb +25 -15
  51. data/lib/whirled_peas/graphics/mock_screen.rb +1 -1
  52. data/lib/whirled_peas/graphics/painter.rb +15 -6
  53. data/lib/whirled_peas/graphics/renderer.rb +13 -30
  54. data/lib/whirled_peas/graphics/text_painter.rb +11 -13
  55. data/lib/whirled_peas/settings/alignment.rb +24 -0
  56. data/lib/whirled_peas/settings/bg_color.rb +2 -0
  57. data/lib/whirled_peas/settings/border.rb +16 -16
  58. data/lib/whirled_peas/settings/color.rb +13 -14
  59. data/lib/whirled_peas/settings/container_settings.rb +133 -40
  60. data/lib/whirled_peas/settings/debugger.rb +9 -0
  61. data/lib/whirled_peas/settings/display_flow.rb +13 -11
  62. data/lib/whirled_peas/settings/element_settings.rb +8 -3
  63. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  64. data/lib/whirled_peas/settings/grid_settings.rb +15 -0
  65. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  66. data/lib/whirled_peas/settings/sizing.rb +19 -0
  67. data/lib/whirled_peas/settings/spacing.rb +34 -0
  68. data/lib/whirled_peas/settings/text_color.rb +2 -0
  69. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  70. data/lib/whirled_peas/utils/ansi.rb +13 -0
  71. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  72. data/lib/whirled_peas/utils/title_font.rb +1 -1
  73. data/lib/whirled_peas/version.rb +1 -1
  74. data/screen_test/{rendered/elements → elements}/box.frame +1 -1
  75. data/screen_test/{rendered/elements → elements}/box.rb +0 -0
  76. data/screen_test/elements/graph.frame +1 -0
  77. data/screen_test/elements/graph.rb +12 -0
  78. data/screen_test/elements/grid.frame +1 -0
  79. data/screen_test/{rendered/elements → elements}/grid.rb +0 -0
  80. data/screen_test/elements/screen_overflow_x.frame +1 -0
  81. data/screen_test/{rendered/elements/screen_overflow.rb → elements/screen_overflow_x.rb} +0 -0
  82. data/screen_test/elements/screen_overflow_y.frame +1 -0
  83. data/screen_test/elements/screen_overflow_y.rb +9 -0
  84. data/screen_test/elements/text.frame +1 -0
  85. data/screen_test/{rendered/elements → elements}/text.rb +0 -0
  86. data/screen_test/elements/text_multiline.frame +1 -0
  87. data/screen_test/{rendered/elements → elements}/text_multiline.rb +0 -0
  88. data/screen_test/settings/align/box_around.frame +1 -0
  89. data/screen_test/settings/align/box_around.rb +16 -0
  90. data/screen_test/settings/align/box_between.frame +1 -0
  91. data/screen_test/settings/align/box_between.rb +16 -0
  92. data/screen_test/settings/align/box_center.frame +1 -0
  93. data/screen_test/{rendered/settings/align/box.rb → settings/align/box_center.rb} +5 -4
  94. data/screen_test/settings/align/box_default.frame +1 -0
  95. data/screen_test/{rendered/settings/align/grid.rb → settings/align/box_default.rb} +6 -6
  96. data/screen_test/settings/align/box_evenly.frame +1 -0
  97. data/screen_test/settings/align/box_evenly.rb +16 -0
  98. data/screen_test/settings/align/box_left.frame +1 -0
  99. data/screen_test/settings/align/box_left.rb +21 -0
  100. data/screen_test/settings/align/box_right.frame +1 -0
  101. data/screen_test/settings/align/box_right.rb +21 -0
  102. data/screen_test/settings/align/children_center.frame +1 -0
  103. data/screen_test/settings/align/children_center.rb +15 -0
  104. data/screen_test/settings/align/children_left.frame +1 -0
  105. data/screen_test/settings/align/children_left.rb +15 -0
  106. data/screen_test/settings/align/children_right.frame +1 -0
  107. data/screen_test/settings/align/children_right.rb +15 -0
  108. data/screen_test/settings/align/grid_center.frame +1 -0
  109. data/screen_test/settings/align/grid_center.rb +18 -0
  110. data/screen_test/settings/align/grid_default.frame +1 -0
  111. data/screen_test/settings/align/grid_default.rb +17 -0
  112. data/screen_test/settings/align/grid_left.frame +1 -0
  113. data/screen_test/settings/align/grid_left.rb +18 -0
  114. data/screen_test/settings/align/grid_right.frame +1 -0
  115. data/screen_test/settings/align/grid_right.rb +18 -0
  116. data/screen_test/settings/ansi/bold.frame +1 -0
  117. data/screen_test/{rendered/settings/width/overflow_box_t2b.rb → settings/ansi/bold.rb} +4 -5
  118. data/screen_test/{rendered/settings → settings}/ansi/color.frame +1 -1
  119. data/screen_test/{rendered/settings → settings}/ansi/color.rb +0 -0
  120. data/screen_test/settings/ansi/underline.frame +1 -0
  121. data/screen_test/{rendered/settings → settings}/ansi/underline.rb +4 -5
  122. data/screen_test/{rendered/settings → settings}/border.frame +1 -1
  123. data/screen_test/{rendered/settings → settings}/border.rb +1 -1
  124. data/screen_test/settings/flow/box_b2t.frame +1 -0
  125. data/screen_test/settings/flow/box_b2t.rb +26 -0
  126. data/screen_test/settings/flow/box_l2r.frame +1 -0
  127. data/screen_test/settings/flow/box_l2r.rb +26 -0
  128. data/screen_test/settings/flow/box_r2l.frame +1 -0
  129. data/screen_test/settings/flow/box_r2l.rb +26 -0
  130. data/screen_test/settings/flow/box_t2b.frame +1 -0
  131. data/screen_test/settings/flow/box_t2b.rb +26 -0
  132. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  133. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  134. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  135. data/screen_test/{rendered/settings/margin.rb → settings/flow/grid_l2r.rb} +4 -4
  136. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  137. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  138. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  139. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  140. data/screen_test/settings/height/box.frame +1 -0
  141. data/screen_test/{rendered/settings → settings}/height/box.rb +0 -0
  142. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  143. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  144. data/screen_test/settings/height/grid.frame +1 -0
  145. data/screen_test/{rendered/settings → settings}/height/grid.rb +0 -0
  146. data/screen_test/settings/height/overflow_box.frame +1 -0
  147. data/screen_test/settings/height/overflow_box.rb +13 -0
  148. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  149. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  150. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  151. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  152. data/screen_test/settings/height/overflow_grid.frame +1 -0
  153. data/screen_test/{rendered/settings → settings}/height/overflow_grid.rb +0 -0
  154. data/screen_test/settings/margin.frame +1 -0
  155. data/screen_test/settings/margin.rb +16 -0
  156. data/screen_test/settings/padding.frame +1 -0
  157. data/screen_test/settings/padding.rb +13 -0
  158. data/screen_test/settings/position/box_left.frame +1 -0
  159. data/screen_test/{rendered/settings → settings}/position/box_left.rb +2 -2
  160. data/screen_test/settings/position/box_left_negative.frame +1 -0
  161. data/screen_test/{rendered/settings → settings}/position/box_left_negative.rb +2 -2
  162. data/screen_test/settings/position/box_top.frame +1 -0
  163. data/screen_test/{rendered/settings → settings}/position/box_top.rb +1 -1
  164. data/screen_test/settings/position/box_top_negative.frame +1 -0
  165. data/screen_test/{rendered/settings → settings}/position/box_top_negative.rb +2 -2
  166. data/screen_test/settings/position/grid_left.frame +1 -0
  167. data/screen_test/{rendered/settings → settings}/position/grid_left.rb +1 -1
  168. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  169. data/screen_test/{rendered/settings → settings}/position/grid_left_negative.rb +1 -1
  170. data/screen_test/settings/position/grid_top.frame +1 -0
  171. data/screen_test/{rendered/settings → settings}/position/grid_top.rb +1 -1
  172. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  173. data/screen_test/{rendered/settings → settings}/position/grid_top_negative.rb +1 -1
  174. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  175. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  176. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  177. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  178. data/screen_test/settings/scroll/vert_box.frame +1 -0
  179. data/screen_test/settings/scroll/vert_box.rb +20 -0
  180. data/screen_test/settings/title_font.frame +1 -0
  181. data/screen_test/{rendered/settings → settings}/title_font.rb +1 -1
  182. data/screen_test/settings/valign/box_around.frame +1 -0
  183. data/screen_test/settings/valign/box_around.rb +17 -0
  184. data/screen_test/settings/valign/box_between.frame +1 -0
  185. data/screen_test/settings/valign/box_between.rb +17 -0
  186. data/screen_test/settings/valign/box_bottom.frame +1 -0
  187. data/screen_test/settings/valign/box_bottom.rb +17 -0
  188. data/screen_test/settings/valign/box_default.frame +1 -0
  189. data/screen_test/settings/valign/box_default.rb +16 -0
  190. data/screen_test/settings/valign/box_evenly.frame +1 -0
  191. data/screen_test/settings/valign/box_evenly.rb +17 -0
  192. data/screen_test/settings/valign/box_middle.frame +1 -0
  193. data/screen_test/settings/valign/box_middle.rb +17 -0
  194. data/screen_test/settings/valign/box_top.frame +1 -0
  195. data/screen_test/settings/valign/box_top.rb +17 -0
  196. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  197. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  198. data/screen_test/settings/valign/grid_default.frame +1 -0
  199. data/screen_test/settings/valign/grid_default.rb +14 -0
  200. data/screen_test/settings/valign/grid_middle.frame +1 -0
  201. data/screen_test/settings/valign/grid_middle.rb +15 -0
  202. data/screen_test/settings/valign/grid_top.frame +1 -0
  203. data/screen_test/settings/valign/grid_top.rb +15 -0
  204. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  205. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  206. data/screen_test/settings/width/box_content.frame +1 -0
  207. data/screen_test/settings/width/box_content.rb +15 -0
  208. data/screen_test/settings/width/box_default.frame +1 -0
  209. data/screen_test/{rendered/settings/width/box.rb → settings/width/box_default.rb} +3 -2
  210. data/screen_test/settings/width/grid.frame +1 -0
  211. data/screen_test/{rendered/settings → settings}/width/grid.rb +2 -2
  212. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  213. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  214. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  215. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  216. data/screen_test/settings/width/overflow_box.frame +1 -0
  217. data/screen_test/settings/width/overflow_box.rb +13 -0
  218. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  219. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  220. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  221. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  222. data/screen_test/settings/width/overflow_grid.frame +1 -0
  223. data/screen_test/{rendered/settings → settings}/width/overflow_grid.rb +0 -0
  224. data/tools/whirled_peas/tools/screen_tester.rb +285 -0
  225. metadata +192 -98
  226. data/bin/debug +0 -35
  227. data/lib/whirled_peas/debugger.rb +0 -80
  228. data/lib/whirled_peas/frame.rb +0 -6
  229. data/lib/whirled_peas/frame/consumer.rb +0 -30
  230. data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
  231. data/lib/whirled_peas/frame/event_loop.rb +0 -90
  232. data/lib/whirled_peas/frame/producer.rb +0 -67
  233. data/lib/whirled_peas/graphics/screen.rb +0 -65
  234. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
  235. data/lib/whirled_peas/settings/text_align.rb +0 -19
  236. data/lib/whirled_peas/template.rb +0 -5
  237. data/lib/whirled_peas/template/box_element.rb +0 -8
  238. data/lib/whirled_peas/template/composer.rb +0 -68
  239. data/lib/whirled_peas/template/container.rb +0 -28
  240. data/lib/whirled_peas/template/debugger.rb +0 -34
  241. data/lib/whirled_peas/template/element.rb +0 -13
  242. data/lib/whirled_peas/template/grid_element.rb +0 -8
  243. data/lib/whirled_peas/template/text_element.rb +0 -24
  244. data/screen_test/rendered/elements/grid.frame +0 -1
  245. data/screen_test/rendered/elements/text.frame +0 -1
  246. data/screen_test/rendered/elements/text_multiline.frame +0 -1
  247. data/screen_test/rendered/settings/align/box.frame +0 -1
  248. data/screen_test/rendered/settings/align/children_center.frame +0 -1
  249. data/screen_test/rendered/settings/align/children_center.rb +0 -13
  250. data/screen_test/rendered/settings/align/children_left.frame +0 -1
  251. data/screen_test/rendered/settings/align/children_left.rb +0 -13
  252. data/screen_test/rendered/settings/align/children_right.frame +0 -1
  253. data/screen_test/rendered/settings/align/children_right.rb +0 -13
  254. data/screen_test/rendered/settings/align/grid.frame +0 -1
  255. data/screen_test/rendered/settings/ansi/bold.frame +0 -1
  256. data/screen_test/rendered/settings/ansi/bold.rb +0 -15
  257. data/screen_test/rendered/settings/ansi/underline.frame +0 -1
  258. data/screen_test/rendered/settings/flow/l2r.frame +0 -1
  259. data/screen_test/rendered/settings/flow/l2r.rb +0 -24
  260. data/screen_test/rendered/settings/flow/t2b.frame +0 -1
  261. data/screen_test/rendered/settings/flow/t2b.rb +0 -24
  262. data/screen_test/rendered/settings/height/box.frame +0 -1
  263. data/screen_test/rendered/settings/height/grid.frame +0 -1
  264. data/screen_test/rendered/settings/height/overflow_box.frame +0 -1
  265. data/screen_test/rendered/settings/height/overflow_box.rb +0 -13
  266. data/screen_test/rendered/settings/height/overflow_box_l2r.frame +0 -1
  267. data/screen_test/rendered/settings/height/overflow_box_l2r.rb +0 -15
  268. data/screen_test/rendered/settings/height/overflow_box_t2b.frame +0 -1
  269. data/screen_test/rendered/settings/height/overflow_box_t2b.rb +0 -14
  270. data/screen_test/rendered/settings/height/overflow_grid.frame +0 -1
  271. data/screen_test/rendered/settings/margin.frame +0 -1
  272. data/screen_test/rendered/settings/padding.frame +0 -1
  273. data/screen_test/rendered/settings/padding.rb +0 -11
  274. data/screen_test/rendered/settings/position/box_left.frame +0 -1
  275. data/screen_test/rendered/settings/position/box_left_negative.frame +0 -1
  276. data/screen_test/rendered/settings/position/box_top.frame +0 -1
  277. data/screen_test/rendered/settings/position/box_top_negative.frame +0 -1
  278. data/screen_test/rendered/settings/position/grid_left.frame +0 -1
  279. data/screen_test/rendered/settings/position/grid_left_negative.frame +0 -1
  280. data/screen_test/rendered/settings/position/grid_top.frame +0 -1
  281. data/screen_test/rendered/settings/position/grid_top_negative.frame +0 -1
  282. data/screen_test/rendered/settings/title_font.frame +0 -1
  283. data/screen_test/rendered/settings/width/box.frame +0 -1
  284. data/screen_test/rendered/settings/width/grid.frame +0 -1
  285. data/screen_test/rendered/settings/width/overflow_box.frame +0 -1
  286. data/screen_test/rendered/settings/width/overflow_box.rb +0 -11
  287. data/screen_test/rendered/settings/width/overflow_box_l2r.frame +0 -1
  288. data/screen_test/rendered/settings/width/overflow_box_l2r.rb +0 -14
  289. data/screen_test/rendered/settings/width/overflow_box_t2b.frame +0 -1
  290. data/screen_test/rendered/settings/width/overflow_grid.frame +0 -1
  291. data/screen_test/screen_tester.rb +0 -191
@@ -1,6 +0,0 @@
1
- module WhirledPeas
2
- module Frame
3
- end
4
-
5
- private_constant :Frame
6
- end
@@ -1,30 +0,0 @@
1
- module WhirledPeas
2
- module Frame
3
- # Abstract class for consuming frame events.
4
- class Consumer
5
- EOF = '__EOF__'
6
-
7
- def enqueue(name, duration, args)
8
- raise NotImplemented, "#{self.class} must implement #enqueue"
9
- end
10
-
11
- def running?
12
- @running == true
13
- end
14
-
15
- def start
16
- self.running = true
17
- end
18
-
19
- def stop
20
- enqueue(EOF, nil, {})
21
- end
22
-
23
- private
24
-
25
- attr_writer :running
26
- end
27
-
28
- private_constant :Consumer
29
- end
30
- end
@@ -1,30 +0,0 @@
1
- require 'whirled_peas/null_logger'
2
-
3
- require_relative 'consumer'
4
-
5
- module WhirledPeas
6
- module Frame
7
- class DebugConsumer < Consumer
8
- LOGGER_ID = 'PRINTER'
9
-
10
- def initialize(output=STDOUT, logger=NullLogger.new)
11
- @output = output
12
- @logger = logger
13
- end
14
-
15
- def enqueue(name, duration, args)
16
- if name == EOF
17
- output.puts "EOF frame detected"
18
- else
19
- displayed_for = duration ? "#{duration} second(s)" : '1 frame'
20
- args_str = args.empty? ? '' : " '#{JSON.generate(args)}'"
21
- output.puts "Frame '#{name}' displayed for #{displayed_for}#{args_str}"
22
- end
23
- end
24
-
25
- private
26
-
27
- attr_reader :output, :logger
28
- end
29
- end
30
- end
@@ -1,90 +0,0 @@
1
- require 'whirled_peas/null_logger'
2
- require 'whirled_peas/graphics/screen'
3
-
4
- require_relative 'consumer'
5
-
6
- module WhirledPeas
7
- module Frame
8
- class EventLoop < Consumer
9
- DEFAULT_REFRESH_RATE = 30
10
-
11
- LOGGER_ID = 'EVENT LOOP'
12
-
13
- def initialize(
14
- template_factory,
15
- loading_template_factory=nil,
16
- refresh_rate: DEFAULT_REFRESH_RATE,
17
- logger: NullLogger.new,
18
- screen: Graphics::Screen.new
19
- )
20
- @template_factory = template_factory
21
- @loading_template_factory = loading_template_factory
22
- @queue = Queue.new
23
- @frame_duration = 1.0 / refresh_rate
24
- @logger = logger
25
- @screen = screen
26
- end
27
-
28
- def enqueue(name, duration, args)
29
- # If duration is nil, set it to the duration of a single frame
30
- queue.push([name, duration || frame_duration, args])
31
- end
32
-
33
- def start
34
- super
35
- wait_for_content
36
- play_content
37
- rescue
38
- self.running = false
39
- logger.warn(LOGGER_ID) { 'Exiting with error' }
40
- raise
41
- ensure
42
- screen.finalize
43
- end
44
-
45
- private
46
-
47
- attr_reader :template_factory, :loading_template_factory, :queue, :frame_duration, :logger, :screen
48
-
49
- def wait_for_content
50
- if loading_template_factory
51
- play_loading_screen
52
- else
53
- sleep(frame_duration) while queue.empty?
54
- end
55
- end
56
-
57
- def play_loading_screen
58
- while queue.empty?
59
- screen.paint(loading_template_factory.build)
60
- sleep(frame_duration)
61
- end
62
- end
63
-
64
- def play_content
65
- template = nil
66
- frame_until = Time.new(0) # Tell the loop to immediately pick up a new frame
67
- while running?
68
- frame_start = Time.now
69
- next_frame_at = frame_start + frame_duration
70
- if frame_until > frame_start
71
- # While we're still displaying the previous frame, refresh the screen
72
- screen.refresh
73
- elsif !queue.empty?
74
- name, duration, args = queue.pop
75
- if name == EOF
76
- self.running = false
77
- else
78
- frame_until = frame_start + duration
79
- template = template_factory.build(name, args)
80
- screen.paint(template)
81
- end
82
- else
83
- wait_for_content
84
- end
85
- sleep([0, next_frame_at - Time.now].max)
86
- end
87
- end
88
- end
89
- end
90
- end
@@ -1,67 +0,0 @@
1
- require 'socket'
2
- require 'json'
3
-
4
- require 'whirled_peas/null_logger'
5
-
6
- module WhirledPeas
7
- module Frame
8
- # A Producer is the object given to the driver as the interface that allows
9
- # the driver to emit frame events. The recommended way of creating a Producer
10
- # is by invoking `Producer.produce` as it handles the lifecycle methods of
11
- # the consumer.
12
- class Producer
13
- LOGGER_ID = 'PRODUCER'
14
-
15
- # Manages the consumer lifecycle and yields a Producer to send frames to the
16
- # consumer
17
- #
18
- # @param consumer [Consumer] instance that consumes frame events through
19
- # `#enqueue`
20
- def self.produce(consumer, logger=NullLogger.new)
21
- producer = new(consumer, logger)
22
- consumer_thread = Thread.new do
23
- Thread.current.report_on_exception = false
24
- consumer.start
25
- end
26
- yield producer
27
- producer.flush
28
- rescue => e
29
- logger.warn(LOGGER_ID) { 'Exited with error' }
30
- logger.error(LOGGER_ID) { e }
31
- raise
32
- ensure
33
- consumer.stop
34
- consumer_thread.join if consumer_thread
35
- end
36
-
37
- def initialize(consumer, logger=NullLogger.new)
38
- @consumer = consumer
39
- @logger = logger
40
- @queue = Queue.new
41
- end
42
-
43
- # Buffer a frame to be played for the given duration. `#flush` must be called
44
- # for frames to get pushed to the EventLoop.
45
- #
46
- # @param name [String] name of frame, which is passed to #build of the
47
- # TemplateFactory
48
- # @param duration [Float|Integer] duration in seconds the frame should be,
49
- # displayed (default is nil, which results in a duration of a single refresh
50
- # cycle)
51
- # @param args [Hash] key/value pair of arguments, which is passed to #build of
52
- # the TemplateFactory
53
- def send_frame(name, duration: nil, args: {})
54
- queue.push([name, duration, args])
55
- end
56
-
57
- # Send any buffered frames to the EventLoop
58
- def flush
59
- consumer.enqueue(*queue.pop) while !queue.empty?
60
- end
61
-
62
- private
63
-
64
- attr_reader :consumer, :logger, :queue
65
- end
66
- end
67
- end
@@ -1,65 +0,0 @@
1
- require 'highline'
2
-
3
- require 'whirled_peas/utils/ansi'
4
-
5
- require_relative 'renderer'
6
-
7
- module WhirledPeas
8
- module Graphics
9
- class Screen
10
- def self.current_dimensions
11
- width, height = HighLine.new.terminal.terminal_size
12
- [width || 0, height || 0]
13
- end
14
-
15
- def initialize(output=STDOUT)
16
- @output = output
17
- @terminal = HighLine.new.terminal
18
- @strokes = []
19
- refresh_size!
20
- Signal.trap('SIGWINCH', proc { self.refresh_size! })
21
- end
22
-
23
- def paint(template)
24
- @template = template
25
- draw
26
- end
27
-
28
- def refresh
29
- # No need to refresh if the screen dimensions have not changed
30
- return if @refreshed_width == width || @refreshed_height == height
31
- draw
32
- end
33
-
34
- def finalize
35
- output.print Utils::Ansi.clear
36
- output.print Utils::Ansi.cursor_pos(top: height - 1)
37
- output.print Utils::Ansi.cursor_visible(true)
38
- output.flush
39
- end
40
-
41
- protected
42
-
43
- def refresh_size!
44
- @width, @height = self.class.current_dimensions
45
- end
46
-
47
- private
48
-
49
- attr_reader :output, :cursor, :terminal, :width, :height
50
-
51
- def draw
52
- strokes = [Utils::Ansi.cursor_visible(false), Utils::Ansi.cursor_pos, Utils::Ansi.clear_down]
53
- Renderer.new(@template, width, height).paint do |left, top, fstring|
54
- next unless fstring.length > 0
55
- strokes << Utils::Ansi.cursor_pos(left: left, top: top)
56
- strokes << fstring
57
- end
58
- strokes.each { |stroke| output.print(stroke) }
59
- output.flush
60
- @refreshed_width = width
61
- @refreshed_height = height
62
- end
63
- end
64
- end
65
- end
@@ -1,15 +0,0 @@
1
- module WhirledPeas
2
- module Graphics
3
- class TextDimensions
4
- attr_reader :outer_width, :outer_height
5
-
6
- def initialize(content)
7
- @outer_width = 0
8
- content.each do |line|
9
- @outer_width = line.length if line.length > @outer_width
10
- end
11
- @outer_height = content.length
12
- end
13
- end
14
- end
15
- end
@@ -1,19 +0,0 @@
1
- module WhirledPeas
2
- module Settings
3
- module TextAlign
4
- LEFT = :left
5
- CENTER = :center
6
- RIGHT = :right
7
-
8
- def self.validate!(align)
9
- return unless align
10
- if [TextAlign::LEFT, TextAlign::CENTER, TextAlign::RIGHT].include?(align)
11
- align
12
- else
13
- raise ArgumentError, "Unsupported text alignment: #{align}"
14
- end
15
- end
16
- end
17
- private_constant :TextAlign
18
- end
19
- end
@@ -1,5 +0,0 @@
1
- module WhirledPeas
2
- module Template
3
- end
4
- private_constant :Template
5
- end
@@ -1,8 +0,0 @@
1
- require_relative 'container'
2
-
3
- module WhirledPeas
4
- module Template
5
- class BoxElement < Container
6
- end
7
- end
8
- end
@@ -1,68 +0,0 @@
1
- require 'whirled_peas/settings/box_settings'
2
- require 'whirled_peas/settings/grid_settings'
3
- require 'whirled_peas/settings/text_settings'
4
-
5
- require_relative 'box_element'
6
- require_relative 'grid_element'
7
- require_relative 'text_element'
8
-
9
- module WhirledPeas
10
- module Template
11
- class Composer
12
- def self.next_name
13
- @counter ||= 0
14
- @counter += 1
15
- "Element-#{@counter}"
16
- end
17
-
18
- def self.build
19
- settings = Settings::BoxSettings.new
20
- template = BoxElement.new('TEMPLATE', settings)
21
- composer = Template::Composer.new(template)
22
- value = yield composer, settings
23
- if !template.children? && TextElement.stringable?(value)
24
- composer.add_text { value.to_s }
25
- end
26
- template
27
- end
28
-
29
- attr_reader :element
30
-
31
- def initialize(element)
32
- @element = element
33
- end
34
-
35
- def add_text(name=self.class.next_name, &block)
36
- child_settings = Settings::TextSettings.inherit(element.settings)
37
- child = TextElement.new(name, child_settings)
38
- # TextElements are not composable, so yield nil
39
- child.content = yield nil, child_settings
40
- element.add_child(child)
41
- end
42
-
43
- def add_box(name=self.class.next_name, &block)
44
- child_settings = Settings::BoxSettings.inherit(element.settings)
45
- child = BoxElement.new(name, child_settings)
46
- composer = self.class.new(child)
47
- value = yield composer, child.settings
48
- element.add_child(child)
49
- if !child.children? && TextElement.stringable?(value)
50
- composer.add_text("#{name}-Text") { value.to_s }
51
- end
52
- end
53
-
54
- def add_grid(name=self.class.next_name, &block)
55
- child_settings = Settings::GridSettings.inherit(element.settings)
56
- child = GridElement.new(name, child_settings)
57
- composer = self.class.new(child)
58
- values = yield composer, child.settings
59
- element.add_child(child)
60
- if !child.children? && values.is_a?(Array)
61
- values.each.with_index do |value, index|
62
- composer.add_text("#{name}-Text-#{index}") { value.to_s }
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
@@ -1,28 +0,0 @@
1
- require_relative 'element'
2
-
3
- module WhirledPeas
4
- module Template
5
- class Container < Element
6
- def initialize(name, settings)
7
- super
8
- @children = []
9
- end
10
-
11
- def add_child(child)
12
- @children << child
13
- end
14
-
15
- def children?
16
- @children.length > 0
17
- end
18
-
19
- def num_children
20
- @children.length
21
- end
22
-
23
- def each_child(&block)
24
- @children.each(&block)
25
- end
26
- end
27
- end
28
- end