1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-15 16:29:34 +00:00

#4374 Lion: animate filtering files table

This commit is contained in:
Mitchell Livingston 2011-07-21 02:36:12 +00:00
parent b28c4fb6cc
commit 4fde6035fd
2 changed files with 156 additions and 22 deletions

View file

@ -30,11 +30,13 @@
@interface FileOutlineController : NSObject
{
Torrent * fTorrent;
NSArray * fFileList;
NSMutableArray * fFileList;
IBOutlet FileOutlineView * fOutline;
NSString * fFilterText;
NSLock * fLock;
}
- (FileOutlineView *) outlineView;

View file

@ -28,6 +28,7 @@
#import "FilePriorityCell.h"
#import "FileListNode.h"
#import "NSApplicationAdditions.h"
#import "NSMutableArrayAdditions.h"
#import <Quartz/Quartz.h>
#define ROW_SMALL_HEIGHT 18.0
@ -49,23 +50,28 @@ typedef enum
- (NSMenu *) menu;
- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list inRange: (NSRange) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent;
@end
@implementation FileOutlineController
- (void) awakeFromNib
{
fFileList = [[NSMutableArray alloc] init];
[fOutline setDoubleAction: @selector(revealFile:)];
[fOutline setTarget: self];
//set table header tool tips
[[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download",
"file table -> header tool tip")];
[[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority",
"file table -> header tool tip")];
[[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download", "file table -> header tool tip")];
[[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority", "file table -> header tool tip")];
[fOutline setMenu: [self menu]];
#warning needed?
fLock = [[NSLock alloc] init];
[self setTorrent: nil];
}
@ -73,6 +79,9 @@ typedef enum
{
[fFileList release];
[fFilterText release];
[fLock release];
[super dealloc];
}
@ -85,48 +94,131 @@ typedef enum
{
fTorrent = torrent;
[fFileList release];
fFileList = [[fTorrent fileList] retain];
[fFileList setArray: [fTorrent fileList]];
[fFilterText release];
fFilterText = nil;
[fLock lock];
[fOutline deselectAll: nil];
[fOutline reloadData];
[fLock unlock];
}
- (void) setFilterText: (NSString *) text
{
[fLock lock];
if ([text isEqualToString: @""])
text = nil;
if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString: fFilterText]))
{
[fLock unlock];
return;
}
const BOOL onLion = [NSApp isOnLionOrBetter];
if (onLion)
[fOutline beginUpdates];
NSUInteger currentIndex = 0, totalCount = 0;
NSMutableArray * itemsToAdd = [NSMutableArray array];
NSMutableIndexSet * itemsToAddIndexes = [NSMutableIndexSet indexSet];
NSMutableDictionary * removedIndexesForParents = nil; //ugly, but we can't modify the actual file nodes
NSArray * tempList = !text ? [fTorrent fileList] : [fTorrent flatFileList];
for (FileListNode * item in tempList)
{
if (!text || [[item name] rangeOfString: text options: (NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)].location != NSNotFound)
{
FileListNode * parent = nil;
NSUInteger previousIndex = ![item isFolder] ? [self findFileNode: item inList: fFileList inRange: NSMakeRange(currentIndex, [fFileList count]-currentIndex) currentParent: nil finalParent: &parent] : NSNotFound;
if (previousIndex == NSNotFound)
{
[itemsToAdd addObject: item];
[itemsToAddIndexes addIndex: totalCount];
}
else
{
BOOL move = YES;
if (!parent)
{
if (previousIndex != currentIndex)
[fFileList moveObjectAtIndex: previousIndex toIndex: currentIndex];
else
move = NO;
}
else
{
[fFileList insertObject: item atIndex: currentIndex];
//figure out the index within the semi-edited table - UGLY
if (!removedIndexesForParents)
removedIndexesForParents = [NSMutableDictionary dictionary];
NSMutableIndexSet * removedIndexes = [removedIndexesForParents objectForKey: parent];
if (!removedIndexes)
{
removedIndexes = [NSMutableIndexSet indexSetWithIndex: previousIndex];
[removedIndexesForParents setObject: removedIndexes forKey: parent];
}
else
{
[removedIndexes addIndex: previousIndex];
previousIndex -= [removedIndexes countOfIndexesInRange: NSMakeRange(0, previousIndex)];
}
}
if (move && onLion)
[fOutline moveItemAtIndex: previousIndex inParent: parent toIndex: currentIndex inParent: nil];
++currentIndex;
}
++totalCount;
}
}
//remove trailing items - those are the unused
if (currentIndex < [fFileList count])
{
const NSRange removeRange = NSMakeRange(currentIndex, [fFileList count]-currentIndex);
[fFileList removeObjectsInRange: removeRange];
if (onLion)
[fOutline removeItemsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: removeRange] inParent: nil withAnimation: NSTableViewAnimationSlideDown];
}
//add new items
[fFileList insertObjects: itemsToAdd atIndexes: itemsToAddIndexes];
if (onLion)
[fOutline insertItemsAtIndexes: itemsToAddIndexes inParent: nil withAnimation: NSTableViewAnimationSlideUp];
if (onLion)
[fOutline endUpdates];
else
[fOutline reloadData];
[fFilterText release];
fFilterText = [text retain];
[fFileList release];
if (!fFilterText)
fFileList = [[fTorrent fileList] retain];
else
{
NSMutableArray * list = [NSMutableArray arrayWithCapacity: [fTorrent fileCount]];
for (FileListNode * node in [fTorrent flatFileList])
if ([[node name] rangeOfString: fFilterText options: (NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch)].location != NSNotFound)
[list addObject: node];
fFileList = [[NSArray alloc] initWithArray: list];
}
[fOutline reloadData];
[fLock unlock];
}
- (void) reloadData
{
[fTorrent updateFileStat];
[fLock lock];
[fOutline reloadData];
[fLock unlock];
}
- (void) outlineViewSelectionDidChange: (NSNotification *) notification
@ -265,6 +357,8 @@ typedef enum
- (void) setCheck: (id) sender
{
[fLock lock];
NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSOffState : NSOnState;
NSIndexSet * indexSet = [fOutline selectedRowIndexes];
@ -274,10 +368,14 @@ typedef enum
[fTorrent setFileCheckState: state forIndexes: itemIndexes];
[fOutline reloadData];
[fLock unlock];
}
- (void) setOnlySelectedCheck: (id) sender
{
[fLock lock];
NSIndexSet * indexSet = [fOutline selectedRowIndexes];
NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
@ -290,6 +388,8 @@ typedef enum
[fTorrent setFileCheckState: NSOffState forIndexes: remainingItemIndexes];
[fOutline reloadData];
[fLock unlock];
}
- (void) setPriority: (id) sender
@ -307,6 +407,8 @@ typedef enum
priority = TR_PRI_LOW;
}
[fLock lock];
NSIndexSet * indexSet = [fOutline selectedRowIndexes];
NSMutableIndexSet * itemIndexes = [NSMutableIndexSet indexSet];
for (NSInteger i = [indexSet firstIndex]; i != NSNotFound; i = [indexSet indexGreaterThanIndex: i])
@ -314,10 +416,14 @@ typedef enum
[fTorrent setFilePriority: priority forIndexes: itemIndexes];
[fOutline reloadData];
[fLock unlock];
}
- (void) revealFile: (id) sender
{
[fLock lock];
NSIndexSet * indexes = [fOutline selectedRowIndexes];
if ([NSApp isOnSnowLeopardOrBetter])
{
@ -341,6 +447,8 @@ typedef enum
[[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: nil];
}
}
[fLock unlock];
}
#warning make real view controller (Leopard-only) so that Command-R will work
@ -510,4 +618,28 @@ typedef enum
return [menu autorelease];
}
- (NSUInteger) findFileNode: (FileListNode *) node inList: (NSArray *) list inRange: (NSRange) range currentParent: (FileListNode *) currentParent finalParent: (FileListNode **) parent
{
NSAssert(![node isFolder], @"Looking up folder node!");
const NSUInteger nodeIndex = [[node indexes] firstIndex];
for (NSUInteger index = range.location; index < NSMaxRange(range); ++index)
{
FileListNode * checkNode = [list objectAtIndex: index];
if ([checkNode isEqualTo: node])
{
*parent = currentParent;
return index;
}
else if ([checkNode isFolder] && [[checkNode indexes] containsIndex: nodeIndex])
{
const NSUInteger subIndex = [self findFileNode: node inList: [checkNode children] inRange: NSMakeRange(0, [[checkNode children] count]) currentParent: checkNode finalParent: parent];
NSAssert(subIndex != NSNotFound, @"We didn't find an expected file node.");
return subIndex;
}
}
return NSNotFound;
}
@end