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:
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user