adium-1.4 3215:e36d4a14d249: Efficiency in this less-used tablev...

commits at adium.im commits at adium.im
Tue Nov 2 01:24:51 UTC 2010


details:	http://hg.adium.im/adium-1.4/rev/e36d4a14d249
revision:	3215:e36d4a14d249
author:		Evan Schoenberg
date:		Mon Nov 01 20:23:44 2010 -0500

Efficiency in this less-used tableview too. Every bit helps
Subject: adium-1.4 3216:ab8a205c5901: Work around a bug in NSTableView by implementing our own drawRowIndexes:clipRect: so we can stop drawing once we're outside the clipping rect. Fixes #14463

details:	http://hg.adium.im/adium-1.4/rev/ab8a205c5901
revision:	3216:ab8a205c5901
author:		Evan Schoenberg
date:		Mon Nov 01 20:24:45 2010 -0500

Work around a bug in NSTableView by implementing our own drawRowIndexes:clipRect: so we can stop drawing once we're outside the clipping rect. Fixes #14463

diffs (86 lines):

diff -r c41ed8da034b -r ab8a205c5901 Frameworks/AIUtilities Framework/Source/AIVariableHeightFlexibleColumnsOutlineView.m
--- a/Frameworks/AIUtilities Framework/Source/AIVariableHeightFlexibleColumnsOutlineView.m	Mon Nov 01 18:41:38 2010 -0500
+++ b/Frameworks/AIUtilities Framework/Source/AIVariableHeightFlexibleColumnsOutlineView.m	Mon Nov 01 20:24:45 2010 -0500
@@ -36,7 +36,10 @@
 #pragma mark Drawing
 - (void)drawRow:(NSInteger)row clipRect:(NSRect)rect
 {
-	if (row >= 0 && row < [self numberOfRows]) { //Somebody keeps calling this method with row = numberOfRows, which is wrong.
+	if (row >= 0 && row < [self numberOfRows]) { //Somebody keeps calling this method with row = numberOfRows, which is wrong.		
+		if (NSIntersectsRect([self rectOfRow:row], rect) == FALSE)
+			return;
+
 		NSArray		*tableColumns = [self tableColumns];
 		id			item = [self itemAtRow:row];
 		unsigned	tableColumnIndex, count = [tableColumns count];
diff -r c41ed8da034b -r ab8a205c5901 Frameworks/AIUtilities Framework/Source/AIVariableHeightOutlineView.m
--- a/Frameworks/AIUtilities Framework/Source/AIVariableHeightOutlineView.m	Mon Nov 01 18:41:38 2010 -0500
+++ b/Frameworks/AIUtilities Framework/Source/AIVariableHeightOutlineView.m	Mon Nov 01 20:24:45 2010 -0500
@@ -230,14 +230,21 @@
 	}
 }
 
-- (void)drawRow:(NSInteger)row clipRect:(NSRect)rect
+/*!
+ * @brief Our implementation of drawRow:clipRect: which returns whether the row was drawn
+ *
+ * This is very useful if you are iterating rows in sequence. If drawRowIndexes:clipRect: is passed 1000 rows,
+ * but row 61 is outside the clip rect, rows 62 through 1000 will also be outside the clip rect.  Although
+ * -[self rectOfRow:] is reasonable cheap once, it can get quite expensive additively. See for example #14463 (700 Twitter contacts).
+ */
+- (BOOL)_ai_drawRow:(NSInteger)row clipRect:(NSRect)rect
 {		  
 	if (row >= 0 && row < [self numberOfRows]) { //Somebody keeps calling this method with row = numberOfRows, which is wrong.
-
 		/* Most important optimization ever:
 		 * Only draw if some part of this row's rect is in the clip rect */
-		if (NSIntersectsRect([self rectOfRow:row], rect) == FALSE)
-			return;
+		if (NSIntersectsRect([self rectOfRow:row], rect) == FALSE) {
+			return NO;
+		}
 		
 		NSArray		*tableColumns = [self tableColumns];
 		id			item = [self itemAtRow:row];
@@ -271,6 +278,41 @@
 			[cell drawWithFrame:cellFrame inView:self];
 		}
 	}
+	
+	return YES;
+}
+
+
+- (void)drawRow:(NSInteger)row clipRect:(NSRect)rect
+{
+	(void)[self _ai_drawRow:row clipRect:rect];
+}
+
+/*!
+ * @brief Override drawRowIndexes:clipRect: to stop when we're outside the clipRect.
+ *
+ * When -[NSTableView drawRect:] is called before any table view data is cached, it will pass every row of the table
+ * in indexes - not just those we'll soon know are outside of clipRect, which it does on subsequent calls.
+ *
+ * That's okay for a small table, but if, say, 1000 rows are in the list, it's expensive to check each one to see
+ * if it should be displayed.
+ */
+- (void)drawRowIndexes:(NSIndexSet *)indexes clipRect:(NSRect)clipRect
+{
+	NSUInteger bufSize = indexes.count;
+	NSUInteger *buf = malloc(bufSize * sizeof(NSUInteger));
+	NSUInteger i;
+	
+	NSRange range = NSMakeRange(indexes.firstIndex, (indexes.lastIndex - indexes.firstIndex) + 1);
+	[indexes getIndexes:buf maxCount:bufSize inIndexRange:&range];
+	
+	for (i = 0; i != bufSize; i++) {
+		/* draw until we're outside the clip rect.... */
+		if (![self _ai_drawRow:buf[i] clipRect:clipRect])
+			break;
+	}
+	
+	free(buf);
 }
 
 - (NSImage *)dragImageForRows:(NSUInteger *)buf count:(unsigned int)count tableColumns:(NSArray *)tableColumns event:(NSEvent*)dragEvent offset:(NSPointPointer)dragImageOffset




More information about the commits mailing list