use egui::{CornerRadius, Id, Rect, Sense, Ui, pos2, vec2};
use crate::tokens::Tokens;
const MAX_WIDTH: f32 = 1.0e6;
pub(crate) struct HScroll {
id: Id,
pub offset: f32,
content: f32,
view: f32,
}
impl HScroll {
pub(crate) fn begin(ui: &Ui, id: Id, area: Rect, content: f32, view: f32) -> Self {
let content = if content.is_finite() { content.clamp(0.0, MAX_WIDTH) } else { 0.0 };
let view = if view.is_finite() { view.max(1.0) } else { 1.0 };
let mut offset: f32 = ui.data(|d| d.get_temp(id)).unwrap_or(0.0);
let max = (content - view).max(0.0);
if max > 0.0 && ui.rect_contains_pointer(area) {
let dx = ui.input(|i| i.smooth_scroll_delta.x);
if dx != 0.0 && dx.is_finite() {
offset -= dx;
ui.ctx().input_mut(|i| i.smooth_scroll_delta.x = 0.0);
}
}
let offset = if offset.is_finite() { offset.clamp(0.0, max) } else { 0.0 };
HScroll { id, offset, content, view }
}
pub(crate) fn see(&mut self, width: f32) {
if width.is_finite() {
self.content = self.content.max(width.min(MAX_WIDTH));
}
}
pub(crate) fn end(mut self, ui: &mut Ui, track: Rect, t: &Tokens) {
let max = (self.content - self.view).max(0.0);
if max > 0.0 && track.width() > 8.0 {
let h = t.space.xs.max(3.0) * 1.5;
let bar = Rect::from_min_max(pos2(track.left(), track.bottom() - h), track.max);
let thumb_w = (bar.width() * self.view / self.content).clamp(h * 2.0, bar.width());
let room = (bar.width() - thumb_w).max(1.0);
let x = bar.left() + room * (self.offset / max).clamp(0.0, 1.0);
let thumb = Rect::from_min_size(pos2(x, bar.top()), vec2(thumb_w, h));
let resp = ui.interact(thumb, self.id.with("thumb"), Sense::drag());
if resp.dragged() {
self.offset = (self.offset + resp.drag_delta().x * max / room).clamp(0.0, max);
}
if ui.is_rect_visible(bar) {
let painter = ui.painter_at(track);
let r = CornerRadius::same((h / 2.0).round().clamp(0.0, 255.0) as u8);
let fill = if resp.dragged() || resp.hovered() { t.text.secondary } else { t.border_strong };
painter.rect_filled(thumb, r, fill);
}
} else {
self.offset = 0.0;
}
let (id, offset) = (self.id, self.offset);
ui.data_mut(|d| d.insert_temp(id, offset));
}
}