Skip to content

Commit 1c5636b

Browse files
committed
Allow implementing a GAction interface
1 parent 35e15b7 commit 1c5636b

File tree

2 files changed

+256
-0
lines changed

2 files changed

+256
-0
lines changed

gio/src/subclass/action.rs

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
use glib::{
4+
ffi::{gboolean, GVariant, GVariantType},
5+
prelude::*,
6+
subclass::prelude::*,
7+
translate::*,
8+
GString, Variant, VariantType,
9+
};
10+
11+
use crate::{ffi, Action};
12+
13+
pub trait ActionImpl: ObjectImpl + ObjectSubclass<Type: IsA<Action>> {
14+
fn name(&self) -> GString {
15+
self.parent_name()
16+
}
17+
18+
fn parameter_type(&self) -> Option<VariantType> {
19+
self.parent_parameter_type()
20+
}
21+
22+
fn state_type(&self) -> Option<VariantType> {
23+
self.parent_state_type()
24+
}
25+
26+
fn state_hint(&self) -> Option<Variant> {
27+
self.parent_state_hint()
28+
}
29+
30+
fn enabled(&self) -> bool {
31+
self.parent_enabled()
32+
}
33+
34+
fn state(&self) -> Option<Variant> {
35+
self.parent_state()
36+
}
37+
38+
fn change_state(&self, value: Variant) {
39+
self.parent_change_state(value);
40+
}
41+
42+
fn activate(&self, parameter: Option<Variant>) {
43+
self.parent_activate(parameter);
44+
}
45+
}
46+
47+
pub trait ActionImplExt: ActionImpl {
48+
fn parent_name(&self) -> GString {
49+
unsafe {
50+
let type_data = Self::type_data();
51+
let parent_iface =
52+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
53+
54+
let func = (*parent_iface)
55+
.get_name
56+
.expect("no parent \"get_name\" implementation");
57+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
58+
from_glib_none(ret)
59+
}
60+
}
61+
62+
fn parent_parameter_type(&self) -> Option<VariantType> {
63+
unsafe {
64+
let type_data = Self::type_data();
65+
let parent_iface =
66+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
67+
68+
let func = (*parent_iface)
69+
.get_parameter_type
70+
.expect("no parent \"get_parameter_type\" implementation");
71+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
72+
from_glib_none(ret)
73+
}
74+
}
75+
76+
fn parent_state_type(&self) -> Option<VariantType> {
77+
unsafe {
78+
let type_data = Self::type_data();
79+
let parent_iface =
80+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
81+
82+
let func = (*parent_iface)
83+
.get_state_type
84+
.expect("no parent \"get_state_type\" implementation");
85+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
86+
from_glib_none(ret)
87+
}
88+
}
89+
90+
fn parent_state_hint(&self) -> Option<Variant> {
91+
unsafe {
92+
let type_data = Self::type_data();
93+
let parent_iface =
94+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
95+
96+
let func = (*parent_iface)
97+
.get_state_hint
98+
.expect("no parent \"get_state_hint\" implementation");
99+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
100+
from_glib_none(ret)
101+
}
102+
}
103+
104+
fn parent_enabled(&self) -> bool {
105+
unsafe {
106+
let type_data = Self::type_data();
107+
let parent_iface =
108+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
109+
110+
let func = (*parent_iface)
111+
.get_enabled
112+
.expect("no parent \"get_enabled\" implementation");
113+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
114+
ret != 0
115+
}
116+
}
117+
118+
fn parent_state(&self) -> Option<Variant> {
119+
unsafe {
120+
let type_data = Self::type_data();
121+
let parent_iface =
122+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
123+
124+
let func = (*parent_iface)
125+
.get_state
126+
.expect("no parent \"get_state\" implementation");
127+
let ret = func(self.obj().unsafe_cast_ref::<Action>().to_glib_none().0);
128+
from_glib_none(ret)
129+
}
130+
}
131+
132+
fn parent_change_state(&self, value: Variant) {
133+
unsafe {
134+
let type_data = Self::type_data();
135+
let parent_iface =
136+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
137+
138+
let func = (*parent_iface)
139+
.change_state
140+
.expect("no parent \"change_state\" implementation");
141+
func(
142+
self.obj().unsafe_cast_ref::<Action>().to_glib_none().0,
143+
value.to_glib_none().0,
144+
);
145+
}
146+
}
147+
148+
fn parent_activate(&self, parameter: Option<Variant>) {
149+
unsafe {
150+
let type_data = Self::type_data();
151+
let parent_iface =
152+
type_data.as_ref().parent_interface::<Action>() as *const ffi::GActionInterface;
153+
154+
let func = (*parent_iface)
155+
.activate
156+
.expect("no parent \"activate\" implementation");
157+
func(
158+
self.obj().unsafe_cast_ref::<Action>().to_glib_none().0,
159+
parameter.to_glib_none().0,
160+
);
161+
}
162+
}
163+
}
164+
165+
impl<T: ActionImpl> ActionImplExt for T {}
166+
167+
unsafe impl<T: ActionImpl> IsImplementable<T> for Action {
168+
fn interface_init(iface: &mut glib::Interface<Self>) {
169+
let iface = iface.as_mut();
170+
171+
iface.get_name = Some(action_get_name::<T>);
172+
iface.get_parameter_type = Some(action_get_parameter_type::<T>);
173+
iface.get_state_type = Some(action_get_state_type::<T>);
174+
iface.get_state_hint = Some(action_get_state_hint::<T>);
175+
iface.get_enabled = Some(action_get_enabled::<T>);
176+
iface.get_state = Some(action_get_state::<T>);
177+
iface.change_state = Some(action_change_state::<T>);
178+
iface.activate = Some(action_activate::<T>);
179+
}
180+
}
181+
182+
unsafe extern "C" fn action_get_name<T: ActionImpl>(
183+
actionptr: *mut ffi::GAction,
184+
) -> *const libc::c_char {
185+
let instance = &*(actionptr as *mut T::Instance);
186+
let imp = instance.imp();
187+
188+
imp.name().to_glib_none().0
189+
}
190+
191+
unsafe extern "C" fn action_get_parameter_type<T: ActionImpl>(
192+
actionptr: *mut ffi::GAction,
193+
) -> *const GVariantType {
194+
let instance = &*(actionptr as *mut T::Instance);
195+
let imp = instance.imp();
196+
197+
imp.parameter_type().to_glib_none().0
198+
}
199+
200+
unsafe extern "C" fn action_get_state_type<T: ActionImpl>(
201+
actionptr: *mut ffi::GAction,
202+
) -> *const GVariantType {
203+
let instance = &*(actionptr as *mut T::Instance);
204+
let imp = instance.imp();
205+
206+
imp.state_type().to_glib_none().0
207+
}
208+
209+
unsafe extern "C" fn action_get_state_hint<T: ActionImpl>(
210+
actionptr: *mut ffi::GAction,
211+
) -> *mut GVariant {
212+
let instance = &*(actionptr as *mut T::Instance);
213+
let imp = instance.imp();
214+
215+
imp.state_hint().to_glib_full()
216+
}
217+
218+
unsafe extern "C" fn action_get_enabled<T: ActionImpl>(actionptr: *mut ffi::GAction) -> gboolean {
219+
let instance = &*(actionptr as *mut T::Instance);
220+
let imp = instance.imp();
221+
222+
imp.enabled() as gboolean
223+
}
224+
225+
unsafe extern "C" fn action_get_state<T: ActionImpl>(
226+
actionptr: *mut ffi::GAction,
227+
) -> *mut GVariant {
228+
let instance = &*(actionptr as *mut T::Instance);
229+
let imp = instance.imp();
230+
231+
imp.state().to_glib_full()
232+
}
233+
234+
unsafe extern "C" fn action_change_state<T: ActionImpl>(
235+
actionptr: *mut ffi::GAction,
236+
value: *mut GVariant,
237+
) {
238+
let instance = &*(actionptr as *mut T::Instance);
239+
let imp = instance.imp();
240+
let value: Variant = from_glib_none(value);
241+
242+
imp.change_state(value);
243+
}
244+
245+
unsafe extern "C" fn action_activate<T: ActionImpl>(
246+
actionptr: *mut ffi::GAction,
247+
parameterptr: *mut GVariant,
248+
) {
249+
let instance = &*(actionptr as *mut T::Instance);
250+
let imp = instance.imp();
251+
let parameter: Option<Variant> = from_glib_none(parameterptr);
252+
253+
imp.activate(parameter);
254+
}

gio/src/subclass/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

3+
mod action;
34
mod action_group;
45
mod action_map;
56
mod application;
@@ -19,6 +20,7 @@ pub mod prelude {
1920
pub use glib::subclass::prelude::*;
2021

2122
pub use super::{
23+
action::{ActionImpl, ActionImplExt},
2224
action_group::{ActionGroupImpl, ActionGroupImplExt},
2325
action_map::{ActionMapImpl, ActionMapImplExt},
2426
application::{ApplicationImpl, ApplicationImplExt},

0 commit comments

Comments
 (0)