1
1
use crate :: core:: event:: { self , Event } ;
2
2
use crate :: core:: mouse;
3
3
use crate :: core:: renderer;
4
+ use crate :: core:: widget:: operation:: {
5
+ Operation , OperationOutputWrapper , OperationWrapper , Outcome ,
6
+ } ;
4
7
use crate :: core:: { Clipboard , Point , Size } ;
5
8
use crate :: user_interface:: { self , UserInterface } ;
6
- use crate :: { Command , Debug , Program } ;
9
+ use crate :: { command :: Action , Command , Debug , Program } ;
7
10
8
11
/// The execution state of a [`Program`]. It leverages caching, event
9
12
/// processing, and rendering primitive storage.
97
100
style : & renderer:: Style ,
98
101
clipboard : & mut dyn Clipboard ,
99
102
debug : & mut Debug ,
100
- ) -> ( Vec < Event > , Option < Command < P :: Message > > ) {
103
+ ) -> ( Vec < Event > , Vec < Action < P :: Message > > ) {
101
104
let mut user_interface = build_user_interface (
102
105
id,
103
106
& mut self . program ,
@@ -132,21 +135,21 @@ where
132
135
messages. append ( & mut self . queued_messages ) ;
133
136
debug. event_processing_finished ( ) ;
134
137
135
- let command = if messages. is_empty ( ) {
138
+ let actions = if messages. is_empty ( ) {
136
139
debug. draw_started ( ) ;
137
140
self . mouse_interaction =
138
141
user_interface. draw ( renderer, theme, style, cursor_position) ;
139
142
debug. draw_finished ( ) ;
140
143
141
144
self . cache = Some ( user_interface. into_cache ( ) ) ;
142
145
143
- None
146
+ Vec :: new ( )
144
147
} else {
145
148
// When there are messages, we are forced to rebuild twice
146
149
// for now :^)
147
150
let temp_cache = user_interface. into_cache ( ) ;
148
151
149
- let commands =
152
+ let ( actions , widget_actions ) =
150
153
Command :: batch ( messages. into_iter ( ) . map ( |message| {
151
154
debug. log_message ( & message) ;
152
155
@@ -155,7 +158,12 @@ where
155
158
debug. update_finished ( ) ;
156
159
157
160
command
158
- } ) ) ;
161
+ } ) )
162
+ . actions ( )
163
+ . into_iter ( )
164
+ . partition :: < Vec < _ > , _ > ( |action| {
165
+ !matches ! ( action, Action :: Widget ( _) )
166
+ } ) ;
159
167
160
168
let mut user_interface = build_user_interface (
161
169
id,
@@ -166,17 +174,58 @@ where
166
174
debug,
167
175
) ;
168
176
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
+
169
218
debug. draw_started ( ) ;
170
219
self . mouse_interaction =
171
220
user_interface. draw ( renderer, theme, style, cursor_position) ;
172
221
debug. draw_finished ( ) ;
173
222
174
223
self . cache = Some ( user_interface. into_cache ( ) ) ;
175
224
176
- Some ( commands )
225
+ actions
177
226
} ;
178
227
179
- ( uncaptured_events, command )
228
+ ( uncaptured_events, actions )
180
229
}
181
230
}
182
231
0 commit comments