]> granicus.if.org Git - transmission/commitdiff
#4375 Lion: animate filtering message window
authorMitchell Livingston <livings124@transmissionbt.com>
Thu, 21 Jul 2011 02:36:27 +0000 (02:36 +0000)
committerMitchell Livingston <livings124@transmissionbt.com>
Thu, 21 Jul 2011 02:36:27 +0000 (02:36 +0000)
macosx/MessageWindowController.m

index a606d9777ffd119fdd62abe4b6dcfc737df62686..f06c03578ed5a0c24acfcf511930b54f28cf20af 100644 (file)
@@ -24,6 +24,7 @@
 
 #import "MessageWindowController.h"
 #import "NSApplicationAdditions.h"
+#import "NSMutableArrayAdditions.h"
 #import "NSStringAdditions.h"
 #import <transmission.h>
 #import <utils.h>
@@ -38,6 +39,7 @@
 
 - (void) resizeColumn;
 - (BOOL) shouldIncludeMessageForFilter: (NSString *) filterString message: (NSDictionary *) message;
+- (void) updateListForFilter;
 - (NSString *) stringForMessage: (NSDictionary *) message;
 
 @end
     return [super initWithWindowNibName: @"MessageWindow"];
 }
 
-- (void) dealloc
-{
-    [[NSNotificationCenter defaultCenter] removeObserver: self];
-    
-    [fTimer invalidate];
-    [fLock release];
-    
-    [fMessages release];
-    [fDisplayedMessages release];
-    
-    [fAttributes release];
-    
-    [super dealloc];
-}
-
 - (void) awakeFromNib
 {
     NSWindow * window = [self window];
     fLock = [[NSLock alloc] init];
 }
 
+- (void) dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    
+    [fTimer invalidate];
+    [fLock release];
+    
+    [fMessages release];
+    [fDisplayedMessages release];
+    
+    [fAttributes release];
+    
+    [super dealloc];
+}
+
 - (void) windowDidBecomeKey: (NSNotification *) notification
 {
     if (!fTimer)
     if ([[NSUserDefaults standardUserDefaults] integerForKey: @"MessageLevel"] == level)
         return;
     
-    [fLock lock];
-    
     [[NSUserDefaults standardUserDefaults] setInteger: level forKey: @"MessageLevel"];
     
-    NSString * filterString = [fFilterField stringValue];
-    
-    [fDisplayedMessages removeAllObjects];
-    for (NSDictionary * message in fMessages)
-        if ([[message objectForKey: @"Level"] integerValue] <= level
-            && [self shouldIncludeMessageForFilter: filterString message: message])
-            [fDisplayedMessages addObject: message];
-    
-    [fDisplayedMessages sortUsingDescriptors: [fMessageTable sortDescriptors]];
-    
-    [fMessageTable reloadData];
+    [fLock lock];
     
-    if ([fDisplayedMessages count] > 0)
-    {
-        [fMessageTable deselectAll: self];
-        [fMessageTable scrollRowToVisible: [fMessageTable numberOfRows]-1];
-    }
+    [self updateListForFilter];
     
     [fLock unlock];
 }
 {
     [fLock lock];
     
-    const NSInteger level = [[NSUserDefaults standardUserDefaults] integerForKey: @"MessageLevel"];
-    NSString * filterString = [fFilterField stringValue];
-    
-    [fDisplayedMessages removeAllObjects];
-    for (NSDictionary * message in fMessages)
-        if ([[message objectForKey: @"Level"] integerValue] <= level
-            && [self shouldIncludeMessageForFilter: filterString message: message])
-            [fDisplayedMessages addObject: message];
-    
-    [fDisplayedMessages sortUsingDescriptors: [fMessageTable sortDescriptors]];
-    
-    [fMessageTable reloadData];
-    
-    if ([fDisplayedMessages count] > 0)
-    {
-        [fMessageTable deselectAll: self];
-        [fMessageTable scrollRowToVisible: [fMessageTable numberOfRows]-1];
-    }
+    [self updateListForFilter];
     
     [fLock unlock];
 }
     [fLock lock];
     
     [fMessages removeAllObjects];
+    
+    const BOOL onLion = [NSApp isOnLionOrBetter];
+    
+    if (onLion)
+        [fMessageTable beginUpdates];
+    
+    if (onLion)
+        [fMessageTable removeRowsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fDisplayedMessages count])] withAnimation: NSTableViewAnimationSlideLeft];
     [fDisplayedMessages removeAllObjects];
-    [fMessageTable reloadData];
+    
+    if (onLion)
+        [fMessageTable endUpdates];
+    else
+        [fMessageTable reloadData];
     
     [fLock unlock];
 }
             || [[message objectForKey: @"Message"] rangeOfString: filterString options: searchOptions].location != NSNotFound;
 }
 
+- (void) updateListForFilter
+{
+    const NSInteger level = [[NSUserDefaults standardUserDefaults] integerForKey: @"MessageLevel"];
+    NSString * filterString = [fFilterField stringValue];
+    
+    NSMutableArray * tempMessages = [NSMutableArray arrayWithCapacity: [fMessages count]]; //rough guess
+    
+    for (NSDictionary * message in fMessages)
+    {
+        if ([[message objectForKey: @"Level"] integerValue] <= level
+            && [self shouldIncludeMessageForFilter: filterString message: message])
+            [tempMessages addObject: message];
+    }
+    
+    [tempMessages sortUsingDescriptors: [fMessageTable sortDescriptors]];
+    
+    const BOOL onLion = [NSApp isOnLionOrBetter];
+    
+    if (onLion)
+        [fMessageTable beginUpdates];
+    
+    //figure out which rows were added/moved
+    NSUInteger currentIndex = 0, totalCount = 0;
+    NSMutableArray * itemsToAdd = [NSMutableArray array];
+    NSMutableIndexSet * itemsToAddIndexes = [NSMutableIndexSet indexSet];
+    
+    for (NSDictionary * message in tempMessages)
+    {
+        const NSUInteger previousIndex = [fDisplayedMessages indexOfObject: message inRange: NSMakeRange(currentIndex, [fDisplayedMessages count]-currentIndex)];
+        if (previousIndex == NSNotFound)
+        {
+            [itemsToAdd addObject: message];
+            [itemsToAddIndexes addIndex: totalCount];
+        }
+        else
+        {
+            if (previousIndex != currentIndex)
+            {
+                [fDisplayedMessages moveObjectAtIndex: previousIndex toIndex: currentIndex];
+                if (onLion)
+                    [fMessageTable moveRowAtIndex: previousIndex toIndex: currentIndex];
+            }
+            ++currentIndex;
+        }
+        
+        ++totalCount;
+    }
+    
+    //remove trailing items - those are the unused
+    if (currentIndex < [fDisplayedMessages count])
+    {
+        const NSRange removeRange = NSMakeRange(currentIndex, [fDisplayedMessages count]-currentIndex);
+        [fDisplayedMessages removeObjectsInRange: removeRange];
+        if (onLion)
+            [fMessageTable removeRowsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: removeRange] withAnimation: NSTableViewAnimationSlideDown];
+    }
+    
+    //add new items
+    [fDisplayedMessages insertObjects: itemsToAdd atIndexes: itemsToAddIndexes];
+    if (onLion)
+        [fMessageTable insertRowsAtIndexes: itemsToAddIndexes withAnimation: NSTableViewAnimationSlideUp];
+    
+    if (onLion)
+        [fMessageTable endUpdates];
+    else
+    {
+        [fMessageTable reloadData];
+        
+        if ([fDisplayedMessages count] > 0)
+            [fMessageTable deselectAll: self];
+    }
+    
+    NSAssert([fDisplayedMessages isEqualToArray: tempMessages], @"Inconsistency between message arrays! %@ %@", fDisplayedMessages, tempMessages);
+}
+
 - (NSString *) stringForMessage: (NSDictionary *) message
 {
     NSString * levelString;