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/text.rs | 58 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 22 deletions(-) (limited to 'src/text.rs') diff --git a/src/text.rs b/src/text.rs index acc7d2c..76560ce 100644 --- a/src/text.rs +++ b/src/text.rs @@ -70,6 +70,7 @@ pub struct Text< fragment: Fragment<'a>, format: Format, class: Theme::Class<'a>, + independent_selection: bool, } impl<'a, Theme, Renderer> Text<'a, Theme, Renderer> @@ -83,6 +84,7 @@ where fragment: fragment.into_fragment(), format: Format::default(), class: Theme::default(), + independent_selection: true, } } @@ -150,6 +152,15 @@ where self } + /// Makes this [`Text`] selection independent of others. + /// + /// Independent texts handle their own selection copy and don't allow being selected from + /// outside its bounds. + pub fn independent(mut self, independent_selection: bool) -> Self { + self.independent_selection = independent_selection; + self + } + /// Sets the style of the [`Text`]. #[must_use] pub fn style(mut self, style: impl Fn(&Theme) -> Style + 'a) -> Self @@ -178,7 +189,6 @@ pub struct State { dragging: Option, last_click: Option, potential_click: Option, - has_cleared_clipboard: bool, keyboard_modifiers: keyboard::Modifiers, visual_lines_bounds: Vec, } @@ -436,7 +446,9 @@ where shell.capture_event(); } else { - if let Some(position) = cursor.land().position() { + if let Some(position) = cursor.land().position() + && !self.independent_selection + { let potential_click = mouse::Click::new( position, mouse::Button::Left, @@ -537,33 +549,20 @@ where state.last_click = Some(potential_click); state.potential_click = None; - - // Clear the clipboard so that we can append to it if the user presses the copy - // shortcut to be able to include all selected texts. - clipboard.write(clipboard::Kind::Standard, String::new()); - state.has_cleared_clipboard = true; } } Event::Keyboard(keyboard::Event::KeyPressed { key, .. }) => { match key.as_ref() { keyboard::Key::Character("c") if state.keyboard_modifiers.command() + && !shell.is_event_captured() + && self.independent_selection && !state.selection.is_empty() => { - let contents = - if state.has_cleared_clipboard { - state.has_cleared_clipboard = false; - clipboard - .read(clipboard::Kind::Standard) - .map(|c| { - if !c.is_empty() { c + "\n" } else { c } - }) - .unwrap_or_default() - + &state.selection.text(&state.paragraph) - } else { - state.selection.text(&state.paragraph) - }; - clipboard.write(clipboard::Kind::Standard, contents); + clipboard.write( + clipboard::Kind::Standard, + state.selection.text(&state.paragraph), + ); shell.capture_event(); } @@ -734,12 +733,27 @@ where fn operate( &mut self, - _state: &mut Tree, + state: &mut Tree, layout: Layout<'_>, _renderer: &Renderer, operation: &mut dyn Operation, ) { operation.text(None, layout.bounds(), &self.fragment); + + if !self.independent_selection { + let state = state.state.downcast_ref::(); + let selection = state.selection.text(&state.paragraph); + if !selection.is_empty() { + operation.custom( + None, + layout.bounds(), + &mut crate::operation::Selection(selection), + ); + } + } + + // let mut isel = crate::operation::IndependentSelection::new(&mut self.independent_selection); + operation.custom(None, layout.bounds(), &mut self.independent_selection); } fn mouse_interaction( -- cgit v1.2.3