diff options
| author | 2019-11-17 07:09:46 +0100 | |
|---|---|---|
| committer | 2019-11-17 07:11:44 +0100 | |
| commit | 02c20e6202f1c8c28753f3233cc635790707937a (patch) | |
| tree | b13ec79b938a6000709d1241ac1344724386c77a | |
| parent | e640b875900a3833fd38efa195e99b40ec3f6820 (diff) | |
| download | iced-02c20e6202f1c8c28753f3233cc635790707937a.tar.gz iced-02c20e6202f1c8c28753f3233cc635790707937a.tar.bz2 iced-02c20e6202f1c8c28753f3233cc635790707937a.zip | |
Support async actions in `iced_winit`
| -rw-r--r-- | examples/scroll.rs | 14 | ||||
| -rw-r--r-- | examples/todos.rs | 14 | ||||
| -rw-r--r-- | examples/tour.rs | 36 | ||||
| -rw-r--r-- | src/lib.rs | 22 | ||||
| -rw-r--r-- | src/winit.rs | 4 | ||||
| -rw-r--r-- | winit/Cargo.toml | 1 | ||||
| -rw-r--r-- | winit/src/application.rs | 66 | 
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> { @@ -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); +    } +} | 
