25 @
typedef CPModalSession
36 - (void)applicationDidChangeScreenParameters:(
CPNotification)aNotification;
37 - (void)applicationDidFinishLaunching:(
CPNotification)aNotification;
40 - (void)applicationWillFinishLaunching:(
CPNotification)aNotification;
72 CPArray _eventListeners;
73 int _eventListenerInsertionIndex;
86 CPModalSession _currentSession;
89 id <CPApplicationDelegate> _delegate;
90 BOOL _finishedLaunching;
130 _eventListeners = [];
131 _eventListenerInsertionIndex = 0;
149 if (_delegate == aDelegate)
153 delegateNotifications =
155 CPApplicationWillFinishLaunchingNotification, @selector(applicationWillFinishLaunching:),
156 CPApplicationDidFinishLaunchingNotification, @selector(applicationDidFinishLaunching:),
157 CPApplicationWillBecomeActiveNotification, @selector(applicationWillBecomeActive:),
158 CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
159 CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
160 CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
161 CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:),
162 CPApplicationDidChangeScreenParametersNotification, @selector(applicationDidChangeScreenParameters:)
164 count = [delegateNotifications count];
170 for (; index < count; index += 2)
172 var notificationName = delegateNotifications[index],
173 selector = delegateNotifications[index + 1];
175 if ([_delegate respondsToSelector:selector])
176 [defaultCenter removeObserver:_delegate name:notificationName object:self];
180 _delegate = aDelegate;
184 for (; index < count; index += 2)
186 var notificationName = delegateNotifications[index],
187 selector = delegateNotifications[index + 1];
189 if ([_delegate respondsToSelector:selector])
190 [defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
208 - (void)finishLaunching
221 delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
223 if (delegateClassName)
225 var delegateClass = objj_getClass(delegateClassName);
234 postNotificationName:CPApplicationWillFinishLaunchingNotification
237 var types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
239 if ([types count] > 0)
242 var needsUntitled = !!_documentController,
246 URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings();
250 count = [URLStrings count];
252 for (; index < count; ++index)
253 needsUntitled = ![
self _openURL:[
CPURL URLWithString:URLStrings[index]]] && needsUntitled;
255 if (needsUntitled && [_delegate respondsToSelector:
@selector(applicationShouldOpenUntitledFile:)])
256 needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
259 [_documentController newDocument:self];
261 [_documentController _updateRecentDocumentsMenu];
264 postNotificationName:CPApplicationDidFinishLaunchingNotification
269 _finishedLaunching = YES;
272 - (void)terminate:(
id)aSender
281 didCloseAllSelector:@selector(_documentController:didCloseAll:context:)
296 - (void)setApplicationIconImage:(
CPImage)anImage
298 _applicationIconImage = anImage;
307 if (_applicationIconImage)
308 return _applicationIconImage;
314 return _applicationIconImage;
320 - (void)orderFrontStandardAboutPanel:(
id)sender
354 applicationTitle = [options
objectForKey:"ApplicationName"] || [mainInfo objectForKey:@"CPBundleName"],
356 version = [options
objectForKey:@"Version"] || [mainInfo objectForKey:@"CPBundleVersion"],
357 applicationVersion = [options
objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
358 copyright = [options
objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
360 var windowWidth = 275,
366 imageView = [[
CPImageView alloc] initWithFrame:CGRectMake((windowWidth / 2) - (imgWidth / 2), interField, imgWidth, imgHeight)],
367 applicationLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 16, windowWidth - 34, 24)],
368 versionLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 48, windowWidth - 34, 16)],
369 copyrightLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 72, windowWidth - 34, 32)],
370 contentView = [aboutPanel contentView];
373 [applicationLabel setAlignment:CPCenterTextAlignment];
375 [versionLabel setAlignment:CPCenterTextAlignment];
377 [copyrightLabel setAlignment:CPCenterTextAlignment];
378 [copyrightLabel setLineBreakMode:CPLineBreakByWordWrapping];
380 [contentView addSubview:imageView];
381 [contentView addSubview:applicationLabel];
382 [contentView addSubview:versionLabel];
383 [contentView addSubview:copyrightLabel];
388 size:CGSizeMake(256, 256)]];
390 [applicationLabel setStringValue:applicationTitle || ""];
392 if (applicationVersion && version)
393 [versionLabel setStringValue:@"Version " + applicationVersion + " (" + version + ")"];
394 else if (applicationVersion || version)
395 [versionLabel setStringValue:@"Version " + (applicationVersion || version)];
397 [versionLabel setStringValue:@""];
399 [copyrightLabel setStringValue:copyright || @""];
402 _aboutPanel = aboutPanel;
405 [_aboutPanel orderFront:self];
409 - (void)_documentController:(
CPDocumentController)docController didCloseAll:(BOOL)didCloseAll context:(Object)info
414 if ([_delegate respondsToSelector:
@selector(applicationShouldTerminate:)])
415 [
self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
417 [
self replyToApplicationShouldTerminate:YES];
421 - (void)replyToApplicationShouldTerminate:(BOOL)terminate
430 - (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
432 [
self _willBecomeActive];
437 [
self _didBecomeActive];
442 [
self _willResignActive];
447 [
self _didResignActive];
455 - (void)hideOtherApplications:(
id)aSender
484 - (void)stopModalWithCode:(
int)aCode
486 if (!_currentSession)
492 _currentSession._state = aCode;
493 _currentSession = _currentSession._previous;
496 [
self _removeRunModalLoop];
500 - (void)_removeRunModalLoop
502 var count = _eventListeners.length;
505 if (_eventListeners[count]._callback === _CPRunModalLoop)
507 _eventListeners.splice(count, 1);
508 if (count <= _eventListenerInsertionIndex)
509 _eventListenerInsertionIndex--;
535 - (CPModalSession)beginModalSessionForWindow:(
CPWindow)aWindow
537 return _CPModalSessionMake(aWindow, 0);
544 - (void)runModalSession:(CPModalSession)aModalSession
546 aModalSession._previous = _currentSession;
547 _currentSession = aModalSession;
549 var theWindow = aModalSession._window;
552 [theWindow makeKeyWindow];
553 [theWindow orderFront:self];
557 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:YES];
566 if (!_currentSession)
569 return _currentSession._window;
573 - (BOOL)_handleKeyEquivalent:(
CPEvent)anEvent
575 return [[
self keyWindow] performKeyEquivalent:anEvent] ||
576 [[
self mainMenu] performKeyEquivalent:anEvent];
585 _currentEvent = anEvent;
588 var theWindow = [anEvent
window];
591 if ([anEvent _couldBeKeyEquivalent] && [
self _handleKeyEquivalent:anEvent])
597 if (theWindow !== _lastMouseMoveWindow)
598 [_lastMouseMoveWindow _mouseExitedResizeRect];
600 _lastMouseMoveWindow = theWindow;
609 for (var i = _eventListeners.length - 1; i >= 0; i--)
611 var listener = _eventListeners[i];
613 if (listener._mask & (1 << [anEvent type]))
615 _eventListeners.splice(i, 1);
617 _eventListenerInsertionIndex = i;
618 listener._callback(anEvent);
620 if (listener._dequeue)
623 _eventListenerInsertionIndex = _eventListeners.length;
629 _eventListenerInsertionIndex = _eventListeners.length;
632 [theWindow sendEvent:anEvent];
639 - (void)doCommandBySelector:(
SEL)aSelector
641 if ([_delegate respondsToSelector:aSelector])
642 [_delegate performSelector:aSelector];
666 - (
CPWindow)windowWithWindowNumber:(
int)aWindowNumber
672 return _windows[aWindowNumber];
681 return [_windows subarrayWithRange:CPMakeRange(1, [_windows count] - 1)];
687 - (CPArray)orderedWindows
690 return CPWindowObjectList();
696 - (void)hide:(
id)aSender
721 if ([aMenu _menuName] ===
"CPMainMenu")
723 if ([
self menu] === aMenu)
729 window.cpSetMainMenu([
self menu]);
732 [aMenu _setMenuName:@"CPMainMenu"];
739 - (void)orderFrontColorPanel:(
id)aSender
754 - (BOOL)tryToPerform:(
SEL)anAction with:(
id)anObject
759 if ([super tryToPerform:anAction with:anObject])
762 if ([_delegate respondsToSelector:anAction])
764 [_delegate performSelector:anAction withObject:anObject];
779 - (BOOL)sendAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
786 [target performSelector:anAction withObject:aSender];
802 - (id)targetForAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
830 - (id)_targetForWindow:(
CPWindow)aWindow action:(
SEL)anAction
837 if ([responder respondsToSelector:anAction])
840 if (responder == aWindow)
843 responder = [responder nextResponder];
846 if (checkWindow && [aWindow respondsToSelector:anAction])
851 if ([delegate respondsToSelector:anAction])
856 if ([windowController respondsToSelector:anAction])
857 return windowController;
859 var theDocument = [windowController document];
860 if (theDocument !== delegate && [theDocument respondsToSelector:anAction])
880 - (id)targetForAction:(
SEL)anAction
885 var target = [
self _targetForWindow:[
self keyWindow] action:anAction];
890 target = [
self _targetForWindow:[
self mainWindow] action:anAction];
895 if ([
self respondsToSelector:anAction])
898 if ([_delegate respondsToSelector:anAction])
901 if ([_documentController respondsToSelector:anAction])
902 return _documentController;
922 - (void)setCallback:(Function)aCallback forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
924 _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, aCallback, shouldDequeue));
944 - (void)setTarget:(
id)aTarget selector:(
SEL)aSelector forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
946 _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask,
function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue));
954 return _currentEvent;
967 - (void)beginSheet:(
CPWindow)aSheet modalForWindow:(
CPWindow)aWindow modalDelegate:(
id)aModalDelegate didEndSelector:(
SEL)didEndSelector contextInfo:(
id)contextInfo
969 if ([aWindow isSheet])
971 [
CPException raise:CPInternalInconsistencyException
reason:@"The target window of beginSheet: cannot be a sheet"];
975 if (![aWindow attachedSheet])
976 [aSheet._windowView _enableSheet:YES inWindow:aWindow];
978 [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
994 - (void)endSheet:(
CPWindow)sheet returnCode:(
int)returnCode
996 var count = [_windows count];
1000 var aWindow = [_windows objectAtIndex:count],
1001 context = aWindow._sheetContext;
1003 if (context && context[
"sheet"] === sheet)
1005 context["returnCode"] = returnCode;
1006 [aWindow _endSheet];
1037 - (CPArray)arguments
1040 if (window && window.location && _fullArgsString !== window.location.
hash)
1041 [
self _reloadArguments];
1062 - (void)setArguments:(CPArray)args
1064 if (!args || args.length == 0)
1068 if (window && window.location)
1069 window.location.hash =
@"#";
1073 if (![args isKindOfClass:CPArray])
1074 args = [CPArray arrayWithObject:args];
1078 var toEncode = [_args copy];
1079 for (var i = 0, count = toEncode.length; i < count; i++)
1080 toEncode[i] = encodeURIComponent(toEncode[i]);
1082 var hash = [toEncode componentsJoinedByString:@"/"];
1085 if (window && window.location)
1086 window.location.hash =
@"#" + hash;
1089 - (void)_reloadArguments
1092 _fullArgsString = (window && window.location) ? window.location.
hash :
"";
1096 var args = _fullArgsString.substring(1).split(
"/");
1098 for (var i = 0, count = args.length; i < count; i++)
1099 args[i] = decodeURIComponent(args[i]);
1129 - (BOOL)_openURL:(
CPURL)aURL
1131 if (_delegate && [_delegate respondsToSelector:
@selector(application:openFile:)])
1133 CPLog.warn(
"application:openFile: is deprecated, use application:openURL: instead.");
1134 return [_delegate application:self openFile:[aURL
absoluteString]];
1137 if (_delegate && [_delegate respondsToSelector:
@selector(application:openURL:)])
1138 return [_delegate application:self openURL:aURL];
1140 return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL];
1143 - (void)_willBecomeActive
1150 - (void)_didBecomeActive
1152 if (![
self keyWindow] && _previousKeyWindow &&
1153 [[
self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !==
CPNotFound)
1154 [_previousKeyWindow makeKeyWindow];
1156 if (![
self mainWindow] && _previousMainWindow &&
1157 [[
self windows] indexOfObjectIdenticalTo:_previousMainWindow] !==
CPNotFound)
1158 [_previousMainWindow makeMainWindow];
1160 if ([
self keyWindow])
1161 [[
self keyWindow] orderFront:self];
1162 else if ([
self mainWindow])
1163 [[
self mainWindow] makeKeyAndOrderFront:self];
1164 else if ([
self mainMenu])
1165 [[
self mainMenu]._menuWindow makeKeyWindow];
1167 _previousKeyWindow = nil;
1168 _previousMainWindow = nil;
1175 - (void)_willResignActive
1182 - (void)_didResignActive
1184 if (
self._activeMenu)
1185 [
self._activeMenu cancelTracking];
1187 if ([
self keyWindow])
1189 _previousKeyWindow = [
self keyWindow];
1190 [_previousKeyWindow resignKeyWindow];
1193 if ([
self mainWindow])
1195 _previousMainWindow = [
self mainWindow];
1196 [_previousMainWindow resignMainWindow];
1206 return ([[
CPBundle mainBundle] objectForInfoDictionaryKey:
"CPDefaultTheme"] ||
@"Aristo2");
1211 var _CPModalSessionMake =
function(aWindow, aStopCode)
1216 var _CPEventListenerMake =
function(anEventMask, aCallback, shouldDequeue)
1218 return { _mask:anEventMask, _callback:aCallback, _dequeue:shouldDequeue };
1222 _CPRunModalLoop =
function(anEvent)
1224 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:YES];
1226 var theWindow = [anEvent
window],
1227 modalSession =
CPApp._currentSession;
1232 if (theWindow == modalSession._window ||
1233 [theWindow worksWhenModal] ||
1234 [theWindow attachedSheet] == modalSession._window ||
1235 ([theWindow isKindOfClass:_CPPopoverWindow] && [[theWindow targetView] window] === modalSession._window))
1237 [theWindow sendEvent:anEvent];
1252 if (window.parent !== window && typeof window.parent._childAppIsStarting ===
"function")
1256 window.parent._childAppIsStarting(window);
1261 CPLog.warn(
"Failed to call parent frame's _childAppIsStarting().");
1267 principalClass = [mainBundle principalClass];
1269 if (!principalClass)
1272 [principalClass sharedApplication];
1274 if ([args containsObject:
"debug"])
1275 CPLogRegister(CPLogPopup);
1278 CPApp._namedArgs = namedArgs;
1280 [_CPAppBootstrapper performActions];
1283 var _CPAppBootstrapperActions = nil;
1284 @implementation _CPAppBootstrapper :
CPObject
1291 return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
1294 + (void)performActions
1296 if (!_CPAppBootstrapperActions)
1297 _CPAppBootstrapperActions = [
self actions];
1299 while (_CPAppBootstrapperActions.length)
1301 var action = _CPAppBootstrapperActions.shift();
1303 if (objj_msgSend(
self, action))
1310 + (BOOL)bootstrapPlatform
1315 + (BOOL)loadDefaultTheme
1320 if (defaultThemeName ===
@"Aristo" || defaultThemeName ===
@"Aristo2")
1326 [blend loadWithDelegate:self];
1331 + (void)blendDidFinishLoading:(
CPThemeBlend)aThemeBlend
1336 [
self performActions];
1339 + (BOOL)loadMainCibFile
1342 mainCibFile = [mainBundle objectForInfoDictionaryKey:CPMainCibFile] || [mainBundle objectForInfoDictionaryKey:CPMainCibFileHumanFriendly];
1346 [mainBundle loadCibFile:mainCibFile
1347 externalNameTable:@{ CPCibOwner: CPApp }
1353 [
self loadCiblessBrowserMainMenu];
1358 + (void)loadCiblessBrowserMainMenu
1363 [mainMenu setAutoenablesItems:NO];
1370 [mainMenu addItem:newMenuItem];
1377 [mainMenu addItem:openMenuItem];
1388 [saveMenuItem setSubmenu:saveMenu];
1390 [mainMenu addItem:saveMenuItem];
1398 [undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
1399 [redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
1401 [editMenu addItem:undoMenuItem];
1402 [editMenu addItem:redoMenuItem];
1408 [editMenuItem setSubmenu:editMenu];
1409 [editMenuItem setHidden:YES];
1411 [mainMenu addItem:editMenuItem];
1415 [CPApp setMainMenu:mainMenu];
1418 + (void)cibDidFinishLoading:(
CPCib)aCib
1420 [
self performActions];
1423 + (void)cibDidFailToLoad:(
CPCib)aCib
1425 throw new Error(
"Could not load main cib file. Did you forget to nib2cib it?");
1430 _CPAppBootstrapperActions = nil;
1441 + (unsigned)modifierFlags
1463 _themeBlend = aValue;