use azul_core::geom::{LogicalPosition, LogicalRect, LogicalSize};
use azul_core::dom::ScrollbarOrientation;
#[derive(Debug, Clone, Default)]
#[repr(C)]
pub struct ScrollbarRequirements {
pub needs_horizontal: bool,
pub needs_vertical: bool,
pub scrollbar_width: f32,
pub scrollbar_height: f32,
pub visual_width_px: f32,
}
impl ScrollbarRequirements {
pub fn needs_reflow(&self) -> bool {
self.scrollbar_width > 0.0 || self.scrollbar_height > 0.0
}
pub fn shrink_size(&self, size: LogicalSize) -> LogicalSize {
LogicalSize {
width: (size.width - self.scrollbar_width).max(0.0),
height: (size.height - self.scrollbar_height).max(0.0),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ScrollbarGeometry {
pub orientation: ScrollbarOrientation,
pub track_rect: LogicalRect,
pub button_size: f32,
pub usable_track_length: f32,
pub thumb_length: f32,
pub thumb_size_ratio: f32,
pub scroll_ratio: f32,
pub thumb_offset: f32,
pub max_scroll: f32,
pub width_px: f32,
}
impl Default for ScrollbarGeometry {
fn default() -> Self {
Self {
orientation: ScrollbarOrientation::Vertical,
track_rect: LogicalRect::zero(),
button_size: 0.0,
usable_track_length: 0.0,
thumb_length: 0.0,
thumb_size_ratio: 0.0,
scroll_ratio: 0.0,
thumb_offset: 0.0,
max_scroll: 0.0,
width_px: 0.0,
}
}
}
pub fn compute_scrollbar_geometry(
orientation: ScrollbarOrientation,
inner_rect: LogicalRect,
content_size: LogicalSize,
scroll_offset: f32,
scrollbar_width_px: f32,
has_other_scrollbar: bool,
) -> ScrollbarGeometry {
compute_scrollbar_geometry_with_button_size(
orientation,
inner_rect,
content_size,
scroll_offset,
scrollbar_width_px,
has_other_scrollbar,
scrollbar_width_px, )
}
pub fn compute_scrollbar_geometry_with_button_size(
orientation: ScrollbarOrientation,
inner_rect: LogicalRect,
content_size: LogicalSize,
scroll_offset: f32,
scrollbar_width_px: f32,
has_other_scrollbar: bool,
button_size: f32,
) -> ScrollbarGeometry {
match orientation {
ScrollbarOrientation::Vertical => {
let track_total = if has_other_scrollbar {
inner_rect.size.height - scrollbar_width_px
} else {
inner_rect.size.height
};
let track_rect = LogicalRect {
origin: LogicalPosition::new(
inner_rect.origin.x + inner_rect.size.width - scrollbar_width_px,
inner_rect.origin.y,
),
size: LogicalSize::new(scrollbar_width_px, track_total),
};
let usable_track_length = (track_total - 2.0 * button_size).max(0.0);
let viewport_length = inner_rect.size.height;
let content_length = content_size.height;
let thumb_size_ratio = if content_length > 0.0 {
(viewport_length / content_length).min(1.0)
} else {
1.0
};
let thumb_length = (usable_track_length * thumb_size_ratio)
.max(scrollbar_width_px * 2.0)
.min(usable_track_length);
let max_scroll = (content_length - viewport_length).max(0.0);
let scroll_ratio = if max_scroll > 0.0 {
(scroll_offset.abs() / max_scroll).clamp(0.0, 1.0)
} else {
0.0
};
let thumb_offset = (usable_track_length - thumb_length) * scroll_ratio;
ScrollbarGeometry {
orientation,
track_rect,
button_size,
usable_track_length,
thumb_length,
thumb_size_ratio,
scroll_ratio,
thumb_offset,
max_scroll,
width_px: scrollbar_width_px,
}
}
ScrollbarOrientation::Horizontal => {
let track_total = if has_other_scrollbar {
inner_rect.size.width - scrollbar_width_px
} else {
inner_rect.size.width
};
let track_rect = LogicalRect {
origin: LogicalPosition::new(
inner_rect.origin.x,
inner_rect.origin.y + inner_rect.size.height - scrollbar_width_px,
),
size: LogicalSize::new(track_total, scrollbar_width_px),
};
let usable_track_length = (track_total - 2.0 * button_size).max(0.0);
let viewport_length = inner_rect.size.width;
let content_length = content_size.width;
let thumb_size_ratio = if content_length > 0.0 {
(viewport_length / content_length).min(1.0)
} else {
1.0
};
let thumb_length = (usable_track_length * thumb_size_ratio)
.max(scrollbar_width_px * 2.0)
.min(usable_track_length);
let max_scroll = (content_length - viewport_length).max(0.0);
let scroll_ratio = if max_scroll > 0.0 {
(scroll_offset.abs() / max_scroll).clamp(0.0, 1.0)
} else {
0.0
};
let thumb_offset = (usable_track_length - thumb_length) * scroll_ratio;
ScrollbarGeometry {
orientation,
track_rect,
button_size,
usable_track_length,
thumb_length,
thumb_size_ratio,
scroll_ratio,
thumb_offset,
max_scroll,
width_px: scrollbar_width_px,
}
}
}
}