class WhirledPeas::Graphics::ContainerPainter
Abstract Painter
for containers. Containers (as the name implies) contain other child elements and must delegate painting of the children to the children themselves.
Constants
- PADDING
Attributes
Public Class Methods
# File lib/whirled_peas/graphics/container_painter.rb, line 14 def initialize(name, settings) super @children = [] end
Public Instance Methods
Tightly manage access to the children (rather than simply exposing the underlying array). This allows subclasses to easily modify behavior based on that element's specific settings.
# File lib/whirled_peas/graphics/container_painter.rb, line 85 def add_child(child) children << child end
# File lib/whirled_peas/graphics/container_painter.rb, line 93 def children? num_children > 0 end
# File lib/whirled_peas/graphics/container_painter.rb, line 97 def each_child(&block) children.each(&block) end
# File lib/whirled_peas/graphics/container_painter.rb, line 89 def num_children children.length end
Paint the common attributes of containers (e.g. border and background color). Any class that inherits from this one should call `super` at the start of its paint
method, before painting its children.
# File lib/whirled_peas/graphics/container_painter.rb, line 22 def paint(canvas, left, top, &block) return unless canvas.writable? return unless needs_printing? canvas_coords = coords(left, top) # Paint the border, background color, and scrollbar starting from the top left # border position, moving down row by row until we reach the bottom border # position stroke_left = canvas_coords.border_left stroke_top = canvas_coords.border_top # All strokes will have the same formatting options formatting = [*settings.border.color, *settings.bg_color] # Paint the top border if the settings call for it if settings.border.top? canvas.stroke(stroke_left, stroke_top, top_border_stroke, formatting, &block) stroke_top += 1 end # Precalculate the middle border container grids with more than 1 row middle_border = dimensions.num_rows > 1 ? middle_border_stroke : '' vert_scrollbar = settings.scrollbar.vert? ? ScrollbarHelper.vert( dimensions.children_height + dimensions.padding_height, dimensions.inner_grid_height, canvas_coords.content_top - canvas_coords.offset_content_top, ) : [] # Paint each grid row by row dimensions.num_rows.times do |row_num| # In a grid with N rows, we will need to paint N - 1 inner horizontal borders. # This code treats the inner horizontal border as the top of each row except for # the first one. if row_num > 0 && settings.border.inner_horiz? canvas.stroke(stroke_left, stroke_top, middle_border, formatting, &block) stroke_top += 1 end # Paint the interior of each row (horizontal borders, veritical scroll bar and # background color for the padding and content area) dimensions.inner_grid_height.times do |row_within_cell| content_line = content_line_stroke(row_within_cell, vert_scrollbar) canvas.stroke(stroke_left, stroke_top, content_line, formatting, &block) stroke_top += 1 end # Paint the horizontal scroll bar is the settings call for it if settings.scrollbar.horiz? canvas.stroke(stroke_left, stroke_top, bottom_scroll_stroke(canvas_coords), formatting, &block) stroke_top += 1 end end # Paint the bottom border if the settings call for it if settings.border.bottom? canvas.stroke(stroke_left, stroke_top, bottom_border_stroke, formatting, &block) stroke_top += 1 end end
Private Instance Methods
Return the stroke for the bottom border
# File lib/whirled_peas/graphics/container_painter.rb, line 209 def bottom_border_stroke line_stroke( settings.border.style.bottom_left, settings.border.style.bottom_junc, settings.border.style.bottom_right ) do settings.border.style.bottom_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0)) end end
Return the stroke for the horizontal scroll bar
# File lib/whirled_peas/graphics/container_painter.rb, line 235 def bottom_scroll_stroke(canvas_coords) line_stroke( settings.border.style.left_vert, settings.border.style.middle_vert, settings.border.style.right_vert, ) do ScrollbarHelper.horiz( dimensions.children_width + dimensions.padding_width, dimensions.inner_grid_width, canvas_coords.content_left - canvas_coords.offset_content_left ).join end end
Return the stroke for a grid row between any borders
# File lib/whirled_peas/graphics/container_painter.rb, line 220 def content_line_stroke(row_within_cell, vert_scrollbar) line_stroke( settings.border.style.left_vert, settings.border.style.middle_vert, settings.border.style.right_vert, ) do if settings.scrollbar.vert? PADDING * dimensions.inner_grid_width + vert_scrollbar[row_within_cell] else PADDING * dimensions.inner_grid_width end end end
Return an object that allows easy access to important coordinates within the container, e.g. the left position where the left border is printed
# File lib/whirled_peas/graphics/container_painter.rb, line 117 def coords(left, top) ContainerCoords.new(dimensions, settings, left, top) end
@return [Array<Integer>] a two-item array, the first being the amount of horizontal
spacing to paint *before the first* child and the second being the amount of spacing to paint *between each* child
# File lib/whirled_peas/graphics/container_painter.rb, line 124 def horiz_justify_offset(containing_width) if settings.align_center? [(dimensions.content_width - containing_width) / 2, 0] elsif settings.align_right? [dimensions.content_width - containing_width, 0] elsif settings.align_between? return [0, 0] if num_children == 1 [0, (dimensions.content_width - containing_width) / (num_children - 1)] elsif settings.align_around? full_spacing = (dimensions.content_width - containing_width) / num_children [full_spacing / 2, full_spacing] elsif settings.align_evenly? spacing = (dimensions.content_width - containing_width) / (num_children + 1) [spacing, spacing] else [0, 0] end end
Return a stroke for one line of the container
@param left_border [String] the character to print as the first character if there
is a left border
@param junc_border [String] the character to print as the junction between two grid
columns if there is an inner vertical border
@param right_border [String] the character to print as the last character if there
is a right border
@block [String] the block should yield a string that represents the interior
(including padding) of a grid cell
# File lib/whirled_peas/graphics/container_painter.rb, line 175 def line_stroke(left_border, junc_border, right_border, &block) stroke = '' stroke += left_border if settings.border.left? dimensions.num_cols.times do |col_num| stroke += junc_border if col_num > 0 && settings.border.inner_vert? stroke += yield end stroke += right_border if settings.border.right? stroke end
Return the stroke for an inner horizontal border
# File lib/whirled_peas/graphics/container_painter.rb, line 198 def middle_border_stroke line_stroke( settings.border.style.left_junc, settings.border.style.cross_junc, settings.border.style.right_junc ) do settings.border.style.middle_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0)) end end
Determine if there is anything to print for the container (this does not accont for children, just the border, scrollbar, and background color)
# File lib/whirled_peas/graphics/container_painter.rb, line 107 def needs_printing? return true if settings.bg_color return true if settings.border.outer? return true if dimensions.num_cols > 1 && settings.border.inner_vert? return true if dimensions.num_rows > 1 && settings.border.inner_horiz? settings.scrollbar.horiz? || settings.scrollbar.vert? end
Return the stroke for the top border
# File lib/whirled_peas/graphics/container_painter.rb, line 187 def top_border_stroke line_stroke( settings.border.style.top_left, settings.border.style.top_junc, settings.border.style.top_right ) do settings.border.style.top_horiz * (dimensions.inner_grid_width + (settings.scrollbar.vert? ? 1 : 0)) end end
@return [Array<Integer>] a two-item array, the first being the amount of vertical
spacing to paint *above the first* child and the second being the amount of spacing to paint *between each* child
# File lib/whirled_peas/graphics/container_painter.rb, line 146 def vert_justify_offset(containing_height) if settings.valign_middle? [(dimensions.content_height - containing_height) / 2, 0] elsif settings.valign_bottom? [dimensions.content_height - containing_height, 0] elsif settings.valign_between? return [0, 0] if num_children == 1 [0, (dimensions.content_height - containing_height) / (num_children - 1)] elsif settings.valign_around? full_spacing = (dimensions.content_height - containing_height) / num_children [full_spacing / 2, full_spacing] elsif settings.valign_evenly? spacing = (dimensions.content_height - containing_height) / (num_children + 1) [spacing, spacing] else [0, 0] end end