Index: chrome/browser/ui/views/frame/browser_view.cc |
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc |
index b5c17fb15e71e9b7e202041aa9628d64a321b239..d25f24b33b60cee9afc48609d020e5b2f1701a7d 100644 |
--- a/chrome/browser/ui/views/frame/browser_view.cc |
+++ b/chrome/browser/ui/views/frame/browser_view.cc |
@@ -21,6 +21,8 @@ |
#include "chrome/browser/browser_process.h" |
#include "chrome/browser/chrome_notification_types.h" |
#include "chrome/browser/extensions/extension_util.h" |
+#include "chrome/browser/extensions/sidebar_container.h" |
+#include "chrome/browser/extensions/sidebar_manager.h" |
#include "chrome/browser/extensions/tab_helper.h" |
#include "chrome/browser/infobars/infobar_service.h" |
#include "chrome/browser/native_window_notification_source.h" |
@@ -131,10 +133,13 @@ |
#include "ui/gfx/screen.h" |
#include "ui/strings/grit/ui_strings.h" |
#include "ui/views/controls/button/menu_button.h" |
+#include "ui/views/controls/single_split_view.h" |
+#include "ui/views/controls/single_split_view_listener.h" |
#include "ui/views/controls/textfield/textfield.h" |
#include "ui/views/controls/webview/webview.h" |
#include "ui/views/focus/external_focus_tracker.h" |
#include "ui/views/focus/view_storage.h" |
+#include "ui/views/layout/box_layout.h" |
#include "ui/views/layout/grid_layout.h" |
#include "ui/views/widget/native_widget.h" |
#include "ui/views/widget/root_view.h" |
@@ -519,6 +524,10 @@ void BrowserView::Init(Browser* browser) { |
browser_->tab_strip_model()->AddObserver(this); |
immersive_mode_controller_.reset( |
chrome::CreateImmersiveModeController(browser_->host_desktop_type())); |
+ |
+ extensions::SidebarManager* sidebar_manager = |
+ extensions::SidebarManager::GetFromContext(browser_->profile()); |
+ sidebar_manager->AddObserver(this); |
} |
// static |
@@ -540,6 +549,14 @@ void BrowserView::InitStatusBubble() { |
contents_web_view_->SetStatusBubble(status_bubble_.get()); |
} |
+bool BrowserView::SplitHandleMoved(views::SingleSplitView* sender) { |
+ for (int i = 0; i < sender->child_count(); ++i) |
+ sender->child_at(i)->InvalidateLayout(); |
+ SchedulePaint(); |
+ Layout(); |
+ return false; |
+} |
+ |
gfx::Rect BrowserView::GetToolbarBounds() const { |
gfx::Rect toolbar_bounds(toolbar_->bounds()); |
if (toolbar_bounds.IsEmpty()) |
@@ -654,6 +671,16 @@ gfx::ImageSkia BrowserView::GetOTRAvatarIcon() const { |
return *GetThemeProvider()->GetImageSkiaNamed(IDR_OTR_ICON); |
} |
+void BrowserView::OnSidebarShown(content::WebContents* tab, |
+ const std::string& content_id) { |
+ UpdateSidebarForContents(tab); |
+} |
+ |
+void BrowserView::OnSidebarHidden(content::WebContents* tab, |
+ const std::string& content_id) { |
+ UpdateSidebarForContents(tab); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
// BrowserView, BrowserWindow implementation: |
@@ -883,6 +910,7 @@ void BrowserView::OnActiveTabChanged(content::WebContents* old_contents, |
// to avoid toggling the size of any of them. |
UpdateDevToolsForContents(new_contents, !change_tab_contents); |
+ UpdateSidebarForContents(new_contents); |
if (change_tab_contents) { |
web_contents_close_handler_->ActiveTabChanged(); |
contents_web_view_->SetWebContents(new_contents); |
@@ -1311,6 +1339,12 @@ void BrowserView::ShowOneClickSigninBubble( |
} |
#endif |
+int BrowserView::GetSidebarWidth() const { |
+ if (!sidebar_container_ || !sidebar_container_->visible()) |
+ return 0; |
+ return sidebar_split_->divider_offset(); |
+} |
+ |
void BrowserView::SetDownloadShelfVisible(bool visible) { |
// This can be called from the superclass destructor, when it destroys our |
// child views. At that point, browser_ is already gone. |
@@ -1564,6 +1598,7 @@ void BrowserView::TabDetachedAt(WebContents* contents, int index) { |
infobar_container_->ChangeInfoBarManager(nullptr); |
UpdateDevToolsForContents(nullptr, true); |
} |
+ UpdateSidebarForContents(NULL); |
} |
void BrowserView::TabDeactivated(WebContents* contents) { |
@@ -2042,8 +2077,27 @@ void BrowserView::InitViews() { |
contents_container_->AddChildView(contents_web_view_); |
contents_container_->SetLayoutManager(new ContentsLayoutManager( |
devtools_web_view_, contents_web_view_)); |
- AddChildView(contents_container_); |
- set_contents_view(contents_container_); |
+ |
+ sidebar_web_view_ = new views::WebView(browser_->profile()); |
+ sidebar_web_view_->set_id(VIEW_ID_SIDE_BAR_VIEW); |
+ sidebar_web_view_->SetVisible(false); |
+ |
+ sidebar_container_ = new views::View(); |
+ sidebar_container_->AddChildView(sidebar_web_view_); |
+ sidebar_container_->set_id(VIEW_ID_SIDE_BAR_CONTAINER); |
+ sidebar_container_->SetVisible(false); |
+ |
+ sidebar_split_ = new views::SingleSplitView( |
+ contents_container_, sidebar_container_, |
+ views::SingleSplitView::HORIZONTAL_SPLIT, this); |
+ |
+ sidebar_split_->set_id(VIEW_ID_SIDE_BAR_SPLIT); |
+ sidebar_split_->set_background(views::Background::CreateSolidBackground( |
+ GetWidget()->GetThemeProvider()->GetColor( |
+ ThemeProperties::COLOR_TOOLBAR))); |
+ sidebar_split_->set_resize_leading_on_bounds_change(false); |
+ AddChildView(sidebar_split_); |
+ set_contents_view(sidebar_split_); |
// Top container holds tab strip and toolbar and lives at the front of the |
// view hierarchy. |
@@ -2072,16 +2126,10 @@ void BrowserView::InitViews() { |
immersive_mode_controller_->Init(this); |
BrowserViewLayout* browser_view_layout = new BrowserViewLayout; |
- browser_view_layout->Init(new BrowserViewLayoutDelegateImpl(this), |
- browser(), |
- this, |
- top_container_, |
- tabstrip_, |
- toolbar_, |
- infobar_container_, |
- contents_container_, |
- GetContentsLayoutManager(), |
- immersive_mode_controller_.get()); |
+ browser_view_layout->Init( |
+ new BrowserViewLayoutDelegateImpl(this), browser(), this, top_container_, |
+ tabstrip_, toolbar_, infobar_container_, sidebar_split_, |
+ GetContentsLayoutManager(), immersive_mode_controller_.get()); |
SetLayoutManager(browser_view_layout); |
#if defined(OS_WIN) |
@@ -2095,6 +2143,67 @@ void BrowserView::InitViews() { |
GetLocationBar()->GetOmniboxView()->model()->popup_model()->AddObserver(this); |
} |
+void BrowserView::UpdateSidebarForContents(content::WebContents* new_contents) { |
+ if (!sidebar_container_) |
+ return; // Happens when sidebar is not allowed. |
+ extensions::SidebarManager* sidebar_manager = |
+ extensions::SidebarManager::GetFromContext(browser_->profile()); |
+ if (!sidebar_manager) |
+ return; // Happens only in tests.s |
+ |
+ WebContents* sidebar_contents = NULL; |
+ if (new_contents) { |
+ SidebarContainer* client_host = |
+ sidebar_manager->GetActiveSidebarContainerFor(new_contents); |
+ if (client_host) |
+ sidebar_contents = client_host->host_contents(); |
+ } |
+ |
+ bool visible = NULL != sidebar_contents; |
+ |
+ bool should_show = visible && !sidebar_container_->visible(); |
+ bool should_hide = !visible && sidebar_container_->visible(); |
+ |
+ // Update sidebar content. |
+ WebContents* old_contents = |
+ static_cast<WebContents*>(sidebar_web_view_->web_contents()); |
+ |
+ sidebar_web_view_->SetWebContents(sidebar_contents); |
+ |
+ sidebar_manager->NotifyStateChanges(old_contents, sidebar_contents); |
+ |
+ // Update sidebar UI width. |
+ if (should_show) { |
+ // Restore split offset. |
+ int sidebar_width = g_browser_process->local_state()->GetInteger( |
+ prefs::kExtensionSidebarWidth); |
+ if (sidebar_width < 0) { |
+ // By default sidebar width is 1/7th of the current page content width. |
+ sidebar_width = sidebar_split_->width() / 7; |
+ } |
+ int min_sidebar_width = sidebar_split_->GetMinimumSize().width(); |
+ // Not allowed to be wider than 50% of the split-view's frame |
+ sidebar_width = std::min(sidebar_split_->width() / 2 - min_sidebar_width, |
+ std::max(min_sidebar_width, sidebar_width)); |
+ sidebar_split_->set_divider_offset(sidebar_split_->width() - sidebar_width); |
+ |
+ sidebar_container_->SetVisible(true); |
+ sidebar_web_view_->SetVisible(true); |
+ sidebar_split_->InvalidateLayout(); |
+ Layout(); |
+ |
+ } else if (should_hide) { |
+ // Store split offset when hiding sidebar only. |
+ g_browser_process->local_state()->SetInteger( |
+ prefs::kExtensionSidebarWidth, |
+ sidebar_split_->width() - sidebar_split_->divider_offset()); |
+ |
+ sidebar_container_->SetVisible(false); |
+ sidebar_split_->InvalidateLayout(); |
+ Layout(); |
+ } |
+} |
+ |
void BrowserView::LoadingAnimationCallback() { |
base::TimeTicks now = base::TimeTicks::Now(); |
if (!last_animation_time_.is_null()) { |