Skip to main content

tui_pages/dialog/
state.rs

1//! Dialog content and result types.
2
3/// The content of a modal dialog.
4///
5/// `D` is an application-owned "purpose" payload (often an enum) that the app
6/// uses to tell apart which dialog was answered. It is opaque to the library.
7///
8/// `DialogData` is stored as the focus manager's dialog payload via
9/// [`DialogData::show_intent`](crate::dialog::DialogData::show_intent); the
10/// focus manager tracks which button is active and navigates between them.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct DialogData<D = ()> {
13    pub title: String,
14    pub message: String,
15    pub buttons: Vec<String>,
16    pub purpose: Option<D>,
17    pub is_loading: bool,
18}
19
20impl<D> DialogData<D> {
21    /// A dialog with a title, message, selectable buttons, and a purpose used
22    /// to interpret the selection.
23    pub fn new(
24        title: impl Into<String>,
25        message: impl Into<String>,
26        buttons: impl IntoIterator<Item = impl Into<String>>,
27        purpose: D,
28    ) -> Self {
29        Self {
30            title: title.into(),
31            message: message.into(),
32            buttons: buttons.into_iter().map(Into::into).collect(),
33            purpose: Some(purpose),
34            is_loading: false,
35        }
36    }
37
38    /// A buttonless "please wait" dialog. Replace it with [`DialogData::new`]
39    /// (via [`show_intent`](DialogData::show_intent)) once the work completes.
40    pub fn loading(title: impl Into<String>, message: impl Into<String>) -> Self {
41        Self {
42            title: title.into(),
43            message: message.into(),
44            buttons: Vec::new(),
45            purpose: None,
46            is_loading: true,
47        }
48    }
49
50    pub fn button_count(&self) -> usize {
51        self.buttons.len()
52    }
53}
54
55/// The outcome of a dialog interaction.
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub enum DialogResult<D> {
58    /// The dialog was closed without choosing a button (e.g. a loading dialog,
59    /// or one dismissed with Esc).
60    Dismissed,
61    /// A button was chosen. `purpose` is the dialog's payload; `index` is which
62    /// button (0-based, left to right).
63    Selected { purpose: Option<D>, index: usize },
64}