summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-21 17:12:53 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-21 17:12:53 +0000
commit08f75ed78a7f1823b850aa8cc0c90d4f760fc6ca (patch)
treef2ac1138b71e215c89d27926a440d8516562e38f
parent9bf98f6112f3780034f8e8e3914f08ac7e5fabd5 (diff)
downloadchromium_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.cc37
-rw-r--r--chrome/browser/gtk/download_shelf_gtk.h15
-rw-r--r--chrome/browser/gtk/infobar_container_gtk.cc9
-rw-r--r--chrome/browser/gtk/infobar_gtk.cc41
-rw-r--r--chrome/browser/gtk/slide_animator_gtk.cc83
-rw-r--r--chrome/browser/gtk/slide_animator_gtk.h77
-rw-r--r--chrome/chrome.gyp2
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',