• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/slide_animator_gtk.h"
6 
7 #include "chrome/browser/ui/gtk/gtk_expanded_container.h"
8 #include "ui/base/animation/animation.h"
9 #include "ui/base/animation/slide_animation.h"
10 
11 namespace {
12 
OnChildSizeRequest(GtkWidget * expanded,GtkWidget * child,GtkRequisition * requisition,gpointer control_child_size)13 void OnChildSizeRequest(GtkWidget* expanded,
14                         GtkWidget* child,
15                         GtkRequisition* requisition,
16                         gpointer control_child_size) {
17   // If |control_child_size| is true, then we want |child_| to match the width
18   // of the |widget_|, but the height of |child_| should not change.
19   if (!GPOINTER_TO_INT(control_child_size)) {
20     requisition->width = -1;
21   }
22   requisition->height = -1;
23 }
24 
25 }  // namespace
26 
27 bool SlideAnimatorGtk::animations_enabled_ = true;
28 
SlideAnimatorGtk(GtkWidget * child,Direction direction,int duration,bool linear,bool control_child_size,Delegate * delegate)29 SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child,
30                                    Direction direction,
31                                    int duration,
32                                    bool linear,
33                                    bool control_child_size,
34                                    Delegate* delegate)
35     : child_(child),
36       direction_(direction),
37       delegate_(delegate) {
38   widget_.Own(gtk_expanded_container_new());
39   gtk_container_add(GTK_CONTAINER(widget_.get()), child);
40   gtk_widget_set_size_request(widget_.get(), -1, 0);
41 
42   // If the child requests it, we will manually set the size request for
43   // |child_| every time the |widget_| changes sizes. This is mainly useful
44   // for bars, where we want the child to expand to fill all available space.
45   g_signal_connect(widget_.get(), "child-size-request",
46                    G_CALLBACK(OnChildSizeRequest),
47                    GINT_TO_POINTER(control_child_size));
48 
49   // We connect to this signal to set an initial position for our child widget.
50   // The reason we connect to this signal rather than setting the initial
51   // position here is that the widget is currently unallocated and may not
52   // even have a size request.
53   g_signal_connect(child, "size-allocate",
54                    G_CALLBACK(OnChildSizeAllocate), this);
55 
56   child_needs_move_ = (direction == DOWN);
57 
58   animation_.reset(new ui::SlideAnimation(this));
59   // Default tween type is EASE_OUT.
60   if (linear)
61     animation_->SetTweenType(ui::Tween::LINEAR);
62   if (duration != 0)
63     animation_->SetSlideDuration(duration);
64 }
65 
~SlideAnimatorGtk()66 SlideAnimatorGtk::~SlideAnimatorGtk() {
67   widget_.Destroy();
68 }
69 
Open()70 void SlideAnimatorGtk::Open() {
71   if (!animations_enabled_)
72     return OpenWithoutAnimation();
73 
74   gtk_widget_show(widget_.get());
75   animation_->Show();
76 }
77 
OpenWithoutAnimation()78 void SlideAnimatorGtk::OpenWithoutAnimation() {
79   gtk_widget_show(widget_.get());
80   animation_->Reset(1.0);
81   animation_->Show();
82   AnimationProgressed(animation_.get());
83 }
84 
Close()85 void SlideAnimatorGtk::Close() {
86   if (!animations_enabled_)
87     return CloseWithoutAnimation();
88 
89   animation_->Hide();
90 }
91 
End()92 void SlideAnimatorGtk::End() {
93   animation_->End();
94 }
95 
CloseWithoutAnimation()96 void SlideAnimatorGtk::CloseWithoutAnimation() {
97   animation_->Reset(0.0);
98   animation_->Hide();
99   AnimationProgressed(animation_.get());
100   gtk_widget_hide(widget_.get());
101 }
102 
IsShowing()103 bool SlideAnimatorGtk::IsShowing() {
104   return animation_->IsShowing();
105 }
106 
IsClosing()107 bool SlideAnimatorGtk::IsClosing() {
108   return animation_->IsClosing();
109 }
110 
IsAnimating()111 bool SlideAnimatorGtk::IsAnimating() {
112   return animation_->is_animating();
113 }
114 
AnimationProgressed(const ui::Animation * animation)115 void SlideAnimatorGtk::AnimationProgressed(const ui::Animation* animation) {
116   GtkRequisition req;
117   gtk_widget_size_request(child_, &req);
118 
119   int showing_height = static_cast<int>(req.height *
120                                         animation_->GetCurrentValue());
121   if (direction_ == DOWN) {
122     gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()),
123                                 child_, 0, showing_height - req.height);
124     child_needs_move_ = false;
125   }
126   gtk_widget_set_size_request(widget_.get(), -1, showing_height);
127 }
128 
AnimationEnded(const ui::Animation * animation)129 void SlideAnimatorGtk::AnimationEnded(const ui::Animation* animation) {
130   if (!animation_->IsShowing()) {
131     gtk_widget_hide(widget_.get());
132     if (delegate_)
133       delegate_->Closed();
134   }
135 }
136 
137 // static
SetAnimationsForTesting(bool enable)138 void SlideAnimatorGtk::SetAnimationsForTesting(bool enable) {
139   animations_enabled_ = enable;
140 }
141 
142 // static
OnChildSizeAllocate(GtkWidget * child,GtkAllocation * allocation,SlideAnimatorGtk * slider)143 void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget* child,
144                                            GtkAllocation* allocation,
145                                            SlideAnimatorGtk* slider) {
146   if (slider->child_needs_move_) {
147     gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider->widget()),
148                                 child, 0, -allocation->height);
149     slider->child_needs_move_ = false;
150   }
151 }
152