blob: 1e1e8f42f7921e47507d1788d26a5da355408d5a [file] [log] [blame]
// 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.
#import "chrome/browser/cocoa/dev_tools_controller.h"
#include <algorithm>
#include <Cocoa/Cocoa.h>
#include "chrome/browser/browser_process.h"
#import "chrome/browser/cocoa/view_id_util.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
namespace {
// Default offset of the contents splitter in pixels.
const int kDefaultContentsSplitOffset = 400;
// Never make the web part of the tab contents smaller than this (needed if the
// window is only a few pixels high).
const int kMinWebHeight = 50;
} // end namespace
@interface DevToolsController (Private)
- (void)showDevToolsContents:(TabContents*)devToolsContents;
- (void)resizeDevToolsToNewHeight:(CGFloat)height;
@end
@implementation DevToolsController
- (id)initWithDelegate:(id<TabContentsControllerDelegate>)delegate {
if ((self = [super init])) {
splitView_.reset([[NSSplitView alloc] initWithFrame:NSZeroRect]);
[splitView_ setDividerStyle:NSSplitViewDividerStyleThin];
[splitView_ setVertical:NO];
[splitView_ setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
[splitView_ setDelegate:self];
contentsController_.reset(
[[TabContentsController alloc] initWithContents:NULL
delegate:delegate]);
}
return self;
}
- (void)dealloc {
[splitView_ setDelegate:nil];
[super dealloc];
}
- (NSView*)view {
return splitView_.get();
}
- (NSSplitView*)splitView {
return splitView_.get();
}
- (void)updateDevToolsForTabContents:(TabContents*)contents {
// Get current devtools content.
TabContents* devToolsContents = contents ?
DevToolsWindow::GetDevToolsContents(contents) : NULL;
[self showDevToolsContents:devToolsContents];
}
- (void)ensureContentsVisible {
[contentsController_ ensureContentsVisible];
}
- (void)showDevToolsContents:(TabContents*)devToolsContents {
[contentsController_ ensureContentsSizeDoesNotChange];
NSArray* subviews = [splitView_ subviews];
if (devToolsContents) {
DCHECK_GE([subviews count], 1u);
// |devToolsView| is a TabContentsViewCocoa object, whose ViewID was
// set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
// VIEW_ID_DEV_TOOLS_DOCKED here.
view_id_util::SetID(
devToolsContents->GetNativeView(), VIEW_ID_DEV_TOOLS_DOCKED);
CGFloat splitOffset = 0;
if ([subviews count] == 1) {
// Load the default split offset.
splitOffset = g_browser_process->local_state()->GetInteger(
prefs::kDevToolsSplitLocation);
if (splitOffset < 0) {
// Initial load, set to default value.
splitOffset = kDefaultContentsSplitOffset;
}
[splitView_ addSubview:[contentsController_ view]];
} else {
DCHECK_EQ([subviews count], 2u);
// If devtools are already visible, keep the current size.
splitOffset = NSHeight([[subviews objectAtIndex:1] frame]);
}
// Make sure |splitOffset| isn't too large or too small.
splitOffset = std::max(static_cast<CGFloat>(kMinWebHeight), splitOffset);
splitOffset =
std::min(splitOffset, NSHeight([splitView_ frame]) - kMinWebHeight);
DCHECK_GE(splitOffset, 0) << "kMinWebHeight needs to be smaller than "
<< "smallest available tab contents space.";
[self resizeDevToolsToNewHeight:splitOffset];
} else {
if ([subviews count] > 1) {
NSView* oldDevToolsContentsView = [subviews objectAtIndex:1];
// Store split offset when hiding devtools window only.
int splitOffset = NSHeight([oldDevToolsContentsView frame]);
g_browser_process->local_state()->SetInteger(
prefs::kDevToolsSplitLocation, splitOffset);
[oldDevToolsContentsView removeFromSuperview];
[splitView_ adjustSubviews];
}
}
[contentsController_ changeTabContents:devToolsContents];
}
- (void)resizeDevToolsToNewHeight:(CGFloat)height {
NSArray* subviews = [splitView_ subviews];
// It seems as if |-setPosition:ofDividerAtIndex:| should do what's needed,
// but I can't figure out how to use it. Manually resize web and devtools.
// TODO(alekseys): either make setPosition:ofDividerAtIndex: work or to add a
// category on NSSplitView to handle manual resizing.
NSView* devToolsView = [subviews objectAtIndex:1];
NSRect devToolsFrame = [devToolsView frame];
devToolsFrame.size.height = height;
[devToolsView setFrame:devToolsFrame];
NSView* webView = [subviews objectAtIndex:0];
NSRect webFrame = [webView frame];
webFrame.size.height =
NSHeight([splitView_ frame]) - ([splitView_ dividerThickness] + height);
[webView setFrame:webFrame];
[splitView_ adjustSubviews];
}
// NSSplitViewDelegate protocol.
- (BOOL)splitView:(NSSplitView *)splitView
shouldAdjustSizeOfSubview:(NSView *)subview {
// Return NO for the devTools view to indicate that it should not be resized
// automatically. It preserves the height set by the user and also keeps
// view height the same while changing tabs when one of the tabs shows infobar
// and others are not.
if ([[splitView_ subviews] indexOfObject:subview] == 1)
return NO;
return YES;
}
@end