perspective_viewer/components/
main_panel.rs1use perspective_js::utils::*;
14use wasm_bindgen::prelude::*;
15use yew::prelude::*;
16
17use super::render_warning::RenderWarning;
18use super::status_bar::StatusBar;
19use crate::custom_events::CustomEvents;
20use crate::presentation::Presentation;
21use crate::renderer::limits::RenderLimits;
22use crate::renderer::*;
23use crate::session::{Session, TableErrorState, TableLoadState, ViewStats};
24use crate::utils::*;
25
26#[derive(Clone, Properties)]
27pub struct MainPanelProps {
28 pub on_settings: Callback<()>,
29
30 pub on_reset: Callback<bool>,
34
35 pub render_limits: Option<RenderLimits>,
39
40 pub has_table: Option<TableLoadState>,
43 pub is_errored: bool,
44 pub stats: Option<ViewStats>,
45 pub update_count: u32,
46 pub error: Option<TableErrorState>,
47 pub title: Option<String>,
48
49 pub is_settings_open: bool,
51 pub selected_theme: Option<String>,
52 pub available_themes: PtrEqRc<Vec<String>>,
53 pub is_workspace: bool,
54
55 pub custom_events: CustomEvents,
57 pub session: Session,
58 pub renderer: Renderer,
59 pub presentation: Presentation,
60}
61
62impl PartialEq for MainPanelProps {
63 fn eq(&self, rhs: &Self) -> bool {
64 self.has_table == rhs.has_table
65 && self.is_errored == rhs.is_errored
66 && self.stats == rhs.stats
67 && self.update_count == rhs.update_count
68 && self.error == rhs.error
69 && self.title == rhs.title
70 && self.is_settings_open == rhs.is_settings_open
71 && self.selected_theme == rhs.selected_theme
72 && self.available_themes == rhs.available_themes
73 && self.is_workspace == rhs.is_workspace
74 && self.render_limits == rhs.render_limits
75 }
76}
77
78impl MainPanelProps {
79 fn is_title(&self) -> bool {
80 self.title.is_some()
81 }
82}
83
84#[derive(Debug)]
85pub enum MainPanelMsg {
86 PointerEvent(web_sys::PointerEvent),
87}
88
89pub struct MainPanel {
90 main_panel_ref: NodeRef,
91}
92
93impl Component for MainPanel {
94 type Message = MainPanelMsg;
95 type Properties = MainPanelProps;
96
97 fn create(_ctx: &Context<Self>) -> Self {
98 Self {
99 main_panel_ref: NodeRef::default(),
100 }
101 }
102
103 fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
104 match msg {
105 MainPanelMsg::PointerEvent(event) => {
106 if event.target().map(JsValue::from)
107 == self
108 .main_panel_ref
109 .cast::<web_sys::HtmlElement>()
110 .map(JsValue::from)
111 {
112 ctx.props()
113 .custom_events
114 .dispatch_event(format!("statusbar-{}", event.type_()).as_str(), &event)
115 .unwrap();
116 }
117
118 false
119 },
120 }
121 }
122
123 fn changed(&mut self, _ctx: &Context<Self>, _old: &Self::Properties) -> bool {
124 true
125 }
126
127 fn view(&self, ctx: &Context<Self>) -> Html {
128 let Self::Properties {
129 custom_events,
130 presentation,
131 renderer,
132 session,
133 ..
134 } = ctx.props();
135
136 let is_settings_open = ctx.props().is_settings_open
137 && matches!(ctx.props().has_table, Some(TableLoadState::Loaded));
138
139 let on_settings = (!is_settings_open).then(|| ctx.props().on_settings.clone());
140
141 let mut class = classes!();
142 if !is_settings_open {
143 class.push("settings-closed");
144 }
145
146 if ctx.props().is_title() {
147 class.push("titled");
148 }
149
150 let pointerdown = ctx.link().callback(MainPanelMsg::PointerEvent);
151 let on_dismiss_warning = {
152 clone!(renderer, session);
153 Callback::from(move |_: ()| {
154 clone!(renderer, session);
155 ApiFuture::spawn(async move {
156 renderer.disable_active_plugin_render_warning();
157 let view_task = session.get_view();
158 renderer.update(view_task).await
159 });
160 })
161 };
162
163 html! {
164 <div id="main_column">
165 <StatusBar
166 id="status_bar"
167 {on_settings}
168 on_reset={ctx.props().on_reset.clone()}
169 has_table={ctx.props().has_table.clone()}
170 is_errored={ctx.props().is_errored}
171 stats={ctx.props().stats.clone()}
172 update_count={ctx.props().update_count}
173 error={ctx.props().error.clone()}
174 title={ctx.props().title.clone()}
175 is_settings_open={ctx.props().is_settings_open}
176 selected_theme={ctx.props().selected_theme.clone()}
177 available_themes={ctx.props().available_themes.clone()}
178 is_workspace={ctx.props().is_workspace}
179 {custom_events}
180 {presentation}
181 {renderer}
182 {session}
183 />
184 <div
185 id="main_panel_container"
186 ref={self.main_panel_ref.clone()}
187 {class}
188 onpointerdown={pointerdown}
189 >
190 <RenderWarning
191 on_dismiss={on_dismiss_warning}
192 dimensions={ctx.props().render_limits}
193 />
194 <slot />
195 </div>
196 </div>
197 }
198 }
199
200 fn destroy(&mut self, _ctx: &Context<Self>) {}
201}