Skip to content

Commit

Permalink
started working on dialogs
Browse files Browse the repository at this point in the history
  • Loading branch information
FantasyPvP committed Mar 20, 2024
1 parent b0da719 commit e80df51
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 460 deletions.
10 changes: 8 additions & 2 deletions src/system/std/frame.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use crate::system::kernel::render::{BUFFER_HEIGHT, BUFFER_WIDTH, RENDERER, ScreenChar};
use crate::system::kernel::render::{RENDERER, ScreenChar};
use crate::std::io::{Color, Screen};

/// TODO: get a working implementation for CLI apps
Expand All @@ -12,7 +12,13 @@ use crate::std::io::{Color, Screen};
/// nothing will appear on the screen until the frame is actually rendered by
/// the write_to_screen() method on the renderer
pub use crate::system::kernel::render::{special_char, RenderError, ColorCode};
pub use crate::system::kernel::render::{
special_char,
RenderError,
ColorCode,
BUFFER_WIDTH,
BUFFER_HEIGHT
};


#[derive(Clone, Copy, Debug, PartialEq)]
Expand Down
1 change: 1 addition & 0 deletions src/user/bin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ mod gameoflife;
mod tetris;
mod asteroids;
mod crystalrpg;
mod pong;
57 changes: 57 additions & 0 deletions src/user/bin/pong.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use async_trait::async_trait;
use core::fmt::Write;
use crate::std::application::{Application, Error};
use crate::std;

struct Game {
ball: Ball,
player1: Player,
player2: Player,
}

#[async_trait]
impl Application for Game {
fn new() -> Self {
Game {
ball: Ball::new(),
player1: Player::new(1),
player2: Player::new(2),
}
}

async fn run(&mut self, _: Vec<String>) -> Result<(), Error> {
loop {
self.ball.update(&self.player1, &self.player2);
}
Ok(())
}
}

struct Player {
x: i32,
y: i32,
score: i32,
}

impl Player {
fn new(y: i32) -> Self {
Player { x: 0, y, score: 0 }
}
}

struct Ball {
x: i32,
y: i32,
}

impl Ball {
fn new() -> Self {
Ball { x: 0, y: 0 }
}
fn update(&mut self, player1: &Player, player2: &Player) {
self.x += 1;
}
}
13 changes: 13 additions & 0 deletions src/user/bin/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::user::lib::libgui::{
cg_inputs::CgLineEdit,
};
use crate::user::lib::libgui::cg_core::{CgTextInput, Widget};
use crate::user::lib::libgui::cg_widgets::CgDialog;

lazy_static! {
pub static ref CMD: Mutex<CommandHandler> = Mutex::new(CommandHandler::new());
Expand Down Expand Up @@ -253,6 +254,18 @@ struct CmdHistory {
}

async fn setup_ui() {
let dialog = CgDialog::new(
Dimensions::new(40, 10),
String::from("test dialog"),
String::from("dialog body"),
String::from("[dialog footer]")
);

if let Ok(frame) = dialog.render() {
frame.write_to_screen().unwrap();
}
return;

serial_println!("idk");
let label= Widget::insert(CgLabel::new(
String::from("test label"),
Expand Down
6 changes: 4 additions & 2 deletions src/user/lib/libgui/cg_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub trait CgComponent: Any {
fn as_any(&self) -> &dyn Any;
}


/// trait for components that can have editable text, such as search boxes, command palettes, terminals, text inputs etc.
pub trait CgTextEdit: CgComponent {
fn write_char(&mut self, c: char); // this can also be implemented in a way that inserts characters
Expand All @@ -43,7 +42,10 @@ pub trait CgTextInput: CgTextEdit {
async fn input(&mut self, break_condition: fn(KeyStroke) -> (KeyStroke, Exit), id: &Widget, app: &Widget) -> Result<(String, bool), RenderError>;
}


#[async_trait]
pub trait CgKeyboardCapture: CgComponent {
async fn keyboard_capture(&mut self, break_condition: fn(KeyStroke) -> (KeyStroke, Exit), app: Option<&Widget>) -> Result<bool, RenderError>;
}

static ID_COUNTER: Mutex<usize> = Mutex::new(0);

Expand Down
21 changes: 21 additions & 0 deletions src/user/lib/libgui/cg_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::std::frame::{ColouredChar, Dimensions, Frame, Position};

pub(crate) fn render_outline(frame: &mut Frame, dimensions: Dimensions) {
// draws the sides of the container
for i in 0..frame.dimensions.x {
frame.write(Position::new(i, 0), ColouredChar::new('─'));
frame.write(Position::new(i, frame.dimensions.y - 1), ColouredChar::new('─'));
}

// draws the top and bottom of the container
for i in 0..frame.dimensions.y {
frame.write(Position::new(0, i), ColouredChar::new('│'));
frame.write(Position::new(frame.dimensions.x - 1, i), ColouredChar::new('│'));
}

// draws the corners of the container
frame.write(Position::new(0, 0), ColouredChar::new('┌'));
frame.write(Position::new(dimensions.x - 1, 0), ColouredChar::new('┐'));
frame.write(Position::new(0, dimensions.y - 1), ColouredChar::new('└'));
frame.write(Position::new(dimensions.x - 1, dimensions.y - 1), ColouredChar::new('┘'));
}
102 changes: 49 additions & 53 deletions src/user/lib/libgui/cg_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use core::cmp::{max, min};
use hashbrown::HashMap;
use crate::serial_println;
use super::cg_core::{CgComponent, CgOutline, Widget};
use crate::std::frame::{ColouredChar, Dimensions, Position, Frame, RenderError, ColorCode};
use super::cg_utils::render_outline;
use crate::std::frame::{ColouredChar, Dimensions, Position, Frame, RenderError, ColorCode, BUFFER_WIDTH, BUFFER_HEIGHT};
use crate::std::io::Color;

#[derive(Debug, Clone)]
Expand All @@ -33,29 +34,6 @@ impl CgContainer {
self.elements.get(name)
}
}

impl CgOutline for CgContainer {
fn render_outline(&self, frame: &mut Frame) {
// draws the sides of the container
for i in 0..frame.dimensions.x {
frame.write(Position::new(i, 0), ColouredChar::new('─'));
frame.write(Position::new(i, frame.dimensions.y - 1), ColouredChar::new('─'));
}

// draws the top and bottom of the container
for i in 0..frame.dimensions.y {
frame.write(Position::new(0, i), ColouredChar::new('│'));
frame.write(Position::new(frame.dimensions.x - 1, i), ColouredChar::new('│'));
}

// draws the corners of the container
frame.write(Position::new(0, 0), ColouredChar::new('┌'));
frame.write(Position::new(self.dimensions.x - 1, 0), ColouredChar::new('┐'));
frame.write(Position::new(0, self.dimensions.y - 1), ColouredChar::new('└'));
frame.write(Position::new(self.dimensions.x - 1, self.dimensions.y - 1), ColouredChar::new('┘'));
}
}

impl CgComponent for CgContainer {
fn render(&self) -> Result<Frame, RenderError> {
let mut result = Frame::new(self.position, self.dimensions)?;
Expand All @@ -68,7 +46,7 @@ impl CgComponent for CgContainer {
}

if self.outlined {
self.render_outline(&mut result);
render_outline(&mut result, self.dimensions.clone());
}

Ok(result)
Expand Down Expand Up @@ -115,7 +93,7 @@ impl CgComponent for CgTextBox {
let mut result = Frame::new(self.position, self.dimensions)?;

if self.outlined {
self.render_outline(&mut result);
render_outline(&mut result, self.dimensions.clone());
}

self.render_title(&mut result);
Expand Down Expand Up @@ -161,32 +139,6 @@ impl CgComponent for CgTextBox {
}
}


impl CgOutline for CgTextBox {
fn render_outline(&self, frame: &mut Frame) {
// draws the sides of the container
for i in 0..frame.dimensions.x {
frame.write(Position::new(i, 0), ColouredChar::new('─'));
frame.write(Position::new(i, frame.dimensions.y - 1), ColouredChar::new('─'));
}

// draws the top and bottom of the container
for i in 0..frame.dimensions.y {
frame.write(Position::new(0, i), ColouredChar::new('│'));
frame.write(Position::new(frame.dimensions.x - 1, i), ColouredChar::new('│'));
}

// draws the corners of the container
frame.write(Position::new(0, 0), ColouredChar::new('┌'));
frame.write(Position::new(self.dimensions.x - 1, 0), ColouredChar::new('┐'));
frame.write(Position::new(0, self.dimensions.y - 1), ColouredChar::new('└'));
frame.write(Position::new(self.dimensions.x - 1, self.dimensions.y - 1), ColouredChar::new('┘'));
}
}




#[derive(Debug, Clone)]
pub struct CgLabel {
content: String,
Expand Down Expand Up @@ -349,7 +301,7 @@ impl CgComponent for CgStatusBar {
fn render(&self) -> Result<Frame, RenderError> {
let mut frame = Frame::new(self.position, self.dimensions)?;

(0..80).for_each(|x| frame[0][x] = ColouredChar::coloured(' ', ColorCode::new(Color::Black, Color::DarkGray)));
(0..BUFFER_WIDTH).for_each(|x| frame[0][x] = ColouredChar::coloured(' ', ColorCode::new(Color::Black, Color::DarkGray)));

// render window title centred
let mut window_title = self.window_title.render()?;
Expand Down Expand Up @@ -393,10 +345,54 @@ impl CgStatusBar {
}
}

enum CgDialogType {
Information,
Confirmation,
}

pub struct CgDialog {
dimensions: Dimensions,
title: String,
content: String,
button_text: String,
accepted: bool,
outlined: bool,
}

impl CgDialog {
pub(crate) fn new(dimensions: Dimensions, title: String, content: String, button_text: String) -> CgDialog {
CgDialog {
dimensions,
title,
content,
button_text,
accepted: false,
outlined: true,
}
}
}

impl CgComponent for CgDialog {
fn render(&self) -> Result<Frame, RenderError> {
if self.dimensions.x > BUFFER_WIDTH || self.dimensions.y > BUFFER_HEIGHT {
return Err(RenderError::OutOfBounds(self.dimensions.x > BUFFER_WIDTH, self.dimensions.y > BUFFER_HEIGHT));
}
let x_offset = (BUFFER_WIDTH - self.dimensions.x) / 2;
let y_offset = (BUFFER_HEIGHT - self.dimensions.y) / 2;

let mut frame = Frame::new(Position::new(x_offset, y_offset), Dimensions::new(self.dimensions.x, self.dimensions.y))?;

if self.outlined {
render_outline(&mut frame, self.dimensions);
}

Ok(frame)
}

fn as_any(&self) -> &dyn Any {
self
}
}



Expand Down
1 change: 1 addition & 0 deletions src/user/lib/libgui/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod cg_core;
pub mod cg_widgets;
pub mod cg_inputs;
mod cg_utils;

Loading

0 comments on commit e80df51

Please sign in to comment.