Skip to content

Commit a919867

Browse files
gio: Add Icon subclassing support
1 parent 4da6553 commit a919867

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

gio/src/subclass/icon.rs

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
use std::{
4+
collections::hash_map::DefaultHasher,
5+
hash::{Hash, Hasher},
6+
};
7+
8+
use glib::{prelude::*, subclass::prelude::*, translate::*, Error};
9+
10+
use crate::Icon;
11+
12+
pub trait IconImpl: ObjectImpl + Hash + PartialEq {
13+
fn serialize(&self) -> Option<glib::Variant> {
14+
self.parent_serialize()
15+
}
16+
17+
fn to_tokens(&self) -> Option<(Vec<String>, i32)> {
18+
self.parent_to_tokens()
19+
}
20+
21+
fn from_tokens(tokens: &[String], version: i32) -> Result<Icon, Error> {
22+
Self::parent_from_tokens(tokens, version)
23+
}
24+
}
25+
26+
pub trait IconImplExt: ObjectSubclass {
27+
fn parent_serialize(&self) -> Option<glib::Variant>;
28+
fn parent_to_tokens(&self) -> Option<(Vec<String>, i32)>;
29+
fn parent_from_tokens(tokens: &[String], version: i32) -> Result<Icon, Error>;
30+
}
31+
32+
impl<T: IconImpl> IconImplExt for T {
33+
fn parent_serialize(&self) -> Option<glib::Variant> {
34+
unsafe {
35+
let type_data = Self::type_data();
36+
let parent_iface =
37+
type_data.as_ref().parent_interface::<Icon>() as *const ffi::GIconIface;
38+
39+
let func = (*parent_iface)
40+
.serialize
41+
.expect("No parent iface implementation for \"serialize\"");
42+
from_glib_full(func(self.obj().unsafe_cast_ref::<Icon>().to_glib_none().0))
43+
}
44+
}
45+
46+
fn parent_to_tokens(&self) -> Option<(Vec<String>, i32)> {
47+
unsafe {
48+
let type_data = Self::type_data();
49+
let parent_iface =
50+
type_data.as_ref().parent_interface::<Icon>() as *const ffi::GIconIface;
51+
52+
let tokens = std::ptr::null_mut();
53+
let mut version = std::mem::MaybeUninit::uninit();
54+
let func = (*parent_iface)
55+
.to_tokens
56+
.expect("No parent iface implementation for \"to_tokens\"");
57+
let result = from_glib(func(
58+
self.obj().unsafe_cast_ref::<Icon>().to_glib_none().0,
59+
tokens,
60+
version.as_mut_ptr(),
61+
));
62+
if result {
63+
Some((
64+
FromGlibPtrArrayContainerAsVec::from_glib_full_as_vec(tokens),
65+
version.assume_init(),
66+
))
67+
} else {
68+
None
69+
}
70+
}
71+
}
72+
73+
fn parent_from_tokens(tokens: &[String], version: i32) -> Result<Icon, Error> {
74+
unsafe {
75+
let type_data = Self::type_data();
76+
let parent_iface =
77+
type_data.as_ref().parent_interface::<Icon>() as *const ffi::GIconIface;
78+
79+
let func = (*parent_iface)
80+
.from_tokens
81+
.expect("No parent iface implementation for \"from_tokens\"");
82+
let mut err = std::ptr::null_mut();
83+
84+
let icon = func(
85+
tokens.as_ptr() as *mut _,
86+
tokens.len() as _,
87+
version,
88+
&mut err,
89+
);
90+
if err.is_null() {
91+
Ok(Icon::from_glib_full(icon))
92+
} else {
93+
Err(from_glib_full(err))
94+
}
95+
}
96+
}
97+
}
98+
99+
unsafe impl<T: IconImpl> IsImplementable<T> for Icon {
100+
fn interface_init(iface: &mut glib::Interface<Self>) {
101+
let iface = iface.as_mut();
102+
103+
iface.to_tokens = Some(icon_to_tokens::<T>);
104+
iface.from_tokens = Some(icon_from_tokens::<T>);
105+
iface.serialize = Some(icon_serialize::<T>);
106+
iface.equal = Some(icon_equal::<T>);
107+
iface.hash = Some(icon_hash::<T>);
108+
}
109+
}
110+
111+
unsafe extern "C" fn icon_hash<T: IconImpl>(icon: *mut ffi::GIcon) -> u32 {
112+
let instance = &*(icon as *mut T::Instance);
113+
let imp = instance.imp();
114+
let mut hasher = DefaultHasher::new();
115+
imp.hash(&mut hasher);
116+
hasher.finish() as _
117+
}
118+
119+
unsafe extern "C" fn icon_equal<T: IconImpl>(
120+
icon1: *mut ffi::GIcon,
121+
icon2: *mut ffi::GIcon,
122+
) -> glib::ffi::gboolean {
123+
let instance = &*(icon1 as *mut T::Instance);
124+
let imp1 = instance.imp();
125+
let instance = &*(icon2 as *mut T::Instance);
126+
let imp2 = instance.imp();
127+
128+
imp1.eq(imp2).into_glib()
129+
}
130+
131+
unsafe extern "C" fn icon_serialize<T: IconImpl>(
132+
icon: *mut ffi::GIcon,
133+
) -> *mut glib::ffi::GVariant {
134+
let instance = &*(icon as *mut T::Instance);
135+
let imp = instance.imp();
136+
137+
imp.serialize().to_glib_full()
138+
}
139+
140+
unsafe extern "C" fn icon_to_tokens<T: IconImpl>(
141+
icon: *mut ffi::GIcon,
142+
tokens_ptr: *mut glib::ffi::GPtrArray,
143+
version_ptr: *mut libc::c_int,
144+
) -> glib::ffi::gboolean {
145+
let instance = &*(icon as *mut T::Instance);
146+
let imp = instance.imp();
147+
148+
if let Some((tokens, version)) = imp.to_tokens() {
149+
*version_ptr = version;
150+
*tokens_ptr =
151+
*ToGlibContainerFromSlice::<*mut glib::ffi::GPtrArray>::to_glib_full_from_slice(
152+
&tokens,
153+
);
154+
true.into_glib()
155+
} else {
156+
false.into_glib()
157+
}
158+
}
159+
160+
unsafe extern "C" fn icon_from_tokens<T: IconImpl>(
161+
tokens_ptr: *mut *mut libc::c_char,
162+
n_tokens: i32,
163+
version: i32,
164+
err_ptr: *mut *mut glib::ffi::GError,
165+
) -> *mut ffi::GIcon {
166+
let tokens = String::from_glib_none_num_as_vec(tokens_ptr, n_tokens as _);
167+
match T::from_tokens(tokens.as_slice(), version) {
168+
Ok(icon) => icon.to_glib_full(),
169+
Err(err) => {
170+
*err_ptr = err.into_glib_ptr();
171+
std::ptr::null_mut()
172+
}
173+
}
174+
}

gio/src/subclass/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod app_launch_context;
66
mod application;
77
mod async_initable;
88
mod file_monitor;
9+
mod icon;
910
mod initable;
1011
mod input_stream;
1112
mod io_stream;
@@ -26,6 +27,7 @@ pub mod prelude {
2627
application::{ApplicationImpl, ApplicationImplExt},
2728
async_initable::{AsyncInitableImpl, AsyncInitableImplExt},
2829
file_monitor::{FileMonitorImpl, FileMonitorImplExt},
30+
icon::{IconImpl, IconImplExt},
2931
initable::{InitableImpl, InitableImplExt},
3032
input_stream::{InputStreamImpl, InputStreamImplExt},
3133
io_stream::{IOStreamImpl, IOStreamImplExt},

0 commit comments

Comments
 (0)