Стилизация 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!

Другие вопросы по тегам