perspective_viewer/components/
string_column_style.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::*;
14use yew::*;
15
16use super::form::color_selector::*;
17use super::modal::{ModalLink, SetModalLink};
18use super::style::LocalStyle;
19use crate::components::form::select_field::SelectEnumField;
20use crate::config::*;
21use crate::utils::WeakScope;
22use crate::*;
23
24pub enum StringColumnStyleMsg {
25    Reset(StringColumnStyleConfig),
26    FormatChanged(Option<FormatMode>),
27    ColorModeChanged(Option<StringColorMode>),
28    ColorChanged(String),
29    ColorReset,
30}
31
32#[derive(Properties)]
33pub struct StringColumnStyleProps {
34    pub config: Option<StringColumnStyleConfig>,
35    pub default_config: StringColumnStyleDefaultConfig,
36
37    #[prop_or_default]
38    pub on_change: Callback<ColumnConfigValueUpdate>,
39
40    #[prop_or_default]
41    weak_link: WeakScope<StringColumnStyle>,
42}
43
44impl ModalLink<StringColumnStyle> for StringColumnStyleProps {
45    fn weak_link(&self) -> &'_ WeakScope<StringColumnStyle> {
46        &self.weak_link
47    }
48}
49
50impl PartialEq for StringColumnStyleProps {
51    fn eq(&self, _other: &Self) -> bool {
52        false
53    }
54}
55
56/// A component for the style form control for [`String`] columns.
57pub struct StringColumnStyle {
58    config: StringColumnStyleConfig,
59    default_config: StringColumnStyleDefaultConfig,
60}
61
62impl StringColumnStyle {
63    /// When this config has changed, we must signal the wrapper element.
64    fn dispatch_config(&self, ctx: &Context<Self>) {
65        let update = Some(self.config.clone()).filter(|x| x != &StringColumnStyleConfig::default());
66        ctx.props()
67            .on_change
68            .emit(ColumnConfigValueUpdate::DatagridStringStyle(update));
69    }
70
71    /// Generate a color selector component for a specific `StringColorMode`
72    /// variant.
73    fn color_select_row(&self, ctx: &Context<Self>, mode: &StringColorMode, title: &str) -> Html {
74        let on_color = ctx.link().callback(StringColumnStyleMsg::ColorChanged);
75        let color = self
76            .config
77            .color
78            .clone()
79            .unwrap_or_else(|| self.default_config.color.to_owned());
80
81        let color_props = props!(ColorProps {
82            title: title.to_owned(),
83            on_color,
84            is_modified: color != self.default_config.color,
85            color,
86            on_reset: ctx.link().callback(|_| StringColumnStyleMsg::ColorReset)
87        });
88
89        if &self.config.string_color_mode == mode {
90            html! { <div class="row"><ColorSelector ..color_props /></div> }
91        } else {
92            html! {}
93        }
94    }
95}
96
97impl Component for StringColumnStyle {
98    type Message = StringColumnStyleMsg;
99    type Properties = StringColumnStyleProps;
100
101    fn create(ctx: &Context<Self>) -> Self {
102        ctx.set_modal_link();
103        Self {
104            config: ctx.props().config.clone().unwrap_or_default(),
105            default_config: ctx.props().default_config.clone(),
106        }
107    }
108
109    // Always re-render when config changes.
110    fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
111        let mut new_config = ctx.props().config.clone().unwrap_or_default();
112        if self.config != new_config {
113            std::mem::swap(&mut self.config, &mut new_config);
114            true
115        } else {
116            false
117        }
118    }
119
120    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
121        match msg {
122            StringColumnStyleMsg::Reset(config) => {
123                self.config = config;
124                true
125            },
126            StringColumnStyleMsg::FormatChanged(val) => {
127                self.config.format = val.unwrap_or_default();
128                self.dispatch_config(ctx);
129                true
130            },
131            StringColumnStyleMsg::ColorModeChanged(mode) => {
132                self.config.string_color_mode = mode.unwrap_or_default();
133                self.dispatch_config(ctx);
134                true
135            },
136            StringColumnStyleMsg::ColorChanged(color) => {
137                self.config.color = Some(color);
138                self.dispatch_config(ctx);
139                true
140            },
141            StringColumnStyleMsg::ColorReset => {
142                self.config.color = Some(self.default_config.color.clone());
143                self.dispatch_config(ctx);
144                true
145            },
146        }
147    }
148
149    fn view(&self, ctx: &Context<Self>) -> Html {
150        let format_mode_selected = self.config.format;
151        let format_mode_changed = ctx.link().callback(StringColumnStyleMsg::FormatChanged);
152        let selected_color_mode = self.config.string_color_mode;
153        let color_mode_changed = ctx.link().callback(StringColumnStyleMsg::ColorModeChanged);
154        let color_controls = match selected_color_mode {
155            StringColorMode::Foreground => {
156                self.color_select_row(ctx, &StringColorMode::Foreground, "foreground-label")
157            },
158            StringColorMode::Background => {
159                self.color_select_row(ctx, &StringColorMode::Background, "background-label")
160            },
161            StringColorMode::Series => {
162                self.color_select_row(ctx, &StringColorMode::Series, "series-label")
163            },
164            StringColorMode::None => html! {},
165        };
166
167        html! {
168            <>
169                <LocalStyle href={css!("column-style")} />
170                <div id="column-style-container" class="string-column-style-container">
171                    <SelectEnumField<FormatMode>
172                        label="format"
173                        on_change={format_mode_changed}
174                        current_value={format_mode_selected}
175                    />
176                    <SelectEnumField<StringColorMode>
177                        label="color"
178                        on_change={color_mode_changed}
179                        current_value={selected_color_mode}
180                    />
181                    { color_controls }
182                </div>
183            </>
184        }
185    }
186}