Skip to main content

perspective_viewer/components/
render_warning.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 yew::prelude::*;
14
15use super::style::LocalStyle;
16use crate::css;
17use crate::renderer::limits::RenderLimits;
18
19#[derive(Properties, PartialEq)]
20pub struct RenderWarningProps {
21    pub dimensions: Option<RenderLimits>,
22
23    /// Called when the user clicks "Render all points".  The parent disables
24    /// the render warning on the active plugin and re-draws.
25    pub on_dismiss: Callback<()>,
26}
27
28#[function_component(RenderWarning)]
29pub fn render_warning(props: &RenderWarningProps) -> Html {
30    let dimensions = props.dimensions;
31    let (col_warn, row_warn) = if let Some(limits) = dimensions {
32        let col_warn = if limits.max_cols.is_some_and(|x| x < limits.num_cols) {
33            Some((limits.max_cols.unwrap(), limits.num_cols))
34        } else {
35            None
36        };
37
38        let row_warn = if limits.max_rows.is_some_and(|x| x < limits.num_rows) {
39            Some((
40                limits.num_cols * limits.max_rows.unwrap(),
41                limits.num_cols * limits.num_rows,
42            ))
43        } else {
44            None
45        };
46
47        (col_warn, row_warn)
48    } else {
49        (None, None)
50    };
51
52    if col_warn.is_some() || row_warn.is_some() {
53        let warning = match (col_warn, row_warn) {
54            (Some((x, y)), Some((a, b))) => html! {
55                <span style="white-space: nowrap">
56                    { "Rendering" }
57                    { render_pair(x, y) }
58                    { "of columns and" }
59                    { render_pair(a, b) }
60                    { "of points." }
61                </span>
62            },
63            (Some((x, y)), None) => html! {
64                <span style="white-space: nowrap">
65                    { "Rendering" }
66                    { render_pair(x, y) }
67                    { "of columns." }
68                </span>
69            },
70            (None, Some((x, y))) => html! {
71                <span style="white-space: nowrap">
72                    { "Rendering" }
73                    { render_pair(x, y) }
74                    { "of points." }
75                </span>
76            },
77            _ => html! { <div /> },
78        };
79
80        let on_dismiss = props.on_dismiss.clone();
81        let onclick = Callback::from(move |_: MouseEvent| on_dismiss.emit(()));
82        html! {
83            <>
84                <LocalStyle href={css!("render-warning")} />
85                <div
86                    class="plugin_information plugin_information--warning"
87                    id="plugin_information--size"
88                >
89                    <span class="plugin_information__icon" />
90                    <span class="plugin_information__text" id="plugin_information_count">
91                        { warning }
92                    </span>
93                    <span class="plugin_information__actions">
94                        <span class="plugin_information__action" onmousedown={onclick}>
95                            { "Render all points" }
96                        </span>
97                    </span>
98                </div>
99            </>
100        }
101    } else {
102        html! {}
103    }
104}
105
106fn pretty_print_int(i: usize) -> String {
107    let mut s = String::new();
108    let i_str = i.to_string();
109    let a = i_str.chars().rev().enumerate();
110    for (idx, val) in a {
111        if idx != 0 && idx % 3 == 0 {
112            s.insert(0, ',');
113        }
114        s.insert(0, val);
115    }
116    s
117}
118
119fn render_pair(n: usize, d: usize) -> Html {
120    let x = pretty_print_int(n);
121    let y = pretty_print_int(d);
122    let total = ((n as f64 / d as f64) * 100_f64).floor() as usize;
123    html! {
124        <span title={format!("${x} / ${y}")} class="plugin_information--overflow-hint">
125            { "\u{00a0}" }
126            <span class="plugin_information--overflow-hint-percent">{ format!("{}%", total) }</span>
127            { "\u{00a0}" }
128        </span>
129    }
130}