Skip to content
This repository was archived by the owner on Mar 4, 2024. It is now read-only.

Commit a624e44

Browse files
authored
Merge pull request #699 from gtk-rs/bilelmoussaoui/container-getter-setter
manually implement Container::(get|set)_property
2 parents ee10907 + 62f99a5 commit a624e44

File tree

5 files changed

+125
-1
lines changed

5 files changed

+125
-1
lines changed

gtk/Gir.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,9 +854,10 @@ generate_builder = true
854854
[[object]]
855855
name = "Gtk.Container"
856856
status = "generate"
857+
manual_traits = ["ContainerExtManual"]
857858
[[object.function]]
858859
pattern = "child_[gs]et_property"
859-
ignore = true
860+
manual = true
860861
[[object.function]]
861862
name = "propagate_draw"
862863
[[object.function.parameter]]

gtk/src/container.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
use crate::{Container, Widget};
4+
use glib::translate::*;
5+
use glib::{value::FromValue, IsA, ToValue};
6+
7+
pub trait ContainerExtManual: 'static {
8+
#[doc(alias = "gtk_container_child_get_property")]
9+
fn child_property_value(&self, child: &impl IsA<Widget>, property_name: &str) -> glib::Value;
10+
11+
#[doc(alias = "gtk_container_child_get_property")]
12+
fn child_property<V: for<'b> FromValue<'b> + 'static>(
13+
&self,
14+
child: &impl IsA<Widget>,
15+
property_name: &str,
16+
) -> V;
17+
18+
#[doc(alias = "gtk_container_child_set_property")]
19+
fn child_set_property(
20+
&self,
21+
child: &impl IsA<Widget>,
22+
property_name: &str,
23+
value: &dyn ToValue,
24+
);
25+
}
26+
27+
impl<O: IsA<Container>> ContainerExtManual for O {
28+
fn child_property_value(&self, child: &impl IsA<Widget>, property_name: &str) -> glib::Value {
29+
unsafe {
30+
let container_class = glib::Class::<Container>::from_type(O::static_type()).unwrap();
31+
let pspec: Option<glib::ParamSpec> =
32+
from_glib_none(ffi::gtk_container_class_find_child_property(
33+
container_class.as_ref() as *const _ as *const glib::gobject_ffi::GObjectClass,
34+
property_name.to_glib_none().0,
35+
));
36+
let pspec = pspec.unwrap_or_else(|| {
37+
panic!("The Container property '{}' doesn't exists", property_name)
38+
});
39+
40+
if !pspec.flags().contains(glib::ParamFlags::READABLE)
41+
|| !pspec.flags().contains(glib::ParamFlags::READWRITE)
42+
{
43+
panic!("The Container property '{}' is not readable", property_name);
44+
}
45+
46+
let mut value = glib::Value::from_type(pspec.value_type());
47+
ffi::gtk_container_child_get_property(
48+
self.as_ref().to_glib_none().0,
49+
child.as_ref().to_glib_none().0,
50+
property_name.to_glib_none().0,
51+
value.to_glib_none_mut().0,
52+
);
53+
value
54+
}
55+
}
56+
57+
fn child_property<V: for<'b> FromValue<'b> + 'static>(
58+
&self,
59+
child: &impl IsA<Widget>,
60+
property_name: &str,
61+
) -> V {
62+
let value = self.child_property_value(child, property_name);
63+
value
64+
.get_owned::<V>()
65+
.expect("Failed to get value of container")
66+
}
67+
68+
fn child_set_property(
69+
&self,
70+
child: &impl IsA<Widget>,
71+
property_name: &str,
72+
value: &dyn ToValue,
73+
) {
74+
unsafe {
75+
let container_class = glib::Class::<Container>::from_type(O::static_type()).unwrap();
76+
let pspec: Option<glib::ParamSpec> =
77+
from_glib_none(ffi::gtk_container_class_find_child_property(
78+
container_class.as_ref() as *const _ as *const glib::gobject_ffi::GObjectClass,
79+
property_name.to_glib_none().0,
80+
));
81+
let pspec = pspec.unwrap_or_else(|| {
82+
panic!("The Container property '{}' doesn't exists", property_name)
83+
});
84+
85+
if !pspec.flags().contains(glib::ParamFlags::WRITABLE)
86+
|| !pspec.flags().contains(glib::ParamFlags::READWRITE)
87+
{
88+
panic!(
89+
"The Container property '{}' is not writeable",
90+
property_name
91+
);
92+
}
93+
94+
assert!(
95+
pspec.value_type().is_a(value.value_type()),
96+
"The Container property '{}' is value is of wrong type. Expected '{}' but got '{}'",
97+
property_name,
98+
pspec.value_type(),
99+
value.value_type()
100+
);
101+
102+
ffi::gtk_container_child_set_property(
103+
self.as_ref().to_glib_none().0,
104+
child.as_ref().to_glib_none().0,
105+
property_name.to_glib_none().0,
106+
value.to_value().to_glib_none().0,
107+
);
108+
}
109+
}
110+
}

gtk/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ mod clipboard;
7272
mod color_button;
7373
mod color_chooser;
7474
mod combo_box;
75+
mod container;
7576
mod dialog;
7677
mod drag_context;
7778
mod entry;

gtk/src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub use crate::cell_renderer_pixbuf::CellRendererPixbufExtManual;
2525
pub use crate::color_button::ColorButtonExtManual;
2626
pub use crate::color_chooser::ColorChooserExtManual;
2727
pub use crate::combo_box::ComboBoxExtManual;
28+
pub use crate::container::ContainerExtManual;
2829
pub use crate::dialog::DialogExtManual;
2930
pub use crate::drag_context::DragContextExtManual;
3031
pub use crate::entry::EntryExtManual;

gtk/sys/src/manual.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,14 @@
33
pub mod xlib {
44
pub type Window = i32;
55
}
6+
7+
//=========================================================================
8+
// GtkContainerClass
9+
//=========================================================================
10+
11+
extern "C" {
12+
pub fn gtk_container_class_find_child_property(
13+
cclass: *const gobject::GObjectClass,
14+
property_name: *const libc::c_char,
15+
) -> *mut gobject::GParamSpec;
16+
}

0 commit comments

Comments
 (0)