diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index 26aa821e6..626d36718 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -719,9 +719,40 @@ CPRunContinuesResponse = -1002; */ - (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo { + var styleMask = [aSheet styleMask]; + if (!(styleMask & CPDocModalWindowMask)) + { + [CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"]; + return; + } + [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo]; } +- (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode +{ + var count = [_windows count]; + + while (--count >= 0) + { + var aWindow = [_windows objectAtIndex:count]; + var context = aWindow._sheetContext; + + if (context != nil && context["sheet"] === sheet) + { + context["returnCode"] = returnCode; + [aWindow _detachSheetWindow]; + return; + } + } +} + +- (void)endSheet:(CPWindow)sheet +{ + [self endSheet:sheet returnCode:0]; +} + + - (CPArray)arguments { if(_fullArgsString != window.location.hash) diff --git a/AppKit/CPPanel.j b/AppKit/CPPanel.j index 65dc9b177..61480d50a 100644 --- a/AppKit/CPPanel.j +++ b/AppKit/CPPanel.j @@ -46,6 +46,13 @@ CPCancelButton = 0;
  • A panel can be made to work even when there's an attention panel on-screen. This permits actions within the panel to affect the attention panel.
  • */ + +/* + @global + @class CPWindow +*/ +CPDocModalWindowMask = 1 << 6; + @implementation CPPanel : CPWindow { BOOL _becomesKeyOnlyIfNeeded; diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 7dc79c3ca..a341b0852 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -309,6 +309,8 @@ var CPWindowSaveImage = nil, BOOL _isFullPlatformWindow; _CPWindowFullPlatformWindowSession _fullPlatformWindowSession; + + CPDictionary _sheetContext; } /* @@ -439,7 +441,10 @@ CPTexturedBackgroundWindowMask else if (aStyleMask === CPBorderlessWindowMask) return _CPBorderlessWindowView; - + + else if (aStyleMask & CPDocModalWindowMask) + return _CPDocModalWindowView; + return _CPStandardWindowView; } @@ -1722,57 +1727,146 @@ CPTexturedBackgroundWindowMask */ } +- (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve +{ + var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame]; + [animation setDelegate:delegate]; + [animation setAnimationCurve:curve]; + [animation setDuration:duration]; + [animation startAnimation]; +} + /* @ignore */ - (void)_setAttachedSheetFrameOrigin { // Position the sheet above the contentRect. + var attachedSheet = [self attachedSheet]; var contentRect = [[self contentView] frame], - sheetFrame = CGRectMakeCopy([_attachedSheet frame]); + sheetFrame = CGRectMakeCopy([attachedSheet frame]); sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect); sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0); - [_attachedSheet setFrameOrigin:sheetFrame.origin]; -} - -/* @ignore */ -- (void)_animateAttachedSheet -{ -/* NSWindow *sheet = [sheetContext sheet]; - NSRect sheetFrame; - - [_sheetContext autorelease]; - _sheetContext=[sheetContext retain]; - - [self _setSheetOrigin]; - sheetFrame = [sheet frame]; - - [(NSWindowBackgroundView *)[sheet _backgroundView] setBorderType:NSButtonBorder]; - [[sheet contentView] setAutoresizesSubviews:NO]; - [[sheet contentView] setAutoresizingMask:NSViewNotSizable]; - -// [(NSWindowBackgroundView *)[sheet _backgroundView] cacheImageForAnimation]; - - [_attachedSheet setFrame:CPRectMake(CGRectGetMinX(sheetFrame), CGRectGetMinY(sheetFrame), CGRectGetWidth(sheetFrame), 0.0) display:YES]; - [sheet setFrame:NSMakeRect(sheetFrame.origin.x, NSMaxY([self frame]), sheetFrame.size.width, 0) display:YES]; - [self _setSheetOriginAndFront]; - - [sheet setFrame:sheetFrame display:YES animate:YES];*/ + [attachedSheet setFrameOrigin:sheetFrame.origin]; } /* @ignore */ - (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo { - // Set this as our attached sheet. - _attachedSheet = aSheet; + var sheetFrame = [aSheet frame]; + +// setup contexts + _sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO}; + + [self _attachSheetWindow:aSheet]; +} + +/* @ignore */ +- (void)_attachSheetWindow:(CPWindow)aSheet +{ + var sheetFrame = [aSheet frame], + frame = [self frame], + sheetContent = [aSheet contentView]; - // If a window is ever run as a sheet, then it's sheet bit is set to YES. +// Configure sheet. +// if ([aSheet styleMask] & CPHUDBackgroundWindowMask) +// [aSheet setMovableByWindowBackground:NO]; + + _sheetContext["autoresizingMask"] = [sheetContent autoresizingMask]; + [sheetContent setAutoresizingMask:CPViewMinYMargin]; + [sheetContent setAutoresizesSubviews:NO]; aSheet._isSheet = YES; + aSheet._parentView = self; - [self _setAttachedSheetFrameOrigin]; +// calculate start/end frames + var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width)/2); + var originy = frame.origin.y + [[self contentView] frame].origin.y; + var startFrame = CGRectMake(originx, originy , sheetFrame.size.width, 0); + var endFrame = CGRectMake(originx, originy ,sheetFrame.size.width,sheetFrame.size.height); + +// Notify the world we will open the sheet + [[CPNotificationCenter defaultCenter] postNotificationName:@"CPWindowWillBeginSheetNotification" object:self]; +// Start modal + [CPApp runModalForWindow:aSheet]; + +// Order front and animate the sheet +// aSheet._isAnimating = YES; + [aSheet orderFront:self]; + [aSheet setFrame:startFrame]; + _sheetContext["opened"] = YES; + + [aSheet _setFrame:endFrame delegate:self duration:0.3 curve:CPAnimationEaseOut]; + + // Should run the main loop here until _isAnimating = FALSE + [aSheet becomeKeyWindow]; +} + +/* @ignore */ +- (void)_detachSheetWindow +{ + var sheet = [self attachedSheet]; - // Place this window above ourselves. - [_platformWindow order:CPWindowAbove window:aSheet relativeTo:self]; +// End frame for animation + var startFrame = [sheet frame]; + var endFrame = CGRectMakeCopy(startFrame); + endFrame.size.height = 0; + +// Set the new frame in case the sheet have been resized + _sheetContext["frame"] = startFrame; + +// Autoresizing + var sheetContent = [sheet contentView]; + [sheetContent setAutoresizingMask:CPViewMinYMargin]; + [sheetContent setAutoresizesSubviews:NO]; + +// Start animation with delegate + _sheetContext["opened"] = NO; + + [sheet _setFrame:endFrame delegate:self duration:0.2 curve:CPAnimationLinear]; +} + +/* @ignore */ +- (void)animationDidEnd:(id)anim +{ + var sheet = _sheetContext["sheet"]; + if (anim._window != sheet) + return; + +// Retore autoresizing + var sheetContent = [sheet contentView]; + [sheetContent setAutoresizingMask:_sheetContext["autoresizingMask"]]; + [sheetContent setAutoresizesSubviews:YES]; + +// If we are opened return now + if (_sheetContext["opened"] == YES) + return; + +// Stop modal + [CPApp stopModal]; + +// Notify the world we closed the sheet + [[CPNotificationCenter defaultCenter] postNotificationName:@"CPWindowDidEndSheetNotification" object:self]; + +// check first if front ? + [sheet orderOut:self]; + +// Set the sheet frame to its last open state. + var lastFrame = _sheetContext["frame"]; + [sheet setFrame:lastFrame]; + +// Send didEndSelector + var delegate = _sheetContext["modalDelegate"]; + var endSelector = _sheetContext["endSelector"]; + if(delegate != nil && endSelector != nil) + objj_msgSend(_sheetContext["modalDelegate"], + _sheetContext["endSelector"], + sheet, + _sheetContext["returnCode"], + _sheetContext["contextInfo"]); + +// reset contexts + _sheetContext = nil; + sheet._parentView = nil; } /*! @@ -1780,7 +1874,10 @@ CPTexturedBackgroundWindowMask */ - (CPWindow)attachedSheet { - return _attachedSheet; + if (_sheetContext == nil) + return nil; + + return _sheetContext["sheet"]; } /*! @@ -2225,6 +2322,7 @@ function _CPWindowFullPlatformWindowSessionMake(aWindowView, aContentRect, hasSh @import "_CPWindowView.j" @import "_CPStandardWindowView.j" +@import "_CPDocModalWindowView.j" @import "_CPHUDWindowView.j" @import "_CPBorderlessWindowView.j" @import "_CPBorderlessBridgeWindowView.j" diff --git a/AppKit/CPWindow/_CPDocModalWindowView.j b/AppKit/CPWindow/_CPDocModalWindowView.j new file mode 100644 index 000000000..af233e84d --- /dev/null +++ b/AppKit/CPWindow/_CPDocModalWindowView.j @@ -0,0 +1,50 @@ + +@import "_CPWindowView.j" + +var _CPStandardWindowViewBodyBackgroundColor = nil; + +@implementation _CPDocModalWindowView : _CPWindowView +{ + CPView _bodyView; +} + ++ (CPColor)bodyBackgroundColor +{ + if (!_CPStandardWindowViewBodyBackgroundColor) + _CPStandardWindowViewBodyBackgroundColor = [CPColor colorWithWhite:0.96 alpha:1.0]; + + return _CPStandardWindowViewBodyBackgroundColor; +} + +- (id)initWithFrame:(CPRect)aFrame styleMask:(unsigned)aStyleMask +{ + self = [super initWithFrame:aFrame styleMask:aStyleMask]; + + if (self) + { + var theClass = [self class], + bounds = [self bounds]; + + _bodyView = [[CPView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))]; + + [_bodyView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; + [_bodyView setBackgroundColor:[theClass bodyBackgroundColor]]; + [_bodyView setHitTests:NO]; + + [self addSubview:_bodyView]; + } + + return self; +} + +- (CGRect)contentRectForFrameRect:(CGRect)aFrameRect +{ + return aFrameRect; +} + +- (CGRect)frameRectForContentRect:(CGRect)aContentRect +{ + return aContentRect; +} + +@end \ No newline at end of file diff --git a/AppKit/CPWindow/_CPWindowView.j b/AppKit/CPWindow/_CPWindowView.j index 890044daa..5231016f6 100644 --- a/AppKit/CPWindow/_CPWindowView.j +++ b/AppKit/CPWindow/_CPWindowView.j @@ -135,7 +135,14 @@ var _CPWindowViewResizeIndicatorImage = nil; } else if (type === CPLeftMouseDragged) - [theWindow setFrameSize:CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame))]; + { + var newSize = CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame)); + + if (theWindow._isSheet && theWindow._parentView && (theWindow._frame.size.width !== newSize.width)) + [theWindow._parentView _setAttachedSheetFrameOrigin]; + + [theWindow setFrameSize:newSize]; + } [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; }