diff --git a/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.h b/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.h index 6a8086f5..d4a81ccf 100644 --- a/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.h +++ b/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.h @@ -7,6 +7,10 @@ @property (nonatomic) NSArray* openURLs; @property (nonatomic) NSArray* modifiedURLs; +@property (nonatomic) SEL openItemSelector; +@property (nonatomic) SEL closeItemSelector; +@property (nonatomic, weak) id target; + - (void)selectURLs:(NSArray*)someURLs expandChildren:(BOOL)expandAncestors; - (void)editURL:(NSURL*)anURL; - (void)scrollToOffset:(CGFloat)anOffset; diff --git a/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.mm b/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.mm index 22ce2b6d..c2e665e6 100644 --- a/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.mm +++ b/Frameworks/OakFileBrowser/src/FSOutlineViewDelegate.mm @@ -3,17 +3,154 @@ #import "io/FSDataSource.h" #import "io/FSItem.h" #import "ui/OFBOutlineView.h" -#import "ui/OFBPathInfoCell.h" #import +#import +#import #import +#import +#import +#import #import #import #import #import -@interface NSCell (FSItemCell) -- (void)setImage:(NSImage*)anImage; -- (void)setLabelIndex:(NSInteger)anInteger; +@interface OakSelectBasenameCell : NSTextFieldCell +@end + +@implementation OakSelectBasenameCell +- (void)selectWithFrame:(NSRect)aRect inView:(NSView*)aView editor:(NSText*)aText delegate:(id)someDelegate start:(NSInteger)start length:(NSInteger)length +{ + NSString* basename = [self.stringValue stringByDeletingPathExtension]; + [super selectWithFrame:aRect inView:aView editor:aText delegate:someDelegate start:start length:(start == 0 && basename ? MIN(basename.length, length) : length)]; +} +@end + +@interface OakFSItemTableCellView : NSTableCellView +@property (nonatomic) NSButton* openButton; +@property (nonatomic) NSButton* closeButton; +@property (nonatomic) NSArray* openURLs; +@property (nonatomic) NSArray* modifiedURLs; +@property (nonatomic) NSInteger labelIndex; +@end + +@implementation OakFSItemTableCellView +- (instancetype)initWithOpenButton:(NSButton*)openButton closeButton:(NSButton*)closeButton +{ + if((self = [super initWithFrame:NSZeroRect])) + { + _openButton = openButton; + _closeButton = closeButton; + + [openButton setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; + [openButton setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; + + NSTextField* fileTextField = OakCreateLabel(@"", [NSFont controlContentFontOfSize:0]); + fileTextField.cell = [[OakSelectBasenameCell alloc] initTextCell:@""]; + fileTextField.editable = YES; + fileTextField.delegate = self; + + NSDictionary* views = @{ @"icon" : openButton, @"file" : fileTextField, @"close" : closeButton }; + OakAddAutoLayoutViewsToSuperview([views allValues], self); + + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(4)-[icon]-(4)-[file]-(4@750)-[close(==16)]-(8)-|" options:0 metrics:nil views:views]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[file]-(2)-|" options:NSLayoutFormatAlignAllLeading|NSLayoutFormatAlignAllTrailing metrics:nil views:views]]; + [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:openButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; + [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:closeButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; + + [openButton bind:NSImageBinding toObject:self withKeyPath:@"objectValue.icon" options:nil]; + [fileTextField bind:NSValueBinding toObject:self withKeyPath:@"objectValue.displayName" options:nil]; + [fileTextField bind:NSToolTipBinding toObject:self withKeyPath:@"objectValue.toolTip" options:nil]; + [self bind:@"labelIndex" toObject:self withKeyPath:@"objectValue.labelIndex" options:nil]; + + self.textField = fileTextField; + } + return self; +} + +- (void)controlTextDidEndEditing:(NSNotification*)aNotification +{ + FSItem* item = self.objectValue; + if(![item setNewDisplayName:self.textField.stringValue view:self]) + item.displayName = [NSString stringWithCxxString:path::display_name([item.url.path fileSystemRepresentation])]; +} + +- (void)setObjectValue:(FSItem*)item +{ + [super setObjectValue:item]; + self.openURLs = _openURLs; + self.modified = [_modifiedURLs containsObject:item.url]; +} + +- (void)setLabelIndex:(NSInteger)newLabelIndex +{ + if(_labelIndex != newLabelIndex) + { + _labelIndex = newLabelIndex; + [self setNeedsDisplay:YES]; + } +} + +- (void)setModified:(BOOL)flag +{ + FSItem* item = self.objectValue; + NSImage* icon = [item.icon copy]; + + SEL setModifiedSelector = @selector(setModified:); + if([icon respondsToSelector:setModifiedSelector]) + { + auto fn = (void(*)(id, SEL, BOOL))[icon methodForSelector:setModifiedSelector]; + fn(icon, setModifiedSelector, flag); + item.icon = icon; + } +} + +- (void)setOpenURLs:(NSArray*)someURLs +{ + _openURLs = someURLs; + FSItem* item = self.objectValue; + _closeButton.hidden = ![_openURLs containsObject:item.url]; +} + +- (void)setModifiedURLs:(NSArray*)someURLs +{ + FSItem* item = self.objectValue; + BOOL wasModified = [_modifiedURLs containsObject:item.url]; + BOOL isModified = [someURLs containsObject:item.url]; + + _modifiedURLs = someURLs; + if(wasModified != isModified) + self.modified = isModified; +} + +- (void)resetCursorRects +{ + [self addCursorRect:self.openButton.frame cursor:[NSCursor pointingHandCursor]]; +} + +- (void)drawLabelIndex:(NSUInteger)labelColorIndex inFrame:(NSRect)cellFrame +{ + if(labelColorIndex == 0) + return; + ASSERT(labelColorIndex < 8); + + // color names: Gray, Green, Purple, Blue, Yellow, Red, Orange + static NSString* const startCol[] = { @"#CFCFCF", @"#D4EE9C", @"#DDBDEA", @"#ACD0FE", @"#F8F79C", @"#FC999A", @"#F9D194" }; + static NSString* const stopCol[] = { @"#A8A8A8", @"#AFDC49", @"#C186D7", @"#5B9CFE", @"#ECDF4A", @"#FC605C", @"#F6AC46" }; + + NSRect r = NSIntegralRect(NSInsetRect(cellFrame, 2, 0)), unused; + if(self.backgroundStyle == NSBackgroundStyleDark) + NSDivideRect(r, &r, &unused, 30, NSMaxXEdge); + + NSGradient* gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithString:startCol[labelColorIndex-1]] endingColor:[NSColor colorWithString:stopCol[labelColorIndex-1]]]; + NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:r xRadius:8 yRadius:8]; + [gradient drawInBezierPath:path angle:90]; +} + +- (void)drawRect:(NSRect)aRect +{ + [self drawLabelIndex:_labelIndex inFrame:[self bounds]]; +} @end static NSArray* ConvertURLSetToStringArray (NSSet* aSet) @@ -265,55 +402,9 @@ struct expansion_state_t // = Outline view delegate methods = // ================================= -- (void)outlineView:(NSOutlineView*)anOutlineView willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn*)tableColumn item:(FSItem*)item -{ - if([cell respondsToSelector:@selector(setImage:)]) - { - SEL selector = @selector(setModified:); - if([item.icon respondsToSelector:selector]) - { - auto fn = (void(*)(id, SEL, BOOL))[item.icon methodForSelector:selector]; - fn(item.icon, selector, [_modifiedURLs containsObject:item.url]); - } - [cell setImage:item.icon]; - } - cell.stringValue = item.displayName; - // cell.textColor = lstat([[item.url path] fileSystemRepresentation], &(struct stat){ 0 }) == 0 ? [NSColor textColor] : [NSColor redColor]; - // cell.target = delegate; - cell.representedObject = item; - if([cell respondsToSelector:@selector(setLabelIndex:)]) - [cell setLabelIndex:item.labelIndex]; - if([cell respondsToSelector:@selector(setIsOpen:)]) - ((OFBPathInfoCell*)cell).isOpen = [_openURLs containsObject:item.url]; - // cell.isLoading = item.isLoading; - - if([anOutlineView editedRow] != -1 && item == [anOutlineView itemAtRow:[anOutlineView editedRow]]) - { - if(NSString* path = [[item.url filePathURL] path]) - cell.stringValue = [NSString stringWithCxxString:path::display_name([path fileSystemRepresentation])]; - } -} - - (BOOL)outlineView:(NSOutlineView*)anOutlineView shouldSelectItem:(id)item { - if([self outlineView:anOutlineView isGroupItem:item]) - return NO; - - NSInteger col = [anOutlineView clickedColumn]; - NSInteger row = [anOutlineView clickedRow]; - if(col != -1 && row != -1) - { - NSCell* cell = [anOutlineView preparedCellAtColumn:col row:row]; - NSUInteger hit = [cell hitTestForEvent:[NSApp currentEvent] inRect:[anOutlineView frameOfCellAtColumn:col row:row] ofView:anOutlineView]; - if(hit & (OFBPathInfoCellHitOpenItem | OFBPathInfoCellHitRevealItem | NSCellHitTrackableArea)) - return NO; - } - return YES; -} - -- (BOOL)outlineView:(NSOutlineView*)anOutlineView shouldTrackCell:(NSCell*)cell forTableColumn:(NSTableColumn*)tableColumn item:(id)item -{ - return YES; + return [self outlineView:anOutlineView isGroupItem:item] == NO; } - (BOOL)outlineView:(NSOutlineView*)anOutlineView isGroupItem:(FSItem*)item @@ -321,11 +412,6 @@ struct expansion_state_t return [item respondsToSelector:@selector(group)] ? item.group : NO; } -- (NSString*)outlineView:(NSOutlineView*)outlineView toolTipForCell:(NSCell*)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn*)tc item:(FSItem*)item mouseLocation:(NSPoint)mouseLocation -{ - return [item respondsToSelector:@selector(toolTip)] ? item.toolTip : nil; -} - // =========================== // = Expand Delegate Methods = // =========================== @@ -462,4 +548,41 @@ struct expansion_state_t if([_dataSource unloadItem:item]) [_outlineView reloadItem:item reloadChildren:YES]; } + +// =============================== +// = Table cell view constructor = +// =============================== + +- (NSView*)outlineView:(NSOutlineView*)outlineView viewForTableColumn:(NSTableColumn*)tableColumn item:(FSItem*)item +{ + NSTableCellView* res = [outlineView makeViewWithIdentifier:tableColumn.identifier owner:self]; + if(!res) + { + NSButton* openButton = [[NSButton alloc] initWithFrame:NSZeroRect]; + openButton.refusesFirstResponder = YES; + openButton.buttonType = NSMomentaryChangeButton; + openButton.bordered = NO; + openButton.imagePosition = NSImageOnly; + openButton.target = _target; + openButton.action = _openItemSelector; + + OakRolloverButton* closeButton = [[OakRolloverButton alloc] initWithFrame:NSZeroRect]; + OakSetAccessibilityLabel(closeButton, @"Close document"); + + closeButton.regularImage = [NSImage imageNamed:@"CloseTemplate" inSameBundleAsClass:[self class]]; + closeButton.pressedImage = [NSImage imageNamed:@"ClosePressedTemplate" inSameBundleAsClass:[self class]]; + closeButton.rolloverImage = [NSImage imageNamed:@"CloseRolloverTemplate" inSameBundleAsClass:[self class]]; + closeButton.target = _target; + closeButton.action = _closeItemSelector; + + res = [[OakFSItemTableCellView alloc] initWithOpenButton:openButton closeButton:closeButton]; + res.identifier = tableColumn.identifier; + + [res bind:@"openURLs" toObject:self withKeyPath:@"openURLs" options:nil]; + [res bind:@"modifiedURLs" toObject:self withKeyPath:@"modifiedURLs" options:nil]; + } + + res.objectValue = item; + return res; +} @end diff --git a/Frameworks/OakFileBrowser/src/OakFileBrowser.mm b/Frameworks/OakFileBrowser/src/OakFileBrowser.mm index 37d4194a..79cc6bea 100644 --- a/Frameworks/OakFileBrowser/src/OakFileBrowser.mm +++ b/Frameworks/OakFileBrowser/src/OakFileBrowser.mm @@ -2,7 +2,6 @@ #import "OakFSUtilities.h" #import "ui/OFBHeaderView.h" #import "ui/OFBOutlineView.h" -#import "ui/OFBPathInfoCell.h" #import "ui/OFBActionsView.h" #import "io/FSDataSource.h" #import "io/FSSCMDataSource.h" @@ -136,15 +135,6 @@ static bool is_binary (std::string const& path) return false; } -static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anotherSet) -{ - NSMutableSet* unionSet = [aSet mutableCopy]; - [unionSet unionSet:anotherSet]; - [anotherSet intersectSet:aSet]; - [unionSet minusSet:anotherSet]; - return unionSet; -} - @implementation OakFileBrowser - (id)init { @@ -238,20 +228,16 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot _view = [OakFileBrowserView new]; - NSTextFieldCell* cell = [OFBPathInfoCell new]; - cell.lineBreakMode = NSLineBreakByTruncatingMiddle; - [cell setEditable:YES]; - if(_outlineView.renderAsSourceList && oak::os_tuple() >= std::make_tuple(10, 10, 0)) - cell.textColor = [NSColor textColor]; - NSTableColumn* tableColumn = [NSTableColumn new]; - [tableColumn setDataCell:cell]; [_outlineView addTableColumn:tableColumn]; [_outlineView setOutlineTableColumn:tableColumn]; [_outlineView sizeLastColumnToFit]; _outlineViewDelegate = [FSOutlineViewDelegate new]; - _outlineViewDelegate.outlineView = _outlineView; + _outlineViewDelegate.outlineView = _outlineView; + _outlineViewDelegate.openItemSelector = @selector(takeItemToOpenFrom:); + _outlineViewDelegate.closeItemSelector = @selector(takeItemToCloseFrom:); + _outlineViewDelegate.target = self; NSDictionary* views = @{ @"header" : _headerView, @@ -543,41 +529,10 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot // = Externally provided item state = // ================================== -- (NSArray*)openURLs -{ - return _outlineViewDelegate.openURLs; -} - -- (void)setOpenURLs:(NSArray*)newOpenURLs -{ - if([_outlineViewDelegate.openURLs isEqualToArray:newOpenURLs]) - return; - - NSSet* symmetricDifference = SymmetricDifference([NSMutableSet setWithArray:_outlineViewDelegate.openURLs], [NSMutableSet setWithArray:newOpenURLs]); - - // make a note of files in view, with changed open state - NSIndexSet* updateRows = [self indexSetforURLs:symmetricDifference]; - _outlineViewDelegate.openURLs = newOpenURLs; - [_outlineView reloadDataForRowIndexes:updateRows columnIndexes:[NSIndexSet indexSetWithIndex:0]]; -} - -- (NSArray*)modifiedURLs -{ - return _outlineViewDelegate.modifiedURLs; -} - -- (void)setModifiedURLs:(NSArray*)newModifiedURLs -{ - if([_outlineViewDelegate.modifiedURLs isEqualToArray:newModifiedURLs]) - return; - - NSSet* symmetricDifference = SymmetricDifference([NSMutableSet setWithArray:_outlineViewDelegate.modifiedURLs], [NSMutableSet setWithArray:newModifiedURLs]); - - // make a note of files in view, with changed modified state - NSIndexSet* updateRows = [self indexSetforURLs:symmetricDifference]; - _outlineViewDelegate.modifiedURLs = newModifiedURLs; - [_outlineView reloadDataForRowIndexes:updateRows columnIndexes:[NSIndexSet indexSetWithIndex:0]]; -} +- (NSArray*)openURLs { return _outlineViewDelegate.openURLs; } +- (NSArray*)modifiedURLs { return _outlineViewDelegate.modifiedURLs; } +- (void)setOpenURLs:(NSArray*)someURLs { _outlineViewDelegate.openURLs = someURLs; } +- (void)setModifiedURLs:(NSArray*)someURLs { _outlineViewDelegate.modifiedURLs = someURLs; } - (NSIndexSet*)indexSetforURLs:(NSSet*)urls { @@ -1040,10 +995,37 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot // = Action methods = // ================== +- (void)takeItemToOpenFrom:(id)sender +{ + NSInteger row = [_outlineView rowForView:sender]; + if(row != -1) + { + if(FSItem* item = [_outlineView itemAtRow:row]) + { + if([item.url isFileURL] && ([NSEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSCommandKeyMask)) == NSCommandKeyMask) + [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:@[ item.url ]]; + else [self openItems:@[ item ] animate:YES]; + } + } +} + +- (void)takeItemToCloseFrom:(id)sender +{ + NSInteger row = [_outlineView rowForView:sender]; + if(row != -1) + { + FSItem* item = [_outlineView itemAtRow:row]; + [_delegate fileBrowser:self closeURL:item.url]; + } +} + - (IBAction)didDoubleClickOutlineView:(id)sender { - NSArray* items = _outlineView.clickedRow != -1 ? @[ [_outlineView itemAtRow:_outlineView.clickedRow] ] : self.selectedItems; + [self openItems:_outlineView.clickedRow != -1 ? @[ [_outlineView itemAtRow:_outlineView.clickedRow] ] : self.selectedItems animate:YES]; +} +- (void)openItems:(NSArray*)items animate:(BOOL)animateFlag +{ NSMutableArray* urlsToOpen = [NSMutableArray array]; NSMutableArray* itemsToAnimate = [NSMutableArray array]; @@ -1083,7 +1065,7 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot } } - if(![[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsFileBrowserOpenAnimationDisabled]) + if(animateFlag && ![[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsFileBrowserOpenAnimationDisabled]) { for(FSItem* item in itemsToAnimate) [OakZoomingIcon zoomIcon:item.icon fromRect:[self iconFrameForEntry:item]]; @@ -1095,18 +1077,11 @@ static NSMutableSet* SymmetricDifference (NSMutableSet* aSet, NSMutableSet* anot - (IBAction)didSingleClickOutlineView:(id)sender { - NSInteger row = [_outlineView clickedRow]; - NSInteger col = [_outlineView clickedColumn]; - col = row != -1 && col == -1 ? 0 : col; // Clicking a row which participates in multi-row selection causes clickedColumn to return -1 - NSCell* cell = [_outlineView preparedCellAtColumn:col row:row]; - NSUInteger hit = [cell hitTestForEvent:[NSApp currentEvent] inRect:[_outlineView frameOfCellAtColumn:col row:row] ofView:_outlineView]; - FSItem* item = [_outlineView itemAtRow:row]; - if((hit & OFBPathInfoCellHitRevealItem) && [item.url isFileURL]) - [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:@[ item.url ]]; - else if(hit & (OFBPathInfoCellHitOpenItem | OFBPathInfoCellHitRevealItem)) - [self didDoubleClickOutlineView:sender]; - else if(hit & OFBPathInfoCellHitCloseButton) - [_delegate fileBrowser:self closeURL:item.url]; + BOOL singleClickShouldOpen = [[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsFileBrowserSingleClickToOpenKey]; + BOOL noModifiers = !([NSEvent modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSCommandKeyMask)); + FSItem* item = _outlineView.clickedRow != -1 ? [_outlineView itemAtRow:_outlineView.clickedRow] : nil; + if(singleClickShouldOpen && noModifiers && item.urlType == FSItemURLTypeFile) + [self openItems:@[ item ] animate:NO]; } - (IBAction)reload:(id)sender diff --git a/Frameworks/OakFileBrowser/src/io/FSDataSource.mm b/Frameworks/OakFileBrowser/src/io/FSDataSource.mm index 60fb6c57..e59717cf 100644 --- a/Frameworks/OakFileBrowser/src/io/FSDataSource.mm +++ b/Frameworks/OakFileBrowser/src/io/FSDataSource.mm @@ -81,17 +81,6 @@ FSDataSource* DataSourceForURL (NSURL* anURL, NSUInteger someOptions) return [(item ?: self.rootItem).children objectAtIndex:childIndex]; } -- (id)outlineView:(NSOutlineView*)anOutlineView objectValueForTableColumn:(NSTableColumn*)tableColumn byItem:(FSItem*)item -{ - return item; -} - -- (void)outlineView:(NSOutlineView*)anOutlineView setObjectValue:(id)objectValue forTableColumn:(NSTableColumn*)tableColumn byItem:(FSItem*)item -{ - if([objectValue isKindOfClass:[NSString class]]) - [item setNewDisplayName:objectValue view:anOutlineView]; -} - - (BOOL)outlineView:(NSOutlineView*)anOutlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard { NSMutableArray* urls = [NSMutableArray array]; diff --git a/Frameworks/OakFileBrowser/src/ui/OFBOutlineView.mm b/Frameworks/OakFileBrowser/src/ui/OFBOutlineView.mm index ea8bab00..caaeb5d9 100644 --- a/Frameworks/OakFileBrowser/src/ui/OFBOutlineView.mm +++ b/Frameworks/OakFileBrowser/src/ui/OFBOutlineView.mm @@ -1,5 +1,4 @@ #import "OFBOutlineView.h" -#import "OFBPathInfoCell.h" #import #import #import @@ -14,8 +13,6 @@ { OBJC_WATCH_LEAKS(OFBOutlineView); - NSRect mouseHoverRect; - NSTableViewSelectionHighlightStyle defaultSelectionHighlightStyle; NSTableViewDraggingDestinationFeedbackStyle defaultDraggingDestinationFeedbackStyle; CGFloat defaultRowHeight; @@ -142,18 +139,13 @@ if([event type] != NSLeftMouseDown) return YES; - id firstResponder = [[self window] firstResponder]; - if(([firstResponder respondsToSelector:@selector(delegate)] && [(NSText*)firstResponder delegate] == self) || firstResponder == self) + NSView* firstResponder = (NSView*)[[self window] firstResponder]; + if([firstResponder isKindOfClass:[NSView class]] && [firstResponder isDescendantOf:self]) return YES; if([event clickCount] != 1 || (event.modifierFlags & NSCommandKeyMask)) return NO; - NSInteger row = [self rowAtPoint:[self convertPoint:[event locationInWindow] fromView:nil]]; - NSUInteger hit = row == -1 ? 0 : [[self preparedCellAtColumn:0 row:row] hitTestForEvent:event inRect:[self frameOfCellAtColumn:0 row:row] ofView:self]; - if(hit & (OFBPathInfoCellHitOpenItem | OFBPathInfoCellHitRevealItem | NSCellHitTrackableArea)) - return NO; - NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil]; return [self isRowSelected:[self rowAtPoint:p]]; } @@ -231,71 +223,4 @@ if([NSOutlineView respondsToSelector:@selector(draggedImage:endedAt:operation:)]) [super draggedImage:anImage endedAt:aPoint operation:aDragOperation]; } - -// ================== -// = Mouse Tracking = -// ================== - -- (void)cursorUpdate:(NSEvent*)event -{ - if(NSMouseInRect([self convertPoint:[event locationInWindow] fromView:nil], [[event trackingArea] rect], self.isFlipped)) - [[NSCursor pointingHandCursor] set]; - else [super cursorUpdate:event]; -} - -- (void)updateTrackingAreas -{ - for(NSTrackingArea* trackingArea in self.trackingAreas) - [self removeTrackingArea:trackingArea]; - - [super updateTrackingAreas]; - - NSRange rows = [self rowsInRect:[self visibleRect]]; - for(NSUInteger row = rows.location; row < NSMaxRange(rows); ++row) - { - NSRect cellFrame = [self frameOfCellAtColumn:0 row:row]; - NSRect imageFrame = [[[[self tableColumns] lastObject] dataCell] imageFrameWithFrame:cellFrame inControlView:self]; - imageFrame.origin.y = cellFrame.origin.y; - imageFrame.size.height = cellFrame.size.height + self.intercellSpacing.height; - [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:imageFrame options:NSTrackingCursorUpdate|NSTrackingActiveInKeyWindow owner:self userInfo:NULL]]; - } - - [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInKeyWindow owner:self userInfo:NULL]]; -} - -// =============== -// = Mouse Moved = -// =============== - -- (void)mouseMoved:(NSEvent*)theEvent -{ - NSRect newHoverRect = NSZeroRect; - - NSPoint mousePos = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - NSInteger row = [self rowAtPoint:mousePos]; - if(row != -1) - { - OFBPathInfoCell* cell = (OFBPathInfoCell*)[self preparedCellAtColumn:0 row:row]; - NSRect closeButtonRect = [cell closeButtonRectInFrame:[self frameOfCellAtColumn:0 row:row]]; - if(NSMouseInRect(mousePos, closeButtonRect, self.isFlipped)) - newHoverRect = closeButtonRect; - } - - if(!NSEqualRects(mouseHoverRect, newHoverRect)) - { - [self setNeedsDisplayInRect:mouseHoverRect]; - [self setNeedsDisplayInRect:newHoverRect]; - mouseHoverRect = newHoverRect; - } -} - -- (void)mouseExited:(NSEvent*)anEvent -{ - if(!NSIsEmptyRect(mouseHoverRect)) - { - [self setNeedsDisplayInRect:mouseHoverRect]; - mouseHoverRect = NSZeroRect; - } - [super mouseExited:anEvent]; -} @end