Auto-resized Window Position on Restore - cocoa

I have an app that resizes itself for different views using:
NSSize currentSize = [[box contentView] frame].size;
NSSize newSize = [v frame].size;
float deltaWidth = newSize.width - currentSize.width;
float deltaHeight = newSize.height - currentSize.height;
NSRect windowFrame = [w frame];
windowFrame.size.height += deltaHeight;
windowFrame.origin.y -= deltaHeight;
windowFrame.size.width += deltaWidth;
[box setContentView: nil];
[w setFrame: windowFrame
display: YES
animate: YES];
[box setContentView: v];
When you change the view, the window grows/shrinks based on the upper-left corner of the app. The app always starts on the first view, no matter which view the user was in when they quit, because this is a summary view. I also want it to be restorable so the last-used document is open on launch.
The problem: since most views are taller than the summary view, changing to one pushes the bottom left corner of the window farther down the screen. Now quit the app and relaunch, and the app positions the window to where that bottom left corner was previously. I know this is because that's where Cocoa puts the origin, but it makes more sense for the user to have the window restart with the same top left corner, otherwise the app is shifting down the screen each time it's opened.
I tried observing NSWindowWillCloseNotification and calling the above method again to reset the app to the summary view just before closing, but even though the code works, the window still starts in the wrong position - I'm guessing Cocoa sets an app's restorable defaults before the notification is sent.
It's been done before: System Preferences does it - it auto-resizes for views, dictates what your starting view is, but you can move the window and next time you open it, it'll be in the new position based on the top left corner. Anyone have an idea how to emulate that?
Edit: Document.xib has a small window with a popup button and a box. The methods below change the views and resize the window to fit those views. Everything works fine while the app is open, the window shifting is only an issue when the app is closed and re-opened with an active document (ie. using Lion's restore).
============================
| Jump to:___ | The "===" is the top and bottom edge of the window
| | The "___" is the pop-up menu for selecting the view
| -------------------------- | The dashed box on the inside is "box", which holds the views
|| ||
|| ||
|| ||
|| ||
|| ||
|| ||
| -------------------------- |
============================
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
//Note that init creates the array viewControllers
NSMenu *menu = [viewMenu menu];
NSUInteger i, itemCount;
itemCount = [viewControllers count];
for (i = 0; i < itemCount; i++) {
NSViewController *vc = [viewControllers objectAtIndex:i];
NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle: [vc title] action: #selector(changeViewController:) keyEquivalent:#""];
[mi setTag: i];
[menu addItem: mi];
}
[self displayViewController: [viewControllers objectAtIndex: 0]];
[viewMenu selectItemAtIndex: 0];
}
- (void) displayViewController: (ManagingViewController *) vc {
//End editing
NSWindow *w = [box window];
BOOL ended = [w makeFirstResponder:w];
if (!ended) {
NSBeep();
return;
}
//Put view in box
NSView *v = [vc view];
NSSize currentSize = [[box contentView] frame].size;
NSSize newSize = [v frame].size;
float deltaWidth = newSize.width - currentSize.width;
float deltaHeight = newSize.height - currentSize.height;
NSRect windowFrame = [w frame];
windowFrame.size.height += deltaHeight;
windowFrame.origin.y -= deltaHeight;
windowFrame.size.width += deltaWidth;
[box setContentView: nil];
[w setFrame: windowFrame display: YES animate: YES];
[box setContentView: v];
}
- (IBAction)changeViewController:(id)sender {
NSUInteger i = [sender tag];
ManagingViewController *vc = [viewControllers objectAtIndex: i];
[self displayViewController: vc];
}
I tried putting the first block of suggested code from #trudyscousin just below the for loop in -windowControllerDidLoadNib: and that anchored the window correctly, but when the code reaches -displayViewController: it sets currentSize = (6,6). I'm not sure if that's because the box is empty in IB. It then adds the difference between (6,6) and the size of the SummaryView to the size of the window when the app last quit, making it huge.
I then tried using NSUserDefaults by adding two lines to -changeViewController:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger: i forKey: #"lastViewController"];
and in -windowControllerDidLoadNib:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ([userDefaults integerForKey: #"lastViewController"]) {
NSInteger i = [userDefaults integerForKey: #"lastViewController"];
ManagingViewController *vc = [viewControllers objectAtIndex: i];
NSView *v = [vc view];
NSSize currentSize = [v frame].size;
[box setFrameSize: currentSize];
[self displayViewController: vc];
[viewMenu selectItemAtIndex: i];
} else {
[self displayViewController: [viewControllers objectAtIndex: 0]];
[viewMenu selectItemAtIndex: 0];
}
This works, but forces the app to launch with the last used view, which wouldn't be so bad except that it will even do that when a new document is opened/created. If I get rid of the else (i.e., always run those last 2 lines), I'm back to where I started - the app launches being shifted vertically down the screen. It looks like you can't set the window's origin at launch, or maybe it reloads its own defaults at a later point.
The last thing I did was go back to my starting code (not using the mask code provided by #trudyscousin) but at the bottom of -windowControllerDidLoadNib: I added:
[self performSelector: #selector(adjustOrigin) withObject: nil afterDelay:0.0f];
which calls:
- (void) adjustOrigin {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ([userDefaults integerForKey: #"lastViewController"]) {
NSInteger i = [userDefaults integerForKey: #"lastViewController"];
ManagingViewController *vc = [viewControllers objectAtIndex: i];
NSView *v = [vc view];
NSSize previousSize = [v frame].size;
NSSize currentSize = [[[viewControllers objectAtIndex: 0] view] frame].size;
CGFloat delta = previousSize.height - currentSize.height;
NSRect windowFrame = [[box window] frame];
windowFrame.origin.y += delta;
[[box window] setFrame: windowFrame display:YES];
}
}
That actually does work, but if multiple things are running, the lag is enough that you can see the window make the "jump" to its new origin, which is a little inelegant.

Your code appears to be sound, but the real problem may be your document xib.
If your document xib is set up for Auto Layout, turn that off. You can do that by selecting the file in Xcode. In the File inspector, turn off the "Use Auto Layout" check box.
Once you've done that, select your popup button. In the Size inspector, anchor the button at the top and left side. Select your box. In the Size inspector, anchor the box on all four sides, and make sure it expands horizontally and vertically.
To recap from my earlier answer, here's your -windowControllerDidLoadNib: method with the changes I had suggested earlier:
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
//Note that init creates the array viewControllers
NSMenu *menu = [viewMenu menu];
NSUInteger i, itemCount;
itemCount = [viewControllers count];
for (i = 0; i < itemCount; i++) {
NSViewController *vc = [viewControllers objectAtIndex:i];
NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle: [vc title] action: #selector(changeViewController:) keyEquivalent:#""];
[mi setTag: i];
[menu addItem: mi];
}
// ---
NSWindow *myWindow = [[[self windowControllers] objectAtIndex:0] window];
NSUInteger styleMask = [myWindow styleMask];
styleMask ^= NSResizableWindowMask;
[myWindow setStyleMask:styleMask];
if ([myWindow setFrameUsingName:#"windowFrameAutosaveName"] == NO)
{
[myWindow center];
}
(void) [myWindow setFrameAutosaveName:#"windowFrameAutosaveName"];
styleMask &= ~NSResizableWindowMask;
[myWindow setStyleMask:styleMask];
// ---
[self displayViewController:[viewControllers objectAtIndex:0]];
[viewMenu selectItemAtIndex:0];
}
I removed the older comments but now indicate where the additional code is. With this, you shouldn't have to bother with maintaining your own defaults for the document, and you don't have to bother with adjusting the origin.
Put these two things together, and you (largely) have your fix.
Yes, I needed to qualify that somewhat. Yours is a document-based application, and so you're going to have to either come up with either a unique name under which to save your document's window location in your user defaults, or perhaps a means of somehow storing that information with the document itself.
As always, good luck to you in your endeavors.

Related

Best practice for resize window with animation using ToolBar on Cocoa

I'm wondering what's the best practice to resize a window when Toolbar changes.
I'm trying to get this effect (animated) when a Toolbar selected option changes.
Any ideas?
Thank you for your help! :)
Here's my commonly used method:
After clicking the new toolbar item, firstly get the frame size of the new subview to be added, then change window's frame with animation.
Demo (just change height, but you can add support to change width):
- (void)switchToTabView:(NSView *)settingView withAnimation:(BOOL)animation
{
NSView *windowView = self.window.contentView;
for (NSView *view in windowView.subviews) {
[view removeFromSuperview];
}
CGFloat oldHeight = windowView.frame.size.height;
[windowView addSubview:settingView];
CGFloat newHeight = settingView.frame.size.height;
CGFloat delta = newHeight - oldHeight;
NSPoint origin = settingView.frame.origin;
origin.y -= delta;
[settingView setFrameOrigin:origin];
NSRect frame = self.window.frame;
frame.size.height += delta;
frame.origin.y -= delta;
[self.window setFrame:frame display:YES animate:animation];
}
#GoKu Your answer gave me a hint how to solve it. I just added a new property for my window called "win".
Here's my solution:
- (void)updateView:(int)tag{
[[_ourViewController view] removeFromSuperview];
if (tag==0) {
self.ourViewController = [[UserView alloc] initWithNibName:#"UserView" bundle:nil];
} else if (tag==1){
self.ourViewController = [[ComputerView alloc] initWithNibName:#"ComputerView" bundle:nil];
}
NSView *newView = _ourViewController.view;
NSRect windowRect = _win.frame;
NSRect currentViewRect = newView.frame;
windowRect.origin.y = windowRect.origin.y + (windowRect.size.height - currentViewRect.size.height);
windowRect.size.height = currentViewRect.size.height;
windowRect.size.width = currentViewRect.size.width;
[self.win setContentView:newView];
[self.win setFrame:windowRect display:YES animate:YES];
}
Thanx!

How do I implement frameForAlignmentRect:/alignmentRectForFrame: such that the frame outside the alignment rect encapsulates those of subviews?

So I now have my Auto Layout-based container working, for the most part. On 10.8 (I need to run on 10.7 and newer), I see this:
Notice how the sides of the NSProgressIndicator and NSPopUpButton are clipped.
After some experimentation, I found that overriding alignmentRectInsets and returning 50 pixels of insets on all sides shows no clipping:
In both cases, the controls are bound to the left and right edges of the container view alignment rect with H:|[view]|. I imagine this will happen on other versions of OS X too, but it's most noticeable here (and as of writing I only have access to 10.8 and 10.10 installs).
Now, using alignment rect insets of 50 pixels on each side sounds wrong. I don't think there'd be any control that would need more than 50 pixels, but I'd rather do these correctly. So my question is: How do I implement the alignmentRectForFrame: and frameForAlignmentRect: selectors to properly account for the frames and alignment rects of the subviews?
Right now, I'm thinking to force a layout and then observe the frames and alignment rects of each subview, assuming that alignment rect (0, 0) of my last subview (the subviews are arranged linearly) will be at alignment rect (0, 0) of the container view. But I'm not sure if this approach is sufficient to handle all cases, and I'm not sure if I can invert the operation in the same way that these two selectors require. Subtraction, maybe?
If what I described above is the solution, could I do that with alignmentRectInsets, or must the insets returned by that method never change during the lifetime of the view?
Or is the second screenshot showing a scenario that Interface Builder won't reproduce, and thus I assume is "wrong" from a guidelines standpoint?
In the sample program below, start without a command-line argument to simulate the first screenshot, and start with an argument to simulate the second screenshot. Check the Spaced checkbox to add spacing to the views.
Thanks!
// 17 august 2015
#import <Cocoa/Cocoa.h>
BOOL useInsets = NO;
#interface ContainerView : NSView
#end
#implementation ContainerView
- (NSEdgeInsets)alignmentRectInsets
{
if (useInsets)
return NSEdgeInsetsMake(50, 50, 50, 50);
return [super alignmentRectInsets];
}
#end
NSWindow *mainwin;
NSView *containerView;
NSProgressIndicator *progressbar;
NSPopUpButton *popupbutton;
NSButton *checkbox;
void addConstraints(NSView *view, NSString *constraint, NSDictionary *views)
{
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:constraint
options:0
metrics:nil
views:views];
[view addConstraints:constraints];
}
void relayout(BOOL spaced)
{
[containerView removeConstraints:[containerView constraints]];
NSDictionary *views = #{
#"pbar": progressbar,
#"pbutton": popupbutton,
#"checkbox": checkbox,
};
NSString *vconstraint = #"V:|[pbar][pbutton][checkbox]|";
if (spaced)
vconstraint = #"V:|[pbar]-[pbutton]-[checkbox]|";
addConstraints(containerView, vconstraint, views);
addConstraints(containerView, #"H:|[pbar]|", views);
addConstraints(containerView, #"H:|[pbutton]|", views);
addConstraints(containerView, #"H:|[checkbox]|", views);
NSView *contentView = [mainwin contentView];
[contentView removeConstraints:[contentView constraints]];
NSString *base = #":|[view]|";
if (spaced)
base = #":|-[view]-|";
views = #{
#"view": containerView,
};
addConstraints(contentView, [#"H" stringByAppendingString:base], views);
addConstraints(contentView, [#"V" stringByAppendingString:base], views);
}
#interface appDelegate : NSObject<NSApplicationDelegate>
#end
#implementation appDelegate
- (IBAction)onChecked:(id)sender
{
relayout([checkbox state] == NSOnState);
}
- (void)applicationDidFinishLaunching:(NSNotification *)note
{
mainwin = [[NSWindow alloc]
initWithContentRect:NSMakeRect(0, 0, 320, 240)
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
backing:NSBackingStoreBuffered
defer:YES];
NSView *contentView = [mainwin contentView];
containerView = [[ContainerView alloc] initWithFrame:NSZeroRect];
[containerView setTranslatesAutoresizingMaskIntoConstraints:NO];
progressbar = [[NSProgressIndicator alloc] initWithFrame:NSZeroRect];
[progressbar setControlSize:NSRegularControlSize];
[progressbar setBezeled:YES];
[progressbar setStyle:NSProgressIndicatorBarStyle];
[progressbar setIndeterminate:NO];
[progressbar setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:progressbar];
popupbutton = [[NSPopUpButton alloc] initWithFrame:NSZeroRect];
[popupbutton setPreferredEdge:NSMinYEdge];
NSPopUpButtonCell *pbcell = (NSPopUpButtonCell *) [popupbutton cell];
[pbcell setArrowPosition:NSPopUpArrowAtBottom];
[popupbutton addItemWithTitle:#"Item 1"];
[popupbutton addItemWithTitle:#"Item 2"];
[popupbutton setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:popupbutton];
checkbox = [[NSButton alloc] initWithFrame:NSZeroRect];
[checkbox setTitle:#"Spaced"];
[checkbox setButtonType:NSSwitchButton];
[checkbox setBordered:NO];
[checkbox setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
[checkbox setTarget:self];
[checkbox setAction:#selector(onChecked:)];
[checkbox setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:checkbox];
[contentView addSubview:containerView];
relayout(NO);
[mainwin cascadeTopLeftFromPoint:NSMakePoint(20, 20)];
[mainwin makeKeyAndOrderFront:mainwin];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
{
return YES;
}
#end
int main(int argc, char *argv[])
{
useInsets = (argc > 1);
NSApplication *app = [NSApplication sharedApplication];
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
[app setDelegate:[appDelegate new]];
[app run];
return 0;
}

Programmatically add a close button to an NSWindow

I'd like to add a close button to an NSWindow programmatically. I can get the button to display, but there are no mouse-over or mouse-down effects. My "selector" never seems to get called when i click the button. I'm not really sure whats wrong and why this is so annoying.
Here is what I've been messing with:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
NSRect c = [themeFrame frame]; // c for "container"
NSRect aV = [closeButton frame]; // aV for "accessory view"
NSRect newFrame = NSMakeRect( c.size.width - aV.size.width - 5, // x position c.size.height - aV.size.height - 5, // y position aV.size.width, // width aV.size.height); // height
[closeButton setFrame:newFrame];
[themeFrame addSubview:closeButton];
[closeButton setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[closeButton setEnabled:YES];
[closeButton setTarget:self];
[closeButton setAction:NSSelectorFromString(#"testClick:") ];
Where "testClick" is just a memeber function of my class and is defined as such:
- (void)testClick:(id)sender
The problem seems to be the call to:
[themeFrame addSubview:closeButton];
where the themeFrame is: [[self contentView] superview] Just adding the button to [self contentView] works, but I'd like it added to the titlebar.
No Interface Builder please...
Potential issue # 1)
The way you're calling "NSSelectorFromString" seems incorrect to me. I don't think you can pass parameters via this way in Objective C.
Try this:
[closeButton setAction: #selector(closeWindow:)];
and create a new "closeWindow:" action that looks like:
- (void) closeWindow: (id) sender;
which closes the window.
Potential issue # 2)
Instead of:
closeButton = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
NSView *themeFrame = [[self contentView] superview];
Why not use:
NSWindow * parentWindow = [[self contentView] window];
if(parentWindow)
{
closeButton = [parentWindow standardWindowButton:NSWindowCloseButton forStyleMask:self.styleMask];
}

How to flash a custom NSMenuItem view after selection?

I need to assign a view to an NSMenuItem and do some custom drawing. Basically, I'm adding a little delete button next to the currently selected menu item, among other things. But I want my custom menu item to look and behave like a regular menu item in all other ways. According to the doc:
A menu item with a view does not draw
its title, state, font, or other
standard drawing attributes, and
assigns drawing responsibility
entirely to the view.
Ok, so I had to duplicate the look of the state column and the selection gradient, which wasn't that hard. The part I'm having trouble with is the way the menu item "flashes" or "blinks" after it is selected. I'm using an NSTimer to try to mimic this little animation, but it just feels off. How many times does it blink? What time interval should I use? I've experimented a lot and it just feels out of whack.
Has anyone done this before or have other suggestions on how to add a button to a menu item? Maybe there should be a stack exchange site just for custom cocoa drawing...
I know this is over a year old, but this was the first hit on my Google search and was unanswered, so I'm posting my answer for sake of those still looking for a solution.
For my app, I used Core Animation with a custom NSView for the NSMenuItem view. I created a new layer-backed view, set the background color, and added it to my custom view. I then animated the layer (the flashing part). Then in the -(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag callback, I removed the overlay and closed the menu. This doesn't perfectly match the default NSMenu's flash, but I wanted a 37Signals/Stack Overflow Yellow Fade Technique, so it works for me. Here it is in code:
-(void) mouseUp:(NSEvent *)theEvent {
CALayer *layer = [CALayer layer];
[layer setDelegate:self];
[layer setBackgroundColor:CGColorCreateGenericRGB(0.0, 0.0, 1.0, 1.0)];
selectionOverlayView = [[NSView alloc] init];
[selectionOverlayView setWantsLayer:YES];
[selectionOverlayView setFrame:self.frame];
[selectionOverlayView setLayer:layer];
[[selectionOverlayView layer] setNeedsDisplay];
[selectionOverlayView setAlphaValue:0.0];
[self addSubview:selectionOverlayView];
CABasicAnimation *alphaAnimation1 = [CABasicAnimation animationWithKeyPath: #"alphaValue"];
alphaAnimation1.beginTime = 0.0;
alphaAnimation1.fromValue = [NSNumber numberWithFloat: 0.0];
alphaAnimation1.toValue = [NSNumber numberWithFloat: 1.0];
alphaAnimation1.duration = 0.07;
CABasicAnimation *alphaAnimation2 = [CABasicAnimation animationWithKeyPath: #"alphaValue"];
alphaAnimation2.beginTime = 0.07;
alphaAnimation2.fromValue = [NSNumber numberWithFloat: 1.0];
alphaAnimation2.toValue = [NSNumber numberWithFloat: 0.0];
alphaAnimation2.duration = 0.07;
CAAnimationGroup *selectionAnimation = [CAAnimationGroup animation];
selectionAnimation.delegate = self;
selectionAnimation.animations = [NSArray arrayWithObjects:alphaAnimation1, alphaAnimation2, nil];
selectionAnimation.duration = 0.14;
[selectionOverlayView setAnimations:[NSDictionary dictionaryWithObject:selectionAnimation forKey:#"frameOrigin"]];
[[selectionOverlayView animator] setFrame:[selectionOverlayView frame]];
}
-(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
[selectionOverlayView removeFromSuperview];
NSMenuItem *enclosingMenuItem = [self enclosingMenuItem];
NSMenu *enclosingMenu = [enclosingMenuItem menu];
[enclosingMenu cancelTracking];
[enclosingMenu performActionForItemAtIndex:[enclosingMenu indexOfItem:enclosingMenuItem]];
}
It is actually possible to have your custom view flash like a regular NSMenuItem without implementing the animation manually.
Note: this uses a private API and also fixes a handful of other strange NSMenuItem quirks related to custom views.
NSMenuItem.h
#import <AppKit/AppKit.h>
#interface NSMenuItem ()
- (BOOL)_viewHandlesEvents;
#end
Bridging Header
#import "NSMenuItem.h"
MenuItem.swift
class MenuItem: NSMenuItem {
override func _viewHandlesEvents() -> Bool {
return false
}
}
This API really ought to be public, and if you're not developing for the App Store, it might be worth having a look at.
Here is my code that flashes a custom menu item.
int16_t fireTimes;
BOOL isSelected;
- (void)mouseEntered:(NSEvent*)event
{
isSelected = YES;
}
- (void)mouseUp:(NSEvent*)event {
fireTimes = 0;
isSelected = !isSelected;
[self setNeedsDisplay:YES];
NSTimer *timer = [NSTimer timerWithTimeInterval:0.05 target:self selector:#selector(animateDismiss:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
}
-(void)animateDismiss:(NSTimer *)aTimer
{
if (fireTimes <= 2) {
isSelected = !isSelected;
[self setNeedsDisplay:YES];
} else {
[aTimer invalidate];
[self sendAction];
}
fireTimes++;
}
- (void)drawRect:(NSRect)dirtyRect {
if (isSelected) {
NSRect frame = NSInsetRect([self frame], -4.0f, -4.0f);
[[NSColor selectedMenuItemColor] set];
NSRectFill(frame);
[itemNameFld setTextColor:[NSColor whiteColor]];
} else {
[itemNameFld setTextColor:[NSColor blackColor]];
}
}
- (void)sendAction
{
NSMenuItem *actualMenuItem = [self enclosingMenuItem];
[NSApp sendAction:[actualMenuItem action] to:[actualMenuItem target] from:actualMenuItem];
NSMenu *menu = [actualMenuItem menu];
[menu cancelTracking];
// [self setNeedsDisplay:YES]; // I'm not sure of this
}

Setting Position of NSWindow before Display

Right now I'm setting the position of a window that is about to open like this:
-(void) setActiveNodeDialog:(ISKNodeDialogController *)dialog
{
if (activeNodeDialog)
[[activeNodeDialog window] close];
activeNodeDialog = dialog;
if (activeNodeDialog) {
[activeNodeDialog setMainWindowController:self];
NSRect windowRect = [[self window] frame];
NSRect dialogRect = [[activeNodeDialog window] frame];
NSPoint pos;
pos.x = windowRect.origin.x + windowRect.size.width - dialogRect.size.width - 10;
pos.y = windowRect.origin.y + 32;
[[activeNodeDialog window] setFrameOrigin:pos];
[[activeNodeDialog window] makeKeyAndOrderFront:nil];
}
}
The problem with that is, that the window will "jump" when shown. And that even though I set the position before showing the window with "makeKeyAndOrderFront". The window is a NSPanel *. Anyone any ideas how to fix the jumping?
Setting the position in awakeFromNib is not an option because the main controller is set later.
In Interface Builder, is "visible at launch" checked for the window? If so uncheck it and then you won't even need this code [[activeNodeDialog window] close];. Basically if that is checked then the window is automatically shown when the xib is instantiated... which you don't want.

Resources