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
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