From de65c1dc7285b15c87862198b98b435345715d7d Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Thu, 4 Dec 2025 02:40:12 +0000 Subject: feat(selectable): draft implementation of selectable widget --- src/operation.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/operation.rs (limited to 'src/operation.rs') 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 { + struct CopySelection { + contents: Vec, + } + + impl Operation for CopySelection { + + 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_ref::() { + self.contents.push(selection.0.clone()); + } + } + + 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 + }); + 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::>() { + // *selection.0 = false; + // } + if let Some(selection) = _state.downcast_mut::() { + *selection = false; + } + } + } + + SetGlobalSelection +} -- cgit v1.2.3