lib/whirled_peas/ui/element.rb in whirled_peas-0.1.1 vs lib/whirled_peas/ui/element.rb in whirled_peas-0.2.0
- old
+ new
@@ -1,109 +1,157 @@
require_relative 'settings'
module WhirledPeas
module UI
+ STRINGALBE_CLASSES = [FalseClass, Float, Integer, NilClass, String, Symbol, TrueClass]
+
class Element
attr_accessor :preferred_width, :preferred_height
- attr_reader :settings
+ attr_reader :name, :settings
- def initialize(settings)
+ def initialize(name, settings)
+ @name = name
@settings = settings
end
end
private_constant :Element
class TextElement < Element
attr_reader :value
- def initialize(settings)
- super(TextSettings.merge(settings))
+ def initialize(name, settings)
+ super(name, TextSettings.merge(settings))
end
def value=(val)
- @value = val
+ unless STRINGALBE_CLASSES.include?(val.class)
+ raise ArgmentError, "Unsupported type for TextElement: #{val.class}"
+ end
+ @value = val.to_s
@preferred_width = settings.width || value.length
@preferred_height = 1
end
def inspect(indent='')
dims = unless preferred_width.nil?
- "#{indent + ' '}Dimensions: #{preferred_width}x#{preferred_height}"
+ "#{indent + ' '}- Dimensions: #{preferred_width}x#{preferred_height}"
end
[
- "#{indent}#{self.class.name}",
+ "#{indent}+ #{name} [#{self.class.name}]",
dims,
- "#{indent + ' '}Settings",
+ "#{indent + ' '}- Settings",
settings.inspect(indent + ' ')
].compact.join("\n")
end
end
class ComposableElement < Element
- def initialize(settings)
+ class << self
+ def next_name
+ @counter ||= 0
+ @counter += 1
+ "Element-#{@counter}"
+ end
+ end
+
+ def initialize(name, settings)
super
end
def children
@children ||= []
end
- def add_text(&block)
- element = TextElement.new(settings)
+ def add_text(name=self.class.next_name, &block)
+ element = TextElement.new(name, settings)
element.value = yield nil, element.settings
children << element
end
- def add_box(&block)
- element = BoxElement.new(settings)
+ def add_box(name=self.class.next_name, &block)
+ element = BoxElement.new(name, settings)
value = yield element, element.settings
children << element
- if element.children.empty? && value.is_a?(String)
- element.add_text { value }
+ if element.children.empty? && STRINGALBE_CLASSES.include?(value.class)
+ element.add_text { value.to_s }
end
end
- def add_grid(&block)
- element = GridElement.new(settings)
+ def add_grid(name=self.class.next_name, &block)
+ element = GridElement.new(name, settings)
values = yield element, element.settings
children << element
if element.children.empty? && values.is_a?(Array)
- values.each { |v| element.add_text { v } }
+ values.each { |v| element.add_text { v.to_s } }
end
end
def inspect(indent='')
kids = children.map { |c| c.inspect(indent + ' ') }.join("\n")
dims = unless preferred_width.nil?
- "#{indent + ' '}Dimensions: #{preferred_width}x#{preferred_height}"
+ "#{indent + ' '}- Dimensions: #{preferred_width}x#{preferred_height}"
end
[
- "#{indent}#{self.class.name}",
+ "#{indent}+ #{name} [#{self.class.name}]",
dims,
- "#{indent + ' '}Settings",
+ "#{indent + ' '}- Settings",
settings.inspect(indent + ' '),
- "#{indent + ' '}Children",
+ "#{indent + ' '}- Children",
kids
].compact.join("\n")
end
+
+ private
+
+ def margin_width
+ settings.margin.left + settings.margin.right
+ end
+
+ def margin_height
+ settings.margin.top + settings.margin.bottom
+ end
+
+ def outer_border_width
+ (settings.border.left? ? 1 : 0) + (settings.border.right? ? 1 : 0)
+ end
+
+ def outer_border_height
+ (settings.border.top? ? 1 : 0) + (settings.border.bottom? ? 1 : 0)
+ end
+
+ def inner_border_width
+ settings.border.inner_vert? ? 1 : 0
+ end
+
+ def inner_border_height
+ settings.border.inner_horiz? ? 1 : 0
+ end
+
+ def padding_width
+ settings.padding.left + settings.padding.right
+ end
+
+ def padding_height
+ settings.padding.top + settings.padding.bottom
+ end
end
class Template < ComposableElement
def initialize(settings=TemplateSettings.new)
- super(settings)
+ super('TEMPLATE', settings)
end
end
class BoxElement < ComposableElement
attr_writer :content_width, :content_height
- def initialize(settings)
- super(BoxSettings.merge(settings))
+ def initialize(name, settings)
+ super(name, BoxSettings.merge(settings))
end
def self.from_template(template, width, height)
- box = new(template.settings)
+ box = new(template.name, template.settings)
template.children.each { |c| box.children << c }
box.content_width = box.preferred_width = width
box.content_height = box.preferred_height = height
box
end
@@ -115,40 +163,30 @@
[width, *settings.width].max
end
end
def preferred_width
- @preferred_width ||= settings.margin.left +
- (settings.border.left? ? 1 : 0) +
- settings.padding.left +
- content_width +
- settings.padding.right +
- (settings.border.right? ? 1 : 0) +
- settings.margin.right
+ @preferred_width ||=
+ margin_width + outer_border_width + padding_width + content_width
end
def content_height
@content_height ||= begin
child_heights = children.map(&:preferred_height)
settings.vertical_flow? ? child_heights.sum : (child_heights.max || 0)
end
end
def preferred_height
- @preferred_height ||= settings.margin.top +
- (settings.border.top? ? 1 : 0) +
- settings.padding.top +
- content_height +
- settings.padding.bottom +
- (settings.border.bottom? ? 1 : 0) +
- settings.margin.bottom
+ @preferred_height ||=
+ margin_height + outer_border_height + padding_height + content_height
end
end
class GridElement < ComposableElement
- def initialize(settings)
- super(GridSettings.merge(settings))
+ def initialize(name, settings)
+ super(name, GridSettings.merge(settings))
end
def col_width
return @col_width if @col_width
@col_width = 0
@@ -167,33 +205,21 @@
@row_height
end
def preferred_width
- settings.margin.left +
- (settings.border.left? ? 1 : 0) +
- settings.num_cols * (
- settings.padding.left +
- col_width +
- settings.padding.right
- ) +
- (settings.num_cols - 1) * (settings.border.inner_vert? ? 1 : 0) +
- (settings.border.right? ? 1 : 0) +
- settings.margin.right
+ margin_width +
+ outer_border_width +
+ settings.num_cols * (padding_width + col_width) +
+ (settings.num_cols - 1) * inner_border_width
end
def preferred_height
num_rows = (children.length / settings.num_cols).ceil
- settings.margin.top +
- (settings.border.top? ? 1 : 0) +
- num_rows * (
- settings.padding.top +
- row_height +
- settings.padding.bottom
- ) +
- (num_rows - 1) * (settings.border.inner_horiz? ? 1 : 0) +
- (settings.border.bottom? ? 1 : 0) +
- settings.margin.bottom
+ margin_height +
+ outer_border_height +
+ num_rows * (padding_height + row_height) +
+ (num_rows - 1) * inner_border_height
end
end
end
end