How to show an NSWindow as sheet at specific location - objective-c

I have a window like this, having 3 subviews, each one of them has button. On click of those- I need to show sheet.
By using this code, sheet comes in centre of the window.
- (IBAction)closeSubWindow:(id)sender{
[NSApp endSheet:self.subWindow];
[self.subWindow orderOut:nil];
}
- (IBAction)showSubWindow:(id)sender {
[NSApp beginSheet:self.subWindow
modalForWindow:self.window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
}
Is there any option or way to show the sheet at specific co-ordinates?
EDIT:
My current implementation is by using NSPopover. Can I make this NSPopover to animate like sheet?

Take a look at the NSWindow delegate method -window:willPositionSheet:usingRect:

A sheet is per definition that what you see. So no, there is no way to place it at a different position. You could create an own implementation, but maybe it is better in your situation not to use a sheet but e.g. an NSPopover. This is availabe since OSX 10.7 and a great means to have a temporary view for displaying/entering values. By using the transient (or semi-transient) style the framework takes care for managing the display (automatically hiding the popover when no longer needed). Of course you can also have an OK button on it to commit changes.
The popover is also kinda modal, just like the sheet, so, functionally they are quite similar, but you have more freedom regarding its position.

Related

Howto identify modalForWindow using NSViewController

I have one NSWindow (mainwindow) for my OSX NSApplicationDelegate. The NSWindow also holds several NSView's where the content is set using NSViewControllers. Currently I ran into a problem when I wanted a NSPanel, a sheet, to drop down from the top of one of my NSViews (not from the top of my app). I wanted to use the code:
[NSApp beginSheet:self.loginSheet.window
modalForWindow:self.view.window
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
The loginSheet is a subclass of NSWindowController which loads the xib file using:
loginSheet = [[sheetWindowController alloc] initWithWindowNibName:#"loginSheet"];
However, I run this code from my NSViewController and my self.view.window is always nil. My NSView seems otherwise correctly initialized and works fine, but the drop down of the sheet does not work as my modalForwindow (self.view.window) is nil. If I use the code:
[NSApp beginSheet:self.loginSheet.window
modalForWindow:[[NSApplication sharedApplication] mainWindow]
modalDelegate:self
didEndSelector:nil
contextInfo:nil];
it works like a charm. But from all my searching to find an answer to my problem it seems that this working approach is a big no-no since it blocks the entire app from any response. I wanted my sheet to be linked to one of my NSViews' but I dont see how I can do this given that the app only have one NSWindow? Am I not doing something that makes my self.view.window stay nil? Is there a good way for me to find the parent window of custom views? If you have any suggestions for how to solve this problem or can give me a hint on what I am doing wrong that would be greatly appreciated.
Thanks! Cheers, Trond
You should have a look at the "Positioning Sheets" section of "Introduction to Sheets" docs. It explains how to make a sheet appear from somewhere other then under the window's title bar using window:willPositionSheet:usingRect:

NSOutlineView selection does not work

I have an NSOutlineView with a custom datasource (I don't know if this is relevant).
I have only one column (again, I don't know if this is relevant) and I want to perform a specific action upon cell selection, so I thought I should override outlineViewSelectionDidChange. This what I did:
-(void)outlineViewSelectionDidChange:(NSNotification *)notification
{
NSLog(#"selection changed");
}
But this is not working. I have been playing around in IB with the Outline View, the Table Column and the Text Field Cell properties but so far I had no luck. I don't know if I changed any property that caused this situation or if this is something specific to my specific implementation.
So, anyone's got any clue on what I may be missing?
EDIT: Just in case I'm mis-interpreting the selection concept within an OutlineView, I expected the cells to be selected if I just click on the text outside the area of the expand arrow.
Well after a long struggle, as always, just after I posted my question, I found the answer. The problem is I am using the NSOutlineView in an NSPanel and somehow the NSPanel is not allowing the cells to be selected. If I just move the NSOutlineView to an NSWindow it works just as intended.

How to check if a NSWindow is visible

Is there a way to check if a NSWindow is visible or not? I want to display a sheet controller once the first window of my app became visible (the animation on 10.7 ended and the user can see the window!). If I just show the sheet in windowDidLoad, it results in a stupid looking animation (sheet rolling out, window popping out from the back). I know that NSWindowDelegate provides two methods which are invoked when a window either became the key window or the main window, however, this doesn't have to mean that the window is already fully visible at the time. This is even more noticeable on Lion where windows tend to pop up with this stupid animation.
I would go for something like this:
if ([myWindow isVisible]) {
// Do stuff
}
Or an an observer for this key path to be notified when the change occurs.
For what it's worth, you can also bind to the window.visible property. Xcode 4 may squawk at you, saying it's not a bindable property, but it will work.
This can be useful if you are trying enable/disable show/hide NSStatusItem based on whether the window is visible, as well as other approaches.
i.e. in Interface Builder:
Bind to: App Delegate
Model Key Path: self.window.visible

How do I make an action in one view close itself and open another view?

New to obj-c and cocoa, working a on a simple game as my first (mac os x) app. I have a menu view and a game view:
MenuView.h/m
MenuViewController.h/m
GameView.h/m
GameViewController.h/m
I want the menu to be displayed by default, and when the play button (which is in the MenuView) is clicked I want the menu to go away and the game to appear. I understand actions and outlets, but I don't know where to start on making the views swap themselves out. Any help? It seems like I would need to somehow make my MenuViewController talk to my MainController?
Peter Hosey,
If you are looking at the MenuViewController as a sort of "main" view controller, at the moment the play button is clicked, you could initialize an instance of GameViewController:
- (IBAction)gameButtonClicked {
GameViewController *game = [[GameViewController alloc] init];
// we put the game view as the MenuViewController's view
[self setView:game.view];
[game release];
}
Of course, you need to import the "GameViewController.h" to access it.
If you want them in the same window and at the same size, you can put both views into a tabless tab view. Just switch the tab to switch which view is visible.
Another way would be to put them in different windows and use a window controller rather than a view controller for each one. Among other things, this makes it easy to make the game window user-resizable without disturbing the size of the menu window.
Since you want your MenuViewController to be what calls and takes care of GameViewController, I'd suggest something similar to what Rafael said. Try putting an instance of GameViewController in your Interface Builder file, but making it hidden. When they press the "Play" button to activate the game, simply send the GameViewController to the front and make it visible. It's a bit clumsy, but it works. Remember to hide all the buttons and interactions regarding your menu though. You don't want to accidentally activate the high scores list when playing a game!
Also, I'd recommend looking into Utility applications. (They're one of the template types you're given when you create a new project.) They're built to switch between two seperate view controllers, and it might just be what you're looking for.

Why isn't my sheet attached to the window it's run for?

I have a NIB which contains two windows, one is the app's main window visible at launch and the other is a custom sheet (and therefore not visible at launch). When the sheet is required my controller calls:
[NSApp beginSheet: sheetWindow modalForWindow: mainWindow modalDelegate: self didEndSelector: #selector(didEndSheet:returnCode:contextInfo:) contextInfo: nil];
which displays the sheet window and starts a modal session, but the window has a standard Aqua title bar, is not 'connected' to the main window and can be moved around just like a regular window. Needless to say, this is not desirable :-). Why doesn't the sheet window "pop out" of the window it's run for, as sheets usually do when begun in this fashion?
I had wondered whether the fact that I was beginning the sheet inside the controller's -awakeFromNib might have an effect, so I moved the sheet to a button's action I could trigger later. This didn't change the behaviour. I haven't thought of anything else to try. I'm targeting the 10.5 SDK, using Xcode 3.1.
Edit: so it looks like I've created a modal dialog; sheets and app-modal dialogs are both started with the -beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo: method. But how do I indicate that my window should be a sheet and not a modal dialog?
This happened to me a couple of days ago:
You forgot to set the window outlet of your window controller (File's owner of the Nib file).
As Indicated by Nathan, you may see that the -[NSWindowController window] method returns nil.
You must also uncheck the Visible at launch option of the sheet.
If mainWindow is nil then the sheet will be displayed as a window/dialog.