113 lines
2.6 KiB
Rust
113 lines
2.6 KiB
Rust
// Copyright (c) 2022 Marceline Crmaer
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
use super::prelude::*;
|
|
|
|
pub struct SliderStyle {
|
|
pub bg_color: Color,
|
|
pub bg_padding: f32,
|
|
pub bg_rounding: f32,
|
|
pub fg_color: Color,
|
|
}
|
|
|
|
impl Default for SliderStyle {
|
|
fn default() -> Self {
|
|
Self {
|
|
bg_color: THEME.palette.overlay,
|
|
bg_padding: 2.5,
|
|
bg_rounding: 2.5,
|
|
fg_color: THEME.palette.blue,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Slider {
|
|
style: SliderStyle,
|
|
bg_rect: Rect,
|
|
fg_rect: Rect,
|
|
position: f32,
|
|
dirty: bool,
|
|
updating: bool,
|
|
}
|
|
|
|
impl Slider {
|
|
pub fn new(style: SliderStyle, rect: Rect) -> Self {
|
|
Self {
|
|
style,
|
|
bg_rect: rect,
|
|
fg_rect: rect,
|
|
position: 0.5,
|
|
dirty: true,
|
|
updating: false,
|
|
}
|
|
}
|
|
|
|
pub fn set_position(&mut self, position: f32) {
|
|
if !self.updating {
|
|
self.position = position;
|
|
self.dirty = true;
|
|
}
|
|
}
|
|
|
|
pub fn has_update(&mut self) -> Option<f32> {
|
|
if self.updating {
|
|
Some(self.position)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn set_rect(&mut self, rect: Rect) {
|
|
self.bg_rect = rect;
|
|
self.dirty = true;
|
|
}
|
|
|
|
fn undirty(&mut self) {
|
|
if !self.dirty {
|
|
return;
|
|
}
|
|
|
|
let mut fg_space = self.bg_rect.inset(self.style.bg_padding);
|
|
fg_space.br.x = (fg_space.width() * self.position) + fg_space.tl.x;
|
|
self.fg_rect = fg_space;
|
|
self.dirty = false;
|
|
}
|
|
|
|
pub fn get_position(&self) -> f32 {
|
|
self.position
|
|
}
|
|
}
|
|
|
|
impl Widget for Slider {
|
|
fn draw(&mut self, ctx: &DrawContext) {
|
|
self.undirty();
|
|
ctx.draw_rounded_rect(self.bg_rect, self.style.bg_rounding, self.style.bg_color);
|
|
ctx.draw_rect(self.fg_rect, self.style.fg_color);
|
|
}
|
|
|
|
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
|
|
if let CursorEventKind::Select = kind {
|
|
if self.bg_rect.contains_point(at) {
|
|
self.updating = true;
|
|
}
|
|
}
|
|
|
|
if !self.updating {
|
|
return;
|
|
}
|
|
|
|
match kind {
|
|
CursorEventKind::Hover => {}
|
|
CursorEventKind::Select | CursorEventKind::Drag => {
|
|
let offset = at.x - self.fg_rect.tl.x;
|
|
let range = self.bg_rect.inset(self.style.bg_padding).width();
|
|
self.position = (offset / range).clamp(0.0, 1.0);
|
|
self.dirty = true;
|
|
}
|
|
CursorEventKind::Deselect => {
|
|
self.updating = false;
|
|
}
|
|
}
|
|
}
|
|
}
|