aboutsummaryrefslogtreecommitdiff
path: root/src/operation.rs
diff options
context:
space:
mode:
authoralex-ds13 <145657253+alex-ds13@users.noreply.github.com>2025-12-04 02:40:12 +0000
committerPolesznyák Márk <contact@pml68.dev>2025-12-30 18:13:59 +0100
commitde65c1dc7285b15c87862198b98b435345715d7d (patch)
treeb864fda857f039595990405c2143d80ebbe8029a /src/operation.rs
parentfeat: implement selection across bounds with hacky copy solution (diff)
downloadiced_selection-de65c1dc7285b15c87862198b98b435345715d7d.tar.gz
feat(selectable): draft implementation of selectable widget
Diffstat (limited to 'src/operation.rs')
-rw-r--r--src/operation.rs100
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
+}