NSTableViewDelegate SelectionDidChange and getting notified when clicked again - cocoa

I'm using the SelectionDidChange form NSTableViewDelegate to alter some data based on the selection and then have the NSTableView reload it again (which will alter the cell's custom control state).
This works great, but I cannot get any notification when clicking a row that is already selected.
I would need something like a "SelectionDidNotChange".
Anyone?

Related

Receive trigger when active NSView focus changes

I'm surprised that I haven't been able to find an answer for this from searching. So if there is a page describing how to do this, let me know, but I've been unable to find it.
I have 3 sibling NSOutlineViews all inside an NSSplitView I have added observers for NSOutlineViewSelectionDidChange which, when triggered update an NSTextView editor. I even test for negative row values to indicate that the user has unselected the row and clear the text.
The NSOutlineViews are connected to custom datasource objects and the NSSplitView is created by my custom NSWindowController in turn created by my custom NSDocument and custom NSDocumentController (I'm not using .nibs)
However I cannot seem to receive triggers for the NSOutlineViews changing their active status, it works if the user selects a different row in a different NSOutlineView, as the selection has changed but if they click the selected row of a different view, I don't receive any event or notification that anything has changed. Visually I can see the change as the row selection highlight colour changes from coloured to grey, in the outline view that has lost focus and the selection row colour changes from grey to coloured in the newly activated view.
I've tried to catch mouseDown events, tried becoming first responder, tried observing changes in the NSSplitView I've been right through the NSObject hierarchy from NSOutlineView to NSResponder looking for the appropriate notification or method. I found deprecated documentation regarding a focus change notification. I've tried combinations of nsview, nsnotification, nsoutlineview and various actions in google but can't find the 'this is how you do it'
EDIT:
this is the code I've added to my NSOutlineView subclass (along with prototypes in the headers) to become first responder, but it is never triggered.
- (BOOL)acceptsFirstResponder { return YES; }
- (BOOL)becomeFirstResponder {
NSLog(#"becomefirstResponder %#",self);
return YES;
}

Preselect a row in NSOutlineView

My app contains an NSOutlineView. When the user quits the app a reference to the selected row is stored in user defaults and I would like to use this to preselect the same row when they next run the app. I know the method is selectRowIndexes:byExtendingSelection: but I can't find out when to call it - the table is not yet populated in awakeFromNib but I don't know how I can tell when it has happened. I really don't want to just wait an arbitrary time - is there some notification or callback I can use?
The answer was to populate the outline view in awakeFromNib and then select the row in applicationDidFinishLaunching: in the app delegate.

How to get notified of clicks in a view-based NSTableView

I have a view-based NSTableView containing a list of words. When the user double-clicks on a word, I would like to take an action. The words are not editable or selectable. How do I do this?
I have tried setting the target and action of the table view in IB, but it only calls the action method when the user clicks in the header of the table, not in one of the words.
I have tried setting the target and action of the NSTextField that the table cell view keeps in IB. This results in this error message being repeated in the console:
2018-01-02 14:14:32.080347-0800 WordExplorer[7089:21457459] Could not connect action, target class NSObject does not respond to -relatedWordClick:
However the target class does respond to the selector. (I connected it in IB directly, so clearly, it does!) It is also not a simple NSObject, so I'm guessing that something else is going wrong there.
I have tried manually calling -setTarget: and -setAction: on the NSTextField contained in the table cell view in my delegate's -tableView:viewForTableColumn:row: method. This has no effect, and the debugger shows that despite calling those methods, they do not set the text field's action or target method. (Though, given this is Xcode we're talking about, it's likely that's just a debugger display issue.) I get no errors in the console like when I make the connection in IB, but it also does not call the appropriate method.
Do I need to make custom view class and use that for the table cell view? Or is there a simpler way to get clicks (and preferably double-clicks) on words in my list?
Simply create an IBAction on the object you have as the NSTableView's target, and then set the NSTableView's doubleAction property to the selector for that IBAction, and you can handle double-click events easily.

NSResponder and multiple NSTableView - who sent message?

I've got two NSTableView in a single NSViewController, and each has their own NSArrayController to handle what exists. I'm now trying to wire up the Edit->Delete button. How do I know, when the delete method is called, 'who' sent that message?
Specifically I want to know whether I was clicked into the first table view or the second one when I then chose the Delete menu item. The 'sender' to the delete method is just the NSMenuItem so I can't back-track that to the table.
Get firstResponder of the window and follow nextResponder until you find a table view.

Make NSTableView cells editable programmatically only

How to configure a view-based NSTableView to behave like so:
Rows are selectable
The user are unable to trigger edit mode by clicking a cell
Edit mode can be triggered by calling NSTableView-editColumn:row:withEvent:select: programmatically
The table view is dragged from the object library of Xcode interface builder, i.e., it uses an NSTableCellView (with an NSImageView and an NSTextField as its subviews) as the table view's cell view.
For view-based table views, -editColumn:row:withEvent:select: is relatively ineffective. It attempts to make the cell view the first responder for the window, but only certain views will accept first responder status. NSTableCellView does not, because it is not itself editable.
If you want to programmatically initiate editing in the text field within an NSTableCellView, you can do something like:
NSTableCellView* cellView = (NSTableCellView*)[tableView viewAtColumn:col row:row makeIfNecessary:YES];
if ([cellView.textField acceptsFirstResponder])
[cellView.window makeFirstResponder:cellView.textField];
To disable the user from starting editing through the UI, I think you will need to set the text field to not be editable. You would make it editable just before you initiate editing programmatically. For example, add a line cellView.textField.editable = YES; between the above two lines.
Then, you'll want to set it back to non-editable after editing ends. To do this, you can set the delegate of the text field to your controller object and implement -controlTextDidEndEditing:. Or, similarly, you can add an observer of the NSControlTextDidEndEditingNotification notification from the text field. Either way, when your code is called, you set the text field's editable property back to false. (If you don't otherwise have a reference to the text field in question, you can obtain it from the NSNotification's object property.)

Resources