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