From d23ed3bfe439131004cf8c247fb4b4600fa92aff Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Sat, 6 Dec 2025 13:33:32 +0000 Subject: fix(selectable): prevent clash with other's custom operations - Make the `global_selection` operation check for the new `IndependentSelection` when trying to downcast_mut. - `IndependentSelection` uses wraps a `RefCell` so it can change its inner value. Theres some helper methods to create this `IndependentSelection` from an existing value and to then get the changed value once the operation is done. This way the `Text` and `Rich` simply need to pass this `IndependentSelection` to the operation `custom` method which will make sure it wont clash with any other custom operations that could be using `&mut bool` as well. --- src/operation.rs | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'src/operation.rs') diff --git a/src/operation.rs b/src/operation.rs index 584f61f..2bfd6d8 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -13,12 +13,17 @@ pub struct Selection(pub String); /// /// [`Text`]: crate::text::Text /// [`Rich`]: crate::text::Rich -pub struct IndependentSelection<'a>(pub &'a mut bool); +pub struct IndependentSelection(pub std::cell::RefCell); -impl<'a> IndependentSelection<'a> { - /// Creates a new [`IndependentSelection`] with the given mutable reference - pub fn new(isel: &'a mut bool) -> Self { - Self(isel) +impl IndependentSelection { + /// Creates a new [`IndependentSelection`] with the given value. + pub fn new(value: bool) -> Self { + Self(std::cell::RefCell::new(value)) + } + + /// Gets the inner bool value of this [`IndependentSelection`]. + pub fn get(&self) -> bool { + *self.0.borrow() } } @@ -29,8 +34,10 @@ pub fn selected() -> impl Operation { } impl Operation for CopySelection { - - fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation)) { + fn traverse( + &mut self, + operate: &mut dyn FnMut(&mut dyn Operation), + ) { operate(self); } @@ -47,15 +54,16 @@ pub fn selected() -> impl Operation { fn finish(&self) -> operation::Outcome { if !self.contents.is_empty() { - let clipboard = self.contents.iter().fold(String::new(), |mut str, s| { - if str.is_empty() { - str = s.to_owned(); - } else { - str.push('\n'); - str.push_str(s); - } - str - }); + let clipboard = + self.contents.iter().fold(String::new(), |mut str, s| { + if str.is_empty() { + str = s.to_owned(); + } else { + str.push('\n'); + str.push_str(s); + } + str + }); operation::Outcome::Some(clipboard) } else { operation::Outcome::None @@ -87,11 +95,10 @@ pub fn global_selection() -> impl Operation { _bounds: iced_widget::core::Rectangle, _state: &mut dyn std::any::Any, ) { - // if let Some(selection) = _state.downcast_mut::>() { - // *selection.0 = false; - // } - if let Some(selection) = _state.downcast_mut::() { - *selection = false; + if let Some(selection) = + _state.downcast_mut::() + { + let _ = selection.0.replace(false); } } } -- cgit v1.2.3