CPTextField + Bindings: textDidEndEditing sent too late when controller selection changes [+1] #1435

Open
Toxe opened this Issue Jan 19, 2012 · 13 comments

Comments

Projects
None yet
7 participants

Toxe commented Jan 19, 2012

Application setup

a CPArrayController that stores a couple of simple objects
a CPTableView with one column
the table column values are bound to the arrangedObjects of the array controller
a CPTextField
the "value" binding of the text field is bound to a key path of the controller, "selection.translations.en" in this case
If you select an entry from the table the value of the text field changes as well. This is all very basic stuff and nothing fancy as you can see in this screenshot.

The problem

If I enter text into the text field and then select another table entry the textDidEndEditing notification is sent after the selection changed. The consequence is that the newly entered value wont be saved. Let's have a look at some log output:

(1) info: textDidFocus
(2) info: insertText 1info: textDidBeginEditinginfo: textDidChangeinfo: insertText 2info: textDidChangeinfo: insertText 3info: textDidChange
(3) info: (Controller) setValue:[number of indexes: 1 (in 1 range), indexes: (2)] forKeyPath:selectionIndexes
(4) info: setObjectValue:MPEG Video
(5) info: textDidEndEditing
(6) info: (Controller) setValue:MPEG Video forKeyPath:selection.translations.eninfo: (Controller) setValue:MPEG Video forKeyPath:selection.translations.en
(7) info: textDidBlur

I clicked into the text field to start typing.
I started typing 1, 2 and 3 and we see the textDidBeginEditing and textDidChange notifications.
I clicked on another table entry and the controller selection changes.
The value of the newly selected table entry is written into the text field. This overwrites our 123 text we just entered.
Finally the text field receives its textDidEndEditing notification.
Now that the text field believes that editing has ended it informes the controller and sends it what the text field believes to be the newly entered text.
The text field loses its input focus.
See the problem? The text field sends the wrong value to the controller. It should send 123, but instead it sent MPEG Video, which is the text of the newly selected table element.

The textDidEndEditing and textDidBlur notifications should probably be sent right before or after step (3), where the controller changes its selection.

Note that if I enter the text into the text field and instead of selecting a new table entry I simply press enter or click right outside of the text field everything works fine.

Workaround

A simple workaround that seems to work fine in this case was that I subclass CPTextField and overwrite textDidChange: and after every entered character manually send a textDidEndEditing notification.

(void)textDidChange:(CPNotification)note
{
CPLog(@"textDidChange");
[super textDidChange:note];
if (_isEditing) {
_isEditing = NO;
[self textDidEndEditing:[CPNotification notificationWithName:CPControlTextDidEndEditingNotification object:self userInfo:nil]];
}
}

As you can see in the following log output the controller gets notified of the new value immediately. Still the textDidBlur is sent way too late, I suppose.

info: insertText 1

info: (Controller) setValue:1 forKeyPath:selection.translations.en

info: insertText 2

info: (Controller) setValue:12 forKeyPath:selection.translations.en

info: insertText 3

info: (Controller) setValue:123 forKeyPath:selection.translations.en

info: (Controller) setValue:[number of indexes: 1 (in 1 range), indexes: (1)] forKeyPath:selectionIndexesinfo: setObjectValue:MPEG-4 Video

Contributor

cacaodev commented Feb 6, 2012

If you turn on the CPContinouslyUpdateBindingOption on the controller side and setContinous: on the view side, does is solve the problem ? Changes should be already committed when you end editing.
Or if you send the textfield action on enter only, the controller discards changes.

It seems to me this bug only occurs if the changes in the controller and the view are triggered by the same event.

The solution if we want to solve this is to implement the NSEditor and NSEditorRegistration protocol. Doesn't seem very complex but if the bug occurs only for one (*) control, and theses conditions, i don't know if it's a priority.

(*) would it help for others editable and bindings-compatible controls like CPTableView ?

Contributor

daboe01 commented Mar 11, 2012

i just stumbled across the same problem.
the CPContinouslyUpdateBindingOption set to "1" did not help.
any hint towards the locations in the capp-source tree for fixing it the quick and dirty way?
many thanks and best greetings,
daniel

Toxe commented Mar 19, 2012

Just want to note out that the workaround I posted above in my original post does not work in practice. If you want to type in text somewhere inside allready existing text the cursor would jump immediately to the end of the text field after the first entered character.

For example if the text field contains the text "Hello world!" and you want to insert the text "nice" right in front of "world" you would get the following:

"Hello world!"
"Hello nworld!"     <-- entered 'n'
"Hello nworld!i"    <-- entered 'i'
"Hello nworld!ic"   <-- entered 'c'
"Hello nworld!ice"  <-- entered 'e'
Contributor

cacaodev commented Mar 20, 2012

I think they are 2 different bugs/missing feature here.

The original issue seems related to the lack of CPEditorRegistration protocol. In this case, the controller should commit pending changes before changing the selection.

The "cursor jumping at the end" is just an effect of #1463 and is not related to the CPContinuouslyUpdateOption and affects all controls.
Sorry if I brought the confusion by suggesting to try this CPContinuouslyUpdateOption.

Toxe commented Mar 20, 2012

Nah its fine, I tried the ContinuouslyUpdate Option in my application a couple of weeks before and for some reason it didn't seem to work so I had to find a workaround. Finally had the time to revisit this problem yesterday and the binding option worked as intended, so thanks for the input. Only problem was with the jumping cursor.

@ghost ghost assigned boucher Mar 30, 2012

Contributor

stewa commented Apr 24, 2012

I noticed that the table view becomes firs responder after changing the selection
(see https://groups.google.com/d/msg/objectivej/_TIxbShwXZ0/Dt1NopT2jo8J ).
and CPTextField doesn't update bindings until resigning first responder. Is this correct behaviour for CPTableView?
cocoadev talks about NSEditorRegistration as a possible solution in the mentioned post.

cappbot commented May 9, 2012

Labels: #accepted, #needs-patch, AppKit, bindings, bug. What's next? This issue needs a volunteer to write and submit code to address it.

stewa added a commit to stewa/cappuccino that referenced this issue May 10, 2012

Owner

aljungberg commented Aug 1, 2012

Note that the changes in #1530 have been changed.

It seems like this issue has not been updated for quite a while. Is it still a problem or should we go ahead and close it?

+#needs-unit-test

cappbot commented Aug 2, 2012

Labels: #accepted, #needs-patch, #needs-unit-test, AppKit, bindings, bug. What's next?

  • This issue needs a volunteer to write and submit code to address it.
  • This issue needs a volunteer to write and submit one or more unit tests execercising the changes and/or the relevant parts of the original problem.

cappbot commented Feb 17, 2013

Milestone: Someday. Labels: #accepted, #needs-patch, #needs-unit-test, AppKit, bindings, bug. What's next?

  • This issue needs a volunteer to write and submit one or more unit tests execercising the changes and/or the relevant parts of the original problem.
  • This issue needs a volunteer to write and submit code to address it.
Contributor

daboe01 commented Sep 25, 2013

the issue is still present in the latest master.
i remember that it had been fixed in between.

Contributor

daboe01 commented Sep 26, 2013

+1

cappbot commented Sep 26, 2013

Milestone: Someday. Vote: 1. Labels: #accepted, #needs-patch, #needs-unit-test, AppKit, bindings, bug. What's next?

  • This issue needs a volunteer to write and submit one or more unit tests execercising the changes and/or the relevant parts of the original problem.
  • This issue needs a volunteer to write and submit code to address it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment