Rafa Febrer
Rafa Febrer

Reputation: 184

NSTableView, making it user-friendly

I have a NSTableView View-Based that have editable rows, but just allow the edition if the user clicks on the text, not on the rest of the cell. (see the image)

Does somebody know how can I make editable the entire cell, not just the zone of the cell that display text?

TableView

The cell

Upvotes: 1

Views: 285

Answers (1)

Ken Thomases
Ken Thomases

Reputation: 90571

I believe I understand what's going on.

First, can you confirm that when the text field is actually being edited, that the focus ring encompasses the whole table cell? It's not just tight around the actual current text, right?

If it encompasses the whole table cell, then that confirms that the constraints are stretching it to fill the table cell rather than the text field hugging its content. In other words, I'm trying to confirm that the "Not Editable" arrow in your image actually does point to a part of the text field. I expect it does.

So, with that out of the way, the problem is how NSTableView manages clicks and whether or not they set the clicked-on view as the first responder. From Table View Programming Guide for Mac: Enabling Row Selection and User Actions – Specifying How Subviews Should Respond to Events, we learn that the table view implements special logic in an override of validateProposedFirstResponder(_:forEvent:):

The default NSTableView implementation of validateProposedFirstResponder:forEvent: uses the following logic:

  1. Return YES for all proposed first responder views unless they are instances or subclasses of NSControl.

  2. Determine whether the proposed first responder is an NSControl instance or subclass.

    • If the control is an NSButton object, return YES.

    • If the control is not an NSButton, call the control’s hitTestForEvent:inRect:ofView: to see whether the hit area is trackable (that is, NSCellHitTrackableArea) or is an editable text area (that is, NSCellHitEditableTextArea), and return the appropriate value. Note that if a text area is hit, NSTableView also delays the first responder action.

I have implemented a custom subclass of NSTextFieldCell. The only thing it does is override hitTestForEvent(_:inRect:ofView:) to call through to super, log the result, and return it. I then set the text field in a table cell view to use that custom class for its cell. From that, I learned that clicking in the empty area of the text field results in .None. Clicking on actual text results in .ContentArea | .EditableTextArea.

The first result does not cause NSTableView's implementation of validateProposedFirstResponder(_:forEvent:) to allow the proposed first responder to actually be made first responder. The latter result does.

So, you could implement your own subclass of NSTextFieldCell which overrides hitTestForEvent(_:inRect:ofView:). In your override, you'd call through to super. If the result is .None, you'd change it to .ContentArea | .EditableTextArea before returning it. Then, use that custom cell class for the text fields in your table.

Alternatively you could try to tackle this by using a custom subclass of NSTableView that overrides validateProposedFirstResponder(_:forEvent:). The problem is that it's not straightforward to reimplement the logic of that method except which hit-test codes it responds to.

Upvotes: 1

Related Questions