23 #import "../Foundation/CPRange.h"
90 CPModalSession _currentSession;
94 BOOL _finishedLaunching;
134 _eventListeners = [];
150 - (void)setDelegate:(
id)aDelegate
152 if (_delegate == aDelegate)
156 delegateNotifications =
158 CPApplicationWillFinishLaunchingNotification, @selector(applicationWillFinishLaunching:),
159 CPApplicationDidFinishLaunchingNotification, @selector(applicationDidFinishLaunching:),
160 CPApplicationWillBecomeActiveNotification, @selector(applicationWillBecomeActive:),
161 CPApplicationDidBecomeActiveNotification, @selector(applicationDidBecomeActive:),
162 CPApplicationWillResignActiveNotification, @selector(applicationWillResignActive:),
163 CPApplicationDidResignActiveNotification, @selector(applicationDidResignActive:),
164 CPApplicationWillTerminateNotification, @selector(applicationWillTerminate:)
166 count = [delegateNotifications count];
172 for (; index < count; index += 2)
174 var notificationName = delegateNotifications[index],
175 selector = delegateNotifications[index + 1];
177 if ([_delegate respondsToSelector:selector])
178 [defaultCenter removeObserver:_delegate name:notificationName object:self];
182 _delegate = aDelegate;
186 for (; index < count; index += 2)
188 var notificationName = delegateNotifications[index],
189 selector = delegateNotifications[index + 1];
191 if ([_delegate respondsToSelector:selector])
192 [defaultCenter addObserver:_delegate selector:selector name:notificationName object:self];
210 - (void)finishLaunching
223 delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
225 if (delegateClassName)
227 var delegateClass = objj_getClass(delegateClassName);
236 postNotificationName:CPApplicationWillFinishLaunchingNotification
239 var types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
241 if ([types count] > 0)
244 var needsUntitled = !!_documentController,
248 URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings();
252 count = [URLStrings count];
254 for (; index < count; ++index)
255 needsUntitled = ![
self _openURL:[
CPURL URLWithString:URLStrings[index]]] && needsUntitled;
257 if (needsUntitled && [_delegate respondsToSelector:
@selector(applicationShouldOpenUntitledFile:)])
258 needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
261 [_documentController newDocument:self];
263 [_documentController _updateRecentDocumentsMenu];
266 postNotificationName:CPApplicationDidFinishLaunchingNotification
271 _finishedLaunching = YES;
274 - (void)terminate:(
id)aSender
283 didCloseAllSelector:@selector(_documentController:didCloseAll:context:)
298 - (void)setApplicationIconImage:(
CPImage)anImage
300 _applicationIconImage = anImage;
309 if (_applicationIconImage)
310 return _applicationIconImage;
316 return _applicationIconImage;
322 - (void)orderFrontStandardAboutPanel:(
id)sender
356 applicationTitle = [options
objectForKey:"ApplicationName"] || [mainInfo objectForKey:@"CPBundleName"],
358 version = [options
objectForKey:@"Version"] || [mainInfo objectForKey:@"CPBundleVersion"],
359 applicationVersion = [options
objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
360 copyright = [options
objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
364 aboutPanelController = [aboutPanelController initWithWindowCibPath:aboutPanelPath owner:aboutPanelController],
365 aboutPanel = [aboutPanelController window],
366 contentView = [aboutPanel contentView],
367 imageView = [contentView viewWithTag:1],
368 applicationLabel = [contentView viewWithTag:2],
369 versionLabel = [contentView viewWithTag:3],
370 copyrightLabel = [contentView viewWithTag:4],
375 [applicationLabel setAlignment:CPCenterTextAlignment];
376 [versionLabel setAlignment:CPCenterTextAlignment];
377 [copyrightLabel setAlignment:CPCenterTextAlignment];
380 size:CGSizeMake(256, 256)]];
382 [applicationLabel setStringValue:applicationTitle || ""];
384 if (applicationVersion && version)
385 [versionLabel setStringValue:@"Version " + applicationVersion + " (" + version + ")"];
386 else if (applicationVersion || version)
387 [versionLabel setStringValue:@"Version " + (applicationVersion || version)];
389 [versionLabel setStringValue:@""];
391 [copyrightLabel setStringValue:copyright || ""];
394 _aboutPanel = aboutPanel;
397 [_aboutPanel orderFront:self];
401 - (void)_documentController:(NSDocumentController *)docController didCloseAll:(BOOL)didCloseAll context:(Object)info
406 if ([_delegate respondsToSelector:
@selector(applicationShouldTerminate:)])
407 [
self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
409 [
self replyToApplicationShouldTerminate:YES];
413 - (void)replyToApplicationShouldTerminate:(BOOL)terminate
422 - (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
424 [
self _willBecomeActive];
429 [
self _willResignActive];
434 [
self _willResignActive];
439 [
self _didResignActive];
447 - (void)hideOtherApplications:(
id)aSender
476 - (void)stopModalWithCode:(
int)aCode
478 if (!_currentSession)
484 _currentSession._state = aCode;
485 _currentSession = _currentSession._previous;
488 [
self _removeRunModalLoop];
492 - (void)_removeRunModalLoop
494 var count = _eventListeners.length;
497 if (_eventListeners[count]._callback === _CPRunModalLoop)
499 _eventListeners.splice(count, 1);
525 - (CPModalSession)beginModalSessionForWindow:(
CPWindow)aWindow
527 return _CPModalSessionMake(aWindow, 0);
534 - (void)runModalSession:(CPModalSession)aModalSession
536 aModalSession._previous = _currentSession;
537 _currentSession = aModalSession;
539 var theWindow = aModalSession._window;
542 [theWindow makeKeyWindow];
543 [theWindow orderFront:self];
547 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
556 if (!_currentSession)
559 return _currentSession._window;
563 - (BOOL)_handleKeyEquivalent:(
CPEvent)anEvent
565 return [[
self keyWindow] performKeyEquivalent:anEvent] ||
566 [[
self mainMenu] performKeyEquivalent:anEvent];
575 _currentEvent = anEvent;
578 var theWindow = [anEvent
window];
581 var willPropagate = [[theWindow platformWindow] _willPropagateCurrentDOMEvent];
585 [[theWindow platformWindow] _propagateCurrentDOMEvent:NO];
589 if ([anEvent _couldBeKeyEquivalent] && [
self _handleKeyEquivalent:anEvent])
596 if ((characters ==
"c" || characters ==
"x" || characters ==
"v") && (modifierFlags &
CPPlatformActionKeyMask))
597 [[theWindow platformWindow] _propagateCurrentDOMEvent:YES];
605 [[theWindow platformWindow] _propagateCurrentDOMEvent:willPropagate];
608 if (_eventListeners.length)
610 if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
611 _eventListeners.pop()._callback(anEvent);
618 if (theWindow !== _lastMouseMoveWindow)
619 [_lastMouseMoveWindow _mouseExitedResizeRect];
621 _lastMouseMoveWindow = theWindow;
625 [theWindow sendEvent:anEvent];
632 - (void)doCommandBySelector:(
SEL)aSelector
634 if ([_delegate respondsToSelector:aSelector])
635 [_delegate performSelector:aSelector];
659 - (
CPWindow)windowWithWindowNumber:(
int)aWindowNumber
665 return _windows[aWindowNumber];
674 return [_windows subarrayWithRange:_CPMakeRange(1, [_windows count] - 1)];
683 return CPWindowObjectList();
689 - (void)hide:(
id)aSender
714 if ([aMenu _menuName] ===
"CPMainMenu")
716 if ([
self menu] === aMenu)
722 window.cpSetMainMenu([
self menu]);
725 [aMenu _setMenuName:@"CPMainMenu"];
732 - (void)orderFrontColorPanel:(
id)aSender
747 - (BOOL)tryToPerform:(
SEL)anAction with:(
id)anObject
752 if ([super tryToPerform:anAction with:anObject])
755 if ([_delegate respondsToSelector:anAction])
757 [_delegate performSelector:anAction withObject:anObject];
772 - (BOOL)sendAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
779 [target performSelector:anAction withObject:aSender];
795 - (id)targetForAction:(
SEL)anAction to:(
id)aTarget from:(
id)aSender
823 - (id)_targetForWindow:(
CPWindow)aWindow action:(
SEL)anAction
830 if ([responder respondsToSelector:anAction])
833 if (responder == aWindow)
836 responder = [responder nextResponder];
839 if (checkWindow && [aWindow respondsToSelector:anAction])
844 if ([delegate respondsToSelector:anAction])
849 if ([windowController respondsToSelector:anAction])
850 return windowController;
852 var theDocument = [windowController document];
853 if (theDocument !== delegate && [theDocument respondsToSelector:anAction])
873 - (id)targetForAction:(
SEL)anAction
878 var target = [
self _targetForWindow:[
self keyWindow] action:anAction];
883 target = [
self _targetForWindow:[
self mainWindow] action:anAction];
888 if ([
self respondsToSelector:anAction])
891 if ([_delegate respondsToSelector:anAction])
894 if ([_documentController respondsToSelector:anAction])
895 return _documentController;
908 - (void)setCallback:(Function)aCallback forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
910 _eventListeners.push(_CPEventListenerMake(aMask, aCallback));
924 - (void)setTarget:(
id)aTarget selector:(
SEL)aSelector forNextEventMatchingMask:(
unsigned int)aMask untilDate:(
CPDate)anExpiration inMode:(
CPString)aMode dequeue:(BOOL)shouldDequeue
926 _eventListeners.push(_CPEventListenerMake(aMask,
function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
934 return _currentEvent;
947 - (void)beginSheet:(
CPWindow)aSheet modalForWindow:(
CPWindow)aWindow modalDelegate:(
id)aModalDelegate didEndSelector:(
SEL)aDidEndSelector contextInfo:(
id)aContextInfo
949 if ([aWindow isSheet])
951 [
CPException raise:CPInternalInconsistencyException
reason:@"The target window of beginSheet: cannot be a sheet"];
955 [aSheet._windowView _enableSheet:YES];
959 if (![aWindow isVisible])
965 [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
981 - (void)endSheet:(
CPWindow)sheet returnCode:(
int)returnCode
983 var count = [_windows count];
987 var aWindow = [_windows objectAtIndex:count],
988 context = aWindow._sheetContext;
990 if (context != nil && context[
"sheet"] === sheet)
992 context["returnCode"] = returnCode;
1027 if (window && window.location && _fullArgsString !== window.location.
hash)
1028 [
self _reloadArguments];
1051 if (!args || args.length == 0)
1055 if (window && window.location)
1056 window.location.
hash =
@"#";
1060 if (![args isKindOfClass:
CPArray])
1065 var toEncode = [_args copy];
1066 for (var i = 0, count = toEncode.length; i < count; i++)
1067 toEncode[i] = encodeURIComponent(toEncode[i]);
1069 var hash = [toEncode componentsJoinedByString:@"/"];
1072 if (window && window.location)
1073 window.location.hash =
@"#" + hash;
1076 - (void)_reloadArguments
1079 _fullArgsString = (window && window.location) ? window.location.
hash :
"";
1083 var args = _fullArgsString.substring(1).split(
"/");
1085 for (var i = 0, count = args.length; i < count; i++)
1086 args[i] = decodeURIComponent(args[i]);
1116 - (BOOL)_openURL:(
CPURL)aURL
1118 if (_delegate && [_delegate respondsToSelector:
@selector(application:openFile:)])
1120 CPLog.warn(
"application:openFile: is deprecated, use application:openURL: instead.");
1121 return [_delegate application:self openFile:[aURL
absoluteString]];
1124 if (_delegate && [_delegate respondsToSelector:
@selector(application:openURL:)])
1125 return [_delegate application:self openURL:aURL];
1127 return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL];
1130 - (void)_willBecomeActive
1137 - (void)_didBecomeActive
1139 if (![
self keyWindow] && _previousKeyWindow &&
1140 [[
self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !==
CPNotFound)
1141 [_previousKeyWindow makeKeyWindow];
1143 if (![
self mainWindow] && _previousMainWindow &&
1144 [[
self windows] indexOfObjectIdenticalTo:_previousMainWindow] !==
CPNotFound)
1145 [_previousMainWindow makeMainWindow];
1147 if ([
self keyWindow])
1148 [[
self keyWindow] orderFront:self];
1149 else if ([
self mainWindow])
1150 [[
self mainWindow] makeKeyAndOrderFront:self];
1152 [[
self mainMenu]._menuWindow makeKeyWindow];
1154 _previousKeyWindow = nil;
1155 _previousMainWindow = nil;
1162 - (void)_willResignActive
1169 - (void)_didResignActive
1171 if (
self._activeMenu)
1172 [
self._activeMenu cancelTracking];
1174 if ([
self keyWindow])
1176 _previousKeyWindow = [
self keyWindow];
1177 [_previousKeyWindow resignKeyWindow];
1180 if ([
self mainWindow])
1182 _previousMainWindow = [
self mainWindow];
1183 [_previousMainWindow resignMainWindow];
1193 return ([[
CPBundle mainBundle] objectForInfoDictionaryKey:
"CPDefaultTheme"] ||
@"Aristo");
1198 var _CPModalSessionMake =
function(aWindow, aStopCode)
1203 var _CPEventListenerMake =
function(anEventMask, aCallback)
1205 return { _mask:anEventMask, _callback:aCallback };
1209 _CPRunModalLoop =
function(anEvent)
1211 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
1213 var theWindow = [anEvent
window],
1214 modalSession =
CPApp._currentSession;
1220 if (theWindow == modalSession._window ||
1221 [theWindow worksWhenModal] ||
1222 [theWindow attachedSheet] == modalSession._window ||
1223 ([theWindow isKindOfClass:_CPAttachedWindow] && [[theWindow targetView] window] === modalSession._window))
1224 [theWindow sendEvent:anEvent];
1239 if (window.parent !== window && typeof window.parent._childAppIsStarting ===
"function")
1243 window.parent._childAppIsStarting(window);
1248 CPLog.warn(
"Failed to call parent frame's _childAppIsStarting().");
1254 principalClass = [mainBundle principalClass];
1256 if (!principalClass)
1259 [principalClass sharedApplication];
1261 if ([args containsObject:
"debug"])
1262 CPLogRegister(CPLogPopup);
1265 CPApp._namedArgs = namedArgs;
1267 [_CPAppBootstrapper performActions];
1270 var _CPAppBootstrapperActions = nil;
1271 @implementation _CPAppBootstrapper :
CPObject
1278 return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
1281 + (void)performActions
1283 if (!_CPAppBootstrapperActions)
1284 _CPAppBootstrapperActions = [
self actions];
1286 while (_CPAppBootstrapperActions.length)
1288 var action = _CPAppBootstrapperActions.shift();
1290 if (objj_msgSend(
self, action))
1297 + (BOOL)bootstrapPlatform
1302 + (BOOL)loadDefaultTheme
1307 if (defaultThemeName ===
@"Aristo")
1313 [blend loadWithDelegate:self];
1318 + (void)blendDidFinishLoading:(
CPThemeBlend)aThemeBlend
1323 [
self performActions];
1326 + (BOOL)loadMainCibFile
1329 mainCibFile = [mainBundle objectForInfoDictionaryKey:CPMainCibFile] || [mainBundle objectForInfoDictionaryKey:CPMainCibFileHumanFriendly];
1333 [mainBundle loadCibFile:mainCibFile
1340 [
self loadCiblessBrowserMainMenu];
1345 + (void)loadCiblessBrowserMainMenu
1350 [mainMenu setAutoenablesItems:NO];
1358 [mainMenu addItem:newMenuItem];
1365 [mainMenu addItem:openMenuItem];
1376 [saveMenuItem setSubmenu:saveMenu];
1378 [mainMenu addItem:saveMenuItem];
1386 [undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
1387 [redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
1389 [editMenu addItem:undoMenuItem];
1390 [editMenu addItem:redoMenuItem];
1396 [editMenuItem setSubmenu:editMenu];
1397 [editMenuItem setHidden:YES];
1399 [mainMenu addItem:editMenuItem];
1403 [CPApp setMainMenu:mainMenu];
1406 + (void)cibDidFinishLoading:(
CPCib)aCib
1408 [
self performActions];
1411 + (void)cibDidFailToLoad:(
CPCib)aCib
1413 throw new Error(
"Could not load main cib file (Did you forget to nib2cib it?).");
1418 _CPAppBootstrapperActions = nil;
1429 + (unsigned)modifierFlags
1451 _themeBlend = aValue;