CTTabWindowController.m 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Copyright (c) 2010 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-chromium file.
  4. #import "CTTabWindowController.h"
  5. #import "CTTabStripView.h"
  6. #import "common.h"
  7. #if VERSION_DMG
  8. #import <PDF_Master-Swift.h>
  9. #else
  10. #import <PDF_Master-Swift.h>
  11. #endif
  12. @interface CTTabWindowController(PRIVATE)
  13. - (void)setUseOverlay:(BOOL)useOverlay;
  14. @end
  15. @interface TabWindowOverlayWindow : NSWindow
  16. @end
  17. @implementation TabWindowOverlayWindow
  18. - (NSPoint)themePatternPhase {
  19. return NSZeroPoint;
  20. }
  21. @end
  22. @implementation CTTabWindowController {
  23. @private
  24. IBOutlet NSView* tabContentArea_;
  25. // TODO(pinkerton): Figure out a better way to initialize one or the other
  26. // w/out needing both to be in the nib.
  27. IBOutlet CTTabStripView* topTabStripView_;
  28. IBOutlet CTTabStripView* sideTabStripView_;
  29. NSWindow* overlayWindow_; // Used during dragging for window opacity tricks
  30. __weak NSView* cachedContentView_; // Used during dragging for identifying which
  31. // view is the proper content area in the overlay
  32. // (weak)
  33. NSMutableSet *lockedTabs_;
  34. BOOL closeDeferred_; // If YES, call performClose: in removeOverlay:.
  35. // Difference between height of window content area and height of the
  36. // |tabContentArea_|. Calculated when the window is loaded from the nib and
  37. // cached in order to restore the delta when switching tab modes.
  38. CGFloat contentAreaHeightDelta_;
  39. BOOL enableTransparentContent_;
  40. }
  41. @synthesize tabContentArea = tabContentArea_;
  42. - (id)initWithWindow:(NSWindow*)window {
  43. if ((self = [super initWithWindow:window]) != nil) {
  44. lockedTabs_ = [[NSMutableSet alloc] initWithCapacity:10];
  45. }
  46. return self;
  47. }
  48. - (void)dealloc {
  49. if (overlayWindow_) {
  50. [self setUseOverlay:NO];
  51. }
  52. }
  53. // Add the top tab strop to the window, above the content box and add it to the
  54. // view hierarchy as a sibling of the content view so it can overlap with the
  55. // window frame.
  56. - (void)addTopTabStripToWindow {
  57. CGFloat rightOffst = NSWidth(self.rightStripView.frame);
  58. NSRect contentFrame = [tabContentArea_ frame];
  59. NSRect rightFrame =
  60. NSMakeRect(NSWidth(contentFrame) - rightOffst, NSMaxY(contentFrame),
  61. rightOffst,
  62. NSHeight([topTabStripView_ frame]));
  63. NSRect tabFrame =
  64. NSMakeRect(topTabStripView_.frame.origin.x, NSMaxY(contentFrame),
  65. NSWidth(contentFrame)-rightOffst,
  66. NSHeight([topTabStripView_ frame]));
  67. [topTabStripView_ setFrame:tabFrame];
  68. [self.rightStripView setFrame:rightFrame];
  69. NSView* contentParent = [[[self window] contentView] superview];
  70. [contentParent addSubview:topTabStripView_ positioned:NSWindowBelow relativeTo:nil];
  71. [contentParent addSubview:self.rightStripView positioned:NSWindowAbove relativeTo:nil];
  72. }
  73. - (void)windowDidLoad {
  74. // Cache the difference in height between the window content area and the
  75. // tab content area.
  76. NSRect tabFrame = [tabContentArea_ frame];
  77. NSRect contentFrame = [[[self window] contentView] frame];
  78. contentAreaHeightDelta_ = NSHeight(contentFrame) - NSHeight(tabFrame);
  79. if ([self hasTabStrip]) {
  80. [self addTopTabStripToWindow];
  81. } else {
  82. // No top tabstrip so remove the tabContentArea offset.
  83. tabFrame.size.height = contentFrame.size.height;
  84. [tabContentArea_ setFrame:tabFrame];
  85. }
  86. }
  87. // Return the appropriate tab strip based on whether or not side tabs are
  88. // enabled.
  89. - (CTTabStripView*)tabStripView {
  90. return topTabStripView_;
  91. }
  92. - (void)removeOverlay {
  93. [self setUseOverlay:NO];
  94. if (closeDeferred_) {
  95. // See comment in BrowserWindowCocoa::Close() about orderOut:.
  96. [[self window] orderOut:self];
  97. [[self window] performClose:self]; // Autoreleases the controller.
  98. }
  99. }
  100. - (void)showOverlay {
  101. [self setUseOverlay:YES];
  102. }
  103. // if |useOverlay| is true, we're moving views into the overlay's content
  104. // area. If false, we're moving out of the overlay back into the window's
  105. // content.
  106. - (void)moveViewsBetweenWindowAndOverlay:(BOOL)useOverlay {
  107. if (useOverlay) {
  108. [[self tabStripView] setAllowGradient:NO];
  109. [[[overlayWindow_ contentView] superview] addSubview:[self tabStripView]];
  110. // Add the original window's content view as a subview of the overlay
  111. // window's content view. We cannot simply use setContentView: here because
  112. // the overlay window has a different content size (due to it being
  113. // borderless).
  114. [[overlayWindow_ contentView] addSubview:cachedContentView_];
  115. } else {
  116. [[self window] setContentView:cachedContentView_];
  117. // The CTTabStripView always needs to be in front of the window's content
  118. // view and therefore it should always be added after the content view is
  119. // set.
  120. [[self tabStripView] setAllowGradient:enableTransparentContent_];
  121. [[[[self window] contentView] superview] addSubview:[self tabStripView]
  122. positioned:NSWindowBelow
  123. relativeTo:nil];
  124. [[[[self window] contentView] superview] updateTrackingAreas];
  125. }
  126. }
  127. -(void)willStartTearingTab {
  128. }
  129. -(void)willEndTearingTab {
  130. }
  131. -(void)didEndTearingTab {
  132. }
  133. // If |useOverlay| is YES, creates a new overlay window and puts the tab strip
  134. // and the content area inside of it. This allows it to have a different opacity
  135. // from the title bar. If NO, returns everything to the previous state and
  136. // destroys the overlay window until it's needed again. The tab strip and window
  137. // contents are returned to the original window.
  138. - (void)setUseOverlay:(BOOL)useOverlay {
  139. [NSObject cancelPreviousPerformRequestsWithTarget:self
  140. selector:@selector(removeOverlay)
  141. object:nil];
  142. NSWindow* window = [self window];
  143. if (useOverlay && !overlayWindow_) {
  144. DCHECK(!cachedContentView_);
  145. overlayWindow_ = [[TabWindowOverlayWindow alloc] initWithContentRect:[window frame]
  146. styleMask:NSBorderlessWindowMask
  147. backing:NSBackingStoreBuffered
  148. defer:YES];
  149. [overlayWindow_ setTitle:@"overlay"];
  150. [overlayWindow_ setBackgroundColor:[NSColor clearColor]];
  151. [overlayWindow_ setOpaque:NO];
  152. [overlayWindow_ setDelegate:self];
  153. cachedContentView_ = [window contentView];
  154. [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
  155. [window makeFirstResponder:nil];
  156. [self moveViewsBetweenWindowAndOverlay:useOverlay];
  157. [overlayWindow_ orderFront:nil];
  158. } else if (!useOverlay && overlayWindow_) {
  159. DCHECK(cachedContentView_);
  160. [window setContentView:cachedContentView_];
  161. [self moveViewsBetweenWindowAndOverlay:useOverlay];
  162. [window makeFirstResponder:cachedContentView_];
  163. [window display];
  164. [window removeChildWindow:overlayWindow_];
  165. [overlayWindow_ orderOut:nil];
  166. overlayWindow_ = nil;
  167. cachedContentView_ = nil;
  168. } else {
  169. NOTREACHED();
  170. }
  171. }
  172. - (NSWindow*)overlayWindow {
  173. return overlayWindow_;
  174. }
  175. - (BOOL)shouldConstrainFrameRect {
  176. // If we currently have an overlay window, do not attempt to change the
  177. // window's size, as our overlay window doesn't know how to resize properly.
  178. return overlayWindow_ == nil;
  179. }
  180. - (BOOL)canReceiveFrom:(CTTabWindowController*)source {
  181. // subclass must implement
  182. NOTIMPLEMENTED();
  183. return NO;
  184. }
  185. - (void)moveTabView:(NSView*)view
  186. fromController:(CTTabWindowController*)dragController {
  187. NOTIMPLEMENTED();
  188. }
  189. - (NSView*)activeTabView {
  190. NOTIMPLEMENTED();
  191. return nil;
  192. }
  193. - (void)layoutTabs {
  194. // subclass must implement
  195. NOTIMPLEMENTED();
  196. }
  197. - (CTTabWindowController*)detachTabToNewWindow:(CTTabView*)tabView {
  198. // subclass must implement
  199. NOTIMPLEMENTED();
  200. return NULL;
  201. }
  202. - (void)insertPlaceholderForTab:(CTTabView*)tab
  203. frame:(NSRect)frame {
  204. self.showsNewTabButton = NO;
  205. }
  206. - (void)removePlaceholder {
  207. self.showsNewTabButton = YES;
  208. }
  209. - (BOOL)tabDraggingAllowed {
  210. return YES;
  211. }
  212. - (BOOL)tabTearingAllowed {
  213. return YES;
  214. }
  215. - (BOOL)windowMovementAllowed {
  216. return YES;
  217. }
  218. - (BOOL)isTabFullyVisible:(CTTabView*)tab {
  219. // Subclasses should implement this, but it's not necessary.
  220. return YES;
  221. }
  222. - (void)setShowsNewTabButton:(BOOL)show {
  223. // subclass must implement
  224. NOTIMPLEMENTED();
  225. }
  226. - (BOOL)showsNewTabButton {
  227. // subclass must implement
  228. NOTIMPLEMENTED();
  229. }
  230. - (void)setEnableTransparentContent:(BOOL)enable {
  231. enableTransparentContent_ = enable;
  232. if (enableTransparentContent_) {
  233. [self.window setOpaque:NO];
  234. } else {
  235. [self.window setOpaque:YES];
  236. }
  237. if (!overlayWindow_) {
  238. [topTabStripView_ setAllowGradient:enable];
  239. }
  240. }
  241. - (BOOL)enableTransparentContent {
  242. return enableTransparentContent_;
  243. }
  244. - (void)detachTabView:(NSView*)view {
  245. // subclass must implement
  246. NOTIMPLEMENTED();
  247. }
  248. - (NSInteger)numberOfTabs {
  249. // subclass must implement
  250. NOTIMPLEMENTED();
  251. return 0;
  252. }
  253. - (BOOL)hasLiveTabs {
  254. // subclass must implement
  255. NOTIMPLEMENTED();
  256. return NO;
  257. }
  258. - (NSString*)activeTabTitle {
  259. // subclass must implement
  260. NOTIMPLEMENTED();
  261. return @"";
  262. }
  263. - (BOOL)hasTabStrip {
  264. // Subclasses should implement this.
  265. NOTIMPLEMENTED();
  266. return YES;
  267. }
  268. - (BOOL)isTabDraggable:(NSView*)tabView {
  269. return ![lockedTabs_ containsObject:tabView];
  270. }
  271. - (void)setTab:(NSView*)tabView isDraggable:(BOOL)draggable {
  272. if (draggable)
  273. [lockedTabs_ removeObject:tabView];
  274. else
  275. [lockedTabs_ addObject:tabView];
  276. }
  277. // Tell the window that it needs to call performClose: as soon as the current
  278. // drag is complete. This prevents a window (and its overlay) from going away
  279. // during a drag.
  280. - (void)deferPerformClose {
  281. closeDeferred_ = YES;
  282. }
  283. // Called when the size of the window content area has changed. Override to
  284. // position specific views. Base class implementation does nothing.
  285. - (void)layoutSubviews {
  286. NOTIMPLEMENTED();
  287. }
  288. @end