1use crate::core::event::{self, Event};
2use crate::core::mouse;
3use crate::core::renderer;
4use crate::core::widget::operation::{self, Operation};
5use crate::core::{Clipboard, Size};
6use crate::user_interface::{self, UserInterface};
7use crate::{Debug, Program, Task};
8
9#[allow(missing_debug_implementations)]
12pub struct State<P>
13where
14 P: Program + 'static,
15{
16 program: P,
17 cache: Option<user_interface::Cache>,
18 queued_events: Vec<Event>,
19 queued_messages: Vec<P::Message>,
20 mouse_interaction: mouse::Interaction,
21}
22
23impl<P> State<P>
24where
25 P: Program + 'static,
26{
27 pub fn new(
30 id: iced_core::id::Id,
31 mut program: P,
32 bounds: Size,
33 renderer: &mut P::Renderer,
34 debug: &mut Debug,
35 ) -> Self {
36 let user_interface = build_user_interface(
37 id,
38 &mut program,
39 user_interface::Cache::default(),
40 renderer,
41 bounds,
42 debug,
43 );
44
45 let cache = Some(user_interface.into_cache());
46
47 State {
48 program,
49 cache,
50 queued_events: Vec::new(),
51 queued_messages: Vec::new(),
52 mouse_interaction: mouse::Interaction::None,
53 }
54 }
55
56 pub fn program(&self) -> &P {
58 &self.program
59 }
60
61 pub fn queue_event(&mut self, event: Event) {
65 self.queued_events.push(event);
66 }
67
68 pub fn queue_message(&mut self, message: P::Message) {
72 self.queued_messages.push(message);
73 }
74
75 pub fn is_queue_empty(&self) -> bool {
77 self.queued_events.is_empty() && self.queued_messages.is_empty()
78 }
79
80 pub fn mouse_interaction(&self) -> mouse::Interaction {
82 self.mouse_interaction
83 }
84
85 pub fn update(
92 &mut self,
93 id: iced_core::id::Id,
94 bounds: Size,
95 cursor: mouse::Cursor,
96 renderer: &mut P::Renderer,
97 theme: &P::Theme,
98 style: &renderer::Style,
99 clipboard: &mut dyn Clipboard,
100 debug: &mut Debug,
101 ) -> (Vec<Event>, Option<Task<P::Message>>) {
102 let mut user_interface = build_user_interface(
103 id.clone(),
104 &mut self.program,
105 self.cache.take().unwrap(),
106 renderer,
107 bounds,
108 debug,
109 );
110
111 debug.event_processing_started();
112 let mut messages = Vec::new();
113
114 let (_, event_statuses) = user_interface.update(
115 &self.queued_events,
116 cursor,
117 renderer,
118 clipboard,
119 &mut messages,
120 );
121
122 let uncaptured_events = self
123 .queued_events
124 .iter()
125 .zip(event_statuses)
126 .filter_map(|(event, status)| {
127 matches!(status, event::Status::Ignored).then_some(event)
128 })
129 .cloned()
130 .collect();
131
132 self.queued_events.clear();
133 messages.append(&mut self.queued_messages);
134 debug.event_processing_finished();
135
136 let task = if messages.is_empty() {
137 debug.draw_started();
138 self.mouse_interaction =
139 user_interface.draw(renderer, theme, style, cursor);
140 debug.draw_finished();
141
142 self.cache = Some(user_interface.into_cache());
143
144 None
145 } else {
146 let temp_cache = user_interface.into_cache();
149
150 let tasks = Task::batch(messages.into_iter().map(|message| {
151 debug.log_message(&message);
152
153 debug.update_started();
154 let task = self.program.update(message);
155 debug.update_finished();
156
157 task
158 }));
159
160 let mut user_interface = build_user_interface(
161 id,
162 &mut self.program,
163 temp_cache,
164 renderer,
165 bounds,
166 debug,
167 );
168
169 debug.draw_started();
170 self.mouse_interaction =
171 user_interface.draw(renderer, theme, style, cursor);
172 debug.draw_finished();
173
174 self.cache = Some(user_interface.into_cache());
175
176 Some(tasks)
177 };
178
179 (uncaptured_events, task)
180 }
181
182 pub fn operate(
184 &mut self,
185 id: iced_core::id::Id,
186 renderer: &mut P::Renderer,
187 operations: impl Iterator<Item = Box<dyn Operation>>,
188 bounds: Size,
189 debug: &mut Debug,
190 ) {
191 let mut user_interface = build_user_interface(
192 id,
193 &mut self.program,
194 self.cache.take().unwrap(),
195 renderer,
196 bounds,
197 debug,
198 );
199
200 for operation in operations {
201 let mut current_operation = Some(operation);
202
203 while let Some(mut operation) = current_operation.take() {
204 user_interface.operate(renderer, operation.as_mut());
205
206 match operation.finish() {
207 operation::Outcome::None => {}
208 operation::Outcome::Some(()) => {}
209 operation::Outcome::Chain(next) => {
210 current_operation = Some(next);
211 }
212 };
213 }
214 }
215
216 self.cache = Some(user_interface.into_cache());
217 }
218}
219
220fn build_user_interface<'a, P: Program>(
221 _id: iced_core::id::Id,
222 program: &'a mut P,
223 cache: user_interface::Cache,
224 renderer: &mut P::Renderer,
225 size: Size,
226 debug: &mut Debug,
227) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
228 debug.view_started();
229 let view = program.view();
230 debug.view_finished();
231
232 debug.layout_started();
233 let user_interface = UserInterface::build(view, size, cache, renderer);
234 debug.layout_finished();
235
236 user_interface
237}