From 1d082409813bfe98f509aa733cd9914dd95f9053 Mon Sep 17 00:00:00 2001 From: FantasyPvP <80643031+FantasyPvP@users.noreply.github.com> Date: Wed, 22 Nov 2023 00:36:23 +0000 Subject: [PATCH] gui stuff gui stuff --- src/system/std/frame.rs | 4 +- src/user/bin/shell.rs | 26 ++++++++-- src/user/lib/gui_v2/mod.rs | 2 +- src/user/lib/gui_v2/widgets.rs | 86 +++++++++++++++++++++++++--------- 4 files changed, 90 insertions(+), 28 deletions(-) diff --git a/src/system/std/frame.rs b/src/system/std/frame.rs index fa2895c..12ae3e8 100644 --- a/src/system/std/frame.rs +++ b/src/system/std/frame.rs @@ -59,8 +59,8 @@ impl Element { #[derive(Clone)] pub struct ColouredElement { - frame: Vec>, - dimensions: (u8, u8) + pub frame: Vec>, + pub dimensions: (u8, u8) } impl ColouredElement { diff --git a/src/user/bin/shell.rs b/src/user/bin/shell.rs index 0e259a2..a81e40c 100644 --- a/src/user/bin/shell.rs +++ b/src/user/bin/shell.rs @@ -7,10 +7,14 @@ use alloc::{boxed::Box, string::{String, ToString}, vec, vec::Vec}; use vga::writers::{GraphicsWriter, PrimitiveDrawing}; use crate::{print, printerr, println, std, std::application::{Application, Error}, user::bin::*}; +use crate::kernel::render::ScreenChar; +use crate::std::frame::ColouredElement; use crate::std::io::{Color, write, Screen, Stdin, Serial}; use crate::std::random::Random; use crate::user::bin::gigachad_detector::GigachadDetector; use crate::user::bin::grapher::Grapher; +use crate::user::lib::gui_v2; +use crate::user::lib::gui_v2::widgets::GuiComponent; lazy_static! { pub static ref CMD: Mutex = Mutex::new(CommandHandler::new()); @@ -177,10 +181,24 @@ async fn exec() -> Result<(), Error> { timer(); } "test_features" => { - use crate::std::random::Random; - println!("{}", Random::int(0, 10)); - // use crate::user::lib::libgui; - // libgui::libgui_core::test_elements(); + + std::io::Screen::application_mode(); + + let mut container = gui_v2::widgets::Container::new( + gui_v2::widgets::Position::new(2, 2), + gui_v2::widgets::Dimensions::new(10, 10), + true, + ); + let res = container.render().unwrap().render(); + + let mut elem = ColouredElement { + frame: res as Vec>, + dimensions: (container.dimensions.x as u8, container.dimensions.y as u8), + }; + + elem.render((2, 2)).unwrap(); + + } _ => { return Err(Error::UnknownCommand( diff --git a/src/user/lib/gui_v2/mod.rs b/src/user/lib/gui_v2/mod.rs index 1e04bdf..f8e41a3 100644 --- a/src/user/lib/gui_v2/mod.rs +++ b/src/user/lib/gui_v2/mod.rs @@ -1,2 +1,2 @@ -mod widgets; +pub mod widgets; diff --git a/src/user/lib/gui_v2/widgets.rs b/src/user/lib/gui_v2/widgets.rs index f009ca9..ebfd847 100644 --- a/src/user/lib/gui_v2/widgets.rs +++ b/src/user/lib/gui_v2/widgets.rs @@ -1,6 +1,8 @@ +use alloc::boxed::Box; use alloc::string::String; use alloc::vec; use alloc::vec::Vec; +use core::slice::from_mut; use crate::kernel::render::ScreenChar; use crate::printerr; use crate::user::lib::gui_v2::widgets::XorY::Both; @@ -11,7 +13,13 @@ pub struct Position { pub y: usize, } -#[derive(Copy, Clone)] +impl Position { + pub fn new(x: usize, y: usize) -> Position { + Position { x, y } + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] pub enum XorY { X, Y, @@ -19,6 +27,7 @@ pub enum XorY { None, } + impl XorY { pub fn setx(&mut self) { if self == &XorY::None { @@ -37,6 +46,7 @@ impl XorY { } +#[derive(Debug)] pub enum GuiError { OutOfBounds(XorY) } @@ -44,7 +54,7 @@ pub enum GuiError { pub type Dimensions = Position; pub type ColouredChar = ScreenChar; -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct Frame { position: Position, dimensions: Dimensions, @@ -52,12 +62,12 @@ pub struct Frame { } impl Frame { - pub fn new(position: Position, dimensions: Dimensions) -> Frame { - Frame { + pub fn new(position: Position, dimensions: Dimensions) -> Result { + Ok(Frame { position, dimensions, frame: vec![vec![ScreenChar::null(); dimensions.x]; dimensions.y], - } + }) } pub fn render(&self) -> Vec> { self.frame.clone() @@ -100,7 +110,7 @@ impl Frame { if should_panic { panic!( "Element is to large to be rendered {} {}", - .dimensions().y + element.position().y, + element.dimensions().y + element.position().y, self.dimensions.y ) } else { @@ -119,35 +129,69 @@ impl Frame { pub trait GuiComponent { - fn render(&self) -> Frame; + fn render(&self) -> Result; } pub struct Container { pub frame: Vec>, - pub elements: Vec, + pub elements: Vec>, pub position: Position, pub dimensions: Dimensions, + pub outlined: bool, } +impl Container { + + pub fn new(position: Position, dimensions: Dimensions, outlined: bool) -> Container { + Container { + frame: vec![vec![ScreenChar::null(); dimensions.x]; dimensions.y], + elements: Vec::new(), + position, + dimensions, + outlined, + } + } + + fn render_outline(&self, frame: &mut Frame) { + // draws the sides of the container + for i in 0..frame.dimensions.x { + frame.set_pos(Position::new(i, 0), ColouredChar::white('│' as u8)); + frame.set_pos(Position::new(i, frame.dimensions.y - 1), ColouredChar::white('│' as u8)); + } + + // draws the top and bottom of the container + for i in 0..frame.dimensions.y { + frame.set_pos(Position::new(0, i), ColouredChar::white('─' as u8)); + frame.set_pos(Position::new(frame.dimensions.x - 1, i), ColouredChar::white('─' as u8)); + } + + // draws the corners of the container + frame.set_pos(Position::new(0, 0), ColouredChar::white('┌' as u8)); + frame.set_pos(Position::new(self.dimensions.x - 1, 0), ColouredChar::white('┐' as u8)); + frame.set_pos(Position::new(0, self.dimensions.y - 1), ColouredChar::white('└' as u8)); + frame.set_pos(Position::new(self.dimensions.x - 1, self.dimensions.y - 1), ColouredChar::white('┘' as u8)); + } +} + + impl GuiComponent for Container { fn render(&self) -> Result { + let mut result = Frame::new(self.position, self.dimensions)?; - let mut frame = Frame::new(self.position, self.dimensions); - - for element in &self.elements { - match frame.render_bounds_check(element, true) { // TODO: this needs to be set to false for production - Ok(()) => { - let r = (*element).render(); - frame.render_element(&r); - } - Err(e) => { - return Err(GuiError::OutOfBounds(e)); - } + for widget in &self.elements { + let frame = widget.render()?; + match result.render_bounds_check(&frame, true) { // TODO: this needs to be set to false for production + Ok(()) => result.render_element(&frame), + Err(e) => return Err(GuiError::OutOfBounds(e)), } } - - Ok(frame) + + if self.outlined { + self.render_outline(&mut result); + } + + Ok(result) } }