5d65f1e4b0645de301f972bbd7120e0f01ce3c68
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / dev_tools_controller.mm
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/dev_tools_controller.h"
6
7 #include <algorithm>
8 #include <cmath>
9
10 #include <Cocoa/Cocoa.h>
11
12 #include "base/prefs/pref_service.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/profiles/profile.h"
15 #import "chrome/browser/ui/cocoa/view_id_util.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/public/browser/web_contents.h"
18 #include "ui/base/cocoa/base_view.h"
19 #include "ui/base/cocoa/focus_tracker.h"
20 #include "ui/gfx/mac/scoped_ns_disable_screen_updates.h"
21 #include "ui/gfx/size_conversions.h"
22
23 using content::WebContents;
24
25 @interface DevToolsContainerView : BaseView {
26   DevToolsContentsResizingStrategy strategy_;
27
28   // Weak references. Ownership via -subviews.
29   NSView* devToolsView_;
30   NSView* contentsView_;
31 }
32
33 - (void)setContentsResizingStrategy:
34     (const DevToolsContentsResizingStrategy&)strategy;
35 - (void)adjustSubviews;
36 - (void)showDevTools:(NSView*)devToolsView;
37 - (void)hideDevTools;
38
39 @end
40
41
42 @implementation DevToolsContainerView
43
44 - (void)setContentsResizingStrategy:
45     (const DevToolsContentsResizingStrategy&)strategy {
46   strategy_.CopyFrom(strategy);
47 }
48
49 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
50   [self adjustSubviews];
51 }
52
53 - (void)showDevTools:(NSView*)devToolsView {
54   NSArray* subviews = [self subviews];
55   DCHECK_EQ(1u, [subviews count]);
56   contentsView_ = [subviews objectAtIndex:0];
57   devToolsView_ = devToolsView;
58   // Place DevTools under contents.
59   [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
60 }
61
62 - (void)hideDevTools {
63   DCHECK_EQ(2u, [[self subviews] count]);
64   [devToolsView_ removeFromSuperview];
65   contentsView_ = nil;
66   devToolsView_ = nil;
67 }
68
69 - (void)adjustSubviews {
70   if (![[self subviews] count])
71     return;
72
73   if (!devToolsView_) {
74     DCHECK_EQ(1u, [[self subviews] count]);
75     NSView* contents = [[self subviews] objectAtIndex:0];
76     [contents setFrame:[self bounds]];
77     return;
78   }
79
80   DCHECK_EQ(2u, [[self subviews] count]);
81
82   gfx::Rect new_devtools_bounds;
83   gfx::Rect new_contents_bounds;
84   ApplyDevToolsContentsResizingStrategy(
85       strategy_, gfx::Size(NSSizeToCGSize([self bounds].size)),
86       [self flipNSRectToRect:[devToolsView_ bounds]],
87       [self flipNSRectToRect:[contentsView_ bounds]],
88       &new_devtools_bounds, &new_contents_bounds);
89   [devToolsView_ setFrame:[self flipRectToNSRect:new_devtools_bounds]];
90   [contentsView_ setFrame:[self flipRectToNSRect:new_contents_bounds]];
91 }
92
93 @end
94
95 @interface DevToolsController (Private)
96 - (void)showDevToolsView;
97 - (void)hideDevToolsView;
98 @end
99
100
101 @implementation DevToolsController
102
103 - (id)init {
104   if ((self = [super init])) {
105     devToolsContainerView_.reset(
106         [[DevToolsContainerView alloc] initWithFrame:NSZeroRect]);
107     [devToolsContainerView_
108         setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
109   }
110   return self;
111 }
112
113 - (NSView*)view {
114   return devToolsContainerView_.get();
115 }
116
117 - (void)updateDevToolsForWebContents:(WebContents*)contents
118                          withProfile:(Profile*)profile {
119   DevToolsWindow* newDevToolsWindow = contents ?
120       DevToolsWindow::GetDockedInstanceForInspectedTab(contents) : NULL;
121
122   // Make sure we do not draw any transient arrangements of views.
123   gfx::ScopedNSDisableScreenUpdates disabler;
124   bool shouldHide = devToolsWindow_ && devToolsWindow_ != newDevToolsWindow;
125   bool shouldShow = newDevToolsWindow && devToolsWindow_ != newDevToolsWindow;
126
127   if (shouldHide)
128     [self hideDevToolsView];
129
130   devToolsWindow_ = newDevToolsWindow;
131   if (devToolsWindow_) {
132     const DevToolsContentsResizingStrategy& strategy =
133         devToolsWindow_->GetContentsResizingStrategy();
134     devToolsWindow_->web_contents()->SetOverlayView(
135         contents,
136         gfx::Point(strategy.insets().left(), strategy.insets().top()));
137     [devToolsContainerView_ setContentsResizingStrategy:strategy];
138   } else {
139     DevToolsContentsResizingStrategy zeroStrategy;
140     [devToolsContainerView_ setContentsResizingStrategy:zeroStrategy];
141   }
142
143   if (shouldShow)
144     [self showDevToolsView];
145
146   [devToolsContainerView_ adjustSubviews];
147 }
148
149 - (void)showDevToolsView {
150   focusTracker_.reset(
151       [[FocusTracker alloc] initWithWindow:[devToolsContainerView_ window]]);
152
153   // |devToolsView| is a WebContentsViewCocoa object, whose ViewID was
154   // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
155   // VIEW_ID_DEV_TOOLS_DOCKED here.
156   NSView* devToolsView = devToolsWindow_->web_contents()->GetNativeView();
157   view_id_util::SetID(devToolsView, VIEW_ID_DEV_TOOLS_DOCKED);
158
159   [devToolsContainerView_ showDevTools:devToolsView];
160 }
161
162 - (void)hideDevToolsView {
163   devToolsWindow_->web_contents()->RemoveOverlayView();
164   [devToolsContainerView_ hideDevTools];
165   [focusTracker_ restoreFocusInWindow:[devToolsContainerView_ window]];
166   focusTracker_.reset();
167 }
168
169 @end