diff options
| author | alex-ds13 <145657253+alex-ds13@users.noreply.github.com> | 2025-12-04 02:40:12 +0000 |
|---|---|---|
| committer | Polesznyák Márk <contact@pml68.dev> | 2025-12-30 18:13:59 +0100 |
| commit | de65c1dc7285b15c87862198b98b435345715d7d (patch) | |
| tree | b864fda857f039595990405c2143d80ebbe8029a /src/operation.rs | |
| parent | feat: implement selection across bounds with hacky copy solution (diff) | |
| download | iced_selection-de65c1dc7285b15c87862198b98b435345715d7d.tar.gz | |
feat(selectable): draft implementation of selectable widget
Diffstat (limited to '')
| -rw-r--r-- | src/operation.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/operation.rs b/src/operation.rs new file mode 100644 index 0000000..584f61f --- /dev/null +++ b/src/operation.rs @@ -0,0 +1,100 @@ +//! Provides some operations to be used on the [`Text`] or [`Rich`]. +//! +//! [`Text`]: crate::text::Text +//! [`Rich`]: crate::text::Rich + +use crate::core::widget::operation::{self, Operation}; + +/// Some selected text +pub struct Selection(pub String); + +/// Some mutable independent selection field of a [`Text`] or [`Rich`] that can be changed through +/// an operation. +/// +/// [`Text`]: crate::text::Text +/// [`Rich`]: crate::text::Rich +pub struct IndependentSelection<'a>(pub &'a mut bool); + +impl<'a> IndependentSelection<'a> { + /// Creates a new [`IndependentSelection`] with the given mutable reference + pub fn new(isel: &'a mut bool) -> Self { + Self(isel) + } +} + +/// Gets all the currently selected text +pub fn selected() -> impl Operation<String> { + struct CopySelection { + contents: Vec<String>, + } + + impl Operation<String> for CopySelection { + + fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<String>)) { + operate(self); + } + + fn custom( + &mut self, + _id: Option<&iced_widget::Id>, + _bounds: iced_widget::core::Rectangle, + _state: &mut dyn std::any::Any, + ) { + if let Some(selection) = _state.downcast_ref::<Selection>() { + self.contents.push(selection.0.clone()); + } + } + + fn finish(&self) -> operation::Outcome<String> { + 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 + }); + operation::Outcome::Some(clipboard) + } else { + operation::Outcome::None + } + } + } + + CopySelection { + contents: Vec::new(), + } +} + +/// Sets all children instances of [`Text`] or [`Rich`] to be globally selectable instead of +/// independently selectable. +/// +/// [`Text`]: crate::text::Text +/// [`Rich`]: crate::text::Rich +pub fn global_selection() -> impl Operation { + struct SetGlobalSelection; + + impl Operation for SetGlobalSelection { + fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation)) { + operate(self); + } + + fn custom( + &mut self, + _id: Option<&iced_widget::Id>, + _bounds: iced_widget::core::Rectangle, + _state: &mut dyn std::any::Any, + ) { + // if let Some(selection) = _state.downcast_mut::<IndependentSelection<'_>>() { + // *selection.0 = false; + // } + if let Some(selection) = _state.downcast_mut::<bool>() { + *selection = false; + } + } + } + + SetGlobalSelection +} |
