Re: Drawing glitches in NSTableView with variable row hight (just like Console.app)
Re: Drawing glitches in NSTableView with variable row hight (just like Console.app)
- Subject: Re: Drawing glitches in NSTableView with variable row hight (just like Console.app)
- From: Marco Masser <email@hidden>
- Date: Wed, 5 May 2010 13:17:03 +0200
On 28.04.2010, at 12:45, Marco Masser wrote:
>
> On 21.04.2010, at 05:47, Adam R. Maxwell wrote:
>
>>
>> On Apr 19, 2010, at 8:56 AM, Marco Masser wrote:
>>
>>> I'm trying to implement a logging facility for an app that should behave quite the same as OS X's Console.app in terms of displaying the log, i.e. an NSTableView with varying row heights. I got it working so far, but there are major drawing glitches when resizing the window or scrolling through the list.
>>
>> I did this a while ago, and it's working fine. I recall having numerous problems with drawing glitches, but don't remember the details. My code is BSD licensed, and found here:
>>
>> http://code.google.com/p/mactlmgr/source/browse/trunk/TLMLogDataSource.m
>>
>> The key point to fix problems during resize was implementing tableViewColumnDidResize: to invalidate row heights, and caching row heights for performance. I think the TLMLogMessageCell subclass was used to get wrapping behavior similar to that of Apple's Console program.
>>
>> hth,
>> Adam
>>
>
> Sorry for my late answer!
>
> Thanks a lot to all three of you, Jerry, Jens, and Adam.
> I can't test your suggestions right now, but I definitely will. If I won't get satisfactory results with Adam's hint, I think I'll opt for the NSTextView. Anyway, I'll let you know how it worked.
Adam's hint seems to do the trick, thanks a lot!
For posterity: My NSTableView implementation has four methods now, two for the data itself:
-numberOfRowsInTableView:
- tableView:objectValueForTableColumn:row:
... and two for the resizing stuff:
- tableView:heightOfRow: Here, I calculate and cache the row height. For calculation I set a string on my table view's data cell directly and call -cellSizeForBounds: on it.
- tableViewColumnDidResize: Here, the string's size is invalidated.
Here's the my (very app-specific) code for the last two methods, I hope this helps someone at some point:
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
// filteredMessageCache is an NSArray of the log entries currently displayed
LogEntry* logEntry = [filteredMessageCache objectAtIndex:row];
// messageColumn is the NSTableColumn displaying the long strings to be wrapped
CGFloat columnWidth = [messageColumn width];
// My LogEntry class has a messageSize NSSize ivar. It would be prettier if it was not directly in the model class...
NSSize stringSize = logEntry.messageSize;
if (stringSize.width < 0.0)
{
// messageCell is the NSTextFieldCell messageColumn's dataCell
[messageCell setStringValue:logEntry.message];
stringSize = [messageCell cellSizeForBounds:NSMakeRect(0.0, 0.0, FLT_MAX, FLT_MAX)];
logEntry.messageSize = stringSize;
}
CGFloat rowHeight = ceilf(stringSize.width / columnWidth) * [tableView rowHeight];
return MAX(rowHeight, stringSize.height);
}
- (void)tableViewColumnDidResize:(NSNotification *)notification
{
NSSize invalidSize = NSMakeSize(-1.0, -1.0);
// reset the size of all messages. Again, it would be prettier if it was not directly in the model class...
for (LogEntry* logEntry in messageCache)
{
logEntry.messageSize = invalidSize;
}
NSRange allIndexes = NSMakeRange(0, [filteredMessageCache count]);
[logTable noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:allIndexes]];
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden