firstResponder and multiple NSTextFields
-
Hi all,
I've got a panel wherein users enter a multi-part
serial number and I'm trying to simplify the process
for them a bit.
As part of that goal, I'd like to have our
registration boxes work a bit more like the one you
see when you install Office, where you can enter one
part of the serial number at a time, with the focus
automatically being set to the next NSTextView when
the right number of characters has been entered.
I've set up an NSFormatter to check the length and
then tell the controller to forward the focus to the
next NSTextView. The NSFormatter is working just fine
and sends the correct message to the controller.
The controller, however, seems very confused.
I'd originally tried:
NSControl *field = (NSControl *)[licenseSheet
firstResponder];
if (field == txtPartialSN1)
but that test always failed. If I did an NSLog of
[field className] it was clearly NSTextView... So, I
tried a slightly different approach, setting the tag
values of each of the serial number text fields:
NSControl *field = (NSControl *)[licenseSheet
firstResponder];
if ([field tag] == 1)
[licenseSheet makeFirstResponder: txtPartialSN2];
Here's where it gets weirder - the [field tag] value
is always -1. Now I'm really confused.
Can anyone offer insight on this? My guess would be
that it has something to do with objects created in
the nib versus at run-time, but I'm not well-versed
enough in that topic to figure it out.
Any help would be appreciated.
Thank you.
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com -
The firstResponder while editing a text field is typically the containing window's field editor.
See Apple's documentation and past discussions on this list about the field editor.
As it happens, while editing a text field, the delegate of the field editor is the field being edited.
You can edit your code as follows:
NSText *fieldEditor = [[licenseSheet firstResponder];
NSControl *field = nil;
if([fieldEditor respondsToSelector:@selector(delegate)])
{
field = [fieldEditor delegate];
}
if (field == txtPartialSN1)
- or-
NSText *fieldEditor = [[licenseSheet firstResponder];
int tag = -1;
if([fieldEditor respondsToSelector:@selector(delegate)])
{
tag = (NSControl *)[[fieldEditor delegate] tag];
}
if (tag == txtPartialSN1)
However, I think that is all unnecessary because I think you can set up your formatter to end editing when the correct number of digits are entered and you can set up the nextField to automatically move to the next field when editing ends. You could also use the controlTextDidEndEditing or some such notification or you could use an action with the text field. Both of these choices avoid having to perform comparisons with the field editor because the field itself is sent as the object of the notification or the sender of the action. -
Hi,
First, thank you. :)> if([fieldEditor
> respondsToSelector:@selector(delegate)])
>
> {
> field = [fieldEditor delegate];
>
> }
> if (field == txtPartialSN1)
Ta-da! That did it! :)>
> However, I think that is all unnecessary because I
> think you can set up your formatter to end editing
> when the correct number of digits are entered and
> you can set up the nextField to automatically move
> to the next field when editing ends.
Ok, fair enough. I do see the nextKeyView, and you're
surely right. However, I don't see how to set it up so
that the user is automatically forwarded when the max
# of characters has been reached. For that matter, I'm
not sure how to get the formatter to prohibit editing.
At the moment, I'm using the isPartialStringValid:
method, but I don't know how I'd explicitly end
editing other than to simply continue to trim any
additional characters the user might try to type
(which I already do).
It sounds like you had something more specific in
mind.
Thanks again!
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com -
Hi.
If the formatter idea doesn't work out, here is another suggestion:
Set your controller class (the window controller for this license
window/sheet) as the delegate of the license textfields.
Have outlets in the controller class to the various textfields that
make up the license fields.
Implement the controlTextDidChange: delegate method.
You could do something like this:
- (void)controlTextDidChange: (NSNotification*)aNotif;
{
id notif_obj = [aNotif object];
if (notif_obj == licenseFieldOne)
{
NSString* val = [notif_obj stringValue];
// Validate the string thus far
// If valid, end editing and go to the next field
[notif_obj resignFirstResponder];
[[notif_obj nextKeyView] becomeFirstResponder]; // If you
set the nextKeyView, otherwise use something like licenseFieldTwo here
}
else if (notif_obj == licenseFieldTwo)
{
// Repeat
}
// Repeat for as many fields as you have
}
I can't remember if the object of the notif is the textfield or the
field editor, you would have to test that. If it is the field editor
Erik's trick for getting the textfield will work.
It assumes that you set the nextKeyView on the textfields to be logical.
Also, I am assuming that different fields in your license string
could have different formats. If not, you could generalize and
remove the messy if chain. And probably get rid of your outlets to
the fields.
I haven't tested this, but I think it should work.
Hope it helps!
Michael.
On 24-Aug-05, at 7:09 PM, Brad Peterson wrote:> Hi,
>
> First, thank you. :)
>
>
>> if([fieldEditor
>> respondsToSelector:@selector(delegate)])
>>
>> {
>> field = [fieldEditor delegate];
>>
>> }
>> if (field == txtPartialSN1)
>>
>
> Ta-da! That did it! :)
>
>
>>
>> However, I think that is all unnecessary because I
>> think you can set up your formatter to end editing
>> when the correct number of digits are entered and
>> you can set up the nextField to automatically move
>> to the next field when editing ends.
>>
>
> Ok, fair enough. I do see the nextKeyView, and you're
> surely right. However, I don't see how to set it up so
> that the user is automatically forwarded when the max
> # of characters has been reached. For that matter, I'm
> not sure how to get the formatter to prohibit editing.
>
>
> At the moment, I'm using the isPartialStringValid:
> method, but I don't know how I'd explicitly end
> editing other than to simply continue to trim any
> additional characters the user might try to type
> (which I already do).
>
> It sounds like you had something more specific in
> mind.
>
> Thanks again!
>
> __________________________________________________
> Do You Yahoo!?
> Tired of spam? Yahoo! Mail has the best spam protection around
> http://mail.yahoo.com
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/mclark.list%
> 40marketcircle.com
>
> This email sent to <mclark.list...>
> -
Doh, brainfart!
Actually, don't do the resign/becomeFirstResponder combo, that is a
no no.
tell the window makeFirstResponder with the next field, and it does
the right thing.
Michael.
On 24-Aug-05, at 11:24 PM, Michael Clark wrote:> Hi.
>
> If the formatter idea doesn't work out, here is another suggestion:
>
> Set your controller class (the window controller for this license
> window/sheet) as the delegate of the license textfields.
> Have outlets in the controller class to the various textfields that
> make up the license fields.
>
> Implement the controlTextDidChange: delegate method.
>
> You could do something like this:
>
> - (void)controlTextDidChange: (NSNotification*)aNotif;
> {
> id notif_obj = [aNotif object];
>
> if (notif_obj == licenseFieldOne)
> {
> NSString* val = [notif_obj stringValue];
> // Validate the string thus far
> // If valid, end editing and go to the next field
> [notif_obj resignFirstResponder];
> [[notif_obj nextKeyView] becomeFirstResponder]; // If you
> set the nextKeyView, otherwise use something like licenseFieldTwo here
> }
> else if (notif_obj == licenseFieldTwo)
> {
> // Repeat
> }
> // Repeat for as many fields as you have
> }
>
> I can't remember if the object of the notif is the textfield or the
> field editor, you would have to test that. If it is the field
> editor Erik's trick for getting the textfield will work.
>
> It assumes that you set the nextKeyView on the textfields to be
> logical.
> Also, I am assuming that different fields in your license string
> could have different formats. If not, you could generalize and
> remove the messy if chain. And probably get rid of your outlets to
> the fields.
>
> I haven't tested this, but I think it should work.
>
> Hope it helps!
> Michael.
>
>
> On 24-Aug-05, at 7:09 PM, Brad Peterson wrote:
>
>
>> Hi,
>>
>> First, thank you. :)
>>
>>
>>
>>> if([fieldEditor
>>> respondsToSelector:@selector(delegate)])
>>>
>>> {
>>> field = [fieldEditor delegate];
>>>
>>> }
>>> if (field == txtPartialSN1)
>>>
>>>
>>
>> Ta-da! That did it! :)
>>
>>
>>
>>>
>>> However, I think that is all unnecessary because I
>>> think you can set up your formatter to end editing
>>> when the correct number of digits are entered and
>>> you can set up the nextField to automatically move
>>> to the next field when editing ends.
>>>
>>>
>>
>> Ok, fair enough. I do see the nextKeyView, and you're
>> surely right. However, I don't see how to set it up so
>> that the user is automatically forwarded when the max
>> # of characters has been reached. For that matter, I'm
>> not sure how to get the formatter to prohibit editing.
>>
>>
>> At the moment, I'm using the isPartialStringValid:
>> method, but I don't know how I'd explicitly end
>> editing other than to simply continue to trim any
>> additional characters the user might try to type
>> (which I already do).
>>
>> It sounds like you had something more specific in
>> mind.
>>
>> Thanks again!
>>
>> __________________________________________________
>> Do You Yahoo!?
>> Tired of spam? Yahoo! Mail has the best spam protection around
>> http://mail.yahoo.com
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Cocoa-dev mailing list (<Cocoa-dev...>)
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/mclark.list%
>> 40marketcircle.com
>>
>> This email sent to <mclark.list...>
>>
>>
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/mclark.list%
> 40marketcircle.com
>
> This email sent to <mclark.list...>
>


