Skip to content

Commit 568b4d9

Browse files
gdk-pixbuf: Add PixbufAnimationIter subclassing support
1 parent a491ef8 commit 568b4d9

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

gdk-pixbuf/src/subclass/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
//! Traits intended for creating custom types.
55
66
pub mod pixbuf_animation;
7+
pub mod pixbuf_animation_iter;
78

89
pub mod prelude {
910
pub use gio::subclass::prelude::*;
1011
pub use glib::subclass::prelude::*;
1112

1213
pub use super::pixbuf_animation::{PixbufAnimationImpl, PixbufAnimationImplExt};
14+
pub use super::pixbuf_animation_iter::{PixbufAnimationIterImpl, PixbufAnimationIterImplExt};
1315
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
// rustdoc-stripper-ignore-next
4+
//! Traits intended for subclassing [`PixbufAnimationIter`](crate::PixbufAnimationIter).
5+
6+
use std::time::Duration;
7+
8+
use glib::subclass::prelude::*;
9+
use glib::translate::*;
10+
use glib::Cast;
11+
12+
use crate::{Pixbuf, PixbufAnimationIter};
13+
14+
pub trait PixbufAnimationIterImpl: ObjectImpl {
15+
// rustdoc-stripper-ignore-next
16+
/// Time in milliseconds, returning `None` implies showing the same pixbuf forever.
17+
fn delay_time(&self) -> Option<Duration> {
18+
self.parent_delay_time()
19+
}
20+
21+
fn pixbuf(&self) -> Pixbuf {
22+
self.parent_pixbuf()
23+
}
24+
25+
fn on_currently_loading_frame(&self) -> bool {
26+
self.parent_on_currently_loading_frame()
27+
}
28+
29+
fn advance(&self, time: Duration) -> bool {
30+
self.parent_advance(time)
31+
}
32+
}
33+
34+
pub trait PixbufAnimationIterImplExt: ObjectSubclass {
35+
fn parent_delay_time(&self) -> Option<Duration>;
36+
fn parent_pixbuf(&self) -> Pixbuf;
37+
fn parent_on_currently_loading_frame(&self) -> bool;
38+
fn parent_advance(&self, time: Duration) -> bool;
39+
}
40+
41+
impl<T: PixbufAnimationIterImpl> PixbufAnimationIterImplExt for T {
42+
fn parent_delay_time(&self) -> Option<Duration> {
43+
unsafe {
44+
let data = T::type_data();
45+
let parent_class =
46+
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
47+
let f = (*parent_class)
48+
.get_delay_time
49+
.expect("No parent class implementation for \"get_delay_time\"");
50+
51+
let time = f(self
52+
.obj()
53+
.unsafe_cast_ref::<PixbufAnimationIter>()
54+
.to_glib_none()
55+
.0);
56+
if time == -1 {
57+
None
58+
} else {
59+
Some(Duration::from_millis(time.try_into().unwrap()))
60+
}
61+
}
62+
}
63+
64+
fn parent_pixbuf(&self) -> Pixbuf {
65+
unsafe {
66+
let data = T::type_data();
67+
let parent_class =
68+
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
69+
let f = (*parent_class)
70+
.get_pixbuf
71+
.expect("No parent class implementation for \"get_pixbuf\"");
72+
73+
from_glib_none(f(self
74+
.obj()
75+
.unsafe_cast_ref::<PixbufAnimationIter>()
76+
.to_glib_none()
77+
.0))
78+
}
79+
}
80+
81+
fn parent_on_currently_loading_frame(&self) -> bool {
82+
unsafe {
83+
let data = T::type_data();
84+
let parent_class =
85+
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
86+
let f = (*parent_class)
87+
.on_currently_loading_frame
88+
.expect("No parent class implementation for \"on_currently_loading_frame\"");
89+
90+
from_glib(f(self
91+
.obj()
92+
.unsafe_cast_ref::<PixbufAnimationIter>()
93+
.to_glib_none()
94+
.0))
95+
}
96+
}
97+
98+
fn parent_advance(&self, time: Duration) -> bool {
99+
unsafe {
100+
let data = T::type_data();
101+
let parent_class =
102+
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
103+
let f = (*parent_class)
104+
.advance
105+
.expect("No parent class implementation for \"advance\"");
106+
107+
let time = glib::ffi::GTimeVal {
108+
tv_sec: time.as_secs() as _,
109+
tv_usec: time.subsec_micros() as _,
110+
};
111+
from_glib(f(
112+
self.obj()
113+
.unsafe_cast_ref::<PixbufAnimationIter>()
114+
.to_glib_none()
115+
.0,
116+
&time as *const _,
117+
))
118+
}
119+
}
120+
}
121+
122+
unsafe impl<T: PixbufAnimationIterImpl> IsSubclassable<T> for PixbufAnimationIter {
123+
fn class_init(class: &mut ::glib::Class<Self>) {
124+
Self::parent_class_init::<T>(class);
125+
126+
let klass = class.as_mut();
127+
klass.get_delay_time = Some(animation_iter_get_delay_time::<T>);
128+
klass.get_pixbuf = Some(animation_iter_get_pixbuf::<T>);
129+
klass.on_currently_loading_frame = Some(animation_iter_on_currently_loading_frame::<T>);
130+
klass.advance = Some(animation_iter_advance::<T>);
131+
}
132+
}
133+
134+
unsafe extern "C" fn animation_iter_get_delay_time<T: PixbufAnimationIterImpl>(
135+
ptr: *mut ffi::GdkPixbufAnimationIter,
136+
) -> i32 {
137+
let instance = &*(ptr as *mut T::Instance);
138+
let imp = instance.imp();
139+
140+
imp.delay_time().map(|t| t.as_millis() as i32).unwrap_or(-1)
141+
}
142+
143+
unsafe extern "C" fn animation_iter_get_pixbuf<T: PixbufAnimationIterImpl>(
144+
ptr: *mut ffi::GdkPixbufAnimationIter,
145+
) -> *mut ffi::GdkPixbuf {
146+
let instance = &*(ptr as *mut T::Instance);
147+
let imp = instance.imp();
148+
149+
imp.pixbuf().to_glib_none().0
150+
}
151+
152+
unsafe extern "C" fn animation_iter_on_currently_loading_frame<T: PixbufAnimationIterImpl>(
153+
ptr: *mut ffi::GdkPixbufAnimationIter,
154+
) -> glib::ffi::gboolean {
155+
let instance = &*(ptr as *mut T::Instance);
156+
let imp = instance.imp();
157+
158+
imp.on_currently_loading_frame().into_glib()
159+
}
160+
161+
unsafe extern "C" fn animation_iter_advance<T: PixbufAnimationIterImpl>(
162+
ptr: *mut ffi::GdkPixbufAnimationIter,
163+
time_ptr: *const glib::ffi::GTimeVal,
164+
) -> glib::ffi::gboolean {
165+
let instance = &*(ptr as *mut T::Instance);
166+
let imp = instance.imp();
167+
168+
let total = Duration::from_secs((*time_ptr).tv_sec.try_into().unwrap())
169+
+ Duration::from_micros((*time_ptr).tv_usec.try_into().unwrap());
170+
171+
imp.advance(total).into_glib()
172+
}

0 commit comments

Comments
 (0)