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:
parent
b28c4fb6cc
commit
4fde6035fd
2 changed files with 156 additions and 22 deletions
|
@ -30,11 +30,13 @@
|
|||
@interface FileOutlineController : NSObject
|
||||
{
|
||||
Torrent * fTorrent;
|
||||
NSArray * fFileList;
|
||||
NSMutableArray * fFileList;
|
||||
|
||||
IBOutlet FileOutlineView * fOutline;
|
||||
|
||||
NSString * fFilterText;
|
||||
|
||||
NSLock * fLock;
|
||||
}
|
||||
|
||||
- (FileOutlineView *) outlineView;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue