chore(text_input): add winit example and do some cleanup
This commit is contained in:
parent
878c2dcd5d
commit
cc74c63d9b
6 changed files with 56 additions and 32 deletions
|
|
@ -124,5 +124,3 @@ exclude = [
|
||||||
|
|
||||||
[patch."https://github.com/pop-os/libcosmic"]
|
[patch."https://github.com/pop-os/libcosmic"]
|
||||||
libcosmic = { path = "./", features = ["wayland", "tokio", "a11y"]}
|
libcosmic = { path = "./", features = ["wayland", "tokio", "a11y"]}
|
||||||
[patch."https://github.com/pop-os/cosmic-time"]
|
|
||||||
cosmic-time = { path = "../cosmic-time"}
|
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,10 @@ impl State {
|
||||||
.size(20)
|
.size(20)
|
||||||
.id(INPUT_ID.clone())
|
.id(INPUT_ID.clone())
|
||||||
.into(),
|
.into(),
|
||||||
|
cosmic::widget::text_input("test", &self.entry_value)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.on_input(Message::InputChanged)
|
||||||
|
.into(),
|
||||||
])
|
])
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,9 @@ pub use warning::*;
|
||||||
|
|
||||||
pub mod cosmic_container;
|
pub mod cosmic_container;
|
||||||
pub use cosmic_container::*;
|
pub use cosmic_container::*;
|
||||||
#[cfg(feature = "wayland")]
|
// #[cfg(feature = "wayland")]
|
||||||
pub mod text_input;
|
pub mod text_input;
|
||||||
#[cfg(feature = "wayland")]
|
// #[cfg(feature = "wayland")]
|
||||||
pub use text_input::*;
|
pub use text_input::*;
|
||||||
|
|
||||||
/// An element to distinguish a boundary between two elements.
|
/// An element to distinguish a boundary between two elements.
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,10 @@ impl<'a> Editor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backspace(&mut self) {
|
pub fn backspace(&mut self) {
|
||||||
match self.cursor.selection(self.value) {
|
if let Some((start, end)) = self.cursor.selection(self.value) {
|
||||||
Some((start, end)) => {
|
|
||||||
self.cursor.move_left(self.value);
|
self.cursor.move_left(self.value);
|
||||||
self.value.remove_many(start, end);
|
self.value.remove_many(start, end);
|
||||||
}
|
} else {
|
||||||
None => {
|
|
||||||
let start = self.cursor.start(self.value);
|
let start = self.cursor.start(self.value);
|
||||||
|
|
||||||
if start > 0 {
|
if start > 0 {
|
||||||
|
|
@ -52,14 +50,11 @@ impl<'a> Editor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(&mut self) {
|
pub fn delete(&mut self) {
|
||||||
match self.cursor.selection(self.value) {
|
if self.cursor.selection(self.value).is_some() {
|
||||||
Some(_) => {
|
|
||||||
self.backspace();
|
self.backspace();
|
||||||
}
|
} else {
|
||||||
None => {
|
|
||||||
let end = self.cursor.end(self.value);
|
let end = self.cursor.end(self.value);
|
||||||
|
|
||||||
if end < self.value.len() {
|
if end < self.value.len() {
|
||||||
|
|
@ -67,5 +62,4 @@ impl<'a> Editor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
//! Display fields that can be filled with text.
|
//! Display fields that can be filled with text.
|
||||||
//!
|
//!
|
||||||
//! A [`TextInput`] has some local [`State`].
|
//! A [`TextInput`] has some local [`State`].
|
||||||
use crate::app;
|
|
||||||
use crate::theme::THEME;
|
use crate::theme::THEME;
|
||||||
|
|
||||||
use super::cursor;
|
use super::cursor;
|
||||||
|
|
@ -28,12 +27,16 @@ use iced_core::{
|
||||||
Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size,
|
Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size,
|
||||||
Vector, Widget,
|
Vector, Widget,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
use iced_renderer::core::event::{wayland, PlatformSpecific};
|
use iced_renderer::core::event::{wayland, PlatformSpecific};
|
||||||
use iced_renderer::core::widget::OperationOutputWrapper;
|
use iced_renderer::core::widget::OperationOutputWrapper;
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
|
use iced_runtime::command::platform_specific;
|
||||||
use iced_runtime::Command;
|
use iced_runtime::Command;
|
||||||
|
|
||||||
use iced_runtime::command::platform_specific;
|
#[cfg(feature = "wayland")]
|
||||||
use iced_runtime::command::platform_specific::wayland::data_device::{DataFromMimeType, DndIcon};
|
use iced_runtime::command::platform_specific::wayland::data_device::{DataFromMimeType, DndIcon};
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
use sctk::reexports::client::protocol::wl_data_device_manager::DndAction;
|
use sctk::reexports::client::protocol::wl_data_device_manager::DndAction;
|
||||||
|
|
||||||
/// Creates a new [`TextInput`].
|
/// Creates a new [`TextInput`].
|
||||||
|
|
@ -140,6 +143,7 @@ where
|
||||||
.padding([spacing, spacing, spacing, spacing])
|
.padding([spacing, spacing, spacing, spacing])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
const SUPPORTED_MIME_TYPES: &[&str; 6] = &[
|
const SUPPORTED_MIME_TYPES: &[&str; 6] = &[
|
||||||
"text/plain;charset=utf-8",
|
"text/plain;charset=utf-8",
|
||||||
"text/plain;charset=UTF-8",
|
"text/plain;charset=UTF-8",
|
||||||
|
|
@ -148,8 +152,11 @@ const SUPPORTED_MIME_TYPES: &[&str; 6] = &[
|
||||||
"text/plain",
|
"text/plain",
|
||||||
"TEXT",
|
"TEXT",
|
||||||
];
|
];
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
pub type DnDCommand =
|
pub type DnDCommand =
|
||||||
Box<dyn Send + Sync + Fn() -> platform_specific::wayland::data_device::ActionInner>;
|
Box<dyn Send + Sync + Fn() -> platform_specific::wayland::data_device::ActionInner>;
|
||||||
|
#[cfg(not(feature = "wayland"))]
|
||||||
|
pub type DnDCommand = ();
|
||||||
|
|
||||||
/// A field that can be filled with text.
|
/// A field that can be filled with text.
|
||||||
///
|
///
|
||||||
|
|
@ -356,6 +363,7 @@ where
|
||||||
/// [`Value`] if provided.
|
/// [`Value`] if provided.
|
||||||
///
|
///
|
||||||
/// [`Renderer`]: text::Renderer
|
/// [`Renderer`]: text::Renderer
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&self,
|
&self,
|
||||||
tree: &Tree,
|
tree: &Tree,
|
||||||
|
|
@ -394,6 +402,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the start dnd handler of the [`TextInput`].
|
/// 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 {
|
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.on_create_dnd_source = Some(Box::new(on_start_dnd));
|
||||||
self
|
self
|
||||||
|
|
@ -401,6 +410,7 @@ where
|
||||||
|
|
||||||
/// Sets the dnd command produced handler of the [`TextInput`].
|
/// Sets the dnd command produced handler of the [`TextInput`].
|
||||||
/// Commands should be returned in the update function of the application.
|
/// Commands should be returned in the update function of the application.
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
pub fn on_dnd_command_produced(
|
pub fn on_dnd_command_produced(
|
||||||
mut self,
|
mut self,
|
||||||
on_dnd_command_produced: impl Fn(
|
on_dnd_command_produced: impl Fn(
|
||||||
|
|
@ -958,6 +968,7 @@ where
|
||||||
click.kind(),
|
click.kind(),
|
||||||
state.cursor().state(value),
|
state.cursor().state(value),
|
||||||
) {
|
) {
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
(None, click::Kind::Single, cursor::State::Selection { start, end }) => {
|
(None, click::Kind::Single, cursor::State::Selection { start, end }) => {
|
||||||
// if something is already selected, we can start a drag and drop for a
|
// if something is already selected, we can start a drag and drop for a
|
||||||
// single click that is on top of the selected text
|
// single click that is on top of the selected text
|
||||||
|
|
@ -965,6 +976,7 @@ where
|
||||||
if is_secure {
|
if is_secure {
|
||||||
return event::Status::Ignored;
|
return event::Status::Ignored;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
Some(on_start_dnd),
|
Some(on_start_dnd),
|
||||||
Some(on_dnd_command_produced),
|
Some(on_dnd_command_produced),
|
||||||
|
|
@ -1384,6 +1396,7 @@ where
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
||||||
wayland::DataSourceEvent::DndFinished | wayland::DataSourceEvent::Cancelled,
|
wayland::DataSourceEvent::DndFinished | wayland::DataSourceEvent::Cancelled,
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1393,6 +1406,7 @@ where
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
||||||
wayland::DataSourceEvent::Cancelled
|
wayland::DataSourceEvent::Cancelled
|
||||||
| wayland::DataSourceEvent::DndFinished
|
| wayland::DataSourceEvent::DndFinished
|
||||||
|
|
@ -1404,6 +1418,7 @@ where
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DataSource(
|
||||||
wayland::DataSourceEvent::DndActionAccepted(action),
|
wayland::DataSourceEvent::DndActionAccepted(action),
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1413,7 +1428,7 @@ where
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: handle dnd offer events
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::Enter { x, y, mime_types },
|
wayland::DndOfferEvent::Enter { x, y, mime_types },
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1480,6 +1495,7 @@ where
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::Motion { x, y },
|
wayland::DndOfferEvent::Motion { x, y },
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1558,6 +1574,7 @@ where
|
||||||
state.cursor.move_to(position.unwrap_or(0));
|
state.cursor.move_to(position.unwrap_or(0));
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::DropPerformed,
|
wayland::DndOfferEvent::DropPerformed,
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1586,6 +1603,7 @@ where
|
||||||
}
|
}
|
||||||
return event::Status::Ignored;
|
return event::Status::Ignored;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::Leave,
|
wayland::DndOfferEvent::Leave,
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1600,6 +1618,7 @@ where
|
||||||
};
|
};
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::DndData { mime_type, data },
|
wayland::DndOfferEvent::DndData { mime_type, data },
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -1636,6 +1655,7 @@ where
|
||||||
}
|
}
|
||||||
return event::Status::Ignored;
|
return event::Status::Ignored;
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::DndOffer(
|
||||||
wayland::DndOfferEvent::SourceActions(actions),
|
wayland::DndOfferEvent::SourceActions(actions),
|
||||||
))) => {
|
))) => {
|
||||||
|
|
@ -2016,6 +2036,7 @@ pub fn mouse_interaction(
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TextInputString(String);
|
pub struct TextInputString(String);
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
impl DataFromMimeType for TextInputString {
|
impl DataFromMimeType for TextInputString {
|
||||||
fn from_mime_type(&self, mime_type: &str) -> Option<Vec<u8>> {
|
fn from_mime_type(&self, mime_type: &str) -> Option<Vec<u8>> {
|
||||||
if SUPPORTED_MIME_TYPES.contains(&mime_type) {
|
if SUPPORTED_MIME_TYPES.contains(&mime_type) {
|
||||||
|
|
@ -2029,9 +2050,11 @@ impl DataFromMimeType for TextInputString {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub(crate) enum DraggingState {
|
pub(crate) enum DraggingState {
|
||||||
Selection,
|
Selection,
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
Dnd(DndAction, String),
|
Dnd(DndAction, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub(crate) enum DndOfferState {
|
pub(crate) enum DndOfferState {
|
||||||
#[default]
|
#[default]
|
||||||
|
|
@ -2040,6 +2063,9 @@ pub(crate) enum DndOfferState {
|
||||||
HandlingOffer(Vec<String>, DndAction),
|
HandlingOffer(Vec<String>, DndAction),
|
||||||
Dropped,
|
Dropped,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
#[cfg(not(feature = "wayland"))]
|
||||||
|
pub(crate) struct DndOfferState;
|
||||||
|
|
||||||
/// The state of a [`TextInput`].
|
/// The state of a [`TextInput`].
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
|
@ -2081,6 +2107,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
/// Returns the current value of the dragged text in the [`TextInput`].
|
/// Returns the current value of the dragged text in the [`TextInput`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn dragged_text(&self) -> Option<String> {
|
pub fn dragged_text(&self) -> Option<String> {
|
||||||
|
|
@ -2095,7 +2122,7 @@ impl State {
|
||||||
Self {
|
Self {
|
||||||
is_focused: None,
|
is_focused: None,
|
||||||
dragging_state: None,
|
dragging_state: None,
|
||||||
dnd_offer: DndOfferState::None,
|
dnd_offer: DndOfferState::default(),
|
||||||
is_pasting: None,
|
is_pasting: None,
|
||||||
last_click: None,
|
last_click: None,
|
||||||
cursor: Cursor::default(),
|
cursor: Cursor::default(),
|
||||||
|
|
@ -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 cursor;
|
||||||
pub mod editor;
|
pub mod editor;
|
||||||
pub mod style;
|
mod input;
|
||||||
mod text_input;
|
mod style;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
pub use text_input::*;
|
pub use input::*;
|
||||||
|
pub use style::{Appearance as TextInputAppearance, StyleSheet as TextInputStyleSheet};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue