Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / slide_animator_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/slide_animator_gtk.h"
6
7 #include "ui/base/gtk/gtk_expanded_container.h"
8 #include "ui/gfx/animation/animation.h"
9 #include "ui/gfx/animation/slide_animation.h"
10
11 namespace {
12
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
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 gfx::SlideAnimation(this));
59   // Default tween type is EASE_OUT.
60   if (linear)
61     animation_->SetTweenType(gfx::Tween::LINEAR);
62   if (duration != 0)
63     animation_->SetSlideDuration(duration);
64 }
65
66 SlideAnimatorGtk::~SlideAnimatorGtk() {
67   widget_.Destroy();
68 }
69
70 void SlideAnimatorGtk::Open() {
71   if (!animations_enabled_)
72     return OpenWithoutAnimation();
73
74   gtk_widget_show(widget_.get());
75   animation_->Show();
76 }
77
78 void SlideAnimatorGtk::OpenWithoutAnimation() {
79   gtk_widget_show(widget_.get());
80   animation_->Reset(1.0);
81   animation_->Show();
82   AnimationProgressed(animation_.get());
83 }
84
85 void SlideAnimatorGtk::Close() {
86   if (!animations_enabled_)
87     return CloseWithoutAnimation();
88
89   animation_->Hide();
90 }
91
92 void SlideAnimatorGtk::End() {
93   animation_->End();
94 }
95
96 void SlideAnimatorGtk::CloseWithoutAnimation() {
97   animation_->Reset(0.0);
98   animation_->Hide();
99   AnimationProgressed(animation_.get());
100   gtk_widget_hide(widget_.get());
101 }
102
103 bool SlideAnimatorGtk::IsShowing() {
104   return animation_->IsShowing();
105 }
106
107 bool SlideAnimatorGtk::IsClosing() {
108   return animation_->IsClosing();
109 }
110
111 bool SlideAnimatorGtk::IsAnimating() {
112   return animation_->is_animating();
113 }
114
115 void SlideAnimatorGtk::AnimationProgressed(const gfx::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     if (gtk_widget_get_parent(widget_.get())) {
123       gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()),
124                                   child_, 0, showing_height - req.height);
125     }
126     child_needs_move_ = false;
127   }
128   gtk_widget_set_size_request(widget_.get(), -1, showing_height);
129 }
130
131 void SlideAnimatorGtk::AnimationEnded(const gfx::Animation* animation) {
132   if (!animation_->IsShowing()) {
133     gtk_widget_hide(widget_.get());
134     if (delegate_)
135       delegate_->Closed();
136   }
137 }
138
139 // static
140 void SlideAnimatorGtk::SetAnimationsForTesting(bool enable) {
141   animations_enabled_ = enable;
142 }
143
144 // static
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;
152   }
153 }