126 lines
3.1 KiB
Rust
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]),
|
|
}
|
|
}
|
|
}
|