use raqote::{DrawTarget, Source, DrawOptions, Color}; use crate::wayland::{ draw::{Draw, DrawArea}, Position, }; pub(super) struct UIColors { draw_area: Color, button: Color, button_accent: Color, background: Color, _text_area: Color, _symbol: Color, _text: Color, } impl Default for UIColors { fn default() -> Self { Self { draw_area: Color::new(0xff, 0x15, 0x15, 0x15), button: Color::new(0xff, 0x22, 0x22, 0x22), button_accent: Color::new(0xff, 0x33, 0x33, 0x33), background: Color::new(0xff, 0x11, 0x11, 0x11), _text_area: Color::new(0xff, 0x33, 0x33, 0x33), _symbol: Color::new(0xff, 0xcc, 0xcc, 0xcc), _text: Color::new(0xff, 0xdd, 0xdd, 0xdd), } } } pub(super) enum Widget { Button(Button), TextArea(TextArea) } pub(super) struct Window { pub(super) width: usize, pub(super) height: usize, pub(super) widgets: Vec, pub(super) draw_area: DrawArea, pub(super) colors: UIColors, pub(super) options: DrawOptions, } impl Window { pub(super) fn new(width: usize, height: usize, draw_area: DrawArea) -> Self { Self { width, height, widgets: Vec::new(), draw_area, colors: UIColors::default(), options: DrawOptions::new(), } } pub(super) fn add_widget(&mut self, widget: Widget) { self.widgets.push(widget); } pub(super) fn render(&self, canvas: &mut [u8]) { // TODO: Make sure this is actually safe let draw_buffer: &mut [u32] = unsafe {canvas.align_to_mut::().1}; let mut target = DrawTarget::from_backing(self.width as i32, self.height as i32, draw_buffer); target.fill_rect( 0.0, 0.0, self.width as f32, self.height as f32, &Source::Solid(self.colors.background.into()), &self.options ); self.draw_area.render(&mut target); for widget in self.widgets.iter() { match widget { Widget::Button(button) => button.render(&mut target), Widget::TextArea(text_area) => text_area.render(&mut target), } } } } pub(super) struct ButtonColors { background: Color, border: Color, glyph: Color, } impl Default for ButtonColors { fn default() -> Self { Self { background: Color::new(0xff, 0x25, 0x2c, 0x33), border: Color::new(0xff, 0x77, 0x7f, 0x97), glyph: Color::new(0xff, 0xea, 0xea, 0xe6), } } } pub(super) struct Button { pub(super) width: f32, pub(super) height: f32, pub(super) position: Position, pub(super) shape: raqote::Path, pub(super) colors: ButtonColors, pub(super) options: DrawOptions, } impl Button { fn background_source(&self) -> Source { Source::Solid(self.colors.background.into()) } pub(crate) fn contains_point(&self, point: Position) -> bool { self.shape.contains_point(0.1, point.x, point.y) } } impl Draw for Button { fn render(&self, area: &mut DrawTarget<&mut [u32]>) { area.fill( &self.shape, &self.background_source(), &self.options, ); } } pub(super) struct TextAreaColors { pub(super) background: Color, pub(super) text: Color, } impl Default for TextAreaColors { fn default() -> Self { Self { background: Color::new(0xff, 0x25, 0x2c, 0x33), text: Color::new(0xff, 0xfc, 0xf8, 0xef), } } } pub(super) struct TextArea { pub(super) width: f32, pub(super) height: f32, pub(super) position: Position, pub(super) colors: TextAreaColors, pub(super) options: DrawOptions, } impl TextArea { pub(super) fn text_source(&self) -> Source { Source::Solid(self.colors.text.into()) } pub(super) fn background_source(&self) -> Source { Source::Solid(self.colors.background.into()) } } impl Draw for TextArea { fn render(&self, area: &mut DrawTarget<&mut [u32]>) { area.fill_rect( self.position.x, self.position.y, self.width, self.height, &self.background_source(), &self.options, ); } }