use std::any::Any;
use super::{Element, ViewLimits};
use super::context::{BasicContext, Context};
use crate::support::color::Color;
use crate::support::font::Font;
use crate::support::point::Point;
use crate::support::theme::get_theme;
pub struct Label {
text: String,
font: Font,
font_size: f32,
color: Color,
}
impl Label {
pub fn new(text: impl Into<String>) -> Self {
let theme = get_theme();
Self {
text: text.into(),
font: theme.label_font.clone(),
font_size: theme.label_font_size,
color: theme.label_font_color,
}
}
pub fn set_text(&mut self, text: impl Into<String>) {
self.text = text.into();
}
pub fn text(&self) -> &str {
&self.text
}
pub fn with_font(mut self, font: Font) -> Self {
self.font = font;
self
}
pub fn with_font_size(mut self, size: f32) -> Self {
self.font_size = size;
self
}
pub fn with_color(mut self, color: Color) -> Self {
self.color = color;
self
}
pub fn font(&self) -> &Font {
&self.font
}
pub fn font_size(&self) -> f32 {
self.font_size
}
pub fn color(&self) -> Color {
self.color
}
}
impl Element for Label {
fn limits(&self, ctx: &BasicContext) -> ViewLimits {
let estimated_width = self.text.len() as f32 * self.font_size * 0.6;
let estimated_height = self.font_size * 1.2;
ViewLimits::fixed(estimated_width, estimated_height)
}
fn stretch(&self) -> super::ViewStretch {
super::ViewStretch::new(0.0, 0.0)
}
fn draw(&self, ctx: &Context) {
let mut canvas = ctx.canvas.borrow_mut();
canvas.fill_style(self.color);
canvas.font(self.font.clone());
canvas.font_size(self.font_size);
let text_pos = Point::new(
ctx.bounds.left,
ctx.bounds.top + self.font_size * 0.8,
);
canvas.fill_text(&self.text, text_pos);
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub struct Heading {
label: Label,
}
impl Heading {
pub fn new(text: impl Into<String>) -> Self {
let theme = get_theme();
Self {
label: Label::new(text)
.with_font(theme.heading_font.clone())
.with_font_size(theme.heading_font_size)
.with_color(theme.heading_font_color),
}
}
pub fn set_text(&mut self, text: impl Into<String>) {
self.label.set_text(text);
}
pub fn text(&self) -> &str {
self.label.text()
}
}
impl Element for Heading {
fn limits(&self, ctx: &BasicContext) -> ViewLimits {
self.label.limits(ctx)
}
fn draw(&self, ctx: &Context) {
self.label.draw(ctx);
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub struct StaticText {
text: &'static str,
font_size: f32,
color: Color,
}
impl StaticText {
pub const fn new(text: &'static str) -> Self {
Self {
text,
font_size: 14.0,
color: Color::new(0.8, 0.8, 0.8, 1.0),
}
}
pub const fn with_font_size(mut self, size: f32) -> Self {
self.font_size = size;
self
}
pub const fn with_color(mut self, color: Color) -> Self {
self.color = color;
self
}
}
impl Element for StaticText {
fn limits(&self, ctx: &BasicContext) -> ViewLimits {
let estimated_width = self.text.len() as f32 * self.font_size * 0.6;
let estimated_height = self.font_size * 1.2;
ViewLimits::fixed(estimated_width, estimated_height)
}
fn draw(&self, ctx: &Context) {
let mut canvas = ctx.canvas.borrow_mut();
canvas.fill_style(self.color);
canvas.font_size(self.font_size);
let text_pos = Point::new(
ctx.bounds.left,
ctx.bounds.top + self.font_size * 0.8,
);
canvas.fill_text(self.text, text_pos);
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub fn label(text: impl Into<String>) -> Label {
Label::new(text)
}
pub fn heading(text: impl Into<String>) -> Heading {
Heading::new(text)
}
pub const fn static_text(text: &'static str) -> StaticText {
StaticText::new(text)
}