holy (crab) that was a lot of work

it works.

the input function is working now, passing it a reference to your root gui widget and a reference to it's own widget and a function to check if it should exit works now

gg
This commit is contained in:
FantasyPvP
2023-11-28 00:12:59 +00:00
parent f48eb133b3
commit c194109487
5 changed files with 138 additions and 68 deletions
+17 -10
View File
@@ -11,7 +11,10 @@ use alloc::{
string::String,
};
use core::any::Any;
use async_trait::async_trait;
use lazy_static::lazy_static;
use crate::std::application::Exit;
use crate::std::io::KeyStroke;
/// implement this trait if you require the widget to be able to have an outline
pub trait CgOutline: CgComponent {
@@ -35,6 +38,11 @@ pub trait CgTextEdit: CgComponent {
fn clear(&mut self);
}
#[async_trait]
pub trait CgTextInput: CgTextEdit {
async fn input(&mut self, break_condition: fn(KeyStroke) -> (KeyStroke, Exit), id: &Widget, app: &Widget) -> Result<(String, bool), RenderError>;
}
static ID_COUNTER: Mutex<usize> = Mutex::new(0);
@@ -76,11 +84,13 @@ impl Widget {
}
pub fn render(&self) -> Result<Frame, RenderError> {
if let Some(frame) = GUITREE.lock().frame(self) {
frame
} else {
panic!("CRITICAL: Widget not found in tree");
}
let component_arc_mutex = match GUITREE.lock().frame(self) {
Some(component) => component,
None => panic!("CRITICAL: Widget not found in tree"),
};
let component = component_arc_mutex.lock();
component.render()
}
}
@@ -121,12 +131,9 @@ impl DataStore {
})
}
fn frame(&self, id: &Widget) -> Option<Result<Frame, RenderError>> {
fn frame(&self, id: &Widget) -> Option<Arc<Mutex<dyn CgComponent + Send + Sync + 'static>>> {
let items = self.items.lock();
items.get(&id.id).and_then(|arc| {
let item = arc.lock();
Some(item.render())
})
items.get(&id.id).cloned()
}
fn remove(&self, id: &Widget) {
+56 -1
View File
@@ -1,8 +1,13 @@
use alloc::string::String;
use alloc::vec::Vec;
use alloc::boxed::Box;
use core::any::Any;
use core::task::ready;
use async_trait::async_trait;
use crate::std::application::Exit;
use crate::std::frame::{ColouredChar, Dimensions, Frame, Position, RenderError};
use crate::user::lib::libgui::cg_core::{CgComponent, CgTextEdit};
use crate::std::io::{KeyStroke, Stdin};
use crate::user::lib::libgui::cg_core::{CgComponent, CgTextEdit, CgTextInput, Widget};
#[derive(Debug, Clone)]
pub struct CgLineEdit {
@@ -84,3 +89,53 @@ impl CgTextEdit for CgLineEdit {
self.ptr = 0
}
}
#[async_trait]
impl CgTextInput for CgLineEdit {
async fn input(&mut self, break_condition: fn(KeyStroke) -> (KeyStroke, Exit), id: &Widget, app: &Widget) -> Result<(String, bool), RenderError> {
while let (c, Exit::None) = break_condition(Stdin::keystroke().await) {
match c {
KeyStroke::Char('\n') => break,
KeyStroke::Char('\x08') => self.backspace(),
KeyStroke::Backspace => self.backspace(),
KeyStroke::Char(c) => self.write_char(c),
KeyStroke::Left => self.move_cursor(false),
KeyStroke::Right => self.move_cursor(true),
_ => (),
}
id.update(self.clone());
match app.render() {
Ok(frame) => frame.write_to_screen()?,
Err(e) => return Err(e),
}
};
let res = self.text.iter().collect();
self.clear();
id.update(self.clone());
match app.render() {
Ok(frame) => frame.write_to_screen()?,
Err(e) => return Err(e),
}
Ok((res, false))
}
}
+7
View File
@@ -29,6 +29,9 @@ impl CgContainer {
pub fn insert(&mut self, name: &'static str, element: Widget) {
self.elements.insert(name,element);
}
pub fn fetch(&self, name: &'static str) -> Option<&Widget> {
self.elements.get(name)
}
}
impl CgOutline for CgContainer {
@@ -55,8 +58,12 @@ impl CgOutline for CgContainer {
impl CgComponent for CgContainer {
fn render(&self) -> Result<Frame, RenderError> {
serial_println!("rendering");
let mut result = Frame::new(self.position, self.dimensions)?;
serial_println!("{:?}", self.elements);
for widget in &self.elements {
let frame = widget.1.render()?;
match result.render_bounds_check(&frame, true) { // TODO: this needs to be set to false for production