Skip to content

Commit

Permalink
[libgui] Buttons render their titles via TTFs
Browse files Browse the repository at this point in the history
  • Loading branch information
codyd51 committed Feb 7, 2024
1 parent ec909c2 commit 072e9d5
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 13 deletions.
14 changes: 9 additions & 5 deletions rust_programs/file_browser/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![no_std]
#![feature(start)]
#![feature(slice_ptr_get)]
#![feature(format_args_nl)]
#![feature(default_alloc_error_handler)]

extern crate alloc;
Expand All @@ -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::{
Expand All @@ -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;
Expand Down Expand Up @@ -62,13 +64,13 @@ impl CurrentPathView {
let current_path_label_clone = Rc::clone(&current_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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -334,6 +336,8 @@ struct DirectoryContentsView {
impl DirectoryContentsView {
pub fn new<F: 'static + Fn(&View, Size) -> 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));
Expand Down
4 changes: 2 additions & 2 deletions rust_programs/ide/src/status_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ impl StatusView {
) -> Rc<Self> {
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<dyn UIElement>);

let status_label = Rc::new(Label::new("", Color::black(), |_, _| {
Expand Down
52 changes: 46 additions & 6 deletions rust_programs/libgui/src/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Rect>,
sizer: RefCell<Box<dyn Fn(&Self, Size) -> Rect>>,
container: RefCell<Option<RefCell<Weak<dyn NestedLayerSlice>>>>,
Expand All @@ -21,17 +25,31 @@ pub struct Button {
}

impl Button {
pub fn new<F: 'static + Fn(&Self, Size) -> Rect>(label: &str, sizer: F) -> Self {
Button {
pub fn new<F: Fn(&Self, Size) -> Rect + 'static>(
label: &str,
font: Option<Font>,
sizer: F,
) -> Rc<Self> {
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<F: 'static + Fn(&Self)>(&self, f: F) {
pub fn on_left_click<F: Fn(&Self) + 'static>(&self, f: F) {
*self.left_click_cb.borrow_mut() = Some(Box::new(f));
}
}
Expand Down Expand Up @@ -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;
}
}
}

Expand Down

0 comments on commit 072e9d5

Please sign in to comment.