Skip to content

Commit

Permalink
[Rust - agx] Scroll bar UI prototyping
Browse files Browse the repository at this point in the history
  • Loading branch information
codyd51 committed Mar 23, 2024
1 parent f20e642 commit 66d0738
Showing 1 changed file with 120 additions and 25 deletions.
145 changes: 120 additions & 25 deletions rust_programs/libgui/src/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use alloc::{
rc::{Rc, Weak},
vec::Vec,
};
//use axle_rt::println;
use core::cmp::{max, min};
use core::fmt::Formatter;
use libgui_derive::Drawable;
use num_traits::Float;
Expand Down Expand Up @@ -748,21 +750,10 @@ impl Bordered for ScrollView {
// drawn on the right hand side will be too thin unless we color it manually)
onto.fill_rect(
scroll_bar_content_frame,
Color::blue(),
Color::light_gray(),
StrokeThickness::Filled,
);

/*
let mut scroll_bar_onto = onto.get_slice(Rect::from_parts(
// Start from y=0 so that the top border lines up with the content's border
Point::new(scroll_bar_content_frame.origin.x, 0),
Size::new(
scroll_bar_content_frame.szi
)
scroll_bar_content_frame.size,
));
*/
let mut scroll_bar_onto = onto.get_slice(scroll_bar_content_frame);
let (_, frame_of_scrollbar_content) = draw_border_with_insets(
&mut scroll_bar_onto,
Expand All @@ -774,18 +765,95 @@ impl Bordered for ScrollView {
false,
);

// PT: Horrible hack to make the highlight border show perfectly on top of the scroll bar
draw_outer_mouse_highlight(onto, self.frame().size, self.currently_contains_mouse());
// Draw the 'background' of the scroll bar
scroll_bar_onto.fill_rect(
frame_of_scrollbar_content,
Color::black(),
StrokeThickness::Filled,
);

// Draw the scroll bar indicator
let scroll_offset_y = self.layer.scroll_offset().y;
let total_scrollable_height = match self.layer.total_content_frame().size.height {
0 => {
// Provide a 'fake' scrollable height
scroll_offset_y.abs()
}
height => height,
};

// TODO(PT): Handle when the scroll offset is 'negative' i.e. when there's a bunch of content above the origin?

let top_of_visible_content = scroll_offset_y.abs();
let bottom_of_visible_content =
top_of_visible_content + self.layer.visible_frame.borrow().size.height;
let percent_scrolled_through_content = {
if total_scrollable_height == 0 {
0.0
} else {
top_of_visible_content as f64 / total_scrollable_height as f64
}
};

/*
let (frame_of_inner_margin, frame_of_content) = draw_border_with_insets(
onto,
self.outer_border_insets(),
self.inner_border_insets(),
self.frame().size,
true,
self.currently_contains_mouse(),
println!(
"total scrollable height {total_scrollable_height} scroll_offset_y {scroll_offset_y} percent {percent_scrolled_through_content}"
);
*/
assert!(
percent_scrolled_through_content >= 0.0 && percent_scrolled_through_content <= 1.0,
"Percent was {percent_scrolled_through_content}"
);

let scroll_box_min_y = frame_of_scrollbar_content.min_y();
let scroll_box_max_y = frame_of_scrollbar_content.max_y();
let center_y_for_scroll_bar_within_scroll_box = scroll_box_min_y
+ ((frame_of_scrollbar_content.height() as f64 * percent_scrolled_through_content)
as isize);
/*
println!(
"total scrollable height {total_scrollable_height} scroll_offset_y {scroll_offset_y} scroll_box_min_y {scroll_box_min_y} {percent_scrolled_through_content} center_y {center_y_for_scroll_bar_within_scroll_box}"
);
*/
// TODO(PT): The height of the scroll bar should be proportional to the content height
let scroll_indicator_size = Size::new(
(frame_of_scrollbar_content.width() as f64 * 0.6) as isize,
200,
);
let mut y_origin_for_scroll_indicator = center_y_for_scroll_bar_within_scroll_box
- ((scroll_indicator_size.height as f64 / 2.0) as isize);
// Ensure the scroll indicator doesn't underflow the scroll box
y_origin_for_scroll_indicator = max(y_origin_for_scroll_indicator, scroll_box_min_y);

/*
scroll_bar_onto.fill_rect(
Rect::from_parts(
Point::new(
frame_of_scrollbar_content.min_x(),
y_origin_for_scroll_indicator,
),
scroll_indicator_size,
),
Color::green(),
StrokeThickness::Filled,
);
*/
let scrollbar_attrs = compute_scrollbar_attributes(
self.layer.frame().size,
self.layer.total_content_frame().size,
self.layer.scroll_offset(),
);
println!("{scrollbar_attrs:?}");
scroll_bar_onto.fill_rect(
Rect::from_parts(scrollbar_attrs.origin, scrollbar_attrs.size),
Color::green(),
StrokeThickness::Filled,
);

// PT: Horrible hack to make the highlight border show perfectly on top of the scroll bar
draw_outer_mouse_highlight(onto, self.frame().size, self.currently_contains_mouse());

frame_of_content
}
Expand Down Expand Up @@ -853,12 +921,10 @@ impl UIElement for ScrollView {
}

fn handle_mouse_scrolled(&self, _mouse_point: Point, delta_z: isize) {
//println!("ScrollView.handle_mouse_scrolled({delta_z})");
let mut scroll_offset = self.layer.scroll_offset();
self.layer.set_scroll_offset(scroll_offset);
//self.draw()
Bordered::draw(self);
let previous_scroll_offset = scroll_offset;
let content_frame = self.layer.total_content_frame();

// Scale how much the mouse scrolls by based on how large the content view is
// TODO(PT): Scale by how fast the user is scrolling
let scroll_step = {
Expand Down Expand Up @@ -897,6 +963,12 @@ impl UIElement for ScrollView {
}
}
// TODO(PT): Update this to handle horizontal scrolls as well?

// Only redraw if we've changed state
if scroll_offset != previous_scroll_offset {
self.layer.set_scroll_offset(scroll_offset);
Bordered::draw(self);
}
}

fn handle_key_released(&self, key: KeyCode) {
Expand Down Expand Up @@ -1176,4 +1248,27 @@ mod test {
],
);
}

#[test]
fn test_compute_scrollbar_parameters() {
// Given a scroll view with a content size three times the viewport
let viewport_size = Size::new(1000, 1000);
let content_size = Size::new(1000, 3000);
// And the user is currently scrolled to the top of the view
let scroll_position = Point::new(0, 0);
// When the scroll bar attributes are computed
let scrollbar_attributes =
compute_scrollbar_attributes(viewport_size, content_size, scroll_position);
// Then the scrollbar looks correct
/*
assert_eq!(
scrollbar_attributes,
ScrollbarAttributes::new(Point::new(0, 0), Size::new(80, 200),)
);
*/
assert_eq!(
scrollbar_attributes,
ScrollbarAttributes::new(Point::new(980, 131), Size::new(20, 208),)
);
}
}

0 comments on commit 66d0738

Please sign in to comment.