summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorerikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 15:41:12 +0000
committererikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 15:41:12 +0000
commitff72d8700783eadd7b6a05e3cec4e60a57dcabb3 (patch)
tree32182a98c82613ac83266c1cd491ee2668a7459b
parent2251c07f73525600c8393c024d4356cb4e2811c3 (diff)
downloadchromium_src-ff72d8700783eadd7b6a05e3cec4e60a57dcabb3.zip
chromium_src-ff72d8700783eadd7b6a05e3cec4e60a57dcabb3.tar.gz
chromium_src-ff72d8700783eadd7b6a05e3cec4e60a57dcabb3.tar.bz2
An attempt to abstract the logic of the various layered windows we're using that are attached to browser UI. I needed another one of these for the extension shelf, and figured I'd try to make one that was generic. Ideally, we'd do more refactoring so that StatusBubbles, InfoBubble, etc. could all share some common code.
BUG=none TEST=none (I'd love some suggestions on what to put into a unit test here) Review URL: http://codereview.chromium.org/113486 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16277 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/views/browser_bubble.cc58
-rw-r--r--chrome/browser/views/browser_bubble.h91
-rw-r--r--chrome/browser/views/browser_bubble_win.cc57
-rw-r--r--chrome/browser/views/browser_views.vcproj12
-rw-r--r--chrome/browser/views/frame/browser_view.cc19
-rw-r--r--chrome/browser/views/frame/browser_view.h12
6 files changed, 248 insertions, 1 deletions
diff --git a/chrome/browser/views/browser_bubble.cc b/chrome/browser/views/browser_bubble.cc
new file mode 100644
index 0000000..cfab7ca
--- /dev/null
+++ b/chrome/browser/views/browser_bubble.cc
@@ -0,0 +1,58 @@
+// 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/views/browser_bubble.h"
+
+#include "app/l10n_util.h"
+#include "views/widget/root_view.h"
+
+BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame,
+ const gfx::Point& origin)
+ : frame_(frame),
+ view_(view),
+ visible_(false),
+ delegate_(NULL) {
+ gfx::Size size = view->GetPreferredSize();
+ bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height());
+ InitPopup();
+}
+
+BrowserBubble::~BrowserBubble() {
+ DestroyPopup();
+}
+
+void BrowserBubble::BrowserWindowMoved() {
+ if (delegate_)
+ delegate_->BubbleBrowserWindowMoved(this);
+ else
+ Hide();
+}
+
+void BrowserBubble::BrowserWindowClosed() {
+ if (delegate_)
+ delegate_->BubbleBrowserWindowClosed(this);
+ else
+ Hide();
+}
+
+void BrowserBubble::SetBounds(int x, int y, int w, int h) {
+ // If the UI layout is RTL, we need to mirror the position of the bubble
+ // relative to the parent.
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
+ gfx::Rect frame_bounds;
+ frame_->GetBounds(&frame_bounds, false);
+ x = frame_bounds.width() - x - w;
+ }
+ bounds_.SetRect(x, y, w, h);
+ Reposition();
+}
+
+void BrowserBubble::Reposition() {
+ gfx::Point top_left;
+ views::View::ConvertPointToScreen(frame_->GetRootView(), &top_left);
+ MovePopup(top_left.x() + bounds_.x(),
+ top_left.y() + bounds_.y(),
+ bounds_.width(),
+ bounds_.height());
+}
diff --git a/chrome/browser/views/browser_bubble.h b/chrome/browser/views/browser_bubble.h
new file mode 100644
index 0000000..49ce7fe
--- /dev/null
+++ b/chrome/browser/views/browser_bubble.h
@@ -0,0 +1,91 @@
+// 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.
+
+#ifndef CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_
+#define CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_
+
+#include "views/view.h"
+#include "views/widget/widget.h"
+
+// A class for creating a floating window that is "attached" to a particular
+// Browser. If you don't install a delegate, the bubble will hide
+// automatically when the browser moves. The bubble is only shown manually.
+// Users are expected to delete the bubble when finished with it.
+class BrowserBubble {
+ public:
+ // Delegate to browser bubble events.
+ class Delegate {
+ public:
+ // Called when the Browser Window that this bubble is attached to moves.
+ virtual void BubbleBrowserWindowMoved(BrowserBubble* bubble) = 0;
+ virtual void BubbleBrowserWindowClosed(BrowserBubble* bubble) = 0;
+ };
+
+ // Note that the bubble will size itself to the preferred size of |view|.
+ // |view| is the embedded view, |frame| is widget that the bubble is being
+ // positioned relative to, |origin| is the location that the bubble will
+ // be positioned relative to |frame|.
+ BrowserBubble(views::View* view, views::Widget* frame,
+ const gfx::Point& origin);
+ virtual ~BrowserBubble();
+
+ // Get/Set the delegate.
+ Delegate* delegate() const { return delegate_; }
+ void set_delegate(Delegate* del) { delegate_ = del; }
+
+ // Notifications from BrowserView.
+ // With no delegate, both of these default to Hiding the bubble.
+ virtual void BrowserWindowMoved();
+ virtual void BrowserWindowClosed();
+
+ // Show or hide the bubble.
+ void Show();
+ void Hide();
+ bool is_visible() const { return visible_; }
+
+ // The contained view.
+ views::View* view() const { return view_; }
+
+ // Set the bounds of the bubble relative to the browser window.
+ void SetBounds(int x, int y, int w, int h);
+ int width() { return bounds_.width(); }
+ int height() { return bounds_.height(); }
+
+ // Reposition the bubble - as we are using a WS_POPUP for the bubble,
+ // we have to manually position it when the browser window moves.
+ void Reposition();
+
+ protected:
+ // Create the popup widget.
+ virtual void InitPopup();
+
+ // Destroy the popup widget.
+ virtual void DestroyPopup();
+
+ // Move the popup to an absolute position.
+ void MovePopup(int x, int y, int w, int h);
+
+ private:
+ // The frame that this bubble is attached to.
+ views::Widget* frame_;
+
+ // The view that is displayed in this bubble.
+ views::View* view_;
+
+ // The actual widget that this bubble is in.
+ scoped_ptr<views::Widget> popup_;
+
+ // The bounds relative to the frame.
+ gfx::Rect bounds_;
+
+ // Current visibility.
+ bool visible_;
+
+ // The delegate isn't owned by the bubble.
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserBubble);
+};
+
+#endif // CHROME_BROWSER_VIEWS_BROWSER_BUBBLE_
diff --git a/chrome/browser/views/browser_bubble_win.cc b/chrome/browser/views/browser_bubble_win.cc
new file mode 100644
index 0000000..7471baa
--- /dev/null
+++ b/chrome/browser/views/browser_bubble_win.cc
@@ -0,0 +1,57 @@
+// 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/views/browser_bubble.h"
+
+#include "app/l10n_util_win.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "views/widget/widget_win.h"
+
+void BrowserBubble::InitPopup() {
+ gfx::NativeView native_view = frame_->GetNativeView();
+ views::WidgetWin* pop = new views::WidgetWin();
+ pop->set_delete_on_destroy(false);
+ pop->set_window_style(WS_POPUP);
+ pop->set_window_ex_style(WS_EX_LAYERED |
+ WS_EX_TOOLWINDOW |
+ l10n_util::GetExtendedTooltipStyles());
+ pop->SetLayeredAlpha(0xFF);
+ pop->Init(native_view, bounds_, false);
+ pop->SetContentsView(view_);
+ popup_.reset(pop);
+ Reposition();
+
+ BrowserView* browser_view = BrowserView::GetBrowserViewForHWND(native_view);
+ DCHECK(browser_view);
+ if (browser_view)
+ browser_view->AttachBrowserBubble(this);
+}
+
+void BrowserBubble::DestroyPopup() {
+ gfx::NativeView native_view = frame_->GetNativeView();
+ BrowserView* browser_view = BrowserView::GetBrowserViewForHWND(native_view);
+ if (browser_view)
+ browser_view->DetachBrowserBubble(this);
+}
+
+void BrowserBubble::MovePopup(int x, int y, int w, int h) {
+ views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_.get());
+ pop->MoveWindow(x, y, w, h);
+}
+
+void BrowserBubble::Show() {
+ if (visible_)
+ return;
+ views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_.get());
+ pop->Show();
+ visible_ = true;
+}
+
+void BrowserBubble::Hide() {
+ if (!visible_)
+ return;
+ views::WidgetWin* pop = static_cast<views::WidgetWin*>(popup_.get());
+ pop->Hide();
+ visible_ = false;
+}
diff --git a/chrome/browser/views/browser_views.vcproj b/chrome/browser/views/browser_views.vcproj
index 75e2939..3039f3c 100644
--- a/chrome/browser/views/browser_views.vcproj
+++ b/chrome/browser/views/browser_views.vcproj
@@ -490,6 +490,18 @@
>
</File>
<File
+ RelativePath=".\browser_bubble.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_bubble.h"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_bubble_win.cc"
+ >
+ </File>
+ <File
RelativePath=".\bug_report_view.cc"
>
</File>
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index e12d4b1..72957ed 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/views/bookmark_bar_view.h"
#include "chrome/browser/views/bookmark_bubble_view.h"
#include "chrome/browser/views/bookmark_manager_view.h"
+#include "chrome/browser/views/browser_bubble.h"
#include "chrome/browser/views/bug_report_view.h"
#include "chrome/browser/views/chrome_views_delegate.h"
#include "chrome/browser/views/clear_browsing_data.h"
@@ -330,6 +331,11 @@ void BrowserView::WindowMoved() {
status_bubble_->Reposition();
+ BubbleSet::iterator bubble = browser_bubbles_.begin();
+ for (; bubble != browser_bubbles_.end(); ++bubble) {
+ (*bubble)->BrowserWindowMoved();
+ }
+
BookmarkBubbleView::Hide();
// Close the omnibox popup, if any.
@@ -507,6 +513,14 @@ void BrowserView::RegisterBrowserViewPrefs(PrefService* prefs) {
kDefaultHungPluginDetectFrequency);
}
+void BrowserView::AttachBrowserBubble(BrowserBubble* bubble) {
+ browser_bubbles_.insert(bubble);
+}
+
+void BrowserView::DetachBrowserBubble(BrowserBubble* bubble) {
+ browser_bubbles_.erase(bubble);
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserView, BrowserWindow implementation:
@@ -540,6 +554,11 @@ void BrowserView::SetBounds(const gfx::Rect& bounds) {
void BrowserView::Close() {
frame_->Close();
+
+ BubbleSet::iterator bubble = browser_bubbles_.begin();
+ for (; bubble != browser_bubbles_.end(); ++bubble) {
+ (*bubble)->BrowserWindowClosed();
+ }
}
void BrowserView::Activate() {
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index 74b04c2..a7a5d31 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_VIEWS_FRAME_BROWSER_VIEW_H_
#define CHROME_BROWSER_VIEWS_FRAME_BROWSER_VIEW_H_
+#include <set>
+
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/hang_monitor/hung_plugin_action.h"
@@ -19,6 +21,7 @@
class BookmarkBarView;
class Browser;
+class BrowserBubble;
class BrowserToolbarView;
class EncodingMenuControllerDelegate;
class ExtensionShelf;
@@ -163,6 +166,10 @@ class BrowserView : public BrowserWindow,
// Register preferences specific to this view.
static void RegisterBrowserViewPrefs(PrefService* prefs);
+ // Attach/Detach a BrowserBubble to the browser.
+ void AttachBrowserBubble(BrowserBubble *bubble);
+ void DetachBrowserBubble(BrowserBubble *bubble);
+
// Overridden from BrowserWindow:
virtual void Show();
virtual void SetBounds(const gfx::Rect& bounds);
@@ -280,7 +287,7 @@ class BrowserView : public BrowserWindow,
int LayoutDownloadShelf(int bottom);
// Layout the Status Bubble.
void LayoutStatusBubble(int top);
- // Layout the Extension Bottom Bar
+ // Layout the Extension Shelf
int LayoutExtensionShelf();
// Prepare to show the Bookmark Bar for the specified TabContents. Returns
@@ -409,6 +416,9 @@ class BrowserView : public BrowserWindow,
// A bottom bar for showing extensions.
ExtensionShelf* extension_shelf_;
+ typedef std::set<BrowserBubble*> BubbleSet;
+ BubbleSet browser_bubbles_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};