1use crate::{ffi, Frame, GridColumn, Widget};
7use glib::{
8 object::ObjectType as _,
9 prelude::*,
10 signal::{connect_raw, SignalHandlerId},
11 translate::*,
12};
13use std::{boxed::Box as Box_, pin::Pin};
14
15glib::wrapper! {
16 #[doc(alias = "PanelGrid")]
17 pub struct Grid(Object<ffi::PanelGrid, ffi::PanelGridClass>) @extends gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
18
19 match fn {
20 type_ => || ffi::panel_grid_get_type(),
21 }
22}
23
24impl Grid {
25 pub const NONE: Option<&'static Grid> = None;
26
27 #[doc(alias = "panel_grid_new")]
28 pub fn new() -> Grid {
29 assert_initialized_main_thread!();
30 unsafe { gtk::Widget::from_glib_none(ffi::panel_grid_new()).unsafe_cast() }
31 }
32
33 pub fn builder() -> GridBuilder {
38 GridBuilder::new()
39 }
40}
41
42impl Default for Grid {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48#[must_use = "The builder must be built to be used"]
53pub struct GridBuilder {
54 builder: glib::object::ObjectBuilder<'static, Grid>,
55}
56
57impl GridBuilder {
58 fn new() -> Self {
59 Self {
60 builder: glib::object::Object::builder(),
61 }
62 }
63
64 pub fn can_focus(self, can_focus: bool) -> Self {
65 Self {
66 builder: self.builder.property("can-focus", can_focus),
67 }
68 }
69
70 pub fn can_target(self, can_target: bool) -> Self {
71 Self {
72 builder: self.builder.property("can-target", can_target),
73 }
74 }
75
76 pub fn css_classes(self, css_classes: impl Into<glib::StrV>) -> Self {
77 Self {
78 builder: self.builder.property("css-classes", css_classes.into()),
79 }
80 }
81
82 pub fn css_name(self, css_name: impl Into<glib::GString>) -> Self {
83 Self {
84 builder: self.builder.property("css-name", css_name.into()),
85 }
86 }
87
88 pub fn cursor(self, cursor: &gdk::Cursor) -> Self {
89 Self {
90 builder: self.builder.property("cursor", cursor.clone()),
91 }
92 }
93
94 pub fn focus_on_click(self, focus_on_click: bool) -> Self {
95 Self {
96 builder: self.builder.property("focus-on-click", focus_on_click),
97 }
98 }
99
100 pub fn focusable(self, focusable: bool) -> Self {
101 Self {
102 builder: self.builder.property("focusable", focusable),
103 }
104 }
105
106 pub fn halign(self, halign: gtk::Align) -> Self {
107 Self {
108 builder: self.builder.property("halign", halign),
109 }
110 }
111
112 pub fn has_tooltip(self, has_tooltip: bool) -> Self {
113 Self {
114 builder: self.builder.property("has-tooltip", has_tooltip),
115 }
116 }
117
118 pub fn height_request(self, height_request: i32) -> Self {
119 Self {
120 builder: self.builder.property("height-request", height_request),
121 }
122 }
123
124 pub fn hexpand(self, hexpand: bool) -> Self {
125 Self {
126 builder: self.builder.property("hexpand", hexpand),
127 }
128 }
129
130 pub fn hexpand_set(self, hexpand_set: bool) -> Self {
131 Self {
132 builder: self.builder.property("hexpand-set", hexpand_set),
133 }
134 }
135
136 pub fn layout_manager(self, layout_manager: &impl IsA<gtk::LayoutManager>) -> Self {
137 Self {
138 builder: self
139 .builder
140 .property("layout-manager", layout_manager.clone().upcast()),
141 }
142 }
143
144 #[cfg(feature = "gtk_v4_18")]
145 #[cfg_attr(docsrs, doc(cfg(feature = "gtk_v4_18")))]
146 pub fn limit_events(self, limit_events: bool) -> Self {
147 Self {
148 builder: self.builder.property("limit-events", limit_events),
149 }
150 }
151
152 pub fn margin_bottom(self, margin_bottom: i32) -> Self {
153 Self {
154 builder: self.builder.property("margin-bottom", margin_bottom),
155 }
156 }
157
158 pub fn margin_end(self, margin_end: i32) -> Self {
159 Self {
160 builder: self.builder.property("margin-end", margin_end),
161 }
162 }
163
164 pub fn margin_start(self, margin_start: i32) -> Self {
165 Self {
166 builder: self.builder.property("margin-start", margin_start),
167 }
168 }
169
170 pub fn margin_top(self, margin_top: i32) -> Self {
171 Self {
172 builder: self.builder.property("margin-top", margin_top),
173 }
174 }
175
176 pub fn name(self, name: impl Into<glib::GString>) -> Self {
177 Self {
178 builder: self.builder.property("name", name.into()),
179 }
180 }
181
182 pub fn opacity(self, opacity: f64) -> Self {
183 Self {
184 builder: self.builder.property("opacity", opacity),
185 }
186 }
187
188 pub fn overflow(self, overflow: gtk::Overflow) -> Self {
189 Self {
190 builder: self.builder.property("overflow", overflow),
191 }
192 }
193
194 pub fn receives_default(self, receives_default: bool) -> Self {
195 Self {
196 builder: self.builder.property("receives-default", receives_default),
197 }
198 }
199
200 pub fn sensitive(self, sensitive: bool) -> Self {
201 Self {
202 builder: self.builder.property("sensitive", sensitive),
203 }
204 }
205
206 pub fn tooltip_markup(self, tooltip_markup: impl Into<glib::GString>) -> Self {
207 Self {
208 builder: self
209 .builder
210 .property("tooltip-markup", tooltip_markup.into()),
211 }
212 }
213
214 pub fn tooltip_text(self, tooltip_text: impl Into<glib::GString>) -> Self {
215 Self {
216 builder: self.builder.property("tooltip-text", tooltip_text.into()),
217 }
218 }
219
220 pub fn valign(self, valign: gtk::Align) -> Self {
221 Self {
222 builder: self.builder.property("valign", valign),
223 }
224 }
225
226 pub fn vexpand(self, vexpand: bool) -> Self {
227 Self {
228 builder: self.builder.property("vexpand", vexpand),
229 }
230 }
231
232 pub fn vexpand_set(self, vexpand_set: bool) -> Self {
233 Self {
234 builder: self.builder.property("vexpand-set", vexpand_set),
235 }
236 }
237
238 pub fn visible(self, visible: bool) -> Self {
239 Self {
240 builder: self.builder.property("visible", visible),
241 }
242 }
243
244 pub fn width_request(self, width_request: i32) -> Self {
245 Self {
246 builder: self.builder.property("width-request", width_request),
247 }
248 }
249
250 pub fn accessible_role(self, accessible_role: gtk::AccessibleRole) -> Self {
251 Self {
252 builder: self.builder.property("accessible-role", accessible_role),
253 }
254 }
255
256 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
259 pub fn build(self) -> Grid {
260 assert_initialized_main_thread!();
261 self.builder.build()
262 }
263}
264
265pub trait PanelGridExt: IsA<Grid> + 'static {
266 #[doc(alias = "panel_grid_add")]
267 fn add(&self, widget: &impl IsA<Widget>) {
268 unsafe {
269 ffi::panel_grid_add(
270 self.as_ref().to_glib_none().0,
271 widget.as_ref().to_glib_none().0,
272 );
273 }
274 }
275
276 #[doc(alias = "panel_grid_agree_to_close_async")]
277 fn agree_to_close_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
278 &self,
279 cancellable: Option<&impl IsA<gio::Cancellable>>,
280 callback: P,
281 ) {
282 let main_context = glib::MainContext::ref_thread_default();
283 let is_main_context_owner = main_context.is_owner();
284 let has_acquired_main_context = (!is_main_context_owner)
285 .then(|| main_context.acquire().ok())
286 .flatten();
287 assert!(
288 is_main_context_owner || has_acquired_main_context.is_some(),
289 "Async operations only allowed if the thread is owning the MainContext"
290 );
291
292 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
293 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
294 unsafe extern "C" fn agree_to_close_async_trampoline<
295 P: FnOnce(Result<(), glib::Error>) + 'static,
296 >(
297 _source_object: *mut glib::gobject_ffi::GObject,
298 res: *mut gio::ffi::GAsyncResult,
299 user_data: glib::ffi::gpointer,
300 ) {
301 let mut error = std::ptr::null_mut();
302 ffi::panel_grid_agree_to_close_finish(_source_object as *mut _, res, &mut error);
303 let result = if error.is_null() {
304 Ok(())
305 } else {
306 Err(from_glib_full(error))
307 };
308 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
309 Box_::from_raw(user_data as *mut _);
310 let callback: P = callback.into_inner();
311 callback(result);
312 }
313 let callback = agree_to_close_async_trampoline::<P>;
314 unsafe {
315 ffi::panel_grid_agree_to_close_async(
316 self.as_ref().to_glib_none().0,
317 cancellable.map(|p| p.as_ref()).to_glib_none().0,
318 Some(callback),
319 Box_::into_raw(user_data) as *mut _,
320 );
321 }
322 }
323
324 fn agree_to_close_future(
325 &self,
326 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
327 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
328 obj.agree_to_close_async(Some(cancellable), move |res| {
329 send.resolve(res);
330 });
331 }))
332 }
333
334 #[doc(alias = "panel_grid_foreach_frame")]
335 fn foreach_frame<P: FnMut(&Frame)>(&self, callback: P) {
336 let mut callback_data: P = callback;
337 unsafe extern "C" fn callback_func<P: FnMut(&Frame)>(
338 frame: *mut ffi::PanelFrame,
339 user_data: glib::ffi::gpointer,
340 ) {
341 let frame = from_glib_borrow(frame);
342 let callback = user_data as *mut P;
343 (*callback)(&frame)
344 }
345 let callback = Some(callback_func::<P> as _);
346 let super_callback0: &mut P = &mut callback_data;
347 unsafe {
348 ffi::panel_grid_foreach_frame(
349 self.as_ref().to_glib_none().0,
350 callback,
351 super_callback0 as *mut _ as *mut _,
352 );
353 }
354 }
355
356 #[doc(alias = "panel_grid_get_column")]
357 #[doc(alias = "get_column")]
358 fn column(&self, column: u32) -> GridColumn {
359 unsafe {
360 from_glib_none(ffi::panel_grid_get_column(
361 self.as_ref().to_glib_none().0,
362 column,
363 ))
364 }
365 }
366
367 #[doc(alias = "panel_grid_get_most_recent_column")]
368 #[doc(alias = "get_most_recent_column")]
369 fn most_recent_column(&self) -> GridColumn {
370 unsafe {
371 from_glib_none(ffi::panel_grid_get_most_recent_column(
372 self.as_ref().to_glib_none().0,
373 ))
374 }
375 }
376
377 #[doc(alias = "panel_grid_get_most_recent_frame")]
378 #[doc(alias = "get_most_recent_frame")]
379 fn most_recent_frame(&self) -> Frame {
380 unsafe {
381 from_glib_none(ffi::panel_grid_get_most_recent_frame(
382 self.as_ref().to_glib_none().0,
383 ))
384 }
385 }
386
387 #[doc(alias = "panel_grid_get_n_columns")]
388 #[doc(alias = "get_n_columns")]
389 fn n_columns(&self) -> u32 {
390 unsafe { ffi::panel_grid_get_n_columns(self.as_ref().to_glib_none().0) }
391 }
392
393 #[doc(alias = "panel_grid_insert_column")]
394 fn insert_column(&self, position: u32) {
395 unsafe {
396 ffi::panel_grid_insert_column(self.as_ref().to_glib_none().0, position);
397 }
398 }
399
400 #[doc(alias = "create-frame")]
401 fn connect_create_frame<F: Fn(&Self) -> Frame + 'static>(&self, f: F) -> SignalHandlerId {
402 unsafe extern "C" fn create_frame_trampoline<P: IsA<Grid>, F: Fn(&P) -> Frame + 'static>(
403 this: *mut ffi::PanelGrid,
404 f: glib::ffi::gpointer,
405 ) -> *mut ffi::PanelFrame {
406 let f: &F = &*(f as *const F);
407 f(Grid::from_glib_borrow(this).unsafe_cast_ref()).to_glib_full()
408 }
409 unsafe {
410 let f: Box_<F> = Box_::new(f);
411 connect_raw(
412 self.as_ptr() as *mut _,
413 c"create-frame".as_ptr() as *const _,
414 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
415 create_frame_trampoline::<Self, F> as *const (),
416 )),
417 Box_::into_raw(f),
418 )
419 }
420 }
421}
422
423impl<O: IsA<Grid>> PanelGridExt for O {}