Make ScrollBar grabbable
This commit is contained in:
parent
4e78cfb3d4
commit
9d83792ef7
|
@ -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)]
|
||||
|
|
Loading…
Reference in New Issue