aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/PSMTabBar/PSMTabDragAssistant.m
diff options
context:
space:
mode:
Diffstat (limited to 'Frameworks/PSMTabBar/PSMTabDragAssistant.m')
-rw-r--r--Frameworks/PSMTabBar/PSMTabDragAssistant.m191
1 files changed, 157 insertions, 34 deletions
diff --git a/Frameworks/PSMTabBar/PSMTabDragAssistant.m b/Frameworks/PSMTabBar/PSMTabDragAssistant.m
index 9c9eb2a8..29fa036c 100644
--- a/Frameworks/PSMTabBar/PSMTabDragAssistant.m
+++ b/Frameworks/PSMTabBar/PSMTabDragAssistant.m
@@ -153,6 +153,10 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
- (void)startDraggingCell:(PSMTabBarCell *)cell fromTabBar:(PSMTabBarControl *)control withMouseDownEvent:(NSEvent *)event
{
+
+ // Ensure the window is frontmost
+ [[control window] makeKeyAndOrderFront:self];
+
[self setIsDragging:YES];
[self setSourceTabBar:control];
[self setDestinationTabBar:control];
@@ -161,7 +165,8 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
[self setDraggedCellIndex:[[control cells] indexOfObject:cell]];
NSRect cellFrame = [cell frame];
- // list of widths for animation
+
+ // Generate a list of widths for animation
NSInteger i;
CGFloat cellStepSize = ([control orientation] == PSMTabBarHorizontalOrientation) ? (cellFrame.size.width + 6) : (cellFrame.size.height + 1);
for (i = 0; i < kPSMTabDragAnimationSteps - 1; i++) {
@@ -198,7 +203,7 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] &&
[[control delegate] tabView:[control tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil]) {
_currentTearOffStyle = [control tearOffStyle];
- _draggedTab = [[PSMTabDragWindowController alloc] initWithImage:dragImage styleMask:NSBorderlessWindowMask tearOffStyle:_currentTearOffStyle];
+ _draggedTab = [[PSMTabDragWindowController alloc] initWithImage:dragImage styleMask:NSBorderlessWindowMask tearOffStyle:_currentTearOffStyle initialAlpha:[control usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha];
cellFrame.origin.y -= cellFrame.size.height;
[control dragImage:[[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] autorelease] at:cellFrame.origin offset:offset event:event pasteboard:pboard source:control slideBack:NO];
@@ -211,20 +216,47 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
- (void)draggingEnteredTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc
{
+
+ // Bring the new tab window to the front
+ [[control window] makeKeyAndOrderFront:self];
+
if (_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![self destinationTabBar]) {
[_draggedTab switchImages];
}
+
+ // If this is not the starting drag bar...
+ if ([self sourceTabBar] != [self destinationTabBar] && control != [self destinationTabBar]) {
+
+ // Add a single placeholder to the tab bar and tell the new tab bar to update.
+ // The placeholder is later removed by distributePlaceholdersInTabBar:.
+ PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control] autorelease];
+ [[control cells] addObject:pc];
+ [control update:NO];
+
+ // Deselect any currently selected tabs after the update
+ for (PSMTabBarCell *aCell in [control cells]) {
+ if ([aCell tabState] & PSMTab_SelectedMask) {
+ [aCell setState:NSOffState];
+ [aCell setTabState:PSMTab_PositionMiddleMask];
+ break;
+ }
+ }
+ }
[self setDestinationTabBar:control];
[self setCurrentMouseLoc:mouseLoc];
- // hide UI buttons
- [[control overflowPopUpButton] setHidden:YES];
- [[control addTabButton] setHidden:YES];
+
+ [_participatingTabBars addObject:control];
+
+ // Add placeholders if necessary
if ([[control cells] count] == 0 || ![[[control cells] objectAtIndex:0] isPlaceholder]) {
[self distributePlaceholdersInTabBar:control];
}
- [_participatingTabBars addObject:control];
+ // hide UI buttons
+ [[control overflowPopUpButton] setHidden:YES];
+ [[control addTabButton] setHidden:YES];
+
//tell the drag window to display only the header if there is one
if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow && _draggedView) {
if (_fadeTimer) {
@@ -264,8 +296,13 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
NSUInteger styleMask;
NSImage *viewImage = [self _imageForViewOfCell:[self draggedCell] styleMask:&styleMask];
- _draggedView = [[PSMTabDragWindowController alloc] initWithImage:viewImage styleMask:styleMask tearOffStyle:PSMTabBarTearOffAlphaWindow];
+ _draggedView = [[PSMTabDragWindowController alloc] initWithImage:viewImage styleMask:styleMask tearOffStyle:PSMTabBarTearOffAlphaWindow initialAlpha:[control usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha];
[[_draggedView window] setAlphaValue:0.0];
+
+ // Inform the delegate a new drag window was created to allow any changes
+ if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabViewDragWindowCreated:)]) {
+ [[control delegate] tabViewDragWindowCreated:[_draggedView window]];
+ }
}
NSPoint windowOrigin = [[control window] frame].origin;
@@ -303,7 +340,7 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
[[[self sourceTabBar] window] setAlphaValue:0.0];
if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) {
- [[_draggedView window] setAlphaValue:kPSMTabDragWindowAlpha];
+ [[_draggedView window] setAlphaValue:kPSMTabDragWindowAlpha];
} else {
#warning fix me - what should we do when the last tab is dragged as a miniwindow?
}
@@ -333,6 +370,7 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
// move actual NSTabViewItem
if ([self sourceTabBar] != [self destinationTabBar]) {
+
//remove the tracking rects and bindings registered on the old tab
[[self sourceTabBar] removeTrackingRect:[[self draggedCell] closeButtonTrackingTag]];
[[self sourceTabBar] removeTrackingRect:[[self draggedCell] cellTrackingTag]];
@@ -404,12 +442,22 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
{
if ([self isDragging]) { // means there was not a successful drop (performDragOperation)
id sourceDelegate = [[self sourceTabBar] delegate];
-
- //split off the dragged tab into a new window
- if ([self destinationTabBar] == nil &&
- sourceDelegate && [sourceDelegate respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] &&
- [sourceDelegate tabView:[[self sourceTabBar] tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil] &&
- [sourceDelegate respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) {
+
+ // Extract the menu bar rect
+ NSScreen *menuBarScreen = [[NSScreen screens] objectAtIndex:0];
+ NSRect menuBarRect = [menuBarScreen frame];
+ menuBarRect.origin.y = menuBarRect.size.height;
+ menuBarRect.size.height = 22;
+
+ // Split off the dragged tab into a new window.
+ // Do this if there's no destination tab bar, the delegate approves it, and the delegate supports it - and
+ // not if the drag ended in the menu bar (which acts as a cancel)
+ if ([self destinationTabBar] == nil
+ && sourceDelegate && [sourceDelegate respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] &&
+ [sourceDelegate tabView:[[self sourceTabBar] tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil]
+ && [sourceDelegate respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]
+ && !NSPointInRect(aPoint, menuBarRect))
+ {
PSMTabBarControl *control = [sourceDelegate tabView:[[self sourceTabBar] tabView] newTabBarForDraggedTabViewItem:[[self draggedCell] representedObject] atPoint:aPoint];
if (control) {
@@ -432,7 +480,11 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
[control update:NO]; //make sure the new tab is set in the correct position
if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) {
+
+ // Grab the window frame, and show - which moves it fully onto screen - before restoring
+ NSRect draggedWindowFrame = [[control window] frame];
[[control window] makeKeyAndOrderFront:nil];
+ [[control window] setFrame:draggedWindowFrame display:YES];
} else {
//center the window over where we ended dragging
[self _expandWindow:[control window] atPoint:[NSEvent mouseLocation]];
@@ -447,8 +499,15 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
}
} else {
+
// put cell back
[[[self sourceTabBar] cells] insertObject:[self draggedCell] atIndex:[self draggedCellIndex]];
+ [[[self sourceTabBar] window] makeKeyAndOrderFront:self];
+
+ // Restore the window alpha if appropriate
+ if ([[[self sourceTabBar] tabView] numberOfTabViewItems]) {
+ [[[self sourceTabBar] window] setAlphaValue:1.0];
+ }
}
[[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidEndNotification object:nil];
@@ -477,21 +536,24 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
_centersDragWindows = NO;
- [self setIsDragging:NO];
+ [_animationTimer invalidate];
+ _animationTimer = nil;
+
[self removeAllPlaceholdersFromTabBar:[self sourceTabBar]];
[self setSourceTabBar:nil];
[self setDestinationTabBar:nil];
+
NSEnumerator *e = [_participatingTabBars objectEnumerator];
PSMTabBarControl *tabBar;
while ( (tabBar = [e nextObject]) ) {
[self removeAllPlaceholdersFromTabBar:tabBar];
}
[_participatingTabBars removeAllObjects];
- [self setDraggedCell:nil];
- [_animationTimer invalidate];
- _animationTimer = nil;
+
+ [self setDraggedCell:nil];
[_sineCurveWidths removeAllObjects];
[self setTargetCell:nil];
+ [self setIsDragging:NO];
}
- (void)draggingBeganAt:(NSPoint)aPoint
@@ -522,6 +584,22 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
frame.origin.y -= frame.size.height / 2;
[[_draggedTab window] setFrame:frame display:NO];
} else {
+
+ // If there is a destination tab bar set to snapping, snap the tab to it.
+ if ([self destinationTabBar]
+ && [[self destinationTabBar] usesSafariStyleDragging]
+ && [[self destinationTabBar] orientation] == PSMTabBarHorizontalOrientation)
+ {
+ NSRect windowFrame = [[[self destinationTabBar] window] frame];
+ NSPoint dragPointInWindow = [[self destinationTabBar] convertPoint:aPoint fromView:nil];
+
+ // Vertical snapping
+ aPoint.y += windowFrame.origin.y + dragPointInWindow.y;
+
+ // Horizontal constraining/snapping
+ if (dragPointInWindow.x - windowFrame.origin.x < 0) aPoint.x = windowFrame.origin.x;
+ if (dragPointInWindow.x - windowFrame.origin.x + [[_draggedTab window] frame].size.width > windowFrame.size.width) aPoint.x = windowFrame.origin.x + windowFrame.size.width - [[_draggedTab window] frame].size.width;
+ }
[[_draggedTab window] setFrameTopLeftPoint:aPoint];
}
@@ -554,15 +632,16 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
{
CGFloat value = [[_draggedView window] alphaValue];
NSWindow *tabWindow = [_draggedTab window], *viewWindow = [_draggedView window];
+ float tabWindowAlphaValue = [[self destinationTabBar] usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha;
if (value <= 0.0) {
[viewWindow setAlphaValue:0.0];
- [tabWindow setAlphaValue:kPSMTabDragWindowAlpha];
+ [tabWindow setAlphaValue:tabWindowAlphaValue];
[timer invalidate];
_fadeTimer = nil;
} else {
- if ([tabWindow alphaValue] < kPSMTabDragWindowAlpha) {
+ if ([tabWindow alphaValue] < tabWindowAlphaValue) {
[tabWindow setAlphaValue:[tabWindow alphaValue] + kPSMTabDragAlphaInterval];
}
[viewWindow setAlphaValue:value - kPSMTabDragAlphaInterval];
@@ -693,33 +772,76 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
NSMutableArray *cells = [control cells];
NSInteger i, cellCount = [cells count];
CGFloat position = [control orientation] == PSMTabBarHorizontalOrientation ? [[control style] leftMarginForTabBarControl] : [[control style] topMarginForTabBarControl];
-
- // identify target cell
- // mouse at beginning of tabs
- NSPoint mouseLoc = [self currentMouseLoc];
+
if ([self destinationTabBar] == control) {
removeFlag = NO;
- if (mouseLoc.x < [[control style] leftMarginForTabBarControl]) {
+
+ // Determine the location of the point to use.
+ NSPoint targetPoint;
+ if ([control usesSafariStyleDragging]) {
+ NSRect draggedTabWindowFrame = [[_draggedTab window] contentRectForFrameRect:[[_draggedTab window] frame]];
+ NSRect controlWindowFrame = [[control window] contentRectForFrameRect:[[control window] frame]];
+ NSPoint tabTopLeftInWindowCoords = NSMakePoint(draggedTabWindowFrame.origin.x - controlWindowFrame.origin.x, controlWindowFrame.origin.y + (2*controlWindowFrame.size.height) - draggedTabWindowFrame.origin.y);
+ targetPoint = [control convertPoint:tabTopLeftInWindowCoords fromView:nil];
+ targetPoint.x += (draggedTabWindowFrame.size.width / 2.0);
+ targetPoint.y = 0 - (draggedTabWindowFrame.size.height / 2.0) - targetPoint.y;
+ } else {
+ targetPoint = [self currentMouseLoc];
+ }
+
+ if (targetPoint.x < [[control style] leftMarginForTabBarControl]) {
[self setTargetCell:[cells objectAtIndex:0]];
} else {
+
+ // Identify which cell the mouse is over
NSRect overCellRect;
- PSMTabBarCell *overCell = [control cellForPoint:mouseLoc cellFrame:&overCellRect];
+ PSMTabBarCell *overCell = [control cellForPoint:targetPoint cellFrame:&overCellRect];
if (overCell) {
- // mouse among cells - placeholder
+
+ // Mouse is among cells - placeholder
if ([overCell isPlaceholder]) {
[self setTargetCell:overCell];
+
+ // Non-placeholder cells - horizontal orientation
} else if ([control orientation] == PSMTabBarHorizontalOrientation) {
- // non-placeholders - horizontal orientation
- if (mouseLoc.x < (overCellRect.origin.x + (overCellRect.size.width / 2.0))) {
- // mouse on left side of cell
- [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]];
+
+ // Handle Safari-style dragging
+ if ([control usesSafariStyleDragging]) {
+
+ // Determine the index of the tab the dragged tab is over
+ NSUInteger overCellIndex = [cells indexOfObject:overCell];
+
+ // Ensure that drag changes aren't as a result of an animation
+ NSInteger currentCellStep = [[cells objectAtIndex:(overCellIndex - 1)] currentStep];
+ if (!currentCellStep || currentCellStep == kPSMTabDragAnimationSteps - 1) {
+
+ // Center of the tab is past the edge of the tab to the left
+ if (targetPoint.x < (overCellRect.origin.x + overCellRect.size.width)
+ && targetPoint.x > (overCellRect.origin.x + overCellRect.size.width/2.0))
+ {
+ [self setTargetCell:[cells objectAtIndex:(overCellIndex - 1)]];
+
+ // Center of the tab is past the edge of the tab to the right
+ } else if (targetPoint.x > overCellRect.origin.x) {
+ [self setTargetCell:[cells objectAtIndex:(overCellIndex + 1)]];
+ }
+ }
+
+ // Handle old-style dragging based on mouse position
} else {
- // mouse on right side of cell
- [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] + 1)]];
+
+ // Mouse is over the left side of the cell
+ if (targetPoint.x < (overCellRect.origin.x + (overCellRect.size.width / 2.0))) {
+ [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]];
+
+ // Otherwise the mouse is over the right side of the cell
+ } else {
+ [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] + 1)]];
+ }
}
} else {
// non-placeholders - vertical orientation
- if (mouseLoc.y < (overCellRect.origin.y + (overCellRect.size.height / 2.0))) {
+ if (targetPoint.y < (overCellRect.origin.y + (overCellRect.size.height / 2.0))) {
// mouse on top of cell
[self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]];
} else {
@@ -823,6 +945,7 @@ static PSMTabDragAssistant *sharedDragAssistant = nil;
for (i = (cellCount - 1); i >= 0; i--) {
PSMTabBarCell *cell = [[control cells] objectAtIndex:i];
if ([cell isPlaceholder]) {
+ [NSObject cancelPreviousPerformRequestsWithTarget:cell];
[control removeTabForCell:cell];
}
}