| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright (c) 2010 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/gtk/hover_controller_gtk.h" |  | 
|    6  |  | 
|    7 #include "base/message_loop.h" |  | 
|    8 #include "chrome/browser/gtk/gtk_chrome_button.h" |  | 
|    9  |  | 
|   10 static const gchar* kHoverControllerGtkKey = "__HOVER_CONTROLLER_GTK__"; |  | 
|   11  |  | 
|   12 HoverControllerGtk::HoverControllerGtk(GtkWidget* button) |  | 
|   13     : throb_animation_(this), |  | 
|   14       hover_animation_(this), |  | 
|   15       button_(button) { |  | 
|   16   g_object_ref(button_); |  | 
|   17   gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); |  | 
|   18  |  | 
|   19   signals_.Connect(button_, "enter-notify-event", |  | 
|   20                    G_CALLBACK(OnEnterThunk), this); |  | 
|   21   signals_.Connect(button_, "leave-notify-event", |  | 
|   22                    G_CALLBACK(OnLeaveThunk), this); |  | 
|   23   signals_.Connect(button_, "destroy", |  | 
|   24                    G_CALLBACK(OnDestroyThunk), this); |  | 
|   25   signals_.Connect(button_, "hierarchy-changed", |  | 
|   26                    G_CALLBACK(OnHierarchyChangedThunk), this); |  | 
|   27  |  | 
|   28 #ifndef NDEBUG |  | 
|   29   if (g_object_get_data(G_OBJECT(button_), kHoverControllerGtkKey)) |  | 
|   30     NOTREACHED(); |  | 
|   31 #endif  // !NDEBUG |  | 
|   32  |  | 
|   33   g_object_set_data(G_OBJECT(button), kHoverControllerGtkKey, this); |  | 
|   34 } |  | 
|   35  |  | 
|   36 HoverControllerGtk::~HoverControllerGtk() { |  | 
|   37 } |  | 
|   38  |  | 
|   39 void HoverControllerGtk::StartThrobbing(int cycles) { |  | 
|   40   throb_animation_.StartThrobbing(cycles); |  | 
|   41 } |  | 
|   42  |  | 
|   43 // static |  | 
|   44 GtkWidget* HoverControllerGtk::CreateChromeButton() { |  | 
|   45   GtkWidget* widget = gtk_chrome_button_new(); |  | 
|   46   new HoverControllerGtk(widget); |  | 
|   47   return widget; |  | 
|   48 } |  | 
|   49  |  | 
|   50 // static |  | 
|   51 HoverControllerGtk* HoverControllerGtk::GetHoverControllerGtk( |  | 
|   52     GtkWidget* button) { |  | 
|   53   return reinterpret_cast<HoverControllerGtk*>( |  | 
|   54       g_object_get_data(G_OBJECT(button), kHoverControllerGtkKey)); |  | 
|   55 } |  | 
|   56  |  | 
|   57 void HoverControllerGtk::Destroy() { |  | 
|   58   gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), -1.0); |  | 
|   59  |  | 
|   60   g_object_set_data(G_OBJECT(button_), kHoverControllerGtkKey, NULL); |  | 
|   61   g_object_unref(button_); |  | 
|   62   button_ = NULL; |  | 
|   63  |  | 
|   64   delete this; |  | 
|   65 } |  | 
|   66  |  | 
|   67 void HoverControllerGtk::AnimationProgressed(const ui::Animation* animation) { |  | 
|   68   if (!button_) |  | 
|   69     return; |  | 
|   70  |  | 
|   71   // Ignore the hover animation if we are throbbing. |  | 
|   72   if (animation == &hover_animation_ && throb_animation_.is_animating()) |  | 
|   73     return; |  | 
|   74  |  | 
|   75   gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), |  | 
|   76                                     animation->GetCurrentValue()); |  | 
|   77 } |  | 
|   78  |  | 
|   79 void HoverControllerGtk::AnimationEnded(const ui::Animation* animation) { |  | 
|   80   if (!button_) |  | 
|   81     return; |  | 
|   82   if (animation != &throb_animation_) |  | 
|   83     return; |  | 
|   84  |  | 
|   85   if (throb_animation_.cycles_remaining() <= 1) |  | 
|   86     gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); |  | 
|   87 } |  | 
|   88  |  | 
|   89 void HoverControllerGtk::AnimationCanceled(const ui::Animation* animation) { |  | 
|   90   AnimationEnded(animation); |  | 
|   91 } |  | 
|   92  |  | 
|   93 gboolean HoverControllerGtk::OnEnter(GtkWidget* widget, |  | 
|   94                                      GdkEventCrossing* event) { |  | 
|   95   hover_animation_.Show(); |  | 
|   96  |  | 
|   97   return FALSE; |  | 
|   98 } |  | 
|   99  |  | 
|  100 gboolean HoverControllerGtk::OnLeave(GtkWidget* widget, |  | 
|  101                                      GdkEventCrossing* event) { |  | 
|  102   // When the user is holding a mouse button, we don't want to animate. |  | 
|  103   if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) { |  | 
|  104     hover_animation_.Reset(); |  | 
|  105     gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); |  | 
|  106   } else { |  | 
|  107     hover_animation_.Hide(); |  | 
|  108   } |  | 
|  109  |  | 
|  110   return FALSE; |  | 
|  111 } |  | 
|  112  |  | 
|  113 void HoverControllerGtk::OnHierarchyChanged(GtkWidget* widget, |  | 
|  114                                             GtkWidget* previous_toplevel) { |  | 
|  115   // GTK+ does not emit leave-notify-event signals when a widget |  | 
|  116   // becomes unanchored, so manually unset the hover states. |  | 
|  117   if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget))) { |  | 
|  118     gtk_widget_set_state(button_, GTK_STATE_NORMAL); |  | 
|  119     hover_animation_.Reset(); |  | 
|  120     gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0.0); |  | 
|  121   } |  | 
|  122 } |  | 
|  123  |  | 
|  124 void HoverControllerGtk::OnDestroy(GtkWidget* widget) { |  | 
|  125   Destroy(); |  | 
|  126 } |  | 
| OLD | NEW |