From 6c102ad1ede9571a1dcd33b94bd39798423c448e Mon Sep 17 00:00:00 2001 From: JoeZane Date: Sun, 4 May 2025 23:17:50 +0800 Subject: [PATCH] upd: add reset effect node to list/tree view --- examples/input_element/holder.rs | 1 + macros/src/extend_container.rs | 37 ++++++++++++++++++++- macros/src/extend_popup.rs | 31 +++++++++++++++++ macros/src/extend_widget.rs | 31 +++++++++++++++++ tmui/src/input/select/dropdown_list.rs | 7 ++++ tmui/src/input/select/mod.rs | 6 ++++ tmui/src/views/list_view/list_store.rs | 20 ++++++++++- tmui/src/views/list_view/list_view_image.rs | 9 +++++ tmui/src/views/list_view/mod.rs | 5 +++ tmui/src/views/tree_view/mod.rs | 5 +++ tmui/src/views/tree_view/tree_store.rs | 29 ++++++++++++---- tmui/src/views/tree_view/tree_view_image.rs | 5 +++ 12 files changed, 177 insertions(+), 9 deletions(-) diff --git a/examples/input_element/holder.rs b/examples/input_element/holder.rs index 6c943e2..a21aa06 100644 --- a/examples/input_element/holder.rs +++ b/examples/input_element/holder.rs @@ -148,6 +148,7 @@ impl ObjectImpl for Holder { ]; self.select1.set_options(&options); self.select1.set_margin_left(20); + self.select1.set_reset_effect_node_on_hide(true); self.select2.set_options(&options); self.select2.set_margin_left(20); diff --git a/macros/src/extend_container.rs b/macros/src/extend_container.rs index e9f70f3..5ca33ae 100644 --- a/macros/src/extend_container.rs +++ b/macros/src/extend_container.rs @@ -390,7 +390,7 @@ pub(crate) fn expand( let inner_on_property_set_clause = if layout.is(LayoutType::Stack) { generate_stack_inner_on_property_set()? } else { - quote!(false) + generate_container_inner_on_property_set()? }; Ok(quote!( @@ -538,3 +538,38 @@ pub(crate) fn gen_container_trait_impl_clause( } )) } + +pub(crate) fn generate_container_inner_on_property_set() -> syn::Result { + Ok(quote! { + match name { + "visible" => { + let visible = value.get::(); + emit!(self, visibility_changed(visible)); + self.inner_visibility_changed(visible); + self.on_visibility_changed(visible); + + if !self.children().is_empty() { + for child in self.children_mut().iter_mut() { + if visible { + if !child.visibility_check() { + continue; + } + if let Some(iv) = cast!(child as IsolatedVisibility) { + if iv.auto_hide() { + continue; + } + } + + child.set_property("visible", true.to_value()); + child.set_render_styles(true); + } else { + child.set_property("visible", false.to_value()); + } + } + } + true + } + _ => false, + } + }) +} diff --git a/macros/src/extend_popup.rs b/macros/src/extend_popup.rs index b166f96..4c92edf 100644 --- a/macros/src/extend_popup.rs +++ b/macros/src/extend_popup.rs @@ -207,6 +207,37 @@ pub(crate) fn expand( let window = ApplicationWindow::window(); connect!(window, size_changed(), self, on_win_size_change(Size)); } + + #[inline] + fn inner_on_property_set(&mut self, name: &str, value: &Value) -> bool { + match name { + "visible" => { + let visible = value.get::(); + emit!(self, visibility_changed(visible)); + self.inner_visibility_changed(visible); + self.on_visibility_changed(visible); + if let Some(child) = self.get_child_mut() { + if visible { + if !child.visibility_check() { + return true; + } + if let Some(iv) = cast!(child as IsolatedVisibility) { + if iv.auto_hide() { + return true; + } + } + + child.set_property("visible", true.to_value()); + child.set_render_styles(true); + } else { + child.set_property("visible", false.to_value()); + } + } + true + } + _ => false, + } + } } impl #impl_generics PointEffective for #name #ty_generics #where_clause { diff --git a/macros/src/extend_widget.rs b/macros/src/extend_widget.rs index 4ed7a3f..2dbb6f4 100644 --- a/macros/src/extend_widget.rs +++ b/macros/src/extend_widget.rs @@ -225,6 +225,37 @@ pub(crate) fn expand_with_general_attr( fn pretreat_construct(&mut self) { #child_ref_clause } + + #[inline] + fn inner_on_property_set(&mut self, name: &str, value: &Value) -> bool { + match name { + "visible" => { + let visible = value.get::(); + emit!(self, visibility_changed(visible)); + self.inner_visibility_changed(visible); + self.on_visibility_changed(visible); + if let Some(child) = self.get_child_mut() { + if visible { + if !child.visibility_check() { + return true; + } + if let Some(iv) = cast!(child as IsolatedVisibility) { + if iv.auto_hide() { + return true; + } + } + + child.set_property("visible", true.to_value()); + child.set_render_styles(true); + } else { + child.set_property("visible", false.to_value()); + } + } + true + } + _ => false, + } + } } impl #impl_generics PointEffective for #name #ty_generics #where_clause { diff --git a/tmui/src/input/select/dropdown_list.rs b/tmui/src/input/select/dropdown_list.rs index 6eb807c..1e77bdf 100644 --- a/tmui/src/input/select/dropdown_list.rs +++ b/tmui/src/input/select/dropdown_list.rs @@ -169,6 +169,13 @@ impl DropdownList { pub(crate) fn trans_focus_take(&mut self, strat: FocusStrat) { self.list.take_over_focus(strat); } + + #[cfg(not(win_select))] + #[inline] + pub(crate) fn set_reset_effect_node_on_hide(&mut self, reset_effect_node_on_hide: bool) { + self.list + .set_reset_effect_node_on_hide(reset_effect_node_on_hide); + } } #[cfg(win_select)] diff --git a/tmui/src/input/select/mod.rs b/tmui/src/input/select/mod.rs index 6b168b9..6378f61 100644 --- a/tmui/src/input/select/mod.rs +++ b/tmui/src/input/select/mod.rs @@ -247,6 +247,12 @@ impl Select { .unwrap() } + #[inline] + pub fn set_reset_effect_node_on_hide(&mut self, reset_effect_node_on_hide: bool) { + self.dropdown_list_mut() + .set_reset_effect_node_on_hide(reset_effect_node_on_hide); + } + #[cfg(win_select)] #[inline] pub fn dropdown_list(&self) -> &CorrDropdownList { diff --git a/tmui/src/views/list_view/list_store.rs b/tmui/src/views/list_view/list_store.rs index 685e0d0..fc492dc 100644 --- a/tmui/src/views/list_view/list_store.rs +++ b/tmui/src/views/list_view/list_store.rs @@ -6,7 +6,10 @@ use super::{ list_view_object::ListViewObject, WidgetHnd, }; -use crate::{views::list_view::list_item::ListItemCast, widget::WidgetImpl}; +use crate::{ + views::{list_view::list_item::ListItemCast, node::Status}, + widget::WidgetImpl, +}; use nohash_hasher::IntMap; use once_cell::sync::Lazy; use std::{ @@ -331,6 +334,21 @@ impl ListStore { } } + #[inline] + pub(crate) fn remove_effected_node_status(&mut self) { + if self.entered_node.is_some() { + self.entered_node = None; + } + if self.hovered_node.is_some() { + nonnull_mut!(self.hovered_node).remove_status(Status::Hovered); + self.hovered_node = None; + } + if self.selected_node.is_some() { + nonnull_mut!(self.selected_node).remove_status(Status::Selected); + self.selected_node = None; + } + } + #[inline] pub(crate) fn set_view(&mut self, view: WidgetHnd) { self.view = view; diff --git a/tmui/src/views/list_view/list_view_image.rs b/tmui/src/views/list_view/list_view_image.rs index 36d71ba..90602a7 100644 --- a/tmui/src/views/list_view/list_view_image.rs +++ b/tmui/src/views/list_view/list_view_image.rs @@ -35,6 +35,7 @@ pub(crate) struct ListViewImage { pub(crate) line_spacing: i32, #[derivative(Default(value = "MouseEffect::all()"))] pub(crate) mouse_effect: MouseEffect, + pub(crate) reset_effect_node_on_hide: bool, pub(crate) on_node_enter: Option, pub(crate) on_node_leave: Option, @@ -112,6 +113,14 @@ impl WidgetImpl for ListViewImage { fn on_mouse_wheel(&mut self, event: &MouseEvent) { nonnull_mut!(self.scroll_bar).on_mouse_wheel(event) } + + #[inline] + fn on_visibility_changed(&mut self, visible: bool) { + if !visible && self.reset_effect_node_on_hide { + self.store.remove_effected_node_status(); + nonnull_mut!(self.scroll_bar).set_value(0); + } + } } impl ListViewImage { diff --git a/tmui/src/views/list_view/mod.rs b/tmui/src/views/list_view/mod.rs index 15c25b5..cd1da58 100644 --- a/tmui/src/views/list_view/mod.rs +++ b/tmui/src/views/list_view/mod.rs @@ -237,6 +237,11 @@ impl ListView { self.get_image_mut().mouse_effect.insert(mouse_effect) } + #[inline] + pub fn set_reset_effect_node_on_hide(&mut self, reset_effect_node_on_hide: bool) { + self.get_image_mut().reset_effect_node_on_hide = reset_effect_node_on_hide; + } + #[inline] pub fn register_node_enter< F: 'static + Fn(&mut ListNode, &mut ConcurrentStoreMutexGuard, &MouseEvent), diff --git a/tmui/src/views/tree_view/mod.rs b/tmui/src/views/tree_view/mod.rs index c95140a..d3c1dca 100644 --- a/tmui/src/views/tree_view/mod.rs +++ b/tmui/src/views/tree_view/mod.rs @@ -163,6 +163,11 @@ impl TreeView { self.get_store_mut().set_sort_proxy(compare) } + #[inline] + pub fn reset_effect_node(&mut self) { + self.get_image_mut().reset_effect_node(); + } + #[inline] pub fn mouse_effect(&self) -> MouseEffect { self.get_image().mouse_effect() diff --git a/tmui/src/views/tree_view/tree_store.rs b/tmui/src/views/tree_view/tree_store.rs index 37f5b6c..63ab7b3 100644 --- a/tmui/src/views/tree_view/tree_store.rs +++ b/tmui/src/views/tree_view/tree_store.rs @@ -28,7 +28,7 @@ pub struct TreeStore { current_line: i32, y_offset: i32, - enterd_node: Option>, + entered_node: Option>, hovered_node: Option>, selected_node: Option>, @@ -116,6 +116,21 @@ impl TreeStore { } } + #[inline] + pub(crate) fn remove_effected_node_status(&mut self) { + if self.entered_node.is_some() { + self.entered_node = None; + } + if self.hovered_node.is_some() { + nonnull_mut!(self.hovered_node).remove_status(Status::Hovered); + self.hovered_node = None; + } + if self.selected_node.is_some() { + nonnull_mut!(self.selected_node).remove_status(Status::Selected); + self.selected_node = None; + } + } + #[inline] pub fn root(&self) -> &TreeNode { self.root.as_ref() @@ -147,7 +162,7 @@ impl TreeStore { self.nodes_buffer.clear(); self.nodes_cache.clear(); - self.enterd_node = None; + self.entered_node = None; self.hovered_node = None; self.selected_node = None; } @@ -170,7 +185,7 @@ impl TreeStore { window_lines: 0, current_line: 0, y_offset: 0, - enterd_node: None, + entered_node: None, hovered_node: None, selected_node: None, id_increment: IdGenerator::new(1), @@ -211,8 +226,8 @@ impl TreeStore { pub(crate) fn remove_node_cache(&mut self, id: ObjectId) { self.nodes_cache.remove(&id); - if self.enterd_node.is_some() && nonnull_ref!(self.enterd_node).id() == id { - self.enterd_node = None; + if self.entered_node.is_some() && nonnull_ref!(self.entered_node).id() == id { + self.entered_node = None; } if self.selected_node.is_some() && nonnull_ref!(self.selected_node).id() == id { @@ -574,12 +589,12 @@ impl TreeStore { #[inline] pub(crate) fn get_entered_node(&self) -> Option> { - self.enterd_node + self.entered_node } #[inline] pub(crate) fn set_entered_node(&mut self, node: &mut TreeNode) { - self.enterd_node = NonNull::new(node) + self.entered_node = NonNull::new(node) } #[inline] diff --git a/tmui/src/views/tree_view/tree_view_image.rs b/tmui/src/views/tree_view/tree_view_image.rs index dedfceb..cf67a18 100644 --- a/tmui/src/views/tree_view/tree_view_image.rs +++ b/tmui/src/views/tree_view/tree_view_image.rs @@ -339,6 +339,11 @@ impl TreeViewImage { self.update(); } + #[inline] + pub(crate) fn reset_effect_node(&mut self) { + self.store.remove_effected_node_status(); + } + #[inline] pub(crate) fn register_node_pressed( &mut self,