From ae5e2c6c734894d71b2034a498a858b7997c5d3d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 May 2020 04:27:31 +0200 Subject: Introduce `Program` and `State` --- native/src/program/state.rs | 154 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 native/src/program/state.rs (limited to 'native/src/program/state.rs') diff --git a/native/src/program/state.rs b/native/src/program/state.rs new file mode 100644 index 00000000..bcb7212d --- /dev/null +++ b/native/src/program/state.rs @@ -0,0 +1,154 @@ +use crate::{ + Cache, Clipboard, Command, Debug, Event, Program, Renderer, Size, + UserInterface, +}; + +#[allow(missing_debug_implementations)] +pub struct State

+where + P: Program + 'static, +{ + program: P, + cache: Option, + primitive: ::Output, + queued_events: Vec, + queued_messages: Vec, +} + +impl

State

+where + P: Program + 'static, +{ + pub fn new( + mut program: P, + bounds: Size, + renderer: &mut P::Renderer, + debug: &mut Debug, + ) -> Self { + let user_interface = build_user_interface( + &mut program, + Cache::default(), + renderer, + bounds, + debug, + ); + + debug.draw_started(); + let primitive = user_interface.draw(renderer); + debug.draw_finished(); + + let cache = Some(user_interface.into_cache()); + + State { + program, + cache, + primitive, + queued_events: Vec::new(), + queued_messages: Vec::new(), + } + } + + pub fn program(&self) -> &P { + &self.program + } + + pub fn primitive(&self) -> &::Output { + &self.primitive + } + + pub fn queue_event(&mut self, event: Event) { + self.queued_events.push(event); + } + + pub fn queue_message(&mut self, message: P::Message) { + self.queued_messages.push(message); + } + + pub fn update( + &mut self, + clipboard: Option<&dyn Clipboard>, + bounds: Size, + renderer: &mut P::Renderer, + debug: &mut Debug, + ) -> Option> { + if self.queued_events.is_empty() && self.queued_messages.is_empty() { + return None; + } + + let mut user_interface = build_user_interface( + &mut self.program, + self.cache.take().unwrap(), + renderer, + bounds, + debug, + ); + + debug.event_processing_started(); + let mut messages = user_interface.update( + self.queued_events.drain(..), + clipboard, + renderer, + ); + messages.extend(self.queued_messages.drain(..)); + debug.event_processing_finished(); + + if messages.is_empty() { + debug.draw_started(); + self.primitive = user_interface.draw(renderer); + debug.draw_finished(); + + self.cache = Some(user_interface.into_cache()); + + None + } else { + // When there are messages, we are forced to rebuild twice + // for now :^) + let temp_cache = user_interface.into_cache(); + + let commands = + Command::batch(messages.into_iter().map(|message| { + debug.log_message(&message); + + debug.update_started(); + let command = self.program.update(message); + debug.update_finished(); + + command + })); + + let user_interface = build_user_interface( + &mut self.program, + temp_cache, + renderer, + bounds, + debug, + ); + + debug.draw_started(); + self.primitive = user_interface.draw(renderer); + debug.draw_finished(); + + self.cache = Some(user_interface.into_cache()); + + Some(commands) + } + } +} + +fn build_user_interface<'a, P: Program>( + program: &'a mut P, + cache: Cache, + renderer: &mut P::Renderer, + size: Size, + debug: &mut Debug, +) -> UserInterface<'a, P::Message, P::Renderer> { + debug.view_started(); + let view = program.view(); + debug.view_finished(); + + debug.layout_started(); + let user_interface = UserInterface::build(view, size, cache, renderer); + debug.layout_finished(); + + user_interface +} -- cgit From 508128436c5da88d4b4f384a9fe73288320eb9ec Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 28 May 2020 02:04:31 +0200 Subject: Write documentation for new `iced_native` API --- native/src/program/state.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'native/src/program/state.rs') diff --git a/native/src/program/state.rs b/native/src/program/state.rs index bcb7212d..8716d8b9 100644 --- a/native/src/program/state.rs +++ b/native/src/program/state.rs @@ -3,6 +3,10 @@ use crate::{ UserInterface, }; +/// The execution state of a [`Program`]. It leverages caching, event +/// processing, and rendering primitive storage. +/// +/// [`Program`]: trait.Program.html #[allow(missing_debug_implementations)] pub struct State

where @@ -19,6 +23,11 @@ impl

State

where P: Program + 'static, { + /// Creates a new [`State`] with the provided [`Program`], initializing its + /// primitive with the given logical bounds and renderer. + /// + /// [`State`]: struct.State.html + /// [`Program`]: trait.Program.html pub fn new( mut program: P, bounds: Size, @@ -48,22 +57,44 @@ where } } + /// Returns a reference to the [`Program`] of the [`State`]. + /// + /// [`Program`]: trait.Program.html + /// [`State`]: struct.State.html pub fn program(&self) -> &P { &self.program } + /// Returns a reference to the current rendering primitive of the [`State`]. + /// + /// [`State`]: struct.State.html pub fn primitive(&self) -> &::Output { &self.primitive } + /// Queues an event in the [`State`] for processing during an [`update`]. + /// + /// [`State`]: struct.State.html + /// [`update`]: #method.update pub fn queue_event(&mut self, event: Event) { self.queued_events.push(event); } + /// Queues a message in the [`State`] for processing during an [`update`]. + /// + /// [`State`]: struct.State.html + /// [`update`]: #method.update pub fn queue_message(&mut self, message: P::Message) { self.queued_messages.push(message); } + /// Processes all the queued events and messages, rebuilding and redrawing + /// the widgets of the linked [`Program`] if necessary. + /// + /// Returns the [`Command`] obtained from [`Program`] after updating it, + /// only if an update was necessary. + /// + /// [`Program`]: trait.Program.html pub fn update( &mut self, clipboard: Option<&dyn Clipboard>, -- cgit