Class: Tuile::Component::Layout::Absolute

Inherits:
Layout
  • Object
show all
Defined in:
lib/tuile/component/layout/absolute.rb,
sig/tuile.rbs

Overview

Places each child at the Rect it was added with, in this layout's own coordinates, and does no arithmetic of its own:

layout = Component::Layout::Absolute.new
layout.add(title, Rect.new(0, 0, 40, 1))
layout.add(body, Rect.new(0, 2, 40, 10))
layout.constrain(body, Rect.new(0, 2, 40, 20))   # moves it on the next settle

The rect is where the child wants to be, and this layout's Tuile::Component#relayout is what assigns it, so moving a child means #constraining it rather than writing its rect. A rect that sticks out of this layout is clipped at paint time, and this layout's own size doesn't matter: a detached Absolute with no rect still places its children, which is how a spec measures a tree that has no screen.

When the rects depend on this layout's size, subclass Tuile::Component::Layout and write the relayout instead.

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Absolute

Returns a new instance of Absolute.



24
25
26
27
28
# File 'lib/tuile/component/layout/absolute.rb', line 24

def initialize
  super
  # Identity-keyed: two == children are still two distinct slots.
  @rects = {}.compare_by_identity
end

Instance Method Details

#add(child, rect = nil) ⇒ void

This method returns an undefined value.

@param child — one child, or several sharing the rect.

@param rect — where the child sits, in this layout's coordinates; nil keeps the rect the child already has, which for a new component is empty.

Parameters:



37
38
39
40
41
42
43
44
# File 'lib/tuile/component/layout/absolute.rb', line 37

def add(child, rect = nil)
  return child.each { add(_1, rect) } if child.is_a?(Enumerable)

  rect ||= child.rect if child.is_a?(Component)
  validate_rect(rect)
  add_child(child)
  @rects[child] = rect
end

#constrain(child, rect) ⇒ void

This method returns an undefined value.

Moves a child already in the layout; it takes the new rect on the next settle.

@param child — a child of this layout.

@param rect

Parameters:



53
54
55
56
57
58
59
60
61
# File 'lib/tuile/component/layout/absolute.rb', line 53

def constrain(child, rect)
  raise ArgumentError, "#{child} is not a child of #{self}" unless children.any? { _1.equal?(child) }

  validate_rect(rect)
  return if @rects[child] == rect

  @rects[child] = rect
  invalidate_layout
end

#relayout ⇒ void

This method returns an undefined value.



73
74
75
# File 'lib/tuile/component/layout/absolute.rb', line 73

def relayout
  children.each { _1.rect = @rects.fetch(_1) }
end

#remove(child) ⇒ void

This method returns an undefined value.

@param child

Parameters:



65
66
67
68
# File 'lib/tuile/component/layout/absolute.rb', line 65

def remove(child)
  super
  @rects.delete(child)
end

#validate_rect(rect) ⇒ void

This method returns an undefined value.

@param rect

Parameters:

  • rect (Object)


80
81
82
# File 'lib/tuile/component/layout/absolute.rb', line 80

def validate_rect(rect)
  raise TypeError, "expected Rect, got #{rect.inspect}" unless rect.is_a?(Rect)
end