mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-30 16:10:37 +00:00
Open on side away from the edge of the screen if there is not enough room
This commit is contained in:
parent
e573b5ce09
commit
3f1e8af9c4
1 changed files with 128 additions and 79 deletions
|
@ -42,27 +42,32 @@
|
||||||
#import "AppKit/NSView.h"
|
#import "AppKit/NSView.h"
|
||||||
#import "AppKit/NSDrawer.h"
|
#import "AppKit/NSDrawer.h"
|
||||||
#import "AppKit/NSGraphics.h"
|
#import "AppKit/NSGraphics.h"
|
||||||
|
#import "AppKit/NSScreen.h"
|
||||||
|
|
||||||
static NSNotificationCenter *nc = nil;
|
static NSNotificationCenter *nc = nil;
|
||||||
|
|
||||||
@interface GSDrawerWindow : NSWindow
|
@interface GSDrawerWindow : NSWindow
|
||||||
{
|
{
|
||||||
NSWindow *_parentWindow;
|
NSWindow *_parentWindow;
|
||||||
NSWindow *_pendingParentWindow;
|
NSWindow *_pendingParentWindow;
|
||||||
NSDrawer *_drawer;
|
NSDrawer *_drawer;
|
||||||
id _container;
|
id _container;
|
||||||
NSBox *_borderBox;
|
NSBox *_borderBox;
|
||||||
NSSize _borderSize;
|
NSSize _borderSize;
|
||||||
NSTimer *_timer;
|
NSTimer *_timer;
|
||||||
NSRect _latestParentFrame;
|
NSRect _latestParentFrame;
|
||||||
BOOL _wasOpen;
|
BOOL _wasOpen;
|
||||||
|
NSRectEdge _currentEdge;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSRect) frameFromParentWindowFrameInState:(NSInteger)state;
|
- (NSRect) frameFromParentWindowFrameInState:(NSInteger)state;
|
||||||
|
|
||||||
// open/close
|
// open/close
|
||||||
- (void) openOnEdge;
|
- (void) openOnEdge: (NSRectEdge)edge;
|
||||||
|
- (void) closeOnEdge: (NSRectEdge)edge;
|
||||||
- (void) closeOnEdge;
|
- (void) closeOnEdge;
|
||||||
- (void) slideOpen:(BOOL)opening;
|
- (void) slideOpen: (BOOL)opening onEdge: (NSRectEdge)edge;
|
||||||
|
- (void) slideOpen: (BOOL)opening;
|
||||||
- (void) startTimer;
|
- (void) startTimer;
|
||||||
- (void) stopTimer;
|
- (void) stopTimer;
|
||||||
|
|
||||||
|
@ -80,9 +85,11 @@ static NSNotificationCenter *nc = nil;
|
||||||
- (void) handleWindowMiniaturize: (NSNotification *)notification;
|
- (void) handleWindowMiniaturize: (NSNotification *)notification;
|
||||||
- (void) handleWindowDeminiaturize: (NSNotification *)notification;
|
- (void) handleWindowDeminiaturize: (NSNotification *)notification;
|
||||||
- (void) handleWindowMove: (NSNotification *)notification;
|
- (void) handleWindowMove: (NSNotification *)notification;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSDrawerWindow
|
@implementation GSDrawerWindow
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
if (self == [GSDrawerWindow class])
|
if (self == [GSDrawerWindow class])
|
||||||
|
@ -151,15 +158,16 @@ static NSNotificationCenter *nc = nil;
|
||||||
return _container;
|
return _container;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSRect) frameFromParentWindowFrameInState:(NSInteger)state
|
- (NSRect) frameFromParentWindowFrameInState: (NSInteger)state
|
||||||
{
|
{
|
||||||
NSRect newFrame = [_parentWindow frame];
|
NSRect newFrame = [_parentWindow frame];
|
||||||
CGFloat totalOffset = [_drawer leadingOffset] + [_drawer trailingOffset];
|
CGFloat totalOffset = [_drawer leadingOffset] + [_drawer trailingOffset];
|
||||||
NSRectEdge edge = [_drawer preferredEdge];
|
NSRectEdge edge = _currentEdge; // [_drawer preferredEdge];
|
||||||
BOOL opened = (state == NSDrawerOpenState || state == NSDrawerOpeningState);
|
BOOL opened = (state == NSDrawerOpenState || state == NSDrawerOpeningState);
|
||||||
NSSize size = [_parentWindow frame].size; // [_drawer maxContentSize];
|
NSSize size = [_parentWindow frame].size;
|
||||||
NSRect windowContentRect = [[_parentWindow contentView] frame];
|
NSRect windowContentRect = [[_parentWindow contentView] frame];
|
||||||
CGFloat windowHeightWithoutTitleBar = windowContentRect.origin.y + windowContentRect.size.height; // FIXME: This should probably add the toolbar height too, if the window has a toolbar
|
CGFloat windowHeightWithoutTitleBar = windowContentRect.origin.y + windowContentRect.size.height;
|
||||||
|
// FIXME: This should probably add the toolbar height too, if the window has a toolbar
|
||||||
|
|
||||||
if (edge == NSMinXEdge) // left
|
if (edge == NSMinXEdge) // left
|
||||||
{
|
{
|
||||||
|
@ -215,8 +223,6 @@ static NSNotificationCenter *nc = nil;
|
||||||
return newFrame;
|
return newFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- (BOOL) canBecomeKeyWindow
|
- (BOOL) canBecomeKeyWindow
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -229,42 +235,18 @@ static NSNotificationCenter *nc = nil;
|
||||||
|
|
||||||
- (void) becomeKeyWindow
|
- (void) becomeKeyWindow
|
||||||
{
|
{
|
||||||
[_parentWindow orderFrontRegardless]; // so clicking on the drawer will bring the parent to the front
|
[_parentWindow orderFrontRegardless]; // so clicking on the drawer will bring the parent to the front
|
||||||
[super becomeKeyWindow];
|
[super becomeKeyWindow];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
- (void) orderFront: (id)sender
|
|
||||||
{
|
|
||||||
NSPoint holdOrigin = [self frame].origin;
|
|
||||||
NSPoint newOrigin = NSMakePoint(-10000,-10000);
|
|
||||||
NSRect tempFrame = [self frame];
|
|
||||||
|
|
||||||
// order the window under the parent...
|
|
||||||
tempFrame.origin = newOrigin;
|
|
||||||
[self setFrame: tempFrame display: NO];
|
|
||||||
[super orderFront: sender];
|
|
||||||
// [_parentWindow orderWindow: NSWindowAbove relativeTo: [self windowNumber]];
|
|
||||||
tempFrame.origin = holdOrigin;
|
|
||||||
// [self setFrame: tempFrame display: YES];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
- (void) orderFront: (id)sender
|
|
||||||
{
|
|
||||||
[super orderWindow:NSWindowBelow relativeTo:[_parentWindow windowNumber]];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
- (void) startTimer
|
- (void) startTimer
|
||||||
{
|
{
|
||||||
NSTimeInterval time = 0.1;
|
NSTimeInterval time = 0.1;
|
||||||
_timer = [NSTimer scheduledTimerWithTimeInterval: time
|
_timer = [NSTimer scheduledTimerWithTimeInterval: time
|
||||||
target: self
|
target: self
|
||||||
selector: @selector(_timedWindowReset)
|
selector: @selector(_timedWindowReset)
|
||||||
userInfo: nil
|
userInfo: nil
|
||||||
repeats: YES];
|
repeats: YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) stopTimer
|
- (void) stopTimer
|
||||||
|
@ -283,19 +265,13 @@ static NSNotificationCenter *nc = nil;
|
||||||
[super orderOut: sender];
|
[super orderOut: sender];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// set the _borderBox to not resize during the slide,
|
||||||
- (void) orderWindow: (NSWindowOrderingMode)place relativeTo: (int)windowNum
|
// and attach it to the appropriate edge instead
|
||||||
{
|
|
||||||
NSLog(@"Ordering window....");
|
|
||||||
[super orderWindow: place relativeTo: windowNum];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
- (void) lockBorderBoxForSliding
|
- (void) lockBorderBoxForSliding
|
||||||
{
|
{
|
||||||
// set the _borderBox to not resize during the slide, and attach it to the appropriate edge instead
|
|
||||||
NSRectEdge edge = [_drawer preferredEdge];
|
NSRectEdge edge = [_drawer preferredEdge];
|
||||||
NSUInteger resizeMask = 0;
|
NSUInteger resizeMask = 0;
|
||||||
|
|
||||||
if (edge == NSMinXEdge) // left
|
if (edge == NSMinXEdge) // left
|
||||||
{
|
{
|
||||||
resizeMask = NSViewMaxXMargin;
|
resizeMask = NSViewMaxXMargin;
|
||||||
|
@ -312,7 +288,9 @@ static NSNotificationCenter *nc = nil;
|
||||||
{
|
{
|
||||||
resizeMask = NSViewMinYMargin;
|
resizeMask = NSViewMinYMargin;
|
||||||
}
|
}
|
||||||
[_borderBox setAutoresizingMask: resizeMask]; // don't resize -- just give appearance of sliding
|
|
||||||
|
// don't resize -- just give appearance of sliding
|
||||||
|
[_borderBox setAutoresizingMask: resizeMask];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) unlockBorderBoxAfterSliding
|
- (void) unlockBorderBoxAfterSliding
|
||||||
|
@ -321,28 +299,34 @@ static NSNotificationCenter *nc = nil;
|
||||||
[_borderBox setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
|
[_borderBox setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) openOnEdge
|
// prepare drawer contents before sliding...
|
||||||
|
- (void) openOnEdge: (NSRectEdge)edge
|
||||||
{
|
{
|
||||||
// prepare drawer contents before sliding...
|
|
||||||
NSRect frame = [self frameFromParentWindowFrameInState:NSDrawerOpenState];
|
NSRect frame = [self frameFromParentWindowFrameInState:NSDrawerOpenState];
|
||||||
|
|
||||||
[self setFrame:frame display: YES]; // make sure it's the full (open) size before locking the borderBox
|
[self setFrame:frame display: YES]; // make sure it's the full (open) size before locking the borderBox
|
||||||
if ([_parentWindow isVisible]) // don't order front until parent window is visible
|
if ([_parentWindow isVisible]) // don't order front until parent window is visible
|
||||||
{
|
{
|
||||||
[self lockBorderBoxForSliding];
|
[self lockBorderBoxForSliding];
|
||||||
|
[self slideOpen: YES onEdge: edge];
|
||||||
[self orderFront: self];
|
[self orderFront: self];
|
||||||
[self slideOpen:YES];
|
|
||||||
[self performSelector:@selector(unlockBorderBoxAfterSliding) withObject:nil afterDelay:0.01];
|
[self performSelector:@selector(unlockBorderBoxAfterSliding) withObject:nil afterDelay:0.01];
|
||||||
}
|
}
|
||||||
[self startTimer];
|
[self startTimer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) closeOnEdge
|
- (void) openOnEdge
|
||||||
|
{
|
||||||
|
[self openOnEdge: _currentEdge];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) closeOnEdge: (NSRectEdge)edge
|
||||||
{
|
{
|
||||||
NSRect frame;
|
NSRect frame;
|
||||||
|
|
||||||
[self stopTimer];
|
[self stopTimer];
|
||||||
[self lockBorderBoxForSliding];
|
[self lockBorderBoxForSliding];
|
||||||
[self slideOpen:NO];
|
[self slideOpen: NO onEdge: edge];
|
||||||
[self orderOut: self];
|
[self orderOut: self];
|
||||||
|
|
||||||
frame = [self frameFromParentWindowFrameInState:NSDrawerOpenState];
|
frame = [self frameFromParentWindowFrameInState:NSDrawerOpenState];
|
||||||
|
@ -353,21 +337,30 @@ static NSNotificationCenter *nc = nil;
|
||||||
&& _pendingParentWindow != _parentWindow)
|
&& _pendingParentWindow != _parentWindow)
|
||||||
{
|
{
|
||||||
[self setParentWindow: _pendingParentWindow];
|
[self setParentWindow: _pendingParentWindow];
|
||||||
ASSIGN(_pendingParentWindow, nil);
|
_pendingParentWindow = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) slideOpen:(BOOL)opening
|
- (void) closeOnEdge
|
||||||
{
|
{
|
||||||
NSRect frame = [self frameFromParentWindowFrameInState:(opening?NSDrawerClosedState:NSDrawerOpenState)];
|
[self closeOnEdge: _currentEdge];
|
||||||
NSRect newFrame = [self frameFromParentWindowFrameInState:(opening?NSDrawerOpenState:NSDrawerClosedState)];
|
}
|
||||||
|
|
||||||
|
- (void) slideOpen: (BOOL)opening onEdge: (NSRectEdge)edge
|
||||||
|
{
|
||||||
|
NSUInteger count = 10;
|
||||||
|
NSRect frame = [self frameFromParentWindowFrameInState:
|
||||||
|
(opening?NSDrawerClosedState:NSDrawerOpenState)];
|
||||||
|
NSRect newFrame = [self frameFromParentWindowFrameInState:
|
||||||
|
(opening?NSDrawerOpenState:NSDrawerClosedState)];
|
||||||
NSTimeInterval slideDelay = 0.03;
|
NSTimeInterval slideDelay = 0.03;
|
||||||
NSDate *nextStop = [NSDate dateWithTimeIntervalSinceNow:slideDelay];
|
NSDate *nextStop = [NSDate dateWithTimeIntervalSinceNow:slideDelay];
|
||||||
int count = 10;
|
|
||||||
CGFloat deltaX = (newFrame.origin.x - frame.origin.x) / count;
|
CGFloat deltaX = (newFrame.origin.x - frame.origin.x) / count;
|
||||||
CGFloat deltaY = (newFrame.origin.y - frame.origin.y) / count;
|
CGFloat deltaY = (newFrame.origin.y - frame.origin.y) / count;
|
||||||
CGFloat deltaW = (newFrame.size.width - frame.size.width) / count;
|
CGFloat deltaW = (newFrame.size.width - frame.size.width) / count;
|
||||||
CGFloat deltaH = (newFrame.size.height - frame.size.height) / count;
|
CGFloat deltaH = (newFrame.size.height - frame.size.height) / count;
|
||||||
|
|
||||||
|
_currentEdge = edge;
|
||||||
while (count--)
|
while (count--)
|
||||||
{
|
{
|
||||||
frame.origin.x += deltaX;
|
frame.origin.x += deltaX;
|
||||||
|
@ -376,11 +369,17 @@ static NSNotificationCenter *nc = nil;
|
||||||
frame.size.height += deltaH;
|
frame.size.height += deltaH;
|
||||||
[self setFrame: frame display: YES];
|
[self setFrame: frame display: YES];
|
||||||
[NSThread sleepUntilDate:nextStop];
|
[NSThread sleepUntilDate:nextStop];
|
||||||
nextStop = [nextStop addTimeInterval:slideDelay];
|
nextStop = [nextStop addTimeInterval: slideDelay];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self setFrame:newFrame display: YES];
|
[self setFrame:newFrame display: YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) slideOpen: (BOOL)opening
|
||||||
|
{
|
||||||
|
[self slideOpen: opening onEdge: _currentEdge];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) _resetWindowPosition
|
- (void) _resetWindowPosition
|
||||||
{
|
{
|
||||||
if ([_parentWindow isVisible]) // don't set our frame until parent window is visible
|
if ([_parentWindow isVisible]) // don't set our frame until parent window is visible
|
||||||
|
@ -552,6 +551,10 @@ static NSNotificationCenter *nc = nil;
|
||||||
preferredEdge: (NSRectEdge)edge
|
preferredEdge: (NSRectEdge)edge
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
|
||||||
|
if (self == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
// initialize the drawer window...
|
// initialize the drawer window...
|
||||||
_drawerWindow = [[GSDrawerWindow alloc]
|
_drawerWindow = [[GSDrawerWindow alloc]
|
||||||
initWithContentRect: NSMakeRect(0, 0, contentSize.width,
|
initWithContentRect: NSMakeRect(0, 0, contentSize.width,
|
||||||
|
@ -565,14 +568,19 @@ static NSNotificationCenter *nc = nil;
|
||||||
_preferredEdge = edge;
|
_preferredEdge = edge;
|
||||||
_currentEdge = edge;
|
_currentEdge = edge;
|
||||||
_maxContentSize = NSMakeSize(200,200);
|
_maxContentSize = NSMakeSize(200,200);
|
||||||
_minContentSize = contentSize; //NSMakeSize(50,50);
|
_minContentSize = contentSize;
|
||||||
if (edge == NSMinXEdge || edge == NSMaxXEdge) {
|
|
||||||
_leadingOffset = 0.0; // for side drawers, top of drawer is immediately below the title bar
|
// for side drawers, top of drawer is immediately below the title bar
|
||||||
_trailingOffset = 10.0;
|
if (edge == NSMinXEdge || edge == NSMaxXEdge)
|
||||||
} else {
|
{
|
||||||
_leadingOffset = 10.0;
|
_leadingOffset = 0.0;
|
||||||
_trailingOffset = 10.0;
|
_trailingOffset = 10.0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_leadingOffset = 10.0;
|
||||||
|
_trailingOffset = 10.0;
|
||||||
|
}
|
||||||
_state = NSDrawerClosedState;
|
_state = NSDrawerClosedState;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -590,6 +598,46 @@ static NSNotificationCenter *nc = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opening and Closing
|
// Opening and Closing
|
||||||
|
- (NSRectEdge) _computeEdge
|
||||||
|
{
|
||||||
|
NSRectEdge result = _preferredEdge;
|
||||||
|
NSRect windowFrame = [[self parentWindow] frame];
|
||||||
|
NSRect screenRect = [[NSScreen mainScreen] frame];
|
||||||
|
|
||||||
|
switch (_preferredEdge)
|
||||||
|
{
|
||||||
|
case NSMinXEdge:
|
||||||
|
if (windowFrame.origin.x < _maxContentSize.width)
|
||||||
|
{
|
||||||
|
result = NSMaxXEdge;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSMinYEdge:
|
||||||
|
if (windowFrame.origin.y < _maxContentSize.height)
|
||||||
|
{
|
||||||
|
result = NSMaxYEdge;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSMaxXEdge:
|
||||||
|
if (windowFrame.origin.x + windowFrame.size.height > screenRect.size.height)
|
||||||
|
{
|
||||||
|
result = NSMinXEdge;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSMaxYEdge:
|
||||||
|
if (windowFrame.origin.y + windowFrame.size.width > screenRect.size.width)
|
||||||
|
{
|
||||||
|
result = NSMinYEdge;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) close
|
- (void) close
|
||||||
{
|
{
|
||||||
if (_state != NSDrawerOpenState)
|
if (_state != NSDrawerOpenState)
|
||||||
|
@ -616,7 +664,8 @@ static NSNotificationCenter *nc = nil;
|
||||||
|
|
||||||
- (void) open
|
- (void) open
|
||||||
{
|
{
|
||||||
[self openOnEdge: _preferredEdge];
|
NSRectEdge edge = [self _computeEdge];
|
||||||
|
[self openOnEdge: edge];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) open: (id)sender
|
- (void) open: (id)sender
|
||||||
|
@ -639,7 +688,7 @@ static NSNotificationCenter *nc = nil;
|
||||||
[nc postNotificationName: NSDrawerWillOpenNotification object: self];
|
[nc postNotificationName: NSDrawerWillOpenNotification object: self];
|
||||||
|
|
||||||
_currentEdge = edge;
|
_currentEdge = edge;
|
||||||
[_drawerWindow openOnEdge];
|
[_drawerWindow openOnEdge: edge];
|
||||||
|
|
||||||
_state = NSDrawerOpenState;
|
_state = NSDrawerOpenState;
|
||||||
[nc postNotificationName: NSDrawerDidOpenNotification object: self];
|
[nc postNotificationName: NSDrawerDidOpenNotification object: self];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue