use egui::{Color32, RichText, Ui, Widget};
use crate::Theme;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TextSize {
Xs,
Sm,
#[default]
Md,
Lg,
Xl,
Xl2,
Xl3,
}
impl TextSize {
pub fn to_size(self, theme: &Theme) -> f32 {
match self {
TextSize::Xs => theme.font_size_xs,
TextSize::Sm => theme.font_size_sm,
TextSize::Md => theme.font_size_md,
TextSize::Lg => theme.font_size_lg,
TextSize::Xl => theme.font_size_xl,
TextSize::Xl2 => theme.font_size_2xl,
TextSize::Xl3 => theme.font_size_3xl,
}
}
}
#[derive(Clone)]
pub struct Text<'a> {
content: &'a str,
size: TextSize,
color: Option<Color32>,
bold: bool,
italic: bool,
strikethrough: bool,
underline: bool,
}
impl<'a> Text<'a> {
pub fn new(content: &'a str) -> Self {
Self {
content,
size: TextSize::Md,
color: None,
bold: false,
italic: false,
strikethrough: false,
underline: false,
}
}
pub fn h1(content: &'a str) -> Self {
Self::new(content).size(TextSize::Xl3).bold()
}
pub fn h2(content: &'a str) -> Self {
Self::new(content).size(TextSize::Xl2).bold()
}
pub fn h3(content: &'a str) -> Self {
Self::new(content).size(TextSize::Xl).bold()
}
pub fn body(content: &'a str) -> Self {
Self::new(content).size(TextSize::Md)
}
pub fn small(content: &'a str) -> Self {
Self::new(content).size(TextSize::Sm)
}
pub fn caption(content: &'a str) -> Self {
Self::new(content).size(TextSize::Xs)
}
pub fn large(content: &'a str) -> Self {
Self::new(content).size(TextSize::Lg)
}
pub fn size(mut self, size: TextSize) -> Self {
self.size = size;
self
}
pub fn color(mut self, color: Color32) -> Self {
self.color = Some(color);
self
}
pub fn muted(mut self) -> Self {
self.color = None; self
}
pub fn bold(mut self) -> Self {
self.bold = true;
self
}
pub fn italic(mut self) -> Self {
self.italic = true;
self
}
pub fn strikethrough(mut self) -> Self {
self.strikethrough = true;
self
}
pub fn underline(mut self) -> Self {
self.underline = true;
self
}
pub fn show(self, ui: &mut Ui) {
ui.add(self);
}
fn to_rich_text(&self, theme: &Theme) -> RichText {
let mut text = RichText::new(self.content).size(self.size.to_size(theme));
let color = self.color.unwrap_or(theme.text_primary);
text = text.color(color);
if self.bold {
text = text.strong();
}
if self.italic {
text = text.italics();
}
if self.strikethrough {
text = text.strikethrough();
}
if self.underline {
text = text.underline();
}
text
}
}
impl<'a> Widget for Text<'a> {
fn ui(self, ui: &mut Ui) -> egui::Response {
let theme = Theme::current(ui.ctx());
let rich_text = self.to_rich_text(&theme);
ui.label(rich_text)
}
}
impl<'a> Text<'a> {
pub fn secondary(content: &'a str) -> Self {
Self::new(content) }
}
pub struct MutedText<'a> {
inner: Text<'a>,
}
impl<'a> MutedText<'a> {
pub fn new(content: &'a str) -> Self {
Self {
inner: Text::new(content),
}
}
pub fn show(self, ui: &mut Ui) {
let theme = Theme::current(ui.ctx());
let text = self.inner.color(theme.text_muted);
ui.add(text);
}
}
impl<'a> Widget for MutedText<'a> {
fn ui(self, ui: &mut Ui) -> egui::Response {
let theme = Theme::current(ui.ctx());
let text = self.inner.color(theme.text_muted);
ui.add(text)
}
}