whirled_peas 0.3.0 → 0.7.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +549 -85
  5. data/Rakefile +28 -3
  6. data/examples/intro.rb +52 -0
  7. data/examples/scrolling.rb +53 -0
  8. data/exe/whirled_peas +7 -0
  9. data/lib/whirled_peas.rb +12 -36
  10. data/lib/whirled_peas/command_line.rb +255 -0
  11. data/lib/whirled_peas/config.rb +21 -0
  12. data/lib/whirled_peas/errors.rb +7 -0
  13. data/lib/whirled_peas/frame.rb +0 -5
  14. data/lib/whirled_peas/frame/consumer.rb +30 -0
  15. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  16. data/lib/whirled_peas/frame/event_loop.rb +69 -38
  17. data/lib/whirled_peas/frame/producer.rb +36 -19
  18. data/lib/whirled_peas/graphics.rb +19 -0
  19. data/lib/whirled_peas/graphics/box_painter.rb +101 -0
  20. data/lib/whirled_peas/graphics/canvas.rb +118 -0
  21. data/lib/whirled_peas/graphics/composer.rb +80 -0
  22. data/lib/whirled_peas/graphics/container_coords.rb +72 -0
  23. data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
  24. data/lib/whirled_peas/graphics/container_painter.rb +272 -0
  25. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  26. data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
  27. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  28. data/lib/whirled_peas/graphics/painter.rb +23 -0
  29. data/lib/whirled_peas/graphics/renderer.rb +26 -0
  30. data/lib/whirled_peas/graphics/screen.rb +70 -0
  31. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  32. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  33. data/lib/whirled_peas/settings.rb +5 -0
  34. data/lib/whirled_peas/settings/alignment.rb +24 -0
  35. data/lib/whirled_peas/settings/bg_color.rb +24 -0
  36. data/lib/whirled_peas/settings/border.rb +101 -0
  37. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  38. data/lib/whirled_peas/settings/color.rb +68 -0
  39. data/lib/whirled_peas/settings/container_settings.rb +223 -0
  40. data/lib/whirled_peas/settings/debugger.rb +96 -0
  41. data/lib/whirled_peas/settings/display_flow.rb +27 -0
  42. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  43. data/lib/whirled_peas/settings/grid_settings.rb +19 -0
  44. data/lib/whirled_peas/settings/margin.rb +8 -0
  45. data/lib/whirled_peas/settings/padding.rb +8 -0
  46. data/lib/whirled_peas/settings/position.rb +15 -0
  47. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  48. data/lib/whirled_peas/settings/sizing.rb +19 -0
  49. data/lib/whirled_peas/settings/spacing.rb +58 -0
  50. data/lib/whirled_peas/settings/text_color.rb +21 -0
  51. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  52. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  53. data/lib/whirled_peas/utils.rb +5 -0
  54. data/lib/whirled_peas/utils/ansi.rb +53 -0
  55. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  56. data/lib/whirled_peas/utils/title_font.rb +75 -0
  57. data/lib/whirled_peas/version.rb +1 -1
  58. data/screen_test/elements/box.frame +1 -0
  59. data/screen_test/elements/box.rb +20 -0
  60. data/screen_test/elements/grid.frame +1 -0
  61. data/screen_test/elements/grid.rb +13 -0
  62. data/screen_test/elements/screen_overflow_x.frame +1 -0
  63. data/screen_test/elements/screen_overflow_x.rb +9 -0
  64. data/screen_test/elements/screen_overflow_y.frame +1 -0
  65. data/screen_test/elements/screen_overflow_y.rb +9 -0
  66. data/screen_test/elements/text.frame +1 -0
  67. data/screen_test/elements/text.rb +9 -0
  68. data/screen_test/elements/text_multiline.frame +1 -0
  69. data/screen_test/elements/text_multiline.rb +9 -0
  70. data/screen_test/settings/align/box_around.frame +1 -0
  71. data/screen_test/settings/align/box_around.rb +16 -0
  72. data/screen_test/settings/align/box_between.frame +1 -0
  73. data/screen_test/settings/align/box_between.rb +16 -0
  74. data/screen_test/settings/align/box_center.frame +1 -0
  75. data/screen_test/settings/align/box_center.rb +21 -0
  76. data/screen_test/settings/align/box_default.frame +1 -0
  77. data/screen_test/settings/align/box_default.rb +20 -0
  78. data/screen_test/settings/align/box_evenly.frame +1 -0
  79. data/screen_test/settings/align/box_evenly.rb +16 -0
  80. data/screen_test/settings/align/box_left.frame +1 -0
  81. data/screen_test/settings/align/box_left.rb +21 -0
  82. data/screen_test/settings/align/box_right.frame +1 -0
  83. data/screen_test/settings/align/box_right.rb +21 -0
  84. data/screen_test/settings/align/children_center.frame +1 -0
  85. data/screen_test/settings/align/children_center.rb +15 -0
  86. data/screen_test/settings/align/children_left.frame +1 -0
  87. data/screen_test/settings/align/children_left.rb +15 -0
  88. data/screen_test/settings/align/children_right.frame +1 -0
  89. data/screen_test/settings/align/children_right.rb +15 -0
  90. data/screen_test/settings/align/grid_center.frame +1 -0
  91. data/screen_test/settings/align/grid_center.rb +18 -0
  92. data/screen_test/settings/align/grid_default.frame +1 -0
  93. data/screen_test/settings/align/grid_default.rb +17 -0
  94. data/screen_test/settings/align/grid_left.frame +1 -0
  95. data/screen_test/settings/align/grid_left.rb +18 -0
  96. data/screen_test/settings/align/grid_right.frame +1 -0
  97. data/screen_test/settings/align/grid_right.rb +18 -0
  98. data/screen_test/settings/ansi/bold.frame +1 -0
  99. data/screen_test/settings/ansi/bold.rb +14 -0
  100. data/screen_test/settings/ansi/color.frame +1 -0
  101. data/screen_test/settings/ansi/color.rb +37 -0
  102. data/screen_test/settings/ansi/underline.frame +1 -0
  103. data/screen_test/settings/ansi/underline.rb +14 -0
  104. data/screen_test/settings/border.frame +1 -0
  105. data/screen_test/settings/border.rb +13 -0
  106. data/screen_test/settings/flow/box_b2t.frame +1 -0
  107. data/screen_test/settings/flow/box_b2t.rb +26 -0
  108. data/screen_test/settings/flow/box_l2r.frame +1 -0
  109. data/screen_test/settings/flow/box_l2r.rb +26 -0
  110. data/screen_test/settings/flow/box_r2l.frame +1 -0
  111. data/screen_test/settings/flow/box_r2l.rb +26 -0
  112. data/screen_test/settings/flow/box_t2b.frame +1 -0
  113. data/screen_test/settings/flow/box_t2b.rb +26 -0
  114. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  115. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  116. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  117. data/screen_test/settings/flow/grid_l2r.rb +14 -0
  118. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  119. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  120. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  121. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  122. data/screen_test/settings/height/box.frame +1 -0
  123. data/screen_test/settings/height/box.rb +13 -0
  124. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  125. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  126. data/screen_test/settings/height/grid.frame +1 -0
  127. data/screen_test/settings/height/grid.rb +14 -0
  128. data/screen_test/settings/height/overflow_box.frame +1 -0
  129. data/screen_test/settings/height/overflow_box.rb +13 -0
  130. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  131. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  132. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  133. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  134. data/screen_test/settings/height/overflow_grid.frame +1 -0
  135. data/screen_test/settings/height/overflow_grid.rb +16 -0
  136. data/screen_test/settings/margin.frame +1 -0
  137. data/screen_test/settings/margin.rb +16 -0
  138. data/screen_test/settings/padding.frame +1 -0
  139. data/screen_test/settings/padding.rb +13 -0
  140. data/screen_test/settings/position/box_left.frame +1 -0
  141. data/screen_test/settings/position/box_left.rb +17 -0
  142. data/screen_test/settings/position/box_left_negative.frame +1 -0
  143. data/screen_test/settings/position/box_left_negative.rb +17 -0
  144. data/screen_test/settings/position/box_top.frame +1 -0
  145. data/screen_test/settings/position/box_top.rb +17 -0
  146. data/screen_test/settings/position/box_top_negative.frame +1 -0
  147. data/screen_test/settings/position/box_top_negative.rb +17 -0
  148. data/screen_test/settings/position/grid_left.frame +1 -0
  149. data/screen_test/settings/position/grid_left.rb +18 -0
  150. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  151. data/screen_test/settings/position/grid_left_negative.rb +18 -0
  152. data/screen_test/settings/position/grid_top.frame +1 -0
  153. data/screen_test/settings/position/grid_top.rb +18 -0
  154. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  155. data/screen_test/settings/position/grid_top_negative.rb +18 -0
  156. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  157. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  158. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  159. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  160. data/screen_test/settings/scroll/vert_box.frame +1 -0
  161. data/screen_test/settings/scroll/vert_box.rb +20 -0
  162. data/screen_test/settings/title_font.frame +1 -0
  163. data/screen_test/settings/title_font.rb +12 -0
  164. data/screen_test/settings/valign/box_around.frame +1 -0
  165. data/screen_test/settings/valign/box_around.rb +17 -0
  166. data/screen_test/settings/valign/box_between.frame +1 -0
  167. data/screen_test/settings/valign/box_between.rb +17 -0
  168. data/screen_test/settings/valign/box_bottom.frame +1 -0
  169. data/screen_test/settings/valign/box_bottom.rb +17 -0
  170. data/screen_test/settings/valign/box_default.frame +1 -0
  171. data/screen_test/settings/valign/box_default.rb +16 -0
  172. data/screen_test/settings/valign/box_evenly.frame +1 -0
  173. data/screen_test/settings/valign/box_evenly.rb +17 -0
  174. data/screen_test/settings/valign/box_middle.frame +1 -0
  175. data/screen_test/settings/valign/box_middle.rb +17 -0
  176. data/screen_test/settings/valign/box_top.frame +1 -0
  177. data/screen_test/settings/valign/box_top.rb +17 -0
  178. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  179. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  180. data/screen_test/settings/valign/grid_default.frame +1 -0
  181. data/screen_test/settings/valign/grid_default.rb +14 -0
  182. data/screen_test/settings/valign/grid_middle.frame +1 -0
  183. data/screen_test/settings/valign/grid_middle.rb +15 -0
  184. data/screen_test/settings/valign/grid_top.frame +1 -0
  185. data/screen_test/settings/valign/grid_top.rb +15 -0
  186. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  187. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  188. data/screen_test/settings/width/box_content.frame +1 -0
  189. data/screen_test/settings/width/box_content.rb +15 -0
  190. data/screen_test/settings/width/box_default.frame +1 -0
  191. data/screen_test/settings/width/box_default.rb +14 -0
  192. data/screen_test/settings/width/grid.frame +1 -0
  193. data/screen_test/settings/width/grid.rb +14 -0
  194. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  195. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  196. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  197. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  198. data/screen_test/settings/width/overflow_box.frame +1 -0
  199. data/screen_test/settings/width/overflow_box.rb +13 -0
  200. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  201. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  202. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  203. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  204. data/screen_test/settings/width/overflow_grid.frame +1 -0
  205. data/screen_test/settings/width/overflow_grid.rb +14 -0
  206. data/tools/whirled_peas/tools/screen_tester.rb +233 -0
  207. data/whirled_peas.gemspec +4 -1
  208. metadata +215 -17
  209. data/lib/whirled_peas/ui.rb +0 -7
  210. data/lib/whirled_peas/ui/ansi.rb +0 -103
  211. data/lib/whirled_peas/ui/canvas.rb +0 -68
  212. data/lib/whirled_peas/ui/color.rb +0 -101
  213. data/lib/whirled_peas/ui/element.rb +0 -224
  214. data/lib/whirled_peas/ui/painter.rb +0 -283
  215. data/lib/whirled_peas/ui/screen.rb +0 -60
  216. data/lib/whirled_peas/ui/settings.rb +0 -523
  217. data/sandbox/auto.rb +0 -13
  218. data/sandbox/box.rb +0 -19
  219. data/sandbox/grid.rb +0 -13
  220. data/sandbox/sandbox.rb +0 -17
  221. data/sandbox/text.rb +0 -33
