gtk/subclass/
container.rs1use glib::translate::*;
4
5use glib::subclass::prelude::*;
6
7use glib::object::Cast;
8
9use super::widget::WidgetImpl;
10use crate::Widget;
11use crate::WidgetPath;
12use crate::{Container, ffi};
13
14pub trait ContainerImpl: ContainerImplExt + WidgetImpl {
15 fn add(&self, widget: &Widget) {
30 self.parent_add(widget)
31 }
32
33 fn remove(&self, widget: &Widget) {
45 self.parent_remove(widget)
46 }
47
48 fn check_resize(&self) {
50 self.parent_check_resize()
51 }
52
53 fn set_focus_child(&self, widget: Option<&Widget>) {
64 self.parent_set_focus_child(widget)
65 }
66
67 fn child_type(&self) -> glib::Type {
77 self.parent_child_type()
78 }
79
80 #[doc(alias = "get_path_for_child")]
89 fn path_for_child(&self, widget: &Widget) -> WidgetPath {
90 self.parent_path_for_child(widget)
91 }
92
93 fn forall(&self, include_internals: bool, callback: &Callback) {
106 self.parent_forall(include_internals, callback);
107 }
108}
109
110mod sealed {
111 pub trait Sealed {}
112 impl<T: super::ContainerImpl> Sealed for T {}
113}
114
115pub trait ContainerImplExt: ObjectSubclass + sealed::Sealed {
116 fn parent_add(&self, widget: &Widget) {
117 unsafe {
118 let data = Self::type_data();
119 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
120 if let Some(f) = (*parent_class).add {
121 f(
122 self.obj().unsafe_cast_ref::<Container>().to_glib_none().0,
123 widget.to_glib_none().0,
124 )
125 }
126 }
127 }
128 fn parent_remove(&self, widget: &Widget) {
129 unsafe {
130 let data = Self::type_data();
131 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
132 if let Some(f) = (*parent_class).remove {
133 f(
134 self.obj().unsafe_cast_ref::<Container>().to_glib_none().0,
135 widget.to_glib_none().0,
136 )
137 }
138 }
139 }
140 fn parent_check_resize(&self) {
141 unsafe {
142 let data = Self::type_data();
143 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
144 if let Some(f) = (*parent_class).check_resize {
145 f(self.obj().unsafe_cast_ref::<Container>().to_glib_none().0)
146 }
147 }
148 }
149 fn parent_set_focus_child(&self, widget: Option<&Widget>) {
150 unsafe {
151 let data = Self::type_data();
152 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
153 if let Some(f) = (*parent_class).set_focus_child {
154 f(
155 self.obj().unsafe_cast_ref::<Container>().to_glib_none().0,
156 widget.to_glib_none().0,
157 )
158 }
159 }
160 }
161 fn parent_child_type(&self) -> glib::Type {
162 unsafe {
163 let data = Self::type_data();
164 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
165 if let Some(f) = (*parent_class).child_type {
166 from_glib(f(self
167 .obj()
168 .unsafe_cast_ref::<Container>()
169 .to_glib_none()
170 .0))
171 } else {
172 glib::Type::UNIT
173 }
174 }
175 }
176 fn parent_path_for_child(&self, widget: &Widget) -> WidgetPath {
177 unsafe {
178 let data = Self::type_data();
179 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
180 let f = (*parent_class)
181 .get_path_for_child
182 .expect("No parent class impl for \"get_path_for_child\"");
183 from_glib_none(f(
184 self.obj().unsafe_cast_ref::<Container>().to_glib_none().0,
185 widget.to_glib_none().0,
186 ))
187 }
188 }
189 fn parent_forall(&self, include_internals: bool, callback: &Callback) {
190 unsafe {
191 let data = Self::type_data();
192 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkContainerClass;
193 if let Some(f) = (*parent_class).forall {
194 f(
195 self.obj().unsafe_cast_ref::<Container>().to_glib_none().0,
196 include_internals.into_glib(),
197 callback.callback,
198 callback.user_data,
199 )
200 }
201 }
202 }
203}
204
205impl<T: ContainerImpl> ContainerImplExt for T {}
206
207unsafe impl<T: ContainerImpl> IsSubclassable<T> for Container {
208 fn class_init(class: &mut ::glib::Class<Self>) {
209 Self::parent_class_init::<T>(class);
210
211 if !crate::rt::is_initialized() {
212 panic!("GTK has to be initialized first");
213 }
214
215 let klass = class.as_mut();
216 klass.add = Some(container_add::<T>);
217 klass.remove = Some(container_remove::<T>);
218 klass.check_resize = Some(container_check_resize::<T>);
219 klass.set_focus_child = Some(container_set_focus_child::<T>);
220 klass.child_type = Some(container_child_type::<T>);
221 klass.get_path_for_child = Some(container_get_path_for_child::<T>);
222 klass.forall = Some(container_forall::<T>);
223 }
224}
225
226unsafe extern "C" fn container_add<T: ContainerImpl>(
227 ptr: *mut ffi::GtkContainer,
228 wdgtptr: *mut ffi::GtkWidget,
229) {
230 unsafe {
231 let instance = &*(ptr as *mut T::Instance);
232 let imp = instance.imp();
233 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
234
235 imp.add(&widget)
236 }
237}
238
239unsafe extern "C" fn container_remove<T: ContainerImpl>(
240 ptr: *mut ffi::GtkContainer,
241 wdgtptr: *mut ffi::GtkWidget,
242) {
243 unsafe {
244 let instance = &*(ptr as *mut T::Instance);
245 let imp = instance.imp();
246 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
247
248 imp.remove(&widget)
249 }
250}
251
252unsafe extern "C" fn container_check_resize<T: ContainerImpl>(ptr: *mut ffi::GtkContainer) {
253 unsafe {
254 let instance = &*(ptr as *mut T::Instance);
255 let imp = instance.imp();
256
257 imp.check_resize()
258 }
259}
260
261unsafe extern "C" fn container_set_focus_child<T: ContainerImpl>(
262 ptr: *mut ffi::GtkContainer,
263 wdgtptr: *mut ffi::GtkWidget,
264) {
265 unsafe {
266 let instance = &*(ptr as *mut T::Instance);
267 let imp = instance.imp();
268 let widget: Borrowed<Option<Widget>> = from_glib_borrow(wdgtptr);
269
270 imp.set_focus_child(widget.as_ref().as_ref())
271 }
272}
273
274unsafe extern "C" fn container_child_type<T: ContainerImpl>(
275 ptr: *mut ffi::GtkContainer,
276) -> glib::ffi::GType {
277 unsafe {
278 let instance = &*(ptr as *mut T::Instance);
279 let imp = instance.imp();
280
281 imp.child_type().into_glib()
282 }
283}
284
285unsafe extern "C" fn container_get_path_for_child<T: ContainerImpl>(
286 ptr: *mut ffi::GtkContainer,
287 wdgtptr: *mut ffi::GtkWidget,
288) -> *mut ffi::GtkWidgetPath {
289 unsafe {
290 let instance = &*(ptr as *mut T::Instance);
291 let imp = instance.imp();
292 let widget: Borrowed<Widget> = from_glib_borrow(wdgtptr);
293
294 imp.path_for_child(&widget).to_glib_none().0
295 }
296}
297
298unsafe extern "C" fn container_forall<T>(
299 ptr: *mut ffi::GtkContainer,
300 include_internals: glib::ffi::gboolean,
301 callback: ffi::GtkCallback,
302 user_data: glib::ffi::gpointer,
303) where
304 T: ObjectSubclass + ContainerImpl,
305{
306 unsafe {
307 let instance = &*(ptr as *mut T::Instance);
308 let imp = instance.imp();
309 let callback = Callback {
310 callback,
311 user_data,
312 };
313
314 imp.forall(from_glib(include_internals), &callback)
315 }
316}
317
318#[derive(Debug)]
319pub struct Callback {
320 callback: ffi::GtkCallback,
321 user_data: glib::ffi::gpointer,
322}
323
324impl Callback {
325 pub fn call(&self, widget: &Widget) {
326 unsafe {
327 if let Some(callback) = self.callback {
328 callback(widget.to_glib_none().0, self.user_data);
329 }
330 }
331 }
332}
333
334pub unsafe trait ContainerClassSubclassExt: ClassStruct {
335 #[doc(alias = "gtk_container_class_handle_border_width")]
336 fn handle_border_width(&mut self) {
337 unsafe {
338 let widget_class = self as *mut _ as *mut ffi::GtkContainerClass;
339 ffi::gtk_container_class_handle_border_width(widget_class);
340 }
341 }
342}
343
344unsafe impl<T: ClassStruct> ContainerClassSubclassExt for T where T::Type: ContainerImpl {}