use crate::layout::style::FlexStyle;
use crate::state::State;
use crate::theme;
use crate::view::node::ViewNode;
use crate::view::paint::PaintStyle;
use crate::widget::layout::LayoutAttr;
use crate::widget::{BuildContext, Widget};
pub struct ScrollView {
height: Option<f32>,
layout: LayoutAttr,
child: Option<Box<dyn Widget>>,
show_scrollbar: bool,
content_width: Option<f32>,
content_height: Option<f32>,
scroll_state: Option<State<(f32, f32)>>,
}
impl ScrollView {
pub fn new(height: f32) -> Self {
Self {
height: Some(height),
layout: LayoutAttr::new(),
child: None,
content_width: None,
content_height: None,
scroll_state: None,
show_scrollbar: false,
}
}
pub fn expand() -> Self {
Self {
height: None,
layout: LayoutAttr::new(),
child: None,
content_width: None,
content_height: None,
scroll_state: None,
show_scrollbar: false,
}
}
pub fn flex_shrink(mut self, v: f32) -> Self {
self.layout = self.layout.flex_shrink(v);
self
}
pub fn layout(mut self, l: LayoutAttr) -> Self {
self.layout = l;
self
}
pub fn scrollbar(mut self, show: bool) -> Self {
self.show_scrollbar = show;
self
}
pub fn child(mut self, v: impl Widget + 'static) -> Self {
self.child = Some(Box::new(v));
self
}
pub fn content_width(mut self, v: f32) -> Self {
self.content_width = Some(v);
self
}
pub fn content_height(mut self, v: f32) -> Self {
self.content_height = Some(v);
self
}
pub fn bind_scroll_state(mut self, s: &State<(f32, f32)>) -> Self {
self.scroll_state = Some(s.clone());
self
}
}
impl Widget for ScrollView {
fn build(&self, _ctx: &mut BuildContext) -> ViewNode {
let t = theme::current();
let inner = match &self.child {
Some(c) => _ctx.child(0, c.as_ref()),
None => ViewNode::Div {
layout: FlexStyle::block(),
paint: PaintStyle::default(),
children: vec![],
listeners: vec![],
key: None,
},
};
let mut viewport = match self.height {
Some(h) => FlexStyle::block().height(h),
None => FlexStyle::block()
.flex_grow(1.0)
.flex_shrink(self.layout.flex_shrink.unwrap_or(1.0)),
}
.overflow_scroll()
.scrollbar(self.show_scrollbar);
if self.height.is_some() {
viewport = self.layout.apply(viewport);
}
if self.show_scrollbar {
viewport = viewport.padding_right(8.0);
}
if let Some(w) = self.content_width {
viewport = viewport.content_width(w);
}
if let Some(h) = self.content_height {
viewport = viewport.content_height(h);
}
if let Some(ref s) = self.scroll_state {
viewport = viewport.bind_scroll_state(s);
}
ViewNode::Div {
layout: viewport,
paint: PaintStyle::new()
.background(t.background.secondary_default)
.clip(true),
children: vec![inner],
listeners: vec![],
key: None,
}
}
}