Make ScrollBar grabbable

This commit is contained in:
mars 2022-07-12 23:40:27 -06:00
parent 4e78cfb3d4
commit 9d83792ef7
1 changed files with 87 additions and 12 deletions

View File

@ -191,7 +191,7 @@ pub struct ScrollBarStyle {
pub body_width: f32,
pub body_idle_color: Color,
pub body_hover_color: Color,
pub body_active_color: Color,
pub body_selected_color: Color,
pub rail_width: f32,
pub rail_color: Color,
}
@ -204,7 +204,7 @@ impl Default for ScrollBarStyle {
body_width: 0.015,
body_idle_color: Color::new(0.5, 0.5, 0.5, 1.0),
body_hover_color: Color::new(0.8, 0.8, 0.8, 1.0),
body_active_color: Color::new(1.0, 1.0, 0.0, 1.0),
body_selected_color: Color::new(1.0, 1.0, 0.0, 1.0),
rail_width: 0.005,
rail_color: Color::new(0.7, 0.7, 0.7, 0.5),
}
@ -217,6 +217,11 @@ pub struct ScrollBar {
scroll: f32,
content_height: f32,
rail_rect: Rect,
body_color_anim: Animation<EaseInQuad, Color>,
is_hovering: bool,
is_selected: bool,
grab_coord: f32,
grab_scroll: f32,
}
impl ScrollBar {
@ -227,33 +232,103 @@ impl ScrollBar {
tr: Vec2::new(center_x + style.rail_width / 2.0, height - style.margin.y),
};
let body_color_anim = Animation::new(
EaseInQuad,
0.05,
style.body_idle_color,
style.body_idle_color,
);
Self {
height,
style,
scroll: height,
scroll: 0.0,
content_height,
rail_rect,
body_color_anim,
is_hovering: false,
is_selected: false,
grab_coord: 0.0,
grab_scroll: 0.0,
}
}
}
impl Widget for ScrollBar {
fn update(&mut self, dt: f32) {}
fn draw(&mut self, ctx: &DrawContext) {
pub fn body_rect(&self) -> Rect {
let style = &self.style;
let rail_height = self.rail_rect.height();
let body_height = (self.height / self.content_height) * rail_height;
let body_y = rail_height - (self.scroll / self.content_height) * rail_height - body_height;
let body_xy = Vec2::new(style.margin.x, body_y + style.margin.y);
let body_size = Vec2::new(style.body_width, body_height);
let body_rect = Rect::from_xy_size(body_xy, body_size);
Rect::from_xy_size(body_xy, body_size)
}
}
ctx.draw_rect(self.rail_rect, style.rail_color);
ctx.draw_rounded_rect(body_rect, style.body_radius, style.body_idle_color);
impl Widget for ScrollBar {
fn update(&mut self, dt: f32) {
self.body_color_anim.update(dt);
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {}
fn draw(&mut self, ctx: &DrawContext) {
let style = &self.style;
let body_rect = self.body_rect();
ctx.draw_rect(self.rail_rect, style.rail_color);
ctx.draw_rounded_rect(body_rect, style.body_radius, self.body_color_anim.get());
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
let is_on = self.body_rect().contains_point(at);
match kind {
CursorEventKind::Hover | CursorEventKind::Drag => {
if is_on {
if !self.is_hovering && !self.is_selected {
self.body_color_anim.ease_to(self.style.body_hover_color);
}
self.is_hovering = true;
} else {
if self.is_hovering && !self.is_selected {
self.body_color_anim.ease_to(self.style.body_idle_color);
}
self.is_hovering = false;
}
if kind == CursorEventKind::Drag && self.is_selected {
self.scroll = ((self.grab_coord - at.y) / self.rail_rect.height())
* self.content_height
+ self.grab_scroll;
let scroll_cap = self.content_height - self.height;
if self.scroll > scroll_cap {
self.scroll = scroll_cap;
} else if self.scroll < 0.0 {
self.scroll = 0.0;
}
}
}
CursorEventKind::Select => {
if is_on {
self.is_selected = true;
self.body_color_anim.ease_to(self.style.body_selected_color);
self.grab_coord = at.y;
self.grab_scroll = self.scroll;
}
}
CursorEventKind::Deselect => {
if self.is_selected {
self.is_selected = false;
if self.is_hovering {
self.body_color_anim.ease_to(self.style.body_hover_color);
} else {
self.body_color_anim.ease_to(self.style.body_idle_color);
}
}
}
}
}
}
#[derive(Eq, PartialEq)]