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

Commit a935b11

Browse files
committed
Add ObjectSubclass::Interfaces associated type for listing all interfaces the subclass should implement
1 parent 496efa5 commit a935b11

13 files changed

+123
-43
lines changed

examples/src/bin/basic_subclass.rs

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod imp_win {
4040
const NAME: &'static str = "SimpleWindow";
4141
type Type = super::SimpleWindow;
4242
type ParentType = gtk::ApplicationWindow;
43+
type Interfaces = ();
4344
type Instance = subclass::simple::InstanceStruct<Self>;
4445
type Class = subclass::simple::ClassStruct<Self>;
4546

@@ -128,6 +129,7 @@ mod imp_app {
128129
const NAME: &'static str = "SimpleApplication";
129130
type Type = super::SimpleApplication;
130131
type ParentType = gtk::Application;
132+
type Interfaces = ();
131133
type Instance = subclass::simple::InstanceStruct<Self>;
132134
type Class = subclass::simple::ClassStruct<Self>;
133135

examples/src/bin/composite_template.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod imp {
2929
const NAME: &'static str = "ExApplicationWindow";
3030
type Type = super::ExApplicationWindow;
3131
type ParentType = gtk::ApplicationWindow;
32+
type Interfaces = ();
3233
type Instance = subclass::simple::InstanceStruct<Self>;
3334
type Class = subclass::simple::ClassStruct<Self>;
3435

examples/src/bin/gio_task.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod imp {
2727
const NAME: &'static str = "FileSize";
2828
type ParentType = glib::Object;
2929
type Instance = subclass::simple::InstanceStruct<Self>;
30+
type Interfaces = ();
3031
type Class = subclass::simple::ClassStruct<Self>;
3132
type Type = super::FileSize;
3233
glib::object_subclass!();

examples/src/bin/listbox_model.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,12 @@ mod model {
3434
const NAME: &'static str = "Model";
3535
type Type = super::Model;
3636
type ParentType = glib::Object;
37+
type Interfaces = (gio::ListModel,);
3738
type Instance = subclass::simple::InstanceStruct<Self>;
3839
type Class = subclass::simple::ClassStruct<Self>;
3940

4041
glib::object_subclass!();
4142

42-
// Called right before class_init and allows a GObject to specify
43-
// which interfaces it implement, in this case gio::ListModel
44-
fn type_init(type_: &mut subclass::InitializingType<Self>) {
45-
type_.add_interface::<gio::ListModel>();
46-
}
47-
4843
// Called once at the very beginning of instantiation
4944
fn new() -> Self {
5045
Self(RefCell::new(Vec::new()))
@@ -311,6 +306,7 @@ mod row_data {
311306
const NAME: &'static str = "RowData";
312307
type Type = super::RowData;
313308
type ParentType = glib::Object;
309+
type Interfaces = ();
314310
type Instance = subclass::simple::InstanceStruct<Self>;
315311
type Class = subclass::simple::ClassStruct<Self>;
316312

gio/src/read_input_stream.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ mod imp {
2525
const NAME: &'static str = "ReadInputStream";
2626
type Type = super::ReadInputStream;
2727
type ParentType = InputStream;
28+
type Interfaces = (crate::Seekable,);
2829
type Instance = subclass::simple::InstanceStruct<Self>;
2930
type Class = subclass::simple::ClassStruct<Self>;
3031

@@ -35,10 +36,6 @@ mod imp {
3536
read: RefCell::new(None),
3637
}
3738
}
38-
39-
fn type_init(type_: &mut subclass::InitializingType<Self>) {
40-
type_.add_interface::<crate::Seekable>();
41-
}
4239
}
4340

4441
impl ObjectImpl for ReadInputStream {}

gio/src/subclass/application.rs

+1
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ mod tests {
493493
const NAME: &'static str = "SimpleApplication";
494494
type Type = super::SimpleApplication;
495495
type ParentType = Application;
496+
type Interfaces = ();
496497
type Instance = subclass::simple::InstanceStruct<Self>;
497498
type Class = subclass::simple::ClassStruct<Self>;
498499

gio/src/subclass/input_stream.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ mod tests {
269269
const NAME: &'static str = "SimpleInputStream";
270270
type Type = super::SimpleInputStream;
271271
type ParentType = InputStream;
272+
type Interfaces = (crate::Seekable,);
272273
type Instance = subclass::simple::InstanceStruct<Self>;
273274
type Class = subclass::simple::ClassStruct<Self>;
274275

@@ -279,10 +280,6 @@ mod tests {
279280
pos: RefCell::new(0),
280281
}
281282
}
282-
283-
fn type_init(type_: &mut subclass::InitializingType<Self>) {
284-
type_.add_interface::<crate::Seekable>();
285-
}
286283
}
287284

288285
impl ObjectImpl for SimpleInputStream {}

gio/src/subclass/output_stream.rs

+1
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ mod tests {
331331
const NAME: &'static str = "SimpleOutputStream";
332332
type Type = super::SimpleOutputStream;
333333
type ParentType = OutputStream;
334+
type Interfaces = ();
334335
type Instance = subclass::simple::InstanceStruct<Self>;
335336
type Class = subclass::simple::ClassStruct<Self>;
336337

gio/src/task.rs

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ mod test {
129129
const NAME: &'static str = "MySimpleObjectPrivate";
130130
type ParentType = glib::Object;
131131
type Instance = subclass::simple::InstanceStruct<Self>;
132+
type Interfaces = ();
132133
type Class = subclass::simple::ClassStruct<Self>;
133134
type Type = MySimpleObject;
134135
glib::object_subclass!();

gio/src/write_output_stream.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod imp {
2727
const NAME: &'static str = "WriteOutputStream";
2828
type Type = super::WriteOutputStream;
2929
type ParentType = OutputStream;
30+
type Interfaces = (crate::Seekable,);
3031
type Instance = subclass::simple::InstanceStruct<Self>;
3132
type Class = subclass::simple::ClassStruct<Self>;
3233

@@ -37,10 +38,6 @@ mod imp {
3738
write: RefCell::new(None),
3839
}
3940
}
40-
41-
fn type_init(type_: &mut subclass::InitializingType<Self>) {
42-
type_.add_interface::<crate::Seekable>();
43-
}
4441
}
4542

4643
impl ObjectImpl for WriteOutputStream {}

glib/src/subclass/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
//! type Type = super::SimpleObject;
7777
//! type ParentType = glib::Object;
7878
//!
79+
//! // Interfaces this type implements
80+
//! type Interfaces = ();
81+
//!
7982
//! // The C/FFI instance and class structs. The simple ones
8083
//! // are enough in most cases and more is only needed to
8184
//! // expose public instance fields to C APIs or to provide

glib/src/subclass/object.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ mod test {
334334
const NAME: &'static str = "ChildObject";
335335
type Type = super::ChildObject;
336336
type ParentType = Object;
337+
type Interfaces = ();
337338
type Instance = subclass::simple::InstanceStruct<Self>;
338339
type Class = subclass::simple::ClassStruct<Self>;
339340

@@ -356,15 +357,12 @@ mod test {
356357
const NAME: &'static str = "SimpleObject";
357358
type Type = super::SimpleObject;
358359
type ParentType = Object;
360+
type Interfaces = (DummyInterface,);
359361
type Instance = subclass::simple::InstanceStruct<Self>;
360362
type Class = subclass::simple::ClassStruct<Self>;
361363

362364
object_subclass!();
363365

364-
fn type_init(type_: &mut subclass::InitializingType<Self>) {
365-
type_.add_interface::<DummyInterface>();
366-
}
367-
368366
fn class_init(klass: &mut Self::Class) {
369367
klass.add_signal(
370368
"name-changed",

glib/src/subclass/types.rs

+106-21
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,10 @@ use std::ptr;
1212

1313
/// A newly registered `glib::Type` that is currently still being initialized.
1414
///
15-
/// This allows running additional type-setup functions, e.g. for implementing
16-
/// interfaces on the type.
15+
/// This allows running additional type-setup functions.
1716
#[derive(Debug, PartialEq, Eq)]
1817
pub struct InitializingType<T>(pub(crate) Type, pub(crate) marker::PhantomData<*const T>);
1918

20-
impl<T: ObjectSubclass> InitializingType<T> {
21-
/// Adds an interface implementation for `I` to the type.
22-
#[doc(alias = "g_type_add_interface_static")]
23-
pub fn add_interface<I: IsImplementable<T>>(&mut self) {
24-
unsafe {
25-
let iface_info = gobject_ffi::GInterfaceInfo {
26-
interface_init: Some(I::interface_init),
27-
interface_finalize: None,
28-
interface_data: ptr::null_mut(),
29-
};
30-
gobject_ffi::g_type_add_interface_static(
31-
self.0.to_glib(),
32-
I::static_type().to_glib(),
33-
&iface_info,
34-
);
35-
}
36-
}
37-
}
38-
3919
impl<T> ToGlib for InitializingType<T> {
4020
type GlibType = ffi::GType;
4121

@@ -128,6 +108,103 @@ pub unsafe trait IsImplementable<T: ObjectSubclass>: StaticType {
128108
unsafe extern "C" fn interface_init(iface: ffi::gpointer, _iface_data: ffi::gpointer);
129109
}
130110

111+
/// Trait for a type list of interfaces.
112+
pub trait InterfaceList<T> {
113+
/// Returns the list of types and corresponding interface infos for this list.
114+
fn iface_infos() -> Vec<(ffi::GType, gobject_ffi::GInterfaceInfo)>;
115+
}
116+
117+
impl<T: ObjectSubclass> InterfaceList<T> for () {
118+
fn iface_infos() -> Vec<(ffi::GType, gobject_ffi::GInterfaceInfo)> {
119+
vec![]
120+
}
121+
}
122+
123+
impl<T: ObjectSubclass, A: IsImplementable<T>> InterfaceList<T> for (A,) {
124+
fn iface_infos() -> Vec<(ffi::GType, gobject_ffi::GInterfaceInfo)> {
125+
vec![(
126+
A::static_type().to_glib(),
127+
gobject_ffi::GInterfaceInfo {
128+
interface_init: Some(A::interface_init),
129+
interface_finalize: None,
130+
interface_data: ptr::null_mut(),
131+
},
132+
)]
133+
}
134+
}
135+
136+
// Generates all the InterfaceList impls for interface_lists of arbitrary sizes based on a list of type
137+
// parameters like A B C. It would generate the impl then for (A, B) and (A, B, C).
138+
macro_rules! interface_list_trait(
139+
($name1:ident, $name2: ident, $($name:ident),*) => (
140+
interface_list_trait!(__impl $name1, $name2; $($name),*);
141+
);
142+
(__impl $($name:ident),+; $name1:ident, $($name2:ident),*) => (
143+
interface_list_trait_impl!($($name),+);
144+
interface_list_trait!(__impl $($name),+ , $name1; $($name2),*);
145+
);
146+
(__impl $($name:ident),+; $name1:ident) => (
147+
interface_list_trait_impl!($($name),+);
148+
interface_list_trait_impl!($($name),+, $name1);
149+
);
150+
);
151+
152+
// Generates the impl block for InterfaceList on interface_lists or arbitrary sizes based on its
153+
// arguments. Takes a list of type parameters as parameters, e.g. A B C
154+
// and then implements the trait on (A, B, C).
155+
macro_rules! interface_list_trait_impl(
156+
($($name:ident),+) => (
157+
impl<T: ObjectSubclass, $($name: IsImplementable<T>),+> InterfaceList<T> for ( $($name),+ ) {
158+
fn iface_infos() -> Vec<(ffi::GType, gobject_ffi::GInterfaceInfo)> {
159+
let mut types = Vec::new();
160+
interface_list_trait_inner!(types, $($name)+)
161+
}
162+
}
163+
);
164+
);
165+
166+
// Generates the inner part of the InterfaceList::types() implementation, which will
167+
// basically look as follows:
168+
//
169+
// let mut types = Vec::new();
170+
//
171+
// types.push((A::static_type().to_glib(), ...));
172+
// types.push((B::static_type().to_glib(), ...));
173+
// [...]
174+
// types.push((Z::static_type().to_glib(), ...));
175+
//
176+
// types
177+
macro_rules! interface_list_trait_inner(
178+
($types:ident, $head:ident $($id:ident)+) => ({
179+
$types.push(
180+
(
181+
$head::static_type().to_glib(),
182+
gobject_ffi::GInterfaceInfo {
183+
interface_init: Some($head::interface_init),
184+
interface_finalize: None,
185+
interface_data: ptr::null_mut(),
186+
},
187+
)
188+
);
189+
interface_list_trait_inner!($types, $($id)+)
190+
});
191+
($types:ident, $head:ident) => ({
192+
$types.push(
193+
(
194+
$head::static_type().to_glib(),
195+
gobject_ffi::GInterfaceInfo {
196+
interface_init: Some($head::interface_init),
197+
interface_finalize: None,
198+
interface_data: ptr::null_mut(),
199+
},
200+
)
201+
);
202+
$types
203+
});
204+
);
205+
206+
interface_list_trait!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
207+
131208
/// Type-specific data that is filled in during type creation.
132209
pub struct TypeData {
133210
#[doc(hidden)]
@@ -257,6 +334,9 @@ pub trait ObjectSubclass: Sized + 'static {
257334
+ FromGlibPtrBorrow<*mut <Self::ParentType as ObjectType>::GlibType>
258335
+ FromGlibPtrNone<*mut <Self::ParentType as ObjectType>::GlibType>;
259336

337+
/// List of interfaces implemented by this type.
338+
type Interfaces: InterfaceList<Self>;
339+
260340
/// The C instance struct.
261341
///
262342
/// See [`simple::InstanceStruct`] for an basic instance struct that should be
@@ -529,6 +609,11 @@ where
529609
};
530610
(*data.as_mut()).private_offset = private_offset as isize;
531611

612+
let iface_types = T::Interfaces::iface_infos();
613+
for (iface_type, iface_info) in iface_types {
614+
gobject_ffi::g_type_add_interface_static(type_.to_glib(), iface_type, &iface_info);
615+
}
616+
532617
T::type_init(&mut InitializingType::<T>(type_, marker::PhantomData));
533618

534619
type_

0 commit comments

Comments
 (0)