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.
5 #include "chrome/browser/ui/gtk/slide_animator_gtk.h"
7 #include "ui/base/gtk/gtk_expanded_container.h"
8 #include "ui/gfx/animation/animation.h"
9 #include "ui/gfx/animation/slide_animation.h"
13 void OnChildSizeRequest(GtkWidget
* expanded
,
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;
22 requisition
->height
= -1;
27 bool SlideAnimatorGtk::animations_enabled_
= true;
29 SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget
* child
,
33 bool control_child_size
,
36 direction_(direction
),
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);
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
));
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);
56 child_needs_move_
= (direction
== DOWN
);
58 animation_
.reset(new gfx::SlideAnimation(this));
59 // Default tween type is EASE_OUT.
61 animation_
->SetTweenType(gfx::Tween::LINEAR
);
63 animation_
->SetSlideDuration(duration
);
66 SlideAnimatorGtk::~SlideAnimatorGtk() {
70 void SlideAnimatorGtk::Open() {
71 if (!animations_enabled_
)
72 return OpenWithoutAnimation();
74 gtk_widget_show(widget_
.get());
78 void SlideAnimatorGtk::OpenWithoutAnimation() {
79 gtk_widget_show(widget_
.get());
80 animation_
->Reset(1.0);
82 AnimationProgressed(animation_
.get());
85 void SlideAnimatorGtk::Close() {
86 if (!animations_enabled_
)
87 return CloseWithoutAnimation();
92 void SlideAnimatorGtk::End() {
96 void SlideAnimatorGtk::CloseWithoutAnimation() {
97 animation_
->Reset(0.0);
99 AnimationProgressed(animation_
.get());
100 gtk_widget_hide(widget_
.get());
103 bool SlideAnimatorGtk::IsShowing() {
104 return animation_
->IsShowing();
107 bool SlideAnimatorGtk::IsClosing() {
108 return animation_
->IsClosing();
111 bool SlideAnimatorGtk::IsAnimating() {
112 return animation_
->is_animating();
115 void SlideAnimatorGtk::AnimationProgressed(const gfx::Animation
* animation
) {
117 gtk_widget_size_request(child_
, &req
);
119 int showing_height
= static_cast<int>(req
.height
*
120 animation_
->GetCurrentValue());
121 if (direction_
== DOWN
) {
122 if (gtk_widget_get_parent(widget_
.get())) {
123 gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_
.get()),
124 child_
, 0, showing_height
- req
.height
);
126 child_needs_move_
= false;
128 gtk_widget_set_size_request(widget_
.get(), -1, showing_height
);
131 void SlideAnimatorGtk::AnimationEnded(const gfx::Animation
* animation
) {
132 if (!animation_
->IsShowing()) {
133 gtk_widget_hide(widget_
.get());
140 void SlideAnimatorGtk::SetAnimationsForTesting(bool enable
) {
141 animations_enabled_
= enable
;
145 void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget
* child
,
146 GtkAllocation
* allocation
,
147 SlideAnimatorGtk
* slider
) {
148 if (slider
->child_needs_move_
) {
149 gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider
->widget()),
150 child
, 0, -allocation
->height
);
151 slider
->child_needs_move_
= false;