diff options
Diffstat (limited to 'Frameworks')
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabBarCell.m | 38 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabBarControl.h | 5 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabBarControl.m | 35 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabBarController.m | 13 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabDragAssistant.h | 2 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabDragAssistant.m | 191 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabDragWindow.m | 1 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabDragWindowController.h | 2 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/PSMTabDragWindowController.m | 4 | ||||
-rw-r--r-- | Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m | 242 |
10 files changed, 380 insertions, 153 deletions
diff --git a/Frameworks/PSMTabBar/PSMTabBarCell.m b/Frameworks/PSMTabBar/PSMTabBarCell.m index d35f68ee..7ecaa183 100644 --- a/Frameworks/PSMTabBar/PSMTabBarCell.m +++ b/Frameworks/PSMTabBar/PSMTabBarCell.m @@ -347,8 +347,10 @@ - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { if (_isPlaceholder) { - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; - NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); + if (![_controlView usesSafariStyleDragging]) { + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; + NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); + } return; } @@ -400,25 +402,31 @@ { NSRect cellFrame = [(id <PSMTabStyle>)[(PSMTabBarControl *)_controlView style] dragRectForTabCell:self orientation:(PSMTabBarOrientation)[(PSMTabBarControl *)_controlView orientation]]; //NSRect cellFrame = [self frame]; - - [_controlView lockFocus]; - NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:cellFrame] autorelease]; - [_controlView unlockFocus]; - NSImage *image = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; - [image addRepresentation:rep]; - NSImage *returnImage = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; - [returnImage lockFocus]; - [image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeSourceOver fraction:1.0]; - [returnImage unlockFocus]; + + // Determine the target coordinates to draw into + NSRect oldFrame = [self frame]; + NSRect tabDrawFrame = oldFrame; + tabDrawFrame.origin.x -= cellFrame.origin.x; + + // Draw the tab into a new image + NSImage *image = [[[NSImage alloc] initWithSize:cellFrame.size] autorelease]; + [image lockFocusFlipped:YES]; + [self setFrame:tabDrawFrame]; + [(id <PSMTabStyle>)[(PSMTabBarControl *)_controlView style] drawTabCell:self]; + [self setFrame:oldFrame]; + [image unlockFocus]; + + // Add the indicator if appropriate if (![[self indicator] isHidden]) { NSImage *pi = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"pi"]]; - [returnImage lockFocus]; + [image lockFocus]; NSPoint indicatorPoint = NSMakePoint([self frame].size.width - MARGIN_X - kPSMTabBarIndicatorWidth, MARGIN_Y); [pi compositeToPoint:indicatorPoint operation:NSCompositeSourceOver fraction:1.0]; - [returnImage unlockFocus]; + [image unlockFocus]; [pi release]; } - return returnImage; + + return image; } #pragma mark - diff --git a/Frameworks/PSMTabBar/PSMTabBarControl.h b/Frameworks/PSMTabBar/PSMTabBarControl.h index c61b92f4..fdfc8f31 100644 --- a/Frameworks/PSMTabBar/PSMTabBarControl.h +++ b/Frameworks/PSMTabBar/PSMTabBarControl.h @@ -79,6 +79,7 @@ enum { BOOL _useOverflowMenu; BOOL _alwaysShowActiveTab; BOOL _allowsScrubbing; + BOOL _useSafariStyleDragging; NSInteger _resizeAreaCompensation; PSMTabBarOrientation _orientation; BOOL _automaticallyAnimates; @@ -157,6 +158,8 @@ enum { - (void)setAlwaysShowActiveTab:(BOOL)value; - (BOOL)allowsScrubbing; - (void)setAllowsScrubbing:(BOOL)value; +- (BOOL)usesSafariStyleDragging; +- (void)setUsesSafariStyleDragging:(BOOL)value; - (PSMTabBarTearOffStyle)tearOffStyle; - (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; @@ -207,7 +210,7 @@ enum { - (BOOL)tabView:(NSTabView *)aTabView shouldDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl; - (BOOL)tabView:(NSTabView *)aTabView shouldAllowTabViewItem:(NSTabViewItem *)tabViewItem toLeaveTabBar:(PSMTabBarControl *)tabBarControl; - (void)tabView:(NSTabView*)aTabView didDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl; - +- (void)draggingEvent:(id <NSDraggingInfo>)dragEvent enteredTabBar:(PSMTabBarControl *)tabBarControl tabView:(NSTabViewItem *)tabViewItem; //Tear-off tabs methods - (NSImage *)tabView:(NSTabView *)aTabView imageForTabViewItem:(NSTabViewItem *)tabViewItem offset:(NSSize *)offset styleMask:(NSUInteger *)styleMask; diff --git a/Frameworks/PSMTabBar/PSMTabBarControl.m b/Frameworks/PSMTabBar/PSMTabBarControl.m index d361364e..6753bc08 100644 --- a/Frameworks/PSMTabBar/PSMTabBarControl.m +++ b/Frameworks/PSMTabBar/PSMTabBarControl.m @@ -137,6 +137,7 @@ _selectsTabsOnMouseDown = NO; _alwaysShowActiveTab = NO; _allowsScrubbing = NO; + _useSafariStyleDragging = NO; _cellMinWidth = 100; _cellMaxWidth = 280; _cellOptimumWidth = 130; @@ -594,6 +595,16 @@ _allowsScrubbing = value; } +- (BOOL)usesSafariStyleDragging +{ + return _useSafariStyleDragging; +} + +- (void)setUsesSafariStyleDragging:(BOOL)value +{ + _useSafariStyleDragging = value; +} + - (PSMTabBarTearOffStyle)tearOffStyle { return _tearOffStyle; @@ -1002,8 +1013,9 @@ - (void)update:(BOOL)animate { - // make sure all of our tabs are accounted for before updating - if ([[self tabView] numberOfTabViewItems] != [_cells count]) { + // make sure all of our tabs are accounted for before updating, + // or only proceed if a drag is in progress (where counts may mismatch) + if ([[self tabView] numberOfTabViewItems] != [_cells count] && ![[PSMTabDragAssistant sharedDragAssistant] isDragging]) { return; } @@ -1163,11 +1175,18 @@ - (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell { + + // Skip tracking rects for placeholders - not required. + if ([cell isPlaceholder]) return; + NSInteger tag, index = [_cells indexOfObject:cell]; NSRect cellTrackingRect = [_controller cellTrackingRectAtIndex:index]; NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; BOOL mouseInCell = NSMouseInRect(mousePoint, cellTrackingRect, [self isFlipped]); - + + // If dragging, suppress mouse interaction + if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) mouseInCell = NO; + //set the cell tracking rect [self removeTrackingRect:[cell cellTrackingTag]]; tag = [self addTrackingRect:cellTrackingRect owner:cell userData:nil assumeInside:mouseInCell]; @@ -1496,10 +1515,12 @@ userInfo:sender repeats:NO] retain]; } - //If user drags a text string to a tab switch to Custom Query Editor - if (![[[cell representedObject] identifier] isCustomQuerySelected] - && [[[sender draggingPasteboard] types] indexOfObject:NSStringPboardType] != NSNotFound) { - [[[cell representedObject] identifier] performSelector:@selector(viewQuery:) withObject:nil]; + + // Notify the delegate to respond to drag events if supported. This allows custom + // behaviour when dragging certain drag types onto the tab - for example changing the + // view appropriately. + if ([self delegate] && [[self delegate] respondsToSelector:@selector(draggingEvent:enteredTabBar:tabView:)]) { + [[self delegate] draggingEvent:sender enteredTabBar:self tabView:[cell representedObject]]; } } return NSDragOperationCopy; diff --git a/Frameworks/PSMTabBar/PSMTabBarController.m b/Frameworks/PSMTabBar/PSMTabBarController.m index 76f3a91b..62e7a818 100644 --- a/Frameworks/PSMTabBar/PSMTabBarController.m +++ b/Frameworks/PSMTabBar/PSMTabBarController.m @@ -11,6 +11,7 @@ #import "PSMTabBarCell.h" #import "PSMTabStyle.h" #import "NSString_AITruncation.h" +#import "PSMTabDragAssistant.h" #define MAX_OVERFLOW_MENUITEM_TITLE_LENGTH 60 @@ -194,11 +195,13 @@ NSArray *cells = [_control cells]; NSInteger cellCount = [cells count]; - // make sure all of our tabs are accounted for before updating - if ([[_control tabView] numberOfTabViewItems] != cellCount) { + // make sure all of our tabs are accounted for before updating, + // or only proceed if a drag is in progress (where counts may mismatch) + if ([[_control tabView] numberOfTabViewItems] != cellCount && ![[PSMTabDragAssistant sharedDragAssistant] isDragging]) { return; } + // [_cellTrackingRects removeAllObjects]; [_closeButtonTrackingRects removeAllObjects]; [_cellFrames removeAllObjects]; @@ -211,7 +214,7 @@ _addButtonRect.size = [[_control addTabButton] frame].size; if ([_control orientation] == PSMTabBarHorizontalOrientation) { _addButtonRect.origin.y = MARGIN_Y; - _addButtonRect.origin.x += [[cellWidths valueForKeyPath:@"@sum.floatValue"] doubleValue] + 2; + _addButtonRect.origin.x += [[cellWidths valueForKeyPath:@"@sum.floatValue"] doubleValue] + MARGIN_X; } else { _addButtonRect.origin.x = 0; _addButtonRect.origin.y = [[cellWidths lastObject] doubleValue]; @@ -326,8 +329,10 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) width = [_control cellOptimumWidth]; } - width = ceil(width); + //if ([currentCell isPlaceholder]) width = 1; + width = ceil(width); + //check to see if there is not enough space to place all tabs as preferred if (totalOccupiedWidth + width >= availableWidth) { //There's not enough space to add currentCell at its preferred width! diff --git a/Frameworks/PSMTabBar/PSMTabDragAssistant.h b/Frameworks/PSMTabBar/PSMTabDragAssistant.h index 07703b7d..2f42c573 100644 --- a/Frameworks/PSMTabBar/PSMTabDragAssistant.h +++ b/Frameworks/PSMTabBar/PSMTabDragAssistant.h @@ -22,7 +22,7 @@ PSMTabBarControl *_destinationTabBar; NSMutableSet *_participatingTabBars; PSMTabBarCell *_draggedCell; - NSInteger _draggedCellIndex; // for snap back + NSInteger _draggedCellIndex; // for snap back BOOL _isDragging; // Support for dragging into new windows 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]; } } diff --git a/Frameworks/PSMTabBar/PSMTabDragWindow.m b/Frameworks/PSMTabBar/PSMTabDragWindow.m index 0d07c432..7a6d6bc6 100644 --- a/Frameworks/PSMTabBar/PSMTabDragWindow.m +++ b/Frameworks/PSMTabBar/PSMTabDragWindow.m @@ -26,6 +26,7 @@ [self setLevel:NSStatusWindowLevel]; [self setIgnoresMouseEvents:YES]; [self setOpaque:NO]; + [self setBackgroundColor:[NSColor clearColor]]; [_dragView setImage:image]; diff --git a/Frameworks/PSMTabBar/PSMTabDragWindowController.h b/Frameworks/PSMTabBar/PSMTabDragWindowController.h index 1727d8b8..babfb1a7 100644 --- a/Frameworks/PSMTabBar/PSMTabDragWindowController.h +++ b/Frameworks/PSMTabBar/PSMTabDragWindowController.h @@ -23,7 +23,7 @@ BOOL _showingAlternate; NSRect _originalWindowFrame; } -- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; +- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle initialAlpha:(CGFloat)initialAlpha; - (NSImage *)image; - (NSImage *)alternateImage; diff --git a/Frameworks/PSMTabBar/PSMTabDragWindowController.m b/Frameworks/PSMTabBar/PSMTabDragWindowController.m index 018bca17..43340786 100644 --- a/Frameworks/PSMTabBar/PSMTabDragWindowController.m +++ b/Frameworks/PSMTabBar/PSMTabDragWindowController.m @@ -12,7 +12,7 @@ @implementation PSMTabDragWindowController -- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle +- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle initialAlpha:(CGFloat)initialAlpha { PSMTabDragWindow *window = [PSMTabDragWindow dragWindowWithImage:image styleMask:styleMask]; if ( (self = [super initWithWindow:window]) ) { @@ -24,7 +24,7 @@ [window setHasShadow:YES]; } - [window setAlphaValue:kPSMTabDragWindowAlpha]; + [window setAlphaValue:initialAlpha]; } return self; } diff --git a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m index 70ceb943..e33aeff8 100644 --- a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m +++ b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m @@ -26,6 +26,7 @@ #import "PSMTabBarCell.h" #import "PSMTabBarControl.h" #import "NSBezierPath_AMShading.h" +#import "PSMTabDragAssistant.h" #define kPSMSequelProObjectCounterRadius 7.0 #define kPSMSequelProCounterMinWidth 20 @@ -133,7 +134,8 @@ if ([cell tabState] & PSMTab_SelectedMask) { if (tabOrientation == PSMTabBarHorizontalOrientation) { - dragRect.size.height -= 2.0; + dragRect.origin.x -= 5.0; + dragRect.size.width += 10.0; } else { dragRect.size.height += 1.0; dragRect.origin.y -= 1.0; @@ -345,7 +347,7 @@ } #pragma mark - -#pragma mark ---- drawing ---- +#pragma mark Drawing // Step 1 - (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect @@ -449,82 +451,143 @@ { NSRect cellFrame = [cell frame]; NSColor *lineColor = nil; + NSColor *fillColor = nil; + NSColor *shadowColor = nil; NSBezierPath *outlineBezier = [NSBezierPath bezierPath]; NSBezierPath *fillBezier = [NSBezierPath bezierPath]; NSPoint center = NSZeroPoint; - BOOL tabBarIsRightOfSelectedTab = NO; - - // Determine if the selected tab is right of this tab - for (PSMTabBarCell *aCell in [tabBar cells]) { - if (aCell == cell) break; - if ([aCell state] == NSOnState) { - tabBarIsRightOfSelectedTab = YES; - break; + NSPoint topLeftArcCenter, bottomLeftArcCenter, topRightArcCenter, bottomRightArcCenter; + BOOL drawRightEdge = YES; + BOOL drawLeftEdge = YES; + + // For cells in the off state, determine whether to draw the edges. + if ([cell state] == NSOffState) { + NSUInteger selectedCellIndex = NSUIntegerMax; + NSUInteger drawingCellIndex = NSUIntegerMax; + NSUInteger firstOverflowedCellIndex = NSUIntegerMax; + + NSUInteger currentIndex = 0; + for (PSMTabBarCell *aCell in [tabBar cells]) { + if (aCell == cell) drawingCellIndex = currentIndex; + if ([aCell state] == NSOnState || ([aCell isPlaceholder] && [aCell currentStep] > 1)) { + selectedCellIndex = currentIndex; + } + if ([aCell isInOverflowMenu]) { + firstOverflowedCellIndex = currentIndex; + break; + } + currentIndex++; + } + + // Draw the left edge if the cell is to the left of the active tab, or if the preceding cell is + // being dragged, and not for the very first cell. + if ((!drawingCellIndex || (drawingCellIndex == 1 && [[[tabBar cells] objectAtIndex:0] isPlaceholder])) + || (drawingCellIndex > selectedCellIndex + && (drawingCellIndex != selectedCellIndex + 1 || ![[[tabBar cells] objectAtIndex:selectedCellIndex] isPlaceholder]))) + { + drawLeftEdge = NO; + } + + // Draw the right edge for tabs to the right, the last tab in the bar, and where the following + // cell is being dragged. + if (drawingCellIndex < selectedCellIndex + && drawingCellIndex != firstOverflowedCellIndex - 1 + && (drawingCellIndex >= selectedCellIndex + 1 || ![[[tabBar cells] objectAtIndex:selectedCellIndex] isPlaceholder])) + { + drawRightEdge = NO; } } - + + // Set up colours if ([[tabBar window] isKeyWindow]) { lineColor = [NSColor darkGrayColor]; + if ([cell state] == NSOnState) { + fillColor = [NSColor colorWithCalibratedWhite:0.59 alpha:1.0]; + shadowColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.7]; + } else { + fillColor = [NSColor colorWithCalibratedWhite:0.495 alpha:1.0]; + shadowColor = [NSColor colorWithCalibratedWhite:0.0 alpha:1.0]; + } } else { lineColor = [NSColor colorWithCalibratedWhite:0.49 alpha:1.0]; + if ([cell state] == NSOnState) { + fillColor = [NSColor colorWithCalibratedWhite:0.81 alpha:1.0]; + shadowColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.4]; + } else { + fillColor = [NSColor colorWithCalibratedWhite:0.685 alpha:1.0]; + shadowColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.7]; + } } - //disable antialiasing of bezier paths [NSGraphicsContext saveGraphicsState]; - [[NSGraphicsContext currentContext] setShouldAntialias:YES]; - NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height); - // selected tab - if ([cell state] == NSOnState) { + // If the tab bar is hidden, don't draw the top pixel + if ([tabBar isTabBarHidden]) { + aRect.origin.y++; + aRect.size.height--; + } - // draw top left arc - center = NSMakePoint(aRect.origin.x - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:270 endAngle:360 clockwise:NO]; - - // draw bottom left arc - center = NSMakePoint(aRect.origin.x + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + // Set up the corner bezier paths arc centers + topLeftArcCenter = NSMakePoint(aRect.origin.x - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); + topRightArcCenter = NSMakePoint(aRect.origin.x + aRect.size.width + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); + bottomLeftArcCenter = NSMakePoint(aRect.origin.x + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius); + bottomRightArcCenter = NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius ); - // draw bottom right arc - center = NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius ); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; - - // draw top right arc - center = NSMakePoint(aRect.origin.x + aRect.size.width + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:270 clockwise:NO]; + // Construct the outline path + if (drawLeftEdge) { + [outlineBezier appendBezierPathWithArcWithCenter:topLeftArcCenter radius:kPSMSequelProTabCornerRadius startAngle:270 endAngle:360 clockwise:NO]; + [outlineBezier appendBezierPathWithArcWithCenter:bottomLeftArcCenter radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + } + if (drawRightEdge) { + [outlineBezier appendBezierPathWithArcWithCenter:bottomRightArcCenter radius:kPSMSequelProTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; + [outlineBezier appendBezierPathWithArcWithCenter:topRightArcCenter radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:270 clockwise:NO]; + } - // Set up a fill bezier with the pieced-together path - [fillBezier appendBezierPath:outlineBezier]; + // Set up a fill bezier based on the outline path + [fillBezier appendBezierPath:outlineBezier]; - // Set the tab outer shadow and draw the shadow - [NSGraphicsContext saveGraphicsState]; - NSShadow *shadow = [[NSShadow alloc] init]; - [shadow setShadowBlurRadius:4]; - [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.0 alpha:[[tabBar window] isKeyWindow]?0.7:0.4]]; - [shadow setShadowOffset:NSMakeSize(0, 0)]; - [shadow set]; - [outlineBezier stroke]; - [shadow release]; - [NSGraphicsContext restoreGraphicsState]; + // If one edge is missing, apply a local fill to the other edge + if (drawRightEdge && !drawLeftEdge) { + [fillBezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y)]; + [fillBezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height)]; + } else if (!drawRightEdge && drawLeftEdge) { + [fillBezier lineToPoint:NSMakePoint(aRect.origin.x + 0.5 + kPSMSequelProTabCornerRadius, aRect.origin.y)]; + } - // Fill the tab with a solid colour - if ([[tabBar window] isKeyWindow]) { - [[NSColor colorWithCalibratedWhite:0.59 alpha:1.0] set]; - } else { - [[NSColor colorWithCalibratedWhite:0.81 alpha:1.0] set]; - } - [fillBezier fill]; + // Set the tab outer shadow and draw the shadow + [NSGraphicsContext saveGraphicsState]; + NSShadow *shadow = [[NSShadow alloc] init]; + [shadow setShadowBlurRadius:4]; + [shadow setShadowColor:shadowColor]; + [shadow setShadowOffset:NSMakeSize(0, 0)]; + [shadow set]; + [outlineBezier stroke]; + [shadow release]; + [NSGraphicsContext restoreGraphicsState]; - // Re-stroke without shadow over the fill. - [lineColor set]; - [outlineBezier stroke]; + // Fill the tab with a solid colour + [fillColor set]; + [fillBezier fill]; - // Add a bottom line to the tab, with a slight inner glow + // Re-stroke without shadow over the fill. + [lineColor set]; + [outlineBezier stroke]; + + // Add a bottom line to the active tab, with a slight inner glow + if ([cell state] == NSOnState) { outlineBezier = [NSBezierPath bezierPath]; - [outlineBezier moveToPoint:NSMakePoint(aRect.origin.x + (2 * kPSMSequelProTabCornerRadius), aRect.origin.y + aRect.size.height - 0.5)]; - [outlineBezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width - (2 * kPSMSequelProTabCornerRadius), aRect.origin.y + aRect.size.height - 0.5)]; + if (drawLeftEdge) { + [outlineBezier appendBezierPathWithArcWithCenter:bottomLeftArcCenter radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + } else { + [outlineBezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y + aRect.size.height - 0.5)]; + } + if (drawRightEdge) { + [outlineBezier appendBezierPathWithArcWithCenter:bottomRightArcCenter radius:kPSMSequelProTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; + } else { + [outlineBezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + aRect.size.height - 0.5)]; + } shadow = [[NSShadow alloc] init]; [shadow setShadowBlurRadius:1]; [shadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.3]]; @@ -532,42 +595,45 @@ [shadow set]; [outlineBezier stroke]; - // unselected tab - } else { - - // rollover -// if ([cell isHighlighted]) { -// [[NSColor colorWithCalibratedWhite:1.0 alpha:0.1] set]; -// NSRectFillUsingOperation(aRect, NSCompositeSourceAtop); -// } - - if (tabBarIsRightOfSelectedTab) { - //lineColor = [NSColor greenColor]; - - // draw bottom right arc - center = NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; - - // draw top right arc - center = NSMakePoint(aRect.origin.x + aRect.size.width + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:270 clockwise:NO]; - - // Don't draw the left edge for the leftmost tab - } else if ([[tabBar cells] objectAtIndex:0] != cell) { - //lineColor = [NSColor redColor]; - - // draw top left arc - center = NSMakePoint(aRect.origin.x - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:270 endAngle:360 clockwise:NO]; - - // draw bottom left arc - center = NSMakePoint(aRect.origin.x + kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + aRect.size.height - kPSMSequelProTabCornerRadius); - [outlineBezier appendBezierPathWithArcWithCenter:center radius:kPSMSequelProTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + // Add the shadow over the tops of background tabs + } else if (drawLeftEdge || drawRightEdge) { + + // Set up a CGContext so that drawing can be clipped (to prevent shadow issues) + CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(context); + NSPoint topLeft, topRight; + CGFloat drawAlpha = [[tabBar window] isKeyWindow] ? 1.0 : 0.7; + outlineBezier = [NSBezierPath bezierPath]; + + // Calculate the endpoints of the line + if (drawLeftEdge) { + topLeft = NSMakePoint(aRect.origin.x + 0.5 - kPSMSequelProTabCornerRadius + 2, aRect.origin.y + 0.5); + } else { + topLeft = NSMakePoint(aRect.origin.x + aRect.size.width - kPSMSequelProTabCornerRadius + 0.5, aRect.origin.y + 0.5); + } + if (drawRightEdge) { + topRight = NSMakePoint(aRect.origin.x + aRect.size.width + kPSMSequelProTabCornerRadius + 0.5 - 2, aRect.origin.y + 0.5); + } else { + topRight = NSMakePoint(aRect.origin.x + 0.5 + kPSMSequelProTabCornerRadius, aRect.origin.y + 0.5); } - [lineColor set]; + // Set up the line and clipping point + CGContextClipToRect(context, NSMakeRect(topLeft.x, topLeft.y, topRight.x-topLeft.x, aRect.size.height)); + [[NSColor colorWithCalibratedWhite:0.2 alpha:drawAlpha] set]; + [outlineBezier moveToPoint:topLeft]; + [outlineBezier lineToPoint:topRight]; + + // Set up the shadow + shadow = [[NSShadow alloc] init]; + [shadow setShadowBlurRadius:4]; + [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.2 alpha:drawAlpha]]; + [shadow setShadowOffset:NSMakeSize(0,0)]; + [shadow set]; + + // Draw, and then restore the previous graphics state [outlineBezier stroke]; - } + CGContextRestoreGState(context); + } [NSGraphicsContext restoreGraphicsState]; |