Skip to main content

fission_charts/
interaction.rs

1use fission_core::{Action, ActionId};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5pub enum ChartTooltipTrigger {
6    None,
7    Item,
8    Axis,
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum ChartSelectionMode {
13    None,
14    Single,
15    Multiple,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19pub enum ChartBrushType {
20    Rect,
21    Horizontal,
22    Vertical,
23    Polygon,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
27pub enum ChartLegendSelectionMode {
28    Static,
29    Toggle,
30    Single,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
34pub enum ChartEmphasisFocus {
35    None,
36    Series,
37    Data,
38    Adjacent,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
42pub enum ChartToolAction {
43    Restore,
44    SaveImage,
45    DataZoom,
46    Brush,
47}
48
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50pub struct ChartEmphasis {
51    pub enabled: bool,
52    pub focus: ChartEmphasisFocus,
53    pub scale: f32,
54}
55
56impl Default for ChartEmphasis {
57    fn default() -> Self {
58        Self {
59            enabled: false,
60            focus: ChartEmphasisFocus::None,
61            scale: 1.08,
62        }
63    }
64}
65
66impl ChartEmphasis {
67    pub fn series() -> Self {
68        Self {
69            enabled: true,
70            focus: ChartEmphasisFocus::Series,
71            ..Self::default()
72        }
73    }
74
75    pub fn data() -> Self {
76        Self {
77            enabled: true,
78            focus: ChartEmphasisFocus::Data,
79            ..Self::default()
80        }
81    }
82
83    pub fn scale(mut self, scale: f32) -> Self {
84        self.scale = scale;
85        self
86    }
87}
88
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct ChartBrush {
91    pub enabled: bool,
92    pub brush_type: ChartBrushType,
93    pub preview_rect: Option<(f32, f32, f32, f32)>,
94}
95
96impl Default for ChartBrush {
97    fn default() -> Self {
98        Self {
99            enabled: false,
100            brush_type: ChartBrushType::Rect,
101            preview_rect: None,
102        }
103    }
104}
105
106impl ChartBrush {
107    pub fn rect() -> Self {
108        Self {
109            enabled: true,
110            brush_type: ChartBrushType::Rect,
111            preview_rect: None,
112        }
113    }
114
115    pub fn horizontal() -> Self {
116        Self {
117            enabled: true,
118            brush_type: ChartBrushType::Horizontal,
119            preview_rect: None,
120        }
121    }
122
123    pub fn vertical() -> Self {
124        Self {
125            enabled: true,
126            brush_type: ChartBrushType::Vertical,
127            preview_rect: None,
128        }
129    }
130
131    pub fn preview_rect(mut self, x: f32, y: f32, width: f32, height: f32) -> Self {
132        self.preview_rect = Some((x, y, width, height));
133        self
134    }
135}
136
137#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
138pub struct ChartInteraction {
139    pub enabled: bool,
140    pub tooltip_trigger: ChartTooltipTrigger,
141    pub selection_mode: ChartSelectionMode,
142    pub legend_selection: ChartLegendSelectionMode,
143    pub brush: Option<ChartBrush>,
144    pub emphasis: ChartEmphasis,
145    pub toolbox_actions: Vec<ChartToolAction>,
146    pub emit_events: bool,
147    pub keyboard_focus: bool,
148}
149
150impl Default for ChartInteraction {
151    fn default() -> Self {
152        Self {
153            enabled: false,
154            tooltip_trigger: ChartTooltipTrigger::None,
155            selection_mode: ChartSelectionMode::None,
156            legend_selection: ChartLegendSelectionMode::Static,
157            brush: None,
158            emphasis: ChartEmphasis::default(),
159            toolbox_actions: Vec::new(),
160            emit_events: false,
161            keyboard_focus: false,
162        }
163    }
164}
165
166impl ChartInteraction {
167    pub fn new() -> Self {
168        Self::default()
169    }
170
171    pub fn tooltips(trigger: ChartTooltipTrigger) -> Self {
172        Self {
173            enabled: trigger != ChartTooltipTrigger::None,
174            tooltip_trigger: trigger,
175            ..Self::default()
176        }
177    }
178
179    pub fn enabled(mut self, enabled: bool) -> Self {
180        self.enabled = enabled;
181        self
182    }
183
184    pub fn tooltip_trigger(mut self, trigger: ChartTooltipTrigger) -> Self {
185        self.tooltip_trigger = trigger;
186        self.enabled |= trigger != ChartTooltipTrigger::None;
187        self
188    }
189
190    pub fn selection_mode(mut self, mode: ChartSelectionMode) -> Self {
191        self.selection_mode = mode;
192        self.enabled |= mode != ChartSelectionMode::None;
193        self
194    }
195
196    pub fn brush(mut self, brush: ChartBrush) -> Self {
197        self.brush = Some(brush);
198        self.enabled = true;
199        self
200    }
201
202    pub fn legend_selection(mut self, mode: ChartLegendSelectionMode) -> Self {
203        self.legend_selection = mode;
204        self.enabled |= mode != ChartLegendSelectionMode::Static;
205        self
206    }
207
208    pub fn emphasis(mut self, emphasis: ChartEmphasis) -> Self {
209        self.enabled |= emphasis.enabled;
210        self.emphasis = emphasis;
211        self
212    }
213
214    pub fn toolbox_actions(mut self, actions: Vec<ChartToolAction>) -> Self {
215        self.enabled |= !actions.is_empty();
216        self.toolbox_actions = actions;
217        self
218    }
219
220    pub fn emit_events(mut self, emit: bool) -> Self {
221        self.emit_events = emit;
222        self.enabled |= emit;
223        self
224    }
225
226    pub fn keyboard_focus(mut self, focusable: bool) -> Self {
227        self.keyboard_focus = focusable;
228        self.enabled |= focusable;
229        self
230    }
231}
232
233#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
234pub enum ChartInteractionKind {
235    Hover,
236    Press,
237    Release,
238    Scroll,
239    Key,
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
243pub enum ChartHitKind {
244    SeriesItem,
245    PlotArea,
246}
247
248#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
249pub struct ChartHit {
250    pub kind: ChartHitKind,
251    pub series_index: Option<usize>,
252    pub series_name: Option<String>,
253    pub data_index: Option<usize>,
254    pub value_x: Option<f32>,
255    pub value_y: Option<f32>,
256}
257
258impl ChartHit {
259    pub fn plot_area() -> Self {
260        Self {
261            kind: ChartHitKind::PlotArea,
262            series_index: None,
263            series_name: None,
264            data_index: None,
265            value_x: None,
266            value_y: None,
267        }
268    }
269
270    pub fn series_item(
271        series_index: usize,
272        series_name: impl Into<String>,
273        data_index: usize,
274        value_x: Option<f32>,
275        value_y: Option<f32>,
276    ) -> Self {
277        Self {
278            kind: ChartHitKind::SeriesItem,
279            series_index: Some(series_index),
280            series_name: Some(series_name.into()),
281            data_index: Some(data_index),
282            value_x,
283            value_y,
284        }
285    }
286}
287
288#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
289pub struct ChartInteractionEvent {
290    pub chart_id: Option<String>,
291    pub kind: ChartInteractionKind,
292    pub local_x: f32,
293    pub local_y: f32,
294    pub modifiers: u8,
295    pub hit: Option<ChartHit>,
296}
297
298impl Action for ChartInteractionEvent {
299    fn static_id() -> ActionId {
300        ActionId::from_name("fission_charts::ChartInteractionEvent")
301    }
302}