[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / tabs / tab_window_controller.mm
blob97c527a7ea929f88adb9402fc8ab7858b91c6d52
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.
5 #import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
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"
15 @interface TabWindowController(PRIVATE)
16 - (void)setUseOverlay:(BOOL)useOverlay;
17 @end
19 @interface TabWindowOverlayWindow : NSWindow
20 @end
22 @implementation TabWindowOverlayWindow
24 - (ui::ThemeProvider*)themeProvider {
25   if ([self parentWindow])
26     return [[[self parentWindow] windowController] themeProvider];
27   return NULL;
30 - (ThemedWindowStyle)themedWindowStyle {
31   if ([self parentWindow])
32     return [[[self parentWindow] windowController] themedWindowStyle];
33   return NO;
36 - (NSPoint)themeImagePositionForAlignment:(ThemeImageAlignment)alignment {
37   if ([self parentWindow]) {
38     return [[[self parentWindow] windowController]
39         themeImagePositionForAlignment:alignment];
40   }
41   return NSZeroPoint;
44 @end
46 @implementation TabWindowController
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];
56   if ((self = [super initWithWindow:window])) {
57     [[self window] setDelegate:self];
59     tabContentArea_.reset([[FastResizeView alloc] initWithFrame:
60         NSMakeRect(0, 0, 750, 600)]);
61     [tabContentArea_ setAutoresizingMask:NSViewWidthSizable |
62                                          NSViewHeightSizable];
63     [[[self window] contentView] addSubview:tabContentArea_];
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;
75 - (TabStripView*)tabStripView {
76   return tabStripView_;
79 - (FastResizeView*)tabContentArea {
80   return tabContentArea_;
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_];
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   }
102 - (void)showOverlay {
103   [self setUseOverlay:YES];
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_);
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];
129     originalContentView_ = [window contentView];
130     [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
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];
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_];
147     [overlayWindow_ orderFront:nil];
148   } else if (!useOverlay && overlayWindow_) {
149     DCHECK(originalContentView_);
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];
159     [focusBeforeOverlay_ restoreFocusInWindow:window];
160     focusBeforeOverlay_.reset();
162     [window display];
163     [window removeChildWindow:overlayWindow_];
165     [overlayWindow_ orderOut:nil];
166     [overlayWindow_ release];
167     overlayWindow_ = nil;
168     originalContentView_ = nil;
169   } else {
170     NOTREACHED();
171   }
174 - (NSWindow*)overlayWindow {
175   return overlayWindow_;
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;
184 - (BOOL)canReceiveFrom:(TabWindowController*)source {
185   // subclass must implement
186   NOTIMPLEMENTED();
187   return NO;
190 - (void)moveTabViews:(NSArray*)views
191       fromController:(TabWindowController*)dragController {
192   NOTIMPLEMENTED();
195 - (NSArray*)tabViews {
196   NOTIMPLEMENTED();
197   return nil;
200 - (NSView*)activeTabView {
201   NOTIMPLEMENTED();
202   return nil;
205 - (void)layoutTabs {
206   // subclass must implement
207   NOTIMPLEMENTED();
210 - (TabWindowController*)detachTabsToNewWindow:(NSArray*)tabViews
211                                    draggedTab:(NSView*)draggedTab {
212   // subclass must implement
213   NOTIMPLEMENTED();
214   return NULL;
217 - (void)insertPlaceholderForTab:(TabView*)tab frame:(NSRect)frame {
218   [self showNewTabButton:NO];
221 - (void)removePlaceholder {
222   [self showNewTabButton:YES];
225 - (BOOL)isDragSessionActive {
226   NOTIMPLEMENTED();
227   return NO;
230 - (BOOL)tabDraggingAllowed {
231   return YES;
234 - (BOOL)tabTearingAllowed {
235   return YES;
238 - (BOOL)windowMovementAllowed {
239   return YES;
242 - (BOOL)isTabFullyVisible:(TabView*)tab {
243   // Subclasses should implement this, but it's not necessary.
244   return YES;
247 - (void)showNewTabButton:(BOOL)show {
248   // subclass must implement
249   NOTIMPLEMENTED();
252 - (void)detachTabView:(NSView*)view {
253   // subclass must implement
254   NOTIMPLEMENTED();
257 - (NSInteger)numberOfTabs {
258   // subclass must implement
259   NOTIMPLEMENTED();
260   return 0;
263 - (BOOL)hasLiveTabs {
264   // subclass must implement
265   NOTIMPLEMENTED();
266   return NO;
269 - (NSString*)activeTabTitle {
270   // subclass must implement
271   NOTIMPLEMENTED();
272   return @"";
275 - (BOOL)hasTabStrip {
276   // Subclasses should implement this.
277   NOTIMPLEMENTED();
278   return YES;
281 - (BOOL)isTabDraggable:(NSView*)tabView {
282   // Subclasses should implement this.
283   NOTIMPLEMENTED();
284   return YES;
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;
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();
300 @end