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::*;
14
15use crate::config::*;
16use crate::ui::{ModalLink, SelectEnumField, SetModalLink};
17use crate::utils::WeakScope;
18
19/// Format-only widget for [`String`] columns. Renders the `format` enum
20/// only; color/color-mode UI is provided externally as primitive `Enum`
21/// + `Color` schema fields.
22#[derive(Properties)]
23pub struct StringColumnStyleProps {
24    pub config: Option<StringColumnStyleConfig>,
25
26    #[prop_or_default]
27    pub on_change: Callback<ColumnConfigFieldUpdate>,
28
29    #[prop_or_default]
30    pub keys: Vec<String>,
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        self.config == other.config
45    }
46}
47
48pub enum StringColumnStyleMsg {
49    FormatChanged(Option<FormatMode>),
50}
51
52pub struct StringColumnStyle {
53    config: StringColumnStyleConfig,
54}
55
56impl Component for StringColumnStyle {
57    type Message = StringColumnStyleMsg;
58    type Properties = StringColumnStyleProps;
59
60    fn create(ctx: &Context<Self>) -> Self {
61        ctx.set_modal_link();
62        Self {
63            config: ctx.props().config.clone().unwrap_or_default(),
64        }
65    }
66
67    fn changed(&mut self, ctx: &Context<Self>, _old: &Self::Properties) -> bool {
68        let mut new_config = ctx.props().config.clone().unwrap_or_default();
69        if self.config != new_config {
70            std::mem::swap(&mut self.config, &mut new_config);
71            true
72        } else {
73            false
74        }
75    }
76
77    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
78        match msg {
79            StringColumnStyleMsg::FormatChanged(val) => {
80                self.config.format = val.unwrap_or_default();
81                self.dispatch_config(ctx);
82                true
83            },
84        }
85    }
86
87    fn view(&self, ctx: &Context<Self>) -> Html {
88        let format_mode_changed = ctx.link().callback(StringColumnStyleMsg::FormatChanged);
89        html! {
90            <>
91                <div id="column-style-container" class="string-column-style-container">
92                    <SelectEnumField<FormatMode>
93                        label="format"
94                        on_change={format_mode_changed}
95                        current_value={self.config.format}
96                    />
97                </div>
98            </>
99        }
100    }
101}
102
103impl StringColumnStyle {
104    /// When this config has changed, we must signal the wrapper element.
105    fn dispatch_config(&self, ctx: &Context<Self>) {
106        let value = if self.config == StringColumnStyleConfig::default() {
107            serde_json::Map::new()
108        } else {
109            match serde_json::to_value(&self.config) {
110                Ok(serde_json::Value::Object(m)) => m,
111                _ => serde_json::Map::new(),
112            }
113        };
114
115        ctx.props().on_change.emit(ColumnConfigFieldUpdate {
116            keys: ctx.props().keys.clone(),
117            value,
118        });
119    }
120}