Question

I have a NSOutlineView (View based) with two columns. In the second column i have a NSButton connected to one NSPopOver.

When i click the button, it show the NSPopOver as expected => Popover is visible.

The problem: If i reloadData of NSOutlineView it hide the NSPopover !

Is it the normal behavior ? How to avoid this ?

In other word, popoverWillClose delegate message is called after each reloadData

//OMN_Object.m
#pragma mark - Actions
- (IBAction)togglePopover:(id)sender
{
   ...
   Call App_delegate togglePopover:withTextLog:withTextInputFileDetails:withTextOutputFileDetails:fromObject:

//App_delegate.m
...
[self.myPopOver setDelegate:self];
...
#pragma mark Popover delegate

- (void)popoverWillClose:(NSNotification *)notification
{
    NSLog(@"%s *** popoverWillClose %@",__PRETTY_FUNCTION__, self.myPopOver);
}

-(void)togglePopover:(id)sender  withTextLog:(NSString*)textLog
withTextInputFileDetails:(NSString*) textInfoInput
withTextOutputFileDetails:(NSString*) textInfoOutput
              fromObject:(id)object
{
    id v = [[self.myPopOver contentViewController] view] ;

    NSTextView *t1 = [v textViewLog];
    [t1 setString:textLog];

    NSTextView *t2 = [v textViewInputFileDetails];
    [t2 setString:textInfoInput];

    NSTextView *t3 = [v textViewOutputFileDetailsLastPassFileOnly];
    [t3 setString:textInfoOutput];

    if (self.myPopOver.isShown == 0) {
        NSLog(@"%s Displaying popover %@", __PRETTY_FUNCTION__, self.myPopOver);
        [self.myPopOver showRelativeToRect:[sender bounds]
                                    ofView:sender
                             preferredEdge:NSMaxYEdge];
        self.objectOwnerOfPopOver = object;
    }
    else {
        NSLog(@"%s Closing popover %@", __PRETTY_FUNCTION__, self.myPopOver);
        [self.myPopOver close];
        self.objectOwnerOfPopOver = nil;
    }
}

// Outline_view_delegate.m
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item{
...
    else  if ([[tableColumn identifier] isEqualToString:@"Status"]){
        if ([item isKindOfClass:[OMN_Object class]])
        {
            OMN_Object *o = item;

            ObjectStatusTableCellView *v = [outlineView makeViewWithIdentifier:@"StatusCell" owner:self];
                  ....

            [v.buttonRevealInFinder setAction:@selector(buttonRevealInFinderClicked:)];
            [v.buttonRevealInFinder setTarget:o];

            [v.buttonInfo setTarget:o];
            [v.buttonInfo setAction:@selector(togglePopover:)];

            return v;
        }
...
}
Was it helpful?

Solution 2

Solved. I attached the popover to NSWindow view and used NSMouseLocation for popover's position.

NSPoint mouseLoc2 = [self.window mouseLocationOutsideOfEventStream];
NSRect r4 = NSMakeRect(mouseLoc2.x -10, mouseLoc2.y -10, 16, 16);
[self.myPopOver showRelativeToRect:r4
                            ofView:self.window.contentView
                     preferredEdge:NSMaxYEdge];

OTHER TIPS

When you call reloadData on the outline view the outline view removes all of its subviews (including the button that the popover is attached to) and recreates them. When the button is removed from its superview the popover is closed.

Do you really need to reload all of the outline view data? Could you reload specific rows instead using -reloadDataForRowIndexes:columnIndexes: or -reloadItem:?

Alternatively, rather than passing the button (sender) to -showRelativeToRect:ofView:preferredEdge:m you could try passing the outline view itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top