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