From 8afbb0386501ca5fd252ee4cbf1c6839d3b79f9a Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Mon, 21 Aug 2023 18:53:33 -0400 Subject: [PATCH] chore(text_input): add winit example and do some cleanup --- examples/cosmic/src/window/demo.rs | 4 +++ src/widget/mod.rs | 4 +-- src/widget/text_input/editor.rs | 34 ++++++++---------- .../text_input/{text_input.rs => input.rs} | 35 ++++++++++++++++--- src/widget/text_input/mod.rs | 9 ++--- 5 files changed, 56 insertions(+), 30 deletions(-) rename src/widget/text_input/{text_input.rs => input.rs} (98%) diff --git a/examples/cosmic/src/window/demo.rs b/examples/cosmic/src/window/demo.rs index c1856eb89d3..375b7044931 100644 --- a/examples/cosmic/src/window/demo.rs +++ b/examples/cosmic/src/window/demo.rs @@ -504,6 +504,10 @@ impl State { .size(20) .id(INPUT_ID.clone()) .into(), + cosmic::widget::text_input("test", &self.entry_value) + .width(Length::Fill) + .on_input(Message::InputChanged) + .into(), ]) .into() } diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 708808d4287..272824b8c61 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -70,9 +70,9 @@ pub use warning::*; pub mod cosmic_container; pub use cosmic_container::*; -#[cfg(feature = "wayland")] +// #[cfg(feature = "wayland")] pub mod text_input; -#[cfg(feature = "wayland")] +// #[cfg(feature = "wayland")] pub use text_input::*; /// An element to distinguish a boundary between two elements. diff --git a/src/widget/text_input/editor.rs b/src/widget/text_input/editor.rs index 3eec052a32b..07648b71c6b 100644 --- a/src/widget/text_input/editor.rs +++ b/src/widget/text_input/editor.rs @@ -38,33 +38,27 @@ impl<'a> Editor<'a> { } pub fn backspace(&mut self) { - match self.cursor.selection(self.value) { - Some((start, end)) => { - self.cursor.move_left(self.value); - self.value.remove_many(start, end); - } - None => { - let start = self.cursor.start(self.value); + if let Some((start, end)) = self.cursor.selection(self.value) { + self.cursor.move_left(self.value); + self.value.remove_many(start, end); + } else { + let start = self.cursor.start(self.value); - if start > 0 { - self.cursor.move_left(self.value); - self.value.remove(start - 1); - } + if start > 0 { + self.cursor.move_left(self.value); + self.value.remove(start - 1); } } } pub fn delete(&mut self) { - match self.cursor.selection(self.value) { - Some(_) => { - self.backspace(); - } - None => { - let end = self.cursor.end(self.value); + if self.cursor.selection(self.value).is_some() { + self.backspace(); + } else { + let end = self.cursor.end(self.value); - if end < self.value.len() { - self.value.remove(end); - } + if end < self.value.len() { + self.value.remove(end); } } } diff --git a/src/widget/text_input/text_input.rs b/src/widget/text_input/input.rs similarity index 98% rename from src/widget/text_input/text_input.rs rename to src/widget/text_input/input.rs index 79e5fb3a3c9..abb4290d412 100644 --- a/src/widget/text_input/text_input.rs +++ b/src/widget/text_input/input.rs @@ -1,7 +1,6 @@ //! Display fields that can be filled with text. //! //! A [`TextInput`] has some local [`State`]. -use crate::app; use crate::theme::THEME; use super::cursor; @@ -28,12 +27,16 @@ use iced_core::{ Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size, Vector, Widget, }; +#[cfg(feature = "wayland")] use iced_renderer::core::event::{wayland, PlatformSpecific}; use iced_renderer::core::widget::OperationOutputWrapper; +#[cfg(feature = "wayland")] +use iced_runtime::command::platform_specific; use iced_runtime::Command; -use iced_runtime::command::platform_specific; +#[cfg(feature = "wayland")] use iced_runtime::command::platform_specific::wayland::data_device::{DataFromMimeType, DndIcon}; +#[cfg(feature = "wayland")] use sctk::reexports::client::protocol::wl_data_device_manager::DndAction; /// Creates a new [`TextInput`]. @@ -140,6 +143,7 @@ where .padding([spacing, spacing, spacing, spacing]) } +#[cfg(feature = "wayland")] const SUPPORTED_MIME_TYPES: &[&str; 6] = &[ "text/plain;charset=utf-8", "text/plain;charset=UTF-8", @@ -148,8 +152,11 @@ const SUPPORTED_MIME_TYPES: &[&str; 6] = &[ "text/plain", "TEXT", ]; +#[cfg(feature = "wayland")] pub type DnDCommand = Box platform_specific::wayland::data_device::ActionInner>; +#[cfg(not(feature = "wayland"))] +pub type DnDCommand = (); /// A field that can be filled with text. /// @@ -356,6 +363,7 @@ where /// [`Value`] if provided. /// /// [`Renderer`]: text::Renderer + #[allow(clippy::too_many_arguments)] pub fn draw( &self, tree: &Tree, @@ -394,6 +402,7 @@ where } /// Sets the start dnd handler of the [`TextInput`]. + #[cfg(feature = "wayland")] pub fn on_start_dnd(mut self, on_start_dnd: impl Fn(State) -> Message + 'a) -> Self { self.on_create_dnd_source = Some(Box::new(on_start_dnd)); self @@ -401,6 +410,7 @@ where /// Sets the dnd command produced handler of the [`TextInput`]. /// Commands should be returned in the update function of the application. + #[cfg(feature = "wayland")] pub fn on_dnd_command_produced( mut self, on_dnd_command_produced: impl Fn( @@ -958,6 +968,7 @@ where click.kind(), state.cursor().state(value), ) { + #[cfg(feature = "wayland")] (None, click::Kind::Single, cursor::State::Selection { start, end }) => { // if something is already selected, we can start a drag and drop for a // single click that is on top of the selected text @@ -965,6 +976,7 @@ where if is_secure { return event::Status::Ignored; } + if let ( Some(on_start_dnd), Some(on_dnd_command_produced), @@ -1384,6 +1396,7 @@ where )); } } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource( wayland::DataSourceEvent::DndFinished | wayland::DataSourceEvent::Cancelled, ))) => { @@ -1393,6 +1406,7 @@ where return event::Status::Captured; } } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource( wayland::DataSourceEvent::Cancelled | wayland::DataSourceEvent::DndFinished @@ -1404,6 +1418,7 @@ where return event::Status::Captured; } } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource( wayland::DataSourceEvent::DndActionAccepted(action), ))) => { @@ -1413,7 +1428,7 @@ where return event::Status::Captured; } } - // TODO: handle dnd offer events + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::Enter { x, y, mime_types }, ))) => { @@ -1480,6 +1495,7 @@ where return event::Status::Captured; } } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::Motion { x, y }, ))) => { @@ -1558,6 +1574,7 @@ where state.cursor.move_to(position.unwrap_or(0)); return event::Status::Captured; } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::DropPerformed, ))) => { @@ -1586,6 +1603,7 @@ where } return event::Status::Ignored; } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::Leave, ))) => { @@ -1600,6 +1618,7 @@ where }; return event::Status::Captured; } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::DndData { mime_type, data }, ))) => { @@ -1636,6 +1655,7 @@ where } return event::Status::Ignored; } + #[cfg(feature = "wayland")] Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer( wayland::DndOfferEvent::SourceActions(actions), ))) => { @@ -2016,6 +2036,7 @@ pub fn mouse_interaction( #[derive(Debug, Clone)] pub struct TextInputString(String); +#[cfg(feature = "wayland")] impl DataFromMimeType for TextInputString { fn from_mime_type(&self, mime_type: &str) -> Option> { if SUPPORTED_MIME_TYPES.contains(&mime_type) { @@ -2029,9 +2050,11 @@ impl DataFromMimeType for TextInputString { #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum DraggingState { Selection, + #[cfg(feature = "wayland")] Dnd(DndAction, String), } +#[cfg(feature = "wayland")] #[derive(Debug, Default, Clone)] pub(crate) enum DndOfferState { #[default] @@ -2040,6 +2063,9 @@ pub(crate) enum DndOfferState { HandlingOffer(Vec, DndAction), Dropped, } +#[derive(Debug, Default, Clone)] +#[cfg(not(feature = "wayland"))] +pub(crate) struct DndOfferState; /// The state of a [`TextInput`]. #[derive(Debug, Default, Clone)] @@ -2081,6 +2107,7 @@ impl State { } } + #[cfg(feature = "wayland")] /// Returns the current value of the dragged text in the [`TextInput`]. #[must_use] pub fn dragged_text(&self) -> Option { @@ -2095,7 +2122,7 @@ impl State { Self { is_focused: None, dragging_state: None, - dnd_offer: DndOfferState::None, + dnd_offer: DndOfferState::default(), is_pasting: None, last_click: None, cursor: Cursor::default(), diff --git a/src/widget/text_input/mod.rs b/src/widget/text_input/mod.rs index 053560acf66..dac71503afd 100644 --- a/src/widget/text_input/mod.rs +++ b/src/widget/text_input/mod.rs @@ -1,9 +1,10 @@ -//! A text input widget from iced_widgets plus some added details. +//! A text input widget from iced widgets plus some added details. pub mod cursor; pub mod editor; -pub mod style; -mod text_input; +mod input; +mod style; pub mod value; -pub use text_input::*; +pub use input::*; +pub use style::{Appearance as TextInputAppearance, StyleSheet as TextInputStyleSheet};