234 lines
5.6 KiB
Rust
234 lines
5.6 KiB
Rust
use super::{margin::Margin, padding::PaddingWidget};
|
|
use crate::ui::UIWidget;
|
|
use maud::{Markup, Render, html};
|
|
|
|
#[allow(non_snake_case)]
|
|
pub fn Scroll<T: UIWidget + 'static>(inner: T) -> ScrollWidget {
|
|
ScrollWidget(Box::new(inner), true, None, None, None, None, false)
|
|
}
|
|
|
|
pub struct ScrollWidget(
|
|
Box<dyn UIWidget>,
|
|
bool,
|
|
Option<Margin>,
|
|
Option<PaddingWidget>,
|
|
Option<Overscroll>,
|
|
Option<SnapType>,
|
|
bool,
|
|
);
|
|
|
|
impl ScrollWidget {
|
|
pub fn smooth(mut self, value: bool) -> Self {
|
|
self.1 = value;
|
|
self
|
|
}
|
|
|
|
pub fn scroll_margin(mut self, margin: Margin) -> Self {
|
|
self.2 = Some(margin);
|
|
self
|
|
}
|
|
|
|
pub fn scroll_padding(mut self, padding: PaddingWidget) -> Self {
|
|
self.3 = Some(padding);
|
|
self
|
|
}
|
|
|
|
pub fn overscroll(mut self, behaviour: Overscroll) -> Self {
|
|
self.4 = Some(behaviour);
|
|
self
|
|
}
|
|
|
|
pub fn snap(mut self, kind: SnapType) -> Self {
|
|
self.5 = Some(kind);
|
|
self
|
|
}
|
|
|
|
pub fn skip_snap(mut self) -> Self {
|
|
self.6 = true;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Render for ScrollWidget {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl UIWidget for ScrollWidget {
|
|
fn can_inherit(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
let mut ret = Vec::new();
|
|
|
|
if self.1 {
|
|
ret.push("scroll-smooth".to_string());
|
|
}
|
|
|
|
if let Some(margin) = &self.2 {
|
|
let classes = margin
|
|
.base_class()
|
|
.into_iter()
|
|
.map(|x| format!("scroll-{x}"))
|
|
.collect::<Vec<_>>();
|
|
ret.extend_from_slice(&classes);
|
|
}
|
|
|
|
if let Some(padding) = &self.3 {
|
|
let classes = padding
|
|
.base_class()
|
|
.into_iter()
|
|
.map(|x| format!("scroll-{x}"))
|
|
.collect::<Vec<_>>();
|
|
ret.extend_from_slice(&classes);
|
|
}
|
|
|
|
if let Some(overscroll) = &self.4 {
|
|
ret.push(overscroll.to_value().to_string());
|
|
}
|
|
|
|
if let Some(snap) = &self.5 {
|
|
ret.push(snap.to_value().to_string());
|
|
}
|
|
|
|
if self.6 {
|
|
ret.push("snap-normal".to_string());
|
|
} else {
|
|
ret.push("snap-always".to_string());
|
|
}
|
|
|
|
ret
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
let mut c = self.base_class();
|
|
c.extend_from_slice(&self.0.extended_class());
|
|
c
|
|
}
|
|
|
|
fn render_with_class(&self, class: &str) -> Markup {
|
|
if self.0.as_ref().can_inherit() {
|
|
self.0
|
|
.as_ref()
|
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
|
} else {
|
|
html! {
|
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
|
(self.0.as_ref())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum Overscroll {
|
|
Auto,
|
|
Contain,
|
|
None,
|
|
YAuto,
|
|
YContain,
|
|
YNone,
|
|
XAuto,
|
|
XContain,
|
|
XNone,
|
|
}
|
|
|
|
impl Overscroll {
|
|
pub const fn to_value(&self) -> &str {
|
|
match self {
|
|
Overscroll::Auto => "overscroll-auto",
|
|
Overscroll::Contain => "overscroll-contain",
|
|
Overscroll::None => "overscroll-none",
|
|
Overscroll::YAuto => "overscroll-y-auto",
|
|
Overscroll::YContain => "overscroll-y-contain",
|
|
Overscroll::YNone => "overscroll-y-none",
|
|
Overscroll::XAuto => "overscroll-x-auto",
|
|
Overscroll::XContain => "overscroll-x-contain",
|
|
Overscroll::XNone => "overscroll-x-none",
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum SnapType {
|
|
None,
|
|
X,
|
|
Y,
|
|
Both,
|
|
Mandatory,
|
|
Proximity,
|
|
}
|
|
|
|
impl SnapType {
|
|
pub const fn to_value(&self) -> &str {
|
|
match self {
|
|
SnapType::None => "snap-none",
|
|
SnapType::X => "snap-x",
|
|
SnapType::Y => "snap-y",
|
|
SnapType::Both => "snap-both",
|
|
SnapType::Mandatory => "snap-mandatory",
|
|
SnapType::Proximity => "snap-proximity",
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct SnapAlign(Box<dyn UIWidget>, String);
|
|
|
|
impl SnapAlign {
|
|
#[allow(non_snake_case)]
|
|
pub fn Start<T: UIWidget + 'static>(inner: T) -> Self {
|
|
Self(Box::new(inner), "snap-start".to_string())
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
pub fn End<T: UIWidget + 'static>(inner: T) -> Self {
|
|
Self(Box::new(inner), "snap-end".to_string())
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
pub fn Center<T: UIWidget + 'static>(inner: T) -> Self {
|
|
Self(Box::new(inner), "snap-center".to_string())
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
pub fn None<T: UIWidget + 'static>(inner: T) -> Self {
|
|
Self(Box::new(inner), "snap-align-none".to_string())
|
|
}
|
|
}
|
|
|
|
impl Render for SnapAlign {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl UIWidget for SnapAlign {
|
|
fn can_inherit(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
vec![self.1.clone()]
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
let mut c = self.base_class();
|
|
c.extend_from_slice(&self.0.extended_class());
|
|
c
|
|
}
|
|
|
|
fn render_with_class(&self, class: &str) -> Markup {
|
|
if self.0.as_ref().can_inherit() {
|
|
self.0
|
|
.as_ref()
|
|
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
|
} else {
|
|
html! {
|
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
|
(self.0.as_ref())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|