| Index: chrome/browser/ui/cocoa/sidebar_controller.mm
|
| diff --git a/chrome/browser/ui/cocoa/sidebar_controller.mm b/chrome/browser/ui/cocoa/sidebar_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d5dd21000becb8a29e9ac6c335f9ae6f1eab2d6b
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/cocoa/sidebar_controller.mm
|
| @@ -0,0 +1,210 @@
|
| +// Copyright (c) 2015 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.
|
| +
|
| +#import "chrome/browser/ui/cocoa/sidebar_controller.h"
|
| +
|
| +#include <Cocoa/Cocoa.h>
|
| +
|
| +#include "base/prefs/pref_service.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/extensions/sidebar_manager.h"
|
| +#import "chrome/browser/ui/cocoa/view_id_util.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +
|
| +namespace {
|
| +
|
| +// By default sidebar width is 1/7th of the current page content width.
|
| +const CGFloat kDefaultSidebarWidthRatio = 1.0f / 7.0f;
|
| +const CGFloat kMaximumSidebarWidthRatio = 1.0f / 2.0f;
|
| +
|
| +} // end namespace
|
| +
|
| +@interface SidebarController (Private)
|
| +- (void)showSidebarContents:(content::WebContents*)sidebarContents;
|
| +- (void)resizeSidebarToNewWidth:(CGFloat)width;
|
| +@end
|
| +
|
| +@interface SidebarSplitView : NSSplitView
|
| +@end
|
| +
|
| +@implementation SidebarSplitView
|
| +- (NSColor*)dividerColor {
|
| + return [NSColor controlColor];
|
| +}
|
| +@end
|
| +
|
| +@implementation SidebarController
|
| +
|
| +- (id)initWithParentViewController:(id)parentController
|
| + andContentsController:(id)contentsController {
|
| + DCHECK(parentController);
|
| +
|
| + if (self = [super init]) {
|
| + splitView_.reset([[SidebarSplitView alloc]
|
| + initWithFrame:[[parentController view] bounds]]);
|
| + [splitView_ setDelegate:self];
|
| + [splitView_ setVertical:YES];
|
| + [splitView_ setDividerStyle:NSSplitViewDividerStyleThin];
|
| + [splitView_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
| + [[parentController view] addSubview:splitView_];
|
| +
|
| + [splitView_ addSubview:[contentsController view]];
|
| + [splitView_ adjustSubviews];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + [splitView_ setDelegate:nil];
|
| + [super dealloc];
|
| +}
|
| +
|
| +- (NSSplitView*)view {
|
| + return splitView_.get();
|
| +}
|
| +
|
| +- (void)updateSidebarForTabContents:(content::WebContents*)contents
|
| + withContext:(content::BrowserContext*)context {
|
| + // Get the active sidebar content.
|
| + extensions::SidebarManager* sidebarManager =
|
| + extensions::SidebarManager::GetFromContext(context);
|
| +
|
| + if (sidebarManager == NULL) // Happens in tests.
|
| + return;
|
| +
|
| + content::WebContents* sidebarContents = NULL;
|
| + if (contents) {
|
| + SidebarContainer* activeSidebar =
|
| + sidebarManager->GetActiveSidebarContainerFor(contents);
|
| + if (!activeSidebar)
|
| + activeSidebar = sidebarManager->MigrateSidebarTo(contents);
|
| + if (activeSidebar)
|
| + sidebarContents = activeSidebar->host_contents();
|
| + }
|
| +
|
| + if (!contentsController_.get())
|
| + contentsController_.reset(
|
| + [[TabContentsController alloc] initWithContents:contents]);
|
| +
|
| + content::WebContents* oldSidebarContents =
|
| + static_cast<content::WebContents*>([contentsController_ webContents]);
|
| + if (oldSidebarContents == sidebarContents)
|
| + return;
|
| +
|
| + // Adjust sidebar view.
|
| + [self showSidebarContents:sidebarContents];
|
| +
|
| + // Notify extensions.
|
| + sidebarManager->NotifyStateChanges(oldSidebarContents, sidebarContents);
|
| +}
|
| +
|
| +- (void)ensureContentsVisible {
|
| + [contentsController_ ensureContentsVisible];
|
| +}
|
| +
|
| +- (void)showSidebarContents:(content::WebContents*)sidebarContents {
|
| + [contentsController_ ensureContentsSizeDoesNotChange];
|
| +
|
| + NSArray* subviews = [splitView_ subviews];
|
| + if (sidebarContents) {
|
| + DCHECK_GE([subviews count], 1u);
|
| +
|
| + // Native view is a TabContentsViewCocoa object, whose ViewID was
|
| + // set to VIEW_ID_TAB_CONTAINER initially, so change it to
|
| + // VIEW_ID_SIDE_BAR_CONTAINER here.
|
| + view_id_util::SetID(sidebarContents->GetNativeView(),
|
| + VIEW_ID_SIDE_BAR_CONTAINER);
|
| +
|
| + CGFloat sidebarWidth = 0;
|
| + if ([subviews count] == 1) {
|
| + // Load the default split offset.
|
| + sidebarWidth = g_browser_process->local_state()->GetInteger(
|
| + prefs::kExtensionSidebarWidth);
|
| + if (sidebarWidth < 0) {
|
| + // Initial load, set to default value.
|
| + sidebarWidth = NSWidth([splitView_ frame]) * kDefaultSidebarWidthRatio;
|
| + }
|
| +
|
| + [splitView_ addSubview:[contentsController_ view]];
|
| + } else {
|
| + DCHECK_EQ([subviews count], 2u);
|
| + sidebarWidth = NSWidth([[subviews objectAtIndex:1] frame]);
|
| + }
|
| +
|
| + sidebarWidth = std::max(static_cast<CGFloat>(0), sidebarWidth);
|
| +
|
| + [self resizeSidebarToNewWidth:sidebarWidth];
|
| + } else {
|
| + if ([subviews count] > 1) {
|
| + NSView* oldSidebarContentsView = [subviews objectAtIndex:1];
|
| + // Store split offset when hiding sidebar window only.
|
| + int sidebarWidth = NSWidth([oldSidebarContentsView frame]);
|
| + g_browser_process->local_state()->SetInteger(
|
| + prefs::kExtensionSidebarWidth, sidebarWidth);
|
| + [oldSidebarContentsView removeFromSuperview];
|
| + [splitView_ adjustSubviews];
|
| + }
|
| + }
|
| +
|
| + [contentsController_ changeWebContents:sidebarContents];
|
| +}
|
| +
|
| +- (void)resizeSidebarToNewWidth:(CGFloat)width {
|
| + NSArray* subviews = [splitView_ subviews];
|
| +
|
| + NSView* sidebarView = [subviews objectAtIndex:1];
|
| + NSRect sidebarFrame = [sidebarView frame];
|
| + sidebarFrame.size.width = width;
|
| + [sidebarView setFrame:sidebarFrame];
|
| +
|
| + NSView* webView = [subviews objectAtIndex:0];
|
| + NSRect webFrame = [webView frame];
|
| + webFrame.size.width =
|
| + NSWidth([splitView_ frame]) - ([splitView_ dividerThickness] + width);
|
| + [webView setFrame:webFrame];
|
| +
|
| + [splitView_ adjustSubviews];
|
| +}
|
| +
|
| +/* NSSplitViewDelegate Support
|
| + *
|
| + * Sidebar behavior:
|
| + * - initial sidebar is kDefaultSidebarWidthRatio * width
|
| + * of the split-view's frame
|
| + * - sidebar width is not allowed to be greater than 50% of width of the
|
| + * the split-view's frame
|
| + *
|
| + */
|
| +
|
| +- (BOOL)splitView:(NSSplitView*)splitView
|
| + shouldHideDividerAtIndex:(NSInteger)dividerIndex {
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)splitView:(NSSplitView*)splitView canCollapseSubview:(NSView*)subview {
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)splitView:(NSSplitView*)splitView
|
| + shouldCollapseSubview:(NSView*)subview
|
| + forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex {
|
| + return NO;
|
| +}
|
| +
|
| +- (CGFloat)splitView:(NSSplitView*)splitView
|
| + constrainMinCoordinate:(CGFloat)proposedMinimumPosition
|
| + ofSubviewAt:(NSInteger)dividerIndex {
|
| + return std::max(proposedMinimumPosition,
|
| + kMaximumSidebarWidthRatio * NSWidth([splitView_ frame]));
|
| +}
|
| +
|
| +- (CGFloat)splitView:(NSSplitView*)splitView
|
| + constrainMaxCoordinate:(CGFloat)proposedMaximumPosition
|
| + ofSubviewAt:(NSInteger)dividerIndex {
|
| + return std::min(proposedMaximumPosition,
|
| + NSWidth([splitView_ frame]) - [splitView_ dividerThickness]);
|
| +}
|
| +
|
| +@end
|
|
|