Rectangle 27 0

What you see in Mail.app is not an actual NSMenu (Apple cheats, shocking!). Turns out, it's actually a custom NSTextField linked to an NSTableView stuck in a transparent window.

It's a fairly old trick to get around the extremely poor version of scrollWheel: NSMenu happens to have implemented. MTTokenField is a mature alternative to pulling your hair out trying to stick a scroll view in an NSMenu.

I conformed your Mail.app with Accessibility Inspector and also with RAFT. I liked the answer, but still NSTokenField problem exists.... raised a radar for that.

objective c - NSTokenField selection list shows empty space while scro...

objective-c osx cocoa nstokenfield
Rectangle 27 0

2011-03-09 14:52:48.888 StackOverflowTesting[27789:a0f] completionsForSubstring: m
2011-03-09 14:52:49.242 StackOverflowTesting[27789:a0f] completionsForSubstring: ma
2011-03-09 14:52:49.560 StackOverflowTesting[27789:a0f] completionsForSubstring: mak
2011-03-09 14:52:49.911 StackOverflowTesting[27789:a0f] completionsForSubstring: maks
2011-03-09 14:52:50.017 StackOverflowTesting[27789:a0f] completionsForSubstring: maksi
2011-03-09 14:52:50.217 StackOverflowTesting[27789:a0f] completionsForSubstring: maksim
2011-03-09 14:52:50.647 StackOverflowTesting[27789:a0f] representedObjectForEditingString: maksim

Which is exactly what'd I'd expect as the output. Have you changed the default tokenizing characters of the NSTokenField? When you hit the tokenizing character, it doesn't look like it tokenized maksim (since after all, you were able to delete it character by character).

Thanks Stephen. I just tried to place in interface another new token field and connect it to delegate, and then a got the same log as you. So i found what was a problem. Old token field was binded to array controller (value binding) .

objective c - NSTokenField delegate - Stack Overflow

objective-c cocoa delegates nstokenfield
Rectangle 27 0

This works. I did it by observing the firstResponder property of the parent window. If the token field or any of its contained NSResponders become first responder, you show the popover.

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    [ self.window addObserver:self forKeyPath:@"firstResponder" options:NSKeyValueObservingOptionNew context:nil ] ;
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ( object == self.window && [ keyPath isEqualToString:@"firstResponder" ] )
    {
        NSResponder * responder = [ change valueForKey:NSKeyValueChangeNewKey ] ;

        while ( NULL != responder )
        {
            if ( responder == self.tokenField )
            {
                // show popover (if not showing)
                NSLog(@"Show popover!\n") ;
                return ;
            }
            responder = responder.nextResponder ;
        }

        NSLog(@"Hide popover!\n") ;
    }
    else
    {
        [ super observeValueForKeyPath:keyPath ofObject:object change:change context:context ] ;
    }
}

@end

You'll have to "debounce" the show popover signal--it may get called multiple times per "show" message. I did it without subclassing--the observation machinery is on the AppDelegate/window owner, but you could easily modify this to work in a custom subclass of NSTokenField

Thanks I solved used the approach from the comment on the main post.

objective c - How can I perform an action (show a popover) when an NST...

objective-c cocoa nstokenfield
Rectangle 27 0

You can get scroll bars in an NSTokenField by inserting the scroll view into the token field. You also have to do the resizing of the token field yourself. Also, make sure the wraps functionality of the token field is turned on.

objective c - Scroll bars in NSTokenField - Stack Overflow

objective-c cocoa interface-builder nstokenfield
Rectangle 27 0

To retrieve the objects represented by the tokens in a token field, send the token field an objectValue message. Although this method is declared by NSControl, NSTokenField implements it to return an array of represented objects. If the token field simply contains a series of strings, objectValue returns an array of strings. To set the represented objects of a token field, use the setObjectValue: method, passing in an array of represented objects. If these objects arent strings, NSTokenField then queries its delegate for the display strings to use for each token.

Great! It would be great if there was a tokens @property of the type NSArray, or at least the same description above on the Class reference page of the NSTokenField... Thanks for your answer

objective c - Getting the tokens from NSTokenField - Stack Overflow

objective-c cocoa
Rectangle 27 0

This could be because the "enter" key might send the event of the token field to it's action where the "tab" key just adds text to it. You could try to set the -isContinuous property to YES and see if you get the desired results.

That sounded promising so I quickly tried it out, but the issue persists so I still have the same behaviour.

isValidObject

objective c - NSTokenField does not check token on blur - Stack Overfl...

objective-c cocoa nstokenfield
Rectangle 27 0

This is what I ended up doing. I'm working on an open-source NSTokenField alternative with this capability built in.

// in an NSWindowController
- (NSMenu *)tokenField:(NSTokenField *)tokenField menuForRepresentedObject:(id)representedObject
{
    NSRect displayRect = NSMakeRect(([NSEvent mouseLocation].x - 2.5),
                                    ([NSEvent mouseLocation].y - 2.5),
                                    5, 5);
    displayRect = [self.window convertRectFromScreen: displayRect];


    // establish popover from displayRect ...
}

objective c - Show NSPopover from NSTokenField Token on Click - Stack ...

objective-c osx cocoa nstokenfield nspopover
Rectangle 27 0

I've written a custom NSValueTransformer to map between the bound NSManagedObject/Tag NSSet and the NSString NSArray of the token field. Here are the 2 methods:

- (id)transformedValue:(id)value {
  if ([value isKindOfClass:[NSSet class]]) {
    NSSet *set = (NSSet *)value;
    NSMutableArray *ary = [NSMutableArray arrayWithCapacity:[set count]];
    for (Tag *tag in [set allObjects]) {
      [ary addObject:tag.name];
    }
    return ary;
  }
  return nil;
}

- (id)reverseTransformedValue:(id)value {
  if ([value isKindOfClass:[NSArray class]]) {
    NSArray *ary = (NSArray *)value;
    // Check each NSString in the array representing a Tag name if a corresponding
    // tag managed object already exists
    NSMutableSet *tagSet = [NSMutableSet setWithCapacity:[ary count]];
    for (NSString *tagName in ary) {
      NSManagedObjectContext *context = [[NSApp delegate] managedObjectContext];
      NSFetchRequest *request = [[NSFetchRequest alloc] init];

      NSPredicate *searchFilter = [NSPredicate predicateWithFormat:@"name = %@", tagName];
      NSEntityDescription *entity = [NSEntityDescription entityForName:[Tag className] inManagedObjectContext:context];

      [request setEntity:entity];
      [request setPredicate:searchFilter];

      NSError *error = nil;
      NSArray *results = [context executeFetchRequest:request error:&error];
      if ([results count] > 0) {
        [tagSet addObjectsFromArray:results];
      }
      else {
        Tag *tag = [[Tag alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
        tag.name = tagName;

        [tagSet addObject:tag];
        [tag release];
      }
    }
    return tagSet;
  }
  return nil;
}

CoreData seems to automatically establish the object relationships on return (but I have not completely verified this yet)

objective c - NSTokenField representing Core Data to-many relationship...

objective-c cocoa core-data nstokenfield
Rectangle 27 0

Your second error is caused by having two separate managed object context with the same model and store active at the same time. You are trying to create an object in one context and then relate it another object in the second context. That is not allowed. You need to lose the second context and make all your relationships within a single context.

Your initial error is caused by an incomplete keypath. From your description it sounds like you are trying to populate the token fields with ItemsArrayController.selectedItem.tags but that will just return a Tag object which the token filed cannot use. Instead, you need to provide it with something that converts to a string e.g. ItemsArrayController.selectedItem.tags.name

objective c - NSTokenField representing Core Data to-many relationship...

objective-c cocoa core-data nstokenfield
Rectangle 27 0

You might try something similar to -setNeedsDisplay: and -displayIfNeeded ... i.e., -setNeedsSizeToFit: and -sizeToFitIfNeeded.

You'll just need a "needsSizeToFit" BOOL flag and the -setNeedsSizeToFit: and -sizeToFitIfNeeded methods.

After you set your tokens, call -setNeedsSizeToFit:YES. It in turn will set the instance's needsSizeToFit flag, then if the flag is YES, it will call [self performSelector:@selector(sizeToFitIfNeeded) withObject:nil afterDelay:0]. Your -sizeToFitIfNeeded method will check if your needsSizeToFit flag is YES, call [self sizeToFit], then set the needsSizeToFit flag to NO.

Here's a complete class (JLNAutoSizingTokenField) that does basic autosizing as described above. The only augmentation was to call this in the afore-mentioned delegate method:

- (NSString *)tokenField:(NSTokenField *)aTokenField 
displayStringForRepresentedObject:(id)representedObject
{
    [(JLNAutoSizingTokenField *)aTokenField setNeedsSizeToFit:YES];
    return representedObject;
}

I started to do something similar to this but I ran into the issue of not knowing when all my tokens are set. That's the real issue I'm having. They are not set after I setObjectValue. They are only set after each displayStringForRepresentedObject is called.

Wouldn't -displayStringForRepresentedObject: be called within the same trip through the runloop as your -setObjectValue: call? If so, then the -sizeToFitIfNeeded would be called in the next trip through the runloop, after all the calls to -displayStringForRepresentedObject:.

Worst case scenario: an unsavory-looking-but-functional call to -setNeedsSizeToFit: with each call to -displayStringForRepresentedObject:.

setObjectValue is called once and then NSTokenField calls displayString for each object in objectValue. I have to try calling the resize method in the diplayStringForRepresentedObject again because when I tried that before it was messing up the strings themselves. The token field didn't like me calling the resize method while it was doing what it needed to do.

Really unsavory would be, and I haven't tried this yet, would be to call a method each time displayStringForRepresentedObject is called and figuring out if its about to display the last one. At that point call the resize method with a delay of 0.1 or something. Calling resize from the displayStringForRepresentedObject is weird because it returns a string. So I call the resize before it returns the string and then would ultimately end up with one string that wasn't accounted for.

objective c - Resizing NSTokenField after populating with tokens - Sta...

objective-c cocoa osx appkit nstokenfield
Rectangle 27 0

I don't know if it's possible to have this behaviour with a NSTokenField.

But you should take a look at MTTokenField which do what you want out of the box.

1.Create an Xcode Project as a Static Library(Do not enable ARC).

3.Drag and drop all the files of MTTokenField located in the subdirectory 'MTTokenField' to your new XCode project. Choose to copy the files.

4.Add this to your rakefile in order to compile and link the library with your Rubymotion project.

app.vendor_project("vendor/MTTokenField/", :xcode, :xcodeproj => "MTTokenField.xcodeproj", :target => "MTTokenField", :products => ["libMTTokenField.a"], :headers_dir => "MTTokenField")

5.In Interface Builder change the class of your NSTokenField to NSTextField and then set its custom class to MTTokenField, and also change the custom class of the cell: MTTokenFieldCell instead of NSTextFieldCell.

6.Then you have to set the delegate of your MTTokenField to a class which has to respond to :

def tokenField(tokenField, completionsForSubstring: substring )
   # your have to return an array containing your results matching substring.
end

objective c - NSTokenField click completion list item - Stack Overflow

objective-c osx cocoa rubymotion
Rectangle 27 0

I think it can't be done (see my endeavours here). The problem is that an individual token is not exposed in such a way that you can reference its bounds in order to hook it up with a popover.

objective c - Show NSPopover from NSTokenField Token on Click - Stack ...

objective-c osx cocoa nstokenfield nspopover
Rectangle 27 0

Actually, you first have to define a tokenizing character, which in your case would be %

[tokenField setTokenizingCharacterSet:[NSCharacterSet characterSetWithCharactersInString:@"%%"]];

The input string needs to changed as well into:

... so that Cocoa knows where the token ends.

And if you want [Tag] to be displayed as Tag in the token field, you also need to implement the tokenField:displayStringForRepresentedObject: method:

- (NSTokenStyle)tokenField:(NSTokenField *)tokenField
 displayStringForRepresentedObject:(id)representedObject
{
    if ([representedObject rangeOfString: @"["].location == 0) {
        return [(NSString*)representedObject substringWithRange:NSMakeRange(1, [(NSString*)representedObject length]-2)];

    return representedObject;
}

However, this has a big drawback : if you copy or just move a token, Cocoa will call tokenField:displayStringForRepresentedObject: and the copied/moved token will be changed to regular text Tag instead of the token [Tag].

If someone has a solution to the above problem, I'd be happy to read it.

You need to implement the delegate method - (BOOL)tokenField:(NSTokenField *)tokenField writeRepresentedObjects:(NSArray *)objects toPasteboard:(NSPasteboard *)pboard

objective c - NSTokenField with mixed token/string input, possible? - ...

objective-c cocoa nstokenfield
Rectangle 27 0

I tried for a little while and I found that the token field calls control:isValidObject: of the NSControlTextEditingDelegate protocol when the Tab key is pressed. So you can implement a delegate method such as

- (BOOL)control:(NSControl *)control isValidObject:(id)object
{
    NSLog(@"control:%@", control);
    NSLog(@"object:%@", object);
    return NO;
}

The 'object' parameter is the content of your incomplete token. If the method returns NO, the token will not be inserted to the array of valid tokens.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

objective c - How to validate all tokens are valid in an NSTokenField ...

objective-c cocoa nstokenfield
Rectangle 27 0

I'm also struggling with this problem and found that using control:isValidObject as suggested by zonble almost gets to the solution, but that it is difficult to determine whether to return NO or YES based on the object parameter. As far as I can tell this problem is only restricted to the tab key so I implemented a pair of methods as follows;

I realise that this is horribly ugly but it's the only way I could get the NSTokenField to avoid creating tokens on tab while not impinging on other NSTextField behaviours of NSTokenField (eg moving the cursor to a new position etc).

- (BOOL)control:(NSControl *)control isValidObject:(id)object
{
    if (self.performingTab) {
        self.performingTab=NO;
        return NO;
    } else {
        return YES;
    }
}

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor
doCommandBySelector:(SEL)commandSelector 
{        
    if (commandSelector==@selector(insertTab:)) {
        self.performingTab=YES;
    }        
    return NO;        
}

objective c - How to validate all tokens are valid in an NSTokenField ...

objective-c cocoa nstokenfield
Rectangle 27 0

just add an observer for the tokenfeilds change : [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(actionhere) name:NSControlTextDidChangeNotification object:nil];

objective c - Callback for deleting NSTokenField Tokens - Stack Overfl...

objective-c osx nstokenfield nstokenfieldcell
Rectangle 27 0

Its possible by using private APIs. Subclass NSTokenAttachmentCell (Private) and NSTokenFieldCell.

Use BWTokenAttachmentCell and BWTokenFieldCell class and NSTokenAttachmentCell class dump from BWToolkit. Modify initialize method of BWTokenAttachmentCell.

Use this method if you are not targeting for Mac App Store.

objective c - NSTokenField: different colors for tokens - Stack Overfl...

objective-c osx cocoa nstokenfield nstokenfieldcell
Rectangle 27 0

NSTokenField is a subclass of NSTextField, which does not have scroll bars. It seems quite unlikely that NSTokenField would have scroll bars.

objective c - Scroll bars in NSTokenField - Stack Overflow

objective-c cocoa interface-builder nstokenfield
Rectangle 27 0

After trying a lot of stuff, I finally got this to work based on Iulius Csar's suggestion.

The trick was to subclass NSTextField and override trackingAreas:

- (NSArray *)trackingAreas
{
    return [NSArray array];
}

Simply deleting the field's tracking areas when creating it wasn't quite enough, because the field was in a scroll view and sometimes the tracking areas would be re-created.

Glad my suggestion was helpful! I wasn't completely sure it was the right route.

objective c - How to make an NSControl (e.g., NSTokenField) ignore mou...

objective-c osx cocoa nstokenfield nsresponder
Rectangle 27 0

This will be send to the delegate to query an array of strings:

tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:

These strings should then be processed by the tokenField in representedObject (or not if you need only strings).

Example in your tokenField delegate:

- (NSArray *)tokenField:(NSTokenField *)tokenField completionsForSubstring:(NSString *)substring indexOfToken:(NSInteger)tokenIndex indexOfSelectedItem:(NSInteger *)selectedIndex
{
    //code to find the tags strings corresponding to substring (the string typed in the token)
    //then put them in an array (returnArray)
    return returnArray;
}

The tokenField will present the strings completed in a menu as you type. All details are in the doc.

objective c - NSTokenField autocomplete - Stack Overflow

objective-c cocoa autocomplete parsing nstokenfield