relm4/factory/sync/collections/
vec_deque.rs1use crate::{Receiver, Sender};
2
3use crate::factory::sync::builder::FactoryBuilder;
4use crate::factory::sync::component_storage::ComponentStorage;
5use crate::factory::sync::traits::CloneableFactoryComponent;
6use crate::factory::{DynamicIndex, FactoryComponent, 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, Index, IndexMut};
16
17#[cfg(feature = "libadwaita")]
18use gtk::prelude::Cast;
19use gtk::prelude::IsA;
20
21#[cfg(feature = "libadwaita")]
22use std::hash::Hasher;
23
24#[derive(Debug)]
28#[must_use]
29pub struct FactoryVecDequeGuard<'a, C>
30where
31 C: FactoryComponent<Index = DynamicIndex>,
32{
33 inner: &'a mut FactoryVecDeque<C>,
34}
35
36impl<C> Drop for FactoryVecDequeGuard<'_, C>
37where
38 C: FactoryComponent<Index = DynamicIndex>,
39{
40 fn drop(&mut self) {
41 self.inner.render_changes();
42 }
43}
44
45impl<'a, C> FactoryVecDequeGuard<'a, C>
46where
47 C: FactoryComponent<Index = DynamicIndex>,
48{
49 fn new(inner: &'a mut FactoryVecDeque<C>) -> Self {
50 #[allow(unused_mut)]
51 #[allow(clippy::let_and_return)]
52 let mut guard = FactoryVecDequeGuard { inner };
53
54 #[cfg(feature = "libadwaita")]
55 guard.apply_external_updates();
56
57 guard
58 }
59
60 pub fn drop(self) {
64 drop(self);
65 }
66
67 #[cfg(feature = "libadwaita")]
73 fn apply_external_updates(&mut self) {
74 if let Some(tab_view) = self.inner.widget().dynamic_cast_ref::<adw::TabView>() {
75 let length = tab_view.n_pages();
76 let mut hash_values: Vec<u64> = Vec::with_capacity(usize::try_from(length).unwrap());
77
78 for i in 0..length {
79 let page = tab_view.nth_page(i);
80 let mut hasher = DefaultHasher::default();
81 page.hash(&mut hasher);
82 hash_values.push(hasher.finish());
83 }
84
85 for (index, hash) in hash_values.iter().enumerate() {
87 if self
88 .inner
89 .rendered_state
90 .get(index)
91 .map(|state| state.widget_hash)
92 == Some(*hash)
93 {
94 let old_position = self
95 .inner
96 .rendered_state
97 .iter()
98 .position(|state| state.widget_hash == *hash)
99 .expect("A new widget was added");
100
101 let elem = self.inner.rendered_state.remove(old_position).unwrap();
102 self.inner.rendered_state.insert(index, elem);
103
104 self.move_to(old_position, index);
105 }
106 }
107
108 let mut index = 0;
110 while index < self.inner.rendered_state.len() {
111 let hash = self.inner.rendered_state[index].widget_hash;
112 if hash_values.contains(&hash) {
113 index += 1;
114 } else {
115 self.inner.rendered_state.remove(index);
116
117 self.remove(index);
118 }
119 }
120 }
121 }
122
123 pub fn get_mut(&mut self, index: usize) -> Option<&mut C> {
128 if let Some(state) = self.inner.model_state.get_mut(index) {
130 state.changed = true;
131 }
132 self.inner
133 .components
134 .get_mut(index)
135 .map(ComponentStorage::get_mut)
136 }
137
138 pub fn back_mut(&mut self) -> Option<&mut C> {
142 self.get_mut(self.len().wrapping_sub(1))
143 }
144
145 pub fn front_mut(&mut self) -> Option<&mut C> {
149 self.get_mut(0)
150 }
151
152 pub fn pop_back(&mut self) -> Option<C> {
155 if self.is_empty() {
156 None
157 } else {
158 self.remove(self.len() - 1)
159 }
160 }
161
162 pub fn pop_front(&mut self) -> Option<C> {
165 self.remove(0)
166 }
167
168 pub fn remove(&mut self, index: usize) -> Option<C> {
173 self.inner.model_state.remove(index);
174 let component = self.inner.components.remove(index);
175
176 for states in self.inner.model_state.iter_mut().skip(index) {
178 states.index.decrement();
179 }
180
181 if let Some(comp) = &component
182 && let Some(widget) = &comp.returned_widget()
183 {
184 self.widget.factory_remove(widget);
185 }
186
187 component.map(ComponentStorage::extract)
188 }
189
190 pub fn push_back(&mut self, init: C::Init) -> DynamicIndex {
192 let index = self.len();
193 self.insert(index, init)
194 }
195
196 pub fn push_front(&mut self, init: C::Init) -> DynamicIndex {
198 self.insert(0, init)
199 }
200
201 pub fn insert(&mut self, index: usize, init: C::Init) -> DynamicIndex {
211 let dyn_index = DynamicIndex::new(index);
212
213 for states in self.inner.model_state.iter_mut().skip(index) {
215 states.index.increment();
216 }
217
218 let builder = FactoryBuilder::new(&dyn_index, init, self.output_sender.clone());
219
220 self.inner
221 .components
222 .insert(index, ComponentStorage::Builder(builder));
223 self.inner.model_state.insert(
224 index,
225 ModelStateValue {
226 index: dyn_index.clone(),
227 uid: self.uid_counter,
228 changed: false,
229 },
230 );
231 self.inner.uid_counter += 1;
232
233 dyn_index
234 }
235
236 pub fn swap(&mut self, first: usize, second: usize) {
246 if first != second {
248 self.inner.model_state.swap(first, second);
249 self.inner.components.swap(first, second);
250
251 self.model_state[first].index.set_value(first);
253 self.model_state[second].index.set_value(second);
254 }
255 }
256
257 pub fn move_to(&mut self, current_position: usize, target: usize) {
268 if current_position != target {
270 let elem = self.inner.model_state.remove(current_position).unwrap();
271 elem.index.set_value(target);
273 self.inner.model_state.insert(target, elem);
274
275 let comp = self.inner.components.remove(current_position).unwrap();
276 self.inner.components.insert(target, comp);
277
278 if current_position > target {
280 for state in self
282 .inner
283 .model_state
284 .iter_mut()
285 .skip(target + 1)
286 .take(current_position - target)
287 {
288 state.index.increment();
289 }
290 } else {
291 for state in self
293 .inner
294 .model_state
295 .iter_mut()
296 .skip(current_position)
297 .take(target - current_position)
298 {
299 state.index.decrement();
300 }
301 }
302 }
303 }
304
305 pub fn move_front(&mut self, current_position: usize) {
312 self.move_to(current_position, 0);
313 }
314
315 pub fn move_back(&mut self, current_position: usize) {
322 self.move_to(current_position, self.len() - 1);
323 }
324
325 pub fn clear(&mut self) {
327 self.inner.model_state.clear();
328
329 for component in self.inner.components.drain(..) {
330 if let Some(widget) = component.returned_widget() {
332 self.inner.widget.factory_remove(widget);
333 }
334
335 component.extract();
337 }
338
339 self.inner.rendered_state.clear();
340 self.inner.uid_counter = 1;
341 }
342
343 pub fn iter_mut(
345 &mut self,
346 ) -> impl DoubleEndedIterator<Item = &mut C> + ExactSizeIterator + FusedIterator {
347 self.inner
348 .components
349 .iter_mut()
350 .zip(self.inner.model_state.iter_mut())
351 .map(|(component, state)| {
352 state.changed = true;
353 component.get_mut()
354 })
355 }
356}
357
358impl<C> Deref for FactoryVecDequeGuard<'_, C>
359where
360 C: FactoryComponent<Index = DynamicIndex>,
361{
362 type Target = FactoryVecDeque<C>;
363
364 fn deref(&self) -> &Self::Target {
365 self.inner
366 }
367}
368
369impl<C> Index<usize> for FactoryVecDequeGuard<'_, C>
370where
371 C: FactoryComponent<Index = DynamicIndex>,
372{
373 type Output = C;
374
375 fn index(&self, index: usize) -> &Self::Output {
376 self.inner.index(index)
377 }
378}
379
380impl<C> IndexMut<usize> for FactoryVecDequeGuard<'_, C>
381where
382 C: FactoryComponent<Index = DynamicIndex>,
383{
384 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
385 self.get_mut(index)
386 .expect("Called `get_mut` on an invalid index")
387 }
388}
389
390#[derive(Debug)]
391pub struct FactoryVecDequeBuilder<C>
393where
394 C: FactoryComponent<Index = DynamicIndex>,
395{
396 _component: PhantomData<C>,
397}
398
399impl<C> Default for FactoryVecDequeBuilder<C>
400where
401 C: FactoryComponent<Index = DynamicIndex>,
402{
403 fn default() -> Self {
404 Self::new()
405 }
406}
407
408impl<C> FactoryVecDequeBuilder<C>
409where
410 C: FactoryComponent<Index = DynamicIndex>,
411 C::ParentWidget: Default,
412{
413 #[must_use]
415 pub fn launch_default(self) -> FactoryVecDequeConnector<C> {
416 self.launch(Default::default())
417 }
418}
419
420impl<C> FactoryVecDequeBuilder<C>
421where
422 C: FactoryComponent<Index = DynamicIndex>,
423{
424 #[must_use]
426 pub fn new() -> Self {
427 Self {
428 _component: PhantomData,
429 }
430 }
431
432 pub fn launch(self, widget: C::ParentWidget) -> FactoryVecDequeConnector<C> {
435 let (output_sender, output_receiver) = crate::channel();
436
437 FactoryVecDequeConnector {
438 widget,
439 output_sender,
440 output_receiver,
441 }
442 }
443}
444
445#[derive(Debug)]
446pub struct FactoryVecDequeConnector<C>
448where
449 C: FactoryComponent<Index = DynamicIndex>,
450{
451 widget: C::ParentWidget,
452 output_sender: Sender<C::Output>,
453 output_receiver: Receiver<C::Output>,
454}
455
456impl<C> FactoryVecDequeConnector<C>
457where
458 C: FactoryComponent<Index = DynamicIndex>,
459{
460 pub fn forward<F, Msg>(self, sender_: &Sender<Msg>, f: F) -> FactoryVecDeque<C>
462 where
463 F: Fn(C::Output) -> Msg + Send + 'static,
464 C::Output: Send,
465 Msg: Send + 'static,
466 {
467 let Self {
468 widget,
469 output_sender,
470 output_receiver,
471 } = self;
472
473 let sender_clone = sender_.clone();
474 crate::spawn(async move {
475 while let Some(msg) = output_receiver.recv().await {
476 if sender_clone.send(f(msg)).is_err() {
477 break;
478 }
479 }
480 });
481
482 FactoryVecDeque {
483 widget,
484 output_sender,
485 components: VecDeque::new(),
486 model_state: VecDeque::new(),
487 rendered_state: VecDeque::new(),
488 uid_counter: 1,
490 }
491 }
492
493 pub fn detach(self) -> FactoryVecDeque<C> {
495 let Self {
496 widget,
497 output_sender,
498 ..
499 } = self;
500 FactoryVecDeque {
501 widget,
502 output_sender,
503 components: VecDeque::new(),
504 model_state: VecDeque::new(),
505 rendered_state: VecDeque::new(),
506 uid_counter: 1,
508 }
509 }
510}
511
512#[derive(Debug)]
517pub struct FactoryVecDeque<C>
518where
519 C: FactoryComponent<Index = DynamicIndex>,
520{
521 widget: C::ParentWidget,
522 output_sender: Sender<C::Output>,
523 components: VecDeque<ComponentStorage<C>>,
524 model_state: VecDeque<ModelStateValue>,
525 rendered_state: VecDeque<RenderedState>,
526 uid_counter: usize,
527}
528
529impl<C> Drop for FactoryVecDeque<C>
530where
531 C: FactoryComponent<Index = DynamicIndex>,
532{
533 fn drop(&mut self) {
534 self.guard().clear();
535 }
536}
537
538impl<C> Index<usize> for FactoryVecDeque<C>
539where
540 C: FactoryComponent<Index = DynamicIndex>,
541{
542 type Output = C;
543
544 fn index(&self, index: usize) -> &Self::Output {
545 self.get(index).expect("Called `get` on an invalid index")
546 }
547}
548
549impl<C> FactoryVecDeque<C>
550where
551 C: FactoryComponent<Index = DynamicIndex>,
552{
553 #[must_use]
555 pub fn builder() -> FactoryVecDequeBuilder<C> {
556 FactoryVecDequeBuilder::new()
557 }
558
559 pub fn guard(&mut self) -> FactoryVecDequeGuard<'_, C> {
563 FactoryVecDequeGuard::new(self)
564 }
565
566 fn render_changes(&mut self) {
575 let mut first_position_change_idx = None;
576
577 let components = &mut self.components;
578 let rendered_state = &mut self.rendered_state;
579 for (index, state) in self.model_state.iter().enumerate() {
580 if state.uid == rendered_state.front().map(|r| r.uid).unwrap_or_default() {
581 rendered_state.pop_front();
583
584 if state.changed {
585 components[index].state_change_notify();
587 }
588 } else if let Some(rendered_index) =
589 rendered_state.iter().position(|r| r.uid == state.uid)
590 {
591 if first_position_change_idx.is_none() {
592 first_position_change_idx = Some(index);
593 }
594
595 rendered_state.remove(rendered_index);
597
598 let widget = components[index].returned_widget().unwrap();
600 if index == 0 {
601 self.widget.factory_move_start(widget);
602 } else {
603 let previous_widget = components[index - 1].returned_widget().unwrap();
604 self.widget.factory_move_after(widget, previous_widget);
605 }
606
607 if state.changed {
608 components[index].state_change_notify();
610 }
611 } else {
612 if first_position_change_idx.is_none() {
613 first_position_change_idx = Some(index);
614 }
615
616 let comp = &components[index];
618 let insert_widget = comp.widget();
619 let position = C::position(comp.get(), &state.index);
620 let returned_widget = if index == 0 {
621 self.widget.factory_prepend(insert_widget, &position)
622 } else {
623 let previous_widget = components[index - 1].returned_widget().unwrap();
624 self.widget
625 .factory_insert_after(insert_widget, &position, previous_widget)
626 };
627 let component = components.remove(index).unwrap();
628 let dyn_index = &self.model_state[index].index;
629 let component = component.launch(dyn_index, returned_widget).unwrap();
630 components.insert(index, component);
631 }
632 }
633
634 self.model_state.iter_mut().for_each(|s| s.changed = false);
636
637 self.rendered_state = self
640 .model_state
641 .iter()
642 .zip(components.iter())
643 .map(|(s, c)| {
644 let mut hasher = DefaultHasher::default();
645 c.returned_widget().unwrap().hash(&mut hasher);
646
647 RenderedState {
648 uid: s.uid,
649 #[cfg(feature = "libadwaita")]
650 widget_hash: hasher.finish(),
651 }
652 })
653 .collect();
654
655 if let Some(change_index) = first_position_change_idx {
656 for (index, comp) in components.iter().enumerate().skip(change_index) {
657 let position = C::position(comp.get(), &self.model_state[index].index);
658 self.widget
659 .factory_update_position(comp.returned_widget().unwrap(), &position);
660 }
661 }
662 }
663
664 pub fn len(&self) -> usize {
666 self.components.len()
667 }
668
669 pub fn is_empty(&self) -> bool {
671 self.components.is_empty()
672 }
673
674 pub fn send(&self, index: usize, msg: C::Input) {
676 self.components[index].send(msg);
677 }
678
679 pub fn broadcast(&self, msg: C::Input)
681 where
682 C::Input: Clone,
683 {
684 self.components.iter().for_each(|c| c.send(msg.clone()));
685 }
686
687 pub fn get(&self, index: usize) -> Option<&C> {
692 self.components.get(index).map(ComponentStorage::get)
693 }
694
695 pub fn back(&self) -> Option<&C> {
699 self.get(self.len().wrapping_sub(1))
700 }
701
702 pub fn front(&self) -> Option<&C> {
706 self.get(0)
707 }
708
709 pub const fn widget(&self) -> &C::ParentWidget {
711 &self.widget
712 }
713
714 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &C> + ExactSizeIterator + FusedIterator {
716 self.components.iter().map(ComponentStorage::get)
717 }
718
719 pub fn from_iter(
721 component_iter: impl IntoIterator<Item = C::Init>,
722 widget: C::ParentWidget,
723 ) -> Self {
724 let mut output = Self::builder().launch(widget).detach();
725 {
726 let mut edit = output.guard();
727 for component in component_iter {
728 edit.push_back(component);
729 }
730 edit.drop();
731 }
732 output
733 }
734 pub fn extend(&mut self, component_iter: impl IntoIterator<Item = C::Init>) {
739 let mut edit = self.guard();
741
742 for component in component_iter {
744 edit.push_back(component);
745 }
746 }
747}
748
749impl<C> Clone for FactoryVecDeque<C>
751where
752 C: CloneableFactoryComponent + FactoryComponent<Index = DynamicIndex>,
753{
754 fn clone(&self) -> Self {
755 let mut clone = FactoryVecDeque::builder()
757 .launch(self.widget.clone())
758 .detach();
759 for item in self.iter() {
761 let init = C::get_init(item);
763 clone.guard().push_back(init);
764 }
765 clone
767 }
768}
769
770impl<C> FactoryVecDeque<C>
771where
772 C: FactoryComponent<Index = DynamicIndex>,
773 C::ParentWidget: IsA<gtk::Stack>,
774 C::Root: IsA<gtk::Widget>,
775{
776 pub fn set_visible(&self, index: usize) -> bool {
779 if let Some(handle) = self.components.get(index) {
780 self.widget
781 .as_ref()
782 .set_visible_child(handle.widget().as_ref());
783 true
784 } else {
785 false
786 }
787 }
788}