summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-21 06:28:47 +0000
committerhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-21 06:28:47 +0000
commit235b2197b020160e95dcf6456dce9ba45a396fbe (patch)
treea27bf229bfa268947c06630e20bd26e73e58af4e
parent51718596075d217dc0c8ffdb6bd624fe068fd0c9 (diff)
downloadchromium_src-235b2197b020160e95dcf6456dce9ba45a396fbe.zip
chromium_src-235b2197b020160e95dcf6456dce9ba45a396fbe.tar.gz
chromium_src-235b2197b020160e95dcf6456dce9ba45a396fbe.tar.bz2
Add a bubble menu to views.
This change adds a new class ConfirmBubble, which is a simple wrapper class to the Bubble class so we can use a bubble menu as we use an infobar menu. (This menu is to be used for asking whether to integrate the Spelling service to Chrome.) BUG=99130 TEST=none Review URL: http://codereview.chromium.org/8060006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106685 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/confirm_bubble_model.cc61
-rw-r--r--chrome/browser/ui/confirm_bubble_model.h77
-rw-r--r--chrome/browser/ui/views/confirm_bubble_view.cc162
-rw-r--r--chrome/browser/ui/views/confirm_bubble_view.h71
-rw-r--r--chrome/chrome_browser.gypi4
5 files changed, 375 insertions, 0 deletions
diff --git a/chrome/browser/ui/confirm_bubble_model.cc b/chrome/browser/ui/confirm_bubble_model.cc
new file mode 100644
index 0000000..9501b2b
--- /dev/null
+++ b/chrome/browser/ui/confirm_bubble_model.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 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/confirm_bubble_model.h"
+
+#include "base/logging.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/ui/views/confirm_bubble_view.h"
+#include "ui/gfx/rect.h"
+#include "views/widget/widget.h"
+#endif
+
+ConfirmBubbleModel::ConfirmBubbleModel() {
+}
+
+ConfirmBubbleModel::~ConfirmBubbleModel() {
+}
+
+int ConfirmBubbleModel::GetButtons() const {
+ return BUTTON_OK | BUTTON_CANCEL;
+}
+
+string16 ConfirmBubbleModel::GetButtonLabel(BubbleButton button) const {
+ return l10n_util::GetStringUTF16((button == BUTTON_OK) ? IDS_OK : IDS_CANCEL);
+}
+
+void ConfirmBubbleModel::Accept() {
+}
+
+void ConfirmBubbleModel::Cancel() {
+}
+
+string16 ConfirmBubbleModel::GetLinkText() const {
+ return string16();
+}
+
+void ConfirmBubbleModel::LinkClicked() {
+}
+
+void ConfirmBubbleModel::Show(gfx::NativeView view,
+ const gfx::Point& origin,
+ ConfirmBubbleModel* model) {
+#if defined(TOOLKIT_VIEWS)
+ views::Widget* parent = views::Widget::GetTopLevelWidgetForNativeView(view);
+ if (!parent)
+ return;
+
+ ConfirmBubbleView* bubble_view = new ConfirmBubbleView(model);
+ Bubble* bubble = Bubble::Show(parent, gfx::Rect(origin, gfx::Size()),
+ views::BubbleBorder::NONE,
+ bubble_view, bubble_view);
+ bubble->SizeToContents();
+#else
+ NOTIMPLEMENTED(); // Bug 99130: Implement it.
+#endif
+}
+
diff --git a/chrome/browser/ui/confirm_bubble_model.h b/chrome/browser/ui/confirm_bubble_model.h
new file mode 100644
index 0000000..4253c38
--- /dev/null
+++ b/chrome/browser/ui/confirm_bubble_model.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 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_UI_CONFIRM_BUBBLE_MODEL_H_
+#define CHROME_BROWSER_UI_CONFIRM_BUBBLE_MODEL_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Image;
+class Point;
+}
+
+// An interface implemented by objects wishing to control an ConfirmBubbleView.
+// To use this class to implement a bubble menu, we need two steps:
+// 1. Implement a class derived from this class.
+// 2. Call ConfirmBubbleModel::Show() with the class implemented in 1.
+class ConfirmBubbleModel {
+ public:
+ enum BubbleButton {
+ BUTTON_NONE = 0,
+ BUTTON_OK = 1 << 0,
+ BUTTON_CANCEL = 1 << 1,
+ };
+
+ ConfirmBubbleModel();
+ virtual ~ConfirmBubbleModel();
+
+ // Returns the title string and the message string to be displayed for this
+ // bubble menu. These must not be empty strings.
+ virtual string16 GetTitle() const = 0;
+ virtual string16 GetMessageText() const = 0;
+
+ // Returns an icon for the bubble. This image should be owned by the
+ // ResourceBundle and callers should not take ownership of it. Must not return
+ // NULL.
+ virtual gfx::Image* GetIcon() const = 0;
+
+ // Return the buttons to be shown for this bubble menu. This function returns
+ // a combination of BubbleButton values, e.g. when we show both an OK button
+ // and a cancel button, it should return (BUTTON_OK | BUTTON_CANCEL). (This is
+ // the default implementation.)
+ virtual int GetButtons() const;
+
+ // Return the label for the specified button. The default implementation
+ // returns "OK" for the OK button and "Cancel" for the Cancel button.
+ virtual string16 GetButtonLabel(BubbleButton button) const;
+
+ // Called when the OK button is pressed.
+ virtual void Accept();
+
+ // Called when the Cancel button is pressed.
+ virtual void Cancel();
+
+ // Returns the text of the link to be displayed, if any. Otherwise returns
+ // and empty string.
+ virtual string16 GetLinkText() const;
+
+ // Called when the Link is clicked.
+ virtual void LinkClicked();
+
+ // Creates a bubble and shows it with its top center at the specified
+ // |origin|. A bubble created by this function takes ownership of the
+ // specified |model|.
+ static void Show(gfx::NativeView view,
+ const gfx::Point& origin,
+ ConfirmBubbleModel* model);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ConfirmBubbleModel);
+};
+
+#endif // CHROME_BROWSER_UI_CONFIRM_BUBBLE_MODEL_H_
diff --git a/chrome/browser/ui/views/confirm_bubble_view.cc b/chrome/browser/ui/views/confirm_bubble_view.cc
new file mode 100644
index 0000000..110938d
--- /dev/null
+++ b/chrome/browser/ui/views/confirm_bubble_view.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2011 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/views/confirm_bubble_view.h"
+
+#include "chrome/browser/ui/confirm_bubble_model.h"
+#include "grit/theme_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "views/controls/button/image_button.h"
+#include "views/controls/button/text_button.h"
+#include "views/controls/image_view.h"
+#include "views/controls/label.h"
+#include "views/controls/link.h"
+#include "views/layout/grid_layout.h"
+#include "views/layout/layout_constants.h"
+
+namespace {
+
+// Maximum width for the message field. We will wrap the message text when its
+// width is wider than this.
+const int kMaxMessageWidth = 400;
+
+} // namespace
+
+ConfirmBubbleView::ConfirmBubbleView(ConfirmBubbleModel* model)
+ : model_(model) {
+ DCHECK(model);
+}
+
+ConfirmBubbleView::~ConfirmBubbleView() {
+}
+
+void ConfirmBubbleView::BubbleClosing(Bubble* bubble, bool closed_by_escape) {
+}
+
+bool ConfirmBubbleView::CloseOnEscape() {
+ return true;
+}
+
+bool ConfirmBubbleView::FadeInOnShow() {
+ return false;
+}
+
+void ConfirmBubbleView::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
+ if (sender->tag() == ConfirmBubbleModel::BUTTON_OK)
+ model_->Accept();
+ else if (sender->tag() == ConfirmBubbleModel::BUTTON_CANCEL)
+ model_->Cancel();
+ GetWidget()->Close();
+}
+
+void ConfirmBubbleView::LinkClicked(views::Link* source, int event_flags) {
+ model_->LinkClicked();
+}
+
+void ConfirmBubbleView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (!is_add || child != this)
+ return;
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ views::GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+
+ // Add the icon, the title label and the close button to the first row.
+ views::ColumnSet* cs = layout->AddColumnSet(0);
+ cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
+ cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
+ cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+
+ layout->StartRow(0, 0);
+ gfx::Image* icon_image = model_->GetIcon();
+ DCHECK(icon_image);
+ views::ImageView* icon_view = new views::ImageView;
+ icon_view->SetImage(icon_image->ToSkBitmap());
+ layout->AddView(icon_view);
+
+ const string16 title_text = model_->GetTitle();
+ DCHECK(!title_text.empty());
+ views::Label* title_label = new views::Label(title_text);
+ title_label->SetFont(bundle.GetFont(ResourceBundle::MediumFont));
+ title_label->SetBackgroundColor(Bubble::kBackgroundColor);
+ layout->AddView(title_label);
+
+ views::ImageButton* close_button = new views::ImageButton(this);
+ const SkBitmap* close_image =
+ bundle.GetImageNamed(IDR_INFO_BUBBLE_CLOSE).ToSkBitmap();
+ close_button->SetImage(views::CustomButton::BS_NORMAL, close_image);
+ close_button->set_tag(ConfirmBubbleModel::BUTTON_NONE);
+ layout->AddView(close_button);
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+
+ // Add the message label to the second row.
+ cs = layout->AddColumnSet(1);
+ const string16 message_text = model_->GetMessageText();
+ DCHECK(!message_text.empty());
+ views::Label* message_label = new views::Label(message_text);
+ int message_width =
+ std::min(kMaxMessageWidth, message_label->GetPreferredSize().width());
+ cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
+ views::GridLayout::FIXED, message_width, false);
+ message_label->SetBounds(0, 0, message_width, 0);
+ message_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ message_label->SetMultiLine(true);
+ message_label->SetBackgroundColor(Bubble::kBackgroundColor);
+ layout->StartRow(0, 1);
+ layout->AddView(message_label);
+
+ // Add the the link label to the third row if it exists.
+ const string16 link_text = model_->GetLinkText();
+ if (!link_text.empty()) {
+ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout->StartRow(0, 1);
+ views::Link* link_label = new views::Link(link_text);
+ link_label->set_listener(this);
+ link_label->SetBackgroundColor(Bubble::kBackgroundColor);
+ layout->AddView(link_label);
+ }
+ layout->AddPaddingRow(0, views::kLabelToControlVerticalSpacing);
+
+ // Add the ok button and the cancel button to the third (or fourth) row if we
+ // have either of them.
+ bool has_ok_button = !!(model_->GetButtons() & ConfirmBubbleModel::BUTTON_OK);
+ bool has_cancel_button =
+ !!(model_->GetButtons() & ConfirmBubbleModel::BUTTON_CANCEL);
+ if (has_ok_button || has_cancel_button) {
+ cs = layout->AddColumnSet(2);
+ cs->AddPaddingColumn(1, views::kRelatedControlHorizontalSpacing);
+ if (has_ok_button) {
+ cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ if (has_cancel_button)
+ cs->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
+ }
+ if (has_cancel_button) {
+ cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+ }
+ layout->StartRow(0, 2);
+ if (has_ok_button) {
+ views::TextButton* ok_button = new views::NativeTextButton(
+ this, model_->GetButtonLabel(ConfirmBubbleModel::BUTTON_OK));
+ ok_button->set_tag(ConfirmBubbleModel::BUTTON_OK);
+ layout->AddView(ok_button);
+ }
+ if (has_cancel_button) {
+ views::TextButton* cancel_button = new views::NativeTextButton(
+ this, model_->GetButtonLabel(ConfirmBubbleModel::BUTTON_CANCEL));
+ cancel_button->set_tag(ConfirmBubbleModel::BUTTON_CANCEL);
+ layout->AddView(cancel_button);
+ }
+ }
+}
diff --git a/chrome/browser/ui/views/confirm_bubble_view.h b/chrome/browser/ui/views/confirm_bubble_view.h
new file mode 100644
index 0000000..89ecd89
--- /dev/null
+++ b/chrome/browser/ui/views/confirm_bubble_view.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2011 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_UI_VIEWS_CONFIRM_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_CONFIRM_BUBBLE_VIEW_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/views/bubble/bubble.h"
+#include "views/controls/button/button.h"
+#include "views/controls/link_listener.h"
+#include "views/view.h"
+
+class ConfirmBubbleModel;
+
+// A class that implements a bubble that consists of the following items:
+// * one icon ("icon")
+// * one title text ("title")
+// * one message text ("message")
+// * one optional link ("link")
+// * two optional buttons ("ok" and "cancel")
+//
+// This bubble is convenient when we wish to ask transient, non-blocking
+// questions. Unlike a dialog, a bubble menu disappears when we click outside of
+// its window to avoid blocking user operations. A bubble is laid out as
+// follows:
+//
+// +------------------------+
+// | icon title x |
+// | message |
+// | link |
+// | [OK] [Cancel] |
+// +------------------------+
+//
+class ConfirmBubbleView : public BubbleDelegate,
+ public views::ButtonListener,
+ public views::LinkListener,
+ public views::View {
+ public:
+ explicit ConfirmBubbleView(ConfirmBubbleModel* model);
+
+ protected:
+ virtual ~ConfirmBubbleView();
+
+ // BubbleDelegate implementation.
+ virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape) OVERRIDE;
+ virtual bool CloseOnEscape() OVERRIDE;
+ virtual bool FadeInOnShow() OVERRIDE;
+
+ // views::ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* sender,
+ const views::Event& event) OVERRIDE;
+
+ // views::LinkListener implementation.
+ virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
+
+ // views::View implementation.
+ virtual void ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) OVERRIDE;
+
+ private:
+ // The model to customize this bubble view.
+ scoped_ptr<ConfirmBubbleModel> model_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfirmBubbleView);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_CONFIRM_BUBBLE_VIEW_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 30eb746..28cb4d0 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2841,6 +2841,8 @@
'browser/ui/cocoa/wrench_menu/wrench_menu_controller.mm',
'browser/ui/collected_cookies_infobar_delegate.cc',
'browser/ui/collected_cookies_infobar_delegate.h',
+ 'browser/ui/confirm_bubble_model.cc',
+ 'browser/ui/confirm_bubble_model.h',
'browser/ui/content_settings/content_setting_bubble_model.cc',
'browser/ui/content_settings/content_setting_bubble_model.h',
'browser/ui/content_settings/content_setting_image_model.cc',
@@ -3280,6 +3282,8 @@
'browser/ui/views/chrome_views_delegate.h',
'browser/ui/views/collected_cookies_win.cc',
'browser/ui/views/collected_cookies_win.h',
+ 'browser/ui/views/confirm_bubble_view.cc',
+ 'browser/ui/views/confirm_bubble_view.h',
'browser/ui/views/constrained_html_delegate_gtk.cc',
'browser/ui/views/constrained_html_delegate_views.cc',
'browser/ui/views/constrained_window_views.cc',