Skip to main content

kas_widgets/
list.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! A row or column with run-time adjustable contents
7
8use kas::Collection;
9use kas::dir::{Down, Right};
10use kas::layout::{
11    DynRowStorage, RowPositionSolver, RowSetter, RowSolver, RowStorage, RulesSetter, RulesSolver,
12};
13use kas::prelude::*;
14use std::collections::hash_map::{Entry, HashMap};
15use std::ops::{Index, IndexMut};
16
17/// Make a [`Row`] widget
18///
19/// # Syntax
20///
21/// > _Collection_ :\
22/// > &nbsp;&nbsp; `row!` `[` _Items_<sup>\?</sup> `]`
23/// >
24/// > _Items_ :\
25/// > &nbsp;&nbsp; (_Item_ `,`)<sup>\*</sup> _Item_ `,`<sup>\?</sup>
26///
27/// ## Stand-alone usage
28///
29/// When used as a stand-alone macro, `row! [/* ... */]` is just syntactic sugar
30/// for `Row::new(kas::collection! [/* ... */])`.
31///
32/// In this case, _Item_ may be:
33///
34/// -   A string literal (interpreted as a label widget), optionally followed by
35///     any of the following method calls: [`align`], [`pack`], [`with_stretch`]
36/// -   An expression yielding an object implementing `Widget<Data = _A>`
37///
38/// In case all _Item_ instances are a string literal, the data type of the
39/// `row!` widget will be `()`; otherwise the data type of the widget is `_A`
40/// where `_A` is a generic type parameter of the widget.
41///
42/// ## Usage within widget layout syntax
43///
44/// When called within [widget layout syntax], `row!` may be evaluated as a
45/// recursive macro and the result does not have a specified type, except that
46/// methods [`map_any`], [`align`], [`pack`] and [`with_stretch`] are supported via
47/// emulation.
48///
49/// In this case, _Item_ is evaluated using [widget layout syntax]. This is
50/// broadly similar to the above with a couple of exceptions:
51///
52/// -   Supported layout macros do not need to be imported to the module scope
53/// -   An _Item_ may be a `#[widget]` field of the widget
54///
55/// # Example
56///
57/// ```
58/// let my_widget = kas_widgets::row!["one", "two"];
59/// ```
60///
61/// [widget layout syntax]: macro@kas::layout
62/// [`map_any`]: crate::AdaptWidgetAny::map_any
63/// [`align`]: crate::AdaptWidget::align
64/// [`pack`]: crate::AdaptWidget::pack
65/// [`with_stretch`]: crate::AdaptWidget::with_stretch
66#[macro_export]
67macro_rules! row {
68    ( $( $ee:expr ),* ) => {
69        $crate::Row::new( ::kas::collection! [ $( $ee ),* ] )
70    };
71    ( $( $ee:expr ),+ , ) => {
72        $crate::Row::new( ::kas::collection! [ $( $ee ),+ ] )
73    };
74}
75
76/// Make a [`Column`] widget
77///
78/// # Syntax
79///
80/// > _Collection_ :\
81/// > &nbsp;&nbsp; `column!` `[` _Items_<sup>\?</sup> `]`
82/// >
83/// > _Items_ :\
84/// > &nbsp;&nbsp; (_Item_ `,`)<sup>\*</sup> _Item_ `,`<sup>\?</sup>
85///
86/// ## Stand-alone usage
87///
88/// When used as a stand-alone macro, `column! [/* ... */]` is just syntactic sugar
89/// for `Column::new(kas::collection! [/* ... */])`.
90///
91/// In this case, _Item_ may be:
92///
93/// -   A string literal (interpreted as a label widget), optionally followed by
94///     any of the following method calls: [`align`], [`pack`], [`with_stretch`]
95/// -   An expression yielding an object implementing `Widget<Data = _A>`
96///
97/// In case all _Item_ instances are a string literal, the data type of the
98/// `column!` widget will be `()`; otherwise the data type of the widget is `_A`
99/// where `_A` is a generic type parameter of the widget.
100///
101/// ## Usage within widget layout syntax
102///
103/// When called within [widget layout syntax], `column!` may be evaluated as a
104/// recursive macro and the result does not have a specified type, except that
105/// methods [`map_any`], [`align`], [`pack`] and [`with_stretch`] are supported via
106/// emulation.
107///
108/// In this case, _Item_ is evaluated using [widget layout syntax]. This is
109/// broadly similar to the above with a couple of exceptions:
110///
111/// -   Supported layout macros do not need to be imported to the module scope
112/// -   An _Item_ may be a `#[widget]` field of the widget
113///
114/// # Example
115///
116/// ```
117/// let my_widget = kas_widgets::column! [
118///     "one",
119///     "two",
120/// ];
121/// ```
122///
123/// [widget layout syntax]: macro@kas::layout
124/// [`map_any`]: crate::AdaptWidgetAny::map_any
125/// [`align`]: crate::AdaptWidget::align
126/// [`pack`]: crate::AdaptWidget::pack
127/// [`with_stretch`]: crate::AdaptWidget::with_stretch
128#[macro_export]
129macro_rules! column {
130    ( $( $ee:expr ),* ) => {
131        $crate::Column::new( ::kas::collection! [ $( $ee ),* ] )
132    };
133    ( $( $ee:expr ),+ , ) => {
134        $crate::Column::new( ::kas::collection! [ $( $ee ),+ ] )
135    };
136}
137
138/// Make a [`List`] widget
139///
140/// # Syntax
141///
142/// > _Collection_ :\
143/// > &nbsp;&nbsp; `list!` `[` _Items_<sup>\?</sup> `]`
144/// >
145/// > _Items_ :\
146/// > &nbsp;&nbsp; (_Item_ `,`)<sup>\*</sup> _Item_ `,`<sup>\?</sup>
147///
148/// ## Stand-alone usage
149///
150/// When used as a stand-alone macro, `list! [/* ... */]` is just syntactic sugar
151/// for `List::new(kas::collection! [/* ... */])`.
152///
153/// In this case, _Item_ may be:
154///
155/// -   A string literal (interpreted as a label widget), optionally followed by
156///     any of the following method calls: [`align`], [`pack`], [`with_stretch`]
157/// -   An expression yielding an object implementing `Widget<Data = _A>`
158///
159/// In case all _Item_ instances are a string literal, the data type of the
160/// `list!` widget will be `()`; otherwise the data type of the widget is `_A`
161/// where `_A` is a generic type parameter of the widget.
162///
163/// ## Usage within widget layout syntax
164///
165/// When called within [widget layout syntax], `list!` may be evaluated as a
166/// recursive macro and the result does not have a specified type, except that
167/// methods [`map_any`], [`align`], [`pack`], [`with_stretch`] and [`with_direction`] are
168/// supported via emulation. In this case, calling [`with_direction`] is
169/// required. Note that the argument passed to [`with_direction`] is expanded
170/// at the use site, so for example `.with_direction(self.dir)` will read
171/// `self.dir` whenever layout is computed.
172///
173/// In this case, _Item_ is evaluated using [widget layout syntax]. This is
174/// broadly similar to the above with a couple of exceptions:
175///
176/// -   Supported layout macros do not need to be imported to the module scope
177/// -   An _Item_ may be a `#[widget]` field of the widget
178///
179/// # Example
180///
181/// ```
182/// let my_widget = kas_widgets::list! ["one", "two"]
183///     .with_direction(kas::dir::Left);
184/// ```
185///
186/// [widget layout syntax]: macro@kas::layout
187/// [`map_any`]: crate::AdaptWidgetAny::map_any
188/// [`align`]: crate::AdaptWidget::align
189/// [`pack`]: crate::AdaptWidget::pack
190/// [`with_stretch`]: crate::AdaptWidget::with_stretch
191/// [`with_direction`]: List::with_direction
192#[macro_export]
193macro_rules! list {
194    ( $( $ee:expr ),* ) => {
195        $crate::List::new( ::kas::collection! [ $( $ee ),* ] )
196    };
197    ( $( $ee:expr ),+ , ) => {
198        $crate::List::new( ::kas::collection! [ $( $ee ),+ ] )
199    };
200}
201
202/// A generic row widget
203///
204/// See documentation of [`List`] type.
205pub type Row<C> = List<C, Right>;
206
207/// A generic column widget
208///
209/// See documentation of [`List`] type.
210pub type Column<C> = List<C, Down>;
211
212#[impl_self]
213mod List {
214    /// A generic row/column widget
215    ///
216    /// A linear widget over a [`Collection`] of widgets.
217    ///
218    /// When the collection uses [`Vec`], various methods to insert/remove
219    /// elements are available.
220    ///
221    /// The layout direction `D` may be compile-time fixed (e.g. [`Right`]) or
222    /// run-time mutable ([`Direction`]); in the latter case
223    /// [`set_direction`] is available.
224    ///
225    /// ## See also
226    ///
227    /// [`Row`] and [`Column`] are type-defs to `List` which fix the direction `D`.
228    ///
229    /// The macros [`row!`] and [`column!`] also create row/column
230    /// layouts, but are not fully equivalent:
231    ///
232    /// -   `row!` and `column!` generate anonymous layout widgets (or objects).
233    ///     These do not have a [`set_direction`] method or support adding or
234    ///     removing elements.
235    /// -   `row!` and `column!` generate layout objects which, when used within
236    ///     a custom widget, may refer to that widget's fields.
237    ///
238    /// ## Performance
239    ///
240    /// Configuring and resizing elements is O(n) in the number of children.
241    /// Drawing and event handling is O(log n) in the number of children (assuming
242    /// only a small number are visible at any one time).
243    ///
244    /// ## Example
245    ///
246    /// ```
247    /// use kas::collection;
248    /// # use kas_widgets::{CheckBox, List};
249    ///
250    /// let list = List::right(collection![
251    ///     "A checkbox",
252    ///     CheckBox::new(|_, state: &bool| *state),
253    /// ]);
254    /// ```
255    ///
256    /// [`row!`]: crate::row
257    /// [`column!`]: crate::column
258    /// [`set_direction`]: List::set_direction
259    #[autoimpl(Default where C: Default, D: Default)]
260    #[widget]
261    pub struct List<C: Collection, D: Directional> {
262        pub(crate) core: widget_core!(),
263        pub(crate) layout: DynRowStorage,
264        #[collection]
265        pub(crate) widgets: C,
266        pub(crate) direction: D,
267        next: usize,
268        id_map: HashMap<usize, usize>, // map key of Id to index
269    }
270
271    impl Layout for Self {
272        fn size_rules(&mut self, cx: &mut SizeCx, axis: AxisInfo) -> SizeRules {
273            let dim = (self.direction, self.widgets.len());
274            let mut solver = RowSolver::new(axis, dim, &mut self.layout);
275            for n in 0..self.widgets.len() {
276                if let Some(child) = self.widgets.get_mut_tile(n) {
277                    solver.for_child(&mut self.layout, n, |axis| child.size_rules(cx, axis));
278                }
279            }
280            solver.finish(&mut self.layout)
281        }
282
283        fn set_rect(&mut self, cx: &mut SizeCx, rect: Rect, hints: AlignHints) {
284            self.core.set_rect(rect);
285            let dim = (self.direction, self.widgets.len());
286            let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, &mut self.layout);
287
288            for n in 0..self.widgets.len() {
289                if let Some(child) = self.widgets.get_mut_tile(n) {
290                    child.set_rect(cx, setter.child_rect(&mut self.layout, n), hints);
291                }
292            }
293        }
294
295        fn draw(&self, mut draw: DrawCx) {
296            let solver = RowPositionSolver::new(self.direction);
297            solver.for_children(&self.widgets, draw.get_clip_rect(), |w| w.draw(draw.re()));
298        }
299    }
300
301    impl Tile for Self {
302        fn role(&self, _: &mut dyn RoleCx) -> Role<'_> {
303            Role::None
304        }
305
306        fn find_child_index(&self, id: &Id) -> Option<usize> {
307            id.next_key_after(self.id_ref())
308                .and_then(|k| self.id_map.get(&k).cloned())
309        }
310    }
311
312    impl Events for Self {
313        type Data = C::Data;
314
315        /// Make a fresh id based on `self.next` then insert into `self.id_map`
316        fn make_child_id(&mut self, index: usize) -> Id {
317            if let Some(child) = self.widgets.get_tile(index) {
318                // Use the widget's existing identifier, if valid
319                if child.id_ref().is_valid() {
320                    if let Some(key) = child.id_ref().next_key_after(self.id_ref()) {
321                        if let Entry::Vacant(entry) = self.id_map.entry(key) {
322                            entry.insert(index);
323                            return child.id();
324                        }
325                    }
326                }
327            }
328
329            loop {
330                let key = self.next;
331                self.next += 1;
332                if let Entry::Vacant(entry) = self.id_map.entry(key) {
333                    entry.insert(index);
334                    return self.id_ref().make_child(key);
335                }
336            }
337        }
338
339        fn probe(&self, coord: Coord) -> Id {
340            let solver = RowPositionSolver::new(self.direction);
341            solver
342                .find_child(&self.widgets, coord)
343                .and_then(|child| child.try_probe(coord))
344                .unwrap_or_else(|| self.id())
345        }
346
347        fn configure(&mut self, _: &mut ConfigCx) {
348            // All children will be re-configured which will rebuild id_map
349            self.id_map.clear();
350        }
351    }
352
353    impl Self
354    where
355        D: Default,
356    {
357        /// Construct a new instance with default-constructed direction
358        ///
359        /// This constructor is available where the direction is determined by the
360        /// type: for `D: Directional + Default`. In other cases, use
361        /// [`Self::new_dir`].
362        ///
363        /// # Examples
364        ///
365        /// Where widgets have the same type and the length is fixed, an array
366        /// may be used:
367        /// ```
368        /// use kas_widgets::{Label, Row};
369        /// let _ = Row::new([Label::new("left"), Label::new("right")]);
370        /// ```
371        ///
372        /// To support run-time insertion/deletion, use [`Vec`]:
373        /// ```
374        /// use kas_widgets::{AdaptWidget, Button, Row};
375        ///
376        /// #[derive(Clone, Debug)]
377        /// enum Msg {
378        ///     Add,
379        ///     Remove,
380        /// }
381        ///
382        /// let _ = Row::new(vec![Button::label_msg("Add", Msg::Add)])
383        ///     .on_messages(|cx, row, data| {
384        ///         if let Some(msg) = cx.try_pop() {
385        ///             match msg {
386        ///                 Msg::Add => {
387        ///                     let button = if row.len() % 2 == 0 {
388        ///                         Button::label_msg("Add", Msg::Add)
389        ///                     } else {
390        ///                         Button::label_msg("Remove", Msg::Remove)
391        ///                     };
392        ///                     row.push(cx, data, button);
393        ///                 }
394        ///                 Msg::Remove => {
395        ///                     let _ = row.pop(cx);
396        ///                 }
397        ///             }
398        ///         }
399        ///     });
400        /// ```
401        #[inline]
402        pub fn new(widgets: C) -> Self {
403            Self::new_dir(widgets, D::default())
404        }
405    }
406
407    impl<C: Collection> List<C, kas::dir::Left> {
408        /// Construct a new instance with fixed direction
409        #[inline]
410        pub fn left(widgets: C) -> Self {
411            Self::new(widgets)
412        }
413    }
414    impl<C: Collection> List<C, kas::dir::Right> {
415        /// Construct a new instance with fixed direction
416        #[inline]
417        pub fn right(widgets: C) -> Self {
418            Self::new(widgets)
419        }
420    }
421    impl<C: Collection> List<C, kas::dir::Up> {
422        /// Construct a new instance with fixed direction
423        #[inline]
424        pub fn up(widgets: C) -> Self {
425            Self::new(widgets)
426        }
427    }
428    impl<C: Collection> List<C, kas::dir::Down> {
429        /// Construct a new instance with fixed direction
430        #[inline]
431        pub fn down(widgets: C) -> Self {
432            Self::new(widgets)
433        }
434    }
435
436    impl<C: Collection, D: Directional + Eq> List<C, D> {
437        /// Set the direction of contents
438        pub fn set_direction(&mut self, cx: &mut ConfigCx, direction: D) {
439            if direction == self.direction {
440                return;
441            }
442
443            self.direction = direction;
444            cx.resize();
445        }
446    }
447
448    impl Self {
449        /// Construct a new instance with explicit direction
450        #[inline]
451        pub fn new_dir(widgets: C, direction: D) -> Self {
452            List {
453                core: Default::default(),
454                layout: Default::default(),
455                widgets,
456                direction,
457                next: 0,
458                id_map: Default::default(),
459            }
460        }
461
462        /// Get the direction of contents
463        pub fn direction(&self) -> Direction {
464            self.direction.as_direction()
465        }
466
467        /// Set the direction of contents (inline)
468        #[inline]
469        pub fn with_direction(mut self, direction: D) -> Self {
470            self.direction = direction;
471            self
472        }
473
474        /// Access layout storage
475        ///
476        /// The number of columns/rows is [`Self::len`].
477        #[inline]
478        pub fn layout_storage(&mut self) -> &mut (impl RowStorage + use<C, D>) {
479            &mut self.layout
480        }
481
482        /// True if there are no child widgets
483        pub fn is_empty(&self) -> bool {
484            self.widgets.is_empty()
485        }
486
487        /// Returns the number of child widgets
488        pub fn len(&self) -> usize {
489            self.widgets.len()
490        }
491    }
492
493    impl<W: Widget, D: Directional> List<Vec<W>, D> {
494        /// Returns a reference to the child, if any
495        pub fn get(&self, index: usize) -> Option<&W> {
496            self.widgets.get(index)
497        }
498
499        /// Returns a mutable reference to the child, if any
500        pub fn get_mut(&mut self, index: usize) -> Option<&mut W> {
501            self.widgets.get_mut(index)
502        }
503
504        /// Remove all child widgets
505        pub fn clear(&mut self) {
506            self.widgets.clear();
507        }
508
509        /// Append a child widget
510        ///
511        /// The new child is configured immediately. Triggers a resize.
512        ///
513        /// Returns the new element's index.
514        pub fn push(&mut self, cx: &mut ConfigCx, data: &W::Data, mut widget: W) -> usize {
515            let index = self.widgets.len();
516            let id = self.make_child_id(index);
517            cx.configure(widget.as_node(data), id);
518            self.widgets.push(widget);
519
520            cx.resize();
521            index
522        }
523
524        /// Remove the last child widget (if any) and return
525        ///
526        /// Triggers a resize.
527        pub fn pop(&mut self, cx: &mut ConfigCx) -> Option<W> {
528            let result = self.widgets.pop();
529            if let Some(w) = result.as_ref() {
530                cx.resize();
531
532                if w.id_ref().is_valid() {
533                    if let Some(key) = w.id_ref().next_key_after(self.id_ref()) {
534                        self.id_map.remove(&key);
535                    }
536                }
537            }
538            result
539        }
540
541        /// Inserts a child widget position `index`
542        ///
543        /// Panics if `index > len`.
544        ///
545        /// The new child is configured immediately. Triggers a resize.
546        pub fn insert(&mut self, cx: &mut ConfigCx, data: &W::Data, index: usize, mut widget: W) {
547            for v in self.id_map.values_mut() {
548                if *v >= index {
549                    *v += 1;
550                }
551            }
552
553            let id = self.make_child_id(index);
554            cx.configure(widget.as_node(data), id);
555            self.widgets.insert(index, widget);
556            cx.resize();
557        }
558
559        /// Removes the child widget at position `index`
560        ///
561        /// Panics if `index` is out of bounds.
562        ///
563        /// Triggers a resize.
564        pub fn remove(&mut self, cx: &mut ConfigCx, index: usize) -> W {
565            let w = self.widgets.remove(index);
566            if w.id_ref().is_valid() {
567                if let Some(key) = w.id_ref().next_key_after(self.id_ref()) {
568                    self.id_map.remove(&key);
569                }
570            }
571
572            cx.resize();
573
574            for v in self.id_map.values_mut() {
575                if *v > index {
576                    *v -= 1;
577                }
578            }
579            w
580        }
581
582        /// Removes all children at positions ≥ `len`
583        ///
584        /// Does nothing if `self.len() < len`.
585        ///
586        /// Triggers a resize.
587        pub fn truncate(&mut self, cx: &mut ConfigCx, len: usize) {
588            if len < self.len() {
589                cx.resize();
590                loop {
591                    let w = self.widgets.pop().unwrap();
592                    if w.id_ref().is_valid() {
593                        if let Some(key) = w.id_ref().next_key_after(self.id_ref()) {
594                            self.id_map.remove(&key);
595                        }
596                    }
597                    if len == self.widgets.len() {
598                        return;
599                    }
600                }
601            }
602        }
603
604        /// Replace the child at `index`
605        ///
606        /// Panics if `index` is out of bounds.
607        ///
608        /// The new child is configured immediately. Triggers a resize.
609        pub fn replace(&mut self, cx: &mut ConfigCx, data: &W::Data, index: usize, mut w: W) -> W {
610            let id = self.make_child_id(index);
611            cx.configure(w.as_node(data), id);
612            std::mem::swap(&mut w, &mut self.widgets[index]);
613
614            if w.id_ref().is_valid() {
615                if let Some(key) = w.id_ref().next_key_after(self.id_ref()) {
616                    self.id_map.remove(&key);
617                }
618            }
619
620            cx.resize();
621
622            w
623        }
624
625        /// Append child widgets from an iterator
626        ///
627        /// New children are configured immediately. Triggers a resize.
628        pub fn extend<T>(&mut self, cx: &mut ConfigCx, data: &W::Data, iter: T)
629        where
630            T: IntoIterator<Item = W>,
631        {
632            let iter = iter.into_iter();
633            if let Some(ub) = iter.size_hint().1 {
634                self.widgets.reserve(ub);
635            }
636            for mut w in iter {
637                let id = self.make_child_id(self.widgets.len());
638                cx.configure(w.as_node(data), id);
639                self.widgets.push(w);
640            }
641
642            cx.resize();
643        }
644
645        /// Resize, using the given closure to construct new widgets
646        ///
647        /// New children are configured immediately. Triggers a resize.
648        pub fn resize_with<F>(&mut self, cx: &mut ConfigCx, data: &W::Data, len: usize, f: F)
649        where
650            F: Fn(usize) -> W,
651        {
652            let old_len = self.widgets.len();
653
654            if len < old_len {
655                cx.resize();
656                loop {
657                    let w = self.widgets.pop().unwrap();
658                    if w.id_ref().is_valid() {
659                        if let Some(key) = w.id_ref().next_key_after(self.id_ref()) {
660                            self.id_map.remove(&key);
661                        }
662                    }
663                    if len == self.widgets.len() {
664                        return;
665                    }
666                }
667            }
668
669            if len > old_len {
670                self.widgets.reserve(len - old_len);
671                for index in old_len..len {
672                    let id = self.make_child_id(index);
673                    let mut w = f(index);
674                    cx.configure(w.as_node(data), id);
675                    self.widgets.push(w);
676                }
677                cx.resize();
678            }
679        }
680
681        /// Iterate over childern
682        pub fn iter(&self) -> impl Iterator<Item = &W> {
683            ListIter {
684                list: &self.widgets,
685            }
686        }
687
688        /// Mutably iterate over childern
689        pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut W> {
690            ListIterMut {
691                list: &mut self.widgets,
692            }
693        }
694    }
695
696    impl<W: Widget, D: Directional> Index<usize> for List<Vec<W>, D> {
697        type Output = W;
698
699        fn index(&self, index: usize) -> &Self::Output {
700            &self.widgets[index]
701        }
702    }
703
704    impl<W: Widget, D: Directional> IndexMut<usize> for List<Vec<W>, D> {
705        fn index_mut(&mut self, index: usize) -> &mut Self::Output {
706            &mut self.widgets[index]
707        }
708    }
709}
710
711struct ListIter<'a, W: Widget> {
712    list: &'a [W],
713}
714impl<'a, W: Widget> Iterator for ListIter<'a, W> {
715    type Item = &'a W;
716    fn next(&mut self) -> Option<Self::Item> {
717        if let Some((first, rest)) = self.list.split_first() {
718            self.list = rest;
719            Some(first)
720        } else {
721            None
722        }
723    }
724    fn size_hint(&self) -> (usize, Option<usize>) {
725        let len = self.len();
726        (len, Some(len))
727    }
728}
729impl<'a, W: Widget> ExactSizeIterator for ListIter<'a, W> {
730    fn len(&self) -> usize {
731        self.list.len()
732    }
733}
734
735struct ListIterMut<'a, W: Widget> {
736    list: &'a mut [W],
737}
738impl<'a, W: Widget> Iterator for ListIterMut<'a, W> {
739    type Item = &'a mut W;
740    fn next(&mut self) -> Option<Self::Item> {
741        let list = std::mem::take(&mut self.list);
742        if let Some((first, rest)) = list.split_first_mut() {
743            self.list = rest;
744            Some(first)
745        } else {
746            None
747        }
748    }
749    fn size_hint(&self) -> (usize, Option<usize>) {
750        let len = self.len();
751        (len, Some(len))
752    }
753}
754impl<'a, W: Widget> ExactSizeIterator for ListIterMut<'a, W> {
755    fn len(&self) -> usize {
756        self.list.len()
757    }
758}