I'm implementing the rename/editing function in an NSOutlineView
. The basic implementation is like:
@objc func renameAction() {
let row = outlineView.clickedRow
let rowView = outlineView.view(
atColumn: 0,
row: row,
makeIfNecessary: false) as! NSTableCellView
rowView.textField!.isEditable = true
rowView.window?.makeFirstResponder(rowView.textField!)
}
A mouseDown:
is handled in the NSOutlineView
so that the NSTextField
can quit editing mode when clicking on the row that is being edited.
The idea of using a custom delegate is from this question
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
let localLocation = self.convert(
event.locationInWindow,
from: nil)
let clickedRow = self.row(at: localLocation)
#if DEBUG
print(#file, #line, clickedRow)
#endif
if clickedRow != -1 {
self.extendedDelegate?.didClickRow(clickedRow)
}
}
In the delegate:
func didClickRow(_ row: Int) {
//... get the textField
textField.isEditable = false
textField.resignFirstResponder()
textField.window?.makeFirstResponder(
textField.window?.contentView
)
}
The strange thing is I can right click on an NSTableCellView
(including both an icon and an NSTextField
) to get the context menu before a left click on ANY row. After the left click, I can only get the context menu by right clicking anywhere outside the NSTableCellView
(of any row, no matter it's the clicked one or not) but inside the row (the blank areas surrouding the NSTableCellView
).
Screenshots
Before any left clicking, right clicking on the NSTableCellView
gets the menu:
After a left clicking on any row, right click doesn't work "on" all the NSTableCellView
s, but still works on the blank area of the row.
// No menu upon clicking on the
NSTableCellView
. But the menu will appear when clicking on the blank areas of the row.
Update:
I found that if the overriding mouseDown:
is commented out, (as expected) there's no issue. But that will throw the ability to end editing by clicking on the current row.