summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-17 07:09:46 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-11-17 07:11:44 +0100
commit02c20e6202f1c8c28753f3233cc635790707937a (patch)
treeb13ec79b938a6000709d1241ac1344724386c77a
parente640b875900a3833fd38efa195e99b40ec3f6820 (diff)
downloadiced-02c20e6202f1c8c28753f3233cc635790707937a.tar.gz
iced-02c20e6202f1c8c28753f3233cc635790707937a.tar.bz2
iced-02c20e6202f1c8c28753f3233cc635790707937a.zip
Support async actions in `iced_winit`
-rw-r--r--examples/scroll.rs14
-rw-r--r--examples/todos.rs14
-rw-r--r--examples/tour.rs36
-rw-r--r--src/lib.rs22
-rw-r--r--src/winit.rs4
-rw-r--r--winit/Cargo.toml1
-rw-r--r--winit/src/application.rs66
7 files changed, 110 insertions, 47 deletions
diff --git a/examples/scroll.rs b/examples/scroll.rs
index 50701879..61ad2a53 100644
--- a/examples/scroll.rs
+++ b/examples/scroll.rs
@@ -1,12 +1,12 @@
use iced::{
- button, scrollable, Align, Application, Button, Container, Element, Image,
- Length, Scrollable, Text,
+ button, scrollable, Align, Application, Button, Command, Container,
+ Element, Image, Length, Scrollable, Text,
};
pub fn main() {
env_logger::init();
- Example::default().run()
+ Example::run()
}
#[derive(Default)]
@@ -25,16 +25,22 @@ pub enum Message {
impl Application for Example {
type Message = Message;
+ fn new() -> (Example, Command<Message>) {
+ (Example::default(), Command::none())
+ }
+
fn title(&self) -> String {
String::from("Scroll - Iced")
}
- fn update(&mut self, message: Message) {
+ fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::AddItem => {
self.item_count += 1;
}
}
+
+ Command::none()
}
fn view(&mut self) -> Element<Message> {
diff --git a/examples/todos.rs b/examples/todos.rs
index f921a666..d97a9e08 100644
--- a/examples/todos.rs
+++ b/examples/todos.rs
@@ -1,11 +1,11 @@
use iced::{
button, scrollable, text::HorizontalAlignment, text_input, Align,
- Application, Background, Button, Checkbox, Color, Column, Container,
- Element, Font, Length, Row, Scrollable, Text, TextInput,
+ Application, Background, Button, Checkbox, Color, Column, Command,
+ Container, Element, Font, Length, Row, Scrollable, Text, TextInput,
};
pub fn main() {
- Todos::default().run()
+ Todos::run()
}
#[derive(Debug, Default)]
@@ -29,11 +29,15 @@ pub enum Message {
impl Application for Todos {
type Message = Message;
+ fn new() -> (Todos, Command<Message>) {
+ (Todos::default(), Command::none())
+ }
+
fn title(&self) -> String {
String::from("Todos - Iced")
}
- fn update(&mut self, message: Message) {
+ fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::InputChanged(value) => {
self.input_value = value;
@@ -58,6 +62,8 @@ impl Application for Todos {
}
dbg!(self);
+
+ Command::none()
}
fn view(&mut self) -> Element<Message> {
diff --git a/examples/tour.rs b/examples/tour.rs
index 34ad0a34..6d7a080f 100644
--- a/examples/tour.rs
+++ b/examples/tour.rs
@@ -1,13 +1,14 @@
use iced::{
button, scrollable, slider, text::HorizontalAlignment, text_input,
- Application, Background, Button, Checkbox, Color, Column, Container,
- Element, Image, Length, Radio, Row, Scrollable, Slider, Text, TextInput,
+ Application, Background, Button, Checkbox, Color, Column, Command,
+ Container, Element, Image, Length, Radio, Row, Scrollable, Slider, Text,
+ TextInput,
};
pub fn main() {
env_logger::init();
- Tour::new().run()
+ Tour::run()
}
pub struct Tour {
@@ -18,26 +19,27 @@ pub struct Tour {
debug: bool,
}
-impl Tour {
- pub fn new() -> Tour {
- Tour {
- steps: Steps::new(),
- scroll: scrollable::State::new(),
- back_button: button::State::new(),
- next_button: button::State::new(),
- debug: true,
- }
- }
-}
-
impl Application for Tour {
type Message = Message;
+ fn new() -> (Tour, Command<Message>) {
+ (
+ Tour {
+ steps: Steps::new(),
+ scroll: scrollable::State::new(),
+ back_button: button::State::new(),
+ next_button: button::State::new(),
+ debug: true,
+ },
+ Command::none(),
+ )
+ }
+
fn title(&self) -> String {
format!("{} - Iced", self.steps.title())
}
- fn update(&mut self, event: Message) {
+ fn update(&mut self, event: Message) -> Command<Message> {
match event {
Message::BackPressed => {
self.steps.go_back();
@@ -49,6 +51,8 @@ impl Application for Tour {
self.steps.update(step_msg, &mut self.debug);
}
}
+
+ Command::none()
}
fn view(&mut self) -> Element<Message> {
diff --git a/src/lib.rs b/src/lib.rs
index 52b0ff8c..945af421 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,21 +4,23 @@ mod platform;
pub use platform::*;
-pub trait Application {
- type Message: std::fmt::Debug;
+pub trait Application: Sized {
+ type Message: std::fmt::Debug + Send;
+
+ fn new() -> (Self, Command<Self::Message>);
fn title(&self) -> String;
- fn update(&mut self, message: Self::Message);
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
fn view(&mut self) -> Element<Self::Message>;
- fn run(self)
+ fn run()
where
Self: 'static + Sized,
{
#[cfg(not(target_arch = "wasm32"))]
- iced_winit::Application::run(Instance(self));
+ <Instance<Self> as iced_winit::Application>::run();
#[cfg(target_arch = "wasm32")]
iced_web::Application::run(Instance(self));
@@ -35,12 +37,18 @@ where
type Renderer = Renderer;
type Message = A::Message;
+ fn new() -> (Self, Command<A::Message>) {
+ let (app, command) = A::new();
+
+ (Instance(app), command)
+ }
+
fn title(&self) -> String {
self.0.title()
}
- fn update(&mut self, message: Self::Message) {
- self.0.update(message);
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
+ self.0.update(message)
}
fn view(&mut self) -> Element<Self::Message> {
diff --git a/src/winit.rs b/src/winit.rs
index d35a339f..c869a269 100644
--- a/src/winit.rs
+++ b/src/winit.rs
@@ -2,8 +2,8 @@ pub use iced_wgpu::{Primitive, Renderer};
pub use iced_winit::{
button, scrollable, slider, text, text_input, winit, Align, Background,
- Checkbox, Color, Font, Image, Length, Radio, Scrollable, Slider, Text,
- TextInput,
+ Checkbox, Color, Command, Font, Image, Length, Radio, Scrollable, Slider,
+ Text, TextInput,
};
pub type Element<'a, Message> = iced_winit::Element<'a, Message, Renderer>;
diff --git a/winit/Cargo.toml b/winit/Cargo.toml
index 2831ba2f..2a33255d 100644
--- a/winit/Cargo.toml
+++ b/winit/Cargo.toml
@@ -13,4 +13,5 @@ debug = []
[dependencies]
iced_native = { version = "0.1.0-alpha", path = "../native" }
winit = { version = "0.20.0-alpha3", git = "https://github.com/rust-windowing/winit", rev = "709808eb4e69044705fcb214bcc30556db761405"}
+futures = { version = "0.3", features = ["thread-pool"] }
log = "0.4"
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 331bafa0..bf41d0c8 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -2,24 +2,26 @@ use crate::{
conversion,
input::{keyboard, mouse},
renderer::{Target, Windowed},
- Cache, Container, Debug, Element, Event, Length, MouseCursor,
+ Cache, Command, Container, Debug, Element, Event, Length, MouseCursor,
UserInterface,
};
-pub trait Application {
+pub trait Application: Sized {
type Renderer: Windowed;
- type Message: std::fmt::Debug;
+ type Message: std::fmt::Debug + Send;
+
+ fn new() -> (Self, Command<Self::Message>);
fn title(&self) -> String;
- fn update(&mut self, message: Self::Message);
+ fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
fn view(&mut self) -> Element<Self::Message, Self::Renderer>;
- fn run(mut self)
+ fn run()
where
- Self: 'static + Sized,
+ Self: 'static,
{
use winit::{
event::{self, WindowEvent},
@@ -28,10 +30,18 @@ pub trait Application {
};
let mut debug = Debug::new();
- let mut title = self.title();
debug.startup_started();
- let event_loop = EventLoop::new();
+ let event_loop = EventLoop::with_user_event();
+ let proxy = event_loop.create_proxy();
+ let mut thread_pool =
+ futures::executor::ThreadPool::new().expect("Create thread pool");
+ let mut external_messages = Vec::new();
+
+ let (mut application, init_command) = Self::new();
+ spawn(init_command, &mut thread_pool, &proxy);
+
+ let mut title = application.title();
// TODO: Ask for window settings and configure this properly
let window = WindowBuilder::new()
@@ -59,7 +69,7 @@ pub trait Application {
debug.layout_started();
let user_interface = UserInterface::build(
- document(&mut self, size, &mut debug),
+ document(&mut application, size, &mut debug),
Cache::default(),
&mut renderer,
);
@@ -85,15 +95,16 @@ pub trait Application {
// handled.
debug.layout_started();
let mut user_interface = UserInterface::build(
- document(&mut self, size, &mut debug),
+ document(&mut application, size, &mut debug),
cache.take().unwrap(),
&mut renderer,
);
debug.layout_finished();
debug.event_processing_started();
- let messages =
+ let mut messages =
user_interface.update(&renderer, events.drain(..));
+ messages.extend(external_messages.drain(..));
debug.event_processing_finished();
if messages.is_empty() {
@@ -113,12 +124,14 @@ pub trait Application {
debug.log_message(&message);
debug.update_started();
- self.update(message);
+ let command = application.update(message);
+
+ spawn(command, &mut thread_pool, &proxy);
debug.update_finished();
}
// Update window title
- let new_title = self.title();
+ let new_title = application.title();
if title != new_title {
window.set_title(&new_title);
@@ -128,7 +141,7 @@ pub trait Application {
debug.layout_started();
let user_interface = UserInterface::build(
- document(&mut self, size, &mut debug),
+ document(&mut application, size, &mut debug),
temp_cache,
&mut renderer,
);
@@ -143,6 +156,9 @@ pub trait Application {
window.request_redraw();
}
+ event::Event::UserEvent(message) => {
+ external_messages.push(message);
+ }
event::Event::RedrawRequested(_) => {
debug.render_started();
@@ -288,3 +304,25 @@ where
.height(Length::Units(size.height.round() as u16))
.into()
}
+
+fn spawn<Message: Send>(
+ command: Command<Message>,
+ thread_pool: &mut futures::executor::ThreadPool,
+ proxy: &winit::event_loop::EventLoopProxy<Message>,
+) {
+ use futures::FutureExt;
+
+ let futures = command.futures();
+
+ for future in futures {
+ let proxy = proxy.clone();
+
+ let future = future.map(move |message| {
+ proxy
+ .send_event(message)
+ .expect("Send command result to event loop");
+ });
+
+ thread_pool.spawn_ok(future);
+ }
+}