From bdef01af31b93f0a6d32675f91a8ab1e53d8716b Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Tue, 25 Jun 2024 07:14:23 -0300 Subject: [PATCH 1/3] Abstract modal into Portal. --- src/app.rs | 51 +++-- src/landing/model_card.rs | 12 +- src/my_models/delete_model_modal.rs | 15 +- src/my_models/downloaded_files_row.rs | 32 ++-- src/my_models/model_info_modal.rs | 4 +- src/shared/download_notification_popup.rs | 10 +- src/shared/mod.rs | 4 +- src/shared/modal.rs | 219 ++-------------------- src/shared/widgets.rs | 2 +- 9 files changed, 79 insertions(+), 270 deletions(-) diff --git a/src/app.rs b/src/app.rs index 364a9259..c17f5ac1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -9,7 +9,7 @@ use crate::shared::actions::{ChatAction, DownloadAction}; use crate::shared::download_notification_popup::{ DownloadNotificationPopupWidgetRefExt, DownloadResult, PopupAction, }; -use crate::shared::modal::ModalWidgetRefExt; +use crate::shared::portal::PortalWidgetRefExt; use makepad_widgets::*; live_design! { @@ -18,6 +18,7 @@ live_design! { import makepad_draw::shader::std::*; import crate::shared::styles::*; + import crate::shared::portal::*; import crate::shared::modal::*; import crate::shared::widgets::SidebarMenuButton; import crate::shared::download_notification_popup::DownloadNotificationPopup; @@ -98,40 +99,34 @@ live_design! { } } - modal_root = { - model_card_view_all_modal_view = { - content = { - model_card_view_all_modal = {} + portal_root = { + modal_model_card_view_all_portal_view = { + modal = { + content = { + model_card_view_all_modal = {} + } } } - delete_model_modal_view = { - content = { - delete_model_modal = {} + modal_delete_model_portal_view = { + modal = { + content = { + delete_model_modal = {} + } } } - model_info_modal_view = { - content = { - model_info_modal = {} + modal_model_info_portal_view = { + modal = { + content = { + model_info_modal = {} + } } } - popup_download_success_modal_view = { + popup_download_success_portal_view = { align: {x: 1, y: 0} - - // TODO: By setting this on Fit we dissable the closing on click outside of modal - // functionallity. We need to rethink the Modal widget so its more generic, - // kinda like a portal that lets you render stuff from anywhere, for now - // we use it as is, with this little hack. - bg_view = { - width: Fit - height: Fit - show_bg: false - } - content = { - popup_download_success = {} - } + popup_download_success = {} } } } @@ -187,7 +182,7 @@ impl MatchEvent for App { .selected_to_visible( cx, &self.ui, - &actions, + actions, ids!( application_pages.discover_frame, application_pages.chat_frame, @@ -302,8 +297,8 @@ impl App { } } - let mut modal = self.ui.modal(id!(modal_root)); - let _ = modal.show_modal_view_by_id(cx, live_id!(popup_download_success_modal_view)); + let mut portal = self.ui.portal(id!(portal_root)); + let _ = portal.show_portal_view_by_id(cx, live_id!(popup_download_success_portal_view)); } } } diff --git a/src/landing/model_card.rs b/src/landing/model_card.rs index d38f8123..0fab7c23 100644 --- a/src/landing/model_card.rs +++ b/src/landing/model_card.rs @@ -1,6 +1,6 @@ use crate::data::store::{ModelWithDownloadInfo, Store}; use crate::shared::external_link::ExternalLinkWidgetExt; -use crate::shared::modal::ModalAction; +use crate::shared::portal::PortalAction; use crate::shared::utils::hugging_face_model_url; use chrono::Utc; use makepad_widgets::*; @@ -410,7 +410,7 @@ impl WidgetMatchEvent for ModelCard { cx.widget_action( widget_uid, &scope.path, - ModalAction::ShowModalView(live_id!(model_card_view_all_modal_view)), + PortalAction::ShowPortalView(live_id!(modal_model_card_view_all_portal_view)), ); cx.widget_action( @@ -446,7 +446,11 @@ impl Widget for ModelCardViewAllModal { fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { let store = scope.data.get::().unwrap(); - let model = store.search.models.iter().find(|model| model.id == self.model_id); + let model = store + .search + .models + .iter() + .find(|model| model.id == self.model_id); if let Some(model) = model { let name = &model.name; @@ -467,7 +471,7 @@ impl WidgetMatchEvent for ModelCardViewAllModal { if let Some(fe) = self.view(id!(close_button)).finger_up(actions) { if fe.was_tap() { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } } diff --git a/src/my_models/delete_model_modal.rs b/src/my_models/delete_model_modal.rs index f1734ea9..6ea8838e 100644 --- a/src/my_models/delete_model_modal.rs +++ b/src/my_models/delete_model_modal.rs @@ -1,7 +1,7 @@ use makepad_widgets::*; use moxin_protocol::data::FileID; -use crate::{chat::chat_panel::ChatPanelAction, data::store::Store, shared::modal::ModalAction}; +use crate::{chat::chat_panel::ChatPanelAction, data::store::Store, shared::portal::PortalAction}; live_design! { import makepad_widgets::base::*; @@ -158,7 +158,12 @@ impl Widget for DeleteModelModal { } fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { - let downloaded_files = &scope.data.get::().unwrap().downloads.downloaded_files; + let downloaded_files = &scope + .data + .get::() + .unwrap() + .downloads + .downloaded_files; let downloaded_file = downloaded_files .iter() @@ -183,7 +188,7 @@ impl WidgetMatchEvent for DeleteModelModal { if let Some(fe) = self.view(id!(close_button)).finger_up(actions) { if fe.was_tap() { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } @@ -201,7 +206,7 @@ impl WidgetMatchEvent for DeleteModelModal { store .delete_file(self.file_id.clone()) .expect("Failed to delete file"); - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } @@ -210,7 +215,7 @@ impl WidgetMatchEvent for DeleteModelModal { .finger_up(actions) { if fe.was_tap() { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } } diff --git a/src/my_models/downloaded_files_row.rs b/src/my_models/downloaded_files_row.rs index 35af68a9..51c70498 100644 --- a/src/my_models/downloaded_files_row.rs +++ b/src/my_models/downloaded_files_row.rs @@ -2,8 +2,8 @@ use makepad_widgets::*; use moxin_protocol::data::{DownloadedFile, FileID}; use crate::my_models::{delete_model_modal::DeleteModelAction, model_info_modal::ModelInfoAction}; -use crate::shared::{actions::ChatAction, modal::ModalAction}; use crate::shared::utils::format_model_size; +use crate::shared::{actions::ChatAction, portal::PortalAction}; live_design! { import makepad_widgets::base::*; @@ -230,13 +230,15 @@ impl Widget for DownloadedFilesRow { .set_text(¶meters); // Version tag - let filename = format!("{}/{}", downloaded_file.model.name, downloaded_file.file.name); + let filename = format!( + "{}/{}", + downloaded_file.model.name, downloaded_file.file.name + ); self.label(id!(h_wrapper.model_file.model_version_tag.version)) .set_text(&filename); // File size tag - let file_size = - format_model_size(&downloaded_file.file.size).unwrap_or("-".to_string()); + let file_size = format_model_size(&downloaded_file.file.size).unwrap_or("-".to_string()); self.label(id!(h_wrapper.file_size_tag.file_size)) .set_text(&file_size); @@ -245,8 +247,10 @@ impl Widget for DownloadedFilesRow { self.label(id!(h_wrapper.date_added_tag.date_added)) .set_text(&formatted_date); - self.button(id!(start_chat_button)).set_visible(!props.show_resume); - self.button(id!(resume_chat_button)).set_visible(props.show_resume); + self.button(id!(start_chat_button)) + .set_visible(!props.show_resume); + self.button(id!(resume_chat_button)) + .set_visible(props.show_resume); self.view.draw_walk(cx, scope, walk) } @@ -258,21 +262,13 @@ impl WidgetMatchEvent for DownloadedFilesRow { if self.button(id!(start_chat_button)).clicked(actions) { if let Some(file_id) = &self.file_id { - cx.widget_action( - widget_uid, - &scope.path, - ChatAction::Start(file_id.clone()), - ); + cx.widget_action(widget_uid, &scope.path, ChatAction::Start(file_id.clone())); } } if self.button(id!(resume_chat_button)).clicked(actions) { if let Some(file_id) = &self.file_id { - cx.widget_action( - widget_uid, - &scope.path, - ChatAction::Resume(file_id.clone()), - ); + cx.widget_action(widget_uid, &scope.path, ChatAction::Resume(file_id.clone())); } } @@ -286,7 +282,7 @@ impl WidgetMatchEvent for DownloadedFilesRow { cx.widget_action( widget_uid, &scope.path, - ModalAction::ShowModalView(live_id!(model_info_modal_view)), + PortalAction::ShowPortalView(live_id!(modal_model_info_portal_view)), ); } } @@ -301,7 +297,7 @@ impl WidgetMatchEvent for DownloadedFilesRow { cx.widget_action( widget_uid, &scope.path, - ModalAction::ShowModalView(live_id!(delete_model_modal_view)), + PortalAction::ShowPortalView(live_id!(modal_delete_model_portal_view)), ); } } diff --git a/src/my_models/model_info_modal.rs b/src/my_models/model_info_modal.rs index 650fd222..da84abfa 100644 --- a/src/my_models/model_info_modal.rs +++ b/src/my_models/model_info_modal.rs @@ -1,6 +1,6 @@ use crate::{ data::store::Store, - shared::{modal::ModalAction, utils::hugging_face_model_url}, + shared::{portal::PortalAction, utils::hugging_face_model_url}, }; use makepad_widgets::*; use moxin_protocol::data::{FileID, ModelID}; @@ -234,7 +234,7 @@ impl WidgetMatchEvent for ModelInfoModal { if let Some(fe) = self.view(id!(close_button)).finger_up(actions) { if fe.was_tap() { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } diff --git a/src/shared/download_notification_popup.rs b/src/shared/download_notification_popup.rs index d3711b71..79d50ee1 100644 --- a/src/shared/download_notification_popup.rs +++ b/src/shared/download_notification_popup.rs @@ -3,7 +3,7 @@ use moxin_protocol::data::{File, FileID}; use crate::shared::actions::DownloadAction; -use super::modal::ModalAction; +use super::portal::PortalAction; live_design! { import makepad_widgets::base::*; @@ -243,7 +243,7 @@ impl WidgetMatchEvent for DownloadNotificationPopup { if let Some(fe) = self.view(id!(close_button)).finger_up(actions) { if fe.was_tap() { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } @@ -253,7 +253,7 @@ impl WidgetMatchEvent for DownloadNotificationPopup { { // TODO: Abstract the navigation actions on a single enum for the whole app. cx.widget_action(widget_uid, &scope.path, PopupAction::NavigateToMyModels); - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } if self.link_label(id!(retry_link)).clicked(actions) { @@ -263,7 +263,7 @@ impl WidgetMatchEvent for DownloadNotificationPopup { &scope.path, DownloadAction::Play(file_id.clone()), ); - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } if self.link_label(id!(cancel_link)).clicked(actions) { @@ -273,7 +273,7 @@ impl WidgetMatchEvent for DownloadNotificationPopup { &scope.path, DownloadAction::Cancel(file_id.clone()), ); - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } } } diff --git a/src/shared/mod.rs b/src/shared/mod.rs index b4517735..fafb4d8d 100644 --- a/src/shared/mod.rs +++ b/src/shared/mod.rs @@ -1,10 +1,11 @@ use makepad_widgets::Cx; pub mod actions; +pub mod download_notification_popup; pub mod external_link; pub mod icon; +pub mod portal; pub mod modal; -pub mod download_notification_popup; pub mod resource_imports; pub mod styles; pub mod utils; @@ -15,6 +16,7 @@ pub fn live_design(cx: &mut Cx) { resource_imports::live_design(cx); widgets::live_design(cx); icon::live_design(cx); + portal::live_design(cx); modal::live_design(cx); external_link::live_design(cx); download_notification_popup::live_design(cx); diff --git a/src/shared/modal.rs b/src/shared/modal.rs index 963c6cdc..5b74601c 100644 --- a/src/shared/modal.rs +++ b/src/shared/modal.rs @@ -1,12 +1,15 @@ use makepad_widgets::*; +use super::portal::PortalAction; + live_design! { import makepad_widgets::base::*; import makepad_widgets::theme_desktop_dark::*; import crate::shared::styles::*; + import crate::shared::portal::*; - ModalView = {{ModalView}} { + Modal = {{Modal}} { width: Fill height: Fill flow: Overlay @@ -27,38 +30,29 @@ live_design! { flow: Overlay width: Fit height: Fit - // This assures that the hit events gets consummed when clicking the content, so it closes when clicking outside of it. - cursor: Arrow } } - - Modal = {{Modal}} { - width: Fill - height: Fill - - flow: Right - } } -// TODO: look for a way of being able to add custom "ModalView" inside de model -// (which should become something like "Portal") maybe with traits. #[derive(Live, LiveHook, LiveRegisterWidget, WidgetRef)] -pub struct ModalView { +pub struct Modal { #[deref] view: View, } -impl Widget for ModalView { +impl Widget for Modal { fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { let widget_uid = self.widget_uid(); self.view(id!(content)).handle_event(cx, event, scope); - match event.hits(cx, self.view(id!(bg_view)).area()) { - Hit::FingerUp(_fe) => { - cx.widget_action(widget_uid, &scope.path, ModalAction::CloseModal); + let content_rec = self.view(id!(content)).area().rect(cx); + + // Check if there was a click outside of the content (bg), then close if true. + if let Hit::FingerUp(fe) = event.hits_with_capture_overload(cx, self.view.area(), true) { + if !content_rec.contains(fe.abs) { + cx.widget_action(widget_uid, &scope.path, PortalAction::Close); } - _ => (), } } @@ -68,203 +62,16 @@ impl Widget for ModalView { } } -impl WidgetNode for ModalView { - fn walk(&mut self, cx: &mut Cx) -> Walk { - self.view.walk(cx) - } - - fn redraw(&mut self, cx: &mut Cx) { - self.view.redraw(cx); - } - - fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) { - self.view.find_widgets(path, cached, results); - } -} - -impl ModalView { - pub fn show(&mut self, cx: &mut Cx) { - self.apply_over(cx, live! {visible: true}); - self.redraw(cx); - } - - pub fn hide(&mut self, cx: &mut Cx) { - self.apply_over(cx, live! {visible: false}); - self.redraw(cx); - } - - pub fn is_showing(&self) -> bool { - self.view.is_visible() - } -} - -impl ModalViewRef { - pub fn show(&mut self, cx: &mut Cx) { - if let Some(mut inner) = self.borrow_mut() { - inner.show(cx); - } - } - - pub fn hide(&mut self, cx: &mut Cx) { - if let Some(mut inner) = self.borrow_mut() { - inner.hide(cx) - } - } - - pub fn is_showing(&self) -> bool { - if let Some(inner) = self.borrow() { - inner.is_showing() - } else { - false - } - } -} - -#[derive(Clone, DefaultNone, Eq, Hash, PartialEq, Debug)] -pub enum ModalAction { - None, - ShowModalView(LiveId), - CloseModal, -} - -#[derive(Default)] -enum ActiveModalView { - #[default] - None, - Active(LiveId), -} - -#[derive(Live, LiveRegisterWidget, WidgetRef)] -pub struct Modal { - #[deref] - view: View, - - #[rust] - active_modal_view: ActiveModalView, -} - -impl Widget for Modal { - fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { - if let Some(widget_ref) = self.get_active_modal_view(cx) { - widget_ref.handle_event(cx, event, scope); - } - - self.widget_match_event(cx, event, scope); - } - - fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { - if let Some(widget_ref) = self.get_active_modal_view(cx) { - widget_ref.draw_walk(cx, scope, walk)?; - } - DrawStep::done() - } -} - -impl LiveHook for Modal { - fn after_new_from_doc(&mut self, _cx: &mut Cx) {} -} - impl WidgetNode for Modal { fn walk(&mut self, cx: &mut Cx) -> Walk { self.view.walk(cx) } fn redraw(&mut self, cx: &mut Cx) { - if let Some(widget_ref) = self.get_active_modal_view(cx) { - widget_ref.redraw(cx); - } + self.view.redraw(cx); } fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) { self.view.find_widgets(path, cached, results); } } - -impl WidgetMatchEvent for Modal { - fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) { - for action in actions { - match action.as_widget_action().cast::() { - ModalAction::ShowModalView(modal_view_id) => { - if let Err(err) = self.show_modal_view_by_id(cx, modal_view_id) { - error!("{err}") - } - } - ModalAction::CloseModal => { - self.close(cx); - } - ModalAction::None => {} - } - } - } -} - -impl Modal { - fn get_active_modal_view(&mut self, _cx: &mut Cx) -> Option { - match self.active_modal_view { - ActiveModalView::None => None, - ActiveModalView::Active(modal_view_id) => { - let modal_view_ref = self.modal_view(&[modal_view_id]); - - if modal_view_ref.is_showing() { - Some(modal_view_ref) - } else { - None - } - } - } - } - - pub fn show_modal_view_by_id( - &mut self, - cx: &mut Cx, - modal_view_id: LiveId, - ) -> Result<(), &'static str> { - let mut modal_view_ref = self.modal_view(&[modal_view_id]); - - if modal_view_ref.is_empty() { - return Err("ModalView not found"); - } - - if let Some(mut current_active_modal_view_ref) = self.get_active_modal_view(cx) { - current_active_modal_view_ref.hide(cx); - } - - modal_view_ref.show(cx); - self.active_modal_view = ActiveModalView::Active(modal_view_id); - - self.redraw(cx); - Ok(()) - } - - pub fn close(&mut self, cx: &mut Cx) { - if let Some(mut current_active_modal_view_ref) = self.get_active_modal_view(cx) { - current_active_modal_view_ref.hide(cx); - } - - self.apply_over(cx, live! {visible: false}); - } -} - -#[allow(dead_code)] -impl ModalRef { - pub fn show_modal_view_by_id( - &mut self, - cx: &mut Cx, - stack_view_id: LiveId, - ) -> Result<(), &'static str> { - if let Some(mut inner) = self.borrow_mut() { - inner.show_modal_view_by_id(cx, stack_view_id) - } else { - Err("Widget not found in the document") - } - } - - pub fn close(&mut self, cx: &mut Cx) -> Result<(), &'static str> { - if let Some(mut inner) = self.borrow_mut() { - inner.close(cx); - Ok(()) - } else { - Err("Widget not found in the document") - } - } -} diff --git a/src/shared/widgets.rs b/src/shared/widgets.rs index 629457be..511198e5 100644 --- a/src/shared/widgets.rs +++ b/src/shared/widgets.rs @@ -28,7 +28,7 @@ live_design! { FadeView = { draw_bg: { instance opacity: 1.0 - + fn pixel(self) -> vec4 { let color = sample2d_rt(self.image, self.pos * self.scale + self.shift) + vec4(self.marked, 0.0, 0.0, 0.0); return Pal::premul(vec4(color.xyz, color.w * self.opacity)) From 3b484d1f89964315fb82565abd01149efbc23d8e Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Tue, 25 Jun 2024 10:12:12 -0300 Subject: [PATCH 2/3] add portal.rs file --- src/shared/portal.rs | 305 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src/shared/portal.rs diff --git a/src/shared/portal.rs b/src/shared/portal.rs new file mode 100644 index 00000000..41d4df03 --- /dev/null +++ b/src/shared/portal.rs @@ -0,0 +1,305 @@ +use std::any::Any; +use std::fmt::Debug; + +use makepad_widgets::*; + +live_design! { + import makepad_widgets::base::*; + import makepad_widgets::theme_desktop_dark::*; + + import crate::shared::styles::*; + + PortalView = {{PortalView}} { + width: Fill + height: Fill + flow: Overlay + } + + Portal = {{Portal}} { + width: Fill + height: Fill + + flow: Right + } +} + +#[derive(Live, LiveHook, LiveRegisterWidget, WidgetRef)] +pub struct PortalView { + #[deref] + view: View, +} + +impl Widget for PortalView { + fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { + self.view.handle_event(cx, event, scope); + } + + fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { + self.view + .draw_walk(cx, scope, walk.with_abs_pos(DVec2 { x: 0., y: 0. })) + } +} + +impl WidgetNode for PortalView { + fn walk(&mut self, cx: &mut Cx) -> Walk { + self.view.walk(cx) + } + + fn redraw(&mut self, cx: &mut Cx) { + self.view.redraw(cx); + } + + fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) { + self.view.find_widgets(path, cached, results); + } +} + +impl PortalView { + pub fn show(&mut self, cx: &mut Cx) { + self.apply_over(cx, live! {visible: true}); + self.redraw(cx); + } + + pub fn hide(&mut self, cx: &mut Cx) { + self.apply_over(cx, live! {visible: false}); + self.redraw(cx); + } + + pub fn is_showing(&self) -> bool { + self.view.is_visible() + } +} + +impl PortalViewRef { + pub fn show(&mut self, cx: &mut Cx) { + if let Some(mut inner) = self.borrow_mut() { + inner.show(cx); + } + } + + pub fn hide(&mut self, cx: &mut Cx) { + if let Some(mut inner) = self.borrow_mut() { + inner.hide(cx) + } + } + + pub fn is_showing(&self) -> bool { + if let Some(inner) = self.borrow() { + inner.is_showing() + } else { + false + } + } +} + +#[derive(Clone, DefaultNone, Eq, PartialEq, Debug)] +pub enum PortalAction { + None, + ShowPortalView(LiveId), + // ShowPortalViewWithProps(Box), + Close, +} + +// #[derive(Debug)] +// pub struct PortalActionWithProps { +// id: LiveId, +// data: Box, +// } +// +// impl PortalActionWithProps { +// pub fn new(id: LiveId, data: T) -> Self { +// Self { +// id, +// data: Box::new(data), +// } +// } +// +// pub fn get_data(&self) -> Option<&T> { +// self.data.downcast_ref::() +// } +// } +// +// impl PortalAction { +// pub fn new_show_portal_view_with_props(id: LiveId, data: T) -> Self { +// PortalAction::ShowPortalViewWithProps(Box::new(PortalActionWithProps::new(id, data))) +// } +// } +// +// impl Clone for PortalActionWithProps { +// fn clone(&self) -> Self { +// Self { +// id: self.id.clone(), +// data: self.data.clone(), +// } +// } +// } +// +// impl PartialEq for PortalActionWithProps { +// fn eq(&self, other: &Self) -> bool { +// self.id == other.id && self.data.type_id() == other.data.type_id() +// } +// } +// +// impl Eq for PortalActionWithProps {} +// +// trait CloneAny { +// fn clone_any(&self) -> Box; +// } +// +// impl CloneAny for T { +// fn clone_any(&self) -> Box { +// Box::new(self.clone()) +// } +// } + +#[derive(Default)] +enum ActivePortalView { + #[default] + None, + Active(LiveId), +} + +#[derive(Live, LiveRegisterWidget, WidgetRef)] +pub struct Portal { + #[deref] + view: View, + + #[rust] + active_portal_view: ActivePortalView, +} + +impl Widget for Portal { + fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { + if let Some(widget_ref) = self.get_active_portal_view(cx) { + widget_ref.handle_event(cx, event, scope); + } + + self.widget_match_event(cx, event, scope); + } + + fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { + if let Some(widget_ref) = self.get_active_portal_view(cx) { + widget_ref.draw_walk(cx, scope, walk)?; + } + + DrawStep::done() + } +} + +impl LiveHook for Portal { + fn after_new_from_doc(&mut self, _cx: &mut Cx) {} +} + +impl WidgetNode for Portal { + fn walk(&mut self, cx: &mut Cx) -> Walk { + self.view.walk(cx) + } + + fn redraw(&mut self, cx: &mut Cx) { + if let Some(widget_ref) = self.get_active_portal_view(cx) { + widget_ref.redraw(cx); + } + } + + fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) { + self.view.find_widgets(path, cached, results); + } +} + +impl WidgetMatchEvent for Portal { + fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) { + for action in actions { + match action.as_widget_action().cast::() { + PortalAction::ShowPortalView(portal_view_id) => { + if let Err(err) = self.show_portal_view_by_id(cx, portal_view_id) { + error!("{err}") + } + } + PortalAction::Close => { + self.close(cx); + } + PortalAction::None => {} + } + } + } +} + +impl Portal { + fn get_active_portal_view(&mut self, _cx: &mut Cx) -> Option { + match self.active_portal_view { + ActivePortalView::None => None, + ActivePortalView::Active(portal_view_id) => { + let portal_view_ref = self.portal_view(&[portal_view_id]); + + if portal_view_ref.is_showing() { + Some(portal_view_ref) + } else { + None + } + } + } + } + + pub fn show_portal_view_by_id( + &mut self, + cx: &mut Cx, + portal_view_id: LiveId, + ) -> Result<(), &'static str> { + let mut portal_view_ref = self.portal_view(&[portal_view_id]); + + if portal_view_ref.is_empty() { + return Err("PortalView not found"); + } + + if let Some(mut current_active_portal_view_ref) = self.get_active_portal_view(cx) { + current_active_portal_view_ref.hide(cx); + } + + portal_view_ref.show(cx); + self.active_portal_view = ActivePortalView::Active(portal_view_id); + + self.redraw(cx); + Ok(()) + } + + // pub fn show_portal_view_by_id_with_props( + // &mut self, + // cx: &mut Cx, + // portal_view_id: LiveId, + // props: T, + // ) -> Result<(), &'static str> { + // self.show_portal_view_by_id(cx, portal_view_id) + // } + + pub fn close(&mut self, cx: &mut Cx) { + if let Some(mut current_active_portal_view_ref) = self.get_active_portal_view(cx) { + current_active_portal_view_ref.hide(cx); + } + + self.apply_over(cx, live! {visible: false}); + } +} + +#[allow(dead_code)] +impl PortalRef { + pub fn show_portal_view_by_id( + &mut self, + cx: &mut Cx, + stack_view_id: LiveId, + ) -> Result<(), &'static str> { + if let Some(mut inner) = self.borrow_mut() { + inner.show_portal_view_by_id(cx, stack_view_id) + } else { + Err("Widget not found in the document") + } + } + + pub fn close(&mut self, cx: &mut Cx) -> Result<(), &'static str> { + if let Some(mut inner) = self.borrow_mut() { + inner.close(cx); + Ok(()) + } else { + Err("Widget not found in the document") + } + } +} From fada09f1f411d9c60561181ea453d66113d2c8ce Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Wed, 26 Jun 2024 14:19:20 -0300 Subject: [PATCH 3/3] Remove unused code --- src/shared/portal.rs | 62 -------------------------------------------- 1 file changed, 62 deletions(-) diff --git a/src/shared/portal.rs b/src/shared/portal.rs index 41d4df03..a983bb56 100644 --- a/src/shared/portal.rs +++ b/src/shared/portal.rs @@ -96,62 +96,9 @@ impl PortalViewRef { pub enum PortalAction { None, ShowPortalView(LiveId), - // ShowPortalViewWithProps(Box), Close, } -// #[derive(Debug)] -// pub struct PortalActionWithProps { -// id: LiveId, -// data: Box, -// } -// -// impl PortalActionWithProps { -// pub fn new(id: LiveId, data: T) -> Self { -// Self { -// id, -// data: Box::new(data), -// } -// } -// -// pub fn get_data(&self) -> Option<&T> { -// self.data.downcast_ref::() -// } -// } -// -// impl PortalAction { -// pub fn new_show_portal_view_with_props(id: LiveId, data: T) -> Self { -// PortalAction::ShowPortalViewWithProps(Box::new(PortalActionWithProps::new(id, data))) -// } -// } -// -// impl Clone for PortalActionWithProps { -// fn clone(&self) -> Self { -// Self { -// id: self.id.clone(), -// data: self.data.clone(), -// } -// } -// } -// -// impl PartialEq for PortalActionWithProps { -// fn eq(&self, other: &Self) -> bool { -// self.id == other.id && self.data.type_id() == other.data.type_id() -// } -// } -// -// impl Eq for PortalActionWithProps {} -// -// trait CloneAny { -// fn clone_any(&self) -> Box; -// } -// -// impl CloneAny for T { -// fn clone_any(&self) -> Box { -// Box::new(self.clone()) -// } -// } - #[derive(Default)] enum ActivePortalView { #[default] @@ -262,15 +209,6 @@ impl Portal { Ok(()) } - // pub fn show_portal_view_by_id_with_props( - // &mut self, - // cx: &mut Cx, - // portal_view_id: LiveId, - // props: T, - // ) -> Result<(), &'static str> { - // self.show_portal_view_by_id(cx, portal_view_id) - // } - pub fn close(&mut self, cx: &mut Cx) { if let Some(mut current_active_portal_view_ref) = self.get_active_portal_view(cx) { current_active_portal_view_ref.hide(cx);