#![crate_name = "direct_gui"]
#[cfg(feature = "file-loading")]
use std::path::Path;
use std::{error::Error, fmt};
pub mod controls;
mod font;
mod resources;
pub use blit::Color;
use controls::*;
pub use font::FontSettings;
use resources::*;
pub use resources::{FontRef, SpriteRef};
#[derive(Debug, Clone)]
pub struct InvalidControlReference;
impl fmt::Display for InvalidControlReference {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "reference to control object doesn't exist anymore")
}
}
impl Error for InvalidControlReference {
fn description(&self) -> &str {
"reference to control object doesn't exist anymore"
}
fn cause(&self) -> Option<&dyn Error> {
None
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ControlRef(usize);
pub struct Gui {
size: (i32, i32),
resources: Resources,
controls: Vec<(ControlRef, Box<dyn Control>)>,
control_ref: usize,
}
impl Gui {
pub fn new(size: (i32, i32)) -> Self {
Gui {
size,
resources: Resources::new(),
controls: Vec::new(),
control_ref: 0,
}
}
pub fn update(&mut self, state: &ControlState) {
for control_tuple in self.controls.iter_mut() {
control_tuple.1.update(state, &self.resources);
}
}
pub fn draw_to_buffer(&mut self, buffer: &mut Vec<u32>) {
for control_tuple in self.controls.iter_mut() {
control_tuple
.1
.draw(buffer, self.size.0 as usize, &self.resources);
}
}
pub fn draw_label<S: Into<String>>(
&mut self,
buffer: &mut Vec<u32>,
font_ref: FontRef,
string: S,
pos: (i32, i32),
) {
let font = self.resources.get_font(font_ref).unwrap();
font.draw_string(buffer, self.size.0 as usize, string.into(), pos);
}
pub fn register<T: 'static + Control>(&mut self, ctrl: T) -> ControlRef {
self.control_ref += 1;
self.controls
.push((ControlRef(self.control_ref), Box::new(ctrl)));
ControlRef(self.control_ref)
}
pub fn get<T: 'static + Control>(&self, control_ref: ControlRef) -> Result<&T, Box<dyn Error>> {
match self.controls.iter().find(|&c| c.0 == control_ref) {
Some(c) => match c.1.as_any().downcast_ref::<T>() {
Some(obj) => Ok(obj),
None => Err(Box::new(InvalidControlReference)),
},
None => Err(Box::new(InvalidControlReference)),
}
}
pub fn get_mut<T: 'static + Control>(
&mut self,
control_ref: ControlRef,
) -> Result<&mut T, Box<dyn Error>> {
match self.controls.iter_mut().find(|c| c.0 == control_ref) {
Some(c) => match c.1.as_any_mut().downcast_mut::<T>() {
Some(obj) => Ok(obj),
None => Err(Box::new(InvalidControlReference)),
},
None => Err(Box::new(InvalidControlReference)),
}
}
pub fn default_font(&self) -> FontRef {
self.resources.default_font()
}
#[cfg(feature = "file-loading")]
pub fn load_sprite_from_file<P>(
&mut self,
path: P,
mask_color: Color,
) -> Result<SpriteRef, Box<dyn Error>>
where
P: AsRef<Path>,
{
self.resources.load_sprite_from_file(path, mask_color)
}
pub fn load_sprite_from_memory(&mut self, buffer: &[u8]) -> Result<SpriteRef, Box<dyn Error>> {
self.resources.load_sprite_from_memory(buffer)
}
#[cfg(feature = "file-loading")]
pub fn load_font_sprite_from_file<P>(
&mut self,
path: P,
settings: FontSettings,
) -> Result<FontRef, Box<dyn Error>>
where
P: AsRef<Path>,
{
self.resources.load_font_sprite_from_file(path, settings)
}
pub fn load_font_sprite_from_memory(
&mut self,
buffer: &[u8],
settings: FontSettings,
) -> Result<FontRef, Box<dyn Error>> {
self.resources
.load_font_sprite_from_memory(buffer, settings)
}
}