use crate::render::callbacks::CallbackRegistry;
use crate::render::layout_cache::LayoutContainer;
use crate::render::widget::*;
use crate::render::widget_cache::WidgetContainer;
use crate::render::widget_config::*;
use crate::render::{Points, Size};
use sdl2::render::{Canvas, Texture, TextureQuery};
use sdl2::ttf::FontStyle;
use sdl2::video::Window;
use crate::render::texture_cache::TextureCache;
use crate::render::texture_store::TextureStore;
use sdl2::rect::Rect;
use std::any::Any;
use std::collections::HashMap;
use std::path::Path;
pub enum TextJustify {
Left,
Center,
Right,
}
pub struct TextWidget {
config: WidgetConfig,
system_properties: HashMap<i32, String>,
callback_registry: CallbackRegistry,
texture_store: TextureStore,
font_name: String,
font_style: FontStyle,
font_size: i32,
justification: TextJustify,
msg: String,
}
impl TextWidget {
pub fn new(
font_name: String,
font_style: FontStyle,
font_size: i32,
justification: TextJustify,
msg: String,
points: Points,
size: Size,
) -> Self {
Self {
config: WidgetConfig::new(points, size),
system_properties: HashMap::new(),
callback_registry: CallbackRegistry::new(),
texture_store: TextureStore::default(),
font_name,
font_style,
font_size,
justification,
msg,
}
}
pub fn set_text(&mut self, msg: String) {
self.msg = msg;
self.get_config().set_invalidated(true);
}
pub fn get_text(&self) -> String {
self.msg.clone()
}
}
impl Widget for TextWidget {
fn draw(&mut self, c: &mut Canvas<Window>, t: &mut TextureCache) -> Option<&Texture> {
if self.get_config().invalidated() {
let bounds = self.get_config().get_size(CONFIG_SIZE);
self.texture_store
.create_or_resize_texture(c, bounds[0] as u32, bounds[1] as u32);
let base_color = self.get_color(CONFIG_COLOR_BASE);
let text_max_width = self.get_size(CONFIG_SIZE)[0]
- ((self.get_numeric(CONFIG_BORDER_WIDTH) * 2) as u32);
let ttf_context = t.get_ttf_context();
let texture_creator = c.texture_creator();
let mut font = ttf_context
.load_font(Path::new(&self.font_name), self.font_size as u16)
.unwrap();
let font_color = self.get_color(CONFIG_COLOR_TEXT);
font.set_style(self.font_style);
let surface = font
.render(&self.msg)
.blended_wrapped(font_color, text_max_width)
.map_err(|e| e.to_string())
.unwrap();
let font_texture = texture_creator
.create_texture_from_surface(&surface)
.map_err(|e| e.to_string())
.unwrap();
let TextureQuery { width, height, .. } = font_texture.query();
let texture_y = 0;
let widget_w = self.get_size(CONFIG_SIZE)[0] as i32;
let texture_x = match self.justification {
TextJustify::Left => 0,
TextJustify::Right => widget_w - width as i32,
TextJustify::Center => (widget_w - width as i32) / 2,
};
c.with_texture_canvas(self.texture_store.get_mut_ref(), |texture| {
texture.set_draw_color(base_color);
texture.clear();
texture
.copy(
&font_texture,
None,
Rect::new(texture_x, texture_y, width, height),
)
.unwrap();
})
.unwrap();
}
self.texture_store.get_optional_ref()
}
fn on_config_changed(&mut self, _k: u8, _v: Config) {
match _k {
CONFIG_COLOR_TEXT => self.get_config().set_invalidated(true),
CONFIG_COLOR_BASE => self.get_config().set_invalidated(true),
CONFIG_FONT_SIZE => {
if let Config::Numeric(size) = _v {
self.font_size = size;
self.get_config().set_invalidated(true);
}
}
CONFIG_TEXT => {
if let Config::Text(text) = _v {
self.msg = text;
self.get_config().set_invalidated(true);
}
}
_ => (),
};
}
default_widget_functions!();
default_widget_properties!();
default_widget_callbacks!();
}