- add sources.
[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)moveTabView:(NSView*)view
191      fromController:(TabWindowController*)dragController {
192   NOTIMPLEMENTED();
193 }
194
195 - (NSView*)activeTabView {
196   NOTIMPLEMENTED();
197   return nil;
198 }
199
200 - (void)layoutTabs {
201   // subclass must implement
202   NOTIMPLEMENTED();
203 }
204
205 - (TabWindowController*)detachTabToNewWindow:(TabView*)tabView {
206   // subclass must implement
207   NOTIMPLEMENTED();
208   return NULL;
209 }
210
211 - (void)insertPlaceholderForTab:(TabView*)tab frame:(NSRect)frame {
212   [self showNewTabButton:NO];
213 }
214
215 - (void)removePlaceholder {
216   [self showNewTabButton:YES];
217 }
218
219 - (BOOL)isDragSessionActive {
220   NOTIMPLEMENTED();
221   return NO;
222 }
223
224 - (BOOL)tabDraggingAllowed {
225   return YES;
226 }
227
228 - (BOOL)tabTearingAllowed {
229   return YES;
230 }
231
232 - (BOOL)windowMovementAllowed {
233   return YES;
234 }
235
236 - (BOOL)isTabFullyVisible:(TabView*)tab {
237   // Subclasses should implement this, but it's not necessary.
238   return YES;
239 }
240
241 - (void)showNewTabButton:(BOOL)show {
242   // subclass must implement
243   NOTIMPLEMENTED();
244 }
245
246 - (void)detachTabView:(NSView*)view {
247   // subclass must implement
248   NOTIMPLEMENTED();
249 }
250
251 - (NSInteger)numberOfTabs {
252   // subclass must implement
253   NOTIMPLEMENTED();
254   return 0;
255 }
256
257 - (BOOL)hasLiveTabs {
258   // subclass must implement
259   NOTIMPLEMENTED();
260   return NO;
261 }
262
263 - (NSString*)activeTabTitle {
264   // subclass must implement
265   NOTIMPLEMENTED();
266   return @"";
267 }
268
269 - (BOOL)hasTabStrip {
270   // Subclasses should implement this.
271   NOTIMPLEMENTED();
272   return YES;
273 }
274
275 - (BOOL)isTabDraggable:(NSView*)tabView {
276   // Subclasses should implement this.
277   NOTIMPLEMENTED();
278   return YES;
279 }
280
281 // Tell the window that it needs to call performClose: as soon as the current
282 // drag is complete. This prevents a window (and its overlay) from going away
283 // during a drag.
284 - (void)deferPerformClose {
285   closeDeferred_ = YES;
286 }
287
288 // Called when the size of the window content area has changed. Override to
289 // position specific views. Base class implementation does nothing.
290 - (void)layoutSubviews {
291   NOTIMPLEMENTED();
292 }
293
294 @end