Skip to main content

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