relm4/factory/async/collections/
vec_deque.rs1use crate::{Receiver, Sender};
2
3use crate::factory::r#async::AsyncFactoryBuilder;
4use crate::factory::r#async::component_storage::AsyncComponentStorage;
5use crate::factory::r#async::traits::AsyncFactoryComponent;
6use crate::factory::{DynamicIndex, FactoryView};
7
8use super::{ModelStateValue, RenderedState};
9
10use std::collections::VecDeque;
11use std::collections::hash_map::DefaultHasher;
12use std::hash::Hash;
13use std::iter::FusedIterator;
14use std::marker::PhantomData;
15use std::ops::Deref;
16
17#[cfg(feature = "libadwaita")]
18use gtk::prelude::Cast;
19
20#[cfg(feature = "libadwaita")]
21use std::hash::Hasher;
22
23#[derive(Debug)]
27#[must_use]
28pub struct AsyncFactoryVecDequeGuard<'a, C: AsyncFactoryComponent>
29where
30 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
31{
32 inner: &'a mut AsyncFactoryVecDeque<C>,
33}
34
35impl<C: AsyncFactoryComponent> Drop for AsyncFactoryVecDequeGuard<'_, C>
36where
37 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
38{
39 fn drop(&mut self) {
40 self.inner.render_changes();
41 }
42}
43
44impl<'a, C: AsyncFactoryComponent> AsyncFactoryVecDequeGuard<'a, C>
45where
46 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
47{
48 fn new(inner: &'a mut AsyncFactoryVecDeque<C>) -> Self {
49 #[allow(unused_mut)]
50 #[allow(clippy::let_and_return)]
51 let mut guard = AsyncFactoryVecDequeGuard { inner };
52
53 #[cfg(feature = "libadwaita")]
54 guard.apply_external_updates();
55
56 guard
57 }
58
59 pub fn drop(self) {
63 drop(self);
64 }
65
66 #[cfg(feature = "libadwaita")]
72 fn apply_external_updates(&mut self) {
73 if let Some(tab_view) = self.inner.widget().dynamic_cast_ref::<adw::TabView>() {
74 let length = tab_view.n_pages();
75 let mut hash_values: Vec<u64> = Vec::with_capacity(usize::try_from(length).unwrap());
76
77 for i in 0..length {
78 let page = tab_view.nth_page(i);
79 let mut hasher = DefaultHasher::default();
80 page.hash(&mut hasher);
81 hash_values.push(hasher.finish());
82 }
83
84 for (index, hash) in hash_values.iter().enumerate() {
86 if self
87 .inner
88 .rendered_state
89 .get(index)
90 .map(|state| state.widget_hash)
91 == Some(*hash)
92 {
93 let old_position = self
94 .inner
95 .rendered_state
96 .iter()
97 .position(|state| state.widget_hash == *hash)
98 .expect("A new widget was added");
99
100 let elem = self.inner.rendered_state.remove(old_position).unwrap();
101 self.inner.rendered_state.insert(index, elem);
102
103 self.move_to(old_position, index);
104 }
105 }
106
107 let mut index = 0;
109 while index < self.inner.rendered_state.len() {
110 let hash = self.inner.rendered_state[index].widget_hash;
111 if hash_values.contains(&hash) {
112 index += 1;
113 } else {
114 self.inner.rendered_state.remove(index);
115
116 self.remove(index);
117 }
118 }
119 }
120 }
121
122 pub fn get_mut(&mut self, index: usize) -> Option<&mut C> {
130 if let Some(state) = self.inner.model_state.get_mut(index) {
132 state.changed = true;
133 }
134 self.inner
135 .components
136 .get_mut(index)
137 .and_then(AsyncComponentStorage::get_mut)
138 }
139
140 pub fn back_mut(&mut self) -> Option<&mut C> {
147 self.get_mut(self.len().wrapping_sub(1))
148 }
149
150 pub fn front_mut(&mut self) -> Option<&mut C> {
157 self.get_mut(0)
158 }
159
160 pub fn pop_back(&mut self) -> Option<C> {
166 if self.is_empty() {
167 None
168 } else {
169 self.remove(self.len() - 1)
170 }
171 }
172
173 pub fn pop_front(&mut self) -> Option<C> {
179 self.remove(0)
180 }
181
182 pub fn remove(&mut self, index: usize) -> Option<C> {
190 self.inner.model_state.remove(index);
191 let component = self.inner.components.remove(index);
192
193 for states in self.inner.model_state.iter_mut().skip(index) {
195 states.index.decrement();
196 }
197
198 if let Some(comp) = &component
199 && let Some(widget) = &comp.returned_widget()
200 {
201 self.widget.factory_remove(widget);
202 }
203
204 component.and_then(AsyncComponentStorage::extract)
205 }
206
207 pub fn push_back(&mut self, init: C::Init) -> DynamicIndex {
209 let index = self.len();
210 self.insert(index, init)
211 }
212
213 pub fn push_front(&mut self, init: C::Init) -> DynamicIndex {
215 self.insert(0, init)
216 }
217
218 pub fn insert(&mut self, index: usize, init: C::Init) -> DynamicIndex {
228 let dyn_index = DynamicIndex::new(index);
229
230 for states in self.inner.model_state.iter_mut().skip(index) {
232 states.index.increment();
233 }
234
235 let builder = AsyncFactoryBuilder::new(init, self.output_sender.clone());
236
237 self.inner
238 .components
239 .insert(index, AsyncComponentStorage::Builder(builder));
240 self.inner.model_state.insert(
241 index,
242 ModelStateValue {
243 index: dyn_index.clone(),
244 uid: self.uid_counter,
245 changed: false,
246 },
247 );
248 self.inner.uid_counter += 1;
249
250 dyn_index
251 }
252
253 pub fn swap(&mut self, first: usize, second: usize) {
263 if first != second {
265 self.inner.model_state.swap(first, second);
266 self.inner.components.swap(first, second);
267
268 self.model_state[first].index.set_value(first);
270 self.model_state[second].index.set_value(second);
271 }
272 }
273
274 pub fn move_to(&mut self, current_position: usize, target: usize) {
285 if current_position != target {
287 let elem = self.inner.model_state.remove(current_position).unwrap();
288 elem.index.set_value(target);
290 self.inner.model_state.insert(target, elem);
291
292 let comp = self.inner.components.remove(current_position).unwrap();
293 self.inner.components.insert(target, comp);
294
295 if current_position > target {
297 for state in self
299 .inner
300 .model_state
301 .iter_mut()
302 .skip(target + 1)
303 .take(current_position - target)
304 {
305 state.index.increment();
306 }
307 } else {
308 for state in self
310 .inner
311 .model_state
312 .iter_mut()
313 .skip(current_position)
314 .take(target - current_position)
315 {
316 state.index.decrement();
317 }
318 }
319 }
320 }
321
322 pub fn move_front(&mut self, current_position: usize) {
329 self.move_to(current_position, 0);
330 }
331
332 pub fn move_back(&mut self, current_position: usize) {
339 self.move_to(current_position, self.len() - 1);
340 }
341
342 pub fn clear(&mut self) {
344 self.inner.model_state.clear();
345
346 for component in self.inner.components.drain(..) {
347 if let Some(widget) = component.returned_widget() {
349 self.inner.widget.factory_remove(widget);
350 }
351
352 component.extract();
354 }
355
356 self.inner.rendered_state.clear();
357
358 self.inner.uid_counter = 1;
359 }
360
361 pub fn iter_mut(
368 &mut self,
369 ) -> impl DoubleEndedIterator<Item = Option<&mut C>> + ExactSizeIterator + FusedIterator {
370 self.inner
371 .components
372 .iter_mut()
373 .zip(self.inner.model_state.iter_mut())
374 .map(|(component, state)| {
375 state.changed = true;
376 component.get_mut()
377 })
378 }
379}
380
381impl<C: AsyncFactoryComponent> Deref for AsyncFactoryVecDequeGuard<'_, C>
382where
383 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
384{
385 type Target = AsyncFactoryVecDeque<C>;
386
387 fn deref(&self) -> &Self::Target {
388 self.inner
389 }
390}
391
392#[derive(Debug)]
393pub struct AsyncFactoryVecDequeBuilder<C>
395where
396 C: AsyncFactoryComponent,
397{
398 _component: PhantomData<C>,
399}
400
401impl<C> Default for AsyncFactoryVecDequeBuilder<C>
402where
403 C: AsyncFactoryComponent,
404{
405 fn default() -> Self {
406 Self::new()
407 }
408}
409
410impl<C> AsyncFactoryVecDequeBuilder<C>
411where
412 C: AsyncFactoryComponent,
413 C::ParentWidget: Default,
414{
415 #[must_use]
417 pub fn launch_default(self) -> AsyncFactoryVecDequeConnector<C> {
418 self.launch(Default::default())
419 }
420}
421
422impl<C> AsyncFactoryVecDequeBuilder<C>
423where
424 C: AsyncFactoryComponent,
425{
426 #[must_use]
428 pub fn new() -> Self {
429 Self {
430 _component: PhantomData,
431 }
432 }
433
434 pub fn launch(self, widget: C::ParentWidget) -> AsyncFactoryVecDequeConnector<C> {
437 let (output_sender, output_receiver) = crate::channel();
438
439 AsyncFactoryVecDequeConnector {
440 widget,
441 output_sender,
442 output_receiver,
443 }
444 }
445}
446
447#[derive(Debug)]
448pub struct AsyncFactoryVecDequeConnector<C>
450where
451 C: AsyncFactoryComponent,
452{
453 widget: C::ParentWidget,
454 output_sender: Sender<C::Output>,
455 output_receiver: Receiver<C::Output>,
456}
457
458impl<C> AsyncFactoryVecDequeConnector<C>
459where
460 C: AsyncFactoryComponent,
461 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
462{
463 pub fn forward<F, Msg>(self, sender_: &Sender<Msg>, f: F) -> AsyncFactoryVecDeque<C>
465 where
466 F: Fn(C::Output) -> Msg + Send + 'static,
467 C::Output: Send,
468 Msg: Send + 'static,
469 {
470 let Self {
471 widget,
472 output_sender,
473 output_receiver,
474 } = self;
475
476 let sender_clone = sender_.clone();
477 crate::spawn(async move {
478 while let Some(msg) = output_receiver.recv().await {
479 if sender_clone.send(f(msg)).is_err() {
480 break;
481 }
482 }
483 });
484
485 AsyncFactoryVecDeque {
486 widget,
487 output_sender,
488 components: VecDeque::new(),
489 model_state: VecDeque::new(),
490 rendered_state: VecDeque::new(),
491 uid_counter: 1,
493 }
494 }
495
496 pub fn detach(self) -> AsyncFactoryVecDeque<C> {
498 let Self {
499 widget,
500 output_sender,
501 ..
502 } = self;
503 AsyncFactoryVecDeque {
504 widget,
505 output_sender,
506 components: VecDeque::new(),
507 model_state: VecDeque::new(),
508 rendered_state: VecDeque::new(),
509 uid_counter: 1,
511 }
512 }
513}
514
515#[derive(Debug)]
520pub struct AsyncFactoryVecDeque<C: AsyncFactoryComponent>
521where
522 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
523{
524 widget: C::ParentWidget,
525 output_sender: Sender<C::Output>,
526 components: VecDeque<AsyncComponentStorage<C>>,
527 model_state: VecDeque<ModelStateValue>,
528 rendered_state: VecDeque<RenderedState>,
529 uid_counter: usize,
530}
531
532impl<C: AsyncFactoryComponent> Drop for AsyncFactoryVecDeque<C>
533where
534 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
535{
536 fn drop(&mut self) {
537 self.guard().clear();
538 }
539}
540
541impl<C: AsyncFactoryComponent> AsyncFactoryVecDeque<C>
542where
543 <C::ParentWidget as FactoryView>::ReturnedWidget: Clone,
544{
545 #[must_use]
547 pub fn builder() -> AsyncFactoryVecDequeBuilder<C> {
548 AsyncFactoryVecDequeBuilder::new()
549 }
550
551 pub fn guard(&mut self) -> AsyncFactoryVecDequeGuard<'_, C> {
555 AsyncFactoryVecDequeGuard::new(self)
556 }
557
558 fn render_changes(&mut self) {
567 let mut first_position_change_idx = None;
568
569 let components = &mut self.components;
570 let rendered_state = &mut self.rendered_state;
571 for (index, state) in self.model_state.iter().enumerate() {
572 if state.uid == rendered_state.front().map(|r| r.uid).unwrap_or_default() {
573 rendered_state.pop_front();
575
576 if state.changed {
577 components[index].state_change_notify();
579 }
580 } else if let Some(rendered_index) =
581 rendered_state.iter().position(|r| r.uid == state.uid)
582 {
583 if first_position_change_idx.is_none() {
584 first_position_change_idx = Some(index);
585 }
586
587 rendered_state.remove(rendered_index);
589
590 let widget = components[index].returned_widget().unwrap();
592 if index == 0 {
593 self.widget.factory_move_start(widget);
594 } else {
595 let previous_widget = components[index - 1].returned_widget().unwrap();
596 self.widget.factory_move_after(widget, previous_widget);
597 }
598
599 if state.changed {
600 components[index].state_change_notify();
602 }
603 } else {
604 if first_position_change_idx.is_none() {
605 first_position_change_idx = Some(index);
606 }
607
608 let insert_widget = components[index].widget();
610 let position = C::position(index);
611 let returned_widget = if index == 0 {
612 self.widget.factory_prepend(insert_widget, &position)
613 } else {
614 let previous_widget = components[index - 1].returned_widget().unwrap();
615 self.widget
616 .factory_insert_after(insert_widget, &position, previous_widget)
617 };
618 let component = components.remove(index).unwrap();
619 let dyn_index = &self.model_state[index].index;
620 let component = component.launch(dyn_index, returned_widget).unwrap();
621 components.insert(index, component);
622 }
623 }
624
625 self.model_state.iter_mut().for_each(|s| s.changed = false);
627
628 self.rendered_state = self
631 .model_state
632 .iter()
633 .zip(components.iter())
634 .map(|(s, c)| {
635 let mut hasher = DefaultHasher::default();
636 c.returned_widget().unwrap().hash(&mut hasher);
637
638 RenderedState {
639 uid: s.uid,
640 #[cfg(feature = "libadwaita")]
641 widget_hash: hasher.finish(),
642 }
643 })
644 .collect();
645
646 if let Some(change_index) = first_position_change_idx {
647 for (index, comp) in components.iter().enumerate().skip(change_index) {
648 let position = C::position(index);
649 self.widget
650 .factory_update_position(comp.returned_widget().unwrap(), &position);
651 }
652 }
653 }
654
655 pub fn len(&self) -> usize {
657 self.components.len()
658 }
659
660 pub fn is_empty(&self) -> bool {
662 self.components.is_empty()
663 }
664
665 pub fn send(&self, index: usize, msg: C::Input) {
667 self.components[index].send(msg);
668 }
669
670 pub fn broadcast(&self, msg: C::Input)
672 where
673 C::Input: Clone,
674 {
675 self.components.iter().for_each(|c| c.send(msg.clone()));
676 }
677
678 pub fn get(&self, index: usize) -> Option<&C> {
686 self.components
687 .get(index)
688 .and_then(AsyncComponentStorage::get)
689 }
690
691 pub fn back(&self) -> Option<&C> {
698 self.get(self.len().wrapping_sub(1))
699 }
700
701 pub fn front(&self) -> Option<&C> {
708 self.get(0)
709 }
710
711 pub const fn widget(&self) -> &C::ParentWidget {
713 &self.widget
714 }
715
716 pub fn iter(
723 &self,
724 ) -> impl DoubleEndedIterator<Item = Option<&C>> + ExactSizeIterator + FusedIterator {
725 self.components.iter().map(AsyncComponentStorage::get)
726 }
727}