Стилизация NSOutlineView Rows
У меня есть приложение Core Data на основе документов с NSTreeController, предоставляющее контент для представления на основе NSOutlineView. Я "стилизую" (задаю цвет текста, цвет фона и т. Д.) Строки, основанные на постоянных "трансформируемых" атрибутах NSColor и NSFont в моей модели данных, которые конечное использование может изменить. Когда появляется новая строка, она отображает вещи с цветами / шрифтами, установленными в модели данных. Вот код делегата / источника данных, который устанавливает цвет фона строки:
- (void) outlineView:(NSOutlineView *)outlineView
didAddRowView:(NSTableRowView *)rowView
forRow:(NSInteger)row
{
// Get the relevant nodeType which contains the attributes
QVItem *aNode = [[outlineView itemAtRow:row] representedObject];
if (aNode.backColor)
{
rowView.backgroundColor = aNode.backColor;
}
}
Однако когда атрибуты стиля меняются, я хочу, чтобы связанные видимые строки перерисовывались с новыми значениями стиля. Каждый раз, когда атрибут "стиля" изменяется, я использую NSNotificationCenter для отправки уведомления делегату представления Outline с объектом модели, чья строка должна быть перерисована с измененным стилем. Это код в делегате, который получает уведомление.
-(void) styleHasChanged: (NSNotification *)aNotification
{
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:aNotification.object];
[myOutlineView reloadItem:aTreeNode];
}
Мое предположение здесь заключается в том, что я могу перемещаться по контроллеру дерева, чтобы найти узел дерева, который представляет мой объект модели, а затем попросить представление схемы перерисовать строку для этого узла дерева. Это код "дополнения" в контроллере дерева, который обходит дерево, чтобы найти объект - не очень эффективный, но я не думаю, что есть другой способ.
@implementation NSTreeController (QVAdditions)
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject
{
return [self treeNodeForModelObject:aModelObject inNodes:[[self arrangedObjects] childNodes]];
}
- (NSTreeNode *)treeNodeForModelObject:(id)aModelObject inNodes:(NSArray*)nodes
{
for(NSTreeNode* node in nodes)
{
if([node representedObject] == aModelObject)
return node;
if([[node childNodes] count])
{
NSTreeNode * treeNode = [self treeNodeForModelObject:aModelObject inNodes:[node childNodes]];
return treeNode;
}
}
return nil;
}
Так что иногда это работает, и строка перерисовывается, а иногда нет. Метод делегата "styleHasChanged:" всегда вызывается, и контроллер дерева всегда возвращает соответствующий узел дерева (на самом деле подкласса NSTreeNode). Но чаще всего контурный вид не распознает узел дерева, и строка не перерисовывается. Это похоже на то, как контроллер дерева вернул другой объект узла дерева тому, который он давал в виде структуры в прошлом. Но странно, что иногда это работает, и правый ряд перерисовывается новым цветом фона. Если я сверну строку из поля зрения и снова открою ее, она будет перерисована правильно.
Кто-нибудь есть идеи, почему это работает иногда, а не в другие времена?
Было бы неплохо иметь возможность каким-либо образом связать атрибуты цвета / шрифта со строкой и столбцами, чтобы в виде структуры автоматически выполнялась эта стилизация с помощью KVO, но я не думаю, что это возможно, не так ли?
1 ответ
Вы проводите часы / дни, пытаясь понять, что вы сделали неправильно; Вы пишете вопрос; Опубликовать это; Спать на нем; и подумай, как глупо ты можешь быть.
Поэтому я попросил NSTableRowView перерисовать себя, но я не установил новый цвет фона. Итак, вот новая улучшенная (и работает) версия styleHasChanged:
-(void) styleHasChanged: (NSNotification *)aNotification
{
QVItem *modelItem = aNotification.object;
NSTreeNode *aTreeNode = [myTreeController treeNodeForModelObject:modelItem];
NSInteger rowIndex = [myOutlineView rowForItem:aTreeNode];
if !(rowIndex == -1)
{
NSTableRowView *rowViewToBeUpdated = [myOutlineView rowViewAtRow:rowIndex makeIfNecessary:YES];
rowViewToBeUpdated.backgroundColor = modelItem.backColor;
}
}
Duh!