Tokenfield blues (literally)

  • Hi!

    I'm struggling with some weird behaviour with NSTokenfield. I have my
    own token subclass and everythings works fine starting with an empty
    tokenfield. Also when I set the tokenfield's objectvalue to an array
    with say three previously stored tokens, they show up nicely. BUT,
    when I try to type in between one of these tokens  I have some weird
    behaviour where each single letter becomes instantly a new token. If I
    type before the first or after the last token it works as it should
    and only creates new tokens upon a return or when it hits a tokenizing
    character. Has any one run into similar problems? What could force
    each character into a single token, but only when typing in between
    two other tokens? Any help is greatly appreciated!
    Alex
  • How about the code used for your token subclass? How about a bit
    more information on exactly how you've configured your NSTokenField?

    --
    I.S.

    On Oct 20, 2006, at 8:42 PM, Alexander Griekspoor wrote:

    > Hi!
    >
    > I'm struggling with some weird behaviour with NSTokenfield. I have my
    > own token subclass and everythings works fine starting with an empty
    > tokenfield. Also when I set the tokenfield's objectvalue to an array
    > with say three previously stored tokens, they show up nicely. BUT,
    > when I try to type in between one of these tokens  I have some weird
    > behaviour where each single letter becomes instantly a new token. If I
    > type before the first or after the last token it works as it should
    > and only creates new tokens upon a return or when it hits a tokenizing
    > character. Has any one run into similar problems? What could force
    > each character into a single token, but only when typing in between
    > two other tokens? Any help is greatly appreciated!
    > Alex
    > _______________________________________________
    > 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/idiotsavant2005%
    > 40gmail.com
    >
    > This email sent to <idiotsavant2005...>
  • Sorry for that, indeed a bit cryptic like this. I'd hoped someone
    would recognize already the situation where you just type in your
    tokenfield and each character turns into a token.

    So I have a very simple custom token class called MTPersonToken,
    it has the getters and setters for 3 NSString variables (firstname,
    initials, lastname)
    and only one additional method:

    - (NSString *)displayString{
    if([self firstname])
      return [NSString stringWithFormat: @"%@ %@", initials, lastname];

    return [self lastname];
    }

    Then my tokenfield is configured in awakeFromNib from my custom
    windowcontroller as follows:

    personField = [[RaisedEditingTokenField alloc] initWithFrame:
    NSMakeRect(10.0, 10.0, 100.0, 16.0)];
    [personField setFont: [NSFont systemFontOfSize: 10]];
    [personField setDrawsBackground: NO];
    [personField setBordered: NO];
    [personField setDelegate: self];

    [[personField cell] setWraps: YES];
    [[personField cell] setFocusRingType: NSFocusRingTypeNone];
    [[personField cell] setControlSize: NSSmallControlSize];
    [[personField cell] setPlaceholderAttributedString:
    [[[NSAttributedString alloc] initWithString: @"Persons (Lastname,
    Firstnames)" attributes:
      [NSDictionary dictionaryWithObjectsAndKeys: [NSColor grayColor],
    NSForegroundColorAttributeName, nil]] autorelease]];
    [[personField cell] setTokenStyle: NSRoundedTokenStyle];
    [[personField cell] setTokenizingCharacterSet: [NSCharacterSet
    characterSetWithCharactersInString: @";"]];

    And finally the relevant delegate methods:

    - (NSArray *)tokenField:(NSTokenField *)tokenField
    shouldAddObjects:(NSArray *)_tokens atIndex:(unsigned)index
    {
    return _tokens;
    }

    - (NSString *)tokenField:(NSTokenField *)tokenField
    displayStringForRepresentedObject:(id)representedObject
    {
    NSString* string;
    if ([representedObject isKindOfClass: [MTPersonToken class]]) {
      MTPersonToken* token = representedObject;
      string = [token displayString];
    }
    else
      string = representedObject;
    return string;
    }

    -(id)tokenField:(NSTokenField *)tokenField
    representedObjectForEditingString:(NSString *)editingString{
          // Names can be entered either as "Griekspoor, Alexander C" or
    "Alexander Griekspoor" Here I filter the first and last name out
    NSString *lastname = nil;
    NSMutableString *initials = nil;
    NSMutableString *firstname = nil;
    // FILTER WEIRD THINGS FIRST
    NSArray *components = [editingString componentsSeparatedByString:@","];

    if([components count] > 1){
      lastname = [components objectAtIndex: 0];
      NSString *firstnames = [editingString substringFromIndex: [lastname length]];
      firstnames = [firstnames stringByTrimmingCharactersInSet:
    [NSCharacterSet characterSetWithCharactersInString:@"?!., "]];
      // separate by space in different firstnames
      NSString *name;
      NSEnumerator *e = [[firstnames componentsSeparatedByString:@"
    "]objectEnumerator];
      while(name = [e nextObject]){
      if(!initials) initials = [NSMutableString stringWithCapacity: 10];
      if(!firstname) firstname = [NSMutableString stringWithCapacity: 100];
      if([firstname length] > 0)[firstname appendString: @" "];
      [firstname appendString: name];
      [initials appendString: [name substringToIndex: 1]];
      }
    }
    else if([components count] == 1){
      components = [editingString componentsSeparatedByString:@" "];
      if([components count] > 1){
      lastname = [components lastObject];
      NSString *name;
      int i;
      for(i=0; i<[components count]-1; i++){
        name = [components objectAtIndex: i];
        if(!initials) initials = [NSMutableString stringWithCapacity: 10];
        if(!firstname) firstname = [NSMutableString stringWithCapacity: 100];
        if([firstname length] > 0)[firstname appendString: @" "];
        [firstname appendString: name];
        [initials appendString: [name substringToIndex: 1]];
      }
      }
      else if([components count] == 1){
      lastname = [components objectAtIndex: 0];
      }
    }

    MTPersonToken* token = [[MTPersonToken alloc]initWithLastname: lastname
                  firstname: firstname
                                                            initials: initials];

    return [token autorelease];
    }

    - (NSString *)tokenField:(NSTokenField *)tokenField
    editingStringForRepresentedObject:(id)representedObject
    {
    NSString* string;
    if ([representedObject isKindOfClass: [MTPersonToken class]]) {
      string = [representedObject displayString];
    }
    else
      string = representedObject;
    return string;
    }

    - (NSTokenStyle)tokenField:(NSTokenField *)tokenField
    styleForRepresentedObject:(id)representedObject
    {
    if ([representedObject isKindOfClass: [MTPersonToken class]])
      return NSRoundedTokenStyle;
    return NSPlainTextTokenStyle;
    }

    - (BOOL)tokenField:(NSTokenField *)tokenField
    hasMenuForRepresentedObject:(id)representedObject
    {
    return NO;
    }

    So as said, everything is fine in an empty NSTokenField, if I then
    populate the field with let say two saved tokens and try to type in
    between the two to create a third token each letter turns into a
    token, instead of after hitting a tokenizing character.

    Also, is there any way to turn a token back into the editing string?
    Double click doesn't seem to work, and more people on the list asked
    this without getting an answer. What I don't get is why you would have
    this method then?!
    - (NSString *)tokenField:(NSTokenField *)tokenField
    editingStringForRepresentedObject:(id)representedObject;
    One thing I could think of is by having a menu item with an edit menu
    item, then you would know the token who send the action, and kind of
    do the reversal yourself perhaps, still it shouldn't work this way and
    it feels like I'm overlooking something.
    Many thanks getting back on my question.
    Cheers,
    Alex

    On 10/21/06, I. Savant <idiotsavant2005...> wrote:
    >
    > How about the code used for your token subclass? How about a bit
    > more information on exactly how you've configured your NSTokenField?
    >
    > --
    > I.S.
    >
    >
    > On Oct 20, 2006, at 8:42 PM, Alexander Griekspoor wrote:
    >
    >> Hi!
    >>
    >> I'm struggling with some weird behaviour with NSTokenfield. I have my
    >> own token subclass and everythings works fine starting with an empty
    >> tokenfield. Also when I set the tokenfield's objectvalue to an array
    >> with say three previously stored tokens, they show up nicely. BUT,
    >> when I try to type in between one of these tokens  I have some weird
    >> behaviour where each single letter becomes instantly a new token. If I
    >> type before the first or after the last token it works as it should
    >> and only creates new tokens upon a return or when it hits a tokenizing
    >> character. Has any one run into similar problems? What could force
    >> each character into a single token, but only when typing in between
    >> two other tokens? Any help is greatly appreciated!
    >> Alex
    >> _______________________________________________
    >> 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/idiotsavant2005%
    >> 40gmail.com
    >>
    >> This email sent to <idiotsavant2005...>
    >
    >
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today