summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/frame/browser_layout_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/frame/browser_layout_manager.cc')
-rw-r--r--chrome/browser/views/frame/browser_layout_manager.cc403
1 files changed, 403 insertions, 0 deletions
diff --git a/chrome/browser/views/frame/browser_layout_manager.cc b/chrome/browser/views/frame/browser_layout_manager.cc
new file mode 100644
index 0000000..cdc7ca3
--- /dev/null
+++ b/chrome/browser/views/frame/browser_layout_manager.cc
@@ -0,0 +1,403 @@
+// 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/frame/browser_layout_manager.h"
+
+#include "app/gfx/scrollbar_size.h"
+#include "chrome/browser/find_bar.h"
+#include "chrome/browser/find_bar_controller.h"
+#include "chrome/browser/view_ids.h"
+#include "chrome/browser/views/bookmark_bar_view.h"
+#include "chrome/browser/views/download_shelf_view.h"
+#include "chrome/browser/views/extensions/extension_shelf.h"
+#include "chrome/browser/views/frame/browser_extender.h"
+#include "chrome/browser/views/frame/browser_frame.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/tabs/tab_strip.h"
+#include "chrome/browser/views/toolbar_view.h"
+
+namespace {
+
+// The vertical overlap between the TabStrip and the Toolbar.
+static const int kToolbarTabStripVerticalOverlap = 3;
+// An offset distance between certain toolbars and the toolbar that preceded
+// them in layout.
+static const int kSeparationLineHeight = 1;
+
+// The layout manager used in chrome browser.
+class ChromeLayoutManager : public BrowserLayoutManager {
+ public:
+ ChromeLayoutManager()
+ : tabstrip_(NULL),
+ toolbar_(NULL),
+ contents_split_(NULL),
+ contents_container_(NULL),
+ infobar_container_(NULL),
+ download_shelf_(NULL),
+ extension_shelf_(NULL),
+ active_bookmark_bar_(NULL),
+ browser_view_(NULL),
+ find_bar_y_(0) {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overridden from LayoutManager.
+
+ virtual void Installed(views::View* host) {
+ toolbar_ = NULL;
+ contents_split_ = NULL;
+ contents_container_ = NULL;
+ infobar_container_ = NULL;
+ download_shelf_ = NULL;
+ extension_shelf_ = NULL;
+ active_bookmark_bar_ = NULL;
+ tabstrip_ = NULL;
+ browser_view_ = static_cast<BrowserView*>(host);
+ }
+
+ virtual void Uninstalled(views::View* host) {}
+
+ virtual void ViewAdded(views::View* host, views::View* view) {
+ switch (view->GetID()) {
+ case VIEW_ID_CONTENTS_SPLIT:
+ contents_split_ = view;
+ contents_container_ = contents_split_->GetChildViewAt(0);
+ break;
+ case VIEW_ID_INFO_BAR_CONTAINER:
+ infobar_container_ = view;
+ break;
+ case VIEW_ID_DOWNLOAD_SHELF:
+ download_shelf_ = static_cast<DownloadShelfView*>(view);
+ break;
+ case VIEW_ID_DEV_EXTENSION_SHELF:
+ extension_shelf_ = static_cast<ExtensionShelf*>(view);
+ break;
+ case VIEW_ID_BOOKMARK_BAR:
+ active_bookmark_bar_ = static_cast<BookmarkBarView*>(view);
+ break;
+ case VIEW_ID_TOOLBAR:
+ toolbar_ = static_cast<ToolbarView*>(view);
+ break;
+ case VIEW_ID_TAB_STRIP:
+ tabstrip_ = static_cast<TabStrip*>(view);
+ break;
+ }
+ }
+
+ virtual void ViewRemoved(views::View* host, views::View* view) {
+ switch (view->GetID()) {
+ case VIEW_ID_BOOKMARK_BAR:
+ active_bookmark_bar_ = NULL;
+ break;
+ }
+ }
+
+ // Lay out the children of |host| according to implementation-specific
+ // heuristics. The graphics used during painting is provided to allow for
+ // string sizing.
+ virtual void Layout(views::View* host) {
+ int top = LayoutTabStrip();
+ top = LayoutToolbar(top);
+ top = LayoutBookmarkAndInfoBars(top);
+ int bottom = LayoutExtensionAndDownloadShelves();
+ LayoutTabContents(top, bottom);
+ // This must be done _after_ we lay out the TabContents since this
+ // code calls back into us to find the bounding box the find bar
+ // must be laid out within, and that code depends on the
+ // TabContentsContainer's bounds being up to date.
+ if (browser()->HasFindBarController()) {
+ browser()->GetFindBarController()->find_bar()->MoveWindowIfNecessary(
+ gfx::Rect(), true);
+ }
+ // Align status bubble with the bottom of the contents_container.
+ browser_view_->LayoutStatusBubble(
+ top + contents_container_->bounds().height());
+ browser_view_->SchedulePaint();
+ }
+
+ // Return the preferred size which is the size required to give each
+ // children their respective preferred size.
+ virtual gfx::Size GetPreferredSize(views::View* host) {
+ return gfx::Size();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overridden from BrowserLayoutManager.
+
+ virtual gfx::Size GetMinimumSize() {
+ // TODO(noname): In theory the tabstrip width should probably be
+ // (OTR + tabstrip + caption buttons) width.
+ gfx::Size tabstrip_size(
+ browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP) ?
+ tabstrip_->GetMinimumSize() : gfx::Size());
+ gfx::Size toolbar_size(
+ (browser()->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
+ browser()->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)) ?
+ toolbar_->GetMinimumSize() : gfx::Size());
+ if (tabstrip_size.height() && toolbar_size.height())
+ toolbar_size.Enlarge(0, -kToolbarTabStripVerticalOverlap);
+ gfx::Size bookmark_bar_size;
+ if (active_bookmark_bar_ &&
+ browser()->SupportsWindowFeature(Browser::FEATURE_BOOKMARKBAR)) {
+ bookmark_bar_size = active_bookmark_bar_->GetMinimumSize();
+ bookmark_bar_size.Enlarge(
+ 0,
+ -kSeparationLineHeight -
+ active_bookmark_bar_->GetToolbarOverlap(true));
+ }
+ gfx::Size contents_size(contents_split_->GetMinimumSize());
+
+ int min_height = tabstrip_size.height() + toolbar_size.height() +
+ bookmark_bar_size.height() + contents_size.height();
+ int widths[] = { tabstrip_size.width(), toolbar_size.width(),
+ bookmark_bar_size.width(), contents_size.width() };
+ int min_width = *std::max_element(&widths[0], &widths[arraysize(widths)]);
+ return gfx::Size(min_width, min_height);
+ }
+
+ virtual gfx::Rect GetFindBarBoundingBox() const {
+ // This function returns the area the Find Bar can be laid out
+ // within. This basically implies the "user-perceived content
+ // area" of the browser window excluding the vertical
+ // scrollbar. This is not quite so straightforward as positioning
+ // based on the TabContentsContainer since the BookmarkBarView may
+ // be visible but not persistent (in the New Tab case) and we
+ // position the Find Bar over the top of it in that case since the
+ // BookmarkBarView is not _visually_ connected to the Toolbar.
+
+ // First determine the bounding box of the content area in Widget
+ // coordinates.
+ gfx::Rect bounding_box(contents_container_->bounds());
+
+ gfx::Point topleft;
+ views::View::ConvertPointToWidget(contents_container_, &topleft);
+ bounding_box.set_origin(topleft);
+
+ // Adjust the position and size of the bounding box by the find bar offset
+ // calculated during the last Layout.
+ int height_delta = find_bar_y_ - bounding_box.y();
+ bounding_box.set_y(find_bar_y_);
+ bounding_box.set_height(std::max(0, bounding_box.height() + height_delta));
+
+ // Finally decrease the width of the bounding box by the width of
+ // the vertical scroll bar.
+ int scrollbar_width = gfx::scrollbar_size();
+ bounding_box.set_width(std::max(0, bounding_box.width() - scrollbar_width));
+ if (browser_view_->UILayoutIsRightToLeft())
+ bounding_box.set_x(bounding_box.x() + scrollbar_width);
+
+ return bounding_box;
+ }
+
+ private:
+ Browser* browser() {
+ return browser_view_->browser();
+ }
+
+ // Layout the TabStrip, returns the coordinate of the bottom of the TabStrip,
+ // for laying out subsequent controls.
+ int LayoutTabStrip() {
+ gfx::Rect layout_bounds =
+ browser_view_->frame()->GetBoundsForTabStrip(tabstrip_);
+ gfx::Rect toolbar_bounds = browser_view_->GetToolbarBounds();
+ tabstrip_->SetBackgroundOffset(
+ gfx::Point(layout_bounds.x() - toolbar_bounds.x(), layout_bounds.y()));
+
+ gfx::Point tabstrip_origin = layout_bounds.origin();
+ views::View::ConvertPointToView(browser_view_->GetParent(), browser_view_,
+ &tabstrip_origin);
+ layout_bounds.set_origin(tabstrip_origin);
+
+ // Layout extra components.
+ int bottom = 0;
+ gfx::Rect tabstrip_bounds;
+ browser_view_->browser_extender()->Layout(
+ layout_bounds, &tabstrip_bounds, &bottom);
+ tabstrip_->SetVisible(browser_view_->IsTabStripVisible());
+ tabstrip_->SetBounds(tabstrip_bounds);
+ return bottom;
+ }
+
+ // Layout the following controls, starting at |top|, returns the coordinate
+ // of the bottom of the control, for laying out the next control.
+ int LayoutToolbar(int top) {
+ int browser_view_width = browser_view_->width();
+ bool visible = browser_view_->IsToolbarVisible();
+ toolbar_->location_bar()->SetFocusable(visible);
+ int y = top -
+ ((visible && browser_view_->IsTabStripVisible())
+ ? kToolbarTabStripVerticalOverlap : 0);
+ int height = visible ? toolbar_->GetPreferredSize().height() : 0;
+ toolbar_->SetVisible(visible);
+ toolbar_->SetBounds(0, y, browser_view_width, height);
+ return y + height;
+ }
+
+ int LayoutBookmarkAndInfoBars(int top) {
+ find_bar_y_ = top + browser_view_->y() - 1;
+ if (active_bookmark_bar_) {
+ // If we're showing the Bookmark bar in detached style, then we
+ // need to show any Info bar _above_ the Bookmark bar, since the
+ // Bookmark bar is styled to look like it's part of the page.
+ if (active_bookmark_bar_->IsDetached())
+ return LayoutTopBar(LayoutInfoBar(top));
+ // Otherwise, Bookmark bar first, Info bar second.
+ top = LayoutTopBar(top);
+ }
+ find_bar_y_ = top + browser_view_->y() - 1;
+ return LayoutInfoBar(top);
+ }
+
+ int LayoutTopBar(int top) {
+ // This method lays out the the bookmark bar, and, if required,
+ // the extension shelf by its side. The bookmark bar appears on
+ // the right of the extension shelf. If there are too many
+ // bookmark items and extension toolstrips to fit in the single
+ // bar, some compromises are made as follows: 1. The bookmark bar
+ // is shrunk till it reaches the minimum width. 2. After reaching
+ // the minimum width, the bookmark bar width is kept fixed - the
+ // extension shelf bar width is reduced.
+ DCHECK(active_bookmark_bar_);
+ int y = top, x = 0;
+ if (!browser_view_->IsBookmarkBarVisible()) {
+ active_bookmark_bar_->SetVisible(false);
+ active_bookmark_bar_->SetBounds(0, y, browser_view_->width(), 0);
+ if (extension_shelf_->IsOnTop())
+ extension_shelf_->SetVisible(false);
+ return y;
+ }
+
+ int bookmark_bar_height = active_bookmark_bar_->GetPreferredSize().height();
+ y -= kSeparationLineHeight + (
+ active_bookmark_bar_->IsDetached() ?
+ 0 : active_bookmark_bar_->GetToolbarOverlap(false));
+
+ if (extension_shelf_->IsOnTop()) {
+ if (!active_bookmark_bar_->IsDetached()) {
+ int extension_shelf_width =
+ extension_shelf_->GetPreferredSize().width();
+ int bookmark_bar_given_width =
+ browser_view_->width() - extension_shelf_width;
+ int minimum_allowed_bookmark_bar_width =
+ active_bookmark_bar_->GetMinimumSize().width();
+ if (bookmark_bar_given_width < minimum_allowed_bookmark_bar_width) {
+ // The bookmark bar cannot compromise on its width any more. The
+ // extension shelf needs to shrink now.
+ extension_shelf_width =
+ browser_view_->width() - minimum_allowed_bookmark_bar_width;
+ }
+ extension_shelf_->SetVisible(true);
+ extension_shelf_->SetBounds(x, y, extension_shelf_width,
+ bookmark_bar_height);
+ x += extension_shelf_width;
+ } else {
+ // TODO(sidchat): For detached style bookmark bar, set the extensions
+ // shelf in a better position. Issue = 20741.
+ extension_shelf_->SetVisible(false);
+ }
+ }
+
+ active_bookmark_bar_->SetVisible(true);
+ active_bookmark_bar_->SetBounds(x, y,
+ browser_view_->width() - x,
+ bookmark_bar_height);
+ return y + bookmark_bar_height;
+ }
+
+ int LayoutInfoBar(int top) {
+ bool visible = browser()->SupportsWindowFeature(Browser::FEATURE_INFOBAR);
+ int height = visible ? infobar_container_->GetPreferredSize().height() : 0;
+ infobar_container_->SetVisible(visible);
+ infobar_container_->SetBounds(0, top, browser_view_->width(), height);
+ return top + height;
+ }
+
+ // Layout the TabContents container, between the coordinates |top| and
+ // |bottom|.
+ void LayoutTabContents(int top, int bottom) {
+ contents_split_->SetBounds(0, top, browser_view_->width(), bottom - top);
+ }
+
+ int LayoutExtensionAndDownloadShelves() {
+ // If we're showing the Extension bar in detached style, then we
+ // need to show Download shelf _above_ the Extension bar, since
+ // the Extension bar is styled to look like it's part of the page.
+ //
+ // TODO(Oshima): confirm this comment.
+ int bottom = browser_view_->height();
+ if (extension_shelf_) {
+ if (extension_shelf_->IsDetached()) {
+ bottom = LayoutDownloadShelf(bottom);
+ return LayoutExtensionShelf(bottom);
+ }
+ // Otherwise, Extension shelf first, Download shelf second.
+ bottom = LayoutExtensionShelf(bottom);
+ }
+ return LayoutDownloadShelf(bottom);
+ }
+
+ // Layout the Download Shelf, returns the coordinate of the top of the
+ // control, for laying out the previous control.
+ int LayoutDownloadShelf(int bottom) {
+ // Re-layout the shelf either if it is visible or if it's close animation
+ // is currently running.
+ if (browser_view_->IsDownloadShelfVisible() ||
+ (download_shelf_ && download_shelf_->IsClosing())) {
+ bool visible = browser()->SupportsWindowFeature(
+ Browser::FEATURE_DOWNLOADSHELF);
+ DCHECK(download_shelf_);
+ int height = visible ? download_shelf_->GetPreferredSize().height() : 0;
+ download_shelf_->SetVisible(visible);
+ download_shelf_->SetBounds(0, bottom - height,
+ browser_view_->width(), height);
+ download_shelf_->Layout();
+ bottom -= height;
+ }
+ return bottom;
+ }
+
+ // Layout the Extension Shelf, returns the coordinate of the top of the
+ // control, for laying out the previous control.
+ int LayoutExtensionShelf(int bottom) {
+ if (!extension_shelf_ || extension_shelf_->IsOnTop())
+ return bottom;
+
+ if (extension_shelf_) {
+ bool visible = browser()->SupportsWindowFeature(
+ Browser::FEATURE_EXTENSIONSHELF);
+ int height =
+ visible ? extension_shelf_->GetPreferredSize().height() : 0;
+ extension_shelf_->SetVisible(visible);
+ extension_shelf_->SetBounds(0, bottom - height,
+ browser_view_->width(), height);
+ extension_shelf_->Layout();
+ bottom -= height;
+ }
+ return bottom;
+ }
+
+ // Child views that the layout manager manages.
+ TabStrip* tabstrip_;
+ ToolbarView* toolbar_;
+ views::View* contents_split_;
+ views::View* contents_container_;
+ views::View* infobar_container_;
+ DownloadShelfView* download_shelf_;
+ ExtensionShelf* extension_shelf_;
+ BookmarkBarView* active_bookmark_bar_;
+
+ BrowserView* browser_view_;
+
+ // The distance the FindBar is from the top of the window, in pixels.
+ int find_bar_y_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeLayoutManager);
+};
+
+} // namespace
+
+// static
+BrowserLayoutManager* BrowserLayoutManager::CreateBrowserLayoutManager() {
+ return new ChromeLayoutManager();
+}