summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-19 19:11:25 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-19 19:11:25 +0000
commitc0e5501cc6e6259381211007e5fc5f3950fc4fab (patch)
tree8b2ae9f6aee6af45c29c0f6543c5673c18f766e1 /chrome
parent63c85eee887a619b61fe4454b579237fdcaf25b9 (diff)
downloadchromium_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.xib2
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h13
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm29
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm1
-rw-r--r--chrome/browser/cocoa/tab_view.mm191
-rw-r--r--chrome/browser/cocoa/tab_window_controller.h55
-rw-r--r--chrome/browser/cocoa/tab_window_controller.mm100
-rw-r--r--chrome/chrome.gyp2
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',