mirror of
https://github.com/textmate/textmate.git
synced 2026-02-14 16:34:57 -05:00
165 lines
4.7 KiB
Plaintext
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
|