Mark b170f3f53f
Reworked renderer for Directives
Added OwnedTextArea & reworked textarea creation
Added ScrollBox
2024-02-07 15:58:14 -08:00

126 lines
3.1 KiB
Rust

use glyphon::{
cosmic_text::Align, Attrs, AttrsOwned, Buffer, Color, FamilyOwned, FontSystem, Metrics,
Shaping, Style, TextBounds, Weight,
};
use nalgebra::Vector2;
use rhai::ImmutableString;
use std::rc::Rc;
use winit::window::Window;
use super::{super::api::Rect, OwnedTextArea};
use crate::{ui::api, RenderInput};
#[derive(Debug)]
pub struct UiTextBox {
pub name: ImmutableString,
text: String,
justify: Align,
rect: Rect,
buffer: Rc<Buffer>,
color: api::Color,
attrs: AttrsOwned,
}
impl UiTextBox {
pub fn new(
font: &mut FontSystem,
name: ImmutableString,
font_size: f32,
line_height: f32,
rect: Rect,
color: api::Color,
) -> Self {
let mut buffer = Buffer::new(font, Metrics::new(font_size, line_height));
// Do NOT apply UI scale here, that's only done when we make a TextArea
buffer.set_size(font, rect.dim.x, rect.dim.y);
Self {
name,
rect,
buffer: Rc::new(buffer),
color,
justify: Align::Left,
attrs: AttrsOwned::new(Attrs::new()),
text: String::new(),
}
}
fn reflow(&mut self, font: &mut FontSystem) {
let buffer = Rc::get_mut(&mut self.buffer).unwrap();
buffer.set_text(font, &self.text, self.attrs.as_attrs(), Shaping::Advanced);
for l in &mut buffer.lines {
l.set_align(Some(self.justify));
}
buffer.shape_until_scroll(font);
}
pub fn set_text(&mut self, font: &mut FontSystem, text: &str) {
self.text.clear();
self.text.push_str(text);
self.reflow(font);
}
pub fn set_align(&mut self, font: &mut FontSystem, align: Align) {
self.justify = align;
self.reflow(font);
}
pub fn set_weight(&mut self, font: &mut FontSystem, weight: Weight) {
self.attrs.weight = weight;
self.reflow(font);
}
pub fn set_font(&mut self, font: &mut FontSystem, family: FamilyOwned) {
self.attrs.family_owned = family;
self.reflow(font);
}
pub fn set_style(&mut self, font: &mut FontSystem, style: Style) {
self.attrs.style = style;
self.reflow(font);
}
}
impl<'a, 'b: 'a> UiTextBox {
pub fn get_textarea(&'b self, input: &RenderInput, window: &Window) -> OwnedTextArea {
self.get_textarea_with_offset(input, window, Vector2::new(0.0, 0.0))
}
pub fn get_textarea_with_offset(
&'b self,
input: &RenderInput,
window: &Window,
offset: Vector2<f32>,
) -> OwnedTextArea {
let mut rect = self.rect.to_centered(window, input.ct.config.ui_scale);
rect.pos += offset;
// Glypon works with physical pixels, so we must do some conversion
let fac = window.scale_factor() as f32;
let corner_ne = Vector2::new(
(rect.pos.x - rect.dim.x / 2.0) * fac + window.inner_size().width as f32 / 2.0,
window.inner_size().height as f32 / 2.0 - (rect.pos.y * fac + rect.dim.y / 2.0),
);
let corner_sw = corner_ne + rect.dim * fac;
let c = self.color.as_array_u8();
OwnedTextArea {
buffer: self.buffer.clone(),
top: corner_ne.y,
left: corner_ne.x,
scale: input.ct.config.ui_scale,
bounds: TextBounds {
top: (corner_ne.y) as i32,
bottom: (corner_sw.y) as i32,
left: (corner_ne.x) as i32,
right: (corner_sw.x) as i32,
},
default_color: Color::rgba(c[0], c[1], c[2], c[3]),
}
}
}