diff options
Diffstat (limited to 'chrome/browser/gtk/slide_animator_gtk.cc')
-rw-r--r-- | chrome/browser/gtk/slide_animator_gtk.cc | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/chrome/browser/gtk/slide_animator_gtk.cc b/chrome/browser/gtk/slide_animator_gtk.cc new file mode 100644 index 0000000..ff20c40 --- /dev/null +++ b/chrome/browser/gtk/slide_animator_gtk.cc @@ -0,0 +1,153 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/slide_animator_gtk.h" + +#include "app/animation.h" +#include "app/slide_animation.h" +#include "base/logging.h" + +#include "chrome/browser/gtk/gtk_expanded_container.h" + +namespace { + +void OnChildSizeRequest(GtkWidget* expanded, + GtkWidget* child, + GtkRequisition* requisition, + gpointer control_child_size) { + // If |control_child_size| is true, then we want |child_| to match the width + // of the |widget_|, but the height of |child_| should not change. + if (!GPOINTER_TO_INT(control_child_size)) { + requisition->width = -1; + } + requisition->height = -1; +} + +} // namespace + +bool SlideAnimatorGtk::animations_enabled_ = true; + +SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child, + Direction direction, + int duration, + bool linear, + bool control_child_size, + Delegate* delegate) + : child_(child), + direction_(direction), + delegate_(delegate) { + widget_.Own(gtk_expanded_container_new()); + gtk_container_add(GTK_CONTAINER(widget_.get()), child); + gtk_widget_set_size_request(widget_.get(), -1, 0); + + // If the child requests it, we will manually set the size request for + // |child_| every time the |widget_| changes sizes. This is mainly useful + // for bars, where we want the child to expand to fill all available space. + g_signal_connect(widget_.get(), "child-size-request", + G_CALLBACK(OnChildSizeRequest), + GINT_TO_POINTER(control_child_size)); + + // We connect to this signal to set an initial position for our child widget. + // The reason we connect to this signal rather than setting the initial + // position here is that the widget is currently unallocated and may not + // even have a size request. + g_signal_connect(child, "size-allocate", + G_CALLBACK(OnChildSizeAllocate), this); + + child_needs_move_ = (direction == DOWN); + + animation_.reset(new SlideAnimation(this)); + // Default tween type is EASE_OUT. + if (linear) + animation_->SetTweenType(Tween::LINEAR); + if (duration != 0) + animation_->SetSlideDuration(duration); +} + +SlideAnimatorGtk::~SlideAnimatorGtk() { + widget_.Destroy(); +} + +void SlideAnimatorGtk::Open() { + if (!animations_enabled_) + return OpenWithoutAnimation(); + + gtk_widget_show(widget_.get()); + animation_->Show(); +} + +void SlideAnimatorGtk::OpenWithoutAnimation() { + gtk_widget_show(widget_.get()); + animation_->Reset(1.0); + animation_->Show(); + AnimationProgressed(animation_.get()); +} + +void SlideAnimatorGtk::Close() { + if (!animations_enabled_) + return CloseWithoutAnimation(); + + animation_->Hide(); +} + +void SlideAnimatorGtk::End() { + animation_->End(); +} + +void SlideAnimatorGtk::CloseWithoutAnimation() { + animation_->Reset(0.0); + animation_->Hide(); + AnimationProgressed(animation_.get()); + gtk_widget_hide(widget_.get()); +} + +bool SlideAnimatorGtk::IsShowing() { + return animation_->IsShowing(); +} + +bool SlideAnimatorGtk::IsClosing() { + return animation_->IsClosing(); +} + +bool SlideAnimatorGtk::IsAnimating() { + return animation_->is_animating(); +} + +void SlideAnimatorGtk::AnimationProgressed(const Animation* animation) { + GtkRequisition req; + gtk_widget_size_request(child_, &req); + + int showing_height = static_cast<int>(req.height * + animation_->GetCurrentValue()); + if (direction_ == DOWN) { + gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()), + child_, 0, showing_height - req.height); + child_needs_move_ = false; + } + gtk_widget_set_size_request(widget_.get(), -1, showing_height); +} + +void SlideAnimatorGtk::AnimationEnded(const Animation* animation) { + if (!animation_->IsShowing()) { + gtk_widget_hide(widget_.get()); + if (delegate_) + delegate_->Closed(); + } +} + +// static +void SlideAnimatorGtk::SetAnimationsForTesting(bool enable) { + animations_enabled_ = enable; +} + +// static +void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget* child, + GtkAllocation* allocation, + SlideAnimatorGtk* slider) { + if (slider->child_needs_move_) { + gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider->widget()), + child, 0, -allocation->height); + slider->child_needs_move_ = false; + } +} |