whirled_peas 0.7.1 → 0.11.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 (262) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +25 -0
  4. data/README.md +530 -121
  5. data/Rakefile +1 -20
  6. data/bin/easing +33 -0
  7. data/bin/reset_cursor +11 -0
  8. data/bin/screen_test +68 -0
  9. data/examples/components.rb +35 -0
  10. data/examples/graph.rb +54 -0
  11. data/examples/intro.rb +3 -3
  12. data/examples/scrolling.rb +13 -23
  13. data/lib/data/themes.yaml +13 -0
  14. data/lib/whirled_peas.rb +33 -13
  15. data/lib/whirled_peas/animator.rb +5 -0
  16. data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
  17. data/lib/whirled_peas/animator/easing.rb +72 -0
  18. data/lib/whirled_peas/animator/frame.rb +5 -0
  19. data/lib/whirled_peas/animator/frameset.rb +33 -0
  20. data/lib/whirled_peas/animator/producer.rb +35 -0
  21. data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
  22. data/lib/whirled_peas/command.rb +5 -0
  23. data/lib/whirled_peas/command/base.rb +86 -0
  24. data/lib/whirled_peas/command/config_command.rb +44 -0
  25. data/lib/whirled_peas/command/debug.rb +21 -0
  26. data/lib/whirled_peas/command/fonts.rb +22 -0
  27. data/lib/whirled_peas/command/frame_command.rb +34 -0
  28. data/lib/whirled_peas/command/frames.rb +24 -0
  29. data/lib/whirled_peas/command/help.rb +38 -0
  30. data/lib/whirled_peas/command/play.rb +112 -0
  31. data/lib/whirled_peas/command/record.rb +57 -0
  32. data/lib/whirled_peas/command/still.rb +29 -0
  33. data/lib/whirled_peas/command/themes.rb +77 -0
  34. data/lib/whirled_peas/command_line.rb +24 -212
  35. data/lib/whirled_peas/component.rb +35 -0
  36. data/lib/whirled_peas/component/list_with_active.rb +88 -0
  37. data/lib/whirled_peas/config.rb +56 -6
  38. data/lib/whirled_peas/device.rb +5 -0
  39. data/lib/whirled_peas/device/null_device.rb +8 -0
  40. data/lib/whirled_peas/device/output_file.rb +19 -0
  41. data/lib/whirled_peas/device/screen.rb +26 -0
  42. data/lib/whirled_peas/graphics/box_painter.rb +4 -4
  43. data/lib/whirled_peas/graphics/composer.rb +27 -2
  44. data/lib/whirled_peas/graphics/container_coords.rb +24 -2
  45. data/lib/whirled_peas/graphics/container_painter.rb +63 -82
  46. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  47. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  48. data/lib/whirled_peas/graphics/debugger.rb +1 -7
  49. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  50. data/lib/whirled_peas/graphics/graph_painter.rb +97 -0
  51. data/lib/whirled_peas/graphics/grid_painter.rb +0 -3
  52. data/lib/whirled_peas/graphics/painter.rb +10 -0
  53. data/lib/whirled_peas/graphics/renderer.rb +8 -2
  54. data/lib/whirled_peas/graphics/scrollbar_helper.rb +124 -0
  55. data/lib/whirled_peas/graphics/text_painter.rb +7 -11
  56. data/lib/whirled_peas/null_logger.rb +0 -1
  57. data/lib/whirled_peas/settings/border.rb +25 -4
  58. data/lib/whirled_peas/settings/container_settings.rb +14 -9
  59. data/lib/whirled_peas/settings/debugger.rb +1 -1
  60. data/lib/whirled_peas/settings/element_settings.rb +12 -3
  61. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  62. data/lib/whirled_peas/settings/grid_settings.rb +7 -0
  63. data/lib/whirled_peas/settings/position.rb +17 -5
  64. data/lib/whirled_peas/settings/text_settings.rb +1 -0
  65. data/lib/whirled_peas/settings/theme.rb +40 -0
  66. data/lib/whirled_peas/settings/theme_library.rb +63 -0
  67. data/lib/whirled_peas/utils/ansi.rb +13 -0
  68. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  69. data/lib/whirled_peas/version.rb +1 -1
  70. data/screen_test/components/list_with_active/l2r_active_color.frame +1 -0
  71. data/screen_test/components/list_with_active/l2r_active_color.rb +18 -0
  72. data/screen_test/components/list_with_active/l2r_position_end.frame +1 -0
  73. data/screen_test/components/list_with_active/l2r_position_end.rb +16 -0
  74. data/screen_test/components/list_with_active/l2r_position_middle.frame +1 -0
  75. data/screen_test/components/list_with_active/l2r_position_middle.rb +16 -0
  76. data/screen_test/components/list_with_active/l2r_position_start.frame +1 -0
  77. data/screen_test/components/list_with_active/l2r_position_start.rb +16 -0
  78. data/screen_test/components/list_with_active/l2r_separator.frame +1 -0
  79. data/screen_test/components/list_with_active/l2r_separator.rb +17 -0
  80. data/screen_test/components/list_with_active/t2b_active_color.frame +1 -0
  81. data/screen_test/components/list_with_active/t2b_active_color.rb +19 -0
  82. data/screen_test/components/list_with_active/t2b_position_end.frame +1 -0
  83. data/screen_test/components/list_with_active/t2b_position_end.rb +17 -0
  84. data/screen_test/components/list_with_active/t2b_position_middle.frame +1 -0
  85. data/screen_test/components/list_with_active/t2b_position_middle.rb +17 -0
  86. data/screen_test/components/list_with_active/t2b_position_start.frame +1 -0
  87. data/screen_test/components/list_with_active/t2b_position_start.rb +17 -0
  88. data/screen_test/components/list_with_active/t2b_separator.frame +1 -0
  89. data/screen_test/components/list_with_active/t2b_separator.rb +18 -0
  90. data/screen_test/elements/box.frame +1 -1
  91. data/screen_test/elements/box.rb +1 -1
  92. data/screen_test/elements/graph.frame +1 -0
  93. data/screen_test/elements/graph.rb +12 -0
  94. data/screen_test/elements/grid.frame +1 -1
  95. data/screen_test/elements/grid.rb +1 -1
  96. data/screen_test/elements/screen_overflow_x.frame +1 -1
  97. data/screen_test/elements/screen_overflow_x.rb +1 -1
  98. data/screen_test/elements/screen_overflow_y.frame +1 -1
  99. data/screen_test/elements/screen_overflow_y.rb +1 -1
  100. data/screen_test/elements/text.frame +1 -1
  101. data/screen_test/elements/text.rb +1 -1
  102. data/screen_test/elements/text_multiline.frame +1 -1
  103. data/screen_test/elements/text_multiline.rb +1 -1
  104. data/screen_test/elements/theme.frame +1 -0
  105. data/screen_test/elements/theme.rb +26 -0
  106. data/screen_test/settings/align/box_around.frame +1 -1
  107. data/screen_test/settings/align/box_around.rb +1 -1
  108. data/screen_test/settings/align/box_between.frame +1 -1
  109. data/screen_test/settings/align/box_between.rb +1 -1
  110. data/screen_test/settings/align/box_center.frame +1 -1
  111. data/screen_test/settings/align/box_center.rb +1 -1
  112. data/screen_test/settings/align/box_default.frame +1 -1
  113. data/screen_test/settings/align/box_default.rb +1 -1
  114. data/screen_test/settings/align/box_evenly.frame +1 -1
  115. data/screen_test/settings/align/box_evenly.rb +1 -1
  116. data/screen_test/settings/align/box_left.frame +1 -1
  117. data/screen_test/settings/align/box_left.rb +1 -1
  118. data/screen_test/settings/align/box_right.frame +1 -1
  119. data/screen_test/settings/align/box_right.rb +1 -1
  120. data/screen_test/settings/align/children_center.frame +1 -1
  121. data/screen_test/settings/align/children_center.rb +1 -1
  122. data/screen_test/settings/align/children_left.frame +1 -1
  123. data/screen_test/settings/align/children_left.rb +1 -1
  124. data/screen_test/settings/align/children_right.frame +1 -1
  125. data/screen_test/settings/align/children_right.rb +1 -1
  126. data/screen_test/settings/align/grid_center.frame +1 -1
  127. data/screen_test/settings/align/grid_center.rb +1 -1
  128. data/screen_test/settings/align/grid_default.frame +1 -1
  129. data/screen_test/settings/align/grid_default.rb +1 -1
  130. data/screen_test/settings/align/grid_left.frame +1 -1
  131. data/screen_test/settings/align/grid_left.rb +1 -1
  132. data/screen_test/settings/align/grid_right.frame +1 -1
  133. data/screen_test/settings/align/grid_right.rb +1 -1
  134. data/screen_test/settings/ansi/bold.frame +1 -1
  135. data/screen_test/settings/ansi/bold.rb +1 -1
  136. data/screen_test/settings/ansi/color.frame +1 -1
  137. data/screen_test/settings/ansi/color.rb +1 -1
  138. data/screen_test/settings/ansi/underline.frame +1 -1
  139. data/screen_test/settings/ansi/underline.rb +1 -1
  140. data/screen_test/settings/border.frame +1 -1
  141. data/screen_test/settings/border.rb +1 -1
  142. data/screen_test/settings/content_start/box_bottom.frame +1 -0
  143. data/screen_test/settings/content_start/box_bottom.rb +17 -0
  144. data/screen_test/settings/content_start/box_left.frame +1 -0
  145. data/screen_test/settings/{position → content_start}/box_left.rb +2 -2
  146. data/screen_test/settings/content_start/box_left_negative.frame +1 -0
  147. data/screen_test/settings/{position → content_start}/box_left_negative.rb +2 -2
  148. data/screen_test/settings/content_start/box_right.frame +1 -0
  149. data/screen_test/settings/content_start/box_right.rb +17 -0
  150. data/screen_test/settings/content_start/box_top.frame +1 -0
  151. data/screen_test/settings/{position → content_start}/box_top.rb +2 -2
  152. data/screen_test/settings/content_start/box_top_negative.frame +1 -0
  153. data/screen_test/settings/{position → content_start}/box_top_negative.rb +2 -2
  154. data/screen_test/settings/content_start/grid_left.frame +1 -0
  155. data/screen_test/settings/{position → content_start}/grid_left.rb +2 -2
  156. data/screen_test/settings/content_start/grid_left_negative.frame +1 -0
  157. data/screen_test/settings/{position → content_start}/grid_left_negative.rb +2 -2
  158. data/screen_test/settings/content_start/grid_top.frame +1 -0
  159. data/screen_test/settings/{position → content_start}/grid_top.rb +2 -2
  160. data/screen_test/settings/content_start/grid_top_negative.frame +1 -0
  161. data/screen_test/settings/{position → content_start}/grid_top_negative.rb +2 -2
  162. data/screen_test/settings/flow/box_b2t.frame +1 -1
  163. data/screen_test/settings/flow/box_b2t.rb +1 -1
  164. data/screen_test/settings/flow/box_l2r.frame +1 -1
  165. data/screen_test/settings/flow/box_l2r.rb +1 -1
  166. data/screen_test/settings/flow/box_r2l.frame +1 -1
  167. data/screen_test/settings/flow/box_r2l.rb +1 -1
  168. data/screen_test/settings/flow/box_t2b.frame +1 -1
  169. data/screen_test/settings/flow/box_t2b.rb +1 -1
  170. data/screen_test/settings/flow/grid_b2t.frame +1 -1
  171. data/screen_test/settings/flow/grid_b2t.rb +1 -1
  172. data/screen_test/settings/flow/grid_l2r.frame +1 -1
  173. data/screen_test/settings/flow/grid_l2r.rb +1 -1
  174. data/screen_test/settings/flow/grid_r2l.frame +1 -1
  175. data/screen_test/settings/flow/grid_r2l.rb +1 -1
  176. data/screen_test/settings/flow/grid_t2b.frame +1 -1
  177. data/screen_test/settings/flow/grid_t2b.rb +1 -1
  178. data/screen_test/settings/height/box.frame +1 -1
  179. data/screen_test/settings/height/box.rb +1 -1
  180. data/screen_test/settings/height/box_border_sizing.frame +1 -1
  181. data/screen_test/settings/height/box_border_sizing.rb +1 -1
  182. data/screen_test/settings/height/grid.frame +1 -1
  183. data/screen_test/settings/height/grid.rb +1 -1
  184. data/screen_test/settings/height/overflow_box.frame +1 -1
  185. data/screen_test/settings/height/overflow_box.rb +1 -1
  186. data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
  187. data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
  188. data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
  189. data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
  190. data/screen_test/settings/height/overflow_grid.frame +1 -1
  191. data/screen_test/settings/height/overflow_grid.rb +1 -1
  192. data/screen_test/settings/margin.frame +1 -1
  193. data/screen_test/settings/margin.rb +1 -1
  194. data/screen_test/settings/padding.frame +1 -1
  195. data/screen_test/settings/padding.rb +1 -1
  196. data/screen_test/settings/scroll/horiz_box.frame +1 -1
  197. data/screen_test/settings/scroll/horiz_box.rb +3 -5
  198. data/screen_test/settings/scroll/horiz_box_align_center.rb +3 -5
  199. data/screen_test/settings/scroll/horiz_box_align_right.rb +3 -5
  200. data/screen_test/settings/scroll/vert_box.frame +1 -1
  201. data/screen_test/settings/scroll/vert_box.rb +6 -8
  202. data/screen_test/settings/title_font.frame +1 -1
  203. data/screen_test/settings/title_font.rb +1 -1
  204. data/screen_test/settings/valign/box_around.frame +1 -1
  205. data/screen_test/settings/valign/box_around.rb +1 -1
  206. data/screen_test/settings/valign/box_between.frame +1 -1
  207. data/screen_test/settings/valign/box_between.rb +1 -1
  208. data/screen_test/settings/valign/box_bottom.frame +1 -1
  209. data/screen_test/settings/valign/box_bottom.rb +1 -1
  210. data/screen_test/settings/valign/box_default.frame +1 -1
  211. data/screen_test/settings/valign/box_default.rb +1 -1
  212. data/screen_test/settings/valign/box_evenly.frame +1 -1
  213. data/screen_test/settings/valign/box_evenly.rb +1 -1
  214. data/screen_test/settings/valign/box_middle.frame +1 -1
  215. data/screen_test/settings/valign/box_middle.rb +1 -1
  216. data/screen_test/settings/valign/box_top.frame +1 -1
  217. data/screen_test/settings/valign/box_top.rb +1 -1
  218. data/screen_test/settings/valign/grid_bottom.frame +1 -1
  219. data/screen_test/settings/valign/grid_bottom.rb +1 -1
  220. data/screen_test/settings/valign/grid_default.frame +1 -1
  221. data/screen_test/settings/valign/grid_default.rb +1 -1
  222. data/screen_test/settings/valign/grid_middle.frame +1 -1
  223. data/screen_test/settings/valign/grid_middle.rb +1 -1
  224. data/screen_test/settings/valign/grid_top.frame +1 -1
  225. data/screen_test/settings/valign/grid_top.rb +1 -1
  226. data/screen_test/settings/width/box_border_sizing.frame +1 -1
  227. data/screen_test/settings/width/box_border_sizing.rb +1 -1
  228. data/screen_test/settings/width/box_content.frame +1 -1
  229. data/screen_test/settings/width/box_content.rb +1 -1
  230. data/screen_test/settings/width/box_default.frame +1 -1
  231. data/screen_test/settings/width/box_default.rb +1 -1
  232. data/screen_test/settings/width/grid.frame +1 -1
  233. data/screen_test/settings/width/grid.rb +1 -1
  234. data/screen_test/settings/width/overflow_align_center.frame +1 -1
  235. data/screen_test/settings/width/overflow_align_center.rb +1 -1
  236. data/screen_test/settings/width/overflow_align_right.frame +1 -1
  237. data/screen_test/settings/width/overflow_align_right.rb +1 -1
  238. data/screen_test/settings/width/overflow_box.frame +1 -1
  239. data/screen_test/settings/width/overflow_box.rb +1 -1
  240. data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
  241. data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
  242. data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
  243. data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
  244. data/screen_test/settings/width/overflow_grid.frame +1 -1
  245. data/screen_test/settings/width/overflow_grid.rb +1 -1
  246. data/tools/whirled_peas/tools/screen_tester.rb +131 -65
  247. metadata +86 -25
  248. data/lib/whirled_peas/frame.rb +0 -6
  249. data/lib/whirled_peas/frame/consumer.rb +0 -30
  250. data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
  251. data/lib/whirled_peas/frame/event_loop.rb +0 -90
  252. data/lib/whirled_peas/frame/producer.rb +0 -67
  253. data/lib/whirled_peas/graphics/screen.rb +0 -70
  254. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
  255. data/screen_test/settings/position/box_left.frame +0 -1
  256. data/screen_test/settings/position/box_left_negative.frame +0 -1
  257. data/screen_test/settings/position/box_top.frame +0 -1
  258. data/screen_test/settings/position/box_top_negative.frame +0 -1
  259. data/screen_test/settings/position/grid_left.frame +0 -1
  260. data/screen_test/settings/position/grid_left_negative.frame +0 -1
  261. data/screen_test/settings/position/grid_top.frame +0 -1
  262. data/screen_test/settings/position/grid_top_negative.frame +0 -1
data/Rakefile CHANGED
@@ -3,29 +3,10 @@ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- def screen_test(file, method)
7
- raise ArgumentError, 'Missing argument: file' unless file
8
- require_relative 'tools/whirled_peas/tools/screen_tester'
9
- WhirledPeas::Tools::ScreenTester.new(file).send(method)
10
- end
11
-
12
- namespace :screen_test do
13
- %i[template view run save update debug].each do |t|
14
- task t, [:file] do |_, args|
15
- screen_test(args[:file], t)
16
- end
17
- end
18
-
19
- task :update_all do
20
- require_relative 'tools/whirled_peas/tools/screen_tester'
21
- WhirledPeas::Tools::ScreenTester.update_all
22
- end
23
- end
24
-
25
6
  task :screen_test do
26
7
  require_relative 'tools/whirled_peas/tools/screen_tester'
27
8
  WhirledPeas::Tools::ScreenTester.run_all
28
9
  end
29
10
 
30
- task default: :ci
31
11
  task ci: %i[spec screen_test]
12
+ task default: :ci
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'whirled_peas'
5
+ require 'whirled_peas/animator/easing'
6
+
7
+ module WhirledPeas
8
+ NUM_POINTS = 60
9
+
10
+ Animator::Easing::EASING.keys.each do |func|
11
+ Animator::Easing::EFFECTS.each do |effect|
12
+ easing = Animator::Easing.new(func, effect)
13
+ graph = Array.new(NUM_POINTS / ASPECT_RATIO) { '┃' }
14
+ NUM_POINTS.times.each do |i|
15
+ input = i.to_f / (NUM_POINTS - 1)
16
+ eased_value = ((easing.ease(input) * NUM_POINTS * 2) / ASPECT_RATIO).floor
17
+ graph.each.with_index do |row, row_num|
18
+ y_value = NUM_POINTS.to_f / ASPECT_RATIO - row_num - 1
19
+ row << if eased_value == 2 * y_value
20
+ '▄'
21
+ elsif eased_value == 2 * y_value + 1
22
+ '▀'
23
+ else
24
+ ' '
25
+ end
26
+ end
27
+ end
28
+ graph << '┗' + '━' * NUM_POINTS
29
+ puts "#{func} (#{effect})"
30
+ puts graph.join("\n")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'whirled_peas'
5
+ require 'whirled_peas/utils/ansi'
6
+
7
+ module WhirledPeas
8
+ print Utils::Ansi.clear
9
+ print Utils::Ansi.cursor_visible(true)
10
+ STDOUT.flush
11
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'whirled_peas'
5
+ require 'whirled_peas/utils/formatted_string'
6
+
7
+ require_relative '../tools/whirled_peas/tools/screen_tester'
8
+
9
+ def print_usage(exit_code=0)
10
+ puts "Usage: #{$0} [file] [options]"
11
+ puts
12
+ puts 'If not file or options are provide, all tests are run'
13
+ puts
14
+ puts 'If no file is provided, the supported options are'
15
+ puts ' --help print this usage statement and exit'
16
+ puts ' --view-pending interactively display and optionally save rendered output for each pending test'
17
+ puts ' --view-failed interactively display and optionally save rendered output for each faiing test'
18
+ puts
19
+ puts 'If a screen test file is provided as the first argument, the supported options are'
20
+ puts ' --run run screen test for given file'
21
+ puts ' --view interactively display and optionally save the file\'s test output'
22
+ puts ' --template print out template tree for the test template'
23
+ puts ' --debug render the test template without displying it, printing out debug information'
24
+ exit(exit_code)
25
+ end
26
+
27
+ module WhirledPeas
28
+ if ARGV.length == 0
29
+ Tools::ScreenTester.run_all
30
+ elsif ARGV.length == 1
31
+ option = ARGV[0]
32
+ case option
33
+ when '--help'
34
+ print_usage
35
+ when '--view-pending'
36
+ Tools::ScreenTester.view_pending
37
+ when '--view-failed'
38
+ Tools::ScreenTester.view_failed
39
+ else
40
+ print_usage(1)
41
+ end
42
+ elsif ARGV.length == 2
43
+ file, option = ARGV
44
+ case option
45
+ when '--run'
46
+ tester = Tools::ScreenTester.new(file)
47
+ if tester.pending?
48
+ puts Utils::FormattedString.new('Pending', Settings::TextColor::YELLOW)
49
+ puts "Run `#{$0} #{file} --view` to view and optionally save ouput."
50
+ elsif tester.failed?
51
+ puts Utils::FormattedString.new('Failed', Settings::TextColor::RED)
52
+ puts "Run `#{$0} #{file} --view` to compare and optionally save ouput."
53
+ else
54
+ puts Utils::FormattedString.new('Pass', Settings::TextColor::GREEN)
55
+ end
56
+ when '--view'
57
+ Tools::ScreenTester.new(file).view
58
+ when '--template'
59
+ Tools::ScreenTester.new(file).template
60
+ when '--debug'
61
+ Tools::ScreenTester.new(file).debug
62
+ else
63
+ print_usage(1)
64
+ end
65
+ else
66
+ print_usage(1)
67
+ end
68
+ end
@@ -0,0 +1,35 @@
1
+ require 'bundler/setup'
2
+ require 'whirled_peas'
3
+ require 'whirled_peas/component/list_with_active'
4
+
5
+ class TemplateFactory
6
+ ITEMS = 400.times.map(&:itself)
7
+
8
+ def build(name, args)
9
+ active = args[:active]
10
+ WhirledPeas.template do |composer, settings|
11
+ WhirledPeas.component(composer, settings, :list_with_active) do |component, settings|
12
+ component.items = %w[red orange yellow green blue indigo violet]
13
+ component.separator = ', '
14
+ component.active_index = active
15
+ component.viewport_size = 27
16
+ component.active_color = :green
17
+ component.active_bg_color = :yellow
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class Application
24
+ def start(producer)
25
+ producer.frameset(5, easing: :parametric) do |fs|
26
+ ITEMS.length.times { |i| fs.add_frame('intro', args: { active: i }) }
27
+ end
28
+ producer.add_frame('hold', duration: 1, args: { active: ITEMS.length - 1 })
29
+ end
30
+ end
31
+
32
+ WhirledPeas.configure do |config|
33
+ config.template_factory = TemplateFactory.new
34
+ config.application = Application.new
35
+ end
@@ -0,0 +1,54 @@
1
+ require 'bundler/setup'
2
+ require 'whirled_peas'
3
+ require 'whirled_peas/animator/easing'
4
+
5
+ module WhirledPeas
6
+ PublicEasing = Animator::Easing
7
+ end
8
+
9
+ class TemplateFactory
10
+ INNER_WIDTH = 60
11
+
12
+ def build(name, args)
13
+ WhirledPeas.template do |composer, settings|
14
+ settings.bg_color = :bright_white
15
+ settings.align = :center
16
+ settings.valign = :middle
17
+ composer.add_grid do |composer, settings|
18
+ settings.num_cols = 2
19
+ WhirledPeas::PublicEasing::EASING.keys.each do |func|
20
+ easing = WhirledPeas::PublicEasing.new(func, :in_out)
21
+ composer.add_box do |composer, settings|
22
+ settings.flow = :t2b
23
+ settings.set_padding(horiz: 4, vert: 2)
24
+ composer.add_box do |_, settings|
25
+ settings.margin.bottom = 1
26
+ settings.color = :blue
27
+ settings.underline = true
28
+ "#{func} (in_out)"
29
+ end
30
+ composer.add_graph do |composer, settings|
31
+ settings.axis_color = :black
32
+ settings.color = :bright_blue
33
+ settings.height = 15
34
+ INNER_WIDTH.times.map do |i|
35
+ easing.ease(i.to_f / (INNER_WIDTH - 1))
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ class Application
46
+ def start(producer)
47
+ producer.add_frame('intro', duration: 5)
48
+ end
49
+ end
50
+
51
+ WhirledPeas.configure do |config|
52
+ config.template_factory = TemplateFactory.new
53
+ config.application = Application.new
54
+ end
@@ -40,13 +40,13 @@ class TemplateFactory
40
40
  end
41
41
  end
42
42
 
43
- class Driver
43
+ class Application
44
44
  def start(producer)
45
- producer.send_frame('intro', duration: 5)
45
+ producer.add_frame('intro', duration: 5)
46
46
  end
47
47
  end
48
48
 
49
49
  WhirledPeas.configure do |config|
50
50
  config.template_factory = TemplateFactory.new
51
- config.driver = Driver.new
51
+ config.application = Application.new
52
52
  end
@@ -2,52 +2,42 @@ require 'bundler/setup'
2
2
  require 'whirled_peas'
3
3
 
4
4
  class TemplateFactory
5
- HPADDING = 0
6
- VPADDING = 0
7
5
  ITEM_COUNT = 64
8
6
 
9
7
  def build(name, args)
10
8
  top = args[:top]
11
9
  WhirledPeas.template do |composer, settings|
12
- settings.color = :green
13
10
  composer.add_box('Vert') do |composer, settings|
14
- settings.bg_color = :bright_red
15
- settings.full_border(color: :blue)
11
+ settings.full_border
16
12
  settings.set_scrollbar(vert: true)
17
13
  settings.height = 12
18
- composer.add_box('Inner') do |composer, settings|
19
- settings.flow = :t2b
20
- settings.set_padding(left: HPADDING, right: HPADDING, top: VPADDING, bottom: VPADDING)
21
- settings.set_position(top: top)
22
- ITEM_COUNT.times do |i|
23
- composer.add_text { "%2d" % i }
24
- end
14
+ settings.flow = :t2b
15
+ settings.content_start.top = top
16
+ ITEM_COUNT.times do |i|
17
+ composer.add_text { "%2d" % i }
25
18
  end
26
19
  end
27
20
  composer.add_box('Horiz') do |composer, settings|
28
- settings.bg_color = :bright_red
29
- settings.full_border(color: :blue)
30
- settings.set_padding(left: HPADDING, right: HPADDING, top: VPADDING, bottom: VPADDING)
21
+ settings.full_border
31
22
  settings.set_scrollbar(horiz: true)
32
23
  settings.width = 12
33
- composer.add_box('Inner') do |composer, settings|
34
- settings.set_position(left: top)
35
- ITEM_COUNT.times.map { |i| (i % 10).to_s }.join
36
- end
24
+ settings.content_start.left = top
25
+ ITEM_COUNT.times.map { |i| (i % 10).to_s }.join
37
26
  end
38
27
  end
39
28
  end
40
29
  end
41
30
 
42
- class Driver
31
+ class Application
43
32
  def start(producer)
44
- 53.times do |i|
45
- producer.send_frame('intro', duration: 0.3, args: { top: -i })
33
+ producer.frameset(5, easing: :bezier) do |fs|
34
+ 53.times { |i| fs.add_frame('intro', args: { top: -i }) }
46
35
  end
36
+ producer.add_frame('hold', duration: 1, args: { top: -52})
47
37
  end
48
38
  end
49
39
 
50
40
  WhirledPeas.configure do |config|
51
41
  config.template_factory = TemplateFactory.new
52
- config.driver = Driver.new
42
+ config.application = Application.new
53
43
  end
@@ -0,0 +1,13 @@
1
+ bright:
2
+ bg_color: :bright_white
3
+ color: :blue
4
+ border_color: :bright_blue
5
+ axis_color: :red
6
+ title_font: :default
7
+
8
+ dark:
9
+ bg_color: :black
10
+ color: :white
11
+ border_color: :gray
12
+ axis_color: :bright_white
13
+ title_font: :swan
@@ -1,24 +1,44 @@
1
- require 'logger'
2
-
3
- require 'whirled_peas/errors'
1
+ require 'whirled_peas/animator'
4
2
  require 'whirled_peas/config'
5
- require 'whirled_peas/frame'
3
+ require 'whirled_peas/errors'
6
4
  require 'whirled_peas/graphics'
7
5
  require 'whirled_peas/settings'
8
6
  require 'whirled_peas/utils'
9
7
  require 'whirled_peas/version'
10
8
 
11
9
  module WhirledPeas
12
- def self.config
13
- @config ||= Config.new
14
- end
10
+ class << self
11
+ def configure(&block)
12
+ yield config
13
+ end
15
14
 
16
- def self.configure(&block)
17
- yield config
18
- end
15
+ def register_component(name, klass)
16
+ require 'whirled_peas/component'
17
+ Component::Factory.register(name, klass)
18
+ end
19
+
20
+ def component(composer, settings, name, &block)
21
+ require 'whirled_peas/component'
22
+ component = Component::Factory.build(name)
23
+ yield component
24
+ component.compose(composer, settings)
25
+ end
26
+
27
+ def template(theme_name=nil, &block)
28
+ require 'whirled_peas/graphics/composer'
29
+ Graphics::Composer.build(theme_name, &block)
30
+ end
31
+
32
+ def register_theme(name, &block)
33
+ require 'whirled_peas/settings/theme'
34
+ require 'whirled_peas/settings/theme_library'
35
+ theme = Settings::Theme.new
36
+ yield theme
37
+ Settings::ThemeLibrary.add(name, theme)
38
+ end
19
39
 
20
- def self.template(&block)
21
- require 'whirled_peas/graphics/composer'
22
- Graphics::Composer.build(&block)
40
+ def config
41
+ @config ||= Config.new
42
+ end
23
43
  end
24
44
  end
@@ -0,0 +1,5 @@
1
+ module WhirledPeas
2
+ module Animator
3
+ end
4
+ private_constant :Animator
5
+ end
@@ -0,0 +1,17 @@
1
+ module WhirledPeas
2
+ module Animator
3
+ class DebugConsumer
4
+ def add_frameset(frameset)
5
+ require 'json'
6
+
7
+ frameset.each_frame do |frame, args|
8
+ puts [frame, *(JSON.generate(args) unless args.empty?)].join(' ')
9
+ end
10
+ end
11
+
12
+ def process
13
+ # no op
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,72 @@
1
+ module WhirledPeas
2
+ module Animator
3
+ class Easing
4
+ # Implementations of available ease-in functions. Ease-out and ease-in-out can all be
5
+ # derived from ease-in.
6
+ EASING = {
7
+ bezier: proc do |value|
8
+ value /= 2
9
+ 2 * value * value * (3 - 2 * value)
10
+ end,
11
+ linear: proc { |value| value },
12
+ parametric: proc do |value|
13
+ value /= 2
14
+ squared = value * value
15
+ 2 * squared / (2 * (squared - value) + 1)
16
+ end,
17
+ quadratic: proc do |value|
18
+ value * value
19
+ end
20
+ }
21
+
22
+ EFFECTS = %i[in out in_out]
23
+
24
+ def initialize(easing=:linear, effect=:in_out)
25
+ unless EASING.key?(easing)
26
+ raise ArgumentError,
27
+ "Invalid easing function: #{easing}, expecting one of #{EASING.keys.join(', ')}"
28
+ end
29
+ unless EFFECTS.include?(effect)
30
+ raise ArgumentError,
31
+ "Invalid effect: #{effect}, expecting one of #{EFFECTS.join(', ')}"
32
+ end
33
+ @easing = easing
34
+ @effect = effect
35
+ end
36
+
37
+ def ease(value)
38
+ case effect
39
+ when :in
40
+ ease_in(value)
41
+ when :out
42
+ ease_out(value)
43
+ else
44
+ ease_in_out(value)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :easing, :effect
51
+
52
+ # The procs in EASING define the ease-in functions, so we simply need
53
+ # to invoke the function with the given normalized value
54
+ def ease_in(value)
55
+ EASING[easing].call(value)
56
+ end
57
+
58
+ # The ease-out function will be the ease-in function rotated 180 degrees.
59
+ def ease_out(value)
60
+ 1 - EASING[easing].call(1 - value)
61
+ end
62
+
63
+ def ease_in_out(value)
64
+ if value < 0.5
65
+ ease_in(value * 2) / 2
66
+ else
67
+ 0.5 + ease_out(2 * value - 1) / 2
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end