Module: Muxr::LayoutManager
- Defined in:
- lib/muxr/layout_manager.rb
Overview
Pure functions that turn (layout_name, pane_count, screen_rect) into an array of pane rectangles. No mutable state; safe to call repeatedly on every render. Following xmonad, layouts decide geometry — users never resize panes by hand.
Defined Under Namespace
Classes: Rect
Constant Summary collapse
- LAYOUTS =
%i[tall grid monocle].freeze
Class Method Summary collapse
- .compute(layout, count, area, focused_index: 0, master_index: 0) ⇒ Object
-
.grid(count, area) ⇒ Object
Roughly square grid.
-
.monocle(count, area, _focused_index = 0) ⇒ Object
All panes occupy the full area; the focused pane is the one drawn last (the Renderer is responsible for the z-order).
-
.tall(count, area, master_index = 0) ⇒ Object
Master pane on the left taking half the width; remaining panes stack vertically on the right, dividing the remaining height evenly.
Class Method Details
.compute(layout, count, area, focused_index: 0, master_index: 0) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/muxr/layout_manager.rb', line 17 def compute(layout, count, area, focused_index: 0, master_index: 0) return [] if count <= 0 master_index = master_index.clamp(0, count - 1) focused_index = focused_index.clamp(0, count - 1) case layout when :tall then tall(count, area, master_index) when :grid then grid(count, area) when :monocle then monocle(count, area, focused_index) else raise ArgumentError, "Unknown layout: #{layout.inspect}" end end |
.grid(count, area) ⇒ Object
Roughly square grid. Each row stretches its panes to fill the full width so an underfull bottom row doesn’t leave gaps.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/muxr/layout_manager.rb', line 57 def grid(count, area) cols_per_row = Math.sqrt(count).ceil rows = (count.to_f / cols_per_row).ceil base_h = area.h / rows h_rem = area.h - base_h * rows rects = [] idx = 0 y = area.y rows.times do |r| remaining = count - idx in_row = [cols_per_row, remaining].min row_h = base_h + (r < h_rem ? 1 : 0) col_w = area.w / in_row w_rem = area.w - col_w * in_row x = area.x in_row.times do |c| w = col_w + (c < w_rem ? 1 : 0) rects << Rect.new(x, y, w, row_h) x += w idx += 1 end y += row_h end rects end |
.monocle(count, area, _focused_index = 0) ⇒ Object
All panes occupy the full area; the focused pane is the one drawn last (the Renderer is responsible for the z-order).
87 88 89 |
# File 'lib/muxr/layout_manager.rb', line 87 def monocle(count, area, _focused_index = 0) Array.new(count) { Rect.new(area.x, area.y, area.w, area.h) } end |
.tall(count, area, master_index = 0) ⇒ Object
Master pane on the left taking half the width; remaining panes stack vertically on the right, dividing the remaining height evenly.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/muxr/layout_manager.rb', line 32 def tall(count, area, master_index = 0) master_index = master_index.clamp(0, count - 1) return [Rect.new(area.x, area.y, area.w, area.h)] if count == 1 master_w = [area.w / 2, 1].max stack_w = [area.w - master_w, 1].max others = (0...count).to_a - [master_index] slave_count = others.length base_h = area.h / slave_count remainder = area.h - base_h * slave_count rects = Array.new(count) rects[master_index] = Rect.new(area.x, area.y, master_w, area.h) y = area.y others.each_with_index do |idx, i| h = base_h + (i < remainder ? 1 : 0) rects[idx] = Rect.new(area.x + master_w, y, stack_w, h) y += h end rects end |