canary-rs/scripts/sao-ui/src/widgets/text.rs

158 lines
3.9 KiB
Rust
Raw Normal View History

2022-10-07 21:52:35 +00:00
// Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: AGPL-3.0-or-later
2022-07-31 05:33:55 +00:00
use super::prelude::*;
2022-07-21 21:19:57 +00:00
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum HorizontalAlignment {
Left,
Center,
Right,
}
pub struct LabelText {
pub font: Font,
pub text: String,
}
pub struct Label {
text: LabelText,
alignment: HorizontalAlignment,
scale: f32,
color: Color,
left: f32,
right: f32,
baseline: f32,
dirty: bool,
layout: Option<TextLayout>,
2022-07-21 21:19:57 +00:00
bounds: Rect,
offset: Vec2,
}
impl Label {
pub fn new(
text: LabelText,
alignment: HorizontalAlignment,
scale: f32,
color: Color,
left: f32,
right: f32,
baseline: f32,
) -> Self {
Self {
text,
alignment,
scale,
color,
left,
right,
baseline,
dirty: true,
layout: None,
2022-07-21 21:19:57 +00:00
bounds: Rect::from_xy_size(Vec2::ZERO, Vec2::ZERO),
offset: Vec2::ZERO,
}
}
2022-11-07 01:27:43 +00:00
pub fn new_centered(text: LabelText, scale: f32, color: Color) -> Self {
Self::new(
text,
HorizontalAlignment::Center,
scale,
color,
0.0,
0.0,
0.0,
)
}
pub fn set_text(&mut self, text: &str) {
if self.text.text != text {
self.text.text = text.to_string();
self.layout = None;
self.dirty = true;
}
}
2022-07-21 21:19:57 +00:00
}
impl Widget for Label {
fn draw(&mut self, ctx: &DrawContext) {
if self.dirty {
let layout = TextLayout::new(&self.text.font, &self.text.text);
let bounds = Rect::from(layout.get_bounds()).scale(self.scale);
self.bounds = bounds;
let xoff = match self.alignment {
2022-11-05 21:03:30 +00:00
HorizontalAlignment::Left => self.left - bounds.tl.x,
HorizontalAlignment::Right => self.right - bounds.br.x,
2022-07-21 21:19:57 +00:00
HorizontalAlignment::Center => {
let available = self.right - self.left;
let halfway = available / 2.0 + self.left;
2022-11-05 21:03:30 +00:00
let width = bounds.br.x - bounds.tl.x;
2022-07-21 21:19:57 +00:00
let left = halfway - width / 2.0;
2022-11-05 21:03:30 +00:00
left - bounds.tl.x
2022-07-21 21:19:57 +00:00
}
};
2022-07-27 06:08:10 +00:00
self.offset = Vec2::new(xoff, self.baseline);
self.dirty = false;
self.layout = Some(layout);
}
if let Some(layout) = self.layout.as_ref() {
ctx.draw_text_layout(layout, self.offset, self.scale, self.color);
}
}
}
pub struct Icon {
text: LabelText,
scale: f32,
color: Color,
center: Vec2,
dirty: bool,
layout: Option<TextLayout>,
bounds: Rect,
offset: Vec2,
}
impl Icon {
pub fn new(text: LabelText, scale: f32, color: Color, center: Vec2) -> Self {
Self {
text,
scale,
color,
center,
dirty: true,
layout: None,
bounds: Rect::from_xy_size(Vec2::ZERO, Vec2::ZERO),
offset: Vec2::ZERO,
}
}
2022-11-07 02:00:56 +00:00
pub fn set_text(&mut self, text: &str) {
if self.text.text != text {
self.text.text = text.to_string();
self.layout = None;
self.dirty = true;
}
}
2022-07-27 06:08:10 +00:00
}
2022-07-21 21:19:57 +00:00
2022-07-27 06:08:10 +00:00
impl Widget for Icon {
fn draw(&mut self, ctx: &DrawContext) {
if self.dirty {
let layout = TextLayout::new(&self.text.font, &self.text.text);
let bounds = Rect::from(layout.get_bounds()).scale(self.scale);
self.bounds = bounds;
self.offset = self.center - bounds.size() / 2.0;
2022-11-05 21:03:30 +00:00
self.offset.y -= bounds.tl.y;
2022-07-21 21:19:57 +00:00
self.dirty = false;
self.layout = Some(layout);
2022-07-21 21:19:57 +00:00
}
if let Some(layout) = self.layout.as_ref() {
ctx.draw_text_layout(layout, self.offset, self.scale, self.color);
}
2022-07-21 21:19:57 +00:00
}
}