| Index: chrome/browser/views/extensions/extension_shelf.cc
|
| diff --git a/chrome/browser/views/extensions/extension_shelf.cc b/chrome/browser/views/extensions/extension_shelf.cc
|
| deleted file mode 100644
|
| index 000c9889fbaca52aa3062e4f481423bb386cbe56..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/views/extensions/extension_shelf.cc
|
| +++ /dev/null
|
| @@ -1,1108 +0,0 @@
|
| -// Copyright (c) 2010 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/extensions/extension_shelf.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "app/resource_bundle.h"
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/stl_util-inl.h"
|
| -#include "base/string_util.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/browser.h"
|
| -#include "chrome/browser/browser_theme_provider.h"
|
| -#include "chrome/browser/extensions/extension_host.h"
|
| -#include "chrome/browser/extensions/extension_process_manager.h"
|
| -#include "chrome/browser/extensions/extensions_service.h"
|
| -#include "chrome/browser/profile.h"
|
| -#include "chrome/browser/tab_contents/tab_contents.h"
|
| -#include "chrome/browser/views/extensions/extension_view.h"
|
| -#include "chrome/browser/view_ids.h"
|
| -#include "chrome/common/chrome_switches.h"
|
| -#include "chrome/common/extensions/extension.h"
|
| -#include "chrome/common/notification_service.h"
|
| -#include "chrome/common/pref_names.h"
|
| -#include "gfx/canvas_skia.h"
|
| -#include "views/controls/label.h"
|
| -#include "views/screen.h"
|
| -#include "views/widget/root_view.h"
|
| -
|
| -namespace {
|
| -
|
| -// This is the slight padding that is there around the edge of the browser. This
|
| -// has been determined empirically.
|
| -// TODO(sidchat): Compute this value from the root view of the extension shelf.
|
| -static const int kExtensionShelfPaddingOnLeft = 4;
|
| -
|
| -// Margins around the content.
|
| -static const int kTopMarginWhenExtensionsOnTop = 1;
|
| -static const int kTopMarginWhenExtensionsOnBottom = 2;
|
| -static const int kBottomMargin = 2;
|
| -static const int kLeftMargin = 0;
|
| -static const int kRightMargin = 0;
|
| -
|
| -// Padding on left and right side of an extension toolstrip.
|
| -static const int kToolstripPadding = 2;
|
| -
|
| -// Width of the toolstrip divider.
|
| -static const int kToolstripDividerWidth = 2;
|
| -
|
| -// Preferred height of the ExtensionShelf.
|
| -static const int kShelfHeight = 29;
|
| -
|
| -// Preferred height of the Extension shelf when only shown on the new tab page.
|
| -const int kNewtabShelfHeight = 58;
|
| -
|
| -// How inset the extension shelf is when displayed on the new tab page. This is
|
| -// in addition to the margins above.
|
| -static const int kNewtabHorizontalPadding = 8;
|
| -static const int kNewtabVerticalPadding = 12;
|
| -
|
| -// We need an extra margin to the left of all the toolstrips in detached mode,
|
| -// so that the first toolstrip doesn't look so squished against the rounded
|
| -// corners of the extension shelf.
|
| -static const int kNewtabExtraHorMargin = 2;
|
| -static const int kNewtabExtraVerMargin = 2;
|
| -
|
| -// Padding for the title inside the handle.
|
| -static const int kHandlePadding = 4;
|
| -
|
| -// Inset for the extension view when displayed either dragging or expanded.
|
| -static const int kWindowInset = 1;
|
| -
|
| -// Delays for showing and hiding the shelf handle.
|
| -static const int kShowDelayMs = 500;
|
| -static const int kHideDelayMs = 300;
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -// A view that holds the place for a toolstrip in the shelf while the toolstrip
|
| -// is being dragged or moved.
|
| -// TODO(erikkay) this should draw a dimmed out version of the toolstrip.
|
| -class ExtensionShelf::PlaceholderView : public views::View {
|
| - public:
|
| - PlaceholderView() {}
|
| -
|
| - void SetWidth(int width) {
|
| - SetBounds(x(), y(), width, height());
|
| - PreferredSizeChanged();
|
| - }
|
| -
|
| - // ExtensionShelf resizes its views to their preferred size at layout,
|
| - // so just always prefer the current size.
|
| - gfx::Size GetPreferredSize() { return size(); }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(PlaceholderView);
|
| -};
|
| -
|
| -// A wrapper class for the ExtensionHost displayed as a toolstrip.
|
| -// The class itself also acts as the View for the handle of the toolstrip
|
| -// it represents.
|
| -class ExtensionShelf::Toolstrip : public views::View,
|
| - public BrowserBubble::Delegate,
|
| - public AnimationDelegate {
|
| - public:
|
| - Toolstrip(ExtensionShelf* shelf, ExtensionHost* host,
|
| - const Extension::ToolstripInfo& info);
|
| - virtual ~Toolstrip();
|
| -
|
| - // Convenience to calculate just the size of the handle.
|
| - gfx::Size GetHandlePreferredSize();
|
| -
|
| - // View methods:
|
| - 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);
|
| - virtual bool OnMousePressed(const views::MouseEvent& event);
|
| - virtual bool OnMouseDragged(const views::MouseEvent& event);
|
| - virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
|
| - virtual bool IsFocusable() const { return true; }
|
| - virtual void ChildPreferredSizeChanged(View* child);
|
| -
|
| - // Adjust the size and position of the window/handle.
|
| - void LayoutWindow();
|
| -
|
| - // Is the toolstrip window visible (not necessarily the handle).
|
| - bool window_visible() { return (window_.get() && window_->visible()); }
|
| -
|
| - // Is the handle for this toolstrip currently visible.
|
| - bool handle_visible() { return (window_visible() && handle_visible_); }
|
| -
|
| - // Is the toolstrip opened in expanded mode.
|
| - bool expanded() { return expanded_; }
|
| -
|
| - // Is the toolstrip being dragged.
|
| - bool dragging() { return dragging_; }
|
| -
|
| - // Accessors for the host and its view.
|
| - ExtensionHost* host() const { return host_; }
|
| - ExtensionView* view() const { return host_->view(); }
|
| -
|
| - // The view that's currently displayed in the shelf. This could be
|
| - // either the ExtensionView or |placeholder_view_| depending on the
|
| - // current state.
|
| - View* GetShelfView() const {
|
| - if (placeholder_view_)
|
| - return placeholder_view_;
|
| - return view();
|
| - }
|
| -
|
| - // Detaching the toolstrip from the shelf means that the ExtensionView is
|
| - // displayed inside of the BrowserBubble rather than the shelf. This may
|
| - // still visually appear to be part of the shelf (expanded) or completely
|
| - // separate (dragging).
|
| - // If |browser| is true, it also will detach/attach to the browser window.
|
| - void DetachFromShelf(bool browser);
|
| - void AttachToShelf(bool browser);
|
| -
|
| - // Show / Hide the shelf handle.
|
| - void ShowShelfHandle();
|
| - void DoShowShelfHandle();
|
| - void HideShelfHandle(int delay_ms);
|
| - void DoHideShelfHandle();
|
| - void StopHandleTimer();
|
| - void HideWindow();
|
| - void ShowWindow();
|
| -
|
| - // Expand / Collapse
|
| - void Expand(int height, const GURL& url);
|
| - void Collapse(const GURL& url);
|
| -
|
| - // BrowserBubble::Delegate
|
| - virtual void BubbleBrowserWindowMoved(BrowserBubble* bubble);
|
| - virtual void BubbleBrowserWindowClosing(BrowserBubble* bubble);
|
| -
|
| - // AnimationDelegate
|
| - virtual void AnimationProgressed(const Animation* animation);
|
| - virtual void AnimationEnded(const Animation* animation);
|
| -
|
| - private:
|
| - // The actual renderer that this toolstrip contains.
|
| - ExtensionHost* host_;
|
| -
|
| - // Manifest definition of this toolstrip.
|
| - Extension::ToolstripInfo info_;
|
| -
|
| - // A window that can be logically attached to the browser window. This is
|
| - // used for two purposes: a handle that sits above the toolstrip when it's
|
| - // collapsed and not dragging, and as a container for the toolstrip when it's
|
| - // dragging or expanded.
|
| - scoped_ptr<BrowserBubble> window_;
|
| -
|
| - // Used for drawing the name of the extension in the handle.
|
| - scoped_ptr<views::Label> title_;
|
| -
|
| - // Pointer back to the containing shelf.
|
| - ExtensionShelf* shelf_;
|
| -
|
| - // When dragging, a placeholder view is put into the shelf to hold space
|
| - // for the ExtensionView. This view is parent owned when it's in the view
|
| - // hierarchy, so there's no ownership issues here.
|
| - PlaceholderView* placeholder_view_;
|
| -
|
| - // Current state of the toolstrip, currently can't both be expanded and
|
| - // dragging.
|
| - // TODO(erikkay) Support dragging while expanded.
|
| - bool dragging_;
|
| - bool expanded_;
|
| - bool handle_visible_;
|
| -
|
| - // The target expanded height of the toolstrip (used for animation).
|
| - int expanded_height_;
|
| -
|
| - // If dragging, where did the drag start from.
|
| - gfx::Point initial_drag_location_;
|
| -
|
| - // We have to remember the initial drag point in screen coordinates, because
|
| - // later, when the toolstrip is being dragged around, there is no good way of
|
| - // computing the screen coordinates given the initial drag view coordinates.
|
| - gfx::Point initial_drag_screen_point_;
|
| -
|
| - // Timers for tracking mouse hovering.
|
| - ScopedRunnableMethodFactory<ExtensionShelf::Toolstrip> timer_factory_;
|
| -
|
| - // Animate opening and closing the mole.
|
| - scoped_ptr<SlideAnimation> mole_animation_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Toolstrip);
|
| -};
|
| -
|
| -ExtensionShelf::Toolstrip::Toolstrip(ExtensionShelf* shelf,
|
| - ExtensionHost* host,
|
| - const Extension::ToolstripInfo& info)
|
| - : host_(host),
|
| - info_(info),
|
| - shelf_(shelf),
|
| - placeholder_view_(NULL),
|
| - dragging_(false),
|
| - expanded_(false),
|
| - handle_visible_(false),
|
| - expanded_height_(0),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(timer_factory_(this)) {
|
| - DCHECK(host->view());
|
| - // We're owned by shelf_, not the bubble that we get inserted in and out of.
|
| - set_parent_owned(false);
|
| -
|
| - mole_animation_.reset(new SlideAnimation(this));
|
| -
|
| - std::wstring name = UTF8ToWide(host_->extension()->name());
|
| - // |title_| isn't actually put in the view hierarchy. We just use it
|
| - // to draw in place. The reason for this is so that we can properly handle
|
| - // the various mouse events necessary for hovering and dragging.
|
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| - title_.reset(new views::Label(name, rb.GetFont(ResourceBundle::BaseFont)));
|
| - title_->SetBounds(kHandlePadding, kHandlePadding, 100, 100);
|
| - title_->SizeToPreferredSize();
|
| -
|
| - SizeToPreferredSize();
|
| -}
|
| -
|
| -ExtensionShelf::Toolstrip::~Toolstrip() {
|
| - if (window_.get() && window_->attached())
|
| - window_->DetachFromBrowser();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::Paint(gfx::Canvas* canvas) {
|
| - // Paint the background.
|
| - SkColor theme_toolbar_color =
|
| - shelf_->GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
|
| - canvas->FillRectInt(theme_toolbar_color, 0, 0, width(), height());
|
| -
|
| - // Paints the handle for the toolstrip (only called on mouse-hover).
|
| - SkColor border_color = ResourceBundle::toolbar_separator_color;
|
| - canvas->FillRectInt(border_color, 0, 0, width(), 1);
|
| - canvas->FillRectInt(border_color, 0, 0, 1, height() - 1);
|
| - canvas->FillRectInt(border_color, width() - 1, 0, 1, height() - 1);
|
| - int ext_width = view()->width() + kToolstripPadding +
|
| - kToolstripDividerWidth;
|
| - if (ext_width < width()) {
|
| - canvas->FillRectInt(border_color, ext_width, height() - 1,
|
| - width() - ext_width, 1);
|
| - }
|
| -
|
| - if (handle_visible_) {
|
| - // Draw the title using a Label as a stamp.
|
| - // See constructor for comment about this.
|
| - title_->ProcessPaint(canvas);
|
| -
|
| - if (dragging_) {
|
| - // When we're dragging, draw the bottom border.
|
| - canvas->FillRectInt(border_color, 0, height() - 1, width(), 1);
|
| - }
|
| - }
|
| -}
|
| -
|
| -gfx::Size ExtensionShelf::Toolstrip::GetHandlePreferredSize() {
|
| - gfx::Size sz;
|
| - if (handle_visible_) {
|
| - sz = title_->GetPreferredSize();
|
| - sz.set_width(std::max(view()->width(), sz.width()));
|
| - sz.Enlarge(2 + kHandlePadding * 2, kHandlePadding * 2);
|
| - }
|
| - return sz;
|
| -}
|
| -
|
| -gfx::Size ExtensionShelf::Toolstrip::GetPreferredSize() {
|
| - gfx::Size sz;
|
| - if (handle_visible_)
|
| - sz = GetHandlePreferredSize();
|
| - if (view()->GetParent() == this) {
|
| - gfx::Size extension_size = view()->GetPreferredSize();
|
| - sz.Enlarge(0, extension_size.height());
|
| - sz.set_width(extension_size.width());
|
| - }
|
| -
|
| - // The view is inset slightly when displayed in the window.
|
| - sz.Enlarge(kWindowInset * 2, kWindowInset * 2);
|
| - return sz;
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::Layout() {
|
| - if (view()->GetParent() == this) {
|
| - int view_y = kWindowInset;
|
| - if (handle_visible_)
|
| - view_y += GetHandlePreferredSize().height();
|
| - view()->SetBounds(kWindowInset, view_y, view()->width(), view()->height());
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::OnMouseEntered(const views::MouseEvent& event) {
|
| - if (dragging_)
|
| - return;
|
| - ShowShelfHandle();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::OnMouseExited(const views::MouseEvent& event) {
|
| - if (dragging_)
|
| - return;
|
| - HideShelfHandle(kHideDelayMs);
|
| -}
|
| -
|
| -bool ExtensionShelf::Toolstrip::OnMousePressed(const views::MouseEvent& event) {
|
| - initial_drag_location_ = event.location();
|
| - initial_drag_screen_point_ = views::Screen::GetCursorScreenPoint();
|
| - return true;
|
| -}
|
| -
|
| -bool ExtensionShelf::Toolstrip::OnMouseDragged(const views::MouseEvent& event) {
|
| - if (expanded_) {
|
| - // Do nothing for now.
|
| - } else if (!dragging_) {
|
| - int y_delta = abs(initial_drag_location_.y() - event.location().y());
|
| - int x_delta = abs(initial_drag_location_.x() - event.location().x());
|
| - if (y_delta > GetVerticalDragThreshold() ||
|
| - x_delta > GetHorizontalDragThreshold()) {
|
| - dragging_ = true;
|
| - StopHandleTimer();
|
| - DetachFromShelf(true);
|
| - }
|
| - } else {
|
| - // When freely dragging a window, you can really only trust the
|
| - // actual screen point. Local coordinate conversions don't work.
|
| - gfx::Point screen = views::Screen::GetCursorScreenPoint();
|
| -
|
| - // However, the handle is actually a child of the browser window
|
| - // so we need to convert it back to local coordinates.
|
| - gfx::Point origin(0, 0);
|
| - views::View::ConvertPointToScreen(shelf_->GetRootView(), &origin);
|
| - int screen_x = screen.x() - initial_drag_location_.x() - origin.x();
|
| -
|
| - // Restrict the horizontal and vertical motions of the toolstrip so that it
|
| - // cannot be dragged out of the extension shelf. If the extension shelf is
|
| - // on the top along with the bookmark bar, the toolstrip cannot be dragged
|
| - // into the space allocated for bookmarks. The toolstrip cannot be dragged
|
| - // out of the browser window.
|
| - if (screen_x < kExtensionShelfPaddingOnLeft) {
|
| - screen_x = kExtensionShelfPaddingOnLeft;
|
| - } else if (screen_x > shelf_->width() - width() +
|
| - kExtensionShelfPaddingOnLeft) {
|
| - screen_x = shelf_->width() - width() + kExtensionShelfPaddingOnLeft;
|
| - }
|
| - screen.set_x(screen_x);
|
| - screen.set_y(initial_drag_screen_point_.y() - origin.y() -
|
| - initial_drag_location_.y());
|
| -
|
| - // TODO(erikkay) as this gets dragged around, update the placeholder view
|
| - // on the shelf to show where it will get dropped to.
|
| - window_->MoveTo(screen.x(), screen.y());
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::OnMouseReleased(const views::MouseEvent& event,
|
| - bool canceled) {
|
| - StopHandleTimer();
|
| - if (dragging_) {
|
| - // Drop the toolstrip roughly where it is now.
|
| - views::View::OnMouseReleased(event, canceled);
|
| - dragging_ = false;
|
| - // |this| and |shelf_| are in different view hierarchies, so we need to
|
| - // convert to screen coordinates and back again to map locations.
|
| - gfx::Point loc = event.location();
|
| - View::ConvertPointToScreen(this, &loc);
|
| - View::ConvertPointToView(NULL, shelf_, &loc);
|
| - shelf_->DropExtension(this, loc, canceled);
|
| - AttachToShelf(true);
|
| - } else if (!canceled) {
|
| - // Toggle mole to either expanded or collapsed.
|
| - // TODO(erikkay) If there's no valid URL in the manifest, should we
|
| - // post an event to the toolstrip in this case?
|
| - if (expanded_) {
|
| - if (info_.toolstrip.is_valid())
|
| - shelf_->CollapseToolstrip(host_, info_.toolstrip);
|
| - } else {
|
| - if (info_.mole.is_valid())
|
| - shelf_->ExpandToolstrip(host_, info_.mole, info_.mole_height);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::LayoutWindow() {
|
| - if (!window_visible() && !handle_visible_ && !expanded_)
|
| - return;
|
| -
|
| - if (!window_.get()) {
|
| - window_.reset(new BrowserBubble(this, shelf_->GetWidget(),
|
| - gfx::Point(0, 0),
|
| - false)); // Do not add a drop-shadow.
|
| - window_->set_delegate(this);
|
| - }
|
| -
|
| - gfx::Size window_size = GetPreferredSize();
|
| - if (mole_animation_->is_animating()) {
|
| - // We only want to animate the body of the mole window. When we're
|
| - // expanding, this is everything except for the handle. When we're
|
| - // collapsing, this is everything except for the handle and the toolstrip.
|
| - // We subtract this amount from the target height, figure out the step in
|
| - // the animation from the rest, and then add it back in.
|
| - int window_offset = shelf_->height();
|
| - if (!mole_animation_->IsShowing())
|
| - window_offset += GetPreferredSize().height();
|
| - else
|
| - window_offset += GetHandlePreferredSize().height();
|
| - int h = expanded_height_ - window_offset;
|
| - window_size.set_height(window_offset +
|
| - static_cast<int>(h * mole_animation_->GetCurrentValue()));
|
| - } else if (!expanded_ && !dragging_) {
|
| - window_size.set_height(GetHandlePreferredSize().height());
|
| - }
|
| -
|
| - // Now figure out where to place the window on the screen. Since it's a top-
|
| - // level widget, we need to do some coordinate conversion to get this right.
|
| - gfx::Point origin(-kToolstripPadding, 0);
|
| - if (expanded_ || mole_animation_->is_animating()) {
|
| - origin.set_y(GetShelfView()->height() - window_size.height());
|
| - views::View::ConvertPointToView(GetShelfView(), shelf_->GetRootView(),
|
| - &origin);
|
| - } else {
|
| - origin.set_y(-(window_size.height() + kToolstripPadding - 1));
|
| - views::View::ConvertPointToWidget(view(), &origin);
|
| - }
|
| - SetBounds(0, 0, window_size.width(), window_size.height());
|
| - window_->SetBounds(origin.x(), origin.y(),
|
| - window_size.width(), window_size.height());
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::ChildPreferredSizeChanged(View* child) {
|
| - if (child == view()) {
|
| - child->SizeToPreferredSize();
|
| - Layout();
|
| - if (window_visible())
|
| - LayoutWindow();
|
| - if (expanded_) {
|
| - placeholder_view_->SetWidth(child->width());
|
| - shelf_->Layout();
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::BubbleBrowserWindowMoved(
|
| - BrowserBubble* bubble) {
|
| - if (!expanded_)
|
| - HideWindow();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::BubbleBrowserWindowClosing(
|
| - BrowserBubble* bubble) {
|
| - HideWindow();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::AnimationProgressed(
|
| - const Animation* animation) {
|
| - LayoutWindow();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::AnimationEnded(const Animation* animation) {
|
| - if (window_visible())
|
| - LayoutWindow();
|
| - if (!expanded_) {
|
| - AttachToShelf(false);
|
| - HideShelfHandle(kHideDelayMs);
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::DetachFromShelf(bool browserDetach) {
|
| - DCHECK(window_.get());
|
| - DCHECK(!placeholder_view_);
|
| - if (browserDetach && window_->attached())
|
| - window_->DetachFromBrowser();
|
| -
|
| - // Construct a placeholder view to replace the view.
|
| - placeholder_view_ = new PlaceholderView();
|
| - placeholder_view_->SetBounds(view()->bounds());
|
| - shelf_->AddChildView(placeholder_view_);
|
| -
|
| - AddChildView(view());
|
| - SizeToPreferredSize();
|
| - window_->ResizeToView();
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::AttachToShelf(bool browserAttach) {
|
| - DCHECK(window_.get());
|
| - DCHECK(placeholder_view_);
|
| - if (browserAttach && !window_->attached())
|
| - window_->AttachToBrowser();
|
| -
|
| - // Move the view back into the shelf and remove the old placeholder.
|
| - shelf_->AddChildView(view());
|
| -
|
| - // The size of the view may have changed, so just set the position.
|
| - view()->SetX(placeholder_view_->x());
|
| - view()->SetY(placeholder_view_->y());
|
| -
|
| - // Remove the old placeholder.
|
| - shelf_->RemoveChildView(placeholder_view_);
|
| - delete placeholder_view_;
|
| - placeholder_view_ = NULL;
|
| -
|
| - SizeToPreferredSize();
|
| - Layout();
|
| - shelf_->Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::DoShowShelfHandle() {
|
| - if (!handle_visible()) {
|
| - handle_visible_ = true;
|
| -
|
| - // Make sure the text color for the title matches the theme colors.
|
| - title_->SetColor(
|
| - shelf_->GetThemeProvider()->GetColor(
|
| - BrowserThemeProvider::COLOR_BOOKMARK_TEXT));
|
| -
|
| - ShowWindow();
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::HideWindow() {
|
| - if (!window_visible())
|
| - return;
|
| - handle_visible_ = false;
|
| - window_->Hide();
|
| - if (expanded_) {
|
| - if (info_.toolstrip.is_valid())
|
| - shelf_->CollapseToolstrip(host_, info_.toolstrip);
|
| - else
|
| - shelf_->CollapseToolstrip(host_, GURL());
|
| - }
|
| - if (window_->attached())
|
| - window_->DetachFromBrowser();
|
| - window_.reset(NULL);
|
| - shelf_->Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::ShowWindow() {
|
| - DCHECK(handle_visible_ || expanded_);
|
| -
|
| - LayoutWindow();
|
| - if (!window_visible())
|
| - window_->Show(false); // |false| means show, but don't activate.
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::DoHideShelfHandle() {
|
| - if (!handle_visible())
|
| - return;
|
| - handle_visible_ = false;
|
| - if (expanded_) {
|
| - LayoutWindow();
|
| - Layout();
|
| - } else {
|
| - HideWindow();
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::StopHandleTimer() {
|
| - if (!timer_factory_.empty())
|
| - timer_factory_.RevokeAll();
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::Expand(int height, const GURL& url) {
|
| - DCHECK(!expanded_);
|
| -
|
| - expanded_ = true;
|
| - ShowWindow();
|
| -
|
| - bool navigate = (!url.is_empty() && url != host_->GetURL());
|
| - if (navigate)
|
| - host_->NavigateToURL(url);
|
| -
|
| - StopHandleTimer();
|
| - DetachFromShelf(false);
|
| -
|
| - mole_animation_->Show();
|
| -
|
| - gfx::Size extension_size = view()->GetPreferredSize();
|
| - extension_size.set_height(height);
|
| - view()->SetPreferredSize(extension_size);
|
| - expanded_height_ = GetPreferredSize().height();
|
| -
|
| - // This is to prevent flickering as the page loads and lays out.
|
| - // Once the navigation is finished, ExtensionView will wind up setting
|
| - // visibility to true.
|
| - if (navigate)
|
| - view()->SetVisible(false);
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::Collapse(const GURL& url) {
|
| - DCHECK(expanded_);
|
| - expanded_ = false;
|
| -
|
| - if (window_visible())
|
| - mole_animation_->Hide();
|
| -
|
| - gfx::Size extension_size = view()->GetPreferredSize();
|
| - extension_size.set_height(
|
| - kShelfHeight - (shelf_->top_margin() + kBottomMargin));
|
| - view()->SetPreferredSize(extension_size);
|
| -
|
| - if (!url.is_empty() && url != host_->GetURL()) {
|
| - host_->NavigateToURL(url);
|
| -
|
| - // This is to prevent flickering as the page loads and lays out.
|
| - // Once the navigation is finished, ExtensionView will wind up setting
|
| - // visibility to true.
|
| - view()->SetVisible(false);
|
| - }
|
| -
|
| - if (!window_visible())
|
| - AnimationEnded(NULL);
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::ShowShelfHandle() {
|
| - StopHandleTimer();
|
| - if (handle_visible())
|
| - return;
|
| - MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| - timer_factory_.NewRunnableMethod(
|
| - &ExtensionShelf::Toolstrip::DoShowShelfHandle),
|
| - kShowDelayMs);
|
| -}
|
| -
|
| -void ExtensionShelf::Toolstrip::HideShelfHandle(int delay_ms) {
|
| - StopHandleTimer();
|
| - if (!handle_visible() || dragging_ || mole_animation_->is_animating())
|
| - return;
|
| - if (delay_ms) {
|
| - MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
| - timer_factory_.NewRunnableMethod(
|
| - &ExtensionShelf::Toolstrip::DoHideShelfHandle),
|
| - delay_ms);
|
| - } else {
|
| - DoHideShelfHandle();
|
| - }
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -ExtensionShelf::ExtensionShelf(Browser* browser)
|
| - : background_needs_repaint_(true),
|
| - browser_(browser),
|
| - model_(browser->extension_shelf_model()),
|
| - fullscreen_(false) {
|
| - SetID(VIEW_ID_DEV_EXTENSION_SHELF);
|
| -
|
| - top_margin_ = kTopMarginWhenExtensionsOnBottom;
|
| -
|
| - model_->AddObserver(this);
|
| - LoadFromModel();
|
| - EnableCanvasFlippingForRTLUI(true);
|
| - registrar_.Add(this,
|
| - NotificationType::EXTENSION_SHELF_VISIBILITY_PREF_CHANGED,
|
| - NotificationService::AllSources());
|
| -
|
| - size_animation_.reset(new SlideAnimation(this));
|
| - if (IsAlwaysShown())
|
| - size_animation_->Reset(1);
|
| - else
|
| - size_animation_->Reset(0);
|
| -}
|
| -
|
| -ExtensionShelf::~ExtensionShelf() {
|
| - if (model_) {
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i) {
|
| - delete ToolstripAtIndex(i);
|
| - model_->SetToolstripDataAt(i, NULL);
|
| - }
|
| - model_->RemoveObserver(this);
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::PaintChildren(gfx::Canvas* canvas) {
|
| - InitBackground(canvas);
|
| -
|
| - int max_x = width();
|
| - if (IsDetached())
|
| - max_x -= 2 * kNewtabHorizontalPadding;
|
| -
|
| - // Draw vertical dividers between Toolstrip items in the Extension shelf.
|
| - int count = GetChildViewCount();
|
| - for (int i = 0; i < count; ++i) {
|
| - int right = GetChildViewAt(i)->bounds().right() + kToolstripPadding;
|
| - if (right >= max_x)
|
| - break;
|
| - int vertical_padding = IsDetached() ? (height() - kShelfHeight) / 2 : 1;
|
| -
|
| - DetachableToolbarView::PaintVerticalDivider(
|
| - canvas, right, height(), vertical_padding,
|
| - DetachableToolbarView::kEdgeDividerColor,
|
| - DetachableToolbarView::kMiddleDividerColor,
|
| - GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR));
|
| - }
|
| -}
|
| -
|
| -// static
|
| -void ExtensionShelf::ToggleWhenExtensionShelfVisible(Profile* profile) {
|
| - PrefService* prefs = profile->GetPrefs();
|
| - const bool always_show = !prefs->GetBoolean(prefs::kShowExtensionShelf);
|
| -
|
| - // The user changed when the Extension Shelf is shown, update the
|
| - // preferences.
|
| - prefs->SetBoolean(prefs::kShowExtensionShelf, always_show);
|
| - prefs->ScheduleSavePersistentPrefs();
|
| -
|
| - // And notify the notification service.
|
| - Source<Profile> source(profile);
|
| - NotificationService::current()->Notify(
|
| - NotificationType::EXTENSION_SHELF_VISIBILITY_PREF_CHANGED,
|
| - source,
|
| - NotificationService::NoDetails());
|
| -}
|
| -
|
| -gfx::Size ExtensionShelf::GetPreferredSize() {
|
| - return LayoutItems(true);
|
| -}
|
| -
|
| -void ExtensionShelf::ChildPreferredSizeChanged(View* child) {
|
| - PreferredSizeChanged();
|
| -}
|
| -
|
| -void ExtensionShelf::Layout() {
|
| - LayoutItems(false);
|
| -}
|
| -
|
| -void ExtensionShelf::OnMouseEntered(const views::MouseEvent& event) {
|
| -}
|
| -
|
| -void ExtensionShelf::OnMouseExited(const views::MouseEvent& event) {
|
| -}
|
| -
|
| -bool ExtensionShelf::GetAccessibleRole(AccessibilityTypes::Role* role) {
|
| - DCHECK(role);
|
| -
|
| - *role = AccessibilityTypes::ROLE_TOOLBAR;
|
| - return true;
|
| -}
|
| -
|
| -void ExtensionShelf::OnThemeChanged() {
|
| - // Refresh the CSS to update toolstrip text colors from theme.
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i)
|
| - ToolstripAtIndex(i)->view()->host()->InsertThemedToolstripCSS();
|
| -
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::ToolstripInsertedAt(ExtensionHost* host,
|
| - int index) {
|
| - model_->SetToolstripDataAt(index,
|
| - new Toolstrip(this, host, model_->ToolstripAt(index).info));
|
| -
|
| - bool had_views = GetChildViewCount() > 0;
|
| - ExtensionView* view = host->view();
|
| - AddChildView(view);
|
| - view->SetContainer(this);
|
| - if (!had_views)
|
| - PreferredSizeChanged();
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::ToolstripRemovingAt(ExtensionHost* host, int index) {
|
| - // Delete the Toolstrip view and remove it from the model.
|
| - Toolstrip* toolstrip = ToolstripAtIndex(index);
|
| - View* view = toolstrip->GetShelfView();
|
| - RemoveChildView(view);
|
| - delete toolstrip;
|
| - model_->SetToolstripDataAt(index, NULL);
|
| -
|
| - // Technically, the toolstrip is still in the model at this point, but
|
| - // the Layout code handles this case.
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::ToolstripDraggingFrom(ExtensionHost* host, int index) {
|
| -}
|
| -
|
| -void ExtensionShelf::ToolstripMoved(ExtensionHost* host, int from_index,
|
| - int to_index) {
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::ToolstripChanged(ExtensionShelfModel::iterator toolstrip) {
|
| - Toolstrip* t = static_cast<Toolstrip*>(toolstrip->data);
|
| - if (toolstrip->height > 0) {
|
| - if (!t->expanded()) {
|
| - t->Expand(toolstrip->height, toolstrip->url);
|
| - }
|
| - } else if (t->expanded()) {
|
| - t->Collapse(toolstrip->url);
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::ExtensionShelfEmpty() {
|
| - PreferredSizeChanged();
|
| -}
|
| -
|
| -void ExtensionShelf::ShelfModelReloaded() {
|
| - // None of the child views are parent owned, so nothing is being leaked here.
|
| - RemoveAllChildViews(false);
|
| - LoadFromModel();
|
| -}
|
| -
|
| -void ExtensionShelf::ShelfModelDeleting() {
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i) {
|
| - delete ToolstripAtIndex(i);
|
| - model_->SetToolstripDataAt(i, NULL);
|
| - }
|
| - model_->RemoveObserver(this);
|
| - model_ = NULL;
|
| -}
|
| -
|
| -void ExtensionShelf::AnimationProgressed(const Animation* animation) {
|
| - if (browser_)
|
| - browser_->ExtensionShelfSizeChanged();
|
| -}
|
| -
|
| -void ExtensionShelf::AnimationEnded(const Animation* animation) {
|
| - if (browser_)
|
| - browser_->ExtensionShelfSizeChanged();
|
| -
|
| - Layout();
|
| -}
|
| -
|
| -void ExtensionShelf::Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - switch (type.value) {
|
| - case NotificationType::EXTENSION_SHELF_VISIBILITY_PREF_CHANGED: {
|
| - if (fullscreen_)
|
| - break;
|
| - if (IsAlwaysShown())
|
| - size_animation_->Show();
|
| - else
|
| - size_animation_->Hide();
|
| - break;
|
| - }
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void ExtensionShelf::OnExtensionMouseMove(ExtensionView* view) {
|
| - Toolstrip *toolstrip = ToolstripForView(view);
|
| - if (toolstrip)
|
| - toolstrip->ShowShelfHandle();
|
| -}
|
| -
|
| -void ExtensionShelf::OnExtensionMouseLeave(ExtensionView* view) {
|
| - Toolstrip *toolstrip = ToolstripForView(view);
|
| - if (toolstrip)
|
| - toolstrip->HideShelfHandle(kHideDelayMs);
|
| -}
|
| -
|
| -void ExtensionShelf::DropExtension(Toolstrip* toolstrip, const gfx::Point& pt,
|
| - bool cancel) {
|
| - Toolstrip* dest_toolstrip = ToolstripAtX(pt.x());
|
| - if (!dest_toolstrip) {
|
| - if (pt.x() > 0)
|
| - dest_toolstrip = ToolstripAtIndex(model_->count() - 1);
|
| - else
|
| - dest_toolstrip = ToolstripAtIndex(0);
|
| - }
|
| - if (toolstrip == dest_toolstrip)
|
| - return;
|
| - int from = model_->IndexOfHost(toolstrip->host());
|
| - int to = model_->IndexOfHost(dest_toolstrip->host());
|
| - DCHECK(from != to);
|
| - model_->MoveToolstripAt(from, to);
|
| -}
|
| -
|
| -void ExtensionShelf::ExpandToolstrip(ExtensionHost* host, const GURL& url,
|
| - int height) {
|
| - ExtensionShelfModel::iterator toolstrip = model_->ToolstripForHost(host);
|
| - model_->ExpandToolstrip(toolstrip, url, height);
|
| -}
|
| -
|
| -void ExtensionShelf::CollapseToolstrip(ExtensionHost* host, const GURL& url) {
|
| - ExtensionShelfModel::iterator toolstrip = model_->ToolstripForHost(host);
|
| - model_->CollapseToolstrip(toolstrip, url);
|
| -}
|
| -
|
| -void ExtensionShelf::InitBackground(gfx::Canvas* canvas) {
|
| - if (!background_needs_repaint_)
|
| - return;
|
| -
|
| - // Capture a background bitmap to give to the toolstrips.
|
| - SkRect background_rect = {
|
| - SkIntToScalar(0),
|
| - SkIntToScalar(0),
|
| - SkIntToScalar(width()),
|
| - SkIntToScalar(height())
|
| - };
|
| -
|
| - // Tell all extension views about the new background.
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i) {
|
| - ExtensionView* view = ToolstripAtIndex(i)->view();
|
| -
|
| - const SkBitmap& background =
|
| - canvas->AsCanvasSkia()->getDevice()->accessBitmap(false);
|
| -
|
| - SkRect mapped_subset = background_rect;
|
| - gfx::Rect view_bounds = view->bounds();
|
| - mapped_subset.offset(SkIntToScalar(view_bounds.x()),
|
| - SkIntToScalar(view_bounds.y()));
|
| - bool result =
|
| - canvas->AsCanvasSkia()->getTotalMatrix().mapRect(&mapped_subset);
|
| - DCHECK(result);
|
| -
|
| - SkIRect isubset;
|
| - mapped_subset.round(&isubset);
|
| - SkBitmap subset_bitmap;
|
| - // This will create another bitmap that just references pixels in the
|
| - // actual bitmap.
|
| - result = background.extractSubset(&subset_bitmap, isubset);
|
| - if (!result)
|
| - return;
|
| -
|
| - // We do a deep copy because extractSubset() returns a bitmap that
|
| - // references pixels in the original one and we want to actually make a
|
| - // smaller copy that will have a long lifetime.
|
| - SkBitmap smaller_copy;
|
| - if (!subset_bitmap.copyTo(&smaller_copy, SkBitmap::kARGB_8888_Config))
|
| - return;
|
| - DCHECK(smaller_copy.readyToDraw());
|
| -
|
| - view->SetBackground(smaller_copy);
|
| - }
|
| -
|
| - background_needs_repaint_ = false;
|
| -}
|
| -
|
| -ExtensionShelf::Toolstrip* ExtensionShelf::ToolstripAtX(int x) {
|
| - int count = model_->count();
|
| - if (count == 0)
|
| - return NULL;
|
| -
|
| - if (x < 0)
|
| - return NULL;
|
| -
|
| - for (int i = 0; i < count; ++i) {
|
| - Toolstrip* toolstrip = ToolstripAtIndex(i);
|
| - View* view = toolstrip->GetShelfView();
|
| - int x_mirrored = view->GetRootView()->MirroredXCoordinateInsideView(x);
|
| - if (x_mirrored > view->x() + view->width() + kToolstripPadding)
|
| - continue;
|
| - return toolstrip;
|
| - }
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -ExtensionShelf::Toolstrip* ExtensionShelf::ToolstripAtIndex(int index) {
|
| - return static_cast<Toolstrip*>(model_->ToolstripAt(index).data);
|
| -}
|
| -
|
| -ExtensionShelf::Toolstrip* ExtensionShelf::ToolstripForView(
|
| - ExtensionView* view) {
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i) {
|
| - Toolstrip* toolstrip = ToolstripAtIndex(i);
|
| - if (view == toolstrip->view())
|
| - return toolstrip;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -void ExtensionShelf::LoadFromModel() {
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i)
|
| - ToolstripInsertedAt(model_->ToolstripAt(i).host, i);
|
| -}
|
| -
|
| -gfx::Size ExtensionShelf::LayoutItems(bool compute_bounds_only) {
|
| - if (!GetParent() || !model_ || !model_->count())
|
| - return gfx::Size(0, 0);
|
| -
|
| - gfx::Size prefsize;
|
| - int x = kLeftMargin;
|
| - int y = top_margin_;
|
| - int content_height = kShelfHeight - top_margin_ - kBottomMargin;
|
| - int max_x = width() - kRightMargin;
|
| -
|
| - if (OnNewTabPage()) {
|
| - double current_state = 1 - size_animation_->GetCurrentValue();
|
| - x += static_cast<int>(static_cast<double>
|
| - (kNewtabHorizontalPadding + kNewtabExtraHorMargin) * current_state);
|
| - y += static_cast<int>(static_cast<double>
|
| - (kNewtabVerticalPadding + kNewtabExtraVerMargin) * current_state);
|
| - max_x -= static_cast<int>(static_cast<double>
|
| - (2 * kNewtabHorizontalPadding) * current_state);
|
| - }
|
| -
|
| - int count = model_->count();
|
| - for (int i = 0; i < count; ++i) {
|
| - x += kToolstripPadding; // Left padding.
|
| - Toolstrip* toolstrip = ToolstripAtIndex(i);
|
| - if (!toolstrip) // Can be NULL while in the process of removing.
|
| - continue;
|
| - View* view = toolstrip->GetShelfView();
|
| - gfx::Size pref = view->GetPreferredSize();
|
| -
|
| - // |next_x| is the x value for where the next toolstrip in the list will be.
|
| - int next_x = x + pref.width() + kToolstripPadding; // Right padding.
|
| - if (!compute_bounds_only) {
|
| - bool clipped = next_x >= max_x;
|
| - if (clipped)
|
| - pref.set_width(std::max(0, max_x - x));
|
| - if (view == toolstrip->view())
|
| - toolstrip->view()->SetIsClipped(clipped);
|
| - view->SetBounds(x, y, pref.width(), content_height);
|
| - view->Layout();
|
| - if (toolstrip->window_visible())
|
| - toolstrip->LayoutWindow();
|
| - }
|
| - x = next_x + kToolstripDividerWidth;
|
| - }
|
| -
|
| - if (!compute_bounds_only) {
|
| - background_needs_repaint_ = true;
|
| - SchedulePaint();
|
| - } else {
|
| - if (OnNewTabPage()) {
|
| - prefsize.set_height(kShelfHeight + static_cast<int>(static_cast<double>
|
| - (kNewtabShelfHeight - kShelfHeight) *
|
| - (1 - size_animation_->GetCurrentValue())));
|
| - } else {
|
| - prefsize.set_height(static_cast<int>(static_cast<double>(kShelfHeight) *
|
| - size_animation_->GetCurrentValue()));
|
| - }
|
| -
|
| - x += kRightMargin;
|
| - prefsize.set_width(x);
|
| - }
|
| -
|
| - return prefsize;
|
| -}
|
| -
|
| -bool ExtensionShelf::IsDetached() const {
|
| - return OnNewTabPage() && (size_animation_->GetCurrentValue() != 1);
|
| -}
|
| -
|
| -bool ExtensionShelf::IsAlwaysShown() const {
|
| - Profile* profile = browser_->profile();
|
| - return profile->GetPrefs()->GetBoolean(prefs::kShowExtensionShelf);
|
| -}
|
| -
|
| -bool ExtensionShelf::OnNewTabPage() const {
|
| - return (browser_ && browser_->GetSelectedTabContents() &&
|
| - browser_->GetSelectedTabContents()->IsExtensionShelfAlwaysVisible());
|
| -}
|
| -
|
| -void ExtensionShelf::OnFullscreenToggled(bool fullscreen) {
|
| - if (fullscreen == fullscreen_)
|
| - return;
|
| - fullscreen_ = fullscreen;
|
| - if (!IsAlwaysShown())
|
| - return;
|
| - size_animation_->Reset(fullscreen ? 0 : 1);
|
| -}
|
|
|