Skip to main content

datui_lib/app/
overlay.rs

1//! What is open over the table: one dialog, panel or view at a time, and the one way
2//! back from it.
3
4use crate::{App, InputMode};
5
6/// The dialog, panel or view over the table. The one place that says which is open:
7/// keys go to it, and it is drawn over the table.
8#[derive(Debug, Default, Clone, PartialEq, Eq)]
9pub enum Overlay {
10    /// Nothing: the table, the query line or home, as `input_mode` says.
11    #[default]
12    None,
13    SortFilter,
14    PivotMelt,
15    /// The export dialog, over the table or Value Counts.
16    Export {
17        returns_to: Box<Overlay>,
18    },
19    /// The copy dialog.
20    Copy,
21    /// The row inspector.
22    Inspect,
23    /// The column picker: type a column's name to go to it.
24    GoToColumn,
25    /// The format picker over a table read through a spec: read it with another.
26    PickFormat,
27    /// A column's type, picked from the Info panel's Schema tab or the cell menu.
28    Retype {
29        returns_to: Box<Overlay>,
30    },
31    /// A datetime made from columns, as a spec's derived column.
32    Combine {
33        returns_to: Box<Overlay>,
34    },
35    /// The table picker over a table of a file of several: open another.
36    PickTable,
37    Info,
38    Chart,
39    /// The chart's export dialog, over the chart.
40    ChartExport,
41    /// Value Counts: how often each value of one column occurs in the view.
42    ValueCounts,
43    /// The hex view: a file's bytes.
44    Hex,
45    /// The Sample form (`S`).
46    Sample,
47    /// The analysis screen (`a`).
48    Analysis,
49    /// The saved views sidebar (`V`).
50    View,
51}
52
53impl Overlay {
54    /// What closing this overlay goes back to.
55    fn back(self) -> Overlay {
56        match self {
57            Overlay::Export { returns_to }
58            | Overlay::Retype { returns_to }
59            | Overlay::Combine { returns_to } => *returns_to,
60            Overlay::ChartExport => Overlay::Chart,
61            _ => Overlay::None,
62        }
63    }
64
65    /// Whether `overlay` is open: this one, or one under it that it goes back to,
66    /// which is drawn beneath it.
67    pub fn shows(&self, overlay: &Overlay) -> bool {
68        self == overlay
69            || match self {
70                Overlay::Export { returns_to }
71                | Overlay::Retype { returns_to }
72                | Overlay::Combine { returns_to } => returns_to.shows(overlay),
73                Overlay::ChartExport => *overlay == Overlay::Chart,
74                _ => false,
75            }
76    }
77}
78
79impl App {
80    /// Open `overlay`. It is over the table: the query line, or home, is left.
81    pub(crate) fn open_overlay(&mut self, overlay: Overlay) {
82        self.show_table();
83        self.overlay = overlay;
84    }
85
86    /// The table takes the keys: home, or the command line, is left.
87    pub(crate) fn show_table(&mut self) {
88        self.input_mode = InputMode::Normal;
89        self.prompt.input_type = None;
90    }
91
92    /// Open an overlay over the one open now, which closing it goes back to.
93    pub(crate) fn open_over(&mut self, overlay: impl FnOnce(Box<Overlay>) -> Overlay) {
94        let under = std::mem::take(&mut self.overlay);
95        self.open_overlay(overlay(Box::new(under)));
96    }
97
98    /// Close the overlay, dropping what it held for this opening, and go back to
99    /// what it was opened over.
100    pub fn close_overlay(&mut self) {
101        match self.overlay {
102            Overlay::Copy => self.copy_modal.close(),
103            Overlay::Inspect => self.inspector_modal.close(),
104            Overlay::SortFilter => self.sort_filter_modal.close(),
105            Overlay::PivotMelt => self.pivot_melt_modal.close(),
106            Overlay::Export { .. } => self.export_modal.close(),
107            Overlay::Retype { .. } | Overlay::Combine { .. } => {
108                self.column_forms.retype = None;
109                self.column_forms.combine = None;
110            }
111            Overlay::Sample => self.sample.form = None,
112            Overlay::PickTable => self.pickers.table_choices = None,
113            Overlay::Hex => {
114                self.stop_hex_find();
115                self.hex.close();
116            }
117            Overlay::Chart => {
118                self.chart.modal.close();
119                self.reset_chart_state();
120            }
121            Overlay::ChartExport => self.chart.export_modal.close(),
122            Overlay::Analysis => self.analysis_modal.close(),
123            Overlay::View => self.view_modal.close(),
124            _ => {}
125        }
126        self.step_back();
127    }
128
129    /// Close every overlay, down to the table.
130    pub(crate) fn close_overlays(&mut self) {
131        while self.overlay != Overlay::None {
132            self.close_overlay();
133        }
134    }
135
136    /// Go back to what the overlay was opened over, keeping what it holds: it waits
137    /// behind a question, or while it runs, to come back as it was.
138    pub(crate) fn step_back(&mut self) {
139        self.overlay = std::mem::take(&mut self.overlay).back();
140    }
141
142    /// The plain table or the query line: no overlay, and not home.
143    pub fn at_table(&self) -> bool {
144        self.overlay == Overlay::None && self.input_mode == InputMode::Normal
145    }
146}