- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / throbber_gtk.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/throbber_gtk.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
10 #include "content/public/browser/notification_source.h"
11 #include "grit/ui_resources.h"
12 #include "ui/gfx/animation/tween.h"
13 #include "ui/gfx/image/cairo_cached_surface.h"
14
15 namespace {
16
17 // The length of a single cycle of the animation in milliseconds.
18 const int kThrobberDurationMs = 750;
19
20 }  // namespace
21
22 ThrobberGtk::ThrobberGtk(GtkThemeService* theme_service)
23     : theme_service_(theme_service),
24       animation_(this),
25       num_frames_(0) {
26   DCHECK(theme_service_);
27   Init();
28 }
29
30 ThrobberGtk::~ThrobberGtk() {
31   widget_.Destroy();
32 }
33
34 void ThrobberGtk::Start() {
35   animation_.Show();
36 }
37
38 void ThrobberGtk::Stop() {
39   animation_.Reset();
40 }
41
42 void ThrobberGtk::AnimationEnded(const gfx::Animation* animation) {
43   animation_.Reset();
44   animation_.Show();
45 }
46
47 void ThrobberGtk::AnimationProgressed(const gfx::Animation* animation) {
48   gtk_widget_queue_draw(widget_.get());
49 }
50
51 void ThrobberGtk::Observe(int type,
52                           const content::NotificationSource& source,
53                           const content::NotificationDetails& details) {
54   DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type);
55   LoadFrames();
56   gtk_widget_queue_draw(widget_.get());
57 }
58
59 gboolean ThrobberGtk::OnExpose(GtkWidget* widget, GdkEventExpose* expose) {
60   cairo_t* cairo_context =
61       gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
62   GtkAllocation allocation;
63   gtk_widget_get_allocation(widget, &allocation);
64   cairo_translate(cairo_context, allocation.x, allocation.y);
65
66   gfx::CairoCachedSurface* cairo_frames = frames_.ToCairo();
67   const int frame =
68       static_cast<int>(animation_.GetCurrentValue() * (num_frames_ - 1));
69   const int image_size = cairo_frames->Height();
70   const int image_offset = frame * image_size;
71
72   cairo_frames->SetSource(cairo_context, widget, -image_offset, 0);
73   cairo_rectangle(cairo_context, 0, 0, image_size, image_size);
74   cairo_fill(cairo_context);
75   cairo_destroy(cairo_context);
76
77   return TRUE;
78 }
79
80 void ThrobberGtk::Init() {
81   animation_.SetSlideDuration(kThrobberDurationMs);
82   animation_.SetTweenType(gfx::Tween::LINEAR);
83   widget_.Own(gtk_image_new());
84   gtk_widget_set_can_focus(widget_.get(), FALSE);
85   g_signal_connect(widget_.get(), "expose-event", G_CALLBACK(OnExposeThunk),
86                    this);
87
88   theme_service_->InitThemesFor(this);
89   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
90                  content::Source<ThemeService>(theme_service_));
91 }
92
93 void ThrobberGtk::LoadFrames() {
94   frames_ = theme_service_->GetImageNamed(IDR_THROBBER);
95   DCHECK(!frames_.IsEmpty());
96   const int width = frames_.ToCairo()->Width();
97   const int height = frames_.ToCairo()->Height();
98   DCHECK_EQ(0, width % height);
99   num_frames_ = width / height;
100
101   gtk_widget_set_size_request(widget_.get(), height, height);
102 }