// 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 { 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; } } } }