]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/animate.cpp
27e535f8effcef1e1d33026d9d353a70d69a508c
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/animate.cpp
3 // Purpose: wxAnimation and wxAnimationCtrl
4 // Author: Francesco Montorsi
8 // Copyright: (c) Francesco Montorsi
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
20 #if wxUSE_ANIMATIONCTRL
22 #include "wx/animate.h"
25 #include <gtk/gtkimage.h>
28 // ============================================================================
30 // ============================================================================
32 void gdk_pixbuf_area_updated(GdkPixbufLoader
*loader
,
39 if (anim
&& anim
->GetPixbuf() == NULL
)
41 // we need to set the pixbuf only if this is the first time this signal
43 anim
->SetPixbuf(gdk_pixbuf_loader_get_animation(loader
));
48 //-----------------------------------------------------------------------------
50 //-----------------------------------------------------------------------------
52 IMPLEMENT_DYNAMIC_CLASS(wxAnimation
, wxAnimationBase
)
54 bool wxAnimation::LoadFile(const wxString
&name
, wxAnimationType
WXUNUSED(type
))
57 m_pixbuf
= gdk_pixbuf_animation_new_from_file(
58 wxConvFileName
->cWX2MB(name
), NULL
);
62 bool wxAnimation::Load(wxInputStream
&stream
, wxAnimationType type
)
69 case wxANIMATION_TYPE_GIF
:
70 strcpy(anim_type
, "gif");
73 case wxANIMATION_TYPE_ANI
:
74 strcpy(anim_type
, "ani");
81 // create a GdkPixbufLoader
83 GdkPixbufLoader
*loader
;
84 if (type
!= wxANIMATION_TYPE_INVALID
&& type
!= wxANIMATION_TYPE_ANY
)
85 loader
= gdk_pixbuf_loader_new_with_type(anim_type
, &error
);
87 loader
= gdk_pixbuf_loader_new();
91 wxLogDebug(wxT("Could not create the loader for '%s' animation type"), anim_type
);
95 // connect to loader signals
96 g_signal_connect(loader
, "area-updated", G_CALLBACK(gdk_pixbuf_area_updated
), this);
98 //m_bLoadComplete = false;
100 while (stream
.IsOk())
102 // read a chunk of data
103 stream
.Read(buf
, 2048);
105 // fetch all data into the loader
106 if (!gdk_pixbuf_loader_write(loader
, buf
, stream
.LastRead(), &error
))
108 gdk_pixbuf_loader_close(loader
, &error
);
109 wxLogDebug(wxT("Could not write to the loader"));
115 if (!gdk_pixbuf_loader_close(loader
, &error
))
117 wxLogDebug(wxT("Could not close the loader"));
120 //m_bLoadComplete = true;
122 // wait until we get the last area_updated signal
127 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
131 IMPLEMENT_DYNAMIC_CLASS(wxAnimationCtrl
, wxAnimationCtrlBase
)
132 BEGIN_EVENT_TABLE(wxAnimationCtrl
, wxAnimationCtrlBase
)
133 EVT_TIMER(wxID_ANY
, wxAnimationCtrl::OnTimer
)
136 bool wxAnimationCtrl::Create( wxWindow
*parent
, wxWindowID id
,
137 const wxAnimation
& anim
,
141 const wxString
& name
)
144 m_acceptsFocus
= true;
146 if (!PreCreation( parent
, pos
, size
) ||
147 !wxControl::CreateBase(parent
, id
, pos
, size
, style
& wxWINDOW_STYLE_MASK
,
148 wxDefaultValidator
, name
))
150 wxFAIL_MSG( wxT("wxAnimationCtrl creation failed") );
154 SetWindowStyle(style
);
156 m_widget
= gtk_image_new();
157 gtk_widget_show( GTK_WIDGET(m_widget
) );
159 m_parent
->DoAddChild( this );
167 if (anim
!= wxNullAnimation
)
170 // init the timer used for animation
171 m_timer
.SetOwner(this);
176 wxAnimationCtrl::~wxAnimationCtrl()
182 bool wxAnimationCtrl::LoadFile(const wxString
&filename
, wxAnimationType type
)
185 if (!anim
.LoadFile(filename
, type
))
192 void wxAnimationCtrl::SetAnimation(const wxAnimation
&anim
)
200 // copy underlying GdkPixbuf object
201 m_anim
= anim
.GetPixbuf();
203 // m_anim may be null in case wxNullAnimation has been passed
206 // add a reference to the GdkPixbufAnimation
207 g_object_ref(m_anim
);
209 if (!this->HasFlag(wxAC_NO_AUTORESIZE
))
212 // display first frame
213 gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget
),
214 gdk_pixbuf_animation_get_static_image(m_anim
));
218 // we need to clear the control to the background colour
219 ClearToBackgroundColour();
223 void wxAnimationCtrl::FitToAnimation()
228 int w
= gdk_pixbuf_animation_get_width(m_anim
),
229 h
= gdk_pixbuf_animation_get_height(m_anim
);
231 // update our size to fit animation
232 //if (w > 0 && h > 0)
233 // gtk_widget_set_size_request(m_widget, w, h);
237 bool wxAnimationCtrl::Play()
242 // init the iterator and start a one-shot timer
244 m_iter
= gdk_pixbuf_animation_get_iter (m_anim
, NULL
);
247 // gdk_pixbuf_animation_iter_get_delay_time() may return -1 which means
248 // that the timer should not start
249 int n
= gdk_pixbuf_animation_iter_get_delay_time(m_iter
);
251 m_timer
.Start(n
, true);
256 void wxAnimationCtrl::Stop()
258 // leave current frame displayed until Play() is called again
264 bool wxAnimationCtrl::IsPlaying() const
266 // NB: we cannot just return m_timer.IsRunning() as this would not
267 // be safe as e.g. if we are displaying a frame forever,
268 // then we are "officially" still playing the animation, but
269 // the timer is not running anymore...
273 wxSize
wxAnimationCtrl::DoGetBestSize() const
275 if (m_anim
&& !this->HasFlag(wxAC_NO_AUTORESIZE
))
277 return wxSize(gdk_pixbuf_animation_get_width(m_anim
),
278 gdk_pixbuf_animation_get_height(m_anim
));
281 return wxSize(100,100);
284 void wxAnimationCtrl::ClearToBackgroundColour()
286 wxSize sz
= GetClientSize();
287 GdkPixbuf
*newpix
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, false, 8,
288 sz
.GetWidth(), sz
.GetHeight());
292 wxColour clr
= GetBackgroundColour();
293 guint32 col
= (clr
.Red() << 24) | (clr
.Green() << 16) | (clr
.Blue() << 8);
294 gdk_pixbuf_fill(newpix
, col
);
296 wxLogDebug(wxT("Clearing to background %s"), clr
.GetAsString().c_str());
298 gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget
), newpix
);
299 g_object_unref(newpix
);
302 bool wxAnimationCtrl::SetBackgroundColour( const wxColour
&colour
)
304 // wxWindowGTK::SetBackgroundColour works but since our m_widget is a GtkImage
305 // it won't show the background colour unlike the user would expect.
306 // Thus we clear the GtkImage contents to the background colour...
307 if (!wxControl::SetBackgroundColour(colour
))
309 ClearToBackgroundColour();
314 //-----------------------------------------------------------------------------
315 // wxAnimationCtrl - event handlers
316 //-----------------------------------------------------------------------------
318 void wxAnimationCtrl::OnTimer(wxTimerEvent
&ev
)
320 wxASSERT(m_iter
!= NULL
);
322 // gdk_pixbuf_animation_iter_advance() will automatically restart
323 // the animation, if necessary and we have no way to know !!
324 if (gdk_pixbuf_animation_iter_advance(m_iter
, NULL
))
326 // start a new one-shot timer
327 int n
= gdk_pixbuf_animation_iter_get_delay_time(m_iter
);
329 m_timer
.Start(n
, true);
331 gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget
),
332 gdk_pixbuf_animation_iter_get_pixbuf(m_iter
));
336 // no need to update the m_widget yet
337 m_timer
.Start(10, true);
341 #endif // wxUSE_ANIMATIONCTRL