Skip to main content

rich_interact/
compose.rs

1//! Composition: containers that are themselves components (0.0.14
2//! workstream 1, #478, #479, #480).
3//!
4//! A container holds children, gives each a [`Rect`] of its own space, and
5//! is a [`Component`] like any other, so containers nest and run under both
6//! drivers and the [headless](crate::headless) one:
7//!
8//! - [`Stack`] lays children out along an [`Axis`], each [`Size`]d fixed,
9//!   flexible or by its content; [`Column`] and [`Row`] are its two axes;
10//! - [`Split`] puts two children side by side or one above the other, with
11//!   a border the mouse drags and the keyboard nudges, and minimum sizes;
12//! - [`Tabs`] shows one child at a time under a bar of titles, and keeps
13//!   every child's state while it is hidden;
14//! - [`Layers`] puts modal and popover [`Layer`]s over a base: a modal
15//!   dims what is under it and traps focus until it is dismissed.
16//!
17//! Children of one container share an output type `M`, the container's.
18//! A child with another output is adapted with
19//! [`ComponentExt::map`], which also decides what its answer means for the
20//! whole: finish with a value, or carry on. [`Label`] and [`Painted`] show
21//! something without taking focus.
22//!
23//! **Routing.** Keys and pastes go to the focused child. A child that does
24//! not use an event returns [`Flow::Ignored`] and it *bubbles*: the
25//! container tries its own bindings, then leaves it to its own container.
26//! Mouse events go to the child under the pointer (a press holds that child
27//! until the release, so a drag stays with it) in the child's own
28//! coordinates, and a click focuses the child. Resizes and ticks reach
29//! every child; a hand-off's [`Event::Returned`] goes back to the child that
30//! handed off.
31//!
32//! **Focus.** Tab and Shift+Tab (the `focus-next` and `focus-previous`
33//! bindings) move focus through every focusable child in order, into and
34//! out of nested containers, and wrap round at the top. They bubble like any
35//! key, so a child that uses Tab (a multi-select marking, an input
36//! completing) keeps it; a container overrides the order by implementing
37//! [`Component::focus_step`] and [`Component::focus_enter`], and rebinds
38//! the keys with its `rebind`.
39//!
40//! **Bindings.** Every container declares its keys in a
41//! [`Keymap`], and [`Component::keymap`] lists the
42//! focused child's then the container's own. `on` adds a binding of yours
43//! that runs when a key bubbles up unused; `shortcut` one that runs before
44//! the focused child sees the key.
45//!
46//! ```
47//! use rich_interact::compose::{Column, ComponentExt, Label, Split};
48//! use rich_interact::{headless, Flow, Input, Outcome, Select};
49//!
50//! let picker = Select::new("File", ["a.rs", "b.rs"]).map(Flow::Done);
51//! let name = Input::new("Name").map(|_| Flow::Continue);
52//! let app = Column::new()
53//!     .child(Label::new("[bold]Demo[/]"))
54//!     .child(Split::horizontal(picker, name).ratio(50));
55//! let script = headless::Script::new().keys("down enter");
56//! let (outcome, _) = headless::run(app, script, 60, 8);
57//! assert_eq!(outcome.unwrap(), Outcome::Done("b.rs"));
58//! ```
59
60use std::cell::{Cell, RefCell};
61use std::marker::PhantomData;
62use std::rc::Rc;
63use std::time::Duration;
64
65use rich::{Segment, Style};
66
67use crate::component::{Component, Context, Flow, View};
68use crate::event::{Event, Key, Mouse, MouseKind};
69use crate::keymap::{Binding, Keymap, keys};
70use crate::kit::{self, Divider, Theme};
71use crate::policy::{LineIo, NotInteractive};
72
73/// The action that moves focus to the next focusable child (Tab).
74pub const FOCUS_NEXT: &str = "focus-next";
75/// The action that moves focus to the previous focusable child (Shift+Tab).
76pub const FOCUS_PREVIOUS: &str = "focus-previous";
77
78/// A child of a container: any component with the container's output,
79/// boxed. [`ComponentExt::boxed`] makes one.
80pub type Child<'a, M> = Box<dyn Component<Output = M> + 'a>;
81
82/// A rectangle of cells, from the top left of the container's view.
83#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
84pub struct Rect {
85    pub x: usize,
86    pub y: usize,
87    pub width: usize,
88    pub height: usize,
89}
90
91impl Rect {
92    pub const fn new(x: usize, y: usize, width: usize, height: usize) -> Rect {
93        Rect {
94            x,
95            y,
96            width,
97            height,
98        }
99    }
100
101    /// Whether the cell at `column`, `row` is inside.
102    pub fn contains(&self, column: usize, row: usize) -> bool {
103        column >= self.x
104            && column < self.x + self.width
105            && row >= self.y
106            && row < self.y + self.height
107    }
108
109    /// `mouse` in this rectangle's own coordinates (0, 0 at its top left).
110    pub fn local(&self, mouse: Mouse) -> Mouse {
111        let clamp = |value: usize| u16::try_from(value).unwrap_or(u16::MAX);
112        Mouse {
113            column: clamp((mouse.column as usize).saturating_sub(self.x)),
114            row: clamp((mouse.row as usize).saturating_sub(self.y)),
115            ..mouse
116        }
117    }
118
119    /// The context a child in this rectangle renders and handles events
120    /// with: the same console, this rectangle's size.
121    pub fn context<'c>(&self, context: &Context<'c>) -> Context<'c> {
122        Context {
123            console: context.console,
124            width: self.width.max(1),
125            height: self.height.max(1),
126        }
127    }
128}
129
130/// Which way a [`Stack`] or a [`Split`] lays children out.
131#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
132pub enum Axis {
133    /// Side by side, left to right.
134    Horizontal,
135    /// One above the other, top to bottom.
136    #[default]
137    Vertical,
138}
139
140/// How much of a [`Stack`] a child takes along its axis.
141#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
142pub enum Size {
143    /// Exactly this many cells (rows in a column, columns in a row), or
144    /// what is left.
145    Fixed(usize),
146    /// A share of what the fixed and content-sized children leave, by
147    /// weight: `Flex(2)` takes twice what `Flex(1)` does.
148    Flex(u16),
149    /// In a column, the rows the child renders; in a row, the same as
150    /// `Flex(1)`.
151    #[default]
152    Auto,
153}
154
155/// Split `total` cells by `weights`, the remainder to the first.
156fn share(total: usize, weights: &[u16]) -> Vec<usize> {
157    let sum: usize = weights.iter().map(|w| usize::from(*w)).sum();
158    if sum == 0 {
159        return vec![0; weights.len()];
160    }
161    let mut out: Vec<usize> = weights
162        .iter()
163        .map(|w| total * usize::from(*w) / sum)
164        .collect();
165    let mut left = total - out.iter().sum::<usize>();
166    for (index, weight) in weights.iter().enumerate() {
167        if left == 0 {
168            break;
169        }
170        if *weight > 0 {
171            out[index] += 1;
172            left -= 1;
173        }
174    }
175    out
176}
177
178// ---------------------------------------------------------------------------
179// Adapting leaves.
180
181/// A component whose answer is turned into a container's
182/// [`Flow`]: see [`ComponentExt::map`]. Once the component has answered or
183/// cancelled, it no longer takes focus or events, and shows its final view.
184pub struct Map<'a, C: Component, M> {
185    inner: C,
186    done: Box<dyn FnMut(C::Output) -> Flow<M> + 'a>,
187    cancel: Box<dyn FnMut() -> Flow<M> + 'a>,
188    finished: bool,
189}
190
191impl<'a, C: Component, M> Map<'a, C, M> {
192    /// What cancelling means (default: [`Flow::Cancel`], which cancels the
193    /// container too).
194    #[must_use]
195    pub fn on_cancel(mut self, cancel: impl FnMut() -> Flow<M> + 'a) -> Self {
196        self.cancel = Box::new(cancel);
197        self
198    }
199
200    /// The component inside.
201    pub fn inner(&self) -> &C {
202        &self.inner
203    }
204
205    pub fn inner_mut(&mut self) -> &mut C {
206        &mut self.inner
207    }
208
209    /// Whether the component has answered or cancelled.
210    pub fn finished(&self) -> bool {
211        self.finished
212    }
213
214    fn convert(&mut self, flow: Flow<C::Output>) -> Flow<M> {
215        match flow {
216            Flow::Continue => Flow::Continue,
217            Flow::Ignored => Flow::Ignored,
218            Flow::Handoff(command) => Flow::Handoff(command),
219            Flow::Done(value) => {
220                self.finished = true;
221                (self.done)(value)
222            }
223            Flow::Cancel => {
224                self.finished = true;
225                (self.cancel)()
226            }
227        }
228    }
229}
230
231impl<C: Component, M> Component for Map<'_, C, M> {
232    type Output = M;
233
234    fn start(&mut self, context: &Context<'_>) -> Flow<M> {
235        let flow = self.inner.start(context);
236        self.convert(flow)
237    }
238
239    fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
240        if self.finished {
241            return Flow::Ignored;
242        }
243        let flow = self.inner.handle(event, context);
244        self.convert(flow)
245    }
246
247    fn render(&self, context: &Context<'_>) -> View {
248        self.inner.render(context)
249    }
250
251    fn tick(&self) -> Option<Duration> {
252        if self.finished {
253            None
254        } else {
255            self.inner.tick()
256        }
257    }
258
259    fn mouse(&self) -> bool {
260        !self.finished && self.inner.mouse()
261    }
262
263    fn keymap(&self) -> Keymap {
264        if self.finished {
265            Keymap::default()
266        } else {
267            self.inner.keymap()
268        }
269    }
270
271    fn focusable(&self) -> bool {
272        !self.finished && self.inner.focusable()
273    }
274
275    fn focus_step(&mut self, forward: bool) -> bool {
276        !self.finished && self.inner.focus_step(forward)
277    }
278
279    fn focus_enter(&mut self, forward: bool) -> bool {
280        !self.finished && self.inner.focus_enter(forward)
281    }
282}
283
284/// Adapters for putting any component in a container.
285pub trait ComponentExt: Component + Sized {
286    /// Turn this component's answer into `M`'s flow: `Flow::Done(m)` to
287    /// finish the whole composition with `m`, `Flow::Continue` to carry on
288    /// (the component stays, showing its answer, and focus moves past it).
289    /// Cancelling cancels the composition unless
290    /// [`on_cancel`](Map::on_cancel) says otherwise.
291    fn map<'a, M>(self, done: impl FnMut(Self::Output) -> Flow<M> + 'a) -> Map<'a, Self, M>
292    where
293        Self: 'a,
294    {
295        Map {
296            inner: self,
297            done: Box::new(done),
298            cancel: Box::new(|| Flow::Cancel),
299            finished: false,
300        }
301    }
302
303    /// Wrap this component in [`Overlays`](crate::overlay::Overlays): a
304    /// command palette, help and a shortcut sheet read from its keymap,
305    /// and room for a status bar and breadcrumbs.
306    fn with_overlays<'a>(self) -> crate::overlay::Overlays<'a, Self::Output>
307    where
308        Self: 'a,
309        Self::Output: 'a,
310    {
311        crate::overlay::Overlays::new(self)
312    }
313
314    /// Box this component as a [`Child`].
315    fn boxed<'a>(self) -> Child<'a, Self::Output>
316    where
317        Self: 'a,
318    {
319        Box::new(self)
320    }
321}
322
323impl<C: Component> ComponentExt for C {}
324
325/// Console markup that takes no focus and uses no events: a title, a note.
326pub struct Label<M> {
327    markup: String,
328    _output: PhantomData<fn() -> M>,
329}
330
331impl<M> Label<M> {
332    pub fn new(markup: impl Into<String>) -> Label<M> {
333        Label {
334            markup: markup.into(),
335            _output: PhantomData,
336        }
337    }
338
339    /// Change what it says.
340    pub fn set(&mut self, markup: impl Into<String>) {
341        self.markup = markup.into();
342    }
343}
344
345impl<M> Component for Label<M> {
346    type Output = M;
347
348    fn handle(&mut self, _: &Event, _: &Context<'_>) -> Flow<M> {
349        Flow::Ignored
350    }
351
352    fn render(&self, context: &Context<'_>) -> View {
353        View::new(context.markup(&self.markup))
354    }
355
356    fn focusable(&self) -> bool {
357        false
358    }
359}
360
361/// A view drawn by a function, taking no focus and using no events: a
362/// status line computed from shared state, a preview.
363pub struct Painted<F, M> {
364    paint: F,
365    _output: PhantomData<fn() -> M>,
366}
367
368impl<F: Fn(&Context<'_>) -> View, M> Painted<F, M> {
369    pub fn new(paint: F) -> Painted<F, M> {
370        Painted {
371            paint,
372            _output: PhantomData,
373        }
374    }
375}
376
377impl<F: Fn(&Context<'_>) -> View, M> Component for Painted<F, M> {
378    type Output = M;
379
380    fn handle(&mut self, _: &Event, _: &Context<'_>) -> Flow<M> {
381        Flow::Ignored
382    }
383
384    fn render(&self, context: &Context<'_>) -> View {
385        (self.paint)(context)
386    }
387
388    fn focusable(&self) -> bool {
389        false
390    }
391}
392
393// ---------------------------------------------------------------------------
394// What every container shares: children with focus, and bindings.
395
396/// Whether a flow ends the event's journey: anything but carrying on.
397fn decisive<M>(flow: &Flow<M>) -> bool {
398    !matches!(flow, Flow::Continue | Flow::Ignored)
399}
400
401/// Children, which one has focus, which one a mouse press holds, and which
402/// one handed the terminal off.
403struct Group<'a, M> {
404    children: Vec<Child<'a, M>>,
405    focus: Option<usize>,
406    grab: Option<usize>,
407    handoff: Option<usize>,
408}
409
410impl<'a, M> Group<'a, M> {
411    fn new() -> Group<'a, M> {
412        Group {
413            children: Vec::new(),
414            focus: None,
415            grab: None,
416            handoff: None,
417        }
418    }
419
420    /// The focused child: the one focused last if it still takes focus,
421    /// else the first that does.
422    fn focused(&self) -> Option<usize> {
423        let takes = |index: usize| self.children[index].focusable();
424        self.focus
425            .filter(|&index| index < self.children.len() && takes(index))
426            .or_else(|| (0..self.children.len()).find(|&index| takes(index)))
427    }
428
429    fn settle(&mut self) {
430        self.focus = self.focused();
431    }
432
433    fn focus_step(&mut self, forward: bool) -> bool {
434        let current = self.focused();
435        if let Some(index) = current
436            && self.children[index].focus_step(forward)
437        {
438            return true;
439        }
440        let count = self.children.len();
441        let order: Vec<usize> = if forward {
442            (current.map_or(0, |index| index + 1)..count).collect()
443        } else {
444            (0..current.unwrap_or(count)).rev().collect()
445        };
446        for index in order {
447            if self.children[index].focus_enter(forward) {
448                self.focus = Some(index);
449                return true;
450            }
451        }
452        false
453    }
454
455    fn focus_enter(&mut self, forward: bool) -> bool {
456        let count = self.children.len();
457        let order: Vec<usize> = if forward {
458            (0..count).collect()
459        } else {
460            (0..count).rev().collect()
461        };
462        for index in order {
463            if self.children[index].focus_enter(forward) {
464                self.focus = Some(index);
465                return true;
466            }
467        }
468        false
469    }
470
471    fn deliver(&mut self, index: usize, event: &Event, context: &Context<'_>) -> Flow<M> {
472        let flow = self.children[index].handle(event, context);
473        if let Flow::Handoff(_) = flow {
474            self.handoff = Some(index);
475        }
476        flow
477    }
478
479    fn start(&mut self, context: &Context<'_>, rect: impl Fn(usize) -> Rect) -> Flow<M> {
480        for index in 0..self.children.len() {
481            let flow = self.children[index].start(&rect(index).context(context));
482            if decisive(&flow) {
483                return flow;
484            }
485        }
486        self.settle();
487        Flow::Continue
488    }
489
490    /// Route `event` to the children laid out at `rects` (child index and
491    /// rectangle); children missing from `rects` (hidden tabs) get resizes
492    /// and ticks at `hidden`.
493    fn route(
494        &mut self,
495        event: &Event,
496        context: &Context<'_>,
497        rects: &[(usize, Rect)],
498        hidden: Rect,
499    ) -> Flow<M> {
500        let rect_of = |index: usize| {
501            rects
502                .iter()
503                .find(|(i, _)| *i == index)
504                .map_or(hidden, |(_, rect)| *rect)
505        };
506        match event {
507            Event::Mouse(mouse) => self.route_mouse(*mouse, context, rects),
508            Event::Tick | Event::Resize { .. } => {
509                for index in 0..self.children.len() {
510                    if matches!(event, Event::Tick) && self.children[index].tick().is_none() {
511                        continue;
512                    }
513                    let flow = self.deliver(index, event, &rect_of(index).context(context));
514                    if decisive(&flow) {
515                        return flow;
516                    }
517                }
518                Flow::Continue
519            }
520            Event::Returned(_) => match self.handoff.take().or_else(|| self.focused()) {
521                Some(index) => self.deliver(index, event, &rect_of(index).context(context)),
522                None => Flow::Ignored,
523            },
524            _ => match self.focused() {
525                Some(index) => {
526                    self.focus = Some(index);
527                    self.deliver(index, event, &rect_of(index).context(context))
528                }
529                None => Flow::Ignored,
530            },
531        }
532    }
533
534    fn route_mouse(
535        &mut self,
536        mouse: Mouse,
537        context: &Context<'_>,
538        rects: &[(usize, Rect)],
539    ) -> Flow<M> {
540        let (column, row) = (mouse.column as usize, mouse.row as usize);
541        // A rect for a child that is not there (Tabs with no tabs) is
542        // nothing under the mouse.
543        let under = rects
544            .iter()
545            .find(|(index, rect)| *index < self.children.len() && rect.contains(column, row))
546            .map(|(index, _)| *index);
547        let mut focused = false;
548        let target = match mouse.kind {
549            MouseKind::Down(_) => {
550                self.grab = under;
551                if let Some(index) = under.filter(|&i| self.children[i].focusable()) {
552                    focused = self.focused() != Some(index);
553                    self.focus = Some(index);
554                }
555                under
556            }
557            MouseKind::Drag(_) => self.grab.or(under),
558            MouseKind::Up(_) => self.grab.take().or(under),
559            _ => under,
560        };
561        let Some(index) = target else {
562            return Flow::Ignored;
563        };
564        let Some((_, rect)) = rects.iter().find(|(i, _)| *i == index).copied() else {
565            return Flow::Ignored;
566        };
567        if !self.children[index].mouse() {
568            return if focused {
569                Flow::Continue
570            } else {
571                Flow::Ignored
572            };
573        }
574        let flow = self.deliver(
575            index,
576            &Event::Mouse(rect.local(mouse)),
577            &rect.context(context),
578        );
579        match flow {
580            Flow::Ignored if focused => Flow::Continue,
581            flow => flow,
582        }
583    }
584
585    fn tick(&self) -> Option<Duration> {
586        self.children.iter().filter_map(|child| child.tick()).min()
587    }
588
589    fn mouse(&self) -> bool {
590        self.children.iter().any(|child| child.mouse())
591    }
592
593    fn focusable(&self) -> bool {
594        self.children.iter().any(|child| child.focusable())
595    }
596}
597
598type Handler<'a, M> = Box<dyn FnMut() -> Flow<M> + 'a>;
599
600/// A container's keymap, which of its actions come before the focused
601/// child, and the handlers of the bindings added with `on` and `shortcut`.
602struct Bindings<'a, M> {
603    keymap: Keymap,
604    priority: Vec<String>,
605    handlers: Vec<(String, Handler<'a, M>)>,
606}
607
608impl<'a, M> Bindings<'a, M> {
609    fn new(context: &str) -> Bindings<'a, M> {
610        Bindings {
611            keymap: Keymap::new(context),
612            priority: Vec::new(),
613            handlers: Vec::new(),
614        }
615    }
616
617    fn declare(&mut self, action: &str, keys: Vec<Key>, description: &str, priority: bool) {
618        let binding = Binding::new(self.keymap.context(), action, keys, description);
619        self.keymap.add(binding);
620        self.priority.retain(|p| p != action);
621        if priority {
622            self.priority.push(action.to_string());
623        }
624    }
625
626    fn focus_keys(mut self) -> Self {
627        self.declare(FOCUS_NEXT, keys("tab"), "next field", false);
628        self.declare(FOCUS_PREVIOUS, keys("shift+tab"), "previous field", false);
629        self
630    }
631
632    fn on(
633        &mut self,
634        action: &str,
635        keys: Vec<Key>,
636        description: &str,
637        priority: bool,
638        handler: impl FnMut() -> Flow<M> + 'a,
639    ) {
640        self.declare(action, keys, description, priority);
641        self.handlers.retain(|(name, _)| name != action);
642        self.handlers.push((action.to_string(), Box::new(handler)));
643    }
644
645    /// The action `key` triggers among the priority (`true`) or the other
646    /// bindings.
647    fn action(&self, key: Key, priority: bool) -> Option<String> {
648        let action = self.keymap.action(key)?;
649        (self.priority.iter().any(|p| p == action) == priority).then(|| action.to_string())
650    }
651
652    /// Run the handler for `action`, if it has one.
653    fn run(&mut self, action: &str) -> Option<Flow<M>> {
654        self.handlers
655            .iter_mut()
656            .find(|(name, _)| name == action)
657            .map(|(_, handler)| handler())
658    }
659}
660
661/// The builder methods every container has for its bindings.
662macro_rules! binding_builders {
663    () => {
664        /// Run `handler` when one of `keys` bubbles up unused by the
665        /// focused child: an action of yours, listed in the keymap under
666        /// this container's context.
667        #[must_use]
668        pub fn on(
669            mut self,
670            action: &str,
671            keys: impl IntoIterator<Item = Key>,
672            description: &str,
673            handler: impl FnMut() -> Flow<M> + 'a,
674        ) -> Self {
675            let keys = keys.into_iter().collect();
676            self.bindings.on(action, keys, description, false, handler);
677            self
678        }
679
680        /// Run `handler` when one of `keys` is pressed, before the focused
681        /// child sees it.
682        #[must_use]
683        pub fn shortcut(
684            mut self,
685            action: &str,
686            keys: impl IntoIterator<Item = Key>,
687            description: &str,
688            handler: impl FnMut() -> Flow<M> + 'a,
689        ) -> Self {
690            let keys = keys.into_iter().collect();
691            self.bindings.on(action, keys, description, true, handler);
692            self
693        }
694
695        /// Make `keys` do this container's `action` (`focus-next`, and the
696        /// container's own); no keys unbinds it.
697        #[must_use]
698        pub fn rebind(mut self, action: &str, keys: impl IntoIterator<Item = Key>) -> Self {
699            self.bindings.keymap.rebind(action, keys);
700            self
701        }
702
703        /// This container's own bindings, without its children's.
704        pub fn own_keymap(&self) -> &Keymap {
705            &self.bindings.keymap
706        }
707
708        /// Report the mouse even when no child asks for it: for a click to
709        /// focus a child, or a border to drag.
710        #[must_use]
711        pub fn with_mouse(mut self, on: bool) -> Self {
712            self.mouse = on;
713            self
714        }
715    };
716}
717
718// ---------------------------------------------------------------------------
719// Stack, Column, Row.
720
721/// Children laid out along an axis, each [`Size`]d: a [`Column`] top to
722/// bottom, a [`Row`] left to right.
723pub struct Stack<'a, M> {
724    axis: Axis,
725    group: Group<'a, M>,
726    sizes: Vec<Size>,
727    gap: usize,
728    bindings: Bindings<'a, M>,
729    mouse: bool,
730}
731
732impl<'a, M> Stack<'a, M> {
733    pub fn new(axis: Axis) -> Stack<'a, M> {
734        Stack {
735            axis,
736            group: Group::new(),
737            sizes: Vec::new(),
738            gap: 0,
739            bindings: Bindings::new("stack").focus_keys(),
740            mouse: false,
741        }
742    }
743
744    /// Add a child sized [`Size::Auto`].
745    #[must_use]
746    pub fn child(self, child: impl Component<Output = M> + 'a) -> Self {
747        self.sized(Size::Auto, child)
748    }
749
750    /// Add a child sized `size`.
751    #[must_use]
752    pub fn sized(mut self, size: Size, child: impl Component<Output = M> + 'a) -> Self {
753        self.push(size, Box::new(child));
754        self
755    }
756
757    /// Add a child to a stack already built.
758    pub fn push(&mut self, size: Size, child: Child<'a, M>) {
759        self.group.children.push(child);
760        self.sizes.push(size);
761    }
762
763    /// Leave `cells` empty between children.
764    #[must_use]
765    pub fn gap(mut self, cells: usize) -> Self {
766        self.gap = cells;
767        self
768    }
769
770    binding_builders!();
771
772    pub fn axis(&self) -> Axis {
773        self.axis
774    }
775
776    pub fn len(&self) -> usize {
777        self.group.children.len()
778    }
779
780    pub fn is_empty(&self) -> bool {
781        self.group.children.is_empty()
782    }
783
784    /// Child `index`.
785    pub fn get(&self, index: usize) -> Option<&(dyn Component<Output = M> + 'a)> {
786        self.group.children.get(index).map(|child| &**child)
787    }
788
789    pub fn get_mut(&mut self, index: usize) -> Option<&mut (dyn Component<Output = M> + 'a)> {
790        self.group.children.get_mut(index).map(|child| &mut **child)
791    }
792
793    /// The focused child's index.
794    pub fn focused(&self) -> Option<usize> {
795        self.group.focused()
796    }
797
798    /// Focus child `index`, if it takes focus.
799    pub fn focus(&mut self, index: usize) -> bool {
800        let takes = self
801            .group
802            .children
803            .get_mut(index)
804            .is_some_and(|child| child.focus_enter(true));
805        if takes {
806            self.group.focus = Some(index);
807        }
808        takes
809    }
810
811    /// Each child's rectangle at `context`'s size. A content-sized child
812    /// in a column is rendered to measure it.
813    pub fn layout(&self, context: &Context<'_>) -> Vec<Rect> {
814        let count = self.len();
815        let gaps = self.gap * count.saturating_sub(1);
816        let vertical = self.axis == Axis::Vertical;
817        let total = if vertical {
818            context.height
819        } else {
820            context.width
821        };
822        let mut left = total.saturating_sub(gaps);
823        let mut extent = vec![0; count];
824        for (index, size) in self.sizes.iter().enumerate() {
825            if let Size::Fixed(cells) = size {
826                extent[index] = (*cells).min(left);
827                left -= extent[index];
828            }
829        }
830        if vertical {
831            for (index, size) in self.sizes.iter().enumerate() {
832                if *size == Size::Auto {
833                    let probe = Rect::new(0, 0, context.width, left).context(context);
834                    extent[index] = self.group.children[index]
835                        .render(&probe)
836                        .lines
837                        .len()
838                        .min(left);
839                    left -= extent[index];
840                }
841            }
842        }
843        let weights: Vec<u16> = self
844            .sizes
845            .iter()
846            .map(|size| match size {
847                Size::Flex(weight) => *weight,
848                Size::Auto if !vertical => 1,
849                _ => 0,
850            })
851            .collect();
852        for (index, cells) in share(left, &weights).into_iter().enumerate() {
853            if weights[index] > 0 {
854                extent[index] = cells;
855            }
856        }
857        let mut at = 0;
858        extent
859            .into_iter()
860            .map(|cells| {
861                let rect = if vertical {
862                    Rect::new(0, at, context.width, cells)
863                } else {
864                    Rect::new(at, 0, cells, context.height)
865                };
866                at += cells + self.gap;
867                rect
868            })
869            .collect()
870    }
871
872    fn indexed(&self, context: &Context<'_>) -> Vec<(usize, Rect)> {
873        self.layout(context).into_iter().enumerate().collect()
874    }
875}
876
877/// The rows of `view` in `rect`: cut to its height, and padded to it when
878/// `fill`.
879fn rows_of(view: &View, rect: Rect, fill: bool) -> Vec<Vec<Segment>> {
880    let mut lines: Vec<Vec<Segment>> = view
881        .lines
882        .iter()
883        .take(rect.height)
884        .map(|line| kit::fit(line.clone(), rect.width))
885        .collect();
886    if fill {
887        lines.resize_with(rect.height, Vec::new);
888    }
889    lines
890}
891
892/// Views side by side at `rects`, each padded to its width but the last;
893/// the cursor of view `focus`, if it has one.
894fn side_by_side(
895    views: &[(View, Rect)],
896    rows: usize,
897    focus: Option<usize>,
898    between: &[Vec<Segment>],
899) -> View {
900    let mut lines = Vec::with_capacity(rows);
901    for row in 0..rows {
902        let mut line = Vec::new();
903        for (index, (view, rect)) in views.iter().enumerate() {
904            let cells = view.lines.get(row).cloned().unwrap_or_default();
905            if index + 1 == views.len() {
906                line.extend(kit::fit(cells, rect.width));
907            } else {
908                line.extend(kit::pad(cells, rect.width));
909                line.extend(between.get(index).cloned().unwrap_or_default());
910            }
911        }
912        lines.push(line);
913    }
914    let mut out = View::new(lines);
915    if let Some((view, rect)) = focus.and_then(|index| views.get(index))
916        && let Some((row, column)) = view.cursor
917        && row < rows
918        && column < rect.width.max(1)
919    {
920        out.cursor = Some((rect.y + row, rect.x + column));
921    }
922    out
923}
924
925/// The container's keymap: the focused child's, then its own.
926fn keymap_with<M>(focused: Option<&Child<'_, M>>, own: &Keymap) -> Keymap {
927    let mut keymap = focused.map(|child| child.keymap()).unwrap_or_default();
928    keymap.extend(own.clone());
929    keymap
930}
931
932impl<M> Component for Stack<'_, M> {
933    type Output = M;
934
935    fn start(&mut self, context: &Context<'_>) -> Flow<M> {
936        let rects = self.layout(context);
937        self.group.start(context, |index| rects[index])
938    }
939
940    fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
941        if let Some(key) = event.key()
942            && let Some(action) = self.bindings.action(key, true)
943            && let Some(flow) = self.bindings.run(&action)
944        {
945            return flow;
946        }
947        let rects = self.indexed(context);
948        let flow = self.group.route(event, context, &rects, Rect::default());
949        self.group.settle();
950        if !matches!(flow, Flow::Ignored) {
951            return flow;
952        }
953        let Some(action) = event.key().and_then(|key| self.bindings.action(key, false)) else {
954            return Flow::Ignored;
955        };
956        match action.as_str() {
957            FOCUS_NEXT | FOCUS_PREVIOUS => {
958                if self.group.focus_step(action == FOCUS_NEXT) {
959                    Flow::Continue
960                } else {
961                    Flow::Ignored
962                }
963            }
964            _ => self.bindings.run(&action).unwrap_or(Flow::Ignored),
965        }
966    }
967
968    fn render(&self, context: &Context<'_>) -> View {
969        let rects = self.layout(context);
970        let focus = self.group.focused();
971        let views: Vec<(View, Rect)> = rects
972            .iter()
973            .enumerate()
974            .map(|(index, rect)| {
975                (
976                    self.group.children[index].render(&rect.context(context)),
977                    *rect,
978                )
979            })
980            .collect();
981        match self.axis {
982            Axis::Vertical => {
983                let mut out = View::default();
984                for (index, (view, rect)) in views.iter().enumerate() {
985                    if index > 0 {
986                        out.lines.extend(std::iter::repeat_n(Vec::new(), self.gap));
987                    }
988                    let fill = self.sizes[index] != Size::Auto;
989                    let top = out.lines.len();
990                    out.lines.extend(rows_of(view, *rect, fill));
991                    if Some(index) == focus
992                        && let Some((row, column)) = view.cursor
993                        && row < rect.height
994                    {
995                        out.cursor = Some((top + row, column));
996                    }
997                }
998                out
999            }
1000            Axis::Horizontal => {
1001                let rows = views
1002                    .iter()
1003                    .map(|(view, _)| view.lines.len())
1004                    .max()
1005                    .unwrap_or(0)
1006                    .min(context.height);
1007                let gap = vec![kit::plain(" ".repeat(self.gap))];
1008                let between = vec![gap; views.len()];
1009                side_by_side(&views, rows, focus, &between)
1010            }
1011        }
1012    }
1013
1014    fn tick(&self) -> Option<Duration> {
1015        self.group.tick()
1016    }
1017
1018    fn mouse(&self) -> bool {
1019        self.mouse || self.group.mouse()
1020    }
1021
1022    fn keymap(&self) -> Keymap {
1023        let focused = self
1024            .group
1025            .focused()
1026            .map(|index| &self.group.children[index]);
1027        keymap_with(focused, &self.bindings.keymap)
1028    }
1029
1030    fn focusable(&self) -> bool {
1031        self.group.focusable()
1032    }
1033
1034    fn focus_step(&mut self, forward: bool) -> bool {
1035        self.group.focus_step(forward)
1036    }
1037
1038    fn focus_enter(&mut self, forward: bool) -> bool {
1039        self.group.focus_enter(forward)
1040    }
1041}
1042
1043/// A [`Stack`] with a fixed axis, under its own name.
1044macro_rules! axis_stack {
1045    ($(#[$doc:meta])* $name:ident, $axis:expr) => {
1046        $(#[$doc])*
1047        pub struct $name<'a, M>(Stack<'a, M>);
1048
1049        impl<'a, M> Default for $name<'a, M> {
1050            fn default() -> Self {
1051                Self::new()
1052            }
1053        }
1054
1055        impl<'a, M> $name<'a, M> {
1056            pub fn new() -> Self {
1057                $name(Stack::new($axis))
1058            }
1059
1060            /// Add a child sized [`Size::Auto`].
1061            #[must_use]
1062            pub fn child(self, child: impl Component<Output = M> + 'a) -> Self {
1063                $name(self.0.child(child))
1064            }
1065
1066            /// Add a child sized `size`.
1067            #[must_use]
1068            pub fn sized(self, size: Size, child: impl Component<Output = M> + 'a) -> Self {
1069                $name(self.0.sized(size, child))
1070            }
1071
1072            /// Leave `cells` empty between children.
1073            #[must_use]
1074            pub fn gap(self, cells: usize) -> Self {
1075                $name(self.0.gap(cells))
1076            }
1077
1078            /// See [`Stack::on`].
1079            #[must_use]
1080            pub fn on(
1081                self,
1082                action: &str,
1083                keys: impl IntoIterator<Item = Key>,
1084                description: &str,
1085                handler: impl FnMut() -> Flow<M> + 'a,
1086            ) -> Self {
1087                $name(self.0.on(action, keys, description, handler))
1088            }
1089
1090            /// See [`Stack::shortcut`].
1091            #[must_use]
1092            pub fn shortcut(
1093                self,
1094                action: &str,
1095                keys: impl IntoIterator<Item = Key>,
1096                description: &str,
1097                handler: impl FnMut() -> Flow<M> + 'a,
1098            ) -> Self {
1099                $name(self.0.shortcut(action, keys, description, handler))
1100            }
1101
1102            /// See [`Stack::rebind`].
1103            #[must_use]
1104            pub fn rebind(self, action: &str, keys: impl IntoIterator<Item = Key>) -> Self {
1105                $name(self.0.rebind(action, keys))
1106            }
1107
1108            /// See [`Stack::with_mouse`].
1109            #[must_use]
1110            pub fn with_mouse(self, on: bool) -> Self {
1111                $name(self.0.with_mouse(on))
1112            }
1113
1114            /// The stack inside.
1115            pub fn stack(&self) -> &Stack<'a, M> {
1116                &self.0
1117            }
1118
1119            pub fn stack_mut(&mut self) -> &mut Stack<'a, M> {
1120                &mut self.0
1121            }
1122        }
1123
1124        impl<'a, M> Component for $name<'a, M> {
1125            type Output = M;
1126
1127            fn start(&mut self, context: &Context<'_>) -> Flow<M> {
1128                self.0.start(context)
1129            }
1130
1131            fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
1132                self.0.handle(event, context)
1133            }
1134
1135            fn render(&self, context: &Context<'_>) -> View {
1136                self.0.render(context)
1137            }
1138
1139            fn tick(&self) -> Option<Duration> {
1140                self.0.tick()
1141            }
1142
1143            fn mouse(&self) -> bool {
1144                Component::mouse(&self.0)
1145            }
1146
1147            fn keymap(&self) -> Keymap {
1148                self.0.keymap()
1149            }
1150
1151            fn focusable(&self) -> bool {
1152                self.0.focusable()
1153            }
1154
1155            fn focus_step(&mut self, forward: bool) -> bool {
1156                self.0.focus_step(forward)
1157            }
1158
1159            fn focus_enter(&mut self, forward: bool) -> bool {
1160                self.0.focus_enter(forward)
1161            }
1162        }
1163    };
1164}
1165
1166axis_stack!(
1167    /// Children top to bottom: a [`Stack`] on the vertical axis. A child
1168    /// sized [`Size::Auto`] takes the rows it renders; flexible children
1169    /// share the rest of the height, and fill it.
1170    Column,
1171    Axis::Vertical
1172);
1173
1174axis_stack!(
1175    /// Children left to right: a [`Stack`] on the horizontal axis. Fixed
1176    /// children take their columns and the rest share what is left.
1177    Row,
1178    Axis::Horizontal
1179);
1180
1181// ---------------------------------------------------------------------------
1182// Split.
1183
1184/// Two children side by side ([`Split::horizontal`]) or one above the other
1185/// ([`Split::vertical`]), with a border between them. The border drags with
1186/// the mouse (#476's preview border, generalised, #479) and moves with
1187/// Alt+H/Alt+L (side by side) or Alt+K/Alt+J (stacked); each pane keeps its
1188/// minimum size. Tab moves focus between the panes.
1189pub struct Split<'a, M> {
1190    axis: Axis,
1191    group: Group<'a, M>,
1192    divider: Divider,
1193    ratio: u8,
1194    style: Style,
1195    bindings: Bindings<'a, M>,
1196    mouse: bool,
1197}
1198
1199impl<'a, M> Split<'a, M> {
1200    fn new(
1201        axis: Axis,
1202        first: impl Component<Output = M> + 'a,
1203        second: impl Component<Output = M> + 'a,
1204    ) -> Split<'a, M> {
1205        let mut group = Group::new();
1206        group.children.push(Box::new(first) as Child<'a, M>);
1207        group.children.push(Box::new(second) as Child<'a, M>);
1208        let mut bindings = Bindings::new("split").focus_keys();
1209        let (shrink, grow) = match axis {
1210            Axis::Horizontal => ("alt+h", "alt+l"),
1211            Axis::Vertical => ("alt+k", "alt+j"),
1212        };
1213        bindings.declare("shrink", keys(shrink), "move the border back", true);
1214        bindings.declare("grow", keys(grow), "move the border on", true);
1215        Split {
1216            axis,
1217            group,
1218            divider: Divider::new(1).min(1),
1219            ratio: 50,
1220            style: Theme::default().border,
1221            bindings,
1222            mouse: false,
1223        }
1224    }
1225
1226    /// `left` and `right`, side by side.
1227    pub fn horizontal(
1228        left: impl Component<Output = M> + 'a,
1229        right: impl Component<Output = M> + 'a,
1230    ) -> Split<'a, M> {
1231        Split::new(Axis::Horizontal, left, right)
1232    }
1233
1234    /// `top` above `bottom`. The split takes the whole height.
1235    pub fn vertical(
1236        top: impl Component<Output = M> + 'a,
1237        bottom: impl Component<Output = M> + 'a,
1238    ) -> Split<'a, M> {
1239        Split::new(Axis::Vertical, top, bottom)
1240    }
1241
1242    /// The first pane's share, in percent, until the border is moved
1243    /// (default 50).
1244    #[must_use]
1245    pub fn ratio(mut self, percent: u8) -> Self {
1246        self.ratio = percent.min(100);
1247        self
1248    }
1249
1250    /// Put the border after `cells` of the first pane, until moved.
1251    #[must_use]
1252    pub fn at(mut self, cells: usize) -> Self {
1253        self.divider.set_position(Some(cells));
1254        self
1255    }
1256
1257    /// Both panes at least `cells` along the axis (default 1).
1258    #[must_use]
1259    pub fn min(mut self, cells: usize) -> Self {
1260        self.divider.min_before = cells;
1261        self.divider.min_after = cells;
1262        self
1263    }
1264
1265    /// The first pane at least `first` cells and the second at least
1266    /// `second`.
1267    #[must_use]
1268    pub fn mins(mut self, first: usize, second: usize) -> Self {
1269        self.divider.min_before = first;
1270        self.divider.min_after = second;
1271        self
1272    }
1273
1274    /// The border's style (default: the theme's, dim).
1275    #[must_use]
1276    pub fn style(mut self, style: Style) -> Self {
1277        self.style = style;
1278        self
1279    }
1280
1281    binding_builders!();
1282
1283    pub fn axis(&self) -> Axis {
1284        self.axis
1285    }
1286
1287    /// The border: where it is, whether it is being dragged.
1288    pub fn divider(&self) -> &Divider {
1289        &self.divider
1290    }
1291
1292    pub fn first(&self) -> &(dyn Component<Output = M> + 'a) {
1293        &*self.group.children[0]
1294    }
1295
1296    pub fn second(&self) -> &(dyn Component<Output = M> + 'a) {
1297        &*self.group.children[1]
1298    }
1299
1300    pub fn first_mut(&mut self) -> &mut (dyn Component<Output = M> + 'a) {
1301        &mut *self.group.children[0]
1302    }
1303
1304    pub fn second_mut(&mut self) -> &mut (dyn Component<Output = M> + 'a) {
1305        &mut *self.group.children[1]
1306    }
1307
1308    /// The focused pane: 0 or 1.
1309    pub fn focused(&self) -> Option<usize> {
1310        self.group.focused()
1311    }
1312
1313    /// Focus pane `index` (0 or 1), if it takes focus.
1314    pub fn focus(&mut self, index: usize) -> bool {
1315        let takes = self
1316            .group
1317            .children
1318            .get_mut(index)
1319            .is_some_and(|child| child.focus_enter(true));
1320        if takes {
1321            self.group.focus = Some(index);
1322        }
1323        takes
1324    }
1325
1326    /// The cells along the axis, and the first pane's.
1327    fn extent(&self, context: &Context<'_>) -> (usize, usize) {
1328        let total = match self.axis {
1329            Axis::Horizontal => context.width,
1330            Axis::Vertical => context.height,
1331        };
1332        let default = self
1333            .divider
1334            .clamp(total * usize::from(self.ratio) / 100, total);
1335        (total, self.divider.resolve(total, default))
1336    }
1337
1338    /// The two panes' rectangles at `context`'s size.
1339    pub fn layout(&self, context: &Context<'_>) -> [Rect; 2] {
1340        let (total, first) = self.extent(context);
1341        let second = total.saturating_sub(first + self.divider.thickness);
1342        match self.axis {
1343            Axis::Horizontal => [
1344                Rect::new(0, 0, first, context.height),
1345                Rect::new(first + self.divider.thickness, 0, second, context.height),
1346            ],
1347            Axis::Vertical => [
1348                Rect::new(0, 0, context.width, first),
1349                Rect::new(0, first + self.divider.thickness, context.width, second),
1350            ],
1351        }
1352    }
1353}
1354
1355impl<M> Component for Split<'_, M> {
1356    type Output = M;
1357
1358    fn start(&mut self, context: &Context<'_>) -> Flow<M> {
1359        let rects = self.layout(context);
1360        self.group.start(context, |index| rects[index])
1361    }
1362
1363    fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
1364        let (total, first) = self.extent(context);
1365        if let Some(key) = event.key()
1366            && let Some(action) = self.bindings.action(key, true)
1367        {
1368            let step = match self.axis {
1369                Axis::Horizontal => 2,
1370                Axis::Vertical => 1,
1371            };
1372            match action.as_str() {
1373                "shrink" => self.divider.nudge(-step, first, total),
1374                "grow" => self.divider.nudge(step, first, total),
1375                _ => {
1376                    if let Some(flow) = self.bindings.run(&action) {
1377                        return flow;
1378                    }
1379                }
1380            }
1381            return Flow::Continue;
1382        }
1383        if let Event::Mouse(mouse) = event {
1384            let along = match self.axis {
1385                Axis::Horizontal => mouse.column as usize,
1386                Axis::Vertical => mouse.row as usize,
1387            };
1388            if self.divider.handle_mouse(mouse, along, first, total) {
1389                self.group.grab = None;
1390                return Flow::Continue;
1391            }
1392        }
1393        let [a, b] = self.layout(context);
1394        let flow = self
1395            .group
1396            .route(event, context, &[(0, a), (1, b)], Rect::default());
1397        self.group.settle();
1398        if !matches!(flow, Flow::Ignored) {
1399            return flow;
1400        }
1401        let Some(action) = event.key().and_then(|key| self.bindings.action(key, false)) else {
1402            return Flow::Ignored;
1403        };
1404        match action.as_str() {
1405            FOCUS_NEXT | FOCUS_PREVIOUS => {
1406                if self.group.focus_step(action == FOCUS_NEXT) {
1407                    Flow::Continue
1408                } else {
1409                    Flow::Ignored
1410                }
1411            }
1412            _ => self.bindings.run(&action).unwrap_or(Flow::Ignored),
1413        }
1414    }
1415
1416    fn render(&self, context: &Context<'_>) -> View {
1417        let [a, b] = self.layout(context);
1418        let focus = self.group.focused();
1419        let first = self.group.children[0].render(&a.context(context));
1420        let second = self.group.children[1].render(&b.context(context));
1421        match self.axis {
1422            Axis::Horizontal => {
1423                let rows = first
1424                    .lines
1425                    .len()
1426                    .max(second.lines.len())
1427                    .min(context.height)
1428                    .max(1);
1429                let border = vec![vec![kit::text("│", &self.style)]];
1430                side_by_side(&[(first, a), (second, b)], rows, focus, &border)
1431            }
1432            Axis::Vertical => {
1433                let mut out = View::new(rows_of(&first, a, true));
1434                out.lines
1435                    .push(vec![kit::text("─".repeat(context.width), &self.style)]);
1436                out.lines.extend(rows_of(&second, b, true));
1437                let (view, rect) = match focus {
1438                    Some(0) => (&first, a),
1439                    _ => (&second, b),
1440                };
1441                if let Some((row, column)) = view.cursor.filter(|(row, _)| *row < rect.height) {
1442                    out.cursor = Some((rect.y + row, column));
1443                }
1444                out
1445            }
1446        }
1447    }
1448
1449    fn tick(&self) -> Option<Duration> {
1450        self.group.tick()
1451    }
1452
1453    fn mouse(&self) -> bool {
1454        self.mouse || self.group.mouse()
1455    }
1456
1457    fn keymap(&self) -> Keymap {
1458        let focused = self
1459            .group
1460            .focused()
1461            .map(|index| &self.group.children[index]);
1462        keymap_with(focused, &self.bindings.keymap)
1463    }
1464
1465    fn focusable(&self) -> bool {
1466        self.group.focusable()
1467    }
1468
1469    fn focus_step(&mut self, forward: bool) -> bool {
1470        self.group.focus_step(forward)
1471    }
1472
1473    fn focus_enter(&mut self, forward: bool) -> bool {
1474        self.group.focus_enter(forward)
1475    }
1476}
1477
1478// ---------------------------------------------------------------------------
1479// Tabs.
1480
1481/// Children one at a time, under a bar of their titles (#478). Every tab
1482/// keeps its state while another shows; hidden tabs still get ticks and
1483/// resizes. Alt+Right or Ctrl+PageDown shows the next tab, Alt+Left or
1484/// Ctrl+PageUp the previous, Alt+1 to Alt+9 a tab by number, and a click
1485/// on a title that tab. These come before the tab's own keys; Tab and
1486/// Shift+Tab move focus inside the tab shown.
1487pub struct Tabs<'a, M> {
1488    titles: Vec<String>,
1489    group: Group<'a, M>,
1490    active: usize,
1491    selected: Style,
1492    unselected: Style,
1493    bindings: Bindings<'a, M>,
1494    mouse: bool,
1495}
1496
1497impl<'a, M> Default for Tabs<'a, M> {
1498    fn default() -> Self {
1499        Self::new()
1500    }
1501}
1502
1503impl<'a, M> Tabs<'a, M> {
1504    pub fn new() -> Tabs<'a, M> {
1505        let mut bindings = Bindings::new("tabs").focus_keys();
1506        bindings.declare("next", keys("alt+right ctrl+pagedown"), "next tab", true);
1507        bindings.declare(
1508            "previous",
1509            keys("alt+left ctrl+pageup"),
1510            "previous tab",
1511            true,
1512        );
1513        Tabs {
1514            titles: Vec::new(),
1515            group: Group::new(),
1516            active: 0,
1517            selected: Style::parse("bold reverse").expect("a built-in style"),
1518            unselected: Theme::default().hint,
1519            bindings,
1520            mouse: false,
1521        }
1522    }
1523
1524    /// Add a tab.
1525    #[must_use]
1526    pub fn tab(mut self, title: impl Into<String>, child: impl Component<Output = M> + 'a) -> Self {
1527        self.push(title, Box::new(child));
1528        self
1529    }
1530
1531    /// Add a tab to tabs already built.
1532    pub fn push(&mut self, title: impl Into<String>, child: Child<'a, M>) {
1533        self.titles.push(title.into());
1534        self.group.children.push(child);
1535        let number = self.titles.len();
1536        if number <= 9 {
1537            self.bindings.declare(
1538                &format!("tab-{number}"),
1539                keys(&format!("alt+{number}")),
1540                &format!("show tab {number}"),
1541                true,
1542            );
1543        }
1544    }
1545
1546    /// The styles of the shown tab's title and the others'.
1547    #[must_use]
1548    pub fn styles(mut self, selected: Style, unselected: Style) -> Self {
1549        self.selected = selected;
1550        self.unselected = unselected;
1551        self
1552    }
1553
1554    /// Show tab `index` first.
1555    #[must_use]
1556    pub fn active(mut self, index: usize) -> Self {
1557        self.select(index);
1558        self
1559    }
1560
1561    binding_builders!();
1562
1563    /// Show tab `index`.
1564    pub fn select(&mut self, index: usize) {
1565        if index < self.titles.len() {
1566            self.active = index;
1567            self.group.focus = Some(index);
1568        }
1569    }
1570
1571    /// The tab shown.
1572    pub fn selected(&self) -> usize {
1573        self.active
1574    }
1575
1576    pub fn titles(&self) -> &[String] {
1577        &self.titles
1578    }
1579
1580    pub fn len(&self) -> usize {
1581        self.titles.len()
1582    }
1583
1584    pub fn is_empty(&self) -> bool {
1585        self.titles.is_empty()
1586    }
1587
1588    /// Tab `index`'s child.
1589    pub fn get(&self, index: usize) -> Option<&(dyn Component<Output = M> + 'a)> {
1590        self.group.children.get(index).map(|child| &**child)
1591    }
1592
1593    pub fn get_mut(&mut self, index: usize) -> Option<&mut (dyn Component<Output = M> + 'a)> {
1594        self.group.children.get_mut(index).map(|child| &mut **child)
1595    }
1596
1597    /// The tab bar at `width`, and each title's columns.
1598    fn bar(&self, width: usize) -> (Vec<Segment>, Vec<(usize, usize)>) {
1599        let mut line = Vec::new();
1600        let mut spans = Vec::new();
1601        let mut at = 0;
1602        for (index, title) in self.titles.iter().enumerate() {
1603            if index > 0 {
1604                line.push(kit::plain(" "));
1605                at += 1;
1606            }
1607            // As painted: a control in a title shows as a one-cell picture,
1608            // so the spans clicks are matched against count it.
1609            let label = format!(" {} ", kit::shown(title));
1610            let cells = rich::cells::cell_len(&label);
1611            let style = if index == self.active {
1612                &self.selected
1613            } else {
1614                &self.unselected
1615            };
1616            line.push(kit::text(label, style));
1617            spans.push((at, at + cells));
1618            at += cells;
1619        }
1620        (kit::fit(line, width), spans)
1621    }
1622
1623    /// Where the shown tab's child is.
1624    pub fn content(&self, context: &Context<'_>) -> Rect {
1625        Rect::new(0, 1, context.width, context.height.saturating_sub(1))
1626    }
1627}
1628
1629impl<M> Component for Tabs<'_, M> {
1630    type Output = M;
1631
1632    fn start(&mut self, context: &Context<'_>) -> Flow<M> {
1633        let rect = self.content(context);
1634        let flow = self.group.start(context, |_| rect);
1635        self.group.focus = Some(self.active);
1636        flow
1637    }
1638
1639    fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
1640        let count = self.titles.len();
1641        if let Some(key) = event.key()
1642            && let Some(action) = self.bindings.action(key, true)
1643        {
1644            match action.as_str() {
1645                "next" if count > 0 => self.select((self.active + 1) % count),
1646                "previous" if count > 0 => self.select((self.active + count - 1) % count),
1647                number if number.starts_with("tab-") => {
1648                    if let Ok(n) = number[4..].parse::<usize>() {
1649                        self.select(n.saturating_sub(1));
1650                    }
1651                }
1652                _ => {
1653                    if let Some(flow) = self.bindings.run(&action) {
1654                        return flow;
1655                    }
1656                }
1657            }
1658            return Flow::Continue;
1659        }
1660        if let Event::Mouse(mouse) = event
1661            && mouse.row == 0
1662            && self.group.grab.is_none()
1663        {
1664            if mouse.is_click() {
1665                let (_, spans) = self.bar(context.width);
1666                let column = mouse.column as usize;
1667                if let Some(index) = spans.iter().position(|(a, b)| (*a..*b).contains(&column)) {
1668                    self.select(index);
1669                    return Flow::Continue;
1670                }
1671            }
1672            return Flow::Ignored;
1673        }
1674        let rect = self.content(context);
1675        self.group.focus = Some(self.active);
1676        let flow = self
1677            .group
1678            .route(event, context, &[(self.active, rect)], rect);
1679        if !matches!(flow, Flow::Ignored) {
1680            return flow;
1681        }
1682        let Some(action) = event.key().and_then(|key| self.bindings.action(key, false)) else {
1683            return Flow::Ignored;
1684        };
1685        match action.as_str() {
1686            FOCUS_NEXT | FOCUS_PREVIOUS => {
1687                let forward = action == FOCUS_NEXT;
1688                // No tabs, no child to step through.
1689                if self
1690                    .group
1691                    .children
1692                    .get_mut(self.active)
1693                    .is_some_and(|child| child.focus_step(forward))
1694                {
1695                    Flow::Continue
1696                } else {
1697                    Flow::Ignored
1698                }
1699            }
1700            _ => self.bindings.run(&action).unwrap_or(Flow::Ignored),
1701        }
1702    }
1703
1704    fn render(&self, context: &Context<'_>) -> View {
1705        let (bar, _) = self.bar(context.width);
1706        let mut out = View::new(vec![bar]);
1707        if let Some(child) = self.group.children.get(self.active) {
1708            let rect = self.content(context);
1709            let view = child.render(&rect.context(context));
1710            out.lines.extend(rows_of(&view, rect, false));
1711            if let Some((row, column)) = view.cursor.filter(|(row, _)| *row < rect.height) {
1712                out.cursor = Some((rect.y + row, column));
1713            }
1714        }
1715        out
1716    }
1717
1718    fn tick(&self) -> Option<Duration> {
1719        self.group.tick()
1720    }
1721
1722    fn mouse(&self) -> bool {
1723        self.mouse || self.group.mouse()
1724    }
1725
1726    fn keymap(&self) -> Keymap {
1727        keymap_with(self.group.children.get(self.active), &self.bindings.keymap)
1728    }
1729
1730    fn focusable(&self) -> bool {
1731        self.group
1732            .children
1733            .get(self.active)
1734            .is_some_and(|child| child.focusable())
1735    }
1736
1737    fn focus_step(&mut self, forward: bool) -> bool {
1738        let active = self.active;
1739        self.group
1740            .children
1741            .get_mut(active)
1742            .is_some_and(|child| child.focus_step(forward))
1743    }
1744
1745    fn focus_enter(&mut self, forward: bool) -> bool {
1746        let active = self.active;
1747        self.group
1748            .children
1749            .get_mut(active)
1750            .is_some_and(|child| child.focus_enter(forward))
1751    }
1752}
1753
1754// ---------------------------------------------------------------------------
1755// Layers.
1756
1757/// How a [`Layer`] sits over what is under it.
1758#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
1759pub enum LayerKind {
1760    /// Traps focus until dismissed, dims what is under it (a backdrop), and
1761    /// ignores clicks outside it.
1762    #[default]
1763    Modal,
1764    /// Takes the keys while open, but a click outside closes it, and there
1765    /// is no backdrop: a menu, a completion list.
1766    Popover,
1767}
1768
1769/// Where a [`Layer`] goes, border included, cut to the space there is.
1770#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1771pub enum Placement {
1772    /// This many cells, centred: horizontally in the width, vertically in
1773    /// the base's rows (or the layer's own height, if taller).
1774    Center { width: usize, height: usize },
1775    /// At this rectangle of the host's view.
1776    At(Rect),
1777}
1778
1779impl Default for Placement {
1780    fn default() -> Self {
1781        Placement::Center {
1782            width: 40,
1783            height: 10,
1784        }
1785    }
1786}
1787
1788/// A component shown over a [`Layers`] host's base: a modal dialog or a
1789/// popover. It closes when it answers (its flow still goes up, so a mapped
1790/// `Flow::Done` finishes the host), when it cancels or Escape reaches the
1791/// host unused (it is dismissed, the host carries on), or through a
1792/// [`LayerHandle`].
1793pub struct Layer<'a, M> {
1794    child: Child<'a, M>,
1795    kind: LayerKind,
1796    placement: Placement,
1797    title: Option<String>,
1798    border: bool,
1799    backdrop: bool,
1800    dismissable: bool,
1801    /// Whether the child took focus when opened: a layer whose child stops
1802    /// taking focus (it answered) closes; one that never took it (a label)
1803    /// stays until dismissed.
1804    took_focus: bool,
1805}
1806
1807impl<'a, M> Layer<'a, M> {
1808    fn new(kind: LayerKind, child: impl Component<Output = M> + 'a) -> Layer<'a, M> {
1809        Layer {
1810            child: Box::new(child),
1811            kind,
1812            placement: Placement::default(),
1813            title: None,
1814            border: true,
1815            backdrop: kind == LayerKind::Modal,
1816            dismissable: true,
1817            took_focus: false,
1818        }
1819    }
1820
1821    /// A modal layer: see [`LayerKind::Modal`].
1822    pub fn modal(child: impl Component<Output = M> + 'a) -> Layer<'a, M> {
1823        Layer::new(LayerKind::Modal, child)
1824    }
1825
1826    /// A popover: see [`LayerKind::Popover`].
1827    pub fn popover(child: impl Component<Output = M> + 'a) -> Layer<'a, M> {
1828        Layer::new(LayerKind::Popover, child)
1829    }
1830
1831    /// Centred, `width` × `height` cells with the border (default 40 × 10).
1832    #[must_use]
1833    pub fn size(mut self, width: usize, height: usize) -> Self {
1834        self.placement = Placement::Center { width, height };
1835        self
1836    }
1837
1838    #[must_use]
1839    pub fn placement(mut self, placement: Placement) -> Self {
1840        self.placement = placement;
1841        self
1842    }
1843
1844    /// A title in the top border.
1845    #[must_use]
1846    pub fn title(mut self, title: impl Into<String>) -> Self {
1847        self.title = Some(title.into());
1848        self
1849    }
1850
1851    /// Draw a border round it (default: yes).
1852    #[must_use]
1853    pub fn border(mut self, on: bool) -> Self {
1854        self.border = on;
1855        self
1856    }
1857
1858    /// Dim what is under it (default: for a modal).
1859    #[must_use]
1860    pub fn backdrop(mut self, on: bool) -> Self {
1861        self.backdrop = on;
1862        self
1863    }
1864
1865    /// Whether Escape, reaching the host unused, closes it (default: yes).
1866    #[must_use]
1867    pub fn dismissable(mut self, on: bool) -> Self {
1868        self.dismissable = on;
1869        self
1870    }
1871
1872    pub fn kind(&self) -> LayerKind {
1873        self.kind
1874    }
1875}
1876
1877enum Request<'a, M> {
1878    Open(Layer<'a, M>),
1879    Close,
1880}
1881
1882/// Opens and closes layers on a [`Layers`] host from anywhere: a binding's
1883/// handler, your own component, a timer. Requests take effect when the host
1884/// next handles an event (the one being handled, from inside it).
1885pub struct LayerHandle<'a, M> {
1886    requests: Rc<RefCell<Vec<Request<'a, M>>>>,
1887    open: Rc<Cell<usize>>,
1888}
1889
1890impl<M> Clone for LayerHandle<'_, M> {
1891    fn clone(&self) -> Self {
1892        LayerHandle {
1893            requests: Rc::clone(&self.requests),
1894            open: Rc::clone(&self.open),
1895        }
1896    }
1897}
1898
1899impl<'a, M> LayerHandle<'a, M> {
1900    /// Open `layer` over the others.
1901    pub fn open(&self, layer: Layer<'a, M>) {
1902        self.requests.borrow_mut().push(Request::Open(layer));
1903    }
1904
1905    /// Close the top layer.
1906    pub fn close(&self) {
1907        self.requests.borrow_mut().push(Request::Close);
1908    }
1909
1910    /// How many layers were open when the host last handled an event.
1911    pub fn open_count(&self) -> usize {
1912        self.open.get()
1913    }
1914}
1915
1916/// A base component with [`Layer`]s over it (#480): modal dialogs and
1917/// popovers. The top layer takes the keys; a modal also traps focus (Tab
1918/// cycles inside it) and dims the base. Escape dismisses the top layer when
1919/// the layer does not use it, and a layer that cancels is dismissed rather
1920/// than cancelling the host. With no layer open, the host is its base.
1921pub struct Layers<'a, M> {
1922    base: Child<'a, M>,
1923    layers: Vec<Layer<'a, M>>,
1924    requests: Rc<RefCell<Vec<Request<'a, M>>>>,
1925    open: Rc<Cell<usize>>,
1926    backdrop: Style,
1927    border: Style,
1928    bindings: Bindings<'a, M>,
1929    mouse: bool,
1930    grab: Option<Option<usize>>,
1931    handoff: Option<Option<usize>>,
1932}
1933
1934impl<'a, M> Layers<'a, M> {
1935    pub fn new(base: impl Component<Output = M> + 'a) -> Layers<'a, M> {
1936        let mut bindings = Bindings::new("layers").focus_keys();
1937        bindings.declare("dismiss", keys("escape"), "close the dialog", false);
1938        Layers {
1939            base: Box::new(base),
1940            layers: Vec::new(),
1941            requests: Rc::new(RefCell::new(Vec::new())),
1942            open: Rc::new(Cell::new(0)),
1943            backdrop: Style::parse("dim").expect("a built-in style"),
1944            border: Style::default(),
1945            bindings,
1946            mouse: false,
1947            grab: None,
1948            handoff: None,
1949        }
1950    }
1951
1952    /// A handle that opens and closes layers here.
1953    pub fn handle(&self) -> LayerHandle<'a, M> {
1954        LayerHandle {
1955            requests: Rc::clone(&self.requests),
1956            open: Rc::clone(&self.open),
1957        }
1958    }
1959
1960    /// Open `layer` now.
1961    pub fn open(&mut self, mut layer: Layer<'a, M>) {
1962        layer.took_focus = layer.child.focusable();
1963        self.layers.push(layer);
1964        self.open.set(self.layers.len());
1965    }
1966
1967    /// Close the top layer; `false` when none is open.
1968    pub fn close(&mut self) -> bool {
1969        let closed = self.layers.pop().is_some();
1970        self.open.set(self.layers.len());
1971        closed
1972    }
1973
1974    /// Open a layer made by `layer` when one of `keys` reaches the host
1975    /// unused, with no layer open: a help dialog on `?`, a palette on
1976    /// Ctrl+P.
1977    #[must_use]
1978    pub fn open_on(
1979        mut self,
1980        action: &str,
1981        keys: impl IntoIterator<Item = Key>,
1982        description: &str,
1983        mut layer: impl FnMut() -> Layer<'a, M> + 'a,
1984    ) -> Self
1985    where
1986        M: 'a,
1987    {
1988        let handle = self.handle();
1989        let keys = keys.into_iter().collect();
1990        self.bindings.on(action, keys, description, false, move || {
1991            handle.open(layer());
1992            Flow::Continue
1993        });
1994        self
1995    }
1996
1997    /// The style put over the base under a modal (default: dim).
1998    #[must_use]
1999    pub fn backdrop_style(mut self, style: Style) -> Self {
2000        self.backdrop = style;
2001        self
2002    }
2003
2004    /// The style of a layer's border (default: none).
2005    #[must_use]
2006    pub fn border_style(mut self, style: Style) -> Self {
2007        self.border = style;
2008        self
2009    }
2010
2011    binding_builders!();
2012
2013    /// How many layers are open.
2014    pub fn depth(&self) -> usize {
2015        self.layers.len()
2016    }
2017
2018    pub fn base(&self) -> &(dyn Component<Output = M> + 'a) {
2019        &*self.base
2020    }
2021
2022    pub fn base_mut(&mut self) -> &mut (dyn Component<Output = M> + 'a) {
2023        &mut *self.base
2024    }
2025
2026    /// Carry out the handles' requests; new layers start at `context`.
2027    fn apply(&mut self, context: &Context<'_>) -> Flow<M> {
2028        let requests: Vec<Request<'a, M>> = self.requests.borrow_mut().drain(..).collect();
2029        let mut result = Flow::Continue;
2030        for request in requests {
2031            match request {
2032                Request::Open(mut layer) => {
2033                    layer.took_focus = layer.child.focusable();
2034                    self.layers.push(layer);
2035                    let index = self.layers.len() - 1;
2036                    let inner = self.placements(context)[index].1;
2037                    let flow = self.layers[index].child.start(&inner.context(context));
2038                    if let Some(flow) = self.after_layer(index, flow) {
2039                        result = flow;
2040                    }
2041                }
2042                Request::Close => {
2043                    self.layers.pop();
2044                }
2045            }
2046        }
2047        self.open.set(self.layers.len());
2048        result
2049    }
2050
2051    /// Each open layer's outer and inner rectangles at `context`.
2052    pub fn placements(&self, context: &Context<'_>) -> Vec<(Rect, Rect)> {
2053        if self.layers.is_empty() {
2054            return Vec::new();
2055        }
2056        let rows = self.base.render(context).lines.len();
2057        self.layers
2058            .iter()
2059            .map(|layer| {
2060                let outer = match layer.placement {
2061                    Placement::Center { width, height } => {
2062                        let width = width.min(context.width);
2063                        let height = height.min(context.height.max(1));
2064                        let area = rows.max(height).min(context.height.max(height));
2065                        Rect::new(
2066                            (context.width - width) / 2,
2067                            (area - height) / 2,
2068                            width,
2069                            height,
2070                        )
2071                    }
2072                    Placement::At(rect) => {
2073                        let x = rect.x.min(context.width);
2074                        Rect::new(x, rect.y, rect.width.min(context.width - x), rect.height)
2075                    }
2076                };
2077                let inner = if layer.border && outer.width >= 2 && outer.height >= 2 {
2078                    Rect::new(outer.x + 1, outer.y + 1, outer.width - 2, outer.height - 2)
2079                } else {
2080                    outer
2081                };
2082                (outer, inner)
2083            })
2084            .collect()
2085    }
2086
2087    /// Close layer `index` if its flow ends it; the flow the host returns.
2088    fn after_layer(&mut self, index: usize, flow: Flow<M>) -> Option<Flow<M>> {
2089        let layer = &self.layers[index];
2090        let finished = layer.took_focus && !layer.child.focusable();
2091        match flow {
2092            Flow::Cancel => {
2093                self.layers.remove(index);
2094                Some(Flow::Continue)
2095            }
2096            Flow::Done(value) => {
2097                self.layers.remove(index);
2098                Some(Flow::Done(value))
2099            }
2100            Flow::Handoff(command) => {
2101                self.handoff = Some(Some(index));
2102                Some(Flow::Handoff(command))
2103            }
2104            flow if finished => {
2105                self.layers.remove(index);
2106                Some(match flow {
2107                    Flow::Ignored => Flow::Continue,
2108                    flow => flow,
2109                })
2110            }
2111            _ => None,
2112        }
2113    }
2114
2115    fn handle_top(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
2116        let top = self.layers.len() - 1;
2117        let places = self.placements(context);
2118        let (outer, inner) = places[top];
2119        match event {
2120            Event::Tick | Event::Resize { .. } => {
2121                let flow = self.broadcast(event, context, &places);
2122                return flow;
2123            }
2124            Event::Returned(_) => {
2125                return match self.handoff.take() {
2126                    Some(None) => self.base.handle(event, context),
2127                    Some(Some(index)) if index < self.layers.len() => {
2128                        let inner = places[index].1;
2129                        let flow = self.layers[index]
2130                            .child
2131                            .handle(event, &inner.context(context));
2132                        self.after_layer(index, flow).unwrap_or(Flow::Continue)
2133                    }
2134                    _ => Flow::Continue,
2135                };
2136            }
2137            Event::Mouse(mouse) => {
2138                let (column, row) = (mouse.column as usize, mouse.row as usize);
2139                let inside = outer.contains(column, row);
2140                let held = matches!(mouse.kind, MouseKind::Drag(_) | MouseKind::Up(_))
2141                    && self.grab == Some(Some(top));
2142                if let MouseKind::Down(_) = mouse.kind {
2143                    // Outside: held by nobody, so its release goes nowhere.
2144                    self.grab = Some(Some(if inside { top } else { usize::MAX }));
2145                }
2146                if !inside && !held {
2147                    if mouse.is_click() && self.layers[top].kind == LayerKind::Popover {
2148                        self.layers.pop();
2149                    }
2150                    if let MouseKind::Up(_) = mouse.kind {
2151                        self.grab = None;
2152                    }
2153                    return Flow::Continue;
2154                }
2155                if matches!(mouse.kind, MouseKind::Up(_)) {
2156                    self.grab = None;
2157                }
2158                if !self.layers[top].child.mouse() || !(inner.contains(column, row) || held) {
2159                    return Flow::Continue;
2160                }
2161                let event = Event::Mouse(inner.local(*mouse));
2162                let flow = self.layers[top]
2163                    .child
2164                    .handle(&event, &inner.context(context));
2165                return self.after_layer(top, flow).unwrap_or(Flow::Continue);
2166            }
2167            _ => {}
2168        }
2169        let flow = self.layers[top]
2170            .child
2171            .handle(event, &inner.context(context));
2172        let ignored = matches!(flow, Flow::Ignored);
2173        if let Some(flow) = self.after_layer(top, flow) {
2174            return flow;
2175        }
2176        if !ignored {
2177            return Flow::Continue;
2178        }
2179        // Unused by the layer: dismiss, move focus inside it, or stop here.
2180        let Some(action) = event.key().and_then(|key| self.bindings.action(key, false)) else {
2181            return Flow::Continue;
2182        };
2183        match action.as_str() {
2184            "dismiss" if self.layers[top].dismissable => {
2185                self.layers.pop();
2186            }
2187            FOCUS_NEXT | FOCUS_PREVIOUS => {
2188                let forward = action == FOCUS_NEXT;
2189                let child = &mut self.layers[top].child;
2190                if !child.focus_step(forward) {
2191                    child.focus_enter(forward);
2192                }
2193            }
2194            _ => {}
2195        }
2196        Flow::Continue
2197    }
2198
2199    fn broadcast(
2200        &mut self,
2201        event: &Event,
2202        context: &Context<'_>,
2203        places: &[(Rect, Rect)],
2204    ) -> Flow<M> {
2205        if !matches!(event, Event::Tick) || self.base.tick().is_some() {
2206            let flow = self.base.handle(event, context);
2207            if decisive(&flow) {
2208                return flow;
2209            }
2210        }
2211        let mut index = 0;
2212        while index < self.layers.len() {
2213            if matches!(event, Event::Tick) && self.layers[index].child.tick().is_none() {
2214                index += 1;
2215                continue;
2216            }
2217            let inner = places
2218                .get(index)
2219                .map_or(Rect::default(), |(_, inner)| *inner);
2220            let flow = self.layers[index]
2221                .child
2222                .handle(event, &inner.context(context));
2223            let count = self.layers.len();
2224            if let Some(flow) = self.after_layer(index, flow)
2225                && decisive(&flow)
2226            {
2227                return flow;
2228            }
2229            if self.layers.len() == count {
2230                index += 1;
2231            }
2232        }
2233        Flow::Continue
2234    }
2235
2236    /// The layer's box: its border and title round its view.
2237    fn boxed(
2238        &self,
2239        layer: &Layer<'a, M>,
2240        view: &View,
2241        outer: Rect,
2242        inner: Rect,
2243    ) -> Vec<Vec<Segment>> {
2244        let lines = rows_of(view, inner, true)
2245            .into_iter()
2246            .map(|line| kit::pad(line, inner.width))
2247            .collect::<Vec<_>>();
2248        if !(layer.border && inner != outer) {
2249            return lines;
2250        }
2251        kit::frame(lines, inner.width, layer.title.as_deref(), &self.border)
2252    }
2253}
2254
2255impl<M> Component for Layers<'_, M> {
2256    type Output = M;
2257
2258    fn start(&mut self, context: &Context<'_>) -> Flow<M> {
2259        let flow = self.base.start(context);
2260        if decisive(&flow) {
2261            return flow;
2262        }
2263        // Layers opened before the host started start with it.
2264        let places = self.placements(context);
2265        let mut index = 0;
2266        while index < self.layers.len() {
2267            let inner = places
2268                .get(index)
2269                .map_or(Rect::default(), |(_, inner)| *inner);
2270            let flow = self.layers[index].child.start(&inner.context(context));
2271            let count = self.layers.len();
2272            if let Some(flow) = self.after_layer(index, flow)
2273                && decisive(&flow)
2274            {
2275                return flow;
2276            }
2277            if self.layers.len() == count {
2278                index += 1;
2279            }
2280        }
2281        self.apply(context)
2282    }
2283
2284    fn handle(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
2285        let before = self.apply(context);
2286        if decisive(&before) {
2287            return before;
2288        }
2289        let flow = if self.layers.is_empty() {
2290            self.handle_base(event, context)
2291        } else {
2292            self.handle_top(event, context)
2293        };
2294        self.open.set(self.layers.len());
2295        if decisive(&flow) {
2296            return flow;
2297        }
2298        let after = self.apply(context);
2299        if decisive(&after) {
2300            return after;
2301        }
2302        flow
2303    }
2304
2305    fn render(&self, context: &Context<'_>) -> View {
2306        let base = self.base.render(context);
2307        if self.layers.is_empty() {
2308            return base;
2309        }
2310        let places = self.placements(context);
2311        let mut lines = base.lines;
2312        let mut cursor = None;
2313        for (index, layer) in self.layers.iter().enumerate() {
2314            let (outer, inner) = places[index];
2315            let view = layer.child.render(&inner.context(context));
2316            let boxed = self.boxed(layer, &view, outer, inner);
2317            let backdrop = layer.backdrop.then_some(&self.backdrop);
2318            kit::place(&mut lines, outer.x, outer.y, &boxed, backdrop);
2319            cursor = view
2320                .cursor
2321                .filter(|(row, column)| *row < inner.height && *column < inner.width.max(1))
2322                .map(|(row, column)| (inner.y + row, inner.x + column));
2323        }
2324        View { lines, cursor }
2325    }
2326
2327    fn tick(&self) -> Option<Duration> {
2328        self.layers
2329            .iter()
2330            .filter_map(|layer| layer.child.tick())
2331            .chain(self.base.tick())
2332            .min()
2333    }
2334
2335    fn mouse(&self) -> bool {
2336        self.mouse || self.base.mouse() || self.layers.iter().any(|layer| layer.child.mouse())
2337    }
2338
2339    fn keymap(&self) -> Keymap {
2340        match self.layers.last() {
2341            Some(layer) => keymap_with(Some(&layer.child), &self.bindings.keymap),
2342            None => keymap_with(Some(&self.base), &self.bindings.keymap),
2343        }
2344    }
2345
2346    fn focusable(&self) -> bool {
2347        match self.layers.last() {
2348            Some(_) => true,
2349            None => self.base.focusable(),
2350        }
2351    }
2352
2353    fn focus_step(&mut self, forward: bool) -> bool {
2354        match self.layers.last_mut() {
2355            // Focus stays in a layer: past its last stop, round to its first.
2356            Some(layer) => {
2357                if !layer.child.focus_step(forward) {
2358                    layer.child.focus_enter(forward);
2359                }
2360                true
2361            }
2362            None => self.base.focus_step(forward),
2363        }
2364    }
2365
2366    fn focus_enter(&mut self, forward: bool) -> bool {
2367        match self.layers.last_mut() {
2368            Some(layer) => {
2369                layer.child.focus_enter(forward);
2370                true
2371            }
2372            None => self.base.focus_enter(forward),
2373        }
2374    }
2375
2376    fn default_value(&self) -> Option<M> {
2377        self.base.default_value()
2378    }
2379
2380    fn prompt(&mut self, io: &mut dyn LineIo) -> Result<Option<M>, NotInteractive> {
2381        self.base.prompt(io)
2382    }
2383}
2384
2385impl<M> Layers<'_, M> {
2386    fn handle_base(&mut self, event: &Event, context: &Context<'_>) -> Flow<M> {
2387        if let Some(key) = event.key()
2388            && let Some(action) = self.bindings.action(key, true)
2389            && let Some(flow) = self.bindings.run(&action)
2390        {
2391            return flow;
2392        }
2393        if let Event::Mouse(mouse) = event {
2394            if !self.base.mouse() {
2395                return Flow::Ignored;
2396            }
2397            match mouse.kind {
2398                MouseKind::Down(_) => self.grab = Some(None),
2399                // A press that started on a layer (one since closed) is
2400                // not the base's to finish.
2401                MouseKind::Drag(_) | MouseKind::Up(_) if matches!(self.grab, Some(Some(_))) => {
2402                    if matches!(mouse.kind, MouseKind::Up(_)) {
2403                        self.grab = None;
2404                    }
2405                    return Flow::Continue;
2406                }
2407                MouseKind::Up(_) => self.grab = None,
2408                _ => {}
2409            }
2410        }
2411        if let Event::Returned(_) = event {
2412            self.handoff = None;
2413        }
2414        let flow = self.base.handle(event, context);
2415        if let Flow::Handoff(_) = flow {
2416            self.handoff = Some(None);
2417        }
2418        if !matches!(flow, Flow::Ignored) {
2419            return flow;
2420        }
2421        let Some(action) = event.key().and_then(|key| self.bindings.action(key, false)) else {
2422            return Flow::Ignored;
2423        };
2424        match action.as_str() {
2425            FOCUS_NEXT | FOCUS_PREVIOUS | "dismiss" => Flow::Ignored,
2426            _ => self.bindings.run(&action).unwrap_or(Flow::Ignored),
2427        }
2428    }
2429}