rpick/
ui.rs

1/* Copyright © 2021-2023 Randy Barlow
2This program is free software: you can redistribute it and/or modify
3it under the terms of the GNU General Public License as published by
4the Free Software Foundation, version 3 of the License.
5
6This program is distributed in the hope that it will be useful,
7but WITHOUT ANY WARRANTY; without even the implied warranty of
8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9GNU General Public License for more details.
10
11You should have received a copy of the GNU General Public License
12along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
13//! # The Ui Trait
14//!
15//! The Ui Trait defines an interface for bridging human interactions with the rpick crate.
16
17/// An individual cell within rpick's chance tables.
18///
19/// Each of the variants expresses its contained type, and should be fairly obvious.
20#[non_exhaustive]
21#[derive(Debug, PartialEq)]
22pub enum Cell<'a> {
23    Boolean(bool),
24    Text(&'a str),
25    Integer(i64),
26    Float(f64),
27    Unsigned(u64),
28}
29
30impl From<f64> for Cell<'_> {
31    fn from(f: f64) -> Self {
32        Self::Float(f)
33    }
34}
35
36impl<'a> From<&'a str> for Cell<'a> {
37    fn from(s: &'a str) -> Self {
38        Self::Text(s)
39    }
40}
41
42impl From<u64> for Cell<'_> {
43    fn from(u: u64) -> Self {
44        Self::Unsigned(u)
45    }
46}
47
48impl From<&Cell<'_>> for String {
49    fn from(c: &Cell) -> String {
50        match c {
51            Cell::Boolean(value) => value.to_string(),
52            Cell::Text(value) => value.to_string(),
53            Cell::Integer(value) => value.to_string(),
54            Cell::Float(value) => value.to_string(),
55            Cell::Unsigned(value) => value.to_string(),
56        }
57    }
58}
59
60/// Represents a row in the [`Table`] struct.
61#[derive(Debug, PartialEq)]
62pub struct Row<'a> {
63    /// The row's individual cells.
64    pub cells: Vec<Cell<'a>>,
65    /// Whether this row was chosen in a rpick.
66    pub chosen: bool,
67}
68
69/// rpick uses this to send a chance table to the user.
70#[derive(Debug, PartialEq)]
71pub struct Table<'a> {
72    /// The Table's footer.
73    pub footer: Vec<Cell<'a>>,
74    /// The Table's header.
75    pub header: Vec<Cell<'a>>,
76    /// The Table's rows.
77    pub rows: Vec<Row<'a>>,
78}
79
80/// A struct implementing this trait must be passed to the rpick engine.
81///
82/// This is how rpick interacts with users.
83pub trait Ui {
84    /// If this method returns `true`, [`Ui::display_table`] will be called by the engine.
85    ///
86    /// This is a small optimization - generating tables that the Ui isn't going to show to the
87    /// user or otherwise use is a waste of compute time. If the table isn't going to get used,
88    /// this method should return `false`.
89    fn call_display_table(&self) -> bool;
90
91    /// Display the given table to the user.
92    fn display_table(&self, table: &Table);
93
94    /// Display the given message to the user.
95    fn info(&self, message: &str);
96
97    /// Prompt the user if they wish to accept the given choice.
98    ///
99    /// Return `true` if the user accepts the choice.
100    fn prompt_choice(&self, choice: &str) -> bool;
101}