diff options
author | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-19 19:11:25 +0000 |
---|---|---|
committer | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-19 19:11:25 +0000 |
commit | c0e5501cc6e6259381211007e5fc5f3950fc4fab (patch) | |
tree | 8b2ae9f6aee6af45c29c0f6543c5673c18f766e1 /chrome | |
parent | 63c85eee887a619b61fe4454b579237fdcaf25b9 (diff) | |
download | chromium_src-c0e5501cc6e6259381211007e5fc5f3950fc4fab.zip chromium_src-c0e5501cc6e6259381211007e5fc5f3950fc4fab.tar.gz chromium_src-c0e5501cc6e6259381211007e5fc5f3950fc4fab.tar.bz2 |
Stage 1 of tab dragging infrastructure, disabled. Put in a base class below the browser window for windows with tabs to promote re-use in contexts other than just the browser. Add code to the tab view to track drags, but it's disabled as it still needs much work.
Review URL: http://codereview.chromium.org/42397
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12125 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/app/nibs/en.lproj/BrowserWindow.xib | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 13 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 29 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_controller.mm | 1 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_view.mm | 191 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_window_controller.h | 55 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_window_controller.mm | 100 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
8 files changed, 371 insertions, 22 deletions
diff --git a/chrome/app/nibs/en.lproj/BrowserWindow.xib b/chrome/app/nibs/en.lproj/BrowserWindow.xib index eb76ef9..dd5073b 100644 --- a/chrome/app/nibs/en.lproj/BrowserWindow.xib +++ b/chrome/app/nibs/en.lproj/BrowserWindow.xib @@ -105,7 +105,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSButton" id="131944810"> <reference key="NSNextResponder" ref="1029219716"/> - <int key="NSvFlags">-2147483348</int> + <int key="NSvFlags">300</int> <string key="NSFrame">{{295, 0}, {40, 27}}</string> <reference key="NSSuperview" ref="1029219716"/> <bool key="NSEnabled">YES</bool> diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index 443a8d8..1e1e798 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -10,6 +10,8 @@ #import <Cocoa/Cocoa.h> +#import "chrome/browser/cocoa/tab_window_controller.h" + class Browser; class BrowserWindow; class BrowserWindowCocoa; @@ -20,18 +22,11 @@ class TabContents; @class TabStripController; @interface BrowserWindowController : - NSWindowController<NSUserInterfaceValidations> { + TabWindowController<NSUserInterfaceValidations> { @private + TabStripController* tabStripController_; Browser* browser_; BrowserWindowCocoa* windowShim_; - TabStripController* tabStripController_; - - IBOutlet NSBox* contentBox_; - IBOutlet TabStripView* tabStripView_; - - // Views for the toolbar - IBOutlet NSView* toolbarView_; - IBOutlet NSTextField* urlBarView_; } // Load the browser window nib and do any Cocoa-specific initialization. diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index f5d0d02..b20f30c 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -37,20 +37,14 @@ } - (void)windowDidLoad { + [super windowDidLoad]; + // Create a controller for the tab strip, giving it the model object for // this window's Browser and the tab strip view. The controller will handle // registering for the appropriate tab notifications from the back-end and // managing the creation of new tabs. tabStripController_ = [[TabStripController alloc] - initWithView:tabStripView_ browser:browser_]; - - // Place the tab bar above the content box and add it to the view hierarchy - // as a sibling of the content view so it can overlap with the window frame. - NSRect tabFrame = [contentBox_ frame]; - tabFrame.origin = NSMakePoint(0, NSMaxY(tabFrame)); - tabFrame.size.height = NSHeight([tabStripView_ frame]); - [tabStripView_ setFrame:tabFrame]; - [[[[self window] contentView] superview] addSubview:tabStripView_]; + initWithView:[self tabStripView] browser:browser_]; } - (void)destroyBrowser { @@ -200,6 +194,23 @@ [tabStripController_ focusLocationBar]; } +- (void)arrangeTabs { + NOTIMPLEMENTED(); +} + +- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView { + NOTIMPLEMENTED(); + return NULL; +} + +- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation { + NOTIMPLEMENTED(); +} + +- (void)removePlaceholder { + NOTIMPLEMENTED(); +} + - (BOOL)isBookmarkBarVisible { return [tabStripController_ isBookmarkBarVisible]; diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm index ce74d1c..ef8363e 100644 --- a/chrome/browser/cocoa/tab_strip_controller.mm +++ b/chrome/browser/cocoa/tab_strip_controller.mm @@ -196,7 +196,6 @@ class TabStripBridge : public TabStripModelObserver { NSRect newTabButtonFrame = [newTabButton_ frame]; newTabButtonFrame.origin.x = maxRightEdge + kNewTabXOffset; [newTabButton_ setFrame:newTabButtonFrame]; - [newTabButton_ setHidden:NO]; } // Handles setting the title of the tab based on the given |contents|. Uses diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm index ffca1de..5fee1d5 100644 --- a/chrome/browser/cocoa/tab_view.mm +++ b/chrome/browser/cocoa/tab_view.mm @@ -4,6 +4,8 @@ #include "chrome/browser/cocoa/tab_view.h" +#include "chrome/browser/cocoa/tab_window_controller.h" + @implementation TabView - (id)initWithFrame:(NSRect)frame { @@ -38,13 +40,198 @@ // Handle clicks and drags in this button. We get here because we have // overridden acceptsFirstMouse: and the click is within our bounds. +// TODO(pinkerton/alcor): This routine needs *a lot* of work to marry Cole's +// ideas of dragging cocoa views between windows and how the Browser and +// TabStrip models want to manage tabs. - (void)mouseDown:(NSEvent *)theEvent { - // fire the action to select the tab + // Make sure the controller doesn't go away while we're doing this. + // TODO(pinkerton): cole had this, not sure why it's necessary. + [[controller_ retain] autorelease]; + + // Fire the action to select the tab. if ([[controller_ target] respondsToSelector:[controller_ action]]) [[controller_ target] performSelector:[controller_ action] withObject:self]; - // TODO(alcor): handle dragging... + // TODO(pinkerton): necessary to pre-arrange the tabs here? + + // Resolve overlay back to original window. + NSWindow* sourceWindow = [self window]; + if ([sourceWindow isKindOfClass:[NSPanel class]]) { + sourceWindow = [sourceWindow parentWindow]; + } + TabWindowController* sourceController = [sourceWindow windowController]; + TabWindowController* draggedController = nil; + TabWindowController* targetController = nil; + + BOOL isLastTab = NO; // TODO(alcor) + + NSWindow* dragWindow = nil; + NSWindow* dragOverlay = nil; + BOOL dragging = YES; + BOOL moved = NO; + + NSDate* targetDwellDate = nil; // The date this target was first chosen + NSMutableArray* targets = [NSMutableArray array]; + + NSPoint lastPoint = + [[theEvent window] convertBaseToScreen:[theEvent locationInWindow]]; + + while (dragging) { + theEvent = + [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode dequeue:YES]; + NSPoint thisPoint = [NSEvent mouseLocation]; + + // Find all the windows that could be a target. It has to be of the + // appropriate class, and visible (obviously). + if (![targets count]) { + for (NSWindow* window in [NSApp windows]) { + if (window == sourceWindow && isLastTab) continue; + if (window == dragWindow) continue; + if (![window isVisible]) continue; + NSWindowController *controller = [window windowController]; + if ([controller isKindOfClass:[TabWindowController class]]) { + [targets addObject:controller]; + } + } + } + + // Iterate over possible targets checking for the one the mouse is in. + // The mouse can be in either the tab or window frame. + TabWindowController* newTarget = nil; + for (TabWindowController* target in targets) { + NSRect windowFrame = [[target window] frame]; + if (NSPointInRect(thisPoint, windowFrame)) { + if (NSPointInRect(thisPoint, [[target tabStripView] frame])) { + newTarget = target; + } + break; + } + } + + // If we're now targeting a new window, re-layout the tabs in the old + // target and reset how long we've been hovering over this new one. + if (targetController != newTarget) { + targetDwellDate = [NSDate date]; + [targetController arrangeTabs]; + targetController = newTarget; + } + + NSEventType type = [theEvent type]; + if (type == NSLeftMouseDragged) { +#if 0 + // TODO(alcor): get this working... + moved = YES; + if (!draggedController) { + if (isLastTab) { + draggedController = sourceController; + dragWindow = [draggedController window]; + } else { + // Detach from the current window. + // TODO(pinkerton): Create a new window, probably with + // Browser::CreateNewStripWithContents(), but that requires that + // we make some changes to return the new Browser object. + draggedController = [sourceController detachTabToNewWindow:self]; + dragWindow = [draggedController window]; + + // TODO(pinkerton): reconcile how the view moves from one window + // to the other with the TabStrip model wanting to create the tabs. + // [[sourceController tabController] removeTab:tab_]; + // [[sourceController tabController] addTab:tab_]; + [dragWindow setAlphaValue:0.0]; + } + + // Bring the target window to the front and make sure it has a border. + [[draggedController window] setLevel:NSFloatingWindowLevel]; + [dragWindow orderFront:nil]; + [dragWindow makeMainWindow]; + [draggedController showOverlay]; + dragOverlay = [draggedController overlayWindow]; + + if (![targets count]) + [dragOverlay setHasShadow:NO]; + } else { + NSPoint origin = [dragWindow frame].origin; + origin.x += thisPoint.x - lastPoint.x; + origin.y += thisPoint.y - lastPoint.y; + [dragWindow setFrameOrigin:NSMakePoint(origin.x, origin.y)]; + } + + // If we're not hovering over any window, make the window is fully + // opaque. Otherwise, find where the tab might be dropped and insert + // a placeholder so it appears like it's part of that window. + if (!targetContoller) { + [[dragWindow animator] setAlphaValue:1.0]; + } else { + if (![[targetController window] isKeyWindow]) { + // && ([targetDwellDate timeIntervalSinceNow] < -REQUIRED_DWELL)) { + [[targetController window] makeKeyAndOrderFront:nil]; + [targets removeAllObjects]; + targetDwellDate = nil; + } + + // Compute where placeholder should go and insert it into the + // destination tab strip. + NSRect dropTabFrame = [[targetController tabStripView] frame]; + NSPoint point = + [sourceWindow convertBaseToScreen: + [self convertPointToBase:NSZeroPoint]]; + int x = NSWidth([self bounds]) / 2 + point.x - dropTabFrame.origin.x; + [targetController insertPlaceholderForTab:tab_ atLocation:x]; + [targetController arrangeTabs]; + + if (!targetController) + [dragWindow makeKeyAndOrderFront:nil]; + [[dragWindow animator] setAlphaValue:targetController ? 0.0 : 0.333]; + + [[[draggedController overlayWindow] animator] + setAlphaValue:targetController ? 0.85 : 1.0]; + // [setAlphaValue:targetController ? 0.0 : 0.6]; + } +#endif + } else if (type == NSLeftMouseUp) { + // Mouse up, break out of the drag event tracking loop + dragging = NO; + } + lastPoint = thisPoint; + } // while tracking mouse + + // The drag/click is done. If the user dragged the mouse, finalize the drag + // and clean up. + if (moved) { + TabWindowController *dropController = targetController; + if (dropController) { + NSRect adjustedFrame = [self bounds]; + NSRect dropTabFrame = [[dropController tabStripView] frame]; + adjustedFrame.origin = [self convertPointToBase:NSZeroPoint]; + adjustedFrame.origin = + [sourceWindow convertBaseToScreen:adjustedFrame.origin]; + adjustedFrame.origin.x = adjustedFrame.origin.x - dropTabFrame.origin.x; +// adjustedFrame.origin.y = adjustedFrame.origin.y - dropTabFrame.origin.y; +// adjustedFrame.size.height += adjustedFrame.origin.y; + adjustedFrame.origin.y = 0; + + // TODO(alcor): get add tab stuff working + // [dropController addTab:tab_]; + + [self setFrame:adjustedFrame]; + [dropController arrangeTabs]; + [draggedController close]; + [dropController showWindow:nil]; + } else { + [[dragWindow animator] setAlphaValue:1.0]; + [dragOverlay setHasShadow:NO]; + [draggedController removeOverlayAfterDelay: + [[NSAnimationContext currentContext] duration]]; + [dragWindow makeKeyAndOrderFront:nil]; + + [[draggedController window] setLevel:NSNormalWindowLevel]; + [draggedController arrangeTabs]; + } + [sourceController arrangeTabs]; + } } @end diff --git a/chrome/browser/cocoa/tab_window_controller.h b/chrome/browser/cocoa/tab_window_controller.h new file mode 100644 index 0000000..fee790a --- /dev/null +++ b/chrome/browser/cocoa/tab_window_controller.h @@ -0,0 +1,55 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TAB_WINDOW_CONTROLLER_H_ +#define CHROME_BROWSER_TAB_WINDOW_CONTROLLER_H_ + +// A class acting as the Objective-C window controller for a window that has +// tabs which can be dragged around. Tabs can be re-arranged within the same +// window or dragged into other TabWindowController windows. This class doesn't +// know anything about the actual tab implementation or model, as that is fairly +// application-specific. It only provides an API to be overridden by subclasses +// to fill in the details. + +#import <Cocoa/Cocoa.h> + +@class TabStripView; +@class TabView; + +@interface TabWindowController : NSWindowController { + @private + IBOutlet NSBox* contentBox_; + IBOutlet TabStripView* tabStripView_; + NSWindow* overlayWindow_; // used during dragging +} +@property(readonly, nonatomic) TabStripView* tabStripView; + +// Used during tab dragging to turn on/off the overlay window when a tab +// is torn off. +- (void)showOverlay; +- (void)removeOverlay; +- (void)removeOverlayAfterDelay:(NSTimeInterval)delay; + +// A collection of methods, stubbed out in this base class, that provide +// the implementation of tab dragging based on whatever model is most +// appropriate. + +// Layout the tabs based on the current ordering of the model. +- (void)arrangeTabs; + +// Creates a new window by pulling the given tab out and placing it in +// the new window. Returns the controller for the new window. The size of the +// new window will be the same size as this window. +- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView; + +// Make room in the tab strip for |tab| at the given x coordinate. +// TODO(pink): is |tab| a necessary parameter? +- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation; + +// Removes the placeholder installed by |-insertPlaceholderForTab:atLocation:|. +- (void)removePlaceholder; + +@end + +#endif // CHROME_BROWSER_TAB_WINDOW_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/tab_window_controller.mm b/chrome/browser/cocoa/tab_window_controller.mm new file mode 100644 index 0000000..0729c37 --- /dev/null +++ b/chrome/browser/cocoa/tab_window_controller.mm @@ -0,0 +1,100 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/tab_window_controller.h" + +#include "base/logging.h" +#import "chrome/browser/cocoa/tab_strip_view.h" + +@interface TabWindowController(PRIVATE) +- (void)setUseOverlay:(BOOL)useOverlay; +@end + +@implementation TabWindowController +@synthesize tabStripView = tabStripView_; + +- (void)windowDidLoad { + // Place the tab bar above the content box and add it to the view hierarchy + // as a sibling of the content view so it can overlap with the window frame. + NSRect tabFrame = [contentBox_ frame]; + tabFrame.origin = NSMakePoint(0, NSMaxY(tabFrame)); + tabFrame.size.height = NSHeight([tabStripView_ frame]); + [tabStripView_ setFrame:tabFrame]; + [[[[self window] contentView] superview] addSubview:tabStripView_]; +} + +- (void)removeOverlay { + [self setUseOverlay:NO]; +} + +- (void)removeOverlayAfterDelay:(NSTimeInterval)delay { + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(removeOverlay) + object:nil]; + [self performSelector:@selector(removeOverlay) + withObject:nil + afterDelay:delay]; +} + +- (void)showOverlay { + [self setUseOverlay:YES]; +} + +- (void)setUseOverlay:(BOOL)useOverlay { + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(removeOverlay) + object:nil]; + if (useOverlay && !overlayWindow_) { + overlayWindow_ = [[NSPanel alloc] initWithContentRect:[[self window] frame] + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + [overlayWindow_ setTitle:@"overlay"]; + [overlayWindow_ setBackgroundColor:[NSColor clearColor]]; + [overlayWindow_ setOpaque:NO]; + NSView *contentView = [overlayWindow_ contentView]; + [contentView addSubview:[self tabStripView]]; + [contentView addSubview:contentBox_]; + [overlayWindow_ setHasShadow:YES]; + [[self window] addChildWindow:overlayWindow_ ordered:NSWindowAbove]; + [overlayWindow_ orderFront:nil]; + + [[self window] setHasShadow:NO]; + } else if (!useOverlay && overlayWindow_) { + NSResponder *responder = [overlayWindow_ firstResponder]; + [[self window] setHasShadow:YES]; + NSView *contentView = [[self window] contentView]; + [contentView addSubview:contentBox_]; + [[contentView superview] addSubview:[self tabStripView]]; + [[self window] makeFirstResponder:responder]; + [[self window] display]; + [[self window] removeChildWindow:overlayWindow_]; + [overlayWindow_ orderOut:nil]; + [overlayWindow_ release]; + overlayWindow_ = nil; + } +} + +- (void)arrangeTabs { + // subclass must implement + NOTIMPLEMENTED(); +} + +- (TabWindowController*)detachTabToNewWindow:(TabView*)tabView { + // subclass must implement + NOTIMPLEMENTED(); + return NULL; +} + +- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation { + // subclass must implement + NOTIMPLEMENTED(); +} + +- (void)removePlaceholder { + // subclass must implement + NOTIMPLEMENTED(); +} + +@end diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index b3cd984..abf5deb 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -512,6 +512,8 @@ 'browser/cocoa/tab_strip_view.mm', 'browser/cocoa/tab_view.h', 'browser/cocoa/tab_view.mm', + 'browser/cocoa/tab_window_controller.h', + 'browser/cocoa/tab_window_controller.mm', 'browser/cocoa/toolbar_button_cell.h', 'browser/cocoa/toolbar_button_cell.mm', 'browser/cocoa/toolbar_view.h', |