Подсветка выделенных строк в NSPredicateEditor

NSPredicateEditorсуперкласс NSRuleEditor подвергает selectedRowIndexes: IndexSet свойство (и соответствующее selectRowIndexes(IndexSet, byExtendingSelection: Bool) сеттер). Добавление наблюдателя к этому свойству показывает, что оно действительно изменяется при каждом щелчке строки в редакторе предикатов. Тем не менее, нет визуальной индикации того, что строка выбрана или отменена.

Я хотел бы визуально выделить выбранные строки в моем редакторе предикатов, но практически нет методов рисования представления для подкласса или делегирования методов для реализации для настройки внешнего вида редактора. Кто-нибудь может предложить какой-то способ донести до использования, что строки редактора правил были выбраны?

3 ответа

В классе NSPredicateEditorRowTemplate вы найдете свойство с именем templateViews Как упомянуто в документации от Apple, вы можете переопределить это, чтобы вернуть дополнительные представления. Вернуть дополнительный вид и использовать его в качестве индикатора для выбора.

/ * возвращает список представлений, размещенных в строке. NSPopUpButtons обрабатываются специально тем, что элементы нескольких шаблонов объединяются вместе; другие виды добавляются как есть. Разработчики могут переопределить это, чтобы возвращать представления в дополнение к представлениям по умолчанию или вместо них. */

Я настроил NSPredicateEditorRowTemplate несколько лет назад для реализации элемента управления рейтингом Star, но мне пришлось бы искать код и то, как это было точно сделано.

Надеюсь это поможет.

Спасибо за все ответы до сих пор. На этом я остановился, но меня беспокоит хрупкость. Любые предложения по улучшению будут оценены...

class RowHighlightingRuleEdtitor : NSRuleEditor {
    var highlightsSelectedRow: Bool = true

    override func didChangeValue(forKey key: String) {
        super.didChangeValue(forKey: key)
        if key == "selectedRowIndexes" {
            // Whenever we change the selection, re-layout the view.
            self.needsLayout = true
        }
    }

    override func layout() {
        super.layout()
        if !highlightsSelectedRow { return }
        let selected = self.selectedRowIndexes

        // Of all the fragile ways to check if the view is a row, checking the class name is the easiest.
        // Possible alternative solution: check for the existence of the add-new-row button.
        func viewIsEditorRow(_ view: NSView) -> Bool { return view.className == "NSRuleEditorViewSliceRow" }

        // Sorting must be done because the order of the rows does not necessarily correspond to the order of the subviews.
        // NSRuleEditorViewSliceRow's superclass NSRuleEditorViewSlice has a rowIndex property, but it is private
        // Possible alternative solution: use valueForKey("rowIndex") to get the index
        func rowOrder(lhs: NSView, rhs: NSView) -> Bool { return lhs.frame.origin.y < rhs.frame.origin.y }

        // subview is NSRuleEditorViewSliceHolder and holds NSBannerView and NSRuleEditorViewSliceRow instances
        for (index, rowView) in subviews.flatMap({ $0.subviews }).filter(viewIsEditorRow).sorted(by: rowOrder).enumerated() {
            if selected.contains(index) {
                // we use *secondary*SelectedControlColor because the rule editor comonent is not actually focusable
                rowView.layer?.backgroundColor = NSColor.secondarySelectedControlColor.cgColor
            } else {
                rowView.layer?.backgroundColor = nil
            }
        }
    }
}

Недокументированный и хакерский, протестирован с NSRuleEditor: Наблюдайте за изменениями выделения и устанавливайте цвет фона срезов строк. Создать категорию на NSRuleEditorViewSliceRow и реализовать drawRect:, Например

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
    change:(NSDictionary *)change context:(void *)context {
    if (context != &myRuleEditorObservingContext)
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    else
    {
        // backgroundColor is a property or ivar of NSRuleEditorViewSlice and subclass NSRuleEditorViewSliceRow
        NSArray *slices = [ruleEditor valueForKey:@"slices"];
        [slices makeObjectsPerformSelector:@selector(setBackgroundColor:) withObject:nil];
        NSArray *selectedSlices = [slices objectsAtIndexes:[ruleEditor selectedRowIndexes]];
        [selectedSlices makeObjectsPerformSelector:@selector(setBackgroundColor:) withObject:[NSColor selectedControlColor]];
    }
}


@interface NSRuleEditorViewSliceRow : NSObject

@end

@interface NSRuleEditorViewSliceRow(Draw)

@end

@implementation NSRuleEditorViewSliceRow(Draw)

- (void)drawRect:(NSRect)dirtyRect {
    NSColor *aColor = [(id)self backgroundColor];
    if (aColor) {
        [aColor set];
        NSRectFill(dirtyRect);
    }
}

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