diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 17:12:53 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 17:12:53 +0000 |
commit | 08f75ed78a7f1823b850aa8cc0c90d4f760fc6ca (patch) | |
tree | f2ac1138b71e215c89d27926a440d8516562e38f | |
parent | 9bf98f6112f3780034f8e8e3914f08ac7e5fabd5 (diff) | |
download | chromium_src-08f75ed78a7f1823b850aa8cc0c90d4f760fc6ca.zip chromium_src-08f75ed78a7f1823b850aa8cc0c90d4f760fc6ca.tar.gz chromium_src-08f75ed78a7f1823b850aa8cc0c90d4f760fc6ca.tar.bz2 |
Add open/close animations to infobar, download shelf.
Animations are implemented by packing the native widget structure into a GtkFixed which resizes and moves its contents around based on AnimationDelegate callbacks.
Review URL: http://codereview.chromium.org/88005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14116 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/download_shelf_gtk.cc | 37 | ||||
-rw-r--r-- | chrome/browser/gtk/download_shelf_gtk.h | 15 | ||||
-rw-r--r-- | chrome/browser/gtk/infobar_container_gtk.cc | 9 | ||||
-rw-r--r-- | chrome/browser/gtk/infobar_gtk.cc | 41 | ||||
-rw-r--r-- | chrome/browser/gtk/slide_animator_gtk.cc | 83 | ||||
-rw-r--r-- | chrome/browser/gtk/slide_animator_gtk.h | 77 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
7 files changed, 216 insertions, 48 deletions
diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc index 0dd3a5e..1ef00a1 100644 --- a/chrome/browser/gtk/download_shelf_gtk.cc +++ b/chrome/browser/gtk/download_shelf_gtk.cc @@ -9,6 +9,7 @@ #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/download_item_gtk.h" #include "chrome/browser/gtk/link_button_gtk.h" +#include "chrome/browser/gtk/slide_animator_gtk.cc" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" @@ -77,9 +78,9 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) gtk_container_add(GTK_CONTAINER(padding), hbox_); gtk_widget_modify_bg(padding_bg, GTK_STATE_NORMAL, &kBackgroundColor); - shelf_ = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(shelf_), top_border, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(shelf_), padding_bg, FALSE, FALSE, 0); + shelf_.Own(gtk_vbox_new(FALSE, 0)); + gtk_box_pack_start(GTK_BOX(shelf_.get()), top_border, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(shelf_.get()), padding_bg, FALSE, FALSE, 0); // Create and pack the close button. close_button_.reset(CustomDrawButton::AddBarCloseButton(hbox_)); @@ -105,13 +106,17 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox_), link_hbox_, FALSE, FALSE, 0); + slide_widget_.reset(new SlideAnimatorGtk(shelf_.get(), + SlideAnimatorGtk::UP, NULL)); // Stick ourselves at the bottom of the parent tab contents. GtkWidget* parent_contents = tab_contents->GetNativeView(); - gtk_box_pack_end(GTK_BOX(parent_contents), shelf_, FALSE, FALSE, 0); - Show(); + gtk_box_pack_end(GTK_BOX(parent_contents), slide_widget_->widget(), + FALSE, FALSE, 0); + slide_widget_->Open(); } DownloadShelfGtk::~DownloadShelfGtk() { + shelf_.Destroy(); } void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) { @@ -119,34 +124,18 @@ void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) { // mass delete on windows, figure out where they do it. download_items_.push_back(new DownloadItemGtk(download_model_, hbox_, link_hbox_)); - Show(); + slide_widget_->Open(); } bool DownloadShelfGtk::IsShowing() const { - return is_showing_; -} - -void DownloadShelfGtk::Show() { - if (is_showing_) - return; - - gtk_widget_show_all(shelf_); - is_showing_ = true; -} - -void DownloadShelfGtk::Hide() { - if (!is_showing_) - return; - - gtk_widget_hide_all(shelf_); - is_showing_ = false; + return slide_widget_->IsShowing(); } // static void DownloadShelfGtk::OnButtonClick(GtkWidget* button, DownloadShelfGtk* shelf) { if (button == shelf->close_button_->widget()) { - shelf->Hide(); + shelf->slide_widget_->Close(); } else { // The link button was clicked. shelf->ShowAllDownloads(); diff --git a/chrome/browser/gtk/download_shelf_gtk.h b/chrome/browser/gtk/download_shelf_gtk.h index 78297d1..76ff640 100644 --- a/chrome/browser/gtk/download_shelf_gtk.h +++ b/chrome/browser/gtk/download_shelf_gtk.h @@ -11,11 +11,13 @@ #include "base/scoped_ptr.h" #include "chrome/browser/download/download_shelf.h" +#include "chrome/common/owned_widget_gtk.h" class BaseDownloadItemModel; class CustomDrawButton; class DownloadItemGtk; class LinkButtonGtk; +class SlideAnimatorGtk; class DownloadShelfGtk : public DownloadShelf { public: @@ -28,20 +30,17 @@ class DownloadShelfGtk : public DownloadShelf { virtual bool IsShowing() const; private: - // Show the shelf. - void Show(); - - // Hide the shelf. - void Hide(); - static void OnButtonClick(GtkWidget* button, DownloadShelfGtk* toolbar); + // The top level widget of the shelf. + scoped_ptr<SlideAnimatorGtk> slide_widget_; + // |hbox_| holds the download items and buttons of the shelf. GtkWidget* hbox_; - // |shelf_| is the highest level widget of the shelf. See the constructor + // |shelf_| is the second highest level widget. See the constructor // for an explanation of the widget layout. - GtkWidget* shelf_; + OwnedWidgetGtk shelf_; // This hbox holds the link text and download icon. It also holds the // distinction of being the leftmost non-download item widget on the shelf. diff --git a/chrome/browser/gtk/infobar_container_gtk.cc b/chrome/browser/gtk/infobar_container_gtk.cc index b30333e..f560ca1 100644 --- a/chrome/browser/gtk/infobar_container_gtk.cc +++ b/chrome/browser/gtk/infobar_container_gtk.cc @@ -28,11 +28,16 @@ void AnimateClosingForDelegate(GtkWidget* infobar_widget, RemoveInfoBarData* data = reinterpret_cast<RemoveInfoBarData*>(remove_info_bar_data); + if (!infobar) { + NOTREACHED(); + return; + } + if (data->delegate == infobar->delegate()) - gtk_container_remove(GTK_CONTAINER(data->container), infobar_widget); + infobar->AnimateClose(); } -} +} // namespace // InfoBarContainerGtk, public: ------------------------------------------------ diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc index 06dd38b..0e4046e 100644 --- a/chrome/browser/gtk/infobar_gtk.cc +++ b/chrome/browser/gtk/infobar_gtk.cc @@ -32,7 +32,7 @@ const int kElementPadding = 5; const int kLeftPadding = 5; const int kRightPadding = 5; -} +} // namespace InfoBar::InfoBar(InfoBarDelegate* delegate) : container_(NULL), @@ -49,9 +49,9 @@ InfoBar::InfoBar(InfoBarDelegate* delegate) // Set the top border and background color. gtk_widget_modify_bg(bg_box, GTK_STATE_NORMAL, &kBackgroundColor); - widget_.Own(gfx::CreateGtkBorderBin(bg_box, &kBorderColor, - 1, 0, 0, 0)); - gtk_widget_set_size_request(widget_.get(), -1, kInfoBarHeight); + border_bin_.Own(gfx::CreateGtkBorderBin(bg_box, &kBorderColor, + 1, 0, 0, 0)); + gtk_widget_set_size_request(border_bin_.get(), -1, kInfoBarHeight); // Add the icon on the left, if any. SkBitmap* icon = delegate->GetIcon(); @@ -66,37 +66,50 @@ InfoBar::InfoBar(InfoBarDelegate* delegate) g_signal_connect(close_button_->widget(), "clicked", G_CALLBACK(OnCloseButton), this); - g_object_set_data(G_OBJECT(widget_.get()), "info-bar", this); + slide_widget_.reset(new SlideAnimatorGtk(border_bin_.get(), + SlideAnimatorGtk::DOWN, + this)); + // We store a pointer back to |this| so we can refer to it from the infobar + // container. + g_object_set_data(G_OBJECT(slide_widget_->widget()), "info-bar", this); } InfoBar::~InfoBar() { - widget_.Destroy(); + border_bin_.Destroy(); +} + +GtkWidget* InfoBar::widget() { + return slide_widget_->widget(); } void InfoBar::AnimateOpen() { - // TODO(port): add animations. In the meantime just Open(). - NOTIMPLEMENTED(); - Open(); + slide_widget_->Open(); } void InfoBar::Open() { - gtk_widget_show_all(widget_.get()); + slide_widget_->OpenWithoutAnimation(); } void InfoBar::AnimateClose() { - // TODO(port): add animations. In the meantime just Close(). - NOTIMPLEMENTED(); - Close(); + slide_widget_->Close(); } void InfoBar::Close() { - gtk_widget_hide(widget_.get()); + if (delegate_) { + delegate_->InfoBarClosed(); + delegate_ = NULL; + } + delete this; } void InfoBar::RemoveInfoBar() const { container_->RemoveDelegate(delegate_); } +void InfoBar::Closed() { + Close(); +} + // static void InfoBar::OnCloseButton(GtkWidget* button, InfoBar* info_bar) { info_bar->AnimateClose(); diff --git a/chrome/browser/gtk/slide_animator_gtk.cc b/chrome/browser/gtk/slide_animator_gtk.cc new file mode 100644 index 0000000..e77756e --- /dev/null +++ b/chrome/browser/gtk/slide_animator_gtk.cc @@ -0,0 +1,83 @@ +// Copyright (c) 2009 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 <gtk/gtk.h> + +#include "base/logging.h" +#include "chrome/common/animation.h" +#include "chrome/common/slide_animation.h" + +namespace { + +void OnSizeAllocate(GtkWidget* fixed, + GtkAllocation* allocation, + GtkWidget* child) { + gint height; + gtk_widget_get_size_request(child, NULL, &height); + // The size of the GtkFixed has changed. We want |child_| to match widths, + // but the height should always be |widget_height_|. + gtk_widget_set_size_request(child, allocation->width, height); +} + +} // namespace + +SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child, + Direction direction, + Delegate* delegate) + : child_(child), + direction_(direction), + delegate_(delegate) { + widget_.Own(gtk_fixed_new()); + // We need to give the GtkFixed its own window so that painting will clip + // correctly. + gtk_fixed_set_has_window(GTK_FIXED(widget_.get()), TRUE); + gtk_fixed_put(GTK_FIXED(widget_.get()), child, 0, 0); + gtk_widget_set_size_request(widget_.get(), -1, 0); + // We have to manually set the size request for |child_| every time the + // GtkFixed changes sizes. + g_signal_connect(widget_.get(), "size-allocate", + G_CALLBACK(OnSizeAllocate), child_); + + animation_.reset(new SlideAnimation(this)); + animation_->SetTweenType(SlideAnimation::NONE); +} + +SlideAnimatorGtk::~SlideAnimatorGtk() { + widget_.Destroy(); +} + +void SlideAnimatorGtk::Open() { + gtk_widget_show_all(widget_.get()); + animation_->Show(); +} + +void SlideAnimatorGtk::OpenWithoutAnimation() { + animation_->Reset(1.0); + Open(); +} + +void SlideAnimatorGtk::Close() { + animation_->Hide(); +} + +bool SlideAnimatorGtk::IsShowing() { + return animation_->IsShowing(); +} + +void SlideAnimatorGtk::AnimationProgressed(const Animation* animation) { + int showing_height = child_->allocation.height * + animation_->GetCurrentValue(); + if (direction_ == DOWN) { + gtk_fixed_move(GTK_FIXED(widget_.get()), child_, 0, + showing_height - child_->allocation.height); + } + gtk_widget_set_size_request(widget_.get(), -1, showing_height); +} + +void SlideAnimatorGtk::AnimationEnded(const Animation* animation) { + if (!animation_->IsShowing() && delegate_) + delegate_->Closed(); +} diff --git a/chrome/browser/gtk/slide_animator_gtk.h b/chrome/browser/gtk/slide_animator_gtk.h new file mode 100644 index 0000000..f884913 --- /dev/null +++ b/chrome/browser/gtk/slide_animator_gtk.h @@ -0,0 +1,77 @@ +// Copyright (c) 2009 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. +// +// A helper class for animating the display of native widget content. +// Currently only handle vertical sliding, but could be extended to handle +// horizontal slides or other types of animations. + +#ifndef CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_ +#define CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_ + +#include "base/scoped_ptr.h" +#include "chrome/common/animation.h" +#include "chrome/common/owned_widget_gtk.h" + +class SlideAnimation; + +typedef struct _GtkWidget GtkWidget; + +class SlideAnimatorGtk : public AnimationDelegate { + public: + class Delegate { + public: + // Called when a call to Close() finishes animating. + virtual void Closed() = 0; + }; + + enum Direction { + DOWN, + UP + }; + + // |child| is the widget we pack into |widget_|. + // |direction| indicates which side the contents will appear to come from. + // |delegate| may be NULL. + SlideAnimatorGtk(GtkWidget* child, + Direction direction, + Delegate* delegate); + + virtual ~SlideAnimatorGtk(); + + GtkWidget* widget() { return widget_.get(); } + + // Slide open. + void Open(); + + // Immediately show the widget. + void OpenWithoutAnimation(); + + // Slide shut. + void Close(); + + // Returns whether the widget is visible. + bool IsShowing(); + + // AnimationDelegate implementation. + void AnimationProgressed(const Animation* animation); + void AnimationEnded(const Animation* animation); + + private: + scoped_ptr<SlideAnimation> animation_; + + // The top level widget of the SlideAnimatorGtk. It is a GtkFixed. + OwnedWidgetGtk widget_; + + // The widget passed to us at construction time, and the only direct child of + // |widget_|. + GtkWidget* child_; + + // The direction of the slide. + Direction direction_; + + // The object to inform about certain events. It may be NULL. + Delegate* delegate_; +}; + +#endif // CHROME_BROWSER_GTK_SLIDE_ANIMATOR_GTK_H_ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index fe47cc4..9092d88 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -752,6 +752,8 @@ 'browser/gtk/menu_gtk.h', 'browser/gtk/nine_box.cc', 'browser/gtk/nine_box.h', + 'browser/gtk/slide_animator_gtk.cc', + 'browser/gtk/slide_animator_gtk.h', 'browser/gtk/standard_menus.cc', 'browser/gtk/standard_menus.h', 'browser/gtk/status_bubble_gtk.cc', |