00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPBundle.j>
00024
00025 @import "CPCompatibility.j"
00026 @import "CPEvent.j"
00027 @import "CPMenu.j"
00028 @import "CPResponder.j"
00029 @import "CPDocumentController.j"
00030 @import "CPThemeBlend.j"
00031 @import "CPCibLoading.j"
00032 @import "CPPlatform.j"
00033
00034
00035 var CPMainCibFile = @"CPMainCibFile",
00036 CPMainCibFileHumanFriendly = @"Main cib file base name";
00037
00038 CPApp = nil;
00039
00040 CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification";
00041 CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification";
00042 CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification";
00043 CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification";
00044 CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification";
00045 CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification";
00046 CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification";
00047
00048 CPTerminateNow = YES;
00049 CPTerminateCancel = NO;
00050 CPTerminateLater = -1;
00051
00052 CPRunStoppedResponse = -1000;
00053 CPRunAbortedResponse = -1001;
00054 CPRunContinuesResponse = -1002;
00055
00081 @implementation CPApplication : CPResponder
00082 {
00083 CPArray _eventListeners;
00084
00085 CPEvent _currentEvent;
00086
00087 CPArray _windows;
00088 CPWindow _keyWindow;
00089 CPWindow _mainWindow;
00090 CPWindow _previousKeyWindow;
00091 CPWindow _previousMainWindow;
00092
00093 CPMenu _mainMenu;
00094 CPDocumentController _documentController;
00095
00096 CPModalSession _currentSession;
00097
00098
00099 id _delegate;
00100 BOOL _finishedLaunching;
00101 BOOL _isActive;
00102
00103 CPDictionary _namedArgs;
00104 CPArray _args;
00105 CPString _fullArgsString;
00106
00107 CPImage _applicationIconImage;
00108
00109 CPPanel _aboutPanel;
00110 }
00111
00117 + (CPApplication)sharedApplication
00118 {
00119 if (!CPApp)
00120 CPApp = [[CPApplication alloc] init];
00121
00122 return CPApp;
00123 }
00124
00130 - (id)init
00131 {
00132 self = [super init];
00133
00134 if (self)
00135 {
00136 _eventListeners = [];
00137
00138 _windows = [];
00139
00140 [_windows addObject:nil];
00141
00142
00143 _mainMenu = [[CPMenu alloc] initWithTitle:@"MainMenu"];
00144
00145
00146 [_mainMenu setAutoenablesItems:NO];
00147
00148 var bundle = [CPBundle bundleForClass:[CPApplication class]],
00149 newMenuItem = [[CPMenuItem alloc] initWithTitle:@"New" action:@selector(newDocument:) keyEquivalent:@"N"];
00150
00151 [newMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/New.png"] size:CGSizeMake(16.0, 16.0)]];
00152 [newMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/NewHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
00153
00154 [_mainMenu addItem:newMenuItem];
00155
00156 var openMenuItem = [[CPMenuItem alloc] initWithTitle:@"Open" action:@selector(openDocument:) keyEquivalent:@"O"];
00157
00158 [openMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Open.png"] size:CGSizeMake(16.0, 16.0)]];
00159 [openMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/OpenHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
00160
00161 [_mainMenu addItem:openMenuItem];
00162
00163 var saveMenu = [[CPMenu alloc] initWithTitle:@"Save"],
00164 saveMenuItem = [[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:nil];
00165
00166 [saveMenuItem setImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/Save.png"] size:CGSizeMake(16.0, 16.0)]];
00167 [saveMenuItem setAlternateImage:[[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPApplication/SaveHighlighted.png"] size:CGSizeMake(16.0, 16.0)]];
00168
00169 [saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save" action:@selector(saveDocument:) keyEquivalent:@"S"]];
00170 [saveMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Save As" action:@selector(saveDocumentAs:) keyEquivalent:nil]];
00171
00172 [saveMenuItem setSubmenu:saveMenu];
00173
00174 [_mainMenu addItem:saveMenuItem];
00175
00176 var editMenuItem = [[CPMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:nil],
00177 editMenu = [[CPMenu alloc] initWithTitle:@"Edit"],
00178
00179 undoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:CPUndoKeyEquivalent],
00180 redoMenuItem = [[CPMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:CPRedoKeyEquivalent];
00181
00182 [undoMenuItem setKeyEquivalentModifierMask:CPUndoKeyEquivalentModifierMask];
00183 [redoMenuItem setKeyEquivalentModifierMask:CPRedoKeyEquivalentModifierMask];
00184
00185 [editMenu addItem:undoMenuItem];
00186 [editMenu addItem:redoMenuItem];
00187
00188 [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"X"]],
00189 [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"C"]],
00190 [editMenu addItem:[[CPMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"V"]];
00191
00192 [editMenuItem setSubmenu:editMenu];
00193 [editMenuItem setHidden:YES];
00194
00195 [_mainMenu addItem:editMenuItem];
00196
00197 [_mainMenu addItem:[CPMenuItem separatorItem]];
00198 }
00199
00200 return self;
00201 }
00202
00203
00204
00211 - (void)setDelegate:(id)aDelegate
00212 {
00213 if (_delegate == aDelegate)
00214 return;
00215
00216 var defaultCenter = [CPNotificationCenter defaultCenter];
00217
00218 if (_delegate)
00219 {
00220 [defaultCenter
00221 removeObserver:_delegate
00222 name:CPApplicationWillFinishLaunchingNotification
00223 object:self];
00224
00225 [defaultCenter
00226 removeObserver:_delegate
00227 name:CPApplicationDidFinishLaunchingNotification
00228 object:self];
00229
00230 [defaultCenter
00231 removeObserver:_delegate
00232 name:CPApplicationWillBecomeActiveNotification
00233 object:self];
00234
00235 [defaultCenter
00236 removeObserver:_delegate
00237 name:CPApplicationDidBecomeActiveNotification
00238 object:self];
00239
00240 [defaultCenter
00241 removeObserver:_delegate
00242 name:CPApplicationWillResignActiveNotification
00243 object:self];
00244
00245 [defaultCenter
00246 removeObserver:_delegate
00247 name:CPApplicationDidResignActiveNotification
00248 object:self];
00249 }
00250
00251 _delegate = aDelegate;
00252
00253 if ([_delegate respondsToSelector:@selector(applicationWillFinishLaunching:)])
00254 [defaultCenter
00255 addObserver:_delegate
00256 selector:@selector(applicationWillFinishLaunching:)
00257 name:CPApplicationWillFinishLaunchingNotification
00258 object:self];
00259
00260 if ([_delegate respondsToSelector:@selector(applicationDidFinishLaunching:)])
00261 [defaultCenter
00262 addObserver:_delegate
00263 selector:@selector(applicationDidFinishLaunching:)
00264 name:CPApplicationDidFinishLaunchingNotification
00265 object:self];
00266
00267 if ([_delegate respondsToSelector:@selector(applicationWillBecomeActive:)])
00268 [defaultCenter
00269 addObserver:_delegate
00270 selector:@selector(applicationWillBecomeActive:)
00271 name:CPApplicationWillBecomeActiveNotification
00272 object:self];
00273
00274 if ([_delegate respondsToSelector:@selector(applicationDidBecomeActive:)])
00275 [defaultCenter
00276 addObserver:_delegate
00277 selector:@selector(applicationDidBecomeActive:)
00278 name:CPApplicationDidBecomeActiveNotification
00279 object:self];
00280
00281 if ([_delegate respondsToSelector:@selector(applicationWillResignActive:)])
00282 [defaultCenter
00283 addObserver:_delegate
00284 selector:@selector(applicationWillResignActive:)
00285 name:CPApplicationWillResignActiveNotification
00286 object:self];
00287
00288 if ([_delegate respondsToSelector:@selector(applicationDidResignActive:)])
00289 [defaultCenter
00290 addObserver:_delegate
00291 selector:@selector(applicationDidResignActive:)
00292 name:CPApplicationDidResignActiveNotification
00293 object:self];
00294 }
00295
00299 - (id)delegate
00300 {
00301 return _delegate;
00302 }
00303
00310 - (void)finishLaunching
00311 {
00312
00313
00314
00315 window.status = " ";
00316
00317
00318 [[CPCursor arrowCursor] set];
00319
00320 var bundle = [CPBundle mainBundle],
00321 types = [bundle objectForInfoDictionaryKey:@"CPBundleDocumentTypes"];
00322
00323 if ([types count] > 0)
00324 _documentController = [CPDocumentController sharedDocumentController];
00325
00326 var delegateClassName = [bundle objectForInfoDictionaryKey:@"CPApplicationDelegateClass"];
00327
00328 if (delegateClassName)
00329 {
00330 var delegateClass = objj_getClass(delegateClassName);
00331
00332 if (delegateClass)
00333 if ([_documentController class] == delegateClass)
00334 [self setDelegate:_documentController];
00335 else
00336 [self setDelegate:[[delegateClass alloc] init]];
00337 }
00338
00339 var defaultCenter = [CPNotificationCenter defaultCenter];
00340
00341 [defaultCenter
00342 postNotificationName:CPApplicationWillFinishLaunchingNotification
00343 object:self];
00344
00345 var needsUntitled = !!_documentController,
00346 URLStrings = window.cpOpeningURLStrings && window.cpOpeningURLStrings(),
00347 index = 0,
00348 count = [URLStrings count];
00349
00350 for (; index < count; ++index)
00351 needsUntitled = ![self _openURL:[CPURL URLWithString:URLStrings[index]]] || needsUntitled;
00352
00353 if (needsUntitled && [_delegate respondsToSelector:@selector(applicationShouldOpenUntitledFile:)])
00354 needsUntitled = [_delegate applicationShouldOpenUntitledFile:self];
00355
00356 if (needsUntitled)
00357 [_documentController newDocument:self];
00358
00359 [_documentController _updateRecentDocumentsMenu];
00360
00361 [defaultCenter
00362 postNotificationName:CPApplicationDidFinishLaunchingNotification
00363 object:self];
00364
00365 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00366
00367 _finishedLaunching = YES;
00368 }
00369
00370 - (void)terminate:(id)aSender
00371 {
00372 if (![CPPlatform isBrowser])
00373 {
00374 [[CPDocumentController sharedDocumentController] closeAllDocumentsWithDelegate:self
00375 didCloseAllSelector:@selector(_documentController:didCloseAll:context:)
00376 contextInfo:nil];
00377 }
00378 else
00379 {
00380 [[[self keyWindow] platformWindow] _propagateCurrentDOMEvent:YES];
00381 }
00382 }
00383
00384 - (void)setApplicationIconImage:(CPImage)anImage
00385 {
00386 _applicationIconImage = anImage;
00387 }
00388
00389 - (CPImage)applicationIconImage
00390 {
00391 if (_applicationIconImage)
00392 return _applicationIconImage;
00393
00394 var imagePath = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPApplicationIcon"];
00395 if (imagePath)
00396 _applicationIconImage = [[CPImage alloc] initWithContentsOfFile:imagePath];
00397
00398 return _applicationIconImage;
00399 }
00400
00401 - (void)orderFrontStandardAboutPanel:(id)sender
00402 {
00403 [self orderFrontStandardAboutPanelWithOptions:nil];
00404 }
00405
00406 - (void)orderFrontStandardAboutPanelWithOptions:(CPDictionary)options
00407 {
00408 if (!_aboutPanel)
00409 {
00410 var mainInfo = [[CPBundle mainBundle] infoDictionary],
00411 applicationTitle = [options objectForKey:"ApplicationName"] || [mainInfo objectForKey:@"CPBundleName"],
00412 applicationIcon = [options objectForKey:@"ApplicationIcon"] || [self applicationIconImage],
00413 version = [options objectForKey:@"Version"] || [mainInfo objectForKey:@"CPBundleVersion"],
00414 applicationVersion = [options objectForKey:@"ApplicationVersion"] || [mainInfo objectForKey:@"CPBundleShortVersionString"],
00415 copyright = [options objectForKey:@"Copyright"] || [mainInfo objectForKey:@"CPHumanReadableCopyright"];
00416
00417 var aboutPanelController = [[CPWindowController alloc] initWithWindowCibName:@"AboutPanel"],
00418 aboutPanel = [aboutPanelController window],
00419 contentView = [aboutPanel contentView],
00420 imageView = [contentView viewWithTag:1],
00421 applicationLabel = [contentView viewWithTag:2],
00422 versionLabel = [contentView viewWithTag:3],
00423 copyrightLabel = [contentView viewWithTag:4],
00424 standardPath = [[CPBundle bundleForClass:[self class]] pathForResource:@"standardApplicationIcon.png"];
00425
00426
00427 [applicationLabel setFont:[CPFont boldSystemFontOfSize:14.0]];
00428 [applicationLabel setAlignment:CPCenterTextAlignment];
00429 [versionLabel setAlignment:CPCenterTextAlignment];
00430 [copyrightLabel setAlignment:CPCenterTextAlignment];
00431
00432 [imageView setImage:applicationIcon || [[CPImage alloc] initWithContentsOfFile:standardPath
00433 size:CGSizeMake(256, 256)]];
00434
00435 [applicationLabel setStringValue:applicationTitle || ""];
00436
00437 if (applicationVersion && version)
00438 [versionLabel setStringValue:@"Version " + applicationVersion + " (" + version + ")"];
00439 else if (applicationVersion || version)
00440 [versionLabel setStringValue:@"Version " + (applicationVersion || version)];
00441 else
00442 [versionLabel setStringValue:@""];
00443
00444 [copyrightLabel setStringValue:copyright || ""];
00445 [aboutPanel center];
00446
00447 _aboutPanel = aboutPanel;
00448 }
00449
00450 [_aboutPanel orderFront:self];
00451 }
00452
00453
00454 - (void)_documentController:(NSDocumentController *)docController didCloseAll:(BOOL)didCloseAll context:(Object)info
00455 {
00456
00457 if (didCloseAll)
00458 {
00459 if ([_delegate respondsToSelector:@selector(applicationShouldTerminate:)])
00460 [self replyToApplicationShouldTerminate:[_delegate applicationShouldTerminate:self]];
00461 else
00462 [self replyToApplicationShouldTerminate:YES];
00463 }
00464 }
00465
00466 - (void)replyToApplicationShouldTerminate:(BOOL)terminate
00467 {
00468 if (terminate == CPTerminateNow)
00469 {
00470 [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillTerminateNotification object:self];
00471 [CPPlatform terminateApplication];
00472 }
00473 }
00474
00475 - (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps
00476 {
00477 [self _willBecomeActive];
00478
00479 [CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps];
00480 _isActive = YES;
00481
00482 [self _willResignActive];
00483 }
00484
00485 - (void)deactivate
00486 {
00487 [self _willResignActive];
00488
00489 [CPPlatform deactivate];
00490 _isActive = NO;
00491
00492 [self _didResignActive];
00493 }
00494
00495 - (void)isActive
00496 {
00497 return _isActive;
00498 }
00499
00500 - (void)hideOtherApplications:(id)aSender
00501 {
00502 [CPPlatform hideOtherApplications:self];
00503 }
00504
00509 - (void)run
00510 {
00511 [self finishLaunching];
00512 }
00513
00514
00519 - (void)runModalForWindow:(CPWindow)aWindow
00520 {
00521 [self runModalSession:[self beginModalSessionForWindow:aWindow]];
00522 }
00523
00529 - (void)stopModalWithCode:(int)aCode
00530 {
00531 if (!_currentSession)
00532 {
00533 return;
00534
00535 }
00536
00537 _currentSession._state = aCode;
00538 _currentSession = _currentSession._previous;
00539
00540
00541 [self _removeRunModalLoop];
00542 }
00543
00544
00545 - (void)_removeRunModalLoop
00546 {
00547 var count = _eventListeners.length;
00548
00549 while (count--)
00550 if (_eventListeners[count]._callback === _CPRunModalLoop)
00551 {
00552 _eventListeners.splice(count, 1);
00553
00554 return;
00555 }
00556 }
00557
00561 - (void)stopModal
00562 {
00563 [self stopModalWithCode:CPRunStoppedResponse]
00564 }
00565
00569 - (void)abortModal
00570 {
00571 [self stopModalWithCode:CPRunAbortedResponse];
00572 }
00573
00578 - (CPModalSession)beginModalSessionForWindow:(CPWindow)aWindow
00579 {
00580 return _CPModalSessionMake(aWindow, 0);
00581 }
00582
00587 - (void)runModalSession:(CPModalSession)aModalSession
00588 {
00589 aModalSession._previous = _currentSession;
00590 _currentSession = aModalSession;
00591
00592 var theWindow = aModalSession._window;
00593
00594 [theWindow center];
00595 [theWindow makeKeyAndOrderFront:self];
00596
00597
00598
00599 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
00600 }
00601
00606 - (CPWindow)modalWindow
00607 {
00608 if (!_currentSession)
00609 return nil;
00610
00611 return _currentSession._window;
00612 }
00613
00614
00615 - (BOOL)_handleKeyEquivalent:(CPEvent)anEvent
00616 {
00617 return [[self keyWindow] performKeyEquivalent:anEvent] ||
00618 [_mainMenu performKeyEquivalent:anEvent];
00619 }
00620
00625 - (void)sendEvent:(CPEvent)anEvent
00626 {
00627 _currentEvent = anEvent;
00628
00629 var willPropagate = [[[anEvent window] platformWindow] _willPropagateCurrentDOMEvent];
00630
00631
00632
00633 [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO];
00634
00635
00636 if ([anEvent _couldBeKeyEquivalent] && [self _handleKeyEquivalent:anEvent])
00637 {
00638 var characters = [anEvent characters],
00639 modifierFlags = [anEvent modifierFlags];
00640
00641
00642 if ((characters == "c" || characters == "x" || characters == "v") && (modifierFlags & CPPlatformActionKeyMask))
00643 [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:YES];
00644
00645 return;
00646 }
00647
00648
00649 [[[anEvent window] platformWindow] _propagateCurrentDOMEvent:willPropagate];
00650
00651 if (_eventListeners.length)
00652 {
00653 if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
00654 _eventListeners.pop()._callback(anEvent);
00655
00656 return;
00657 }
00658
00659 [[anEvent window] sendEvent:anEvent];
00660 }
00661
00662 - (void)doCommandBySelector:(SEL)aSelector
00663 {
00664 if ([_delegate respondsToSelector:aSelector])
00665 [_delegate performSelector:aSelector];
00666 else
00667 [super doCommandBySelector:aSelector];
00668 }
00669
00673 - (CPWindow)keyWindow
00674 {
00675 return _keyWindow;
00676 }
00677
00681 - (CPWindow)mainWindow
00682 {
00683 return _mainWindow;
00684 }
00685
00689 - (CPWindow)windowWithWindowNumber:(int)aWindowNumber
00690 {
00691 return _windows[aWindowNumber];
00692 }
00693
00697 - (CPArray)windows
00698 {
00699 return _windows;
00700 }
00701
00705 - (CPArray)orderedWindows
00706 {
00707 return CPWindowObjectList();
00708 }
00709
00710 - (void)hide:(id)aSender
00711 {
00712 [CPPlatform hide:self];
00713 }
00714
00715
00719 - (CPMenu)mainMenu
00720 {
00721 return _mainMenu;
00722 }
00723
00728 - (void)setMainMenu:(CPMenu)aMenu
00729 {
00730 if ([aMenu _menuName] === "CPMainMenu")
00731 {
00732 if (_mainMenu === aMenu)
00733 return;
00734
00735 _mainMenu = aMenu;
00736
00737 if ([CPPlatform supportsNativeMainMenu])
00738 window.cpSetMainMenu(_mainMenu);
00739 }
00740 else
00741 [aMenu _setMenuName:@"CPMainMenu"];
00742 }
00743
00744 - (void)orderFrontColorPanel:(id)aSender
00745 {
00746 [[CPColorPanel sharedColorPanel] orderFront:self];
00747 }
00748
00749
00759 - (BOOL)tryToPerform:(SEL)anAction with:(id)anObject
00760 {
00761 if (!anAction)
00762 return NO;
00763
00764 if ([super tryToPerform:anAction with:anObject])
00765 return YES;
00766
00767 if([_delegate respondsToSelector:anAction])
00768 {
00769 [_delegate performSelector:anAction withObject:anObject];
00770
00771 return YES;
00772 }
00773
00774 return NO;
00775 }
00776
00784 - (BOOL)sendAction:(SEL)anAction to:(id)aTarget from:(id)aSender
00785 {
00786 var target = [self targetForAction:anAction to:aTarget from:aSender];
00787
00788 if (!target)
00789 return NO;
00790
00791 [target performSelector:anAction withObject:aSender];
00792
00793 return YES;
00794 }
00795
00807 - (id)targetForAction:(SEL)anAction to:(id)aTarget from:(id)aSender
00808 {
00809 if (!anAction)
00810 return nil;
00811
00812 if (aTarget)
00813 return aTarget;
00814
00815 return [self targetForAction:anAction];
00816 }
00817
00835 - (id)_targetForWindow:(CPWindow)aWindow action:(SEL)anAction
00836 {
00837 var responder = [aWindow firstResponder],
00838 checkWindow = YES;
00839
00840 while (responder)
00841 {
00842 if ([responder respondsToSelector:anAction])
00843 return responder;
00844
00845 if (responder == aWindow)
00846 checkWindow = NO;
00847
00848 responder = [responder nextResponder];
00849 }
00850
00851 if (checkWindow && [aWindow respondsToSelector:anAction])
00852 return aWindow;
00853
00854 var delegate = [aWindow delegate];
00855
00856 if ([delegate respondsToSelector:anAction])
00857 return delegate;
00858
00859 var windowController = [aWindow windowController];
00860
00861 if ([windowController respondsToSelector:anAction])
00862 return windowController;
00863
00864 var theDocument = [windowController document];
00865 if (theDocument !== delegate && [theDocument respondsToSelector:anAction])
00866 return theDocument;
00867
00868 return nil;
00869 }
00870
00885 - (id)targetForAction:(SEL)anAction
00886 {
00887 if (!anAction)
00888 return nil;
00889
00890 var target = [self _targetForWindow:[self keyWindow] action:anAction];
00891
00892 if (target)
00893 return target;
00894
00895 target = [self _targetForWindow:[self mainWindow] action:anAction];
00896
00897 if (target)
00898 return target;
00899
00900 if ([self respondsToSelector:anAction])
00901 return self;
00902
00903 if ([_delegate respondsToSelector:anAction])
00904 return _delegate;
00905
00906 if ([_documentController respondsToSelector:anAction])
00907 return _documentController;
00908
00909 return nil;
00910 }
00911
00912 - (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
00913 {
00914 _eventListeners.push(_CPEventListenerMake(aMask, aCallback));
00915 }
00916
00917 - (CPEvent)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
00918 {
00919 _eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
00920 }
00921
00922 - (CPEvent)currentEvent
00923 {
00924 return _currentEvent;
00925 }
00926
00927
00928
00937 - (void)beginSheet:(CPWindow)aSheet modalForWindow:(CPWindow)aWindow modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
00938 {
00939 var styleMask = [aSheet styleMask];
00940 if (!(styleMask & CPDocModalWindowMask))
00941 {
00942 [CPException raise:CPInternalInconsistencyException reason:@"Currently only CPDocModalWindowMask style mask is supported for attached sheets"];
00943 return;
00944 }
00945
00946 [aWindow orderFront:self];
00947 [aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:aDidEndSelector contextInfo:aContextInfo];
00948 }
00949
00950 - (void)endSheet:(CPWindow)sheet returnCode:(int)returnCode
00951 {
00952 var count = [_windows count];
00953
00954 while (--count >= 0)
00955 {
00956 var aWindow = [_windows objectAtIndex:count];
00957 var context = aWindow._sheetContext;
00958
00959 if (context != nil && context["sheet"] === sheet)
00960 {
00961 context["returnCode"] = returnCode;
00962 [aWindow _detachSheetWindow];
00963 return;
00964 }
00965 }
00966 }
00967
00968 - (void)endSheet:(CPWindow)sheet
00969 {
00970 [self endSheet:sheet returnCode:0];
00971 }
00972
00973 - (CPArray)arguments
00974 {
00975 if(_fullArgsString !== window.location.hash)
00976 [self _reloadArguments];
00977
00978 return _args;
00979 }
00980
00981 - (void)setArguments:(CPArray)args
00982 {
00983 if(!args || args.length == 0)
00984 {
00985 _args = [];
00986 window.location.hash = @"#";
00987
00988 return;
00989 }
00990
00991 if([args class] != CPArray)
00992 args = [CPArray arrayWithObject:args];
00993
00994 _args = args;
00995
00996 var toEncode = [_args copy];
00997 for(var i=0, count = toEncode.length; i<count; i++)
00998 toEncode[i] = encodeURIComponent(toEncode[i]);
00999
01000 var hash = [toEncode componentsJoinedByString:@"/"];
01001
01002 window.location.hash = @"#" + hash;
01003 }
01004
01005 - (void)_reloadArguments
01006 {
01007 _fullArgsString = window.location.hash;
01008
01009 if (_fullArgsString.length)
01010 {
01011 var args = _fullArgsString.substring(1).split("/");
01012
01013 for (var i = 0, count = args.length; i < count; i++)
01014 args[i] = decodeURIComponent(args[i]);
01015
01016 _args = args;
01017 }
01018 else
01019 _args = [];
01020 }
01021
01022 - (CPDictionary)namedArguments
01023 {
01024 return _namedArgs;
01025 }
01026
01027 - (BOOL)_openURL:(CPURL)aURL
01028 {
01029 if (_delegate && [_delegate respondsToSelector:@selector(application:openFile:)])
01030 {
01031 CPLog.warn("application:openFile: is deprecated, use application:openURL: instead.");
01032 return [_delegate application:self openFile:[aURL absoluteString]];
01033 }
01034
01035 if (_delegate && [_delegate respondsToSelector:@selector(application:openURL:)])
01036 return [_delegate application:self openURL:aURL];
01037
01038 return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL];
01039 }
01040
01041 - (void)_willBecomeActive
01042 {
01043 [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification
01044 object:self
01045 userInfo:nil];
01046 }
01047
01048 - (void)_didBecomeActive
01049 {
01050 if (![self keyWindow] && _previousKeyWindow &&
01051 [[self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !== CPNotFound)
01052 [_previousKeyWindow makeKeyWindow];
01053
01054 if (![self mainWindow] && _previousMainWindow &&
01055 [[self windows] indexOfObjectIdenticalTo:_previousMainWindow] !== CPNotFound)
01056 [_previousMainWindow makeMainWindow];
01057
01058 if ([self keyWindow])
01059 [[self keyWindow] orderFront:self];
01060 else if ([self mainWindow])
01061 [[self mainWindow] makeKeyAndOrderFront:self];
01062 else
01063 [[self mainMenu]._menuWindow makeKeyWindow];
01064
01065 _previousKeyWindow = nil;
01066 _previousMainWindow = nil;
01067
01068 [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification
01069 object:self
01070 userInfo:nil];
01071 }
01072
01073 - (void)_willResignActive
01074 {
01075 [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification
01076 object:self
01077 userInfo:nil];
01078 }
01079
01080 - (void)_didResignActive
01081 {
01082 if (self._activeMenu)
01083 [self._activeMenu cancelTracking];
01084
01085 if ([self keyWindow])
01086 {
01087 _previousKeyWindow = [self keyWindow];
01088 [_previousKeyWindow resignKeyWindow];
01089 }
01090
01091 if ([self mainWindow])
01092 {
01093 _previousMainWindow = [self mainWindow];
01094 [_previousMainWindow resignMainWindow];
01095 }
01096
01097 [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification
01098 object:self
01099 userInfo:nil];
01100 }
01101
01102 + (CPString)defaultThemeName
01103 {
01104
01105 return ([[CPBundle mainBundle] objectForInfoDictionaryKey:"CPDefaultTheme"] || @"Aristo");
01106 }
01107
01108 @end
01109
01110 var _CPModalSessionMake = function(aWindow, aStopCode)
01111 {
01112 return { _window:aWindow, _state:CPRunContinuesResponse , _previous:nil };
01113 }
01114
01115 var _CPEventListenerMake = function(anEventMask, aCallback)
01116 {
01117 return { _mask:anEventMask, _callback:aCallback };
01118 }
01119
01120 var _CPRunModalLoop = function(anEvent)
01121 {
01122 [CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
01123
01124 var theWindow = [anEvent window],
01125 modalSession = CPApp._currentSession;
01126
01127 if (theWindow == modalSession._window || [theWindow worksWhenModal])
01128 [theWindow sendEvent:anEvent];
01129 }
01130
01138 function CPApplicationMain(args, namedArgs)
01139 {
01140 var mainBundle = [CPBundle mainBundle],
01141 principalClass = [mainBundle principalClass];
01142
01143 if (!principalClass)
01144 principalClass = [CPApplication class];
01145
01146 [principalClass sharedApplication];
01147
01148 if ([args containsObject:"debug"])
01149 CPLogRegister(CPLogPopup);
01150
01151 CPApp._args = args;
01152 CPApp._namedArgs = namedArgs;
01153
01154 [_CPAppBootstrapper performActions];
01155 }
01156
01157 var _CPAppBootstrapperActions = nil;
01158
01159 @implementation _CPAppBootstrapper : CPObject
01160 {
01161 }
01162
01163 + (CPArray)actions
01164 {
01165 return [@selector(bootstrapPlatform), @selector(loadDefaultTheme), @selector(loadMainCibFile)];
01166 }
01167
01168 + (void)performActions
01169 {
01170 if (!_CPAppBootstrapperActions)
01171 _CPAppBootstrapperActions = [self actions];
01172
01173 while (_CPAppBootstrapperActions.length)
01174 {
01175 var action = _CPAppBootstrapperActions.shift();
01176
01177 if (objj_msgSend(self, action))
01178 return;
01179 }
01180
01181 [CPApp run];
01182 }
01183
01184 + (BOOL)bootstrapPlatform
01185 {
01186 return [CPPlatform bootstrap];
01187 }
01188
01189 + (BOOL)loadDefaultTheme
01190 {
01191 var blend = [[CPThemeBlend alloc] initWithContentsOfURL:[[CPBundle bundleForClass:[CPApplication class]] pathForResource:[CPApplication defaultThemeName] + ".blend"]];
01192
01193 [blend loadWithDelegate:self];
01194
01195 return YES;
01196 }
01197
01198 + (void)blendDidFinishLoading:(CPThemeBlend)aThemeBlend
01199 {
01200 [CPTheme setDefaultTheme:[CPTheme themeNamed:[CPApplication defaultThemeName]]];
01201
01202 [self performActions];
01203 }
01204
01205 + (BOOL)loadMainCibFile
01206 {
01207 var mainBundle = [CPBundle mainBundle],
01208 mainCibFile = [mainBundle objectForInfoDictionaryKey:CPMainCibFile] || [mainBundle objectForInfoDictionaryKey:CPMainCibFileHumanFriendly];
01209
01210 if (mainCibFile)
01211 {
01212 [mainBundle loadCibFile:mainCibFile
01213 externalNameTable:[CPDictionary dictionaryWithObject:CPApp forKey:CPCibOwner]
01214 loadDelegate:self];
01215
01216 return YES;
01217 }
01218
01219 return NO;
01220 }
01221
01222 + (void)cibDidFinishLoading:(CPCib)aCib
01223 {
01224 [self performActions];
01225 }
01226
01227 + (void)cibDidFailToLoad:(CPCib)aCib
01228 {
01229 throw new Error("Could not load main cib file (Did you forget to nib2cib it?).");
01230 }
01231
01232 + (void)reset
01233 {
01234 _CPAppBootstrapperActions = nil;
01235 }
01236
01237 @end