感谢到目前为止的所有答案。这是我已经解决的问题,但我担心它的脆弱性。任何改进建议将不胜感激......</p>
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
}
}
}
}