Class: Charming::Presentation::Layout::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/charming/presentation/layout/builder.rb

Overview

Builder turns a declarative ‘screen_layout { … }` block into a layout tree of ScreenLayout → Split → Pane nodes. The block DSL is `split(direction) { … }`, `pane(name) { … }`, and `overlay { … }`. Unknown method calls in the block are forwarded to the underlying view so view helpers (e.g., `text`) work inside layout blocks.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(screen:, view:, background: nil) ⇒ Builder

Returns a new instance of Builder.



17
18
19
20
21
# File 'lib/charming/presentation/layout/builder.rb', line 17

def initialize(screen:, view:, background: nil)
  @view = view
  @root = ScreenLayout.new(screen: screen, background: background)
  @stack = [@root]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



59
60
61
62
63
# File 'lib/charming/presentation/layout/builder.rb', line 59

def method_missing(name, ...)
  return view.__send__(name, ...) if view.respond_to?(name, true)

  super
end

Class Method Details

.build(screen:, view:, background: nil) ⇒ Object

Builds the layout tree by evaluating the block in the builder’s context. Returns the root ScreenLayout node.



13
14
15
# File 'lib/charming/presentation/layout/builder.rb', line 13

def self.build(screen:, view:, background: nil, &)
  new(screen: screen, view: view, background: background).build(&)
end

Instance Method Details

#buildObject

Evaluates block in the builder’s context, then returns the root ScreenLayout node.



24
25
26
27
# File 'lib/charming/presentation/layout/builder.rb', line 24

def build(&)
  instance_eval(&) if block_given?
  root
end

#overlay(content = nil, top: :center, left: :center, **options, &block) ⇒ Object

Adds an Overlay node to the root ScreenLayout. top and left default to :center. The block, if given, is evaluated in the view’s context.



49
50
51
# File 'lib/charming/presentation/layout/builder.rb', line 49

def overlay(content = nil, top: :center, left: :center, **options, &block)
  root.add_overlay(Overlay.new(content: content, block: block, view: view, top: top, left: left, **options))
end

#pane(name = nil, content = nil, **options, &block) ⇒ Object

Adds a Pane leaf node to the current scope. name (optional) is the focus slot name; content (or a block) is the body. options are forwarded to Pane.



41
42
43
44
45
# File 'lib/charming/presentation/layout/builder.rb', line 41

def pane(name = nil, content = nil, **options, &block)
  node = Pane.new(name: name, content: content, block: block, view: view, **options)
  append(node)
  node
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Forwards unknown method calls to the underlying view so helpers like ‘text` work inside layout blocks.

Returns:

  • (Boolean)


55
56
57
# File 'lib/charming/presentation/layout/builder.rb', line 55

def respond_to_missing?(name, include_private = false)
  view.respond_to?(name, include_private) || super
end

#split(direction, gap: 0, **options) ⇒ Object

Adds a Split node to the current scope. direction is ‘:horizontal` or `:vertical`. gap (in cells) is inserted between children. Additional options are forwarded to Split. The block, if given, is evaluated in the split’s scope (for nested children).



32
33
34
35
36
37
# File 'lib/charming/presentation/layout/builder.rb', line 32

def split(direction, gap: 0, **options, &)
  node = Split.new(direction: direction, gap: gap, **options)
  append(node)
  within(node, &)
  node
end