On Sep 26, 2008, at 10:16 AM, Gerd Knops wrote:


On Sep 25, 2008, at 10:37 PM, Ken Thomases wrote:

On Sep 25, 2008, at 9:18 PM, Graham Cox wrote:

On 26 Sep 2008, at 10:24 am, Gerd Knops wrote:

I would like to use a key other than "tab" to advance to the next text field, so that users can use a numeric keypad to enter something like "11-22-33" and have 11, 22 and 33 end up in different text fields.


I'd suggest not using a different key from 'Tab', since that's very much hardwired into every Mac user.

Alternative, why not just detect when the field has the required number of characters and move to the next field automatically? For numeric entry this is much more user-friendly.

For implementing such a thing, see -[NSWindow selectNextKeyView:].

I know how to do that part. The tricky part is intercepting and filtering the '-' key. given field editors etc.

One approach I tried was to implement -validateValue:forKey:error: and intercept the key values of the fields I am interested in, testing for a '-' as last character, removing it and advancing to the next key field. That works (after setting the involved bindings to 'Continuously updates value' and 'Verify immediately'), but for some odd reason when the '-' character is entered that method is called twice, causing it to skip a field. I hoped to avoid having to also add connections for the individual views so that I can find the next key view for the key field in question, but it seems to be the least bothersome approach at that point.

Thanks

Gerd


I played around and found "a" solution. However I'm not sure if this would be considered an abuse of the formatter/validation architecture :-)

1) Write a custom subclass of NSNumberFormatter and implement isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription :. In it test for the '-' and set the errorDescription to some custom string and return NO. (you could also subclass NSFormatter but you will need to implement three more methods http://developer.apple.com/documentation/Cocoa/Conceptual/DataFormatting/Articles/CreatingACustomFormatter.html )

2) In your controller:
a) Implement control:didFailToValidatePartialString:errorDescription: and test the errorDescription against your custom string. If it matches, call selectKeyViewFollowingView: on your window with the passed in control. b) Implement control:didFailToFormatString:errorDescription: and if you have an empty string set the control to 0

3) In IB (in any order):
a) Add the NSNumberFormatter to your text fields then change the class to your custom class.
        b) Set your controller as the delegate of the text fields.
        c) Set the nextKeyView for each of the text fields.
        d) Bind the values to your model.
        e) You don't need Validates Immediately or Continuous.



//
//  NumberTabForwardFormatter.h
//

#import <Cocoa/Cocoa.h>

@interface NumberTabForwardFormatter : NSNumberFormatter {

}

@end



//
//  NumberTabForwardFormatter.m
//

#import "NumberTabForwardFormatter.h"

@implementation NumberTabForwardFormatter

- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange: (NSRange)origSelRange errorDescription:(NSString **)error
{
// the user has just deleted the last number and we have an empty string
        if (proposedSelRangePtr->location == 0)
                return YES;
        
        // the user can type '-' anywhere in the string, not just at the end
if ([[*partialStringPtr substringWithRange:NSMakeRange(proposedSelRangePtr->location - 1, 1)] isEqualToString:@"-"]) {
                *error = @"Number Tab Forward Formatter Event";
                return NO;
        }
        
// I added this to only allow numbers, you may not need/want it, for example you may want to allow '.' and ',' if (![[NSCharacterSet decimalDigitCharacterSet] characterIsMember: [*partialStringPtr characterAtIndex:proposedSelRangePtr->location - 1]]) {
                *error = nil;
                return NO;
        }
        
        return YES;
}

@end



//
//  AppController.h
//

@interface AppController : NSObject {
        IBOutlet NSWindow *window;
        
        int num1, num2, num3;
}
@property (assign) int num1, num2, num3;

@end



//
//  AppController.m
//

#import "AppController.h"

@implementation AppController
@synthesize num1, num2, num3;

- (void)control:(NSControl *)control didFailToValidatePartialString: (NSString *)string errorDescription:(NSString *)error
{
        if ([error isEqualToString:@"Number Tab Forward Formatter Event"])
                [window selectKeyViewFollowingView:control];
}

- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
{
        if ([string isEqualToString:@""]) {
                [control setIntValue:0];
                return YES;
        }
        NSBeep();
        return NO;
}

@end



Hope that helps,
--Nathan



_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to