56 CPArray _eventListeners;
57 int _eventListenerInsertionIndex;
70 CPModalSession _currentSession;
74 BOOL _finishedLaunching;
114 _eventListeners = [];
115 _eventListenerInsertionIndex = 0;
131 - (void)setDelegate:(
id)aDelegate
133 if (_delegate == aDelegate)
137 delegateNotifications =
139 CPApplicationWillFinishLaunchingNotification, @selector(applicationWillFinishLaunching:),
140 CPApplicationDidFinishLaunchingNotification, @selector(applicationDidFinishLaunching:),
141 CPApplicationWillBecomeActiveNotification, @selector(applicationWillBecomeActive:),
142 CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
143 CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
144 CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
145 CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:),
146 CPApplicationDidChangeScreenParametersNotification, @selector(applicationDidChangeScreenParameters:)
148 count = [delegateNotifications count];
154 for (; index < count; index += 2)
156 var notificationName = delegateNotifications[index],
157 selector = delegateNotifications[index + 1];
159 if ([_delegate respondsToSelector:selector])
160 [defaultCenter removeObserver:_delegate name:notificationName object:self];
164 _delegate = aDelegate;
168 for (; index < count; index += 2)
170 var notificationName = delegateNotifications[index],
171 selector = delegateNotifications[index + 1];
173 if ([_delegate respondsToSelector:selector])
174 [defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
192 - (void)finishLaunching
205 delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
207 if (delegateClassName)
209 var delegateClass = objj_getClass(delegateClassName);
218 postNotificationName:CPApplicationWillFinishLaunchingNotification
221 var types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
223 if ([types count] > 0)
226 var needsUntitled = !!_documentController,
230 URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings();
234 count = [URLStrings count];
236 for (; index < count; ++index)
237 needsUntitled = ![
self _openURL:[
CPURL URLWithString:URLStrings[index]]] && needsUntitled;
239 if (needsUntitled && [_delegate respondsToSelector:
@selector(applicationShouldOpenUntitledFile:)])
240 needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
243 [_documentController newDocument:self];
245 [_documentController _updateRecentDocumentsMenu];
248 postNotificationName:CPApplicationDidFinishLaunchingNotification
253 _finishedLaunching = YES;
256 - (void)terminate:(
id)aSender
265 didCloseAllSelector:@selector(_documentController:didCloseAll:context:)
270 [[[
self keyWindow] platformWindow] _propagateCurrentDOMEvent:YES];
280 - (void)setApplicationIconImage:(
CPImage)anImage
282 _applicationIconImage = anImage;
291 if (_applicationIconImage)
292 return _applicationIconImage;
296 _applicationIconImage = [[
CPImage alloc] initWithContentsOfFile:imagePath];
298 return _applicationIconImage;
304 - (void)orderFrontStandardAboutPanel:(
id)sender
338 applicationTitle = [options
objectForKey:"ApplicationName"] || [mainInfo objectForKey:@"CPBundleName"],
340 version = [options
objectForKey:@"Version"] || [mainInfo objectForKey:@"CPBundleVersion"],
341 applicationVersion = [options
objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
342 copyright = [options
objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
344 var windowWidth = 275,
349 aboutPanel = [[
CPWindow alloc] initWithContentRect:CGRectMake(0, 0, windowWidth, windowHeight) styleMask:CPClosableWindowMask],
350 imageView = [[
CPImageView alloc] initWithFrame:CGRectMake((windowWidth / 2) - (imgWidth / 2), interField, imgWidth, imgHeight)],
351 applicationLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 16, windowWidth - 34, 24)],
352 versionLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 48, windowWidth - 34, 16)],
353 copyrightLabel = [[
CPTextField alloc] initWithFrame:CGRectMake(17, imgHeight + 72, windowWidth - 34, 32)],
354 contentView = [aboutPanel contentView];
357 [applicationLabel setAlignment:CPCenterTextAlignment];
359 [versionLabel setAlignment:CPCenterTextAlignment];
361 [copyrightLabel setAlignment:CPCenterTextAlignment];
362 [copyrightLabel setLineBreakMode:CPLineBreakByWordWrapping];
364 [contentView addSubview:imageView];
365 [contentView addSubview:applicationLabel];
366 [contentView addSubview:versionLabel];
367 [contentView addSubview:copyrightLabel];
371 [imageView setImage:applicationIcon || [[
CPImage alloc] initWithContentsOfFile:standardPath
372 size:CGSizeMake(256, 256)]];
374 [applicationLabel setStringValue:applicationTitle || ""];
376 if (applicationVersion && version)
377 [versionLabel setStringValue:@"Version " + applicationVersion + " (" + version + ")"];
378 else if (applicationVersion || version)
379 [versionLabel setStringValue:@"Version " + (applicationVersion || version)];
381 [versionLabel setStringValue:@""];
383 [copyrightLabel setStringValue:copyright || @""];
386 _aboutPanel = aboutPanel;
389 [_aboutPanel orderFront:self];
393 - (void)_documentController:(
CPDocumentController)docController didCloseAll:(BOOL)didCloseAll context:(Object)info
398 if ([_delegate respondsToSelector:
@selector(applicationShouldTerminate:)])
399 [
self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
401 [
self replyToApplicationShouldTerminate:YES];
405 - (void)replyToApplicationShouldTerminate:(BOOL)terminate
414 - (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
416 [
self _willBecomeActive];
421 [
self _willResignActive];
426 [
self _willResignActive];
431 [
self _didResignActive];
439 - (void)hideOtherApplications:(
id)aSender
468 - (void)stopModalWithCode:(
int)aCode
470 if (!_currentSession)
476 _currentSession._state = aCode;
477 _currentSession = _currentSession._previous;
480 [
self _removeRunModalLoop];
484 - (void)_removeRunModalLoop
486 var count = _eventListeners.length;
489 if (_eventListeners[count]._callback === _CPRunModalLoop)
491 _eventListeners.splice(count, 1);
492 if (count <= _eventListenerInsertionIndex)
493 _eventListenerInsertionIndex--;
519 - (CPModalSession)beginModalSessionForWindow:(
CPWindow)aWindow
521 return _CPModalSessionMake(aWindow, 0);
528 - (void)runModalSession:(CPModalSession)aModalSession
530 aModalSession._previous = _currentSession;
531 _currentSession = aModalSession;
533 var theWindow = aModalSession._window;
536 [theWindow makeKeyWindow];
537 [theWindow orderFront:self];
541 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:YES];
550 if (!_currentSession)
553 return _currentSession._window;
557 - (BOOL)_handleKeyEquivalent:(
CPEvent)anEvent
559 return [[
self keyWindow] performKeyEquivalent:anEvent] ||
560 [[
self mainMenu] performKeyEquivalent:anEvent];
569 _currentEvent = anEvent;
572 var theWindow = [anEvent window];
575 if ([anEvent _couldBeKeyEquivalent] && [
self _handleKeyEquivalent:anEvent])
581 if (theWindow !== _lastMouseMoveWindow)
582 [_lastMouseMoveWindow _mouseExitedResizeRect];
584 _lastMouseMoveWindow = theWindow;
593 for (var i = _eventListeners.length - 1; i >= 0; i--)
595 var listener = _eventListeners[i];
597 if (listener._mask & (1 << [anEvent type]))
599 _eventListeners.splice(i, 1);
601 _eventListenerInsertionIndex = i;
602 listener._callback(anEvent);
604 if (listener._dequeue)
607 _eventListenerInsertionIndex = _eventListeners.length;
613 _eventListenerInsertionIndex = _eventListeners.length;
616 [theWindow sendEvent:anEvent];
623 - (void)doCommandBySelector:(
SEL)aSelector
625 if ([_delegate respondsToSelector:aSelector])
626 [_delegate performSelector:aSelector];
628 [
super doCommandBySelector:aSelector];
650 - (
CPWindow)windowWithWindowNumber:(
int)aWindowNumber
656 return _windows[aWindowNumber];
665 return [_windows subarrayWithRange:CPMakeRange(1, [_windows count] - 1)];
671 - (CPArray)orderedWindows
674 return CPWindowObjectList();
680 - (void)hide:(
id)aSender
705 if ([aMenu _menuName] ===
"CPMainMenu")
707 if ([
self menu] === aMenu)
710 [
super setMenu:aMenu];
713 window.cpSetMainMenu([
self menu]);
716 [aMenu _setMenuName:@"CPMainMenu"];
723 - (void)orderFrontColorPanel:(
id)aSender
738 - (BOOL)tryToPerform:(
SEL)anAction with:(
id)anObject
743 if ([super tryToPerform:anAction with:anObject])
746 if ([_delegate respondsToSelector:anAction])
748 [_delegate performSelector:anAction withObject:anObject];
763 - (BOOL)sendAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
770 [target performSelector:anAction withObject:aSender];
786 - (id)targetForAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
814 - (id)_targetForWindow:(
CPWindow)aWindow action:(
SEL)anAction
816 var responder = [aWindow firstResponder],
821 if ([responder respondsToSelector:anAction])
824 if (responder == aWindow)
827 responder = [responder nextResponder];
830 if (checkWindow && [aWindow respondsToSelector:anAction])
833 var delegate = [aWindow delegate];
835 if ([delegate respondsToSelector:anAction])
838 var windowController = [aWindow windowController];
840 if ([windowController respondsToSelector:anAction])
841 return windowController;
843 var theDocument = [windowController document];
844 if (theDocument !== delegate && [theDocument respondsToSelector:anAction])
864 - (id)targetForAction:(
SEL)anAction
869 var target = [
self _targetForWindow:[
self keyWindow] action:anAction];
874 target = [
self _targetForWindow:[
self mainWindow] action:anAction];
879 if ([
self respondsToSelector:anAction])
882 if ([_delegate respondsToSelector:anAction])
885 if ([_documentController respondsToSelector:anAction])
886 return _documentController;
906 - (void)setCallback:(Function)aCallback forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
908 _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask, aCallback, shouldDequeue));
928 - (void)setTarget:(
id)aTarget selector:(
SEL)aSelector forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
930 _eventListeners.splice(_eventListenerInsertionIndex++, 0, _CPEventListenerMake(aMask,
function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue));
938 return _currentEvent;
951 - (void)beginSheet:(
CPWindow)aSheet modalForWindow:(
CPWindow)aWindow modalDelegate:(
id)aModalDelegate didEndSelector:(
SEL)didEndSelector contextInfo:(
id)contextInfo
953 if ([aWindow isSheet])
955 [
CPException raise:CPInternalInconsistencyException
reason:@"The target window of beginSheet: cannot be a sheet"];
959 [aSheet._windowView _enableSheet:YES inWindow:aWindow];
960 [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
976 - (void)endSheet:(
CPWindow)sheet returnCode:(
int)returnCode
978 var count = [_windows count];
982 var aWindow = [_windows objectAtIndex:count],
983 context = aWindow._sheetContext;
985 if (context && context[
"sheet"] === sheet)
987 context["returnCode"] = returnCode;
1019 - (CPArray)arguments
1022 if (window && window.location && _fullArgsString !== window.location.hash)
1023 [
self _reloadArguments];
1044 - (void)setArguments:(CPArray)args
1046 if (!args || args.length == 0)
1050 if (window && window.location)
1051 window.location.hash =
@"#";
1055 if (![args isKindOfClass:CPArray])
1056 args = [CPArray arrayWithObject:args];
1060 var toEncode = [_args copy];
1061 for (var i = 0, count = toEncode.length; i < count; i++)
1062 toEncode[i] = encodeURIComponent(toEncode[i]);
1064 var hash = [toEncode componentsJoinedByString:@"/"];
1067 if (window && window.location)
1068 window.location.hash =
@"#" + hash;
1071 - (void)_reloadArguments
1074 _fullArgsString = (window && window.location) ? window.location.hash :
"";
1076 if (_fullArgsString.length)
1078 var args = _fullArgsString.substring(1).split(
"/");
1080 for (var i = 0, count = args.length; i < count; i++)
1081 args[i] = decodeURIComponent(args[i]);
1111 - (BOOL)_openURL:(
CPURL)aURL
1113 if (_delegate && [_delegate respondsToSelector:
@selector(application:openFile:)])
1115 CPLog.warn(
"application:openFile: is deprecated, use application:openURL: instead.");
1116 return [_delegate application:self openFile:[aURL
absoluteString]];
1119 if (_delegate && [_delegate respondsToSelector:
@selector(application:openURL:)])
1120 return [_delegate application:self openURL:aURL];
1122 return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL];
1125 - (void)_willBecomeActive
1132 - (void)_didBecomeActive
1134 if (![
self keyWindow] && _previousKeyWindow &&
1135 [[
self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !==
CPNotFound)
1136 [_previousKeyWindow makeKeyWindow];
1138 if (![
self mainWindow] && _previousMainWindow &&
1139 [[
self windows] indexOfObjectIdenticalTo:_previousMainWindow] !==
CPNotFound)
1140 [_previousMainWindow makeMainWindow];
1142 if ([
self keyWindow])
1143 [[
self keyWindow] orderFront:self];
1144 else if ([
self mainWindow])
1145 [[
self mainWindow] makeKeyAndOrderFront:self];
1147 [[
self mainMenu]._menuWindow makeKeyWindow];
1149 _previousKeyWindow = nil;
1150 _previousMainWindow = nil;
1157 - (void)_willResignActive
1164 - (void)_didResignActive
1166 if (
self._activeMenu)
1167 [
self._activeMenu cancelTracking];
1169 if ([
self keyWindow])
1171 _previousKeyWindow = [
self keyWindow];
1172 [_previousKeyWindow resignKeyWindow];
1175 if ([
self mainWindow])
1177 _previousMainWindow = [
self mainWindow];
1178 [_previousMainWindow resignMainWindow];
1188 return ([[
CPBundle mainBundle] objectForInfoDictionaryKey:
"CPDefaultTheme"] ||
@"Aristo2");
1193 var _CPModalSessionMake =
function(aWindow, aStopCode)
1198 var _CPEventListenerMake =
function(anEventMask, aCallback, shouldDequeue)
1200 return { _mask:anEventMask, _callback:aCallback, _dequeue:shouldDequeue };
1204 _CPRunModalLoop =
function(anEvent)
1206 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:YES];
1208 var theWindow = [anEvent window],
1209 modalSession =
CPApp._currentSession;
1214 if (theWindow == modalSession._window ||
1215 [theWindow worksWhenModal] ||
1216 [theWindow attachedSheet] == modalSession._window ||
1217 ([theWindow isKindOfClass:_CPPopoverWindow] && [[theWindow targetView] window] === modalSession._window))
1219 [theWindow sendEvent:anEvent];
1235 if (window.parent !== window && typeof window.parent._childAppIsStarting ===
"function")
1239 window.parent._childAppIsStarting(window);
1244 CPLog.warn(
"Failed to call parent frame's _childAppIsStarting().");
1250 principalClass = [mainBundle principalClass];
1252 if (!principalClass)
1255 [principalClass sharedApplication];
1257 if ([args containsObject:
"debug"])
1258 CPLogRegister(CPLogPopup);
1261 CPApp._namedArgs = namedArgs;
1263 [_CPAppBootstrapper performActions];
1266 var _CPAppBootstrapperActions = nil;
1267 @implementation _CPAppBootstrapper :
CPObject
1274 return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
1277 + (void)performActions
1279 if (!_CPAppBootstrapperActions)
1280 _CPAppBootstrapperActions = [
self actions];
1282 while (_CPAppBootstrapperActions.length)
1284 var action = _CPAppBootstrapperActions.shift();
1286 if (objj_msgSend(
self, action))
1293 + (BOOL)bootstrapPlatform
1298 + (BOOL)loadDefaultTheme
1303 if (defaultThemeName ===
@"Aristo" || defaultThemeName ===
@"Aristo2")
1308 var blend = [[
CPThemeBlend alloc] initWithContentsOfURL:themeURL];
1309 [blend loadWithDelegate:self];
1314 + (void)blendDidFinishLoading:(
CPThemeBlend)aThemeBlend
1319 [
self performActions];
1322 + (BOOL)loadMainCibFile
1325 mainCibFile = [mainBundle objectForInfoDictionaryKey:CPMainCibFile] || [mainBundle objectForInfoDictionaryKey:CPMainCibFileHumanFriendly];
1329 [mainBundle loadCibFile:mainCibFile
1330 externalNameTable:@{ CPCibOwner: CPApp }
1336 [
self loadCiblessBrowserMainMenu];
1341 + (void)loadCiblessBrowserMainMenu
1343 var mainMenu = [[
CPMenu alloc] initWithTitle:@"MainMenu"];
1346 [mainMenu setAutoenablesItems:NO];
1348 var newMenuItem = [[
CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"n"];
1350 [newMenuItem setImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-new" forClass:_CPMenuView]];
1351 [newMenuItem setAlternateImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-new" inState:CPThemeStateHighlighted forClass:_CPMenuView]];
1353 [mainMenu addItem:newMenuItem];
1355 var openMenuItem = [[
CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"o"];
1357 [openMenuItem setImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-open" forClass:_CPMenuView]];
1358 [openMenuItem setAlternateImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-open" inState:CPThemeStateHighlighted forClass:_CPMenuView]];
1360 [mainMenu addItem:openMenuItem];
1362 var saveMenu = [[
CPMenu alloc] initWithTitle:@"Save"],
1363 saveMenuItem = [[
CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
1365 [saveMenuItem setImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-save" forClass:_CPMenuView]];
1366 [saveMenuItem setAlternateImage:[[
CPTheme defaultTheme] valueForAttributeWithName:@"menu-general-icon-save" inState:CPThemeStateHighlighted forClass:_CPMenuView]];
1368 [saveMenu addItem:[[
CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"s"]];
1369 [saveMenu addItem:[[
CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
1371 [saveMenuItem setSubmenu:saveMenu];
1373 [mainMenu addItem:saveMenuItem];
1375 var editMenuItem = [[
CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
1376 editMenu = [[
CPMenu alloc] initWithTitle:@"Edit"],
1378 undoMenuItem = [[
CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
1379 redoMenuItem = [[
CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
1381 [undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
1382 [redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
1384 [editMenu addItem:undoMenuItem];
1385 [editMenu addItem:redoMenuItem];
1387 [editMenu addItem:[[
CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]];
1388 [editMenu addItem:[[
CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]];
1389 [editMenu addItem:[[
CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]];
1391 [editMenuItem setSubmenu:editMenu];
1392 [editMenuItem setHidden:YES];
1394 [mainMenu addItem:editMenuItem];
1396 [mainMenu addItem:[
CPMenuItem separatorItem]];
1398 [CPApp setMainMenu:mainMenu];
1401 + (void)cibDidFinishLoading:(
CPCib)aCib
1403 [
self performActions];
1406 + (void)cibDidFailToLoad:(
CPCib)aCib
1408 throw new Error(
"Could not load main cib file. Did you forget to nib2cib it?");
1413 _CPAppBootstrapperActions = nil;
1424 + (unsigned)modifierFlags
1446 _themeBlend = aValue;