1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use glib::translate::*;
4 
5 use glib::subclass::prelude::*;
6 
7 use glib::Cast;
8 
9 use super::widget::WidgetImpl;
10 use crate::Container;
11 use crate::Widget;
12 use crate::WidgetPath;
13 
14 pub trait ContainerImpl: ContainerImplExt + WidgetImpl {
add(&self, container: &Self::Type, widget: &Widget)15     fn add(&self, container: &Self::Type, widget: &Widget) {
16         self.parent_add(container, widget)
17     }
18 
remove(&self, container: &Self::Type, widget: &Widget)19     fn remove(&self, container: &Self::Type, widget: &Widget) {
20         self.parent_remove(container, widget)
21     }
22 
check_resize(&self, container: &Self::Type)23     fn check_resize(&self, container: &Self::Type) {
24         self.parent_check_resize(container)
25     }
26 
set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>)27     fn set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>) {
28         self.parent_set_focus_child(container, widget)
29     }
30 
child_type(&self, container: &Self::Type) -> glib::Type31     fn child_type(&self, container: &Self::Type) -> glib::Type {
32         self.parent_child_type(container)
33     }
34 
35     #[doc(alias = "get_path_for_child")]
path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath36     fn path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath {
37         self.parent_path_for_child(container, widget)
38     }
39 
forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback)40     fn forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback) {
41         self.parent_forall(container, include_internals, callback);
42     }
43 }
44 
45 pub trait ContainerImplExt: ObjectSubclass {
parent_add(&self, container: &Self::Type, widget: &Widget)46     fn parent_add(&self, container: &Self::Type, widget: &Widget);
parent_remove(&self, container: &Self::Type, widget: &Widget)47     fn parent_remove(&self, container: &Self::Type, widget: &Widget);
parent_check_resize(&self, container: &Self::Type)48     fn parent_check_resize(&self, container: &Self::Type);
parent_set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>)49     fn parent_set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>);
parent_child_type(&self, container: &Self::Type) -> glib::Type50     fn parent_child_type(&self, container: &Self::Type) -> glib::Type;
parent_path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath51     fn parent_path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath;
parent_forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback)52     fn parent_forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback);
53 }
54 
55 impl<T: ContainerImpl> ContainerImplExt for T {
parent_add(&self, container: &Self::Type, widget: &Widget)56     fn parent_add(&self, container: &Self::Type, widget: &Widget) {
57         unsafe {
58             let data = T::type_data();
59             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
60             if let Some(f) = (*parent_class).add {
61                 f(
62                     container.unsafe_cast_ref::<Container>().to_glib_none().0,
63                     widget.to_glib_none().0,
64                 )
65             }
66         }
67     }
68 
parent_remove(&self, container: &Self::Type, widget: &Widget)69     fn parent_remove(&self, container: &Self::Type, widget: &Widget) {
70         unsafe {
71             let data = T::type_data();
72             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
73             if let Some(f) = (*parent_class).remove {
74                 f(
75                     container.unsafe_cast_ref::<Container>().to_glib_none().0,
76                     widget.to_glib_none().0,
77                 )
78             }
79         }
80     }
81 
parent_check_resize(&self, container: &Self::Type)82     fn parent_check_resize(&self, container: &Self::Type) {
83         unsafe {
84             let data = T::type_data();
85             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
86             if let Some(f) = (*parent_class).check_resize {
87                 f(container.unsafe_cast_ref::<Container>().to_glib_none().0)
88             }
89         }
90     }
91 
parent_set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>)92     fn parent_set_focus_child(&self, container: &Self::Type, widget: Option<&Widget>) {
93         unsafe {
94             let data = T::type_data();
95             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
96             if let Some(f) = (*parent_class).set_focus_child {
97                 f(
98                     container.unsafe_cast_ref::<Container>().to_glib_none().0,
99                     widget.to_glib_none().0,
100                 )
101             }
102         }
103     }
104 
parent_child_type(&self, container: &Self::Type) -> glib::Type105     fn parent_child_type(&self, container: &Self::Type) -> glib::Type {
106         unsafe {
107             let data = T::type_data();
108             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
109             if let Some(f) = (*parent_class).child_type {
110                 from_glib(f(container.unsafe_cast_ref::<Container>().to_glib_none().0))
111             } else {
112                 glib::Type::UNIT
113             }
114         }
115     }
116 
parent_path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath117     fn parent_path_for_child(&self, container: &Self::Type, widget: &Widget) -> WidgetPath {
118         unsafe {
119             let data = T::type_data();
120             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
121             let f = (*parent_class)
122                 .get_path_for_child
123                 .expect("No parent class impl for \"get_path_for_child\"");
124             from_glib_none(f(
125                 container.unsafe_cast_ref::<Container>().to_glib_none().0,
126                 widget.to_glib_none().0,
127             ))
128         }
129     }
130 
parent_forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback)131     fn parent_forall(&self, container: &Self::Type, include_internals: bool, callback: &Callback) {
132         unsafe {
133             let data = T::type_data();
134             let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
135             if let Some(f) = (*parent_class).forall {
136                 f(
137                     container.unsafe_cast_ref::<Container>().to_glib_none().0,
138                     include_internals.into_glib(),
139                     callback.callback,
140                     callback.user_data,
141                 )
142             }
143         }
144     }
145 }
146 
147 unsafe impl<T: ContainerImpl> IsSubclassable<T> for Container {
class_init(class: &mut ::glib::Class<Self>)148     fn class_init(class: &mut ::glib::Class<Self>) {
149         <Widget as IsSubclassable<T>>::class_init(class);
150 
151         let klass = class.as_mut();
152         klass.add = Some(container_add::<T>);
153         klass.remove = Some(container_remove::<T>);
154         klass.check_resize = Some(container_check_resize::<T>);
155         klass.set_focus_child = Some(container_set_focus_child::<T>);
156         klass.child_type = Some(container_child_type::<T>);
157         klass.get_path_for_child = Some(container_get_path_for_child::<T>);
158         klass.forall = Some(container_forall::<T>);
159     }
160 
instance_init(instance: &mut glib::subclass::InitializingObject<T>)161     fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) {
162         <Widget as IsSubclassable<T>>::instance_init(instance);
163     }
164 }
165 
container_add<T: ContainerImpl>( ptr: *mut ffi::GtkContainer, wdgtptr: *mut ffi::GtkWidget, )166 unsafe extern "C" fn container_add<T: ContainerImpl>(
167     ptr: *mut ffi::GtkContainer,
168     wdgtptr: *mut ffi::GtkWidget,
169 ) {
170     let instance = &*(ptr as *mut T::Instance);
171     let imp = instance.impl_();
172     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
173     let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
174 
175     imp.add(wrap.unsafe_cast_ref(), &widget)
176 }
177 
container_remove<T: ContainerImpl>( ptr: *mut ffi::GtkContainer, wdgtptr: *mut ffi::GtkWidget, )178 unsafe extern "C" fn container_remove<T: ContainerImpl>(
179     ptr: *mut ffi::GtkContainer,
180     wdgtptr: *mut ffi::GtkWidget,
181 ) {
182     let instance = &*(ptr as *mut T::Instance);
183     let imp = instance.impl_();
184     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
185     let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
186 
187     imp.remove(wrap.unsafe_cast_ref(), &widget)
188 }
189 
container_check_resize<T: ContainerImpl>(ptr: *mut ffi::GtkContainer)190 unsafe extern "C" fn container_check_resize<T: ContainerImpl>(ptr: *mut ffi::GtkContainer) {
191     let instance = &*(ptr as *mut T::Instance);
192     let imp = instance.impl_();
193     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
194 
195     imp.check_resize(wrap.unsafe_cast_ref())
196 }
197 
container_set_focus_child<T: ContainerImpl>( ptr: *mut ffi::GtkContainer, wdgtptr: *mut ffi::GtkWidget, )198 unsafe extern "C" fn container_set_focus_child<T: ContainerImpl>(
199     ptr: *mut ffi::GtkContainer,
200     wdgtptr: *mut ffi::GtkWidget,
201 ) {
202     let instance = &*(ptr as *mut T::Instance);
203     let imp = instance.impl_();
204     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
205     let widget: Borrowed<Option<Widget>> = from_glib_borrow(wdgtptr);
206 
207     imp.set_focus_child(wrap.unsafe_cast_ref(), widget.as_ref().as_ref())
208 }
209 
container_child_type<T: ContainerImpl>( ptr: *mut ffi::GtkContainer, ) -> glib::ffi::GType210 unsafe extern "C" fn container_child_type<T: ContainerImpl>(
211     ptr: *mut ffi::GtkContainer,
212 ) -> glib::ffi::GType {
213     let instance = &*(ptr as *mut T::Instance);
214     let imp = instance.impl_();
215     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
216 
217     imp.child_type(wrap.unsafe_cast_ref()).into_glib()
218 }
219 
container_get_path_for_child<T: ContainerImpl>( ptr: *mut ffi::GtkContainer, wdgtptr: *mut ffi::GtkWidget, ) -> *mut ffi::GtkWidgetPath220 unsafe extern "C" fn container_get_path_for_child<T: ContainerImpl>(
221     ptr: *mut ffi::GtkContainer,
222     wdgtptr: *mut ffi::GtkWidget,
223 ) -> *mut ffi::GtkWidgetPath {
224     let instance = &*(ptr as *mut T::Instance);
225     let imp = instance.impl_();
226     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
227     let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
228 
229     imp.path_for_child(wrap.unsafe_cast_ref(), &widget)
230         .to_glib_none()
231         .0
232 }
233 
container_forall<T: ObjectSubclass>( ptr: *mut ffi::GtkContainer, include_internals: glib::ffi::gboolean, callback: ffi::GtkCallback, user_data: glib::ffi::gpointer, ) where T: ContainerImpl,234 unsafe extern "C" fn container_forall<T: ObjectSubclass>(
235     ptr: *mut ffi::GtkContainer,
236     include_internals: glib::ffi::gboolean,
237     callback: ffi::GtkCallback,
238     user_data: glib::ffi::gpointer,
239 ) where
240     T: ContainerImpl,
241 {
242     let instance = &*(ptr as *mut T::Instance);
243     let imp = instance.impl_();
244     let wrap: Borrowed<Container> = from_glib_borrow(ptr);
245     let callback = Callback {
246         callback,
247         user_data,
248     };
249 
250     imp.forall(
251         wrap.unsafe_cast_ref(),
252         from_glib(include_internals),
253         &callback,
254     )
255 }
256 
257 #[derive(Debug)]
258 pub struct Callback {
259     callback: ffi::GtkCallback,
260     user_data: glib::ffi::gpointer,
261 }
262 
263 impl Callback {
call(&self, widget: &Widget)264     pub fn call(&self, widget: &Widget) {
265         unsafe {
266             if let Some(callback) = self.callback {
267                 callback(widget.to_glib_none().0, self.user_data);
268             }
269         }
270     }
271 }
272 
273 pub unsafe trait ContainerClassSubclassExt: ClassStruct {
274     #[doc(alias = "gtk_container_class_handle_border_width")]
handle_border_width(&mut self)275     fn handle_border_width(&mut self) {
276         unsafe {
277             let widget_class = self as *mut _ as *mut ffi::GtkContainerClass;
278             ffi::gtk_container_class_handle_border_width(widget_class);
279         }
280     }
281 }
282 
283 unsafe impl<T: ClassStruct> ContainerClassSubclassExt for T where T::Type: ContainerImpl {}
284