diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j index 75b63ce9d..b1dc33d0e 100644 --- a/AppKit/CPAlert.j +++ b/AppKit/CPAlert.j @@ -116,21 +116,12 @@ var CPAlertWarningImage, */ - (id)init { - self = [super init]; - - if (self) + if (self = [super init]) { _buttonCount = 0; _buttons = [CPArray array]; _alertStyle = CPWarningAlertStyle; - - _messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, 220.0, 80.0)]; - [_messageLabel setFont:[CPFont systemFontOfSize:12.0]]; - [_messageLabel setLineBreakMode:CPLineBreakByWordWrapping]; - [_messageLabel setAlignment:CPJustifiedTextAlignment]; - - _alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)]; - + [self setWindowStyle:nil]; } @@ -145,12 +136,12 @@ var CPAlertWarningImage, { _windowStyle = styleMask; - _alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 300.0, 130.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask]; + _alertPanel = [[CPPanel alloc] initWithContentRect:CGRectMake(0.0, 0.0, 400.0, 110.0) styleMask:styleMask ? styleMask | CPTitledWindowMask : CPTitledWindowMask]; [_alertPanel setFloatingPanel:YES]; [_alertPanel center]; - + [_messageLabel setTextColor:(styleMask & CPHUDBackgroundWindowMask) ? [CPColor whiteColor] : [CPColor blackColor]]; - + var count = [_buttons count]; for(var i=0; i < count; i++) { @@ -162,6 +153,18 @@ var CPAlertWarningImage, [[_alertPanel contentView] addSubview:button]; } + if (!_messageLabel) + { + var bounds = [[_alertPanel contentView] bounds]; + + _messageLabel = [[CPTextField alloc] initWithFrame:CGRectMake(57.0, 10.0, CGRectGetWidth(bounds) - 73.0, 62.0)]; + [_messageLabel setFont:[CPFont boldSystemFontOfSize:13.0]]; + [_messageLabel setLineBreakMode:CPLineBreakByWordWrapping]; + [_messageLabel setAlignment:CPJustifiedTextAlignment]; + + _alertImageView = [[CPImageView alloc] initWithFrame:CGRectMake(15.0, 12.0, 32.0, 32.0)]; + } + [[_alertPanel contentView] addSubview:_messageLabel]; [[_alertPanel contentView] addSubview:_alertImageView]; } @@ -251,7 +254,8 @@ var CPAlertWarningImage, */ - (void)addButtonWithTitle:(CPString)title { - var button = [[CPButton alloc] initWithFrame:CGRectMake(200.0 - (_buttonCount * 90.0), 98.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)]; + var bounds = [[_alertPanel contentView] bounds], + button = [[CPButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(bounds) - ((_buttonCount + 1) * 90.0), CGRectGetHeight(bounds) - 34.0, 80.0, (_windowStyle == CPHUDBackgroundWindowMask) ? 20.0 : 24.0)]; [button setTitle:title]; [button setTarget:self]; diff --git a/AppKit/CPDocument.j b/AppKit/CPDocument.j index f3b721227..ee76a1033 100644 --- a/AppKit/CPDocument.j +++ b/AppKit/CPDocument.j @@ -109,6 +109,8 @@ var CPDocumentUntitledCount = 0; CPURLConnection _readConnection; CPURLRequest _writeRequest; + + CPAlert _canCloseAlert; } /*! @@ -529,6 +531,7 @@ var CPDocumentUntitledCount = 0; _writeRequest = nil; objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo); + [self _sendDocumentSavedNotification:NO]; } } } @@ -557,6 +560,7 @@ var CPDocumentUntitledCount = 0; _writeRequest = nil; objj_msgSend(session.delegate, session.didSaveSelector, self, YES, session.contextInfo); + [self _sendDocumentSavedNotification:YES]; } } @@ -584,6 +588,7 @@ var CPDocumentUntitledCount = 0; alert("There was an error saving the document."); objj_msgSend(session.delegate, session.didSaveSelector, self, NO, session.contextInfo); + [self _sendDocumentSavedNotification:NO]; } } @@ -768,6 +773,11 @@ var CPDocumentUntitledCount = 0; @param aSender the object requesting the save */ - (void)saveDocument:(id)aSender +{ + [self saveDocumentWithDelegate:nil didSaveSelector:nil contextInfo:nil]; +} + +- (void)saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo { if (_fileURL) { @@ -775,10 +785,10 @@ var CPDocumentUntitledCount = 0; postNotificationName:CPDocumentWillSaveNotification object:self]; - [self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL]; + [self saveToURL:_fileURL ofType:[self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo]; } else - [self saveDocumentAs:self]; + [self _saveDocumentAsWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo]; } /*! @@ -786,6 +796,11 @@ var CPDocumentUntitledCount = 0; @param aSender the object requesting the operation */ - (void)saveDocumentAs:(id)aSender +{ + [self _saveDocumentAsWithDelegate:nil didSaveSelector:nil contextInfo:nil]; +} + +- (void)_saveDocumentAsWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(Object)contextInfo { var savePanel = [CPSavePanel savePanel], response = [savePanel runModal]; @@ -799,13 +814,13 @@ var CPDocumentUntitledCount = 0; postNotificationName:CPDocumentWillSaveNotification object:self]; - [self saveToURL:saveURL ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:self didSaveSelector:@selector(document:didSave:contextInfo:) contextInfo:NULL]; + [self saveToURL:saveURL ofType:[self fileType] forSaveOperation:CPSaveAsOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo]; } /* @ignore */ -- (void)document:(id)aDocument didSave:(BOOL)didSave contextInfo:(id)aContextInfo +- (void)_sendDocumentSavedNotification:(BOOL)didSave { if (didSave) [[CPNotificationCenter defaultCenter] @@ -819,6 +834,57 @@ var CPDocumentUntitledCount = 0; @end +@implementation CPDocument (ClosingDocuments) + +- (void)shouldCloseWindowController:(CPWindowController)controller delegate:(id)delegate shouldCloseSelector:(SEL)selector contextInfo:(Object)info +{ + if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !== CPNotFound)) + [self canCloseDocumentWithDelegate:delegate shouldCloseSelector:selector contextInfo:info]; + else if ([delegate respondsToSelector:selector]) + objj_msgSend(delegate, selector, self, YES, info); +} + +- (void)canCloseDocumentWithDelegate:(id)aDelegate shouldCloseSelector:(SEL)aSelector contextInfo:(Object)context +{ + if (![self isDocumentEdited]) + return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector, self, YES, context); + + _canCloseAlert = [[CPAlert alloc] init]; + + [_canCloseAlert setDelegate:self]; + [_canCloseAlert setAlertStyle:CPWarningAlertStyle]; + [_canCloseAlert setTitle:@"Unsaved Document"]; + [_canCloseAlert setMessageText:sprintf(@"Do you want to save the changes you've made to the document \"%@\"?", + [self displayName] || [self fileName])]; + + [_canCloseAlert addButtonWithTitle:@"Save"]; + [_canCloseAlert addButtonWithTitle:@"Cancel"]; + [_canCloseAlert addButtonWithTitle:@"Don't Save"]; + + _canCloseAlert._context = {delegate:aDelegate, selector:aSelector, context:context}; + + [_canCloseAlert runModal]; +} + +- (void)alertDidEnd:(CPAlert)alert returnCode:(int)returnCode +{ + if (alert !== _canCloseAlert) + return; + + var delegate = alert._context.delegate, + selector = alert._context.selector, + context = alert._context.context; + + if (returnCode === 0) + [self saveDocumentWithDelegate:delegate didSaveSelector:selector contextInfo:context]; + else + objj_msgSend(delegate, selector, self, returnCode === 2, context); + + _canCloseAlert = nil; +} + +@end + var _CPReadSessionMake = function(aType, aDelegate, aDidReadSelector, aContextInfo) { return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo }; diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 7994ab75f..ebf0815c9 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -951,14 +951,7 @@ var secureStringForString = function(aString) // This is true for when aString === "" and null/undefined. if (!aString) return ""; - - var secureString = "", - length = aString.length; - - while (length--) - secureString += CPSecureTextFieldCharacter; - - return secureString; + return Array(aString.length).join(CPSecureTextFieldCharacter); } diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index ef3eaa277..83fdb8a9f 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -1636,6 +1636,9 @@ CPTexturedBackgroundWindowMask */ - (void)performClose:(id)aSender { + if (!(_styleMask & CPClosableWindowMask)) + return; + // Only send ONE windowShouldClose: message. if ([_delegate respondsToSelector:@selector(windowShouldClose:)]) { @@ -1646,8 +1649,23 @@ CPTexturedBackgroundWindowMask // Only check self is delegate does NOT implement this. This also ensures this when delegate == self (returns true). else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self]) return; - - [self close]; + + var document = [_windowController document]; + if (document) + { + [document shouldCloseWindowController:_windowController + delegate:self + shouldCloseSelector:@selector(_document:shouldClose:contextInfo:) + contextInfo:nil]; + } + else + [self close]; +} + +- (void)_document:(CPDocument)document shouldClose:(BOOL)shouldClose contextInfo:(Object)context +{ + if (shouldClose) + [self close]; } /*! diff --git a/Objective-J/utilities.js b/Objective-J/utilities.js index ac2e74386..31c18333b 100644 --- a/Objective-J/utilities.js +++ b/Objective-J/utilities.js @@ -168,10 +168,7 @@ var _sprintf_justify = function(sign, prefix, string, suffix, width, leftJustify var _sprintf_pad = function(n, ch) { - var result = ""; - for (var i = 0; i < n; i++) - result += ch; - return result; + return Array(MAX(0,n)).join(ch); } // Base64 encoding and decoding