relm4/extensions/
remove.rs

1use crate::{ContainerChild, RelmSetChildExt};
2use gtk::prelude::*;
3
4/// Widget types which can have widgets removed from them.
5pub trait RelmRemoveExt: ContainerChild {
6    /// Removes the widget from the container
7    /// if it is a child of the container.
8    fn container_remove(&self, child: &impl AsRef<Self::Child>);
9}
10
11impl<T> RelmRemoveExt for T
12where
13    T: RelmSetChildExt,
14    T::Child: AsRef<T::Child>,
15{
16    fn container_remove(&self, child: &impl AsRef<Self::Child>) {
17        if let Some(current_child) = self.container_get_child() {
18            let remove_child = child.as_ref().upcast_ref();
19            if remove_child == &current_child {
20                self.container_set_child(None::<&T::Child>);
21            }
22        }
23    }
24}
25
26impl RelmRemoveExt for gtk::ListBox {
27    fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
28        let row = widget.as_ref();
29        row.set_child(None::<&gtk::Widget>);
30        self.remove(row);
31    }
32}
33
34impl RelmRemoveExt for gtk::FlowBox {
35    fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
36        let child = widget.as_ref();
37        child.set_child(None::<&gtk::Widget>);
38        self.remove(widget.as_ref());
39    }
40}
41
42#[cfg(feature = "libadwaita")]
43#[cfg_attr(docsrs, doc(cfg(feature = "libadwaita")))]
44impl RelmRemoveExt for adw::PreferencesGroup {
45    fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
46        use adw::prelude::PreferencesGroupExt;
47        self.remove(widget.as_ref());
48    }
49}
50
51#[cfg(feature = "libadwaita")]
52#[cfg_attr(docsrs, doc(cfg(feature = "libadwaita")))]
53impl RelmRemoveExt for adw::ExpanderRow {
54    fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
55        use adw::prelude::ExpanderRowExt;
56
57        let child = widget.as_ref();
58        self.remove(child);
59    }
60}
61
62macro_rules! remove_impl {
63    ($($type:ty),+) => {
64        $(
65            impl $crate::extensions::RelmRemoveExt for $type {
66                fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
67                    self.remove(widget.as_ref());
68                }
69            }
70        )+
71    }
72}
73
74macro_rules! remove_child_impl {
75    ($($type:ty),+) => {
76        $(
77            #[allow(deprecated)]
78            impl $crate::extensions::RelmRemoveExt for $type {
79                fn container_remove(&self, widget: &impl AsRef<Self::Child>) {
80                    self.remove_child(widget.as_ref());
81                }
82            }
83        )+
84    }
85}
86
87remove_impl!(
88    gtk::Box,
89    gtk::Fixed,
90    gtk::Grid,
91    gtk::ActionBar,
92    gtk::Stack,
93    gtk::HeaderBar
94);
95remove_child_impl!(gtk::InfoBar);
96
97#[cfg(all(feature = "libadwaita", feature = "gnome_45"))]
98#[cfg_attr(docsrs, doc(cfg(all(feature = "libadwaita", feature = "gnome_45"))))]
99mod gnome_45 {
100    remove_impl!(adw::NavigationView);
101}
102
103/// Widget types that allow removal of all their children.
104pub trait RelmRemoveAllExt {
105    /// Remove all children from the container.
106    fn remove_all(&self);
107}
108
109impl<T> RelmRemoveAllExt for T
110where
111    T: RelmSetChildExt,
112    T::Child: AsRef<T::Child>,
113{
114    fn remove_all(&self) {
115        self.container_set_child(None::<&T::Child>);
116    }
117}
118
119macro_rules! remove_all_impl {
120    ($($type:ty),+) => {
121        $(
122            impl RelmRemoveAllExt for $type {
123                fn remove_all(&self) {
124                    while let Some(child) = self.last_child() {
125                        self.remove(&child);
126                    }
127                }
128            }
129        )+
130    }
131}
132
133remove_all_impl!(gtk::Box, gtk::FlowBox, gtk::Stack, gtk::Grid);
134
135impl RelmRemoveAllExt for gtk::ListBox {
136    fn remove_all(&self) {
137        while let Some(child) = self.last_child() {
138            let row = child
139                .downcast::<gtk::ListBoxRow>()
140                .expect("The child of `ListBox` is not a `ListBoxRow`.");
141            row.set_child(None::<&gtk::Widget>);
142            self.remove(&row);
143        }
144    }
145}
146
147#[cfg(feature = "libadwaita")]
148#[cfg_attr(docsrs, doc(cfg(feature = "libadwaita")))]
149impl RelmRemoveAllExt for adw::ExpanderRow {
150    fn remove_all(&self) {
151        use adw::prelude::ExpanderRowExt;
152
153        while let Some(child) = self.last_child() {
154            let row = child
155                .downcast::<gtk::ListBoxRow>()
156                .expect("The child of `ExpanderRow` is not a `ListBoxRow`.");
157            row.set_child(None::<&gtk::Widget>);
158            self.remove(&row);
159        }
160    }
161}