| 1 | //! Gallery: depth (panels), the horizon rule, a dialog and a sheet. |
| 2 | |
| 3 | use ratatui::{ |
| 4 | buffer::Buffer, |
| 5 | layout::Rect, |
| 6 | text::{Line, Span}, |
| 7 | widgets::{Paragraph, Widget, Wrap}, |
| 8 | }; |
| 9 | |
| 10 | use super::Entry; |
| 11 | use crate::{ |
| 12 | Depth, Dialog, DialogWidth, HorizonRule, KeyHint, KeyHints, Paint, Panel, Role, Sheet, |
| 13 | SheetEdge, Theme, glyphs, |
| 14 | }; |
| 15 | |
| 16 | fn depths(area: Rect, buf: &mut Buffer, theme: &Theme) { |
| 17 | let w = area.width / 4; |
| 18 | for (i, (depth, title, body)) in [ |
| 19 | (Depth::Deep, "Deep", "Put away"), |
| 20 | (Depth::Stage, "Stage", "Where work sits"), |
| 21 | (Depth::Raised, "Raised", "A card"), |
| 22 | (Depth::Overlay, "Overlay", "A decision"), |
| 23 | ] |
| 24 | .into_iter() |
| 25 | .enumerate() |
| 26 | { |
| 27 | let rect = Rect { |
| 28 | x: area.x + w * i as u16, |
| 29 | width: w, |
| 30 | ..area |
| 31 | }; |
| 32 | let inner = Panel::new(depth).title(title).draw(rect, buf, theme); |
| 33 | Line::from(Span::styled(body, theme.fg(Role::Muted))).render(inner, buf); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | fn horizon(area: Rect, buf: &mut Buffer, theme: &Theme) { |
| 38 | let row = |n: u16| { |
| 39 | Rect { |
| 40 | y: area.y.saturating_add(n), |
| 41 | height: 1, |
| 42 | ..area |
| 43 | } |
| 44 | .intersection(area) |
| 45 | }; |
| 46 | Line::from(Span::styled( |
| 47 | "Edited summary.md", |
| 48 | theme.fg(Role::Foreground), |
| 49 | )) |
| 50 | .render(row(0), buf); |
| 51 | HorizonRule::new() |
| 52 | .aside("12% of context used") |
| 53 | .paint(row(1), buf, theme); |
| 54 | Line::from(vec![ |
| 55 | Span::styled( |
| 56 | format!("{} ", glyphs::pick("›", theme.ascii())), |
| 57 | theme.fg(Role::Primary), |
| 58 | ), |
| 59 | Span::styled("Ask Codewhale to do something", theme.fg(Role::Muted)), |
| 60 | ]) |
| 61 | .render(row(2), buf); |
| 62 | } |
| 63 | |
| 64 | /// Work on the stage, for a dialog or a sheet to sit over. |
| 65 | fn backdrop(area: Rect, buf: &mut Buffer, theme: &Theme) { |
| 66 | let area = area.intersection(buf.area); |
| 67 | let lines = [ |
| 68 | "Edited summary.md", |
| 69 | "Ran cargo test: 212 passed", |
| 70 | "Read crates/tui/src/tui/views/mod.rs", |
| 71 | "Searched the web for ratatui tabs", |
| 72 | "Edited settings.rs", |
| 73 | ]; |
| 74 | for (row, line) in lines |
| 75 | .iter() |
| 76 | .cycle() |
| 77 | .take(usize::from(area.height)) |
| 78 | .enumerate() |
| 79 | { |
| 80 | buf.set_stringn( |
| 81 | area.x, |
| 82 | area.y + row as u16, |
| 83 | line, |
| 84 | usize::from(area.width), |
| 85 | theme.fg(Role::Muted), |
| 86 | ); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | fn dialog(area: Rect, buf: &mut Buffer, theme: &Theme) { |
| 91 | backdrop(area, buf, theme); |
| 92 | let hints = KeyHints::new(vec![ |
| 93 | KeyHint::new("y", "stop"), |
| 94 | KeyHint::new("n", "keep running"), |
| 95 | ]); |
| 96 | let body = Dialog::new() |
| 97 | .title("Stop the running workflow?") |
| 98 | .width(DialogWidth::Narrow) |
| 99 | .body_rows(2) |
| 100 | .hints(&hints) |
| 101 | .draw(area, buf, theme); |
| 102 | Paragraph::new("2 agents are still working. Their edits so far are kept.") |
| 103 | .style(theme.fg(Role::Foreground)) |
| 104 | .wrap(Wrap { trim: true }) |
| 105 | .render(body, buf); |
| 106 | } |
| 107 | |
| 108 | fn sheet(area: Rect, buf: &mut Buffer, theme: &Theme) { |
| 109 | backdrop(area, buf, theme); |
| 110 | let arrows = super::arrows(theme); |
| 111 | let hints = KeyHints::new(vec![ |
| 112 | KeyHint::new(arrows, "move"), |
| 113 | KeyHint::new("Enter", "change"), |
| 114 | KeyHint::new("Esc", "close"), |
| 115 | ]); |
| 116 | let body = Sheet::new() |
| 117 | .edge(SheetEdge::Bottom) |
| 118 | .title("Settings") |
| 119 | .aside("3 changed") |
| 120 | .size(10) |
| 121 | .max_size(9) |
| 122 | .hints(&hints) |
| 123 | .draw(area, buf, theme); |
| 124 | Paragraph::new(vec![ |
| 125 | Line::from("Theme Shoreline"), |
| 126 | Line::from("Motion Reduced"), |
| 127 | Line::from("Tool detail Collapsed"), |
| 128 | ]) |
| 129 | .style(theme.fg(Role::Foreground)) |
| 130 | .render(body, buf); |
| 131 | } |
| 132 | |
| 133 | pub(crate) fn entries() -> Vec<Entry> { |
| 134 | vec![ |
| 135 | Entry { |
| 136 | name: "dialog", |
| 137 | width: 80, |
| 138 | height: 12, |
| 139 | draw: dialog, |
| 140 | }, |
| 141 | Entry { |
| 142 | name: "sheet", |
| 143 | width: 80, |
| 144 | height: 12, |
| 145 | draw: sheet, |
| 146 | }, |
| 147 | Entry { |
| 148 | name: "depth", |
| 149 | width: 80, |
| 150 | height: 6, |
| 151 | draw: depths, |
| 152 | }, |
| 153 | Entry { |
| 154 | name: "horizon", |
| 155 | width: 60, |
| 156 | height: 3, |
| 157 | draw: horizon, |
| 158 | }, |
| 159 | ] |
| 160 | } |
| 161 |