whirled_peas 0.2.0 → 0.6.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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -0
  3. data/CHANGELOG.md +38 -0
  4. data/Gemfile +1 -0
  5. data/README.md +275 -81
  6. data/Rakefile +38 -3
  7. data/examples/intro.rb +52 -0
  8. data/examples/scrolling.rb +53 -0
  9. data/exe/whirled_peas +7 -0
  10. data/lib/whirled_peas.rb +12 -42
  11. data/lib/whirled_peas/command_line.rb +255 -0
  12. data/lib/whirled_peas/config.rb +21 -0
  13. data/lib/whirled_peas/errors.rb +7 -0
  14. data/lib/whirled_peas/frame.rb +0 -8
  15. data/lib/whirled_peas/frame/consumer.rb +14 -50
  16. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  17. data/lib/whirled_peas/frame/event_loop.rb +68 -38
  18. data/lib/whirled_peas/frame/producer.rb +36 -32
  19. data/lib/whirled_peas/graphics.rb +5 -0
  20. data/lib/whirled_peas/graphics/box_painter.rb +108 -0
  21. data/lib/whirled_peas/graphics/canvas.rb +107 -0
  22. data/lib/whirled_peas/graphics/composer.rb +80 -0
  23. data/lib/whirled_peas/graphics/container_coords.rb +71 -0
  24. data/lib/whirled_peas/graphics/container_dimensions.rb +75 -0
  25. data/lib/whirled_peas/graphics/container_painter.rb +234 -0
  26. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  27. data/lib/whirled_peas/graphics/grid_painter.rb +68 -0
  28. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  29. data/lib/whirled_peas/graphics/painter.rb +19 -0
  30. data/lib/whirled_peas/graphics/renderer.rb +21 -0
  31. data/lib/whirled_peas/graphics/screen.rb +70 -0
  32. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  33. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  34. data/lib/whirled_peas/settings.rb +5 -0
  35. data/lib/whirled_peas/settings/bg_color.rb +22 -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 +69 -0
  39. data/lib/whirled_peas/settings/container_settings.rb +139 -0
  40. data/lib/whirled_peas/settings/debugger.rb +96 -0
  41. data/lib/whirled_peas/settings/display_flow.rb +25 -0
  42. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  43. data/lib/whirled_peas/settings/grid_settings.rb +15 -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/spacing.rb +24 -0
  49. data/lib/whirled_peas/settings/text_align.rb +19 -0
  50. data/lib/whirled_peas/settings/text_color.rb +19 -0
  51. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  52. data/lib/whirled_peas/utils.rb +5 -0
  53. data/lib/whirled_peas/utils/ansi.rb +53 -0
  54. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  55. data/lib/whirled_peas/utils/title_font.rb +75 -0
  56. data/lib/whirled_peas/version.rb +1 -1
  57. data/screen_test/rendered/elements/box.frame +1 -0
  58. data/screen_test/rendered/elements/box.rb +20 -0
  59. data/screen_test/rendered/elements/grid.frame +1 -0
  60. data/screen_test/rendered/elements/grid.rb +13 -0
  61. data/screen_test/rendered/elements/screen_overflow.frame +1 -0
  62. data/screen_test/rendered/elements/screen_overflow.rb +9 -0
  63. data/screen_test/rendered/elements/text.frame +1 -0
  64. data/screen_test/rendered/elements/text.rb +9 -0
  65. data/screen_test/rendered/elements/text_multiline.frame +1 -0
  66. data/screen_test/rendered/elements/text_multiline.rb +9 -0
  67. data/screen_test/rendered/settings/align/box.frame +1 -0
  68. data/screen_test/rendered/settings/align/box.rb +24 -0
  69. data/screen_test/rendered/settings/align/children_center.frame +1 -0
  70. data/screen_test/rendered/settings/align/children_center.rb +13 -0
  71. data/screen_test/rendered/settings/align/children_left.frame +1 -0
  72. data/screen_test/rendered/settings/align/children_left.rb +13 -0
  73. data/screen_test/rendered/settings/align/children_right.frame +1 -0
  74. data/screen_test/rendered/settings/align/children_right.rb +13 -0
  75. data/screen_test/rendered/settings/align/grid.frame +1 -0
  76. data/screen_test/rendered/settings/align/grid.rb +20 -0
  77. data/screen_test/rendered/settings/ansi/bold.frame +1 -0
  78. data/screen_test/rendered/settings/ansi/bold.rb +15 -0
  79. data/screen_test/rendered/settings/ansi/color.frame +1 -0
  80. data/screen_test/rendered/settings/ansi/color.rb +37 -0
  81. data/screen_test/rendered/settings/ansi/underline.frame +1 -0
  82. data/screen_test/rendered/settings/ansi/underline.rb +15 -0
  83. data/screen_test/rendered/settings/border.frame +1 -0
  84. data/screen_test/rendered/settings/border.rb +13 -0
  85. data/screen_test/rendered/settings/flow/box_b2t.frame +1 -0
  86. data/screen_test/rendered/settings/flow/box_b2t.rb +24 -0
  87. data/screen_test/rendered/settings/flow/box_l2r.frame +1 -0
  88. data/screen_test/rendered/settings/flow/box_l2r.rb +24 -0
  89. data/screen_test/rendered/settings/flow/box_r2l.frame +1 -0
  90. data/screen_test/rendered/settings/flow/box_r2l.rb +24 -0
  91. data/screen_test/rendered/settings/flow/box_t2b.frame +1 -0
  92. data/screen_test/rendered/settings/flow/box_t2b.rb +24 -0
  93. data/screen_test/rendered/settings/flow/grid_b2t.frame +1 -0
  94. data/screen_test/rendered/settings/flow/grid_b2t.rb +14 -0
  95. data/screen_test/rendered/settings/flow/grid_l2r.frame +1 -0
  96. data/screen_test/rendered/settings/flow/grid_l2r.rb +14 -0
  97. data/screen_test/rendered/settings/flow/grid_r2l.frame +1 -0
  98. data/screen_test/rendered/settings/flow/grid_r2l.rb +14 -0
  99. data/screen_test/rendered/settings/flow/grid_t2b.frame +1 -0
  100. data/screen_test/rendered/settings/flow/grid_t2b.rb +14 -0
  101. data/screen_test/rendered/settings/height/box.frame +1 -0
  102. data/screen_test/rendered/settings/height/box.rb +13 -0
  103. data/screen_test/rendered/settings/height/grid.frame +1 -0
  104. data/screen_test/rendered/settings/height/grid.rb +14 -0
  105. data/screen_test/rendered/settings/height/overflow_box.frame +1 -0
  106. data/screen_test/rendered/settings/height/overflow_box.rb +13 -0
  107. data/screen_test/rendered/settings/height/overflow_box_l2r.frame +1 -0
  108. data/screen_test/rendered/settings/height/overflow_box_l2r.rb +15 -0
  109. data/screen_test/rendered/settings/height/overflow_box_t2b.frame +1 -0
  110. data/screen_test/rendered/settings/height/overflow_box_t2b.rb +14 -0
  111. data/screen_test/rendered/settings/height/overflow_grid.frame +1 -0
  112. data/screen_test/rendered/settings/height/overflow_grid.rb +16 -0
  113. data/screen_test/rendered/settings/margin.frame +1 -0
  114. data/screen_test/rendered/settings/margin.rb +14 -0
  115. data/screen_test/rendered/settings/padding.frame +1 -0
  116. data/screen_test/rendered/settings/padding.rb +11 -0
  117. data/screen_test/rendered/settings/position/box_left.frame +1 -0
  118. data/screen_test/rendered/settings/position/box_left.rb +17 -0
  119. data/screen_test/rendered/settings/position/box_left_negative.frame +1 -0
  120. data/screen_test/rendered/settings/position/box_left_negative.rb +17 -0
  121. data/screen_test/rendered/settings/position/box_top.frame +1 -0
  122. data/screen_test/rendered/settings/position/box_top.rb +17 -0
  123. data/screen_test/rendered/settings/position/box_top_negative.frame +1 -0
  124. data/screen_test/rendered/settings/position/box_top_negative.rb +17 -0
  125. data/screen_test/rendered/settings/position/grid_left.frame +1 -0
  126. data/screen_test/rendered/settings/position/grid_left.rb +18 -0
  127. data/screen_test/rendered/settings/position/grid_left_negative.frame +1 -0
  128. data/screen_test/rendered/settings/position/grid_left_negative.rb +18 -0
  129. data/screen_test/rendered/settings/position/grid_top.frame +1 -0
  130. data/screen_test/rendered/settings/position/grid_top.rb +18 -0
  131. data/screen_test/rendered/settings/position/grid_top_negative.frame +1 -0
  132. data/screen_test/rendered/settings/position/grid_top_negative.rb +18 -0
  133. data/screen_test/rendered/settings/scroll/horiz_box.frame +1 -0
  134. data/screen_test/rendered/settings/scroll/horiz_box.rb +15 -0
  135. data/screen_test/rendered/settings/scroll/vert_box.frame +1 -0
  136. data/screen_test/rendered/settings/scroll/vert_box.rb +18 -0
  137. data/screen_test/rendered/settings/title_font.frame +1 -0
  138. data/screen_test/rendered/settings/title_font.rb +12 -0
  139. data/screen_test/rendered/settings/width/box.frame +1 -0
  140. data/screen_test/rendered/settings/width/box.rb +13 -0
  141. data/screen_test/rendered/settings/width/grid.frame +1 -0
  142. data/screen_test/rendered/settings/width/grid.rb +14 -0
  143. data/screen_test/rendered/settings/width/overflow_box.frame +1 -0
  144. data/screen_test/rendered/settings/width/overflow_box.rb +11 -0
  145. data/screen_test/rendered/settings/width/overflow_box_l2r.frame +1 -0
  146. data/screen_test/rendered/settings/width/overflow_box_l2r.rb +14 -0
  147. data/screen_test/rendered/settings/width/overflow_box_t2b.frame +1 -0
  148. data/screen_test/rendered/settings/width/overflow_box_t2b.rb +15 -0
  149. data/screen_test/rendered/settings/width/overflow_grid.frame +1 -0
  150. data/screen_test/rendered/settings/width/overflow_grid.rb +14 -0
  151. data/screen_test/screen_tester.rb +201 -0
  152. data/whirled_peas.gemspec +4 -2
  153. metadata +147 -20
  154. data/lib/whirled_peas/ui.rb +0 -7
  155. data/lib/whirled_peas/ui/ansi.rb +0 -154
  156. data/lib/whirled_peas/ui/canvas.rb +0 -35
  157. data/lib/whirled_peas/ui/element.rb +0 -225
  158. data/lib/whirled_peas/ui/painter.rb +0 -283
  159. data/lib/whirled_peas/ui/screen.rb +0 -62
  160. data/lib/whirled_peas/ui/settings.rb +0 -521
  161. data/lib/whirled_peas/ui/stroke.rb +0 -29
  162. data/sandbox/auto.rb +0 -13
  163. data/sandbox/box.rb +0 -19
  164. data/sandbox/grid.rb +0 -13
  165. data/sandbox/sandbox.rb +0 -17
  166. data/sandbox/text.rb +0 -33
@@ -0,0 +1,8 @@
1
+ require_relative 'container_settings'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ class BoxSettings < ContainerSettings
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,69 @@
1
+ require 'whirled_peas/utils/ansi'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ # An abstract class that encapsulates colors for a specific use case
6
+ class Color
7
+ # Validate the `color` argument is either (1) nil, (2) a valid Color constant in
8
+ # this class or (3) a symbol that maps to valid Color constant. E.g. if there
9
+ # is a RED constant in an implementing class, then :red or :bright_red are
10
+ # valid values for `color`
11
+ #
12
+ # @param color [Color|Symbol]
13
+ # @return [Color|Symbol] the value passed in if valid, otherwise an ArgumentError
14
+ # is raised.
15
+ def self.validate!(color)
16
+ return unless color
17
+ if color.is_a?(Symbol)
18
+ error_message = "Unsupported #{self.name.split('::').last}: #{color.inspect}"
19
+ match = color.to_s.match(/^(bright_)?(\w+)$/)
20
+ begin
21
+ color = self.const_get(match[2].upcase)
22
+ raise ArgumentError, error_message unless color.is_a?(Color)
23
+ if match[1]
24
+ raise ArgumentError, error_message if color.bright?
25
+ color.bright
26
+ else
27
+ color
28
+ end
29
+ rescue NameError
30
+ raise ArgumentError, error_message
31
+ end
32
+ else
33
+ color
34
+ end
35
+ end
36
+
37
+ def initialize(code, bright=false)
38
+ @code = code
39
+ @bright = bright
40
+ end
41
+
42
+ def bright?
43
+ @bright
44
+ end
45
+
46
+ def bright
47
+ bright? ? self : self.class.new(@code + Utils::Ansi::BRIGHT_OFFSET, true)
48
+ end
49
+
50
+ def hash
51
+ [@code, @bright].hash
52
+ end
53
+
54
+ def ==(other)
55
+ other.is_a?(self.class) && self.hash == other.hash
56
+ end
57
+ alias_method :eq?, :==
58
+
59
+ def to_s
60
+ @code.to_s
61
+ end
62
+
63
+ def inspect
64
+ "#{self.class.name.split('::').last}(code=#{@code}, bright=#{@bright})"
65
+ end
66
+ end
67
+ private_constant :Color
68
+ end
69
+ end
@@ -0,0 +1,139 @@
1
+ require_relative 'border'
2
+ require_relative 'display_flow'
3
+ require_relative 'element_settings'
4
+ require_relative 'margin'
5
+ require_relative 'padding'
6
+ require_relative 'position'
7
+ require_relative 'scrollbar'
8
+
9
+ module WhirledPeas
10
+ module Settings
11
+ class ContainerSettings < ElementSettings
12
+ attr_accessor :width, :height
13
+
14
+ def align
15
+ @_align || TextAlign::LEFT
16
+ end
17
+
18
+ def align_left?
19
+ align == TextAlign::LEFT
20
+ end
21
+
22
+ def align_center?
23
+ align == TextAlign::CENTER
24
+ end
25
+
26
+ def align_right?
27
+ align == TextAlign::RIGHT
28
+ end
29
+
30
+ def align=(align)
31
+ @_align = TextAlign.validate!(align)
32
+ end
33
+
34
+ def set_border(
35
+ left: nil, top: nil, right: nil, bottom: nil, inner_horiz: nil, inner_vert: nil, style: nil, color: nil
36
+ )
37
+ @_border = Border.new unless @_border
38
+ @_border.left = left unless left.nil?
39
+ @_border.top = top unless top.nil?
40
+ @_border.right = right unless right.nil?
41
+ @_border.bottom = bottom unless bottom.nil?
42
+ @_border.inner_horiz = inner_horiz unless inner_horiz.nil?
43
+ @_border.inner_vert = inner_vert unless inner_vert.nil?
44
+ @_border.style = style unless style.nil?
45
+ @_border.color = color unless color.nil?
46
+ end
47
+
48
+ def full_border(style: nil, color: nil)
49
+ set_border(
50
+ left: true, top: true, right: true, bottom: true, inner_horiz: true, inner_vert: true, style: style, color: color
51
+ )
52
+ end
53
+
54
+ def border
55
+ @_border || Border.new
56
+ end
57
+
58
+ def flow=(flow)
59
+ @_flow = DisplayFlow.validate!(flow)
60
+ end
61
+
62
+ def flow
63
+ @_flow || DisplayFlow::LEFT_TO_RIGHT
64
+ end
65
+
66
+ def horizontal_flow?
67
+ %i[l2r r2l].include?(flow)
68
+ end
69
+
70
+ def vertical_flow?
71
+ !horizontal_flow?
72
+ end
73
+
74
+ def forward_flow?
75
+ %i[l2r t2b].include?(flow)
76
+ end
77
+
78
+ def reverse_flow?
79
+ !forward_flow?
80
+ end
81
+
82
+ def set_margin(left: nil, top: nil, right: nil, bottom: nil)
83
+ @_margin = Margin.new unless @_margin
84
+ @_margin.left = left if left
85
+ @_margin.top = top if top
86
+ @_margin.right = right if right
87
+ @_margin.bottom = bottom if bottom
88
+ end
89
+
90
+ def margin
91
+ @_margin || Margin.new
92
+ end
93
+
94
+ def set_padding(left: nil, top: nil, right: nil, bottom: nil)
95
+ @_padding = Padding.new unless @_padding
96
+ @_padding.left = left if left
97
+ @_padding.top = top if top
98
+ @_padding.right = right if right
99
+ @_padding.bottom = bottom if bottom
100
+ end
101
+
102
+ def padding
103
+ @_padding || Padding.new
104
+ end
105
+
106
+ def set_position(left: nil, top: nil)
107
+ @_position = Position.new unless @_position
108
+ @_position.left = left if left
109
+ @_position.top = top if top
110
+ end
111
+
112
+ def position
113
+ @_position || Position.new
114
+ end
115
+
116
+ def set_scrollbar(horiz: nil, vert: nil)
117
+ @_scrollbar = Scrollbar.new unless @_scrollbar
118
+ @_scrollbar.horiz = horiz unless horiz.nil?
119
+ @_scrollbar.vert = vert unless vert.nil?
120
+ end
121
+
122
+ def scrollbar
123
+ @_scrollbar || Scrollbar.new
124
+ end
125
+
126
+ def inherit(parent)
127
+ super
128
+ return unless parent.is_a?(ContainerSettings)
129
+ @_align = parent._align
130
+ @_flow = parent._flow
131
+ set_border(color: parent.border.color, style: parent.border.style)
132
+ end
133
+
134
+ protected
135
+
136
+ attr_accessor :_align, :_flow
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,96 @@
1
+ require_relative 'border'
2
+ require_relative 'container_settings'
3
+ require_relative 'margin'
4
+ require_relative 'padding'
5
+ require_relative 'position'
6
+ require_relative 'scrollbar'
7
+
8
+ module WhirledPeas
9
+ module Settings
10
+ class Debugger
11
+ def initialize(settings)
12
+ @settings = settings
13
+ end
14
+
15
+ def debug(indent='')
16
+ values = non_default_values(indent + ' ')
17
+ details = values.length > 0 ? values.join("\n") : "#{indent} <default>"
18
+ "#{indent}#{settings.class}\n#{details}"
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :settings
24
+
25
+ def non_default_values(indent)
26
+ settings.instance_variables.map do |ivar, values|
27
+ value = settings.instance_variable_get(ivar)
28
+ next if value.nil?
29
+ printable_value = debug_value(value)
30
+ "#{indent}#{ivar.to_s.sub(/^@?_?/, '')}: #{printable_value}" unless printable_value.nil?
31
+ end.compact
32
+ end
33
+
34
+ def debug_value(value)
35
+ return if value.nil?
36
+ case value
37
+ when Position
38
+ position_value(value)
39
+ when Margin
40
+ margin_value(value)
41
+ when Border
42
+ border_value(value)
43
+ when Padding
44
+ padding_value(value)
45
+ when Scrollbar
46
+ scrollbar_value(value)
47
+ else
48
+ value.inspect
49
+ end
50
+ end
51
+
52
+ def non_defaults(object, default_object, keys)
53
+ values = keys.map.with_object({}) do |key, hash|
54
+ unless object.send(key) == default_object.send(key)
55
+ hash[key] = object.send(key)
56
+ end
57
+ end
58
+ values.keys.map { |k| "#{k}: #{values[k]}"}.join(', ')
59
+ end
60
+
61
+ def position_value(position)
62
+ values = non_defaults(position, Position.new, %i[left top])
63
+ return if values == ''
64
+ "Position(#{values})"
65
+ end
66
+
67
+ def margin_value(margin)
68
+ values = non_defaults(margin, Margin.new, %i[left top right bottom])
69
+ return if values == ''
70
+ "Margin(#{values})"
71
+ end
72
+
73
+ def border_value(border)
74
+ values = non_defaults(
75
+ border,
76
+ Border.new,
77
+ %i[left? top? right? bottom? inner_horiz? inner_vert? style color]
78
+ )
79
+ return if values == ''
80
+ "Border(#{values})"
81
+ end
82
+
83
+ def padding_value(padding)
84
+ values = non_defaults(padding, Padding.new, %i[left top right bottom])
85
+ return if values == ''
86
+ "Padding(#{values})"
87
+ end
88
+
89
+ def scrollbar_value(scrollbar)
90
+ values = non_defaults(scrollbar, Scrollbar.new, %i[horiz? vert?])
91
+ return if values == ''
92
+ "Scrollbar(#{values})"
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,25 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ module DisplayFlow
4
+ LEFT_TO_RIGHT = :l2r
5
+ RIGHT_TO_LEFT = :r2l
6
+ TOP_TO_BOTTOM = :t2b
7
+ BOTTOM_TO_TOP = :b2t
8
+
9
+ def self.validate!(flow)
10
+ return unless flow
11
+ if [
12
+ DisplayFlow::LEFT_TO_RIGHT,
13
+ DisplayFlow::RIGHT_TO_LEFT,
14
+ DisplayFlow::TOP_TO_BOTTOM,
15
+ DisplayFlow::BOTTOM_TO_TOP
16
+ ].include?(flow)
17
+ flow
18
+ else
19
+ raise ArgumentError, "Unsupported display flow: #{flow}"
20
+ end
21
+ end
22
+ end
23
+ private_constant :DisplayFlow
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ require 'json'
2
+
3
+ require_relative 'bg_color'
4
+ require_relative 'text_align'
5
+ require_relative 'text_color'
6
+
7
+ module WhirledPeas
8
+ module Settings
9
+ class ElementSettings
10
+ def self.inherit(parent)
11
+ child = self.new
12
+ child.inherit(parent)
13
+ child
14
+ end
15
+
16
+ def bg_color
17
+ @_bg_color
18
+ end
19
+
20
+ def bg_color=(color)
21
+ @_bg_color = BgColor.validate!(color)
22
+ end
23
+
24
+ def bold?
25
+ @_bold || false
26
+ end
27
+
28
+ def bold=(val)
29
+ @_bold = val
30
+ end
31
+
32
+ def color
33
+ @_color
34
+ end
35
+
36
+ def color=(color)
37
+ @_color = TextColor.validate!(color)
38
+ end
39
+
40
+ def underline?
41
+ @_underline || false
42
+ end
43
+
44
+ def underline=(val)
45
+ @_underline = val
46
+ end
47
+
48
+ def inherit(parent)
49
+ @_bg_color = parent._bg_color
50
+ @_bold = parent._bold
51
+ @_color = parent._color
52
+ @_underline = parent._underline
53
+ end
54
+
55
+ protected
56
+
57
+ attr_accessor :_bg_color, :_bold, :_color, :_underline
58
+ end
59
+ private_constant :ElementSettings
60
+ end
61
+ end
@@ -0,0 +1,15 @@
1
+ require 'whirled_peas/utils/title_font'
2
+
3
+ require_relative 'container_settings'
4
+
5
+ module WhirledPeas
6
+ module Settings
7
+ class GridSettings < ContainerSettings
8
+ attr_accessor :num_cols
9
+
10
+ def set_scrollbar(*)
11
+ raise NotImplemented, 'Grids do not currently support scrollbars'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'spacing'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ class Margin < Spacing
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'spacing'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ class Padding < Spacing
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ class Position
4
+ attr_writer :left, :top
5
+
6
+ def left
7
+ @left || 0
8
+ end
9
+
10
+ def top
11
+ @top || 0
12
+ end
13
+ end
14
+ end
15
+ end