rab/tui/overlay.rs
1use crate::tui::Component;
2
3// =============================================================================
4// Overlay types — matching pi's packages/tui/src/tui.ts
5// =============================================================================
6
7/// Anchor position for overlays
8#[derive(Debug, Clone, Copy, PartialEq, Default)]
9pub enum OverlayAnchor {
10 #[default]
11 Center,
12 TopLeft,
13 TopRight,
14 BottomLeft,
15 BottomRight,
16 TopCenter,
17 BottomCenter,
18 LeftCenter,
19 RightCenter,
20}
21
22/// Margin configuration for overlays
23#[derive(Debug, Clone, Copy, Default)]
24pub struct OverlayMargin {
25 pub top: usize,
26 pub right: usize,
27 pub bottom: usize,
28 pub left: usize,
29}
30
31impl OverlayMargin {
32 pub fn uniform(value: usize) -> Self {
33 Self {
34 top: value,
35 right: value,
36 bottom: value,
37 left: value,
38 }
39 }
40}
41
42/// Value that can be absolute (number) or percentage (string like "50%").
43/// For simplicity in Rust, we represent percentage as f64 (0.0..=100.0).
44#[derive(Debug, Clone, Copy)]
45pub enum SizeValue {
46 Absolute(usize),
47 Percent(f64),
48}
49
50impl SizeValue {
51 pub fn resolve(&self, reference: usize) -> usize {
52 match self {
53 SizeValue::Absolute(v) => *v,
54 SizeValue::Percent(p) => {
55 let v = (reference as f64 * p / 100.0).floor() as usize;
56 v.max(1)
57 }
58 }
59 }
60}
61
62/// Options for overlay positioning and sizing.
63#[derive(Debug, Clone, Default)]
64pub struct OverlayOptions {
65 // === Sizing ===
66 /// Width in columns, or percentage of terminal width
67 pub width: Option<SizeValue>,
68 /// Minimum width in columns
69 pub min_width: Option<usize>,
70 /// Maximum height in rows, or percentage of terminal height
71 pub max_height: Option<SizeValue>,
72
73 // === Positioning - anchor-based ===
74 /// Anchor point for positioning (default: Center)
75 pub anchor: Option<OverlayAnchor>,
76 /// Horizontal offset from anchor position (positive = right)
77 pub offset_x: Option<isize>,
78 /// Vertical offset from anchor position (positive = down)
79 pub offset_y: Option<isize>,
80
81 // === Positioning - percentage or absolute ===
82 /// Row position: absolute number, or percentage from top
83 pub row: Option<SizeValue>,
84 /// Column position: absolute number, or percentage from left
85 pub col: Option<SizeValue>,
86
87 // === Margin from terminal edges ===
88 pub margin: Option<OverlayMargin>,
89
90 // === Visibility ===
91 /// If true, don't capture keyboard focus when shown
92 pub non_capturing: bool,
93}
94
95/// Internal entry in the overlay stack
96pub struct OverlayEntry {
97 pub component: Box<dyn Component>,
98 pub options: OverlayOptions,
99 /// Whether this overlay is temporarily hidden
100 pub hidden: bool,
101 /// Order for compositing (higher = on top)
102 pub focus_order: u64,
103 /// Unique ID for this overlay
104 pub id: u64,
105}
106
107/// Resolved overlay layout
108#[derive(Debug, Clone)]
109pub struct OverlayLayout {
110 pub width: usize,
111 pub row: usize,
112 pub col: usize,
113 pub max_height: Option<usize>,
114}