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