@@ -1,60 +0,0 @@
1
- require 'highline'
2
-
3
- require_relative 'ansi'
4
- require_relative 'painter'
5
-
6
- module WhirledPeas
7
- module UI
8
- class Screen
9
- def initialize(print_output=true)
10
- @print_output = print_output
11
- @terminal = HighLine.new.terminal
12
- @strokes = []
13
- refresh_size!
14
- Signal.trap('SIGWINCH', proc { self.refresh_size! })
15
- end
16
-
17
- def paint(template)
18
- @template = template
19
- refresh
20
- end
21
-
22
- def needs_refresh?
23
- @refreshed_width != width || @refreshed_height != height
24
- end
25
-
26
- def refresh
27
- strokes = [Ansi.cursor_visible(false), Ansi.cursor_pos, Ansi.clear_down]
28
- Painter.paint(@template, Canvas.new(0, 0, width, height)) do |stroke|
29
- unless stroke.chars.nil?
30
- strokes << Ansi.cursor_pos(left: stroke.left, top: stroke.top)
31
- strokes << stroke.chars
32
- end
33
- end
34
- return unless @print_output
35
- strokes.each(&method(:print))
36
- STDOUT.flush
37
- @refreshed_width = width
38
- @refreshed_height = height
39
- end
40
-
41
- def finalize
42
- return unless @print_output
43
- print Ansi.clear
44
- print Ansi.cursor_pos(top: height - 1)
45
- print Ansi.cursor_visible(true)
46
- STDOUT.flush
47
- end
48
-
49
- protected
50
-
51
- def refresh_size!
52
- @width, @height = terminal.terminal_size
53
- end
54
-
55
- private
56
-
57
- attr_reader :cursor, :terminal, :width, :height
58
- end
59
- end
60
- end
@@ -1,523 +0,0 @@
1
- require 'json'
2
-
3
- require_relative 'color'
4
-
5
- module WhirledPeas
6
- module UI
7
- module TextAlign
8
- LEFT = :left
9
- CENTER = :center
10
- RIGHT = :right
11
-
12
- def self.validate!(align)
13
- return unless align
14
- if [TextAlign::LEFT, TextAlign::CENTER, TextAlign::RIGHT].include?(align)
15
- align
16
- else
17
- raise ArgumentError, "Invalid alignment: #{align}"
18
- end
19
- end
20
- end
21
-
22
- module DisplayFlow
23
- LEFT_TO_RIGHT = :l2r
24
- RIGHT_TO_LEFT = :r2l
25
- TOP_TO_BOTTOM = :t2b
26
- BOTTOM_TO_TOP = :b2t
27
-
28
- def self.validate!(flow)
29
- return unless flow
30
- if [
31
- DisplayFlow::LEFT_TO_RIGHT,
32
- DisplayFlow::RIGHT_TO_LEFT,
33
- DisplayFlow::TOP_TO_BOTTOM,
34
- DisplayFlow::BOTTOM_TO_TOP
35
- ].include?(flow)
36
- flow
37
- else
38
- raise ArgumentError, "Invalid flow: #{flow}"
39
- end
40
- end
41
- end
42
-
43
- class Spacing
44
- def left
45
- @_left || 0
46
- end
47
-
48
- def left=(val)
49
- @_left = val
50
- end
51
-
52
- def top
53
- @_top || 0
54
- end
55
-
56
- def top=(val)
57
- @_top = val
58
- end
59
-
60
- def right
61
- @_right || 0
62
- end
63
-
64
- def right=(val)
65
- @_right = val
66
- end
67
-
68
- def bottom
69
- @_bottom || 0
70
- end
71
-
72
- def bottom=(val)
73
- @_bottom = val
74
- end
75
-
76
- def merge(parent)
77
- merged = Spacing.new
78
- merged._left = @_left || parent._left
79
- merged._top = @_top || parent._top
80
- merged._right = @_right || parent._right
81
- merged._bottom = @_bottom || parent._bottom
82
- merged
83
- end
84
-
85
- def inspect
86
- vals = {}
87
- vals[:left] = @_left if @_left
88
- vals[:top] = @_top if @_top
89
- vals[:right] = @_right if @_right
90
- vals[:bottom] = @_bottom if @_bottom
91
- JSON.generate(vals) if vals.any?
92
- end
93
-
94
- protected
95
-
96
- attr_accessor :_left, :_top, :_right, :_bottom
97
- end
98
- private_constant :Spacing
99
-
100
- class Padding < Spacing
101
- end
102
-
103
- class Margin < Spacing
104
- end
105
-
106
- BorderStyle = Struct.new(
107
- :top_left, :top_horiz, :top_junc, :top_right,
108
- :left_vert, :left_junc,
109
- :middle_vert, :cross_junc, :middle_horiz,
110
- :right_vert, :right_junc,
111
- :bottom_left, :bottom_horiz, :bottom_junc, :bottom_right
112
- )
113
-
114
- module BorderStyles
115
- BOLD = BorderStyle.new(
116
- '┏', '━', '┳', '┓',
117
- '┃', '┣',
118
- '┃', '╋', '━',
119
- '┃', '┫',
120
- '┗', '━', '┻', '┛'
121
- )
122
- SOFT = BorderStyle.new(
123
- '╭', '─', '┬', '╮',
124
- '│', '├',
125
- '│', '┼', '─',
126
- '│', '┤',
127
- '╰', '─', '┴', '╯'
128
- )
129
- DOUBLE = BorderStyle.new(
130
- '╔', '═', '╦', '╗',
131
- '║', '╠',
132
- '║', '╬', '═',
133
- '║', '╣',
134
- '╚', '═', '╩', '╝'
135
- )
136
-
137
- def self.validate!(style)
138
- return unless style
139
- if style.is_a?(Symbol)
140
- error_message = "Unsupported border style: #{style}"
141
- begin
142
- style = self.const_get(style.upcase)
143
- raise ArgumentError, error_message unless style.is_a?(BorderStyle)
144
- style
145
- rescue NameError
146
- raise ArgumentError, error_message
147
- end
148
- else
149
- style
150
- end
151
- end
152
- end
153
-
154
- class Border
155
- def left?
156
- @_left == true
157
- end
158
-
159
- def left=(val)
160
- @_left = val
161
- end
162
-
163
- def top?
164
- @_top == true
165
- end
166
-
167
- def top=(val)
168
- @_top = val
169
- end
170
-
171
- def right?
172
- @_right == true
173
- end
174
-
175
- def right=(val)
176
- @_right = val
177
- end
178
-
179
- def bottom?
180
- @_bottom == true
181
- end
182
-
183
- def bottom=(val)
184
- @_bottom = val
185
- end
186
-
187
- def inner_horiz?
188
- @_inner_horiz == true
189
- end
190
-
191
- def inner_horiz=(val)
192
- @_inner_horiz = val
193
- end
194
-
195
- def inner_vert?
196
- @_inner_vert == true
197
- end
198
-
199
- def inner_vert=(val)
200
- @_inner_vert = val
201
- end
202
-
203
- def style
204
- @_style || BorderStyles::BOLD
205
- end
206
-
207
- def style=(val)
208
- @_style = BorderStyles.validate!(val)
209
- end
210
-
211
- def color
212
- @_color || TextColor::WHITE
213
- end
214
-
215
- def color=(val)
216
- @_color = TextColor.validate!(val)
217
- end
218
-
219
- def merge(parent)
220
- merged = Border.new
221
- merged._left = @_left.nil? ? parent._left : @_left
222
- merged._top = @_top.nil? ? parent._top : @_top
223
- merged._right = @_right.nil? ? parent._right : @_right
224
- merged._bottom = @_bottom.nil? ? parent._bottom : @_bottom
225
- merged._inner_horiz = @_inner_horiz.nil? ? parent._inner_horiz : @_inner_horiz
226
- merged._inner_vert = @_inner_vert.nil? ? parent._inner_vert : @_inner_vert
227
- merged._style = @_style || parent._style
228
- merged._color = @_color || parent._color
229
- merged
230
- end
231
-
232
- def inspect
233
- vals = {}
234
- vals[:left] = @_left unless @_left.nil?
235
- vals[:top] = @_top unless @_top.nil?
236
- vals[:right] = @_right unless @_right.nil?
237
- vals[:bottom] = @_bottom unless @_bottom.nil?
238
- vals[:inner_horiz] = @_inner_horiz unless @_inner_horiz.nil?
239
- vals[:inner_vert] = @_inner_vert unless @_inner_vert.nil?
240
- JSON.generate(vals) if vals.any?
241
- end
242
-
243
- protected
244
-
245
- attr_accessor :_left, :_top, :_right, :_bottom, :_inner_horiz, :_inner_vert, :_style, :_color
246
- end
247
-
248
- class ElementSettings
249
- def self.merge(parent)
250
- self.new.merge(parent)
251
- end
252
-
253
- def color
254
- @_color
255
- end
256
-
257
- def color=(color)
258
- @_color = TextColor.validate!(color)
259
- end
260
-
261
- def bg_color
262
- @_bg_color
263
- end
264
-
265
- def bg_color=(color)
266
- @_bg_color = BgColor.validate!(color)
267
- end
268
-
269
- def bold?
270
- @_bold || false
271
- end
272
-
273
- def bold=(val)
274
- @_bold = val
275
- end
276
-
277
- def underline?
278
- @_underline || false
279
- end
280
-
281
- def underline=(val)
282
- @_underline = val
283
- end
284
-
285
- def merge(parent)
286
- merged = self.class.new
287
- merged.color = @color || parent.color
288
- merged.bg_color = @bg_color || parent.bg_color
289
- merged._bold = @_bold.nil? ? parent._bold : @_bold
290
- merged._underline = @_underline.nil? ? parent._underline : @_underline
291
- merged
292
- end
293
-
294
- def inspect(indent='')
295
- values = self.instance_variables.map do |v|
296
- unless instance_variable_get(v).nil? || instance_variable_get(v).inspect.nil?
297
- "#{indent} #{v} = #{instance_variable_get(v).inspect}"
298
- end
299
- end.compact
300
- details = values.length > 0 ? values.join("\n") : "#{indent} <default>"
301
- "#{indent}#{self.class.name}\n#{details}"
302
- end
303
-
304
- protected
305
-
306
- attr_accessor :_bold, :_underline
307
- end
308
- private_constant :ElementSettings
309
-
310
- module WidthSettings
311
- attr_accessor :width
312
- end
313
-
314
- module AlignSettings
315
- def align
316
- @_align || TextAlign::LEFT
317
- end
318
-
319
- def align=(align)
320
- @_align = TextAlign.validate!(align)
321
- end
322
-
323
- def merge(parent)
324
- merged = super
325
- merged._align = if @_align
326
- @_align
327
- elsif parent.is_a?(AlignSettings)
328
- parent._align
329
- end
330
- merged
331
- end
332
-
333
- protected
334
-
335
- attr_accessor :_align
336
- end
337
-
338
- module MarginSettings
339
- def set_margin(left: nil, top: nil, right: nil, bottom: nil)
340
- @_margin = Margin.new unless @_margin
341
- @_margin.left = left if left
342
- @_margin.top = top if top
343
- @_margin.right = right if right
344
- @_margin.bottom = bottom if bottom
345
- end
346
-
347
- def clear_margin
348
- set_margin(left: 0, top: 0, right: 0, bottom: 0)
349
- @_auto_margin = nil
350
- end
351
-
352
- def margin
353
- @_margin || Margin.new
354
- end
355
-
356
- def auto_margin=(val)
357
- @_auto_margin = val
358
- end
359
-
360
- def auto_margin?
361
- @_auto_margin || false
362
- end
363
-
364
- def merge(parent)
365
- merged = super
366
- if parent.is_a?(MarginSettings)
367
- merged._margin = margin.merge(parent.margin)
368
- merged._auto_margin = @_auto_margin.nil? ? parent._auto_margin : @_auto_margin
369
- else
370
- merged._margin = _margin
371
- merged._auto_margin = @_auto_margin
372
- end
373
- merged
374
- end
375
-
376
- protected
377
-
378
- attr_accessor :_margin, :_auto_margin
379
- end
380
- private_constant :MarginSettings
381
-
382
- module BorderSettings
383
- def set_border(
384
- left: nil, top: nil, right: nil, bottom: nil, inner_horiz: nil, inner_vert: nil, style: nil, color: nil
385
- )
386
- @_border = Border.new unless @_border
387
- @_border.left = left unless left.nil?
388
- @_border.top = top unless top.nil?
389
- @_border.right = right unless right.nil?
390
- @_border.bottom = bottom unless bottom.nil?
391
- @_border.inner_horiz = inner_horiz unless inner_horiz.nil?
392
- @_border.inner_vert = inner_vert unless inner_vert.nil?
393
- @_border.style = style unless style.nil?
394
- @_border.color = color unless color.nil?
395
- end
396
-
397
- def clear_border
398
- set_border(
399
- left: false, top: false, right: false, bottom: false, inner_horiz: false, inner_vert: false
400
- )
401
- end
402
-
403
- def full_border(style: nil, color: nil)
404
- set_border(
405
- left: true, top: true, right: true, bottom: true, inner_horiz: true, inner_vert: true, style: style, color: color
406
- )
407
- end
408
-
409
- def border
410
- @_border || Border.new
411
- end
412
-
413
- def merge(parent)
414
- merged = super
415
- merged._border = parent.is_a?(BorderSettings) ? border.merge(parent.border) : _border
416
- merged
417
- end
418
-
419
- protected
420
-
421
- attr_accessor :_border
422
- end
423
- private_constant :BorderSettings
424
-
425
- module PaddingSettings
426
- def set_padding(left: nil, top: nil, right: nil, bottom: nil)
427
- @_padding = Padding.new unless @_padding
428
- @_padding.left = left if left
429
- @_padding.top = top if top
430
- @_padding.right = right if right
431
- @_padding.bottom = bottom if bottom
432
- end
433
-
434
- def clear_padding
435
- set_padding(left: 0, top: 0, right: 0, bottom: 0)
436
- end
437
-
438
- def padding
439
- @_padding || Padding.new
440
- end
441
-
442
- def merge(parent)
443
- merged = super
444
- merged._padding = parent.is_a?(PaddingSettings) ? padding.merge(parent.padding) : _padding
445
- merged
446
- end
447
-
448
- protected
449
-
450
- attr_accessor :_padding
451
- end
452
- private_constant :PaddingSettings
453
-
454
- class TemplateSettings < ElementSettings
455
- end
456
-
457
- class TextSettings < ElementSettings
458
- include WidthSettings
459
- include AlignSettings
460
- end
461
-
462
- class ContainerSettings < ElementSettings
463
- include MarginSettings
464
- include BorderSettings
465
- include PaddingSettings
466
- end
467
-
468
- class BoxSettings < ContainerSettings
469
- include WidthSettings
470
- include AlignSettings
471
-
472
- def flow=(flow)
473
- @_flow = DisplayFlow.validate!(flow)
474
- end
475
-
476
- def flow
477
- @_flow || DisplayFlow::LEFT_TO_RIGHT
478
- end
479
-
480
- def horizontal_flow?
481
- %i[l2r r2l].include?(flow)
482
- end
483
-
484
- def vertical_flow?
485
- !horizontal_flow?
486
- end
487
-
488
- def forward_flow?
489
- %i[l2r t2b].include?(flow)
490
- end
491
-
492
- def reverse_flow?
493
- !forward_flow?
494
- end
495
-
496
- def merge(parent)
497
- merged = super
498
- merged._flow = if @_flow
499
- @_flow
500
- elsif parent.is_a?(BoxSettings)
501
- parent._flow
502
- end
503
- merged
504
- end
505
-
506
- protected
507
-
508
- attr_accessor :_flow
509
- end
510
-
511
- class GridSettings < ContainerSettings
512
- include WidthSettings
513
- include AlignSettings
514
-
515
- attr_accessor :num_cols
516
- attr_writer :transpose
517
-
518
- def transpose?
519
- @transpose || false
520
- end
521
- end
522
- end
523
- end