Skip to content

Commit 978e9fe

Browse files
authored
runtime: Handle widget operations in program::State helper (#46)
1 parent f2647b9 commit 978e9fe

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

runtime/src/program/state.rs

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use crate::core::event::{self, Event};
22
use crate::core::mouse;
33
use crate::core::renderer;
4+
use crate::core::widget::operation::{
5+
Operation, OperationOutputWrapper, OperationWrapper, Outcome,
6+
};
47
use crate::core::{Clipboard, Point, Size};
58
use crate::user_interface::{self, UserInterface};
6-
use crate::{Command, Debug, Program};
9+
use crate::{command::Action, Command, Debug, Program};
710

811
/// The execution state of a [`Program`]. It leverages caching, event
912
/// processing, and rendering primitive storage.
@@ -97,7 +100,7 @@ where
97100
style: &renderer::Style,
98101
clipboard: &mut dyn Clipboard,
99102
debug: &mut Debug,
100-
) -> (Vec<Event>, Option<Command<P::Message>>) {
103+
) -> (Vec<Event>, Vec<Action<P::Message>>) {
101104
let mut user_interface = build_user_interface(
102105
id,
103106
&mut self.program,
@@ -132,21 +135,21 @@ where
132135
messages.append(&mut self.queued_messages);
133136
debug.event_processing_finished();
134137

135-
let command = if messages.is_empty() {
138+
let actions = if messages.is_empty() {
136139
debug.draw_started();
137140
self.mouse_interaction =
138141
user_interface.draw(renderer, theme, style, cursor_position);
139142
debug.draw_finished();
140143

141144
self.cache = Some(user_interface.into_cache());
142145

143-
None
146+
Vec::new()
144147
} else {
145148
// When there are messages, we are forced to rebuild twice
146149
// for now :^)
147150
let temp_cache = user_interface.into_cache();
148151

149-
let commands =
152+
let (actions, widget_actions) =
150153
Command::batch(messages.into_iter().map(|message| {
151154
debug.log_message(&message);
152155

@@ -155,7 +158,12 @@ where
155158
debug.update_finished();
156159

157160
command
158-
}));
161+
}))
162+
.actions()
163+
.into_iter()
164+
.partition::<Vec<_>, _>(|action| {
165+
!matches!(action, Action::Widget(_))
166+
});
159167

160168
let mut user_interface = build_user_interface(
161169
id,
@@ -166,17 +174,58 @@ where
166174
debug,
167175
);
168176

177+
let had_operations = !widget_actions.is_empty();
178+
for operation in widget_actions
179+
.into_iter()
180+
.map(|action| match action {
181+
Action::Widget(widget_action) => widget_action,
182+
_ => unreachable!(),
183+
})
184+
.map(OperationWrapper::Message)
185+
{
186+
let mut current_operation = Some(operation);
187+
while let Some(mut operation) = current_operation.take() {
188+
user_interface.operate(renderer, &mut operation);
189+
match operation.finish() {
190+
Outcome::Some(OperationOutputWrapper::Message(
191+
message,
192+
)) => self.queued_messages.push(message),
193+
Outcome::Chain(op) => {
194+
current_operation =
195+
Some(OperationWrapper::Wrapper(op));
196+
}
197+
_ => {}
198+
};
199+
}
200+
}
201+
202+
let mut user_interface = if had_operations {
203+
// When there were operations, we are forced to rebuild thrice ...
204+
let temp_cache = user_interface.into_cache();
205+
206+
build_user_interface(
207+
id,
208+
&mut self.program,
209+
temp_cache,
210+
renderer,
211+
bounds,
212+
debug,
213+
)
214+
} else {
215+
user_interface
216+
};
217+
169218
debug.draw_started();
170219
self.mouse_interaction =
171220
user_interface.draw(renderer, theme, style, cursor_position);
172221
debug.draw_finished();
173222

174223
self.cache = Some(user_interface.into_cache());
175224

176-
Some(commands)
225+
actions
177226
};
178227

179-
(uncaptured_events, command)
228+
(uncaptured_events, actions)
180229
}
181230
}
182231

0 commit comments

Comments
 (0)