use crate::types::{Rect, ScrollState};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ScrollableResponse {
pub content_size: f64,
pub viewport_size: f64,
pub has_scrollbar: bool,
pub viewport: Rect,
pub content_area: Rect,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ScrollableConfig {
pub scrollbar_size: f64,
pub always_show_scrollbar: bool,
}
impl Default for ScrollableConfig {
fn default() -> Self {
Self {
scrollbar_size: 8.0,
always_show_scrollbar: false,
}
}
}
pub struct ScrollableContainer {
viewport: Rect,
scroll_offset: f64,
#[allow(dead_code)]
is_dragging: bool,
config: ScrollableConfig,
}
impl ScrollableContainer {
pub fn new(viewport: Rect, scroll_state: &ScrollState, config: Option<ScrollableConfig>) -> Self {
Self {
viewport,
scroll_offset: scroll_state.offset,
is_dragging: scroll_state.is_dragging,
config: config.unwrap_or_default(),
}
}
pub fn content_area(&self) -> Rect {
Rect::new(
self.viewport.x,
self.viewport.y,
self.viewport.width - self.config.scrollbar_size,
self.viewport.height,
)
}
pub fn calculate(self, content_height: f64) -> ScrollableResponse {
let needs_scrollbar = content_height > self.viewport.height || self.config.always_show_scrollbar;
let content_area = Rect::new(
self.viewport.x,
self.viewport.y,
self.viewport.width - self.config.scrollbar_size,
self.viewport.height,
);
ScrollableResponse {
content_size: content_height,
viewport_size: self.viewport.height,
has_scrollbar: needs_scrollbar,
viewport: self.viewport,
content_area,
}
}
pub fn content_y(&self) -> f64 {
self.viewport.y - self.scroll_offset
}
pub fn content_width(&self) -> f64 {
self.viewport.width - self.config.scrollbar_size
}
}