inquire/ui/style.rs
1//! Contains definitions to apply style to rendered contents.
2
3use std::fmt::Display;
4
5use bitflags::bitflags;
6
7use super::Color;
8
9bitflags! {
10 /// Attributes to apply to a text via the [StyleSheet] struct.
11 ///
12 /// These attributes are flags and can thus be combined.
13 ///
14 /// # Example
15 ///
16 /// ```
17 /// use inquire::ui::Attributes;
18 ///
19 /// let attributes = Attributes::ITALIC | Attributes::BOLD;
20 ///
21 /// assert!(attributes.contains(Attributes::BOLD));
22 /// assert!(attributes.contains(Attributes::ITALIC));
23 /// ```
24 pub struct Attributes: u8 {
25 /// Increases the text intensity
26 const BOLD = 0b01;
27
28 /// Emphasises the text.
29 const ITALIC = 0b10;
30 }
31}
32
33/// Style definitions that can be applied to the rendered content.
34///
35/// # Example
36///
37/// ```
38/// use inquire::ui::{Attributes, Color, StyleSheet};
39///
40/// let style_sheet = StyleSheet::default();
41///
42/// assert!(style_sheet.is_empty());
43///
44/// let style_sheet = style_sheet
45/// .with_bg(Color::DarkBlue)
46/// .with_attr(Attributes::ITALIC | Attributes::BOLD);
47///
48/// assert!(!style_sheet.is_empty());
49/// ```
50#[derive(Copy, Clone, Debug, PartialEq, Eq)]
51pub struct StyleSheet {
52 /// Foreground color of text.
53 pub fg: Option<Color>,
54 /// Background color of text.
55 pub bg: Option<Color>,
56 /// Attributes applied to text.
57 pub att: Attributes,
58}
59
60impl StyleSheet {
61 /// Creates a style sheet with no colors and no attributes
62 pub fn new() -> Self {
63 Self::empty()
64 }
65
66 /// A stylesheet with no colors and no attributes.
67 pub fn empty() -> Self {
68 Self {
69 fg: None,
70 bg: None,
71 att: Attributes::empty(),
72 }
73 }
74
75 /// Check if the stylesheet contains no colors and no attributes.
76 pub fn is_empty(&self) -> bool {
77 self.fg.is_none() && self.bg.is_none() && self.att.is_empty()
78 }
79
80 /// Copies the StyleSheet to a new one set with the defined foreground [Color].
81 pub fn with_fg(mut self, fg: Color) -> Self {
82 self.fg = Some(fg);
83 self
84 }
85
86 /// Copies the StyleSheet to a new one set with the defined background [Color].
87 pub fn with_bg(mut self, bg: Color) -> Self {
88 self.bg = Some(bg);
89 self
90 }
91
92 /// Copies the style sheet to a new one with the specified attributes.
93 ///
94 /// Warning: this does not keep the previously applied attributes. If you want
95 /// to just set a new attribute and keep the others, you need to apply the OR
96 /// operation yourself.
97 ///
98 /// # Example
99 ///
100 /// ```
101 /// use inquire::ui::{Attributes, Color, StyleSheet};
102 ///
103 /// let style_sheet = StyleSheet::default().with_attr(Attributes::BOLD);
104 /// assert_eq!(true, style_sheet.att.contains(Attributes::BOLD));
105 /// assert_eq!(false, style_sheet.att.contains(Attributes::ITALIC));
106 ///
107 /// let style_sheet = style_sheet.with_attr(Attributes::ITALIC);
108 /// assert_eq!(false, style_sheet.att.contains(Attributes::BOLD));
109 /// assert_eq!(true, style_sheet.att.contains(Attributes::ITALIC));
110 ///
111 /// let style_sheet = style_sheet.with_attr(style_sheet.att | Attributes::BOLD);
112 /// assert_eq!(true, style_sheet.att.contains(Attributes::BOLD));
113 /// assert_eq!(true, style_sheet.att.contains(Attributes::ITALIC));
114 /// ```
115 pub fn with_attr(mut self, attributes: Attributes) -> Self {
116 self.att = attributes;
117 self
118 }
119}
120
121impl Default for StyleSheet {
122 /// A stylesheet with no colors and no attributes.
123 fn default() -> Self {
124 Self::empty()
125 }
126}
127
128/// Represents a content that when rendered must have the associated style
129/// applied to it.
130#[derive(Clone, Debug)]
131pub struct Styled<T>
132where
133 T: Display,
134{
135 /// Content to be rendered.
136 pub content: T,
137
138 /// Style sheet to be applied to content when rendered.
139 pub style: StyleSheet,
140}
141
142impl<T> Styled<T>
143where
144 T: Display,
145{
146 /// Creates a new `Styled` object with the specified content
147 /// and a default (empty) style sheet.
148 pub fn new(content: T) -> Self {
149 Self {
150 content,
151 style: StyleSheet::default(),
152 }
153 }
154
155 /// Sets the style sheet to the styled struct.
156 #[allow(unused)]
157 pub fn with_style_sheet(mut self, style_sheet: StyleSheet) -> Self {
158 self.style = style_sheet;
159 self
160 }
161
162 /// Sets the styled content to have the defined foreground [Color].
163 pub fn with_fg(mut self, fg: Color) -> Self {
164 self.style.fg = Some(fg);
165 self
166 }
167
168 /// Sets the styled content to have the defined foreground [Color].
169 pub fn with_bg(mut self, bg: Color) -> Self {
170 self.style.bg = Some(bg);
171 self
172 }
173
174 /// Sets the styled content to have the defined attributes.
175 ///
176 /// Warning: this does not keep the previously applied attributes. If you want
177 /// to just set a new attribute and keep the others, you need to apply the OR
178 /// operation yourself.
179 pub fn with_attr(mut self, attributes: Attributes) -> Self {
180 self.style.att = attributes;
181 self
182 }
183}
184
185impl<T> Copy for Styled<T> where T: Copy + Display {}