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