summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-21 22:27:24 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-21 22:27:24 +0000
commit616ed5a653d4bc13b4633d7c7b85d2f0c73bfd72 (patch)
tree04b8cd92d18cd6e1ff54e46c6c32b0d70391a831 /chrome/browser/views
parentc7eeed7fa25e06ec3d0367a74d2b43671958c5d3 (diff)
downloadchromium_src-616ed5a653d4bc13b4633d7c7b85d2f0c73bfd72.zip
chromium_src-616ed5a653d4bc13b4633d7c7b85d2f0c73bfd72.tar.gz
chromium_src-616ed5a653d4bc13b4633d7c7b85d2f0c73bfd72.tar.bz2
Beginnings of a new InfoBar system.
This implements AlertInfoBar and InfoBarContainer. It also makes the crashed plugin/js oom infobars use this new system. Design Doc: http://dev.chromium.org/developers/design-documents/info-barshttp://crbug.com/4620 Review URL: http://codereview.chromium.org/11318 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5856 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views')
-rw-r--r--chrome/browser/views/browser_views.vcproj16
-rw-r--r--chrome/browser/views/frame/browser_view.cc35
-rw-r--r--chrome/browser/views/frame/browser_view.h4
-rw-r--r--chrome/browser/views/infobars/infobar_container.cc131
-rw-r--r--chrome/browser/views/infobars/infobar_container.h73
-rw-r--r--chrome/browser/views/infobars/infobars.cc291
-rw-r--r--chrome/browser/views/infobars/infobars.h138
7 files changed, 679 insertions, 9 deletions
diff --git a/chrome/browser/views/browser_views.vcproj b/chrome/browser/views/browser_views.vcproj
index 5a543cd..f7ca623 100644
--- a/chrome/browser/views/browser_views.vcproj
+++ b/chrome/browser/views/browser_views.vcproj
@@ -216,6 +216,22 @@
RelativePath=".\info_bar_view.h"
>
</File>
+ <File
+ RelativePath=".\infobars\infobar_container.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\infobars\infobar_container.h"
+ >
+ </File>
+ <File
+ RelativePath=".\infobars\infobars.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\infobars\infobars.h"
+ >
+ </File>
</Filter>
<Filter
Name="Options"
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 8dbeb98..c3b5d07 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/browser/views/html_dialog_view.h"
#include "chrome/browser/views/importer_view.h"
+#include "chrome/browser/views/infobars/infobar_container.h"
#include "chrome/browser/views/keyword_editor_view.h"
#include "chrome/browser/views/password_manager_view.h"
#include "chrome/browser/views/status_bubble.h"
@@ -338,6 +339,9 @@ void BrowserView::Init() {
toolbar_->Init(browser_->profile());
toolbar_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TOOLBAR));
+ infobar_container_ = new InfoBarContainer(this);
+ AddChildView(infobar_container_);
+
contents_container_ = new TabContentsContainerView;
set_contents_view(contents_container_);
AddChildView(contents_container_);
@@ -645,7 +649,9 @@ void BrowserView::TabSelectedAt(TabContents* old_contents,
if (old_contents)
old_contents->StoreFocus();
- // Tell the frame what happened so that the TabContents gets resized, etc.
+ // Update various elements that are interested in knowing the current
+ // TabContents.
+ infobar_container_->ChangeTabContents(new_contents);
contents_container_->SetTabContents(new_contents);
// TODO(beng): This should be called automatically by SetTabContents, but I
// am striving for parity now rather than cleanliness. This is
@@ -1055,7 +1061,7 @@ int BrowserView::LayoutBookmarkAndInfoBars(int top) {
// the Bookmark bar isn't visible on all tabs, then we need to show the
// Info bar _above_ the Bookmark bar, since the Bookmark bar is styled to
// look like it's part of the New Tab Page...
- if (active_info_bar_ && active_bookmark_bar_ &&
+ if (active_bookmark_bar_ &&
bookmark_bar_view_->IsNewTabPage() &&
!bookmark_bar_view_->IsAlwaysShown()) {
top = LayoutInfoBar(top);
@@ -1078,13 +1084,21 @@ int BrowserView::LayoutBookmarkBar(int top) {
return top;
}
int BrowserView::LayoutInfoBar(int top) {
- if (SupportsWindowFeature(FEATURE_INFOBAR) && active_info_bar_) {
- gfx::Size ps = active_info_bar_->GetPreferredSize();
- active_info_bar_->SetBounds(0, top, width(), ps.height());
+ if (SupportsWindowFeature(FEATURE_INFOBAR)) {
+ // Layout the new infobar.
+ gfx::Size ps = infobar_container_->GetPreferredSize();
+ infobar_container_->SetBounds(0, top, width(), ps.height());
top += ps.height();
- if (SupportsWindowFeature(FEATURE_BOOKMARKBAR) && active_bookmark_bar_ &&
- !show_bookmark_bar_pref_.GetValue()) {
- top -= kSeparationLineHeight;
+
+ if (active_info_bar_) {
+ // Layout the old infobar.
+ ps = active_info_bar_->GetPreferredSize();
+ active_info_bar_->SetBounds(0, top, width(), ps.height());
+ top += ps.height();
+ if (SupportsWindowFeature(FEATURE_BOOKMARKBAR) && active_bookmark_bar_ &&
+ !show_bookmark_bar_pref_.GetValue()) {
+ top -= kSeparationLineHeight;
+ }
}
}
return top;
@@ -1131,7 +1145,10 @@ bool BrowserView::MaybeShowInfoBar(TabContents* contents) {
if (contents && contents->AsWebContents() &&
contents->AsWebContents()->view()->IsInfoBarVisible())
new_info_bar = contents->AsWebContents()->view()->GetInfoBarView();
- return UpdateChildViewAndLayout(new_info_bar, &active_info_bar_);
+ UpdateChildViewAndLayout(new_info_bar, &active_info_bar_);
+
+ // TODO(beng): remove this function once the InfoBar rejiggering is complete.
+ return true;
}
bool BrowserView::MaybeShowDownloadShelf(TabContents* contents) {
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index d777f5a..172a1db 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -22,6 +22,7 @@ class BookmarkBarView;
class Browser;
class BrowserToolbarView;
class EncodingMenuControllerDelegate;
+class InfoBarContainer;
class Menu;
class StatusBubble;
class TabContentsContainerView;
@@ -343,6 +344,9 @@ class BrowserView : public BrowserWindow,
// The Bookmark Bar View for this window. Lazily created.
scoped_ptr<BookmarkBarView> bookmark_bar_view_;
+ // The InfoBarContainer that contains InfoBars for the current tab.
+ InfoBarContainer* infobar_container_;
+
// The view that contains the selected TabContents.
TabContentsContainerView* contents_container_;
diff --git a/chrome/browser/views/infobars/infobar_container.cc b/chrome/browser/views/infobars/infobar_container.cc
new file mode 100644
index 0000000..2fe7a35
--- /dev/null
+++ b/chrome/browser/views/infobars/infobar_container.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2006-2008 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/views/infobars/infobar_container.h"
+
+#include "chrome/browser/infobar_delegate.h"
+#include "chrome/browser/tab_contents.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/infobars/infobars.h"
+#include "chrome/common/notification_types.h"
+
+// InfoBarContainer, public: ---------------------------------------------------
+
+InfoBarContainer::InfoBarContainer(BrowserView* browser_view)
+ : browser_view_(browser_view),
+ tab_contents_(NULL) {
+
+}
+
+InfoBarContainer::~InfoBarContainer() {
+ ChangeTabContents(NULL);
+}
+
+void InfoBarContainer::ChangeTabContents(TabContents* contents) {
+ if (tab_contents_) {
+ NotificationService::current()->RemoveObserver(
+ this, NOTIFY_TAB_CONTENTS_INFOBAR_ADDED,
+ Source<TabContents>(tab_contents_));
+ NotificationService::current()->RemoveObserver(
+ this, NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED,
+ Source<TabContents>(tab_contents_));
+ }
+ tab_contents_ = contents;
+ if (tab_contents_) {
+ UpdateInfoBars();
+ NotificationService::current()->AddObserver(
+ this, NOTIFY_TAB_CONTENTS_INFOBAR_ADDED,
+ Source<TabContents>(tab_contents_));
+ NotificationService::current()->AddObserver(
+ this, NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED,
+ Source<TabContents>(tab_contents_));
+ }
+}
+
+void InfoBarContainer::InfoBarAnimated(bool completed) {
+ browser_view_->SelectedTabToolbarSizeChanged(!completed);
+}
+
+void InfoBarContainer::RemoveDelegate(InfoBarDelegate* delegate) {
+ tab_contents_->RemoveInfoBar(delegate);
+}
+
+// InfoBarContainer, views::View overrides: ------------------------------------
+
+gfx::Size InfoBarContainer::GetPreferredSize() {
+ // We do not have a preferred width (we will expand to fit the available width
+ // of the BrowserView). Our preferred height is the sum of the preferred
+ // heights of the InfoBars contained within us.
+ int height = 0;
+ for (int i = 0; i < GetChildViewCount(); ++i)
+ height += GetChildViewAt(i)->GetPreferredSize().height();
+ return gfx::Size(0, height);
+}
+
+void InfoBarContainer::Layout() {
+ int top = 0;
+ for (int i = 0; i < GetChildViewCount(); ++i) {
+ views::View* child = GetChildViewAt(i);
+ gfx::Size ps = child->GetPreferredSize();
+ child->SetBounds(0, top, width(), ps.height());
+ top += ps.height();
+ }
+}
+
+void InfoBarContainer::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (parent == this && child->GetParent() == this) {
+ // An InfoBar child was added or removed. Tell the BrowserView it needs to
+ // re-layout since our preferred size will have changed.
+ browser_view_->SelectedTabToolbarSizeChanged(false);
+ }
+}
+
+// InfoBarContainer, NotificationObserver implementation: ----------------------
+
+void InfoBarContainer::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NOTIFY_TAB_CONTENTS_INFOBAR_ADDED) {
+ AddInfoBar(Details<InfoBarDelegate>(details).ptr());
+ } else if (type == NOTIFY_TAB_CONTENTS_INFOBAR_REMOVED) {
+ RemoveInfoBar(Details<InfoBarDelegate>(details).ptr());
+ } else {
+ NOTREACHED();
+ }
+}
+
+// InfoBarContainer, private: --------------------------------------------------
+
+void InfoBarContainer::UpdateInfoBars() {
+ // Clear out all the old child views.
+ RemoveAllChildViews(true);
+
+ for (size_t i = 0; i < tab_contents_->infobar_delegate_count(); ++i) {
+ InfoBarDelegate* delegate = tab_contents_->GetInfoBarDelegateAt(i);
+ InfoBar* infobar = delegate->CreateInfoBar();
+ infobar->set_container(this);
+ AddChildView(infobar);
+ infobar->Open();
+ }
+}
+
+void InfoBarContainer::AddInfoBar(InfoBarDelegate* delegate) {
+ InfoBar* infobar = delegate->CreateInfoBar();
+ infobar->set_container(this);
+ infobar->AnimateOpen();
+ AddChildView(infobar);
+}
+
+void InfoBarContainer::RemoveInfoBar(InfoBarDelegate* delegate) {
+ size_t index = 0;
+ for (; index < tab_contents_->infobar_delegate_count(); ++index) {
+ if (tab_contents_->GetInfoBarDelegateAt(index) == delegate)
+ break;
+ }
+
+ // The View will be removed once the Close animation completes.
+ static_cast<InfoBar*>(GetChildViewAt(index))->AnimateClose();
+}
diff --git a/chrome/browser/views/infobars/infobar_container.h b/chrome/browser/views/infobars/infobar_container.h
new file mode 100644
index 0000000..43c5280
--- /dev/null
+++ b/chrome/browser/views/infobars/infobar_container.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2006-2008 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.
+
+#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
+#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
+
+#include "chrome/common/notification_service.h"
+#include "chrome/views/view.h"
+
+class BrowserView;
+class InfoBarDelegate;
+class TabContents;
+
+// A views::View subclass that contains a collection of InfoBars associated with
+// a TabContents.
+class InfoBarContainer : public views::View,
+ public NotificationObserver {
+ public:
+ explicit InfoBarContainer(BrowserView* browser_view);
+ virtual ~InfoBarContainer();
+
+ // Changes the TabContents for which this container is showing InfoBars. Can
+ // be NULL.
+ void ChangeTabContents(TabContents* contents);
+
+ // Called by child InfoBars as they animate. If |completed| is true, the
+ // animation has finished running.
+ void InfoBarAnimated(bool completed);
+
+ // Remove the specified InfoBarDelegate from the selected TabContents. This
+ // will notify us back and cause us to close the View. This is called from
+ // the InfoBar's close button handler.
+ void RemoveDelegate(InfoBarDelegate* delegate);
+
+ // Overridden from views::View:
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+ protected:
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
+ private:
+ // Overridden from NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Constructs the InfoBars needed to reflect the state of the current
+ // TabContents associated with this container. No animations are run during
+ // this process.
+ void UpdateInfoBars();
+
+ // Adds an InfoBar for the specified delegate, in response to a notification
+ // from the selected TabContents. The InfoBar's appearance will be animated.
+ void AddInfoBar(InfoBarDelegate* delegate);
+
+ // Removes an InfoBar for the specified delegate, in response to a
+ // notification from the selected TabContents. The InfoBar's disappearance
+ // will be animated.
+ void RemoveInfoBar(InfoBarDelegate* delegate);
+
+ // The BrowserView that hosts this InfoBarContainer.
+ BrowserView* browser_view_;
+
+ // The TabContents for which we are currently showing InfoBars.
+ TabContents* tab_contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarContainer);
+};
+
+#endif // #ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_
diff --git a/chrome/browser/views/infobars/infobars.cc b/chrome/browser/views/infobars/infobars.cc
new file mode 100644
index 0000000..5733d33
--- /dev/null
+++ b/chrome/browser/views/infobars/infobars.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2006-2008 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/views/infobars/infobars.h"
+
+#include "chrome/app/theme/theme_resources.h"
+#include "chrome/browser/views/infobars/infobar_container.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/slide_animation.h"
+#include "chrome/views/background.h"
+#include "chrome/views/button.h"
+#include "chrome/views/image_view.h"
+#include "chrome/views/label.h"
+
+#include "generated_resources.h"
+
+const double kInfoBarHeight = 37.0;
+
+static const int kVerticalPadding = 3;
+static const int kHorizontalPadding = 3;
+static const int kIconLabelSpacing = 5;
+static const int kButtonSpacing = 5;
+
+static const SkColor kBackgroundColorTop = SkColorSetRGB(255, 242, 183);
+static const SkColor kBackgroundColorBottom = SkColorSetRGB(250, 230, 145);
+
+static const int kSeparatorLineHeight = 1;
+static const SkColor kSeparatorColor = SkColorSetRGB(165, 165, 165);
+
+namespace {
+int OffsetY(views::View* parent, const gfx::Size prefsize) {
+ return std::max((parent->height() - prefsize.height()) / 2, 0);
+}
+}
+
+// InfoBarBackground -----------------------------------------------------------
+
+class InfoBarBackground : public views::Background {
+ public:
+ InfoBarBackground() {
+ gradient_background_.reset(
+ views::Background::CreateVerticalGradientBackground(
+ kBackgroundColorTop, kBackgroundColorBottom));
+ }
+
+ // Overridden from views::View:
+ virtual void Paint(ChromeCanvas* canvas, views::View* view) const {
+ // First paint the gradient background.
+ gradient_background_->Paint(canvas, view);
+
+ // Now paint the separator line.
+ canvas->FillRectInt(kSeparatorColor, 0,
+ view->height() - kSeparatorLineHeight, view->width(),
+ kSeparatorLineHeight);
+ }
+
+ private:
+ scoped_ptr<views::Background> gradient_background_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBarBackground);
+};
+
+// InfoBar, public: ------------------------------------------------------------
+
+InfoBar::InfoBar(InfoBarDelegate* delegate)
+ : delegate_(delegate),
+ close_button_(new views::Button) {
+ set_background(new InfoBarBackground);
+
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ close_button_->SetImage(views::Button::BS_NORMAL,
+ rb.GetBitmapNamed(IDR_CLOSE_BAR));
+ close_button_->SetImage(views::Button::BS_HOT,
+ rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
+ close_button_->SetImage(views::Button::BS_PUSHED,
+ rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
+ close_button_->SetListener(this, 0);
+ close_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE));
+ AddChildView(close_button_);
+
+ animation_.reset(new SlideAnimation(this));
+ animation_->SetTweenType(SlideAnimation::NONE);
+}
+
+InfoBar::~InfoBar() {
+}
+
+void InfoBar::AnimateOpen() {
+ animation_->Show();
+}
+
+void InfoBar::Open() {
+ animation_->Reset(1.0);
+ animation_->Show();
+}
+
+void InfoBar::AnimateClose() {
+ animation_->Hide();
+}
+
+void InfoBar::Close() {
+ GetParent()->RemoveChildView(this);
+ if (delegate())
+ delegate()->InfoBarClosed();
+ delete this;
+}
+
+// InfoBar, views::View overrides: ---------------------------------------------
+
+gfx::Size InfoBar::GetPreferredSize() {
+ int height = static_cast<int>(kInfoBarHeight * animation_->GetCurrentValue());
+ return gfx::Size(0, height);
+}
+
+void InfoBar::Layout() {
+ gfx::Size button_ps = close_button_->GetPreferredSize();
+ close_button_->SetBounds(width() - kHorizontalPadding - button_ps.width(),
+ OffsetY(this, button_ps), button_ps.width(),
+ button_ps.height());
+
+}
+
+// InfoBar, protected: ---------------------------------------------------------
+
+int InfoBar::GetAvailableWidth() const {
+ return close_button_->x() - kIconLabelSpacing;
+}
+
+// InfoBar, views::BaseButton::ButtonListener implementation: ------------------
+
+void InfoBar::ButtonPressed(views::BaseButton* sender) {
+ if (sender == close_button_)
+ container_->RemoveDelegate(delegate());
+}
+
+// InfoBar, AnimationDelegate implementation: ----------------------------------
+
+void InfoBar::AnimationProgressed(const Animation* animation) {
+ container_->InfoBarAnimated(true);
+}
+
+void InfoBar::AnimationEnded(const Animation* animation) {
+ container_->InfoBarAnimated(false);
+
+ if (!animation_->IsShowing())
+ Close();
+}
+
+// AlertInfoBar, public: -------------------------------------------------------
+
+AlertInfoBar::AlertInfoBar(AlertInfoBarDelegate* delegate)
+ : InfoBar(delegate) {
+ label_ = new views::Label(
+ delegate->GetMessageText(),
+ ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont));
+ label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ AddChildView(label_);
+
+ icon_ = new views::ImageView;
+ if (delegate->GetIcon())
+ icon_->SetImage(delegate->GetIcon());
+ AddChildView(icon_);
+}
+
+AlertInfoBar::~AlertInfoBar() {
+
+}
+
+// AlertInfoBar, views::View overrides: ----------------------------------------
+
+void AlertInfoBar::Layout() {
+ // Layout the close button.
+ InfoBar::Layout();
+
+ // Layout the icon and text.
+ gfx::Size icon_ps = icon_->GetPreferredSize();
+ icon_->SetBounds(kHorizontalPadding, OffsetY(this, icon_ps), icon_ps.width(),
+ icon_ps.height());
+
+ gfx::Size text_ps = label_->GetPreferredSize();
+ int text_width =
+ GetAvailableWidth() - icon_->bounds().right() - kIconLabelSpacing;
+ label_->SetBounds(icon_->bounds().right() + kIconLabelSpacing,
+ OffsetY(this, text_ps), text_width, text_ps.height());
+}
+
+// AlertInfoBar, private: ------------------------------------------------------
+
+AlertInfoBarDelegate* AlertInfoBar::GetDelegate() {
+ return delegate()->AsAlertInfoBarDelegate();
+}
+
+// ConfirmInfoBar, public: -----------------------------------------------------
+
+ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate)
+ : ok_button_(NULL),
+ cancel_button_(NULL),
+ initialized_(false),
+ AlertInfoBar(delegate) {
+}
+
+ConfirmInfoBar::~ConfirmInfoBar() {
+}
+
+// ConfirmInfoBar, views::View overrides: --------------------------------------
+
+void ConfirmInfoBar::Layout() {
+ InfoBar::Layout();
+ int available_width = InfoBar::GetAvailableWidth();
+ int ok_button_width = 0;
+ int cancel_button_width = 0;
+ gfx::Size ok_ps = ok_button_->GetPreferredSize();
+ gfx::Size cancel_ps = cancel_button_->GetPreferredSize();
+
+ if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK)
+ ok_button_width = ok_ps.width();
+ if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL)
+ cancel_button_width = cancel_ps.width();
+
+ cancel_button_->SetBounds(available_width - cancel_button_width,
+ OffsetY(this, cancel_ps), cancel_ps.width(),
+ cancel_ps.height());
+ int spacing = cancel_button_width > 0 ? kButtonSpacing : 0;
+ ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width,
+ OffsetY(this, ok_ps), ok_ps.width(), ok_ps.height());
+
+ AlertInfoBar::Layout();
+}
+
+void ConfirmInfoBar::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && child == this && !initialized_) {
+ Init();
+ initialized_ = true;
+ }
+}
+
+// ConfirmInfoBar, views::NativeButton::Listener implementation: ---------------
+
+void ConfirmInfoBar::ButtonPressed(views::NativeButton* sender) {
+ if (sender == ok_button_) {
+ GetDelegate()->Accept();
+ } else if (sender == cancel_button_) {
+ GetDelegate()->Cancel();
+ } else {
+ NOTREACHED();
+ }
+}
+
+// ConfirmInfoBar, InfoBar overrides: ------------------------------------------
+
+int ConfirmInfoBar::GetAvailableWidth() const {
+ if (ok_button_)
+ return ok_button_->x() - kButtonSpacing;
+ if (cancel_button_)
+ return cancel_button_->x() - kButtonSpacing;
+ return InfoBar::GetAvailableWidth();
+}
+
+// ConfirmInfoBar, private: ----------------------------------------------------
+
+ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
+ return delegate()->AsConfirmInfoBarDelegate();
+}
+
+void ConfirmInfoBar::Init() {
+ ok_button_ = new views::NativeButton(
+ GetDelegate()->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
+ ok_button_->SetListener(this);
+ AddChildView(ok_button_);
+
+ cancel_button_ = new views::NativeButton(
+ GetDelegate()->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL));
+ cancel_button_->SetListener(this);
+ AddChildView(cancel_button_);
+}
+
+// AlertInfoBarDelegate, InfoBarDelegate overrides: ----------------------------
+
+InfoBar* AlertInfoBarDelegate::CreateInfoBar() {
+ return new AlertInfoBar(this);
+}
+
+// ConfirmInfoBarDelegate, InfoBarDelegate overrides: --------------------------
+
+InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() {
+ return new ConfirmInfoBar(this);
+}
diff --git a/chrome/browser/views/infobars/infobars.h b/chrome/browser/views/infobars/infobars.h
new file mode 100644
index 0000000..1e02f96
--- /dev/null
+++ b/chrome/browser/views/infobars/infobars.h
@@ -0,0 +1,138 @@
+// Copyright (c) 2006-2008 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.
+
+#ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_
+#define CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_
+
+#include "chrome/browser/infobar_delegate.h"
+#include "chrome/views/base_button.h"
+#include "chrome/views/native_button.h"
+
+class InfoBarContainer;
+class SlideAnimation;
+namespace views {
+class Button;
+class ImageView;
+class Label;
+}
+
+// This file contains implementations for some general purpose InfoBars. See
+// chrome/browser/infobar_delegate.h for the delegate interface(s) that you must
+// implement to use these.
+
+class InfoBar : public views::View,
+ public views::BaseButton::ButtonListener,
+ public AnimationDelegate {
+ public:
+ explicit InfoBar(InfoBarDelegate* delegate);
+ virtual ~InfoBar();
+
+ InfoBarDelegate* delegate() const { return delegate_; }
+
+ void set_container(InfoBarContainer* container) { container_ = container; }
+
+ // Starts animating the InfoBar open.
+ void AnimateOpen();
+
+ // Opens the InfoBar immediately.
+ void Open();
+
+ // Starts animating the InfoBar closed. It will not be closed until the
+ // animation has completed, when |Close| will be called.
+ void AnimateClose();
+
+ // Closes the InfoBar immediately and removes it from its container. Notifies
+ // the delegate that it has closed. The InfoBar is deleted after this function
+ // is called.
+ void Close();
+
+ // Overridden from views::View:
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+
+ protected:
+ // Returns the available width of the View for use by child view layout,
+ // excluding the close button.
+ virtual int GetAvailableWidth() const;
+
+ private:
+ // Overridden from views::Button::ButtonListener:
+ virtual void ButtonPressed(views::BaseButton* sender);
+
+ // Overridden from AnimationDelegate:
+ virtual void AnimationProgressed(const Animation* animation);
+ virtual void AnimationEnded(const Animation* animation);
+
+ // The InfoBar's container
+ InfoBarContainer* container_;
+
+ // The InfoBar's delegate.
+ InfoBarDelegate* delegate_;
+
+ // The Close Button at the right edge of the InfoBar.
+ views::Button* close_button_;
+
+ // The animation that runs when the InfoBar is opened or closed.
+ scoped_ptr<SlideAnimation> animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(InfoBar);
+};
+
+class AlertInfoBar : public InfoBar {
+ public:
+ explicit AlertInfoBar(AlertInfoBarDelegate* delegate);
+ virtual ~AlertInfoBar();
+
+ // Overridden from views::View:
+ virtual void Layout();
+
+ protected:
+ views::Label* label() const { return label_; }
+ views::ImageView* icon() const { return icon_; }
+
+ private:
+ AlertInfoBarDelegate* GetDelegate();
+
+ views::Label* label_;
+ views::ImageView* icon_;
+
+ DISALLOW_COPY_AND_ASSIGN(AlertInfoBar);
+};
+
+class ConfirmInfoBar : public AlertInfoBar,
+ public views::NativeButton::Listener {
+ public:
+ explicit ConfirmInfoBar(ConfirmInfoBarDelegate* delegate);
+ virtual ~ConfirmInfoBar();
+
+ // Overridden from views::View:
+ virtual void Layout();
+
+ protected:
+ // Overridden from views::View:
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child);
+
+ // Overridden from views::NativeButton::Listener:
+ virtual void ButtonPressed(views::NativeButton* sender);
+
+ // Overridden from InfoBar:
+ virtual int GetAvailableWidth() const;
+
+ private:
+ void Init();
+
+ ConfirmInfoBarDelegate* GetDelegate();
+
+ views::NativeButton* ok_button_;
+ views::NativeButton* cancel_button_;
+
+ bool initialized_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
+};
+
+
+#endif // #ifndef CHROME_BROWSER_VIEWS_INFOBARS_INFOBARS_H_