whirled_peas 0.8.0 → 0.11.1

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +9 -777
  5. data/doc/application.md +92 -0
  6. data/doc/cli.md +115 -0
  7. data/doc/components.md +55 -0
  8. data/doc/easing.md +257 -0
  9. data/doc/elements.md +69 -0
  10. data/doc/screen_test.md +23 -0
  11. data/doc/settings.md +466 -0
  12. data/doc/template_factory.md +53 -0
  13. data/doc/themes.md +15 -0
  14. data/examples/components.rb +35 -0
  15. data/examples/graph.rb +54 -0
  16. data/examples/scrolling.rb +9 -20
  17. data/lib/data/themes.yaml +17 -0
  18. data/lib/whirled_peas.rb +31 -9
  19. data/lib/whirled_peas/animator/frameset.rb +1 -1
  20. data/lib/whirled_peas/animator/producer.rb +1 -1
  21. data/lib/whirled_peas/command/config_command.rb +3 -3
  22. data/lib/whirled_peas/command/play.rb +4 -0
  23. data/lib/whirled_peas/command/themes.rb +77 -0
  24. data/lib/whirled_peas/command_line.rb +3 -1
  25. data/lib/whirled_peas/component.rb +35 -0
  26. data/lib/whirled_peas/component/list_with_active.rb +88 -0
  27. data/lib/whirled_peas/graphics/box_painter.rb +4 -4
  28. data/lib/whirled_peas/graphics/composer.rb +27 -2
  29. data/lib/whirled_peas/graphics/container_coords.rb +23 -25
  30. data/lib/whirled_peas/graphics/container_dimensions.rb +24 -0
  31. data/lib/whirled_peas/graphics/container_painter.rb +27 -139
  32. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  33. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  34. data/lib/whirled_peas/graphics/debugger.rb +2 -7
  35. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  36. data/lib/whirled_peas/graphics/graph_painter.rb +104 -0
  37. data/lib/whirled_peas/graphics/grid_painter.rb +0 -3
  38. data/lib/whirled_peas/graphics/scrollbar_helper.rb +126 -0
  39. data/lib/whirled_peas/graphics/text_painter.rb +7 -11
  40. data/lib/whirled_peas/null_logger.rb +0 -1
  41. data/lib/whirled_peas/settings/bg_color.rb +5 -1
  42. data/lib/whirled_peas/settings/border.rb +25 -4
  43. data/lib/whirled_peas/settings/color.rb +8 -4
  44. data/lib/whirled_peas/settings/container_settings.rb +14 -9
  45. data/lib/whirled_peas/settings/debugger.rb +3 -1
  46. data/lib/whirled_peas/settings/element_settings.rb +22 -5
  47. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  48. data/lib/whirled_peas/settings/grid_settings.rb +7 -0
  49. data/lib/whirled_peas/settings/position.rb +17 -5
  50. data/lib/whirled_peas/settings/text_color.rb +5 -0
  51. data/lib/whirled_peas/settings/text_settings.rb +1 -0
  52. data/lib/whirled_peas/settings/theme.rb +61 -0
  53. data/lib/whirled_peas/settings/theme_library.rb +69 -0
  54. data/lib/whirled_peas/utils/ansi.rb +1 -1
  55. data/lib/whirled_peas/version.rb +1 -1
  56. data/screen_test/components/list_with_active/l2r_active_color.frame +1 -0
  57. data/screen_test/components/list_with_active/l2r_active_color.rb +18 -0
  58. data/screen_test/components/list_with_active/l2r_position_end.frame +1 -0
  59. data/screen_test/components/list_with_active/l2r_position_end.rb +16 -0
  60. data/screen_test/components/list_with_active/l2r_position_middle.frame +1 -0
  61. data/screen_test/components/list_with_active/l2r_position_middle.rb +16 -0
  62. data/screen_test/components/list_with_active/l2r_position_start.frame +1 -0
  63. data/screen_test/components/list_with_active/l2r_position_start.rb +16 -0
  64. data/screen_test/components/list_with_active/l2r_separator.frame +1 -0
  65. data/screen_test/components/list_with_active/l2r_separator.rb +17 -0
  66. data/screen_test/components/list_with_active/t2b_active_color.frame +1 -0
  67. data/screen_test/components/list_with_active/t2b_active_color.rb +19 -0
  68. data/screen_test/components/list_with_active/t2b_position_end.frame +1 -0
  69. data/screen_test/components/list_with_active/t2b_position_end.rb +17 -0
  70. data/screen_test/components/list_with_active/t2b_position_middle.frame +1 -0
  71. data/screen_test/components/list_with_active/t2b_position_middle.rb +17 -0
  72. data/screen_test/components/list_with_active/t2b_position_start.frame +1 -0
  73. data/screen_test/components/list_with_active/t2b_position_start.rb +17 -0
  74. data/screen_test/components/list_with_active/t2b_separator.frame +1 -0
  75. data/screen_test/components/list_with_active/t2b_separator.rb +18 -0
  76. data/screen_test/elements/box.frame +1 -1
  77. data/screen_test/elements/box.rb +1 -1
  78. data/screen_test/elements/graph_asc.frame +1 -0
  79. data/screen_test/elements/graph_asc.rb +12 -0
  80. data/screen_test/elements/graph_desc.frame +1 -0
  81. data/screen_test/elements/graph_desc.rb +12 -0
  82. data/screen_test/elements/graph_horiz.frame +1 -0
  83. data/screen_test/elements/graph_horiz.rb +12 -0
  84. data/screen_test/elements/graph_sin.frame +1 -0
  85. data/screen_test/elements/graph_sin.rb +12 -0
  86. data/screen_test/elements/grid.frame +1 -1
  87. data/screen_test/elements/grid.rb +1 -1
  88. data/screen_test/elements/screen_overflow_x.frame +1 -1
  89. data/screen_test/elements/screen_overflow_x.rb +1 -1
  90. data/screen_test/elements/screen_overflow_y.frame +1 -1
  91. data/screen_test/elements/screen_overflow_y.rb +1 -1
  92. data/screen_test/elements/text.frame +1 -1
  93. data/screen_test/elements/text.rb +1 -1
  94. data/screen_test/elements/text_multiline.frame +1 -1
  95. data/screen_test/elements/text_multiline.rb +1 -1
  96. data/screen_test/elements/theme.frame +1 -0
  97. data/screen_test/elements/theme.rb +26 -0
  98. data/screen_test/settings/align/box_around.frame +1 -1
  99. data/screen_test/settings/align/box_around.rb +1 -1
  100. data/screen_test/settings/align/box_between.frame +1 -1
  101. data/screen_test/settings/align/box_between.rb +1 -1
  102. data/screen_test/settings/align/box_center.frame +1 -1
  103. data/screen_test/settings/align/box_center.rb +1 -1
  104. data/screen_test/settings/align/box_default.frame +1 -1
  105. data/screen_test/settings/align/box_default.rb +1 -1
  106. data/screen_test/settings/align/box_evenly.frame +1 -1
  107. data/screen_test/settings/align/box_evenly.rb +1 -1
  108. data/screen_test/settings/align/box_left.frame +1 -1
  109. data/screen_test/settings/align/box_left.rb +1 -1
  110. data/screen_test/settings/align/box_right.frame +1 -1
  111. data/screen_test/settings/align/box_right.rb +1 -1
  112. data/screen_test/settings/align/children_center.frame +1 -1
  113. data/screen_test/settings/align/children_center.rb +1 -1
  114. data/screen_test/settings/align/children_left.frame +1 -1
  115. data/screen_test/settings/align/children_left.rb +1 -1
  116. data/screen_test/settings/align/children_right.frame +1 -1
  117. data/screen_test/settings/align/children_right.rb +1 -1
  118. data/screen_test/settings/align/grid_center.frame +1 -1
  119. data/screen_test/settings/align/grid_center.rb +1 -1
  120. data/screen_test/settings/align/grid_default.frame +1 -1
  121. data/screen_test/settings/align/grid_default.rb +1 -1
  122. data/screen_test/settings/align/grid_left.frame +1 -1
  123. data/screen_test/settings/align/grid_left.rb +1 -1
  124. data/screen_test/settings/align/grid_right.frame +1 -1
  125. data/screen_test/settings/align/grid_right.rb +1 -1
  126. data/screen_test/settings/ansi/bold.frame +1 -1
  127. data/screen_test/settings/ansi/bold.rb +1 -1
  128. data/screen_test/settings/ansi/color.frame +1 -1
  129. data/screen_test/settings/ansi/color.rb +1 -1
  130. data/screen_test/settings/ansi/underline.frame +1 -1
  131. data/screen_test/settings/ansi/underline.rb +1 -1
  132. data/screen_test/settings/border.frame +1 -1
  133. data/screen_test/settings/border.rb +1 -1
  134. data/screen_test/settings/content_start/box_bottom.frame +1 -0
  135. data/screen_test/settings/content_start/box_bottom.rb +17 -0
  136. data/screen_test/settings/content_start/box_left.frame +1 -0
  137. data/screen_test/settings/{position → content_start}/box_left.rb +2 -2
  138. data/screen_test/settings/content_start/box_left_negative.frame +1 -0
  139. data/screen_test/settings/{position → content_start}/box_left_negative.rb +2 -2
  140. data/screen_test/settings/content_start/box_right.frame +1 -0
  141. data/screen_test/settings/content_start/box_right.rb +17 -0
  142. data/screen_test/settings/content_start/box_top.frame +1 -0
  143. data/screen_test/settings/{position → content_start}/box_top.rb +2 -2
  144. data/screen_test/settings/content_start/box_top_negative.frame +1 -0
  145. data/screen_test/settings/{position → content_start}/box_top_negative.rb +2 -2
  146. data/screen_test/settings/content_start/grid_left.frame +1 -0
  147. data/screen_test/settings/{position → content_start}/grid_left.rb +2 -2
  148. data/screen_test/settings/content_start/grid_left_negative.frame +1 -0
  149. data/screen_test/settings/{position → content_start}/grid_left_negative.rb +2 -2
  150. data/screen_test/settings/content_start/grid_top.frame +1 -0
  151. data/screen_test/settings/{position → content_start}/grid_top.rb +2 -2
  152. data/screen_test/settings/content_start/grid_top_negative.frame +1 -0
  153. data/screen_test/settings/{position → content_start}/grid_top_negative.rb +2 -2
  154. data/screen_test/settings/flow/box_b2t.frame +1 -1
  155. data/screen_test/settings/flow/box_b2t.rb +1 -1
  156. data/screen_test/settings/flow/box_l2r.frame +1 -1
  157. data/screen_test/settings/flow/box_l2r.rb +1 -1
  158. data/screen_test/settings/flow/box_r2l.frame +1 -1
  159. data/screen_test/settings/flow/box_r2l.rb +1 -1
  160. data/screen_test/settings/flow/box_t2b.frame +1 -1
  161. data/screen_test/settings/flow/box_t2b.rb +1 -1
  162. data/screen_test/settings/flow/grid_b2t.frame +1 -1
  163. data/screen_test/settings/flow/grid_b2t.rb +1 -1
  164. data/screen_test/settings/flow/grid_l2r.frame +1 -1
  165. data/screen_test/settings/flow/grid_l2r.rb +1 -1
  166. data/screen_test/settings/flow/grid_r2l.frame +1 -1
  167. data/screen_test/settings/flow/grid_r2l.rb +1 -1
  168. data/screen_test/settings/flow/grid_t2b.frame +1 -1
  169. data/screen_test/settings/flow/grid_t2b.rb +1 -1
  170. data/screen_test/settings/height/box.frame +1 -1
  171. data/screen_test/settings/height/box.rb +1 -1
  172. data/screen_test/settings/height/box_border_sizing.frame +1 -1
  173. data/screen_test/settings/height/box_border_sizing.rb +1 -1
  174. data/screen_test/settings/height/grid.frame +1 -1
  175. data/screen_test/settings/height/grid.rb +1 -1
  176. data/screen_test/settings/height/overflow_box.frame +1 -1
  177. data/screen_test/settings/height/overflow_box.rb +1 -1
  178. data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
  179. data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
  180. data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
  181. data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
  182. data/screen_test/settings/height/overflow_grid.frame +1 -1
  183. data/screen_test/settings/height/overflow_grid.rb +1 -1
  184. data/screen_test/settings/margin.frame +1 -1
  185. data/screen_test/settings/margin.rb +1 -1
  186. data/screen_test/settings/padding.frame +1 -1
  187. data/screen_test/settings/padding.rb +1 -1
  188. data/screen_test/settings/scroll/horiz_box.frame +1 -1
  189. data/screen_test/settings/scroll/horiz_box.rb +3 -5
  190. data/screen_test/settings/scroll/horiz_box_align_center.rb +3 -5
  191. data/screen_test/settings/scroll/horiz_box_align_right.rb +3 -5
  192. data/screen_test/settings/scroll/vert_box.frame +1 -1
  193. data/screen_test/settings/scroll/vert_box.rb +6 -8
  194. data/screen_test/settings/title_font.frame +1 -1
  195. data/screen_test/settings/title_font.rb +1 -1
  196. data/screen_test/settings/valign/box_around.frame +1 -1
  197. data/screen_test/settings/valign/box_around.rb +1 -1
  198. data/screen_test/settings/valign/box_between.frame +1 -1
  199. data/screen_test/settings/valign/box_between.rb +1 -1
  200. data/screen_test/settings/valign/box_bottom.frame +1 -1
  201. data/screen_test/settings/valign/box_bottom.rb +1 -1
  202. data/screen_test/settings/valign/box_default.frame +1 -1
  203. data/screen_test/settings/valign/box_default.rb +1 -1
  204. data/screen_test/settings/valign/box_evenly.frame +1 -1
  205. data/screen_test/settings/valign/box_evenly.rb +1 -1
  206. data/screen_test/settings/valign/box_middle.frame +1 -1
  207. data/screen_test/settings/valign/box_middle.rb +1 -1
  208. data/screen_test/settings/valign/box_top.frame +1 -1
  209. data/screen_test/settings/valign/box_top.rb +1 -1
  210. data/screen_test/settings/valign/grid_bottom.frame +1 -1
  211. data/screen_test/settings/valign/grid_bottom.rb +1 -1
  212. data/screen_test/settings/valign/grid_default.frame +1 -1
  213. data/screen_test/settings/valign/grid_default.rb +1 -1
  214. data/screen_test/settings/valign/grid_middle.frame +1 -1
  215. data/screen_test/settings/valign/grid_middle.rb +1 -1
  216. data/screen_test/settings/valign/grid_top.frame +1 -1
  217. data/screen_test/settings/valign/grid_top.rb +1 -1
  218. data/screen_test/settings/width/box_border_sizing.frame +1 -1
  219. data/screen_test/settings/width/box_border_sizing.rb +1 -1
  220. data/screen_test/settings/width/box_content.frame +1 -1
  221. data/screen_test/settings/width/box_content.rb +1 -1
  222. data/screen_test/settings/width/box_default.frame +1 -1
  223. data/screen_test/settings/width/box_default.rb +1 -1
  224. data/screen_test/settings/width/grid.frame +1 -1
  225. data/screen_test/settings/width/grid.rb +1 -1
  226. data/screen_test/settings/width/overflow_align_center.frame +1 -1
  227. data/screen_test/settings/width/overflow_align_center.rb +1 -1
  228. data/screen_test/settings/width/overflow_align_right.frame +1 -1
  229. data/screen_test/settings/width/overflow_align_right.rb +1 -1
  230. data/screen_test/settings/width/overflow_box.frame +1 -1
  231. data/screen_test/settings/width/overflow_box.rb +1 -1
  232. data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
  233. data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
  234. data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
  235. data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
  236. data/screen_test/settings/width/overflow_grid.frame +1 -1
  237. data/screen_test/settings/width/overflow_grid.rb +1 -1
  238. data/tools/whirled_peas/tools/screen_tester.rb +15 -1
  239. metadata +75 -20
  240. data/lib/whirled_peas/graphics/mock_screen.rb +0 -26
  241. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
  242. data/screen_test/settings/position/box_left.frame +0 -1
  243. data/screen_test/settings/position/box_left_negative.frame +0 -1
  244. data/screen_test/settings/position/box_top.frame +0 -1
  245. data/screen_test/settings/position/box_top_negative.frame +0 -1
  246. data/screen_test/settings/position/grid_left.frame +0 -1
  247. data/screen_test/settings/position/grid_left_negative.frame +0 -1
  248. data/screen_test/settings/position/grid_top.frame +0 -1
  249. data/screen_test/settings/position/grid_top_negative.frame +0 -1
@@ -0,0 +1,53 @@
1
+ ## Template Factory
2
+
3
+ To render the frame events sent by the application, the application requires a template factory. This factory will be called for each frame event, with the frame name and the arguments supplied by the application. A template factory can be an instance of ruby class and thus can maintain state. Whirled Peas provides a few basic building blocks to make simple, yet elegant terminal-based UIs.
4
+
5
+ To build a template in a template factory, use `WhirledPeas.template(theme)`, which takes an optional [theme](themes.md) and yields a composer (used to add [elements](elements.md) to the template) and [settings](settings.md) (used to configure the element).
6
+
7
+ ### Full example
8
+
9
+ ```ruby
10
+ class TemplateFactory
11
+ def build(frame, args)
12
+ set_state(frame, args)
13
+ WhirledPeas.template do |composer, settings|
14
+ settings.flow = :l2r
15
+ settings.align = :center
16
+
17
+ composer.add_box('Title', &method(:title))
18
+ composer.add_box('Sum', &method(:sum))
19
+ composer.add_grid('NumberGrid', &method(:number_grid))
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def set_state(frame, args)
26
+ @frame = frame
27
+ @numbers = args.key?(:numbers) ? args[:numbers] || []
28
+ @sum = args[:sum] if args.key?(:sum)
29
+ @low = args[:low] if args.key?(:low)
30
+ @high = args[:high] if args.key?(:high)
31
+ end
32
+
33
+ def title(_composer, settings)
34
+ settings.underline = true
35
+ "Pair Finder"
36
+ end
37
+
38
+ def sum(_composer, settings)
39
+ settings.color = @frame == 'found-pair' ? :green : :red
40
+ @sum ? "Sum: #{@sum}" : 'N/A'
41
+ end
42
+
43
+ def number_grid(composer, settings)
44
+ settings.full_border
45
+ @numbers.each.with_index do |num, index|
46
+ composer.add_text do |_, settings|
47
+ settings.bg_color = (@low == index || @high == index) ? :cyan : :white
48
+ num
49
+ end
50
+ end
51
+ end
52
+ end
53
+ ```
@@ -0,0 +1,15 @@
1
+ ## Themes
2
+
3
+ The template builder (`WhirledPeas.template`) takes an optional `theme` argument. You can provide the name of a predefined theme (run `whirled_peas themes` to see a list with samples) or define you own with the following
4
+
5
+ ```ruby
6
+ WhirledPeas.register_theme(:my_theme) do |theme|
7
+ theme.bg_color = :bright_white
8
+ theme.color = :blue
9
+ theme.border_color = :bright_green
10
+ theme.axis_color = :bright_red
11
+ theme.title_font = :default
12
+ end
13
+ ```
14
+
15
+ Theme settings will be used as default settings throughout the template, however theme settings can be overridden on any element.
@@ -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
@@ -2,38 +2,27 @@ 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
@@ -42,7 +31,7 @@ end
42
31
  class Application
43
32
  def start(producer)
44
33
  producer.frameset(5, easing: :bezier) do |fs|
45
- 53.times { |i| fs.add_frame('intro', { top: -i }) }
34
+ 53.times { |i| fs.add_frame('intro', args: { top: -i }) }
46
35
  end
47
36
  producer.add_frame('hold', duration: 1, args: { top: -52})
48
37
  end
@@ -0,0 +1,17 @@
1
+ bright:
2
+ axis_color: :red
3
+ bg_color: :bright_white
4
+ border_color: :bright_blue
5
+ border_style: :soft
6
+ color: :blue
7
+ title_font: :default
8
+
9
+ dark:
10
+ axis_color: :bright_white
11
+ bg_color: :black
12
+ border_color: :gray
13
+ border_style: :double
14
+ color: :white
15
+ highlight_bg_color: :bright_red
16
+ highlight_color: :black
17
+ title_font: :swan
@@ -7,16 +7,38 @@ require 'whirled_peas/utils'
7
7
  require 'whirled_peas/version'
8
8
 
9
9
  module WhirledPeas
10
- def self.config
11
- @config ||= Config.new
12
- end
10
+ class << self
11
+ def configure(&block)
12
+ yield config
13
+ end
13
14
 
14
- def self.configure(&block)
15
- yield config
16
- 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
17
39
 
18
- def self.template(&block)
19
- require 'whirled_peas/graphics/composer'
20
- Graphics::Composer.build(&block)
40
+ def config
41
+ @config ||= Config.new
42
+ end
21
43
  end
22
44
  end
@@ -10,7 +10,7 @@ module WhirledPeas
10
10
  @frames = []
11
11
  end
12
12
 
13
- def add_frame(name, args={})
13
+ def add_frame(name, args: {})
14
14
  frames << [name, args]
15
15
  end
16
16
 
@@ -17,7 +17,7 @@ module WhirledPeas
17
17
 
18
18
  def add_frame(name, duration: nil, args: {})
19
19
  frameset(duration || 1 / refresh_rate) do |fs|
20
- fs.add_frame(name, args)
20
+ fs.add_frame(name, args: args)
21
21
  end
22
22
  end
23
23
 
@@ -8,9 +8,9 @@ module WhirledPeas
8
8
  class ConfigCommand < Base
9
9
  def start
10
10
  require config_file
11
- rescue => e
12
- puts "Error loading #{config_file}"
13
- puts e.message
11
+ rescue LoadError => e
12
+ puts e
13
+ puts e.backtrace.join("\n")
14
14
  exit(1)
15
15
  end
16
16
 
@@ -38,6 +38,10 @@ module WhirledPeas
38
38
  config.application.start(producer)
39
39
  end
40
40
  end
41
+ rescue LoadError => e
42
+ puts e
43
+ puts e.backtrace.join("\n")
44
+ exit(1)
41
45
  end
42
46
 
43
47
  private
@@ -0,0 +1,77 @@
1
+ require 'whirled_peas/device/screen'
2
+ require 'whirled_peas/graphics/renderer'
3
+ require 'whirled_peas/settings/theme_library'
4
+
5
+ require_relative 'base'
6
+
7
+ module WhirledPeas
8
+ module Command
9
+ # Display a still frame with the specified arguments.
10
+ class Themes < Base
11
+ def self.description
12
+ 'List all themes with sample template rendered in the theme'
13
+ end
14
+
15
+ def start
16
+ super
17
+
18
+ require config_file unless config_file.nil?
19
+
20
+ theme_names = Settings::ThemeLibrary.theme_names
21
+ theme_names.each.with_index do |name, index|
22
+ template = WhirledPeas.template(name) do |composer, settings|
23
+ settings.full_border
24
+ settings.flow = :t2b
25
+ composer.add_text do |_, settings|
26
+ settings.title_font = :theme
27
+ name
28
+ end
29
+ composer.add_text do
30
+ name == Settings::ThemeLibrary.default_name ? ' (default)' : ''
31
+ end
32
+ composer.add_graph do |_, settings|
33
+ settings.height = 12
34
+ 20.times.map { |i| Math.sqrt(i) }
35
+ end
36
+ end
37
+ Utils::Ansi.with_screen do |width, height|
38
+ rendered = Graphics::Renderer.new(
39
+ template,
40
+ 80,
41
+ 30
42
+ ).paint
43
+ Device::Screen.new(10000).handle_renders([rendered])
44
+ end
45
+
46
+ if index < theme_names.length - 1
47
+ print 'See next theme? [Y/q] '
48
+ STDOUT.flush
49
+ break if gets.chomp == 'q'
50
+ end
51
+ end
52
+ rescue LoadError => e
53
+ puts e
54
+ puts e.backtrace.join("\n")
55
+ exit(1)
56
+ end
57
+
58
+ private
59
+
60
+ attr_reader :config_file
61
+
62
+ def validate!
63
+ super
64
+ config_file = args.shift
65
+ @error_text = 'hi'
66
+ unless config_file.nil?
67
+ # We think we have a valid ruby config file, set the absolute path to @config
68
+ @config_file = config_file[0] == '/' ? config_file : File.join(Dir.pwd, config_file)
69
+ end
70
+ end
71
+
72
+ def options_usage
73
+ '[config file]'
74
+ end
75
+ end
76
+ end
77
+ end
@@ -5,6 +5,7 @@ require 'whirled_peas/command/help'
5
5
  require 'whirled_peas/command/play'
6
6
  require 'whirled_peas/command/record'
7
7
  require 'whirled_peas/command/still'
8
+ require 'whirled_peas/command/themes'
8
9
 
9
10
  module WhirledPeas
10
11
  class CommandLine
@@ -15,7 +16,8 @@ module WhirledPeas
15
16
  Command::Help,
16
17
  Command::Play,
17
18
  Command::Record,
18
- Command::Still
19
+ Command::Still,
20
+ Command::Themes
19
21
  ].map.with_object({}) { |c, h| h[c.command_name] = c }
20
22
 
21
23
  def initialize(args)
@@ -0,0 +1,35 @@
1
+ module WhirledPeas
2
+ module Component
3
+ module Factory
4
+ class << self
5
+ def register(name, klass)
6
+ classes[name] = klass
7
+ end
8
+
9
+ def build(name)
10
+ unless classes.key?(name)
11
+ expected = classes.keys.join(', ')
12
+ raise ArgumentError, "Unrecognized component: #{name.inspect}, expecting one of #{expected}"
13
+ end
14
+ @classes[name].new
15
+ end
16
+
17
+ private
18
+
19
+ def classes
20
+ return @classes if @classes
21
+ @classes = {}
22
+ Component.constants.each do |const|
23
+ next if const == name
24
+ klass = Component.const_get(const)
25
+ next unless klass.is_a?(Class)
26
+ name = const.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
27
+ @classes[name] = klass
28
+ end
29
+ @classes
30
+ end
31
+ end
32
+ end
33
+ end
34
+ private_constant :Component
35
+ end