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