Search code examples
objective-cmacosintellisensenspopover

Show NSPopover without Focus


I'm working on creating an IntelliSense style popover that shows the user who is typing into a text field what syntax is valid. Does anyone know how to show an NSPopover without giving it focus, so that the user can continue to type into the textField? The popover is triggered by controlTextDidChange:

- (void) controlTextDidChange:(NSNotification *)obj
{

    NSTextField *field = [obj object];
    NSString *command = [field stringValue];

    if ([[command substringFromIndex: command.length - 1] isEqualToString: @"#"]){
        CompletionMenuController *completionController = [[CompletionMenuController alloc] initWithNibName: @"CompletionMenuController" bundle:[NSBundle mainBundle]];
        completionMenuPopover = [[NSPopoverInformation alloc] init];
        [completionMenuPopover setContentViewController: completionController];
        [completionMenuPopover setContentSize: completionController.view.frame.size];
        [completionMenuPopover setBehavior: NSPopoverBehaviorTransient];
        [completionMenuPopover setAppearance: NSPopoverAppearanceHUD];
        [completionMenuPopover showRelativeToRect:[_commandBar frame] ofView:_commandBar preferredEdge:NSMaxYEdge];
    }
}

Solution

  • This is a workaround, not exactly how I was trying to accomplish this, but it works. I save the cursor position in the textfield prior to opening the popover, then give the textfield first responder and change the cursor position back to where it was.

    if ([_commandBar stringValue].length > 0){
        NSString *command   = [_commandBar stringValue];
        NSRange range       = [[_commandBar currentEditor] selectedRange];
    
        //Open popover if command is being typed
        if ([[command substringFromIndex: command.length - 1] isEqualToString: @"#"]){
            CompletionMenuController *completionController = [[CompletionMenuController alloc] initWithNibName: @"CompletionMenuController" bundle:[NSBundle mainBundle]];
    
            //Configure and Open Popover
            if ([completionMenuPopover isShown]) [completionMenuPopover close];
            completionMenuPopover = [[NSPopover alloc] init];
            [completionMenuPopover setContentViewController: completionController];
            [completionMenuPopover setContentSize: completionController.view.frame.size];
            [completionMenuPopover setBehavior: NSPopoverBehaviorTransient];
            [completionMenuPopover setAppearance: NSPopoverAppearanceHUD];
            [completionMenuPopover setAnimates: NO];
            [completionMenuPopover showRelativeToRect:[_commandBar frame] ofView:_commandBar preferredEdge:NSMaxYEdge];
    
            //Reset Command Bar as First Responder
            [_commandBar becomeFirstResponder];
            [[_commandBar currentEditor] setSelectedRange: range];
        }
    }