use std::time::Duration;
use crate::animation::{Easing, TransitionConfig};
use crate::core::element::Key;
use crate::style::Rect;
use super::action::ScrollMetrics;
#[derive(Clone, Copy, Debug)]
pub struct ScrollDistanceConfig {
pub min_duration: Duration,
pub max_duration: Duration,
pub duration_per_row: Duration,
pub easing: Easing,
}
impl ScrollDistanceConfig {
pub const fn new(
min_duration: Duration,
max_duration: Duration,
duration_per_row: Duration,
easing: Easing,
) -> Self {
Self {
min_duration,
max_duration,
duration_per_row,
easing,
}
}
pub fn duration_for_distance(self, distance_rows: usize) -> Duration {
if distance_rows == 0 {
return Duration::ZERO;
}
let min_duration = self.min_duration.min(self.max_duration);
let max_duration = self.min_duration.max(self.max_duration);
let rows = distance_rows.min(u32::MAX as usize) as u32;
min_duration
.saturating_add(self.duration_per_row.saturating_mul(rows))
.min(max_duration)
}
pub fn transition_config_for_distance(self, distance_rows: usize) -> TransitionConfig {
TransitionConfig {
duration: self.duration_for_distance(distance_rows),
easing: self.easing,
}
}
pub const fn min_transition_config(self) -> TransitionConfig {
TransitionConfig {
duration: self.min_duration,
easing: self.easing,
}
}
}
impl Default for ScrollDistanceConfig {
fn default() -> Self {
Self {
min_duration: Duration::from_millis(120),
max_duration: Duration::from_millis(700),
duration_per_row: Duration::from_millis(8),
easing: Easing::EaseOutQuad,
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub enum ScrollBehavior {
#[default]
Instant,
Smooth(TransitionConfig),
SmoothDistance(ScrollDistanceConfig),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ScrollWheelConfig {
pub acceleration: f32,
pub deceleration: f32,
pub max_velocity: f32,
pub stop_velocity: f32,
}
impl ScrollWheelConfig {
pub const fn new(
acceleration: f32,
deceleration: f32,
max_velocity: f32,
stop_velocity: f32,
) -> Self {
Self {
acceleration,
deceleration,
max_velocity,
stop_velocity,
}
}
}
impl Default for ScrollWheelConfig {
fn default() -> Self {
Self {
acceleration: 40.0,
deceleration: 12.0,
max_velocity: 320.0,
stop_velocity: 0.05,
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub enum ScrollWheelBehavior {
#[default]
Immediate,
Smooth(ScrollWheelConfig),
}
impl ScrollWheelBehavior {
pub const fn immediate() -> Self {
Self::Immediate
}
pub const fn smooth(config: ScrollWheelConfig) -> Self {
Self::Smooth(config)
}
pub fn smooth_default() -> Self {
Self::Smooth(ScrollWheelConfig::default())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ScrollTarget {
Top,
Bottom,
Key(Key),
KeyOffset {
key: Key,
offset: usize,
},
}
impl ScrollTarget {
pub const fn top() -> Self {
Self::Top
}
pub const fn bottom() -> Self {
Self::Bottom
}
pub fn key(key: impl Into<Key>) -> Self {
Self::Key(key.into())
}
pub fn key_offset(key: impl Into<Key>, offset: usize) -> Self {
Self::KeyOffset {
key: key.into(),
offset,
}
}
}
impl ScrollBehavior {
pub const fn instant() -> Self {
Self::Instant
}
pub const fn smooth(config: TransitionConfig) -> Self {
Self::Smooth(config)
}
pub fn smooth_default() -> Self {
Self::Smooth(TransitionConfig::default())
}
pub fn smooth_adaptive() -> Self {
Self::SmoothDistance(ScrollDistanceConfig::default())
}
pub const fn smooth_distance(config: ScrollDistanceConfig) -> Self {
Self::SmoothDistance(config)
}
pub const fn transition_config(self) -> Option<TransitionConfig> {
match self {
Self::Instant => None,
Self::Smooth(config) => Some(config),
Self::SmoothDistance(config) => Some(config.min_transition_config()),
}
}
pub fn transition_config_for_distance(self, distance_rows: usize) -> Option<TransitionConfig> {
match self {
Self::Instant => None,
Self::Smooth(config) => Some(config),
Self::SmoothDistance(config) => {
Some(config.transition_config_for_distance(distance_rows))
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ScrollEvent {
pub offset: usize,
pub metrics: ScrollMetrics,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ScrollChildVisibility {
FullyVisible,
PartiallyVisible,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ScrollChildExitDirection {
Above,
Below,
Removed,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ScrollVisibleChild {
pub index: usize,
pub key: Option<Key>,
pub content_rect: Rect,
pub viewport_rect: Rect,
pub visible_rect: Rect,
pub visible_height: u16,
pub clipped_above: u16,
pub clipped_below: u16,
pub visibility: ScrollChildVisibility,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ScrollExitedChild {
pub child: ScrollVisibleChild,
pub direction: ScrollChildExitDirection,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ScrollViewportEvent {
pub offset: usize,
pub metrics: ScrollMetrics,
pub viewport_width: u16,
pub children_len: usize,
pub first_visible_index: Option<usize>,
pub last_visible_index: Option<usize>,
pub visible: Vec<ScrollVisibleChild>,
pub entered: Vec<ScrollVisibleChild>,
pub exited: Vec<ScrollExitedChild>,
pub top_indicator: bool,
pub bottom_indicator: bool,
pub bottom_count: usize,
}