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