Files
textmate/Frameworks/OakAppKit/src/OakWindowFrameHelper.mm
Allan Odgaard 9894969e67 Initial commit
2012-08-09 16:25:56 +02:00

165 lines
4.7 KiB
Plaintext

#import "OakWindowFrameHelper.h"
#import "NSScreen Additions.h"
#import <oak/CocoaSTL.h>
OAK_DEBUG_VAR(WindowFrameHelper);
@interface OakWindowFrameHelper ()
- (id)initWithWindow:(NSWindow*)aWindow;
- (void)placeAndSizeWindow:(NSWindow*)aWindow;
- (void)snapshotWindowFrame;
@property (nonatomic, retain) NSWindow* window;
@property (nonatomic, retain) NSString* autosaveName;
@end
@implementation OakWindowFrameHelper
@synthesize window, autosaveName;
+ (OakWindowFrameHelper*)windowFrameHelperWithWindow:(NSWindow*)aWindow
{
return [[[self alloc] initWithWindow:aWindow] autorelease];
}
- (id)initWithWindow:(NSWindow*)aWindow
{
if((self = [super init]))
{
windowDelegateClass = [[aWindow delegate] class];
self.autosaveName = [NSString stringWithFormat:@"%@WindowFrame", NSStringFromClass(windowDelegateClass)];
D(DBF_WindowFrameHelper, bug("Auto-save name: %s\n", [autosaveName UTF8String]););
if([[aWindow delegate] isKindOfClass:[NSWindowController class]])
[(NSWindowController*)[aWindow delegate] setShouldCascadeWindows:NO];
[self placeAndSizeWindow:aWindow];
self.window = aWindow;
}
return self;
}
- (void)dealloc
{
self.window = nil;
self.autosaveName = nil;
[super dealloc];
}
- (void)setWindow:(NSWindow*)newWindow
{
NSWindow* oldWindow = window;
if(oldWindow == newWindow)
return;
if(window = [newWindow retain])
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMoveOrResize:) name:NSWindowDidMoveNotification object:window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMoveOrResize:) name:NSWindowDidResizeNotification object:window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:window];
[self retain]; // as long as we are observing the window, we want to be retained
}
if(oldWindow)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidMoveNotification object:oldWindow];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:oldWindow];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:oldWindow];
[oldWindow release];
[self release];
}
}
- (void)windowDidMoveOrResize:(NSNotification*)aNotification
{
D(DBF_WindowFrameHelper, bug("\n"););
[self snapshotWindowFrame];
}
- (void)windowWillClose:(NSNotification*)aNotification
{
D(DBF_WindowFrameHelper, bug("\n"););
[self snapshotWindowFrame];
self.window = nil;
}
// ====================
// = The Actual Logic =
// ====================
- (void)snapshotWindowFrame
{
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromRect([window frame]) forKey:self.autosaveName];
}
- (BOOL)ignoreWindow:(NSWindow*)aWindow
{
return !([aWindow isVisible] && [[aWindow delegate] isKindOfClass:windowDelegateClass]);
}
- (void)placeAndSizeWindow:(NSWindow*)aWindow
{
NSString* rectStr = [[NSUserDefaults standardUserDefaults] stringForKey:self.autosaveName];
NSRect r = rectStr ? NSRectFromString(rectStr) : NSZeroRect;
NSWindow* lowerWin = nil;
CGFloat winYPos = CGFLOAT_MAX;
for(NSWindow* win in [NSApp windows])
{
if([self ignoreWindow:win])
continue;
D(DBF_WindowFrameHelper, bug("window @ %s (%s)\n", [NSStringFromRect([win frame]) UTF8String], [[[[win delegate] class] description] UTF8String]););
if(NSMaxY([win frame]) < winYPos)
{
winYPos = NSMaxY([win frame]);
lowerWin = win;
}
}
if(lowerWin)
{
D(DBF_WindowFrameHelper, bug("cascade window\n"););
r = [lowerWin frame];
[aWindow setFrame:r display:NO];
r.origin = [aWindow cascadeTopLeftFromPoint:NSMakePoint(NSMinX(r), NSMaxY(r))];
r.origin.y -= r.size.height;
NSRect scrRect = [[NSScreen mainScreen] visibleFrame];
if(!NSContainsRect(scrRect, r))
{
r.origin.x = 61;
r.origin.y = NSMaxY(scrRect) - NSHeight(r);
bool alreadyHasWrappedWindow = false;
for(NSWindow* win in [NSApp windows])
{
if([self ignoreWindow:win])
continue;
if(NSEqualPoints([win frame].origin, r.origin))
alreadyHasWrappedWindow = true;
}
if(alreadyHasWrappedWindow)
{
NSWindow* win = [NSApp mainWindow];
if([[win delegate] isKindOfClass:windowDelegateClass])
{
r = [win frame];
[aWindow setFrame:r display:NO];
r.origin = [aWindow cascadeTopLeftFromPoint:NSMakePoint(NSMinX(r), NSMaxY(r))];
r.origin.y -= r.size.height;
}
}
}
}
else if(NSEqualRects(r, NSZeroRect))
{
D(DBF_WindowFrameHelper, bug("center window\n"););
r = [[NSScreen mainScreen] visibleFrame];
r = NSIntegralRect(NSInsetRect(r, NSWidth(r) / 3, NSHeight(r) / 5));
}
[aWindow setFrame:[[NSScreen screenWithFrame:r] restrainFrameToVisibleScreen:r] display:NO];
}
@end