summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 16:40:39 +0000
committererikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 16:40:39 +0000
commit0d3bd4daa8b2b851dca9410a18ec5981c1086fc7 (patch)
tree6d6ce3d0aa0bba59e274d32a8f40a96b3dbd0c7b /chrome
parent89d7ac15b518146cc57a7cc8df6b73bcf36a1c19 (diff)
downloadchromium_src-0d3bd4daa8b2b851dca9410a18ec5981c1086fc7.zip
chromium_src-0d3bd4daa8b2b851dca9410a18ec5981c1086fc7.tar.gz
chromium_src-0d3bd4daa8b2b851dca9410a18ec5981c1086fc7.tar.bz2
Add a handle to the ExtensionShelf. This is how users will drag extension toolstrips around, and perhaps where we'll add other UI for manipulating an extension.
BUG=none TEST=none depends on the following other changes: http://codereview.chromium.org/113481 http://codereview.chromium.org/113486 http://codereview.chromium.org/113466 Review URL: http://codereview.chromium.org/113483 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16284 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_host.cc10
-rw-r--r--chrome/browser/extensions/extension_host.h2
-rw-r--r--chrome/browser/extensions/extension_shelf.cc215
-rw-r--r--chrome/browser/extensions/extension_shelf.h52
-rw-r--r--chrome/browser/extensions/extension_view.cc12
-rw-r--r--chrome/browser/extensions/extension_view.h19
6 files changed, 305 insertions, 5 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index e2f202a..a38fdd5 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -155,6 +155,16 @@ void ExtensionHost::TakeFocus(bool reverse) {
void ExtensionHost::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
}
+void ExtensionHost::HandleMouseEvent() {
+ if (view_)
+ view_->HandleMouseEvent();
+}
+
+void ExtensionHost::HandleMouseLeave() {
+ if (view_)
+ view_->HandleMouseLeave();
+}
+
Browser* ExtensionHost::GetBrowser() {
if (view_)
return view_->browser();
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index d8e9a50..a6e19d9 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -72,6 +72,8 @@ class ExtensionHost : public RenderViewHostDelegate,
virtual void UpdateDragCursor(bool is_drop_target);
virtual void TakeFocus(bool reverse);
virtual void HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
+ virtual void HandleMouseEvent();
+ virtual void HandleMouseLeave();
virtual void UpdatePreferredWidth(int pref_width);
private:
diff --git a/chrome/browser/extensions/extension_shelf.cc b/chrome/browser/extensions/extension_shelf.cc
index 6b765d8..17623b6 100644
--- a/chrome/browser/extensions/extension_shelf.cc
+++ b/chrome/browser/extensions/extension_shelf.cc
@@ -4,7 +4,9 @@
#include "chrome/browser/extensions/extension_shelf.h"
+#include "app/resource_bundle.h"
#include "base/logging.h"
+#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/extensions/extension.h"
#include "chrome/browser/extensions/extension_process_manager.h"
@@ -13,6 +15,7 @@
#include "chrome/browser/profile.h"
#include "chrome/common/notification_service.h"
#include "skia/ext/skia_utils.h"
+#include "views/controls/label.h"
namespace {
@@ -36,6 +39,14 @@ static const SkColor kBackgroundColor = SkColorSetRGB(230, 237, 244);
static const SkColor kBorderColor = SkColorSetRGB(201, 212, 225);
static const SkColor kDividerHighlightColor = SkColorSetRGB(247, 250, 253);
+// Text colors for the handle
+static const SkColor kHandleTextColor = SkColorSetRGB(6, 45, 117);
+static const SkColor kHandleTextHighlightColor =
+ SkColorSetARGB(200, 255, 255, 255);
+
+// Handle padding
+static const int kHandlePadding = 4;
+
// TODO(erikkay) convert back to a gradient when Glen figures out the
// specs.
// static const SkColor kBackgroundColor = SkColorSetRGB(237, 244, 252);
@@ -44,7 +55,96 @@ static const SkColor kDividerHighlightColor = SkColorSetRGB(247, 250, 253);
} // namespace
-ExtensionShelf::ExtensionShelf(Browser* browser) : browser_(browser) {
+// A small handle that is used for dragging or otherwise interacting with an
+// extension toolstrip.
+class ExtensionShelfHandle : public views::View {
+ public:
+ explicit ExtensionShelfHandle(ExtensionShelf* shelf);
+
+ // The ExtensionView that the handle is attached to.
+ void SetExtensionView(ExtensionView* v);
+
+ // View
+ virtual void Paint(gfx::Canvas* canvas);
+ virtual gfx::Size GetPreferredSize();
+ virtual void Layout();
+ virtual void OnMouseEntered(const views::MouseEvent& event);
+ virtual void OnMouseExited(const views::MouseEvent& event);
+
+ private:
+ ExtensionShelf* shelf_;
+ ExtensionView* extension_view_;
+ views::Label* title_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionShelfHandle);
+};
+
+ExtensionShelfHandle::ExtensionShelfHandle(ExtensionShelf* shelf)
+ : shelf_(shelf), extension_view_(NULL) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ title_ = new views::Label(L"", rb.GetFont(ResourceBundle::BaseFont));
+
+ // Set enabled to false so we get the events.
+ title_->SetEnabled(false);
+
+ // Set the colors afterwards so that the label doesn't get a disabled
+ // color.
+ title_->SetColor(kHandleTextColor);
+ title_->SetDrawHighlighted(true);
+ title_->SetHighlightColor(kHandleTextHighlightColor);
+ title_->SetBounds(kHandlePadding, kHandlePadding, 100, 100);
+ title_->SizeToPreferredSize();
+ AddChildView(title_);
+}
+
+void ExtensionShelfHandle::SetExtensionView(ExtensionView* v) {
+ extension_view_ = v;
+ title_->SetText(UTF8ToWide(extension_view_->extension()->name()));
+ title_->SizeToPreferredSize();
+ SizeToPreferredSize();
+}
+
+void ExtensionShelfHandle::Paint(gfx::Canvas* canvas) {
+ canvas->FillRectInt(kBackgroundColor, 0, 0, width(), height());
+ canvas->FillRectInt(kBorderColor, 0, 0, width(), 1);
+ canvas->FillRectInt(kBorderColor, 0, 0, 1, height() - 1);
+ canvas->FillRectInt(kBorderColor, width() - 1, 0, 1, height() - 1);
+ int ext_width = extension_view_->width() + kToolstripPadding +
+ kToolstripDividerWidth;
+ if (ext_width < width()) {
+ canvas->FillRectInt(kBorderColor, ext_width, height() - 1,
+ width() - ext_width, 1);
+ }
+}
+
+gfx::Size ExtensionShelfHandle::GetPreferredSize() {
+ gfx::Size sz = title_->GetPreferredSize();
+ sz.Enlarge(kHandlePadding * 2, kHandlePadding * 2);
+ return sz;
+}
+
+void ExtensionShelfHandle::Layout() {
+}
+
+void ExtensionShelfHandle::OnMouseEntered(const views::MouseEvent& event) {
+ DCHECK(extension_view_);
+ shelf_->OnExtensionMouseEvent(extension_view_);
+}
+
+void ExtensionShelfHandle::OnMouseExited(const views::MouseEvent& event) {
+ DCHECK(extension_view_);
+ shelf_->OnExtensionMouseLeave(extension_view_);
+}
+
+
+////////////////////////////////////////////////
+
+ExtensionShelf::ExtensionShelf(Browser* browser)
+ : browser_(browser),
+ handle_(NULL),
+ handle_visible_(false),
+ current_handle_view_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(timer_factory_(this)) {
// Watch extensions loaded notification.
NotificationService* ns = NotificationService::current();
Source<Profile> ns_source(browser->profile()->GetOriginalProfile());
@@ -68,6 +168,17 @@ ExtensionShelf::~ExtensionShelf() {
NotificationService::AllSources());
}
+BrowserBubble* ExtensionShelf::GetHandle() {
+ if (!handle_.get() && HasExtensionViews() && current_handle_view_) {
+ ExtensionShelfHandle* handle_view = new ExtensionShelfHandle(this);
+ handle_view->SetExtensionView(current_handle_view_);
+ handle_.reset(new BrowserBubble(handle_view, GetWidget(),
+ gfx::Point(0, 0)));
+ handle_->set_delegate(this);
+ }
+ return handle_.get();
+}
+
void ExtensionShelf::Paint(gfx::Canvas* canvas) {
#if 0
// TODO(erikkay) re-enable this when Glen has the gradient values worked out.
@@ -130,9 +241,27 @@ void ExtensionShelf::Layout() {
child->Layout();
x = next_x + kToolstripDividerWidth;
}
+ if (handle_.get())
+ LayoutShelfHandle();
SchedulePaint();
}
+void ExtensionShelf::OnMouseEntered(const views::MouseEvent& event) {
+ int count = GetChildViewCount();
+ for (int i = 0; i < count; ++i) {
+ ExtensionView* child = static_cast<ExtensionView*>(GetChildViewAt(i));
+ if (event.x() > (child->x() + child->width() + kToolstripPadding))
+ continue;
+ current_handle_view_ = child;
+ ShowShelfHandle();
+ break;
+ }
+}
+
+void ExtensionShelf::OnMouseExited(const views::MouseEvent& event) {
+ HideShelfHandle(100);
+}
+
void ExtensionShelf::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
@@ -165,6 +294,7 @@ bool ExtensionShelf::AddExtensionViews(const ExtensionList* extensions) {
if (!background_.empty())
toolstrip->SetBackground(background_);
AddChildView(toolstrip);
+ toolstrip->SetContainer(this);
added_toolstrip = true;
}
}
@@ -180,6 +310,28 @@ bool ExtensionShelf::HasExtensionViews() {
return GetChildViewCount() > 0;
}
+void ExtensionShelf::OnExtensionMouseEvent(ExtensionView* view) {
+ if (view != current_handle_view_) {
+ current_handle_view_ = view;
+ }
+ ShowShelfHandle();
+}
+
+void ExtensionShelf::OnExtensionMouseLeave(ExtensionView* view) {
+ if (view == current_handle_view_) {
+ HideShelfHandle(100);
+ }
+}
+
+void ExtensionShelf::BubbleBrowserWindowMoved(BrowserBubble* bubble) {
+ HideShelfHandle(0);
+}
+
+void ExtensionShelf::BubbleBrowserWindowClosed(BrowserBubble* bubble) {
+ // We'll be going away shortly, so no need to do any other teardown here.
+ HideShelfHandle(0);
+}
+
void ExtensionShelf::InitBackground(gfx::Canvas* canvas,
const SkRect& subset) {
if (!background_.empty())
@@ -214,3 +366,64 @@ void ExtensionShelf::InitBackground(gfx::Canvas* canvas,
for (int i = 0; i < count; ++i)
static_cast<ExtensionView*>(GetChildViewAt(i))->SetBackground(background_);
}
+
+void ExtensionShelf::ShowShelfHandle() {
+ if (!timer_factory_.empty())
+ timer_factory_.RevokeAll();
+ if (handle_visible_) {
+ // The contents may have changed, even though the handle is still visible.
+ LayoutShelfHandle();
+ return;
+ }
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ timer_factory_.NewRunnableMethod(&ExtensionShelf::DoShowShelfHandle),
+ 1000);
+}
+
+void ExtensionShelf::DoShowShelfHandle() {
+ if (!handle_visible_) {
+ handle_visible_ = true;
+ LayoutShelfHandle();
+ handle_->Show();
+ }
+}
+
+void ExtensionShelf::HideShelfHandle(int delay_ms) {
+ if (!timer_factory_.empty())
+ timer_factory_.RevokeAll();
+ if (!handle_visible_)
+ return;
+ if (delay_ms) {
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ timer_factory_.NewRunnableMethod(&ExtensionShelf::DoHideShelfHandle),
+ delay_ms);
+ } else {
+ DoHideShelfHandle();
+ }
+}
+
+void ExtensionShelf::DoHideShelfHandle() {
+ if (handle_visible_) {
+ handle_visible_ = false;
+ handle_->Hide();
+ // TODO(erikkay) with this enabled, I get an odd crash shortly after hide.
+ //handle_.reset(NULL);
+ current_handle_view_ = NULL;
+ }
+}
+
+void ExtensionShelf::LayoutShelfHandle() {
+ if (current_handle_view_) {
+ GetHandle(); // ensure that the handle exists since we delete on hide
+ ExtensionShelfHandle* handle_view =
+ static_cast<ExtensionShelfHandle*>(GetHandle()->view());
+ handle_view->SetExtensionView(current_handle_view_);
+ int width = std::max(current_handle_view_->width(), handle_view->width());
+ gfx::Point origin(-kToolstripPadding,
+ -(handle_view->height() + kToolstripPadding - 1));
+ views::View::ConvertPointToWidget(current_handle_view_, &origin);
+ handle_view->SetBounds(0, 0, width, handle_view->height());
+ handle_->SetBounds(origin.x(), origin.y(),
+ width, handle_view->height());
+ }
+}
diff --git a/chrome/browser/extensions/extension_shelf.h b/chrome/browser/extensions/extension_shelf.h
index ccfa745..4bc88eb 100644
--- a/chrome/browser/extensions/extension_shelf.h
+++ b/chrome/browser/extensions/extension_shelf.h
@@ -5,25 +5,41 @@
#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_SHELF_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SHELF_H_
-#include "chrome/browser/extensions/extensions_service.h"
#include "app/gfx/canvas.h"
+#include "base/task.h"
+#include "chrome/browser/extensions/extension_view.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/views/browser_bubble.h"
#include "chrome/common/notification_observer.h"
#include "views/view.h"
class Browser;
+class ExtensionShelfHandle;
+namespace views {
+ class Label;
+ class MouseEvent;
+}
+// A shelf that contains Extension toolstrips.
class ExtensionShelf : public views::View,
- public NotificationObserver {
+ public NotificationObserver,
+ public ExtensionContainer,
+ public BrowserBubble::Delegate {
public:
explicit ExtensionShelf(Browser* browser);
virtual ~ExtensionShelf();
+ // Return the current active ExtensionShelfHandle (if any).
+ BrowserBubble* GetHandle();
+
// View
virtual void Paint(gfx::Canvas* canvas);
virtual gfx::Size GetPreferredSize();
virtual void Layout();
+ virtual void OnMouseExited(const views::MouseEvent& event);
+ virtual void OnMouseEntered(const views::MouseEvent& event);
- // NotificationService method.
+ // NotificationService
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
@@ -31,6 +47,14 @@ class ExtensionShelf : public views::View,
bool AddExtensionViews(const ExtensionList* extensions);
bool HasExtensionViews();
+ // ExtensionContainer
+ virtual void OnExtensionMouseEvent(ExtensionView* view);
+ virtual void OnExtensionMouseLeave(ExtensionView* view);
+
+ // BrowserBubble::Delegate
+ virtual void BubbleBrowserWindowMoved(BrowserBubble* bubble);
+ virtual void BubbleBrowserWindowClosed(BrowserBubble* bubble);
+
protected:
// View
virtual void ChildPreferredSizeChanged(View* child);
@@ -39,11 +63,33 @@ class ExtensionShelf : public views::View,
// Inits the background bitmap.
void InitBackground(gfx::Canvas* canvas, const SkRect& subset);
+ // Show / Hide the shelf handle.
+ void ShowShelfHandle();
+ void DoShowShelfHandle();
+ void HideShelfHandle(int delay_ms);
+ void DoHideShelfHandle();
+
+ // Adjust shelf handle size and position.
+ void LayoutShelfHandle();
+
+ // Which browser window this shelf is in.
Browser* browser_;
// Background bitmap to draw under extension views.
SkBitmap background_;
+ // The current shelf handle.
+ scoped_ptr<BrowserBubble> handle_;
+
+ // Whether to handle is visible;
+ bool handle_visible_;
+
+ // Which child view the handle is currently over.
+ ExtensionView* current_handle_view_;
+
+ // Timers for tracking mouse hovering.
+ ScopedRunnableMethodFactory<ExtensionShelf> timer_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionShelf);
};
diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc
index 38028d7..a3a6bc5 100644
--- a/chrome/browser/extensions/extension_view.cc
+++ b/chrome/browser/extensions/extension_view.cc
@@ -15,7 +15,7 @@
ExtensionView::ExtensionView(ExtensionHost* host, Browser* browser,
const GURL& content_url)
: host_(host), browser_(browser), content_url_(content_url),
- initialized_(false) {
+ initialized_(false), container_(NULL) {
host_->set_view(this);
}
@@ -114,3 +114,13 @@ void ExtensionView::ViewHierarchyChanged(bool is_add,
}
}
}
+
+void ExtensionView::HandleMouseEvent() {
+ if (container_)
+ container_->OnExtensionMouseEvent(this);
+}
+
+void ExtensionView::HandleMouseLeave() {
+ if (container_)
+ container_->OnExtensionMouseLeave(this);
+}
diff --git a/chrome/browser/extensions/extension_view.h b/chrome/browser/extensions/extension_view.h
index d58fdc7..6f27249 100644
--- a/chrome/browser/extensions/extension_view.h
+++ b/chrome/browser/extensions/extension_view.h
@@ -23,6 +23,15 @@
class Browser;
class Extension;
+// A class that represents the container that this view is in.
+// (bottom shelf, side bar, etc.)
+class ExtensionContainer {
+ public:
+ // Mouse event notifications from the view. (useful for hover UI).
+ virtual void OnExtensionMouseEvent(ExtensionView* view) = 0;
+ virtual void OnExtensionMouseLeave(ExtensionView* view) = 0;
+};
+
// This handles the display portion of an ExtensionHost.
class ExtensionView : public views::HWNDView {
public:
@@ -36,16 +45,22 @@ class ExtensionView : public views::HWNDView {
// Notification from ExtensionHost.
void DidContentsPreferredWidthChange(const int pref_width);
+ void HandleMouseEvent();
+ void HandleMouseLeave();
// Set a custom background for the view. The background will be tiled.
void SetBackground(const SkBitmap& background);
+ // Sets the container for this view.
+ void SetContainer(ExtensionContainer* container) { container_ = container; }
+
// views::HWNDView
virtual void SetVisible(bool is_visible);
virtual void DidChangeBounds(const gfx::Rect& previous,
const gfx::Rect& current);
virtual void ViewHierarchyChanged(bool is_add,
views::View *parent, views::View *child);
+
private:
friend class ExtensionHost;
@@ -72,6 +87,10 @@ class ExtensionView : public views::HWNDView {
// loaded.
int pending_preferred_width_;
+ // The container this view is in (not necessarily its direct superview).
+ // Note: the view does not own its container.
+ ExtensionContainer* container_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionView);
};