Skip to main content

perspective_viewer/components/viewer/
msg.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
13//! The root component's message protocol. One flat enum — the `update()` match
14//! in `viewer.rs` is its dispatch table; handler bodies live in the sibling
15//! domain modules ([`super::panels`], [`super::settings`], [`super::filters`],
16//! [`super::snapshots`]).
17
18use futures::channel::oneshot::Sender;
19use perspective_client::config::Filter;
20use perspective_js::utils::ApiResult;
21use wasm_bindgen::JsValue;
22
23use crate::components::settings_panel::SelectedTab;
24use crate::config::*;
25use crate::presentation::{ColumnLocator, ColumnSettingsTab, DragDropProps, PresentationProps};
26use crate::renderer::RendererProps;
27use crate::session::{SessionProps, TableLoadState, ViewStats};
28use crate::utils::Completion;
29
30/// The filter-bearing payload of a master panel's selection or click event
31/// (`MasterContribution`), as decoded by the host listeners in
32/// [`super::wiring`].
33#[derive(Debug)]
34pub struct MasterSelection {
35    /// The event's filter clauses (`insertFilters` for the select-detail
36    /// family, `config.filter` for clicks) — BEFORE the master's own stored
37    /// filters are subtracted (see `on_master_contribution`).
38    pub filters: Vec<Filter>,
39
40    /// A synthesized clicked-cell `[column, "==", value]` clause, used when
41    /// `filters` derives to nothing — e.g. a FLAT (un-grouped) datagrid
42    /// master, whose clicks carry no group-by path to filter on.
43    pub cell_fallback: Option<Filter>,
44}
45
46#[derive(Debug)]
47pub enum PerspectiveViewerMsg {
48    ColumnSettingsPanelSizeUpdate(Option<i32>),
49    ColumnSettingsPanelAutoWidth(f64),
50    ToggleColumnSettingsPin,
51    ColumnSettingsTabChanged(ColumnSettingsTab),
52    OpenColumnSettings {
53        locator: Option<ColumnLocator>,
54        sender: Option<Sender<()>>,
55        toggle: bool,
56    },
57    PreloadFontsUpdate,
58
59    /// Element-level reset (the public `reset()` API): reset EVERY panel and
60    /// clear the cross-filter overlay, symmetric with whole-element
61    /// `save`/`restore`. The `bool` also clears expressions/column settings.
62    Reset(bool, Option<Completion>),
63
64    /// Reset ONLY the named panel — or the active panel when `None` — to its
65    /// default `ViewerConfig` (the toolbar Reset button, the context menu's
66    /// "Reset" command, and the public `resetPanel()` API). The `bool` is
67    /// `Reset`'s expressions flag (toolbar shift-click); the `Completion`
68    /// resolves the `resetPanel()` promise after the reset's run completes
69    /// (invariant I6).
70    ResetPanel(Option<String>, bool, Option<Completion>),
71    Resize,
72
73    /// The set of layout panels changed (added/removed); re-render so the
74    /// layout host reconciles its `<regular-layout>` cells.
75    LayoutChanged,
76
77    /// Make the named panel active: re-target the settings panel + status bar
78    /// (and the root's session/renderer subscriptions) to its engines. The
79    /// `Completion` resolves `setActivePanel()` after the activation-chrome
80    /// nudge runs complete (invariant I6).
81    SetActivePanel(String, Option<Completion>),
82
83    /// The named panel's frame was closed (removed from the layout); remove it
84    /// from the workspace and dispose its engines. The `Completion` resolves
85    /// `removePanel()` after the eject's teardown run completes (invariant
86    /// I6) — carrying any teardown error, which was previously dropped.
87    ClosePanel(String, Option<Completion>),
88
89    /// Whole-element `restore` finished replacing the panel set in the
90    /// `Workspace` (new models inserted, old panels ejected, layout staged):
91    /// activate the named panel, re-subscribe the per-panel wiring, and
92    /// re-render — the SINGLE visible commit of the whole restore.
93    CommitWorkspaceRestore(String),
94
95    /// Duplicate the named panel: snapshot its config into a new independent
96    /// panel appended to the layout.
97    DuplicatePanel(String),
98
99    /// New panel: a fresh (default-config) panel bound to the named panel's
100    /// table (from the default client).
101    NewPanel(String),
102
103    /// New panel bound to the named `Table` on the named `Client` (the
104    /// context menu's "New" sub-menu). The `Client` is resolved by name from
105    /// the `Workspace` loaded-clients registry.
106    NewPanelFrom {
107        client: String,
108        table: String,
109    },
110
111    /// Toggle the named panel's master/detail (filter-source) role.
112    ToggleMaster(String),
113
114    /// A master panel's selection state, from EITHER host listener
115    /// (`perspective-global-filter` select/deselect or `perspective-click`):
116    /// `Some` REPLACES that panel's global-filter contribution, `None`
117    /// (deselect) clears it. Non-master sources are ignored by the handler.
118    MasterContribution(String, Option<MasterSelection>),
119
120    /// Remove the global filter at this index (GlobalFilterBar chip ×).
121    RemoveGlobalFilter(usize),
122
123    /// Clear all global filters (GlobalFilterBar "Clear").
124    ClearGlobalFilters,
125
126    /// Some panel's title changed (any panel, via `_title_subscriptions`);
127    /// re-render so the tab titles refresh.
128    TitlesChanged,
129    SettingsPanelSizeUpdate(Option<i32>),
130
131    /// The settings-pane divider proposed a new pane width (per pointermove,
132    /// from the *deferred* `SplitPanel` — it has NOT been applied). Feeds the
133    /// latest-wins presize pump (`PRESIZE_EVERYWHERE_PLAN.md` P1): geometry
134    /// commits only after every visible panel has rendered at its target.
135    SettingsDividerMove(i32),
136
137    /// Run one pump iteration: presize all visible panels at the newest
138    /// proposed pane width, then commit it.
139    SettingsDividerPump,
140
141    /// Presize for this pane width completed — commit it (the deferred
142    /// `SplitPanel`'s controlled `size`), then pump again if a newer target
143    /// arrived meanwhile.
144    SettingsDividerCommit(i32),
145
146    /// Divider drag ended: reactively finalize every visible panel at its
147    /// exact settled cell (debounced no-op when the presizes were exact).
148    SettingsDividerFinish,
149    SettingsPanelTabChanged(SelectedTab),
150    SettingsPanelAutoWidth(f64),
151    ToggleDebug,
152    ToggleSettingsComplete(SettingsUpdate, Sender<()>),
153    ToggleSettingsInit(Option<SettingsUpdate>, Option<Sender<ApiResult<JsValue>>>),
154    UpdateSession(Box<SessionProps>),
155    UpdateRenderer(Box<RendererProps>),
156    UpdatePresentation(Box<PresentationProps>),
157
158    /// Update only `is_settings_open` in the presentation snapshot without
159    /// touching `available_themes` (which requires async data).
160    UpdateSettingsOpen(bool),
161    UpdateIsWorkspace(bool),
162
163    /// Update only `open_column_settings` in the presentation snapshot.
164    UpdateColumnSettings(Box<crate::presentation::OpenColumnSettings>),
165    UpdateDragDrop(Box<DragDropProps>),
166
167    /// Update only stats-related fields of `session_props` without touching
168    /// `config`.  This prevents `stats_changed` events (e.g. from `reset()`)
169    /// from propagating a freshly-cleared config to the column selector.
170    UpdateSessionStats(Option<ViewStats>, Option<TableLoadState>),
171
172    /// Refresh the root's render snapshot of the `Workspace`-owned global
173    /// filter set (dispatched by its `filters_changed` PubSub).
174    UpdateGlobalFilters,
175
176    /// The active panel's in-flight config-run count changed. LEVEL-
177    /// triggered: the payload is the ABSOLUTE count (RAII-settled — see
178    /// `Session::begin_config_run`), which the handler ASSIGNS to
179    /// `update_count`; there is no delta arithmetic to drift. Threaded to
180    /// `StatusIndicator` as the "updating" spinner.
181    UpdateInFlight(u32),
182}