Merge pull request #132 from hecrj/feature/read-clipboard
Clipboard access
This commit is contained in:
commit
773a23630b
15
.travis.yml
15
.travis.yml
@ -1,15 +0,0 @@
|
|||||||
language: rust
|
|
||||||
rust:
|
|
||||||
- stable
|
|
||||||
- beta
|
|
||||||
- nightly
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- rust: nightly
|
|
||||||
fast_finish: true
|
|
||||||
before_install:
|
|
||||||
- |
|
|
||||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
|
||||||
sudo apt-get -qq update
|
|
||||||
sudo apt-get install -y libasound2-dev libudev-dev
|
|
||||||
fi
|
|
@ -1,5 +1,5 @@
|
|||||||
# Iced
|
# Iced
|
||||||
[](https://travis-ci.org/hecrj/iced)
|
[](https://github.com/hecrj/iced/actions)
|
||||||
[][documentation]
|
[][documentation]
|
||||||
[](https://crates.io/crates/iced)
|
[](https://crates.io/crates/iced)
|
||||||
[](https://github.com/hecrj/iced/blob/master/LICENSE)
|
[](https://github.com/hecrj/iced/blob/master/LICENSE)
|
||||||
|
8
native/src/clipboard.rs
Normal file
8
native/src/clipboard.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// A buffer for short-term storage and transfer within and between
|
||||||
|
/// applications.
|
||||||
|
pub trait Clipboard {
|
||||||
|
/// Returns the current content of the [`Clipboard`] as text.
|
||||||
|
///
|
||||||
|
/// [`Clipboard`]: trait.Clipboard.html
|
||||||
|
fn content(&self) -> Option<String>;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
layout, renderer, Color, Event, Hasher, Layout, Length, Point, Widget,
|
layout, renderer, Clipboard, Color, Event, Hasher, Layout, Length, Point,
|
||||||
|
Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A generic [`Widget`].
|
/// A generic [`Widget`].
|
||||||
@ -293,6 +294,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<B>,
|
messages: &mut Vec<B>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
let mut original_messages = Vec::new();
|
let mut original_messages = Vec::new();
|
||||||
|
|
||||||
@ -302,6 +304,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
&mut original_messages,
|
&mut original_messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
);
|
);
|
||||||
|
|
||||||
original_messages
|
original_messages
|
||||||
@ -366,6 +369,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
self.element.widget.on_event(
|
self.element.widget.on_event(
|
||||||
event,
|
event,
|
||||||
@ -373,6 +377,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
messages,
|
messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ pub mod renderer;
|
|||||||
pub mod subscription;
|
pub mod subscription;
|
||||||
pub mod widget;
|
pub mod widget;
|
||||||
|
|
||||||
|
mod clipboard;
|
||||||
mod element;
|
mod element;
|
||||||
mod event;
|
mod event;
|
||||||
mod hasher;
|
mod hasher;
|
||||||
@ -57,6 +58,7 @@ pub use iced_core::{
|
|||||||
Point, Rectangle, Vector, VerticalAlignment,
|
Point, Rectangle, Vector, VerticalAlignment,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use clipboard::Clipboard;
|
||||||
pub use element::Element;
|
pub use element::Element;
|
||||||
pub use event::Event;
|
pub use event::Event;
|
||||||
pub use hasher::Hasher;
|
pub use hasher::Hasher;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use crate::{input::mouse, layout, Element, Event, Layout, Point, Size};
|
use crate::{
|
||||||
|
input::mouse, layout, Clipboard, Element, Event, Layout, Point, Size,
|
||||||
|
};
|
||||||
|
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
||||||
@ -185,7 +187,7 @@ where
|
|||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// // Update the user interface
|
/// // Update the user interface
|
||||||
/// let messages = user_interface.update(&renderer, events.drain(..));
|
/// let messages = user_interface.update(&renderer, None, events.drain(..));
|
||||||
///
|
///
|
||||||
/// cache = user_interface.into_cache();
|
/// cache = user_interface.into_cache();
|
||||||
///
|
///
|
||||||
@ -198,6 +200,7 @@ where
|
|||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
events: impl Iterator<Item = Event>,
|
events: impl Iterator<Item = Event>,
|
||||||
) -> Vec<Message> {
|
) -> Vec<Message> {
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
@ -213,6 +216,7 @@ where
|
|||||||
self.cursor_position,
|
self.cursor_position,
|
||||||
&mut messages,
|
&mut messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +286,7 @@ where
|
|||||||
/// &mut renderer,
|
/// &mut renderer,
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// let messages = user_interface.update(&renderer, events.drain(..));
|
/// let messages = user_interface.update(&renderer, None, events.drain(..));
|
||||||
///
|
///
|
||||||
/// // Draw the user interface
|
/// // Draw the user interface
|
||||||
/// let mouse_cursor = user_interface.draw(&mut renderer);
|
/// let mouse_cursor = user_interface.draw(&mut renderer);
|
||||||
|
@ -24,12 +24,12 @@ pub mod button;
|
|||||||
pub mod checkbox;
|
pub mod checkbox;
|
||||||
pub mod column;
|
pub mod column;
|
||||||
pub mod container;
|
pub mod container;
|
||||||
pub mod svg;
|
|
||||||
pub mod image;
|
pub mod image;
|
||||||
pub mod radio;
|
pub mod radio;
|
||||||
pub mod row;
|
pub mod row;
|
||||||
pub mod scrollable;
|
pub mod scrollable;
|
||||||
pub mod slider;
|
pub mod slider;
|
||||||
|
pub mod svg;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod text_input;
|
pub mod text_input;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ pub use text::Text;
|
|||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use text_input::TextInput;
|
pub use text_input::TextInput;
|
||||||
|
|
||||||
use crate::{layout, Event, Hasher, Layout, Length, Point};
|
use crate::{layout, Clipboard, Event, Hasher, Layout, Length, Point};
|
||||||
|
|
||||||
/// A component that displays information and allows interaction.
|
/// A component that displays information and allows interaction.
|
||||||
///
|
///
|
||||||
@ -142,6 +142,7 @@ where
|
|||||||
_cursor_position: Point,
|
_cursor_position: Point,
|
||||||
_messages: &mut Vec<Message>,
|
_messages: &mut Vec<Message>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
|
_clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
//! [`State`]: struct.State.html
|
//! [`State`]: struct.State.html
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{mouse, ButtonState},
|
input::{mouse, ButtonState},
|
||||||
layout, Background, Element, Event, Hasher, Layout, Length, Point,
|
layout, Background, Clipboard, Element, Event, Hasher, Layout, Length,
|
||||||
Rectangle, Widget,
|
Point, Rectangle, Widget,
|
||||||
};
|
};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
@ -192,6 +192,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
|
_clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse::Event::Input {
|
Event::Mouse(mouse::Event::Input {
|
||||||
|
@ -3,7 +3,7 @@ use std::hash::Hash;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{mouse, ButtonState},
|
input::{mouse, ButtonState},
|
||||||
layout, row, text, Align, Color, Element, Event, Font, Hasher,
|
layout, row, text, Align, Clipboard, Color, Element, Event, Font, Hasher,
|
||||||
HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text,
|
HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text,
|
||||||
VerticalAlignment, Widget,
|
VerticalAlignment, Widget,
|
||||||
};
|
};
|
||||||
@ -114,6 +114,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
|
_clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse::Event::Input {
|
Event::Mouse(mouse::Event::Input {
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout, Align, Element, Event, Hasher, Layout, Length, Point, Widget,
|
layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
|
Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::u32;
|
use std::u32;
|
||||||
@ -153,6 +154,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
self.children.iter_mut().zip(layout.children()).for_each(
|
self.children.iter_mut().zip(layout.children()).for_each(
|
||||||
|(child, layout)| {
|
|(child, layout)| {
|
||||||
@ -162,6 +164,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
messages,
|
messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout, Align, Element, Event, Hasher, Layout, Length, Point, Widget,
|
layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
|
Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::u32;
|
use std::u32;
|
||||||
@ -131,6 +132,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
self.content.widget.on_event(
|
self.content.widget.on_event(
|
||||||
event,
|
event,
|
||||||
@ -138,6 +140,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
messages,
|
messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Create choices using radio buttons.
|
//! Create choices using radio buttons.
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{mouse, ButtonState},
|
input::{mouse, ButtonState},
|
||||||
layout, row, text, Align, Color, Element, Event, Font, Hasher,
|
layout, row, text, Align, Clipboard, Color, Element, Event, Font, Hasher,
|
||||||
HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text,
|
HorizontalAlignment, Layout, Length, Point, Rectangle, Row, Text,
|
||||||
VerticalAlignment, Widget,
|
VerticalAlignment, Widget,
|
||||||
};
|
};
|
||||||
@ -113,6 +113,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
|
_clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse::Event::Input {
|
Event::Mouse(mouse::Event::Input {
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
layout, Align, Element, Event, Hasher, Layout, Length, Point, Widget,
|
layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
|
Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::u32;
|
use std::u32;
|
||||||
@ -154,6 +155,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
self.children.iter_mut().zip(layout.children()).for_each(
|
self.children.iter_mut().zip(layout.children()).for_each(
|
||||||
|(child, layout)| {
|
|(child, layout)| {
|
||||||
@ -163,6 +165,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
messages,
|
messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
column,
|
column,
|
||||||
input::{mouse, ButtonState},
|
input::{mouse, ButtonState},
|
||||||
layout, Align, Column, Element, Event, Hasher, Layout, Length, Point,
|
layout, Align, Clipboard, Column, Element, Event, Hasher, Layout, Length,
|
||||||
Rectangle, Size, Widget,
|
Point, Rectangle, Size, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{f32, hash::Hash, u32};
|
use std::{f32, hash::Hash, u32};
|
||||||
@ -143,6 +143,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
let is_mouse_over = bounds.contains(cursor_position);
|
let is_mouse_over = bounds.contains(cursor_position);
|
||||||
@ -247,6 +248,7 @@ where
|
|||||||
cursor_position,
|
cursor_position,
|
||||||
messages,
|
messages,
|
||||||
renderer,
|
renderer,
|
||||||
|
clipboard,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
//! [`State`]: struct.State.html
|
//! [`State`]: struct.State.html
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{mouse, ButtonState},
|
input::{mouse, ButtonState},
|
||||||
layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size,
|
layout, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
Widget,
|
Rectangle, Size, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{hash::Hash, ops::RangeInclusive};
|
use std::{hash::Hash, ops::RangeInclusive};
|
||||||
@ -133,6 +133,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
|
_clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
let mut change = || {
|
let mut change = || {
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
//! [`State`]: struct.State.html
|
//! [`State`]: struct.State.html
|
||||||
use crate::{
|
use crate::{
|
||||||
input::{keyboard, mouse, ButtonState},
|
input::{keyboard, mouse, ButtonState},
|
||||||
layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size,
|
layout, Clipboard, Element, Event, Hasher, Layout, Length, Point,
|
||||||
Widget,
|
Rectangle, Size, Widget,
|
||||||
};
|
};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
@ -172,6 +172,7 @@ where
|
|||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
messages: &mut Vec<Message>,
|
messages: &mut Vec<Message>,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
|
clipboard: Option<&dyn Clipboard>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
Event::Mouse(mouse::Event::Input {
|
Event::Mouse(mouse::Event::Input {
|
||||||
@ -209,7 +210,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Keyboard(keyboard::Event::CharacterReceived(c))
|
Event::Keyboard(keyboard::Event::CharacterReceived(c))
|
||||||
if self.state.is_focused && !c.is_control() =>
|
if self.state.is_focused
|
||||||
|
&& self.state.is_pasting.is_none()
|
||||||
|
&& !c.is_control() =>
|
||||||
{
|
{
|
||||||
let cursor_position = self.state.cursor_position(&self.value);
|
let cursor_position = self.state.cursor_position(&self.value);
|
||||||
|
|
||||||
@ -254,26 +257,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyboard::KeyCode::Left => {
|
keyboard::KeyCode::Left => {
|
||||||
let jump_modifier_pressed = if cfg!(target_os = "macos") {
|
if platform::is_jump_modifier_pressed(modifiers)
|
||||||
modifiers.alt
|
&& !self.is_secure
|
||||||
} else {
|
{
|
||||||
modifiers.control
|
|
||||||
};
|
|
||||||
|
|
||||||
if jump_modifier_pressed && !self.is_secure {
|
|
||||||
self.state.move_cursor_left_by_words(&self.value);
|
self.state.move_cursor_left_by_words(&self.value);
|
||||||
} else {
|
} else {
|
||||||
self.state.move_cursor_left(&self.value);
|
self.state.move_cursor_left(&self.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyboard::KeyCode::Right => {
|
keyboard::KeyCode::Right => {
|
||||||
let jump_modifier_pressed = if cfg!(target_os = "macos") {
|
if platform::is_jump_modifier_pressed(modifiers)
|
||||||
modifiers.alt
|
&& !self.is_secure
|
||||||
} else {
|
{
|
||||||
modifiers.control
|
|
||||||
};
|
|
||||||
|
|
||||||
if jump_modifier_pressed && !self.is_secure {
|
|
||||||
self.state.move_cursor_right_by_words(&self.value);
|
self.state.move_cursor_right_by_words(&self.value);
|
||||||
} else {
|
} else {
|
||||||
self.state.move_cursor_right(&self.value);
|
self.state.move_cursor_right(&self.value);
|
||||||
@ -285,6 +280,50 @@ where
|
|||||||
keyboard::KeyCode::End => {
|
keyboard::KeyCode::End => {
|
||||||
self.state.move_cursor_to_end(&self.value);
|
self.state.move_cursor_to_end(&self.value);
|
||||||
}
|
}
|
||||||
|
keyboard::KeyCode::V => {
|
||||||
|
if platform::is_copy_paste_modifier_pressed(modifiers) {
|
||||||
|
if let Some(clipboard) = clipboard {
|
||||||
|
let content = match self.state.is_pasting.take() {
|
||||||
|
Some(content) => content,
|
||||||
|
None => {
|
||||||
|
let content: String = clipboard
|
||||||
|
.content()
|
||||||
|
.unwrap_or(String::new())
|
||||||
|
.chars()
|
||||||
|
.filter(|c| !c.is_control())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Value::new(&content)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let cursor_position =
|
||||||
|
self.state.cursor_position(&self.value);
|
||||||
|
|
||||||
|
self.value
|
||||||
|
.insert_many(cursor_position, content.clone());
|
||||||
|
|
||||||
|
self.state.cursor_position += content.len();
|
||||||
|
self.state.is_pasting = Some(content);
|
||||||
|
|
||||||
|
let message =
|
||||||
|
(self.on_change)(self.value.to_string());
|
||||||
|
messages.push(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.state.is_pasting = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Event::Keyboard(keyboard::Event::Input {
|
||||||
|
key_code,
|
||||||
|
state: ButtonState::Released,
|
||||||
|
..
|
||||||
|
}) => match key_code {
|
||||||
|
keyboard::KeyCode::V => {
|
||||||
|
self.state.is_pasting = None;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -397,6 +436,7 @@ where
|
|||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
|
is_pasting: Option<Value>,
|
||||||
cursor_position: usize,
|
cursor_position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +456,7 @@ impl State {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
is_focused: true,
|
is_focused: true,
|
||||||
|
is_pasting: None,
|
||||||
cursor_position: usize::MAX,
|
cursor_position: usize::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,7 +527,7 @@ impl State {
|
|||||||
///
|
///
|
||||||
/// [`TextInput`]: struct.TextInput.html
|
/// [`TextInput`]: struct.TextInput.html
|
||||||
// TODO: Reduce allocations, cache results (?)
|
// TODO: Reduce allocations, cache results (?)
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Value {
|
pub struct Value {
|
||||||
graphemes: Vec<String>,
|
graphemes: Vec<String>,
|
||||||
}
|
}
|
||||||
@ -573,8 +614,6 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts a new `char` at the given grapheme `index`.
|
/// Inserts a new `char` at the given grapheme `index`.
|
||||||
///
|
|
||||||
/// [`Value`]: struct.Value.html
|
|
||||||
pub fn insert(&mut self, index: usize, c: char) {
|
pub fn insert(&mut self, index: usize, c: char) {
|
||||||
self.graphemes.insert(index, c.to_string());
|
self.graphemes.insert(index, c.to_string());
|
||||||
|
|
||||||
@ -584,6 +623,13 @@ impl Value {
|
|||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts a bunch of graphemes at the given grapheme `index`.
|
||||||
|
pub fn insert_many(&mut self, index: usize, mut value: Value) {
|
||||||
|
let _ = self
|
||||||
|
.graphemes
|
||||||
|
.splice(index..index, value.graphemes.drain(..));
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes the grapheme at the given `index`.
|
/// Removes the grapheme at the given `index`.
|
||||||
///
|
///
|
||||||
/// [`Value`]: struct.Value.html
|
/// [`Value`]: struct.Value.html
|
||||||
@ -656,3 +702,27 @@ fn find_cursor_position<Renderer: self::Renderer>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod platform {
|
||||||
|
use crate::input::keyboard;
|
||||||
|
|
||||||
|
pub fn is_jump_modifier_pressed(
|
||||||
|
modifiers: keyboard::ModifiersState,
|
||||||
|
) -> bool {
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
modifiers.alt
|
||||||
|
} else {
|
||||||
|
modifiers.control
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_copy_paste_modifier_pressed(
|
||||||
|
modifiers: keyboard::ModifiersState,
|
||||||
|
) -> bool {
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
modifiers.logo
|
||||||
|
} else {
|
||||||
|
modifiers.control
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ debug = []
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
iced_native = { version = "0.1.0-alpha", path = "../native" }
|
iced_native = { version = "0.1.0-alpha", path = "../native" }
|
||||||
winit = { version = "0.20.0-alpha3", git = "https://github.com/rust-windowing/winit", rev = "709808eb4e69044705fcb214bcc30556db761405"}
|
winit = { version = "0.20.0-alpha3", git = "https://github.com/rust-windowing/winit", rev = "709808eb4e69044705fcb214bcc30556db761405"}
|
||||||
|
window_clipboard = { git = "https://github.com/hecrj/window_clipboard", rev = "22c6dd6c04cd05d528029b50a30c56417cd4bebf" }
|
||||||
futures = { version = "0.3", features = ["thread-pool"] }
|
futures = { version = "0.3", features = ["thread-pool"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ use crate::{
|
|||||||
conversion,
|
conversion,
|
||||||
input::{keyboard, mouse},
|
input::{keyboard, mouse},
|
||||||
renderer::{Target, Windowed},
|
renderer::{Target, Windowed},
|
||||||
subscription, Cache, Command, Container, Debug, Element, Event, Length,
|
subscription, Cache, Clipboard, Command, Container, Debug, Element, Event,
|
||||||
MouseCursor, Settings, Subscription, UserInterface,
|
Length, MouseCursor, Settings, Subscription, UserInterface,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An interactive, native cross-platform application.
|
/// An interactive, native cross-platform application.
|
||||||
@ -139,6 +139,7 @@ pub trait Application: Sized {
|
|||||||
let mut size = window.inner_size();
|
let mut size = window.inner_size();
|
||||||
let mut resized = false;
|
let mut resized = false;
|
||||||
|
|
||||||
|
let clipboard = Clipboard::new(&window);
|
||||||
let mut renderer = Self::Renderer::new();
|
let mut renderer = Self::Renderer::new();
|
||||||
|
|
||||||
let mut target = {
|
let mut target = {
|
||||||
@ -193,8 +194,13 @@ pub trait Application: Sized {
|
|||||||
subscription_pool.broadcast_event(*event)
|
subscription_pool.broadcast_event(*event)
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut messages =
|
let mut messages = user_interface.update(
|
||||||
user_interface.update(&renderer, events.drain(..));
|
&renderer,
|
||||||
|
clipboard
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c as &dyn iced_native::Clipboard),
|
||||||
|
events.drain(..),
|
||||||
|
);
|
||||||
messages.extend(external_messages.drain(..));
|
messages.extend(external_messages.drain(..));
|
||||||
debug.event_processing_finished();
|
debug.event_processing_finished();
|
||||||
|
|
||||||
|
13
winit/src/clipboard.rs
Normal file
13
winit/src/clipboard.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pub struct Clipboard(window_clipboard::Clipboard);
|
||||||
|
|
||||||
|
impl Clipboard {
|
||||||
|
pub fn new(window: &winit::window::Window) -> Option<Clipboard> {
|
||||||
|
window_clipboard::Clipboard::new(window).map(Clipboard).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl iced_native::Clipboard for Clipboard {
|
||||||
|
fn content(&self) -> Option<String> {
|
||||||
|
self.0.read().ok()
|
||||||
|
}
|
||||||
|
}
|
@ -29,11 +29,9 @@ pub mod conversion;
|
|||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
mod application;
|
mod application;
|
||||||
|
mod clipboard;
|
||||||
mod subscription;
|
mod subscription;
|
||||||
|
|
||||||
pub use application::Application;
|
|
||||||
pub use settings::Settings;
|
|
||||||
|
|
||||||
// We disable debug capabilities on release builds unless the `debug` feature
|
// We disable debug capabilities on release builds unless the `debug` feature
|
||||||
// is explicitly enabled.
|
// is explicitly enabled.
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
@ -43,4 +41,8 @@ mod debug;
|
|||||||
#[path = "debug/null.rs"]
|
#[path = "debug/null.rs"]
|
||||||
mod debug;
|
mod debug;
|
||||||
|
|
||||||
|
pub use application::Application;
|
||||||
|
pub use settings::Settings;
|
||||||
|
|
||||||
|
use clipboard::Clipboard;
|
||||||
use debug::Debug;
|
use debug::Debug;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user