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