root/chrome/browser/ui/gtk/slide_animator_gtk.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. OnChildSizeRequest
  2. delegate_
  3. Open
  4. OpenWithoutAnimation
  5. Close
  6. End
  7. CloseWithoutAnimation
  8. IsShowing
  9. IsClosing
  10. IsAnimating
  11. AnimationProgressed
  12. AnimationEnded
  13. SetAnimationsForTesting
  14. OnChildSizeAllocate

// Copyright (c) 2012 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/ui/gtk/slide_animator_gtk.h"

#include "ui/base/gtk/gtk_expanded_container.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/slide_animation.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 gfx::SlideAnimation(this));
  // Default tween type is EASE_OUT.
  if (linear)
    animation_->SetTweenType(gfx::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 gfx::Animation* animation) {
  GtkRequisition req;
  gtk_widget_size_request(child_, &req);

  int showing_height = static_cast<int>(req.height *
                                        animation_->GetCurrentValue());
  if (direction_ == DOWN) {
    if (gtk_widget_get_parent(widget_.get())) {
      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 gfx::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;
  }
}

/* [<][>][^][v][top][bottom][index][help] */