winio_ui_winui/widgets/
scroll_view.rs1use inherit_methods_macro::inherit_methods;
2use windows::core::Interface;
3use winio_handle::{AsContainer, BorrowedContainer};
4use winio_primitive::{Point, Rect, Size};
5use winui3::Microsoft::UI::Xaml::{
6 Controls as MUXC, FrameworkElement, HorizontalAlignment, RoutedEventHandler, VerticalAlignment,
7};
8
9use crate::{Result, Widget, widgets::Convertible};
10
11#[derive(Debug)]
12pub struct ScrollView {
13 handle: Widget,
14 view: MUXC::ScrollViewer,
15 canvas: MUXC::Canvas,
16}
17
18fn set_canvas_to_fit_children(canvas: &MUXC::Canvas) -> Result<()> {
19 let rect = canvas
20 .Children()?
21 .into_iter()
22 .map(|c| {
23 let c = c.cast::<FrameworkElement>()?;
24 let left = MUXC::Canvas::GetLeft(&c)?;
25 let top = MUXC::Canvas::GetTop(&c)?;
26 let size = Size::from_native(c.DesiredSize()?);
27 Result::Ok(Rect::new(Point::new(left, top), size))
28 })
29 .reduce(|a, b| a.and_then(|a| b.map(|b| (a, b))).map(|(a, b)| a.union(&b)))
30 .unwrap_or_else(|| Ok(Rect::zero()))?;
31 canvas.SetWidth(rect.max_x())?;
32 canvas.SetHeight(rect.max_y())?;
33 Ok(())
34}
35
36#[inherit_methods(from = "self.handle")]
37impl ScrollView {
38 pub fn new(parent: impl AsContainer) -> Result<Self> {
39 let view = MUXC::ScrollViewer::new()?;
40 let canvas = MUXC::Canvas::new()?;
41 canvas.SetHorizontalAlignment(HorizontalAlignment::Left)?;
42 canvas.SetVerticalAlignment(VerticalAlignment::Top)?;
43 view.SetContent(&canvas)?;
44 view.SetHorizontalScrollBarVisibility(MUXC::ScrollBarVisibility::Auto)?;
45 view.SetVerticalScrollBarVisibility(MUXC::ScrollBarVisibility::Auto)?;
46 canvas.Loaded(&RoutedEventHandler::new(|sender, _| {
47 let canvas = sender.ok()?.cast::<MUXC::Canvas>()?;
48 set_canvas_to_fit_children(&canvas)?;
49 Ok(())
50 }))?;
51 Ok(Self {
52 handle: Widget::new(parent, view.cast()?)?,
53 view,
54 canvas,
55 })
56 }
57
58 pub fn is_visible(&self) -> Result<bool>;
59
60 pub fn set_visible(&mut self, v: bool) -> Result<()>;
61
62 pub fn is_enabled(&self) -> Result<bool>;
63
64 pub fn set_enabled(&mut self, v: bool) -> Result<()>;
65
66 pub fn loc(&self) -> Result<Point>;
67
68 pub fn set_loc(&mut self, p: Point) -> Result<()>;
69
70 pub fn size(&self) -> Result<Size>;
71
72 pub fn set_size(&mut self, v: Size) -> Result<()> {
73 self.handle.set_size(v)?;
74 set_canvas_to_fit_children(&self.canvas)?;
75 Ok(())
76 }
77
78 pub fn hscroll(&self) -> Result<bool> {
79 Ok(self.view.HorizontalScrollBarVisibility()? != MUXC::ScrollBarVisibility::Disabled)
80 }
81
82 pub fn set_hscroll(&mut self, v: bool) -> Result<()> {
83 self.view.SetHorizontalScrollBarVisibility(if v {
84 MUXC::ScrollBarVisibility::Auto
85 } else {
86 MUXC::ScrollBarVisibility::Disabled
87 })?;
88 Ok(())
89 }
90
91 pub fn vscroll(&self) -> Result<bool> {
92 Ok(self.view.VerticalScrollBarVisibility()? != MUXC::ScrollBarVisibility::Disabled)
93 }
94
95 pub fn set_vscroll(&mut self, v: bool) -> Result<()> {
96 self.view.SetVerticalScrollBarVisibility(if v {
97 MUXC::ScrollBarVisibility::Auto
98 } else {
99 MUXC::ScrollBarVisibility::Disabled
100 })?;
101 Ok(())
102 }
103
104 pub async fn start(&self) -> ! {
105 std::future::pending().await
106 }
107}
108
109winio_handle::impl_as_widget!(ScrollView, handle);
110
111impl AsContainer for ScrollView {
112 fn as_container(&self) -> BorrowedContainer<'_> {
113 BorrowedContainer::winui(&self.canvas)
114 }
115}