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