Pregunta

I have an OSX application that uses NSViewController to swap in-out views in my NSView. One of the views is a NSOutlineView. I now want to have a NSPopover appear when the user double-clicks a row in the outlineview. Currently I use the following approach to have the popover appear:

NSRect theRect = [[NSApp keyWindow] convertRectFromScreen: NSMakeRect(700, 400, 5, 5)];
[myPopover showRelativeToRect: theRect // Window Coordinates
                        ofView: [[NSApp keyWindow] contentView]
                 preferredEdge: NSMinYEdge];

This makes the NSPopover appear at the bottom of the app. This works but I want to be able to have the popover appear exactly below the clicked row of the NSOutlineView. Every view I swap in-out is controlled by a NSViewController and I thought I could identify my view positions using the view property of the NSViewController. However, if I replace [[NSApp keyWindow] contentView] with myViewController.view I receive the error that view does not have a window and the NSPopover crashes. Clearly, I have trouble 1) finding the coordinates of the clicked row in the NSView relative to the main window 2) understanding why my view does not have a window. If anyone has suggestions that could help me understand these problems I would greatly appreciate it.

UPDATE 06/02/2013 I am still struggling with my problem but I have discovered that I can get the correct coordinates for my view if I access its properties through my MainWindowController (myControlledView). When I then ask for the origin and frame size of my view I get the correct values. My VC's load the custom view as a NIB file and when I ask for the origin of the loaded view I get (0,0). I thought that the position of the view relative to the window would remain unchanged even if I load the view as a NIB? I can pass the view origin to my VC and thereby set the NSPopover correctly but this seem rather cumbersome and I would think the NIB loaded view origin was correctly accessible through the VC.

managingViewController *vc = [viewControllers objectAtIndex:[viewIndex intValue]];
[self.currentViewController.view removeFromSuperview];
[self setCurrentViewController:vc];
[self.myControlledView addSubview:vc.view];
NSLog(@"My origin: %f %f",vc.view.frame.origin.x,vc.view.frame.origin.y);

This results in:My origin: 0.000000 0.000000 and is not what I am looking for, while this:

NSLog(@"My origin: %f %f",self.myControlledView.frame.origin.x,self.myControlledView.frame.origin.y);

Results in the correct origin: My origin: 176.000000 38.000000

Clearly there is something about views and windows I dont understand. Any help is apreciated.

Thank you for suggestions and help! Cheers, Trond

¿Fue útil?

Solución

This turned out to be quite easy as soon as I understood what I was doing. It turns out I had two allocations of my currentViewController. One was allocated in IB while one was allocated in code. When I deleted the IB created VC I could interact with the correct code initiated view and I was able to position my NSPopover using the position of the (tracked) mouse:

-(void)mouseMoved:(NSEvent *)theEvent {
    NSPoint p = theEvent.locationInWindow;
    self.myMouseX=[NSNumber numberWithFloat:p.x];
    self.myMouseY=[NSNumber numberWithFloat:p.y];
}

The mouse position was used to define the coordinates for my rect:

NSRect theRect = NSMakeRect([self.myMouseX floatValue] + 5,[self.myMouseY floatValue],1,1);

[myPopover showRelativeToRect: theRect // Window Coordinates
                       ofView: [[NSApp keyWindow] contentView]
                preferredEdge: NSMaxXEdge];

Cheers, Trond

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top