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