Skip to main content

perspective_viewer/ui/containers/
scroll_panel_item.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::cell::Cell;
14use std::rc::Rc;
15
16use yew::prelude::*;
17
18#[derive(PartialEq, Properties)]
19pub struct ScrollPanelItemProps {
20    pub children: Children,
21
22    pub size_hint: f64,
23
24    #[prop_or_default]
25    pub is_debug_mode: bool,
26
27    #[prop_or_default]
28    measured_size: Rc<Cell<Option<f64>>>,
29}
30
31impl ScrollPanelItemProps {
32    pub(crate) fn get_size(&self) -> f64 {
33        if self.is_debug_mode {
34            self.measured_size.get().unwrap_or(self.size_hint)
35        } else {
36            self.size_hint
37        }
38    }
39}
40
41pub struct ScrollPanelItem {
42    node: NodeRef,
43}
44
45impl Component for ScrollPanelItem {
46    type Message = ();
47    type Properties = ScrollPanelItemProps;
48
49    fn create(ctx: &Context<Self>) -> Self {
50        if ctx.props().is_debug_mode {
51            ctx.props().measured_size.set(Some(ctx.props().size_hint));
52        }
53
54        Self {
55            node: NodeRef::default(),
56        }
57    }
58
59    fn view(&self, ctx: &Context<Self>) -> Html {
60        html! {
61            if ctx.props().is_debug_mode {
62                <div class="debug-size-wrapper" style="display: flow-root" ref={self.node.clone()}>
63                    for child in ctx.props().children.iter() {
64                        { child }
65                    }
66                </div>
67            } else {
68                for child in ctx.props().children.iter() {
69                    { child }
70                }
71            }
72        }
73    }
74
75    fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
76        if ctx.props().is_debug_mode {
77            ctx.props().measured_size.set(Some(ctx.props().size_hint));
78        }
79
80        true
81    }
82
83    fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
84        if first_render && ctx.props().is_debug_mode {
85            let elem = self.node.cast::<web_sys::HtmlElement>().unwrap();
86            let new_height = elem.get_bounding_client_rect().height();
87            if ctx.props().measured_size.get() != Some(new_height) {
88                tracing::warn!(
89                    "ScrollPanel size_hint does not match element size: {} != {}",
90                    ctx.props().size_hint,
91                    new_height
92                );
93                web_sys::console::warn_1(&elem);
94                ctx.props().measured_size.set(Some(new_height));
95            }
96        }
97    }
98}