Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / tabs / tab_window_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/tabs/tab_window_controller.h"
6
7 #include "base/logging.h"
8 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
9 #import "chrome/browser/ui/cocoa/framed_browser_window.h"
10 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
11 #import "chrome/browser/ui/cocoa/themed_window.h"
12 #import "ui/base/cocoa/focus_tracker.h"
13 #include "ui/base/theme_provider.h"
14
15 @interface TabWindowController(PRIVATE)
16 - (void)setUseOverlay:(BOOL)useOverlay;
17 @end
18
19 @interface TabWindowOverlayWindow : NSWindow
20 @end
21
22 @implementation TabWindowOverlayWindow
23
24 - (ui::ThemeProvider*)themeProvider {
25   if ([self parentWindow])
26     return [[[self parentWindow] windowController] themeProvider];
27   return NULL;
28 }
29
30 - (ThemedWindowStyle)themedWindowStyle {
31   if ([self parentWindow])
32     return [[[self parentWindow] windowController] themedWindowStyle];
33   return NO;
34 }
35
36 - (NSPoint)themeImagePositionForAlignment:(ThemeImageAlignment)alignment {
37   if ([self parentWindow]) {
38     return [[[self parentWindow] windowController]
39         themeImagePositionForAlignment:alignment];
40   }
41   return NSZeroPoint;
42 }
43
44 @end
45
46 @implementation TabWindowController
47
48 - (id)initTabWindowControllerWithTabStrip:(BOOL)hasTabStrip {
49   NSRect contentRect = NSMakeRect(60, 229, 750, 600);
50   base::scoped_nsobject<FramedBrowserWindow> window(
51       [[FramedBrowserWindow alloc] initWithContentRect:contentRect
52                                            hasTabStrip:hasTabStrip]);
53   [window setReleasedWhenClosed:YES];
54   [window setAutorecalculatesKeyViewLoop:YES];
55
56   if ((self = [super initWithWindow:window])) {
57     [[self window] setDelegate:self];
58
59     tabContentArea_.reset([[FastResizeView alloc] initWithFrame:
60         NSMakeRect(0, 0, 750, 600)]);
61     [tabContentArea_ setAutoresizingMask:NSViewWidthSizable |
62                                          NSViewHeightSizable];
63     [[[self window] contentView] addSubview:tabContentArea_];
64
65     tabStripView_.reset([[TabStripView alloc] initWithFrame:
66         NSMakeRect(0, 0, 750, 37)]);
67     [tabStripView_ setAutoresizingMask:NSViewWidthSizable |
68                                        NSViewMinYMargin];
69     if (hasTabStrip)
70       [self addTabStripToWindow];
71   }
72   return self;
73 }
74
75 - (TabStripView*)tabStripView {
76   return tabStripView_;
77 }
78
79 - (FastResizeView*)tabContentArea {
80   return tabContentArea_;
81 }
82
83 // Add the top tab strop to the window, above the content box and add it to the
84 // view hierarchy as a sibling of the content view so it can overlap with the
85 // window frame.
86 - (void)addTabStripToWindow {
87   // The frame doesn't matter. This class relies on subclasses to do tab strip
88   // layout.
89   NSView* contentParent = [[[self window] contentView] superview];
90   [contentParent addSubview:tabStripView_];
91 }
92
93 - (void)removeOverlay {
94   [self setUseOverlay:NO];
95   if (closeDeferred_) {
96     // See comment in BrowserWindowCocoa::Close() about orderOut:.
97     [[self window] orderOut:self];
98     [[self window] performClose:self];  // Autoreleases the controller.
99   }
100 }
101
102 - (void)showOverlay {
103   [self setUseOverlay:YES];
104 }
105
106 // If |useOverlay| is YES, creates a new overlay window and puts the tab strip
107 // and the content area inside of it. This allows it to have a different opacity
108 // from the title bar. If NO, returns everything to the previous state and
109 // destroys the overlay window until it's needed again. The tab strip and window
110 // contents are returned to the original window.
111 - (void)setUseOverlay:(BOOL)useOverlay {
112   [NSObject cancelPreviousPerformRequestsWithTarget:self
113                                            selector:@selector(removeOverlay)
114                                              object:nil];
115   NSWindow* window = [self window];
116   if (useOverlay && !overlayWindow_) {
117     DCHECK(!originalContentView_);
118
119     overlayWindow_ = [[TabWindowOverlayWindow alloc]
120                          initWithContentRect:[window frame]
121                                    styleMask:NSBorderlessWindowMask
122                                      backing:NSBackingStoreBuffered
123                                        defer:YES];
124     [overlayWindow_ setTitle:@"overlay"];
125     [overlayWindow_ setBackgroundColor:[NSColor clearColor]];
126     [overlayWindow_ setOpaque:NO];
127     [overlayWindow_ setDelegate:self];
128
129     originalContentView_ = [window contentView];
130     [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
131
132     // Explicitly set the responder to be nil here (for restoring later).
133     // If the first responder were to be left non-nil here then
134     // [RenderWidgethostViewCocoa resignFirstResponder] would be called,
135     // followed by RenderWidgetHost::Blur(), which would result in an unexpected
136     // loss of focus.
137     focusBeforeOverlay_.reset([[FocusTracker alloc] initWithWindow:window]);
138     [window makeFirstResponder:nil];
139
140     // Move the original window's tab strip view and content view to the overlay
141     // window. The content view is added as a subview of the overlay window's
142     // content view (rather than using setContentView:) because the overlay
143     // window has a different content size (due to it being borderless).
144     [[[overlayWindow_ contentView] superview] addSubview:[self tabStripView]];
145     [[overlayWindow_ contentView] addSubview:originalContentView_];
146
147     [overlayWindow_ orderFront:nil];
148   } else if (!useOverlay && overlayWindow_) {
149     DCHECK(originalContentView_);
150
151     // Return the original window's tab strip view and content view to their
152     // places. The TabStripView always needs to be in front of the window's
153     // content view and therefore it should always be added after the content
154     // view is set.
155     [window setContentView:originalContentView_];
156     [[[window contentView] superview] addSubview:[self tabStripView]];
157     [[[window contentView] superview] updateTrackingAreas];
158
159     [focusBeforeOverlay_ restoreFocusInWindow:window];
160     focusBeforeOverlay_.reset();
161
162     [window display];
163     [window removeChildWindow:overlayWindow_];
164
165     [overlayWindow_ orderOut:nil];
166     [overlayWindow_ release];
167     overlayWindow_ = nil;
168     originalContentView_ = nil;
169   } else {
170     NOTREACHED();
171   }
172 }
173
174 - (NSWindow*)overlayWindow {
175   return overlayWindow_;
176 }
177
178 - (BOOL)shouldConstrainFrameRect {
179   // If we currently have an overlay window, do not attempt to change the
180   // window's size, as our overlay window doesn't know how to resize properly.
181   return overlayWindow_ == nil;
182 }
183
184 - (BOOL)canReceiveFrom:(TabWindowController*)source {
185   // subclass must implement
186   NOTIMPLEMENTED();
187   return NO;
188 }
189
190 - (void)moveTabViews:(NSArray*)views
191       fromController:(TabWindowController*)dragController {
192   NOTIMPLEMENTED();
193 }
194
195 - (NSArray*)tabViews {
196   NOTIMPLEMENTED();
197   return nil;
198 }
199
200 - (NSView*)activeTabView {
201   NOTIMPLEMENTED();
202   return nil;
203 }
204
205 - (void)layoutTabs {
206   // subclass must implement
207   NOTIMPLEMENTED();
208 }
209
210 - (TabWindowController*)detachTabsToNewWindow:(NSArray*)tabViews
211                                    draggedTab:(NSView*)draggedTab {
212   // subclass must implement
213   NOTIMPLEMENTED();
214   return NULL;
215 }
216
217 - (void)insertPlaceholderForTab:(TabView*)tab frame:(NSRect)frame {
218   [self showNewTabButton:NO];
219 }
220
221 - (void)removePlaceholder {
222   [self showNewTabButton:YES];
223 }
224
225 - (BOOL)isDragSessionActive {
226   NOTIMPLEMENTED();
227   return NO;
228 }
229
230 - (BOOL)tabDraggingAllowed {
231   return YES;
232 }
233
234 - (BOOL)tabTearingAllowed {
235   return YES;
236 }
237
238 - (BOOL)windowMovementAllowed {
239   return YES;
240 }
241
242 - (BOOL)isTabFullyVisible:(TabView*)tab {
243   // Subclasses should implement this, but it's not necessary.
244   return YES;
245 }
246
247 - (void)showNewTabButton:(BOOL)show {
248   // subclass must implement
249   NOTIMPLEMENTED();
250 }
251
252 - (void)detachTabView:(NSView*)view {
253   // subclass must implement
254   NOTIMPLEMENTED();
255 }
256
257 - (NSInteger)numberOfTabs {
258   // subclass must implement
259   NOTIMPLEMENTED();
260   return 0;
261 }
262
263 - (BOOL)hasLiveTabs {
264   // subclass must implement
265   NOTIMPLEMENTED();
266   return NO;
267 }
268
269 - (NSString*)activeTabTitle {
270   // subclass must implement
271   NOTIMPLEMENTED();
272   return @"";
273 }
274
275 - (BOOL)hasTabStrip {
276   // Subclasses should implement this.
277   NOTIMPLEMENTED();
278   return YES;
279 }
280
281 - (BOOL)isTabDraggable:(NSView*)tabView {
282   // Subclasses should implement this.
283   NOTIMPLEMENTED();
284   return YES;
285 }
286
287 // Tell the window that it needs to call performClose: as soon as the current
288 // drag is complete. This prevents a window (and its overlay) from going away
289 // during a drag.
290 - (void)deferPerformClose {
291   closeDeferred_ = YES;
292 }
293
294 // Called when the size of the window content area has changed. Override to
295 // position specific views. Base class implementation does nothing.
296 - (void)layoutSubviews {
297   NOTIMPLEMENTED();
298 }
299
300 @end