diff --git a/rust_programs/file_browser/src/main.rs b/rust_programs/file_browser/src/main.rs index 8fe911d0..17bc2d7d 100644 --- a/rust_programs/file_browser/src/main.rs +++ b/rust_programs/file_browser/src/main.rs @@ -1,6 +1,7 @@ #![no_std] #![feature(start)] #![feature(slice_ptr_get)] +#![feature(format_args_nl)] #![feature(default_alloc_error_handler)] extern crate alloc; @@ -23,7 +24,7 @@ use libgui::AwmWindow; use axle_rt::{ amc_message_await, amc_message_send, amc_register_service, - core_commands::AmcQueryServiceRequest, printf, AmcMessage, + core_commands::AmcQueryServiceRequest, printf, println, AmcMessage, }; use agx_definitions::{ @@ -35,6 +36,7 @@ use file_manager_messages::{ str_from_u8_nul_utf8_unchecked, DirectoryContents, DirectoryEntry, LaunchProgram, ReadDirectory, FILE_SERVER_SERVICE_NAME, }; +use libgui::scroll_view::ScrollView; fn select_current_path_view_height(superview_size: Size) -> isize { let min_height = 100; @@ -62,13 +64,13 @@ impl CurrentPathView { let current_path_label_clone = Rc::clone(¤t_path_label); Rc::clone(&view).add_component(current_path_label_clone); - let back_button = Rc::new(Button::new("Go Back", |_b, superview_size| { + let back_button = Button::new("Go Back", None, |_b, superview_size| { let size = Size::new(80, 30); Rect::from_parts( Point::new(10, superview_size.height - size.height - 10), size, ) - })); + }); let back_button_clone = Rc::clone(&back_button); Rc::clone(&view).add_component(back_button_clone); @@ -200,11 +202,11 @@ impl DirectoryEntryView { true => "Browse", false => "Open", }; - let button = Rc::new(Button::new(button_text, move |_b, superview_size| { + let button = Button::new(button_text, None, move |_b, superview_size| { //printf!("Button sizer, Superview size {:?}\n", superview_size); let size = Size::new(button_width, height - 4); Rect::from_parts(Point::new(superview_size.width - size.width - 10, 1), size) - })); + }); let button_clone = Rc::clone(&button); Rc::clone(&view).add_component(button_clone); @@ -334,6 +336,8 @@ struct DirectoryContentsView { impl DirectoryContentsView { pub fn new Rect>(path: &str, sizer: F) -> Self { let view = Rc::new(View::new(Color::new(170, 170, 170), sizer)); + //let view = ScrollView::new(sizer); + //println!("Got ScrollView"); // TODO(PT): Should return the normalized path (ie strip extra slashes and normalize ../) amc_message_send(FILE_SERVER_SERVICE_NAME, ReadDirectory::new(path)); diff --git a/rust_programs/ide/src/status_view.rs b/rust_programs/ide/src/status_view.rs index 3d1fe25c..ffa95064 100644 --- a/rust_programs/ide/src/status_view.rs +++ b/rust_programs/ide/src/status_view.rs @@ -29,13 +29,13 @@ impl StatusView { ) -> Rc { let view = Rc::new(View::new(Color::new(180, 180, 180), sizer)); - let run_button = Rc::new(Button::new("Run", |_b, superview_size| { + let run_button = Button::new("Run", None, |_b, superview_size| { let size = Size::new(60, 30); Rect::from_parts( Point::new(10, superview_size.height - size.height - 10), size, ) - })); + }); Rc::clone(&view).add_component(Rc::clone(&run_button) as Rc); let status_label = Rc::new(Label::new("", Color::black(), |_, _| { diff --git a/rust_programs/libgui/src/button.rs b/rust_programs/libgui/src/button.rs index fb41884d..b5c3a9c6 100644 --- a/rust_programs/libgui/src/button.rs +++ b/rust_programs/libgui/src/button.rs @@ -5,14 +5,18 @@ use agx_definitions::{ StrokeThickness, }; use alloc::boxed::Box; -use alloc::rc::Weak; +use alloc::rc::{Rc, Weak}; use alloc::string::{String, ToString}; use alloc::vec::Vec; +use ttf_renderer::{rendered_string_size, Font}; +use crate::font::{draw_char_with_font_onto, scaled_metrics_for_codepoint}; +use crate::text_view::DrawnCharacter; use crate::{bordered::Bordered, font::draw_char, ui_elements::UIElement}; pub struct Button { pub label: String, + font: Font, frame: RefCell, sizer: RefCell Rect>>, container: RefCell>>>, @@ -21,17 +25,31 @@ pub struct Button { } impl Button { - pub fn new Rect>(label: &str, sizer: F) -> Self { - Button { + pub fn new Rect + 'static>( + label: &str, + font: Option, + sizer: F, + ) -> Rc { + if font.is_none() { + // TODO(PT): It'd be nice to have some kind of font API that allowed anyone to retrieve a reference to a + // font from any point, instead of needing to pass references all the way through the control flow. + // Maybe there's an in-process font store that caches scanlines, etc, and fetches fonts from the FS. + // The 'fetch from FS' has a platform-specific implementation. To facilitate this (as the paths will be + // different on each OS), we could have an enum to model the possible font options, with an escape hatch + // 'get from this path' variant, which could perhaps hold different values depending on the OS. + todo!("Must handle when no font is passed to a Button?") + } + Rc::new(Self { label: label.to_string(), + font: font.unwrap(), frame: RefCell::new(Rect::zero()), sizer: RefCell::new(Box::new(sizer)), container: RefCell::new(None), left_click_cb: RefCell::new(None), currently_contains_mouse_int: RefCell::new(false), - } + }) } - pub fn on_left_click(&self, f: F) { + pub fn on_left_click(&self, f: F) { *self.left_click_cb.borrow_mut() = Some(Box::new(f)); } } @@ -150,11 +168,33 @@ impl Bordered for Button { (label_size.height as f64 / 2f64) as isize, ); - let mut cursor = label_origin; + //let mut cursor = label_origin; + let mut cursor = Point::zero(); + /* for ch in self.label.chars() { draw_char(onto, ch, &cursor, draw_color, &font_size); cursor.x += font_size.width; } + */ + // TODO(PT): A more reusable string renderer that can be shared between Button and Label? + let font_size = Size::new(36, 36); + let rendered_string_size = rendered_string_size(&self.label, &self.font, font_size); + let mut cursor = Point::new( + ((onto.frame().size.width as f64 / 2.0) - (rendered_string_size.width as f64 / 2.0)) + as isize, + //0, + //((onto.frame().size.height as f64 / 2.0) - (rendered_string_size.height as f64 / 2.0)) + ((onto.frame().size.height as f64 / 2.0) - (font_size.height as f64 / 2.0)) as isize, //as isize, + ); + + //pub fn rendered_string_size(s: &str, font: &Font, font_size: Size) -> Size { + for ch in self.label.chars() { + let mut drawn_ch = DrawnCharacter::new(cursor, Color::black(), ch, font_size); + let (bounding_box, glyph_metrics) = + draw_char_with_font_onto(&mut drawn_ch, &self.font, onto); + let scaled_glyph_metrics = scaled_metrics_for_codepoint(&self.font, font_size, ch); + cursor.x += scaled_glyph_metrics.advance_width as isize + 2; + } } }