Выделение выделенных строк в NSPredicateEditor - PullRequest
0 голосов
/ 03 ноября 2018

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

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

Ответы [ 3 ]

0 голосов
/ 03 ноября 2018

Недокументированный и хакерский, протестирован с 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
0 голосов
/ 03 ноября 2018

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

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
            }
        }
    }
}
0 голосов
/ 03 ноября 2018

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

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

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

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

...