Wrong placeholder string in CPTextField when using bindings

93 views
Skip to first unread message

Stefan Wallström

unread,
Apr 9, 2012, 2:09:21 PM4/9/12
to objec...@googlegroups.com
Hi!

I just noticed that if you bind the value of a CPTextField to an array controller you can get the wrong placeholder string under some circumstances: If you at some point get any other placeholder string than the null placeholder it never switches back to the null placeholder. The placeholder is correct up until that point.

You can try this with the Test/Manual/ArrayController1 test.
Change any name to the empty string and select both rows. The placeholder for the "Selected Name" field will be "Multiple Values". Then select only the row with the empty name and the placeholder will remain the same. Same thing with the "No Selection Placeholder" if you change the app to allow no selected rows.

Below is a suggested patch for CPTextField.j , but I'm not sure it's correct. Maybe CPObjectController.j should be fixed instead?

Cheers,
Stefan

diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j
index 153d4a7..fa742b5 100644
--- a/AppKit/CPTextField.j
+++ b/AppKit/CPTextField.j
@@ -1537,6 +1537,7 @@ var CPTextFieldIsEditableKey            = "CPTextFieldIsEditableKey",
     else
     {
         newValue = [self transformValue:newValue withOptions:options];
+        [_source setPlaceholderString:[self _placeholderForMarker:CPNullMarker]];
         [_source setObjectValue:newValue];
     }
 }

Aparajita Fishman

unread,
Apr 9, 2012, 3:57:22 PM4/9/12
to objec...@googlegroups.com
Stefan,

Thanks for looking into this. Can you please file a ticket and/or make a pull request on github? That will allow us to track it.

> --
> You received this message because you are subscribed to the Google Groups "Cappuccino & Objective-J" group.
> To view this discussion on the web visit https://groups.google.com/d/msg/objectivej/-/icrq5YNdiQwJ.
> To post to this group, send email to objec...@googlegroups.com.
> To unsubscribe from this group, send email to objectivej+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/objectivej?hl=en.

Regards,

Aparajita

Stefan Wallström

unread,
Apr 11, 2012, 2:28:12 AM4/11/12
to objec...@googlegroups.com


Den måndagen den 9:e april 2012 kl. 21:57:22 UTC+2 skrev Aparajita Fishman:
Stefan,

Thanks for looking into this. Can you please file a ticket and/or make a pull request on github? That will allow us to track it.


Filed as Issue #1499

Stefan Wallström

unread,
Apr 18, 2012, 7:21:38 AM4/18/12
to objec...@googlegroups.com
I noticed some another problem which I'm not sure is related or not.
It can also be seen in the ArrayController1 test case.

Say you want to change the price of many rows. You select them all and then tabs thought the fields to get to price. It then clears all name properties. Turns out the reverse bindings kicks in even though the text field isn't edited.

It's not just a problem with multiple selections. If you select just one row and activate the name field and tab out of it, you can see that it calls the setter of "Item". Can easily be seen by adding
- (void)setName:(CPString)newName {
  name = newName;
  CPLog.trace('setting name');
}
to  the Item class.

Cocoa does not do this. Setters are not called unless you actually changed something in the text field. Special case: if the field has a multiple selection marker you can get it to call the setter with the empty string by typing anything and then clearing the field again.

I have no idea where the problem is though. Should CPControl not call the reverse binding stuff or should the binding stuff not call the setter if the value hasn't changed?


Stefan Wallström

unread,
Apr 18, 2012, 2:26:41 PM4/18/12
to objec...@googlegroups.com
One more strange thing observed in ArrayController1:

If you select a row and start editing a field and than select another row in the table without clicking anywhere else first (or tabbing out of the field) , the change is lost. Does not happen in Cocoa.

Stefan Wallström

unread,
Apr 18, 2012, 4:14:17 PM4/18/12
to objec...@googlegroups.com
Turns out the table view updates it's selection indices before becoming first responder. When the table view becomes first responder the text field resigns first responder and triggers _reverseSetBinding, but then the selection is already changed so it's the new row's unchanged value that is updated.

In CPTableView.j I moved
[[self window] makeFirstResponder:self];
in
- (BOOL)startTrackingAt:(CGPoint)aPoint
from the end of the method to the top and that seems to make it work better.

But shouldn't the return value from makeFirstReponder be checked since the current first responder can refuse giving up?

cacaodev

unread,
Apr 19, 2012, 10:39:35 AM4/19/12
to objec...@googlegroups.com
This looks like https://github.com/cappuccino/cappuccino/issues/1435. You can discuss it there.
For me the solution is to have something similar to the NSEditorRegistration: when we edit a control, the binder should mark it as dirty. Then in setSelectionIndexes: we commit all pending changes to the controller very early.

cacaodev

unread,
Apr 19, 2012, 10:47:24 AM4/19/12
to objec...@googlegroups.com
That's definitely a bug. Can you open an issue for this with a reduction , or even better a ojunit test.
It seems easy to fix but we need to find the right place to handle it. Maybe not in CPControl because we should be able to commit again the same value.

Stefan Wallström

unread,
Apr 24, 2012, 7:07:17 AM4/24/12
to objec...@googlegroups.com

Opened Issue #1514
Reply all
Reply to author
Forward
0 new messages