gdk_pixbuf/pixbuf_animation_iter.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::time::{Duration, SystemTime};
4
5use glib::translate::*;
6
7use super::{ffi, Pixbuf};
8
9glib::wrapper! {
10 /// An opaque object representing an iterator which points to a
11 /// certain position in an animation.
12 #[doc(alias = "GdkPixbufAnimationIter")]
13 pub struct PixbufAnimationIter(Object<ffi::GdkPixbufAnimationIter, ffi::GdkPixbufAnimationIterClass>);
14
15 match fn {
16 type_ => || ffi::gdk_pixbuf_animation_iter_get_type(),
17 }
18}
19
20impl PixbufAnimationIter {
21 /// Possibly advances an animation to a new frame.
22 ///
23 /// Chooses the frame based on the start time passed to
24 /// gdk_pixbuf_animation_get_iter().
25 ///
26 /// @current_time would normally come from g_get_current_time(), and
27 /// must be greater than or equal to the time passed to
28 /// gdk_pixbuf_animation_get_iter(), and must increase or remain
29 /// unchanged each time gdk_pixbuf_animation_iter_get_pixbuf() is
30 /// called. That is, you can't go backward in time; animations only
31 /// play forward.
32 ///
33 /// As a shortcut, pass `NULL` for the current time and g_get_current_time()
34 /// will be invoked on your behalf. So you only need to explicitly pass
35 /// @current_time if you're doing something odd like playing the animation
36 /// at double speed.
37 ///
38 /// If this function returns `FALSE`, there's no need to update the animation
39 /// display, assuming the display had been rendered prior to advancing;
40 /// if `TRUE`, you need to call gdk_pixbuf_animation_iter_get_pixbuf()
41 /// and update the display with the new pixbuf.
42 /// ## `current_time`
43 /// current time
44 ///
45 /// # Returns
46 ///
47 /// `TRUE` if the image may need updating
48 #[doc(alias = "gdk_pixbuf_animation_iter_advance")]
49 pub fn advance(&self, current_time: SystemTime) -> bool {
50 let diff = current_time
51 .duration_since(SystemTime::UNIX_EPOCH)
52 .expect("failed to convert time");
53
54 unsafe {
55 from_glib(ffi::gdk_pixbuf_animation_iter_advance(
56 self.to_glib_none().0,
57 &glib::ffi::GTimeVal {
58 tv_sec: diff.as_secs() as _,
59 tv_usec: diff.subsec_micros() as _,
60 },
61 ))
62 }
63 }
64
65 /// Gets the current pixbuf which should be displayed.
66 ///
67 /// The pixbuf might not be the same size as the animation itself
68 /// (gdk_pixbuf_animation_get_width(), gdk_pixbuf_animation_get_height()).
69 ///
70 /// This pixbuf should be displayed for gdk_pixbuf_animation_iter_get_delay_time()
71 /// milliseconds.
72 ///
73 /// The caller of this function does not own a reference to the returned
74 /// pixbuf; the returned pixbuf will become invalid when the iterator
75 /// advances to the next frame, which may happen anytime you call
76 /// gdk_pixbuf_animation_iter_advance().
77 ///
78 /// Copy the pixbuf to keep it (don't just add a reference), as it may get
79 /// recycled as you advance the iterator.
80 ///
81 /// # Returns
82 ///
83 /// the pixbuf to be displayed
84 #[doc(alias = "gdk_pixbuf_animation_iter_get_pixbuf")]
85 #[doc(alias = "get_pixbuf")]
86 pub fn pixbuf(&self) -> Pixbuf {
87 unsafe {
88 from_glib_none(ffi::gdk_pixbuf_animation_iter_get_pixbuf(
89 self.to_glib_none().0,
90 ))
91 }
92 }
93
94 /// Gets the number of milliseconds the current pixbuf should be displayed,
95 /// or -1 if the current pixbuf should be displayed forever.
96 ///
97 /// The `g_timeout_add()` function conveniently takes a timeout in milliseconds,
98 /// so you can use a timeout to schedule the next update.
99 ///
100 /// Note that some formats, like GIF, might clamp the timeout values in the
101 /// image file to avoid updates that are just too quick. The minimum timeout
102 /// for GIF images is currently 20 milliseconds.
103 ///
104 /// # Returns
105 ///
106 /// delay time in milliseconds (thousandths of a second)
107 #[doc(alias = "gdk_pixbuf_animation_iter_get_delay_time")]
108 #[doc(alias = "get_delay_time")]
109 pub fn delay_time(&self) -> Option<Duration> {
110 unsafe {
111 let res = ffi::gdk_pixbuf_animation_iter_get_delay_time(self.to_glib_none().0);
112
113 if res < 0 {
114 None
115 } else {
116 Some(Duration::from_millis(res as u64))
117 }
118 }
119 }
120
121 /// Used to determine how to respond to the area_updated signal on
122 /// #GdkPixbufLoader when loading an animation.
123 ///
124 /// The `::area_updated` signal is emitted for an area of the frame currently
125 /// streaming in to the loader. So if you're on the currently loading frame,
126 /// you will need to redraw the screen for the updated area.
127 ///
128 /// # Returns
129 ///
130 /// `TRUE` if the frame we're on is partially loaded, or the last frame
131 #[doc(alias = "gdk_pixbuf_animation_iter_on_currently_loading_frame")]
132 pub fn on_currently_loading_frame(&self) -> bool {
133 unsafe {
134 from_glib(ffi::gdk_pixbuf_animation_iter_on_currently_loading_frame(
135 self.to_glib_none().0,
136 ))
137 }
138 }
139}