API 0.9.5
AppKit/CPWindow/CPWindow.j
Go to the documentation of this file.
00001 /*
00002  * CPWindow.j
00003  * AppKit
00004  *
00005  * Created by Francisco Tolmasky.
00006  * Copyright 2008, 280 North, Inc.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 
00024 
00025 
00026 /*
00027     Borderless window mask option.
00028     @global
00029     @class CPWindow
00030 */
00031 CPBorderlessWindowMask          = 0;
00032 /*
00033     Titled window mask option.
00034     @global
00035     @class CPWindow
00036 */
00037 CPTitledWindowMask              = 1 << 0;
00038 /*
00039     Closeable window mask option.
00040     @global
00041     @class CPWindow
00042 */
00043 CPClosableWindowMask            = 1 << 1;
00044 /*
00045     Miniaturizabe window mask option.
00046     @global
00047     @class CPWindow
00048 */
00049 CPMiniaturizableWindowMask      = 1 << 2;
00050 /*
00051     Resizable window mask option.
00052     @global
00053     @class CPWindow
00054 */
00055 CPResizableWindowMask           = 1 << 3;
00056 /*
00057     Textured window mask option.
00058     @global
00059     @class CPWindow
00060 */
00061 CPTexturedBackgroundWindowMask  = 1 << 8;
00062 /*
00063     @global
00064     @class CPWindow
00065 */
00066 CPBorderlessBridgeWindowMask    = 1 << 20;
00067 /*
00068     @global
00069     @class CPWindow
00070 */
00071 CPHUDBackgroundWindowMask       = 1 << 21;
00072 
00073 CPWindowNotSizable              = 0;
00074 CPWindowMinXMargin              = 1;
00075 CPWindowWidthSizable            = 2;
00076 CPWindowMaxXMargin              = 4;
00077 CPWindowMinYMargin              = 8;
00078 CPWindowHeightSizable           = 16;
00079 CPWindowMaxYMargin              = 32;
00080 
00081 CPBackgroundWindowLevel         = -1;
00082 /*
00083     Default level for windows
00084     @group CPWindowLevel
00085     @global
00086 */
00087 CPNormalWindowLevel             = 0;
00088 /*
00089     Floating palette type window
00090     @group CPWindowLevel
00091     @global
00092 */
00093 CPFloatingWindowLevel           = 3;
00094 /*
00095     Submenu type window
00096     @group CPWindowLevel
00097     @global
00098 */
00099 CPSubmenuWindowLevel            = 3;
00100 /*
00101     For a torn-off menu
00102     @group CPWindowLevel
00103     @global
00104 */
00105 CPTornOffMenuWindowLevel        = 3;
00106 /*
00107     For the application's main menu
00108     @group CPWindowLevel
00109     @global
00110 */
00111 CPMainMenuWindowLevel           = 24;
00112 /*
00113     Status window level
00114     @group CPWindowLevel
00115     @global
00116 */
00117 CPStatusWindowLevel             = 25;
00118 /*
00119     Level for a modal panel
00120     @group CPWindowLevel
00121     @global
00122 */
00123 CPModalPanelWindowLevel         = 8;
00124 /*
00125     Level for a pop up menu
00126     @group CPWindowLevel
00127     @global
00128 */
00129 CPPopUpMenuWindowLevel          = 101;
00130 /*
00131     Level for a window being dragged
00132     @group CPWindowLevel
00133     @global
00134 */
00135 CPDraggingWindowLevel           = 500;
00136 /*
00137     Level for the screens saver
00138     @group CPWindowLevel
00139     @global
00140 */
00141 CPScreenSaverWindowLevel        = 1000;
00142 
00143 /*
00144     The receiver is removed from the screen list and hidden.
00145     @global
00146     @class CPWindowOrderingMode
00147 */
00148 CPWindowOut                     = 0;
00149 /*
00150     The receiver is placed directly in front of the window specified.
00151     @global
00152     @class CPWindowOrderingMode
00153 */
00154 CPWindowAbove                   = 1;
00155 /*
00156     The receiver is placed directly behind the window specified.
00157     @global
00158     @class CPWindowOrderingMode
00159 */
00160 CPWindowBelow                   = 2;
00161 
00162 CPWindowWillCloseNotification       = @"CPWindowWillCloseNotification";
00163 CPWindowDidBecomeMainNotification   = @"CPWindowDidBecomeMainNotification";
00164 CPWindowDidResignMainNotification   = @"CPWindowDidResignMainNotification";
00165 CPWindowDidBecomeKeyNotification    = @"CPWindowDidBecomeKeyNotification";
00166 CPWindowDidResignKeyNotification    = @"CPWindowDidResignKeyNotification";
00167 CPWindowDidResizeNotification       = @"CPWindowDidResizeNotification";
00168 CPWindowDidMoveNotification         = @"CPWindowDidMoveNotification";
00169 CPWindowWillBeginSheetNotification  = @"CPWindowWillBeginSheetNotification";
00170 CPWindowDidEndSheetNotification     = @"CPWindowDidEndSheetNotification";
00171 CPWindowDidMiniaturizeNotification  = @"CPWindowDidMiniaturizeNotification";
00172 CPWindowWillMiniaturizeNotification = @"CPWindowWillMiniaturizeNotification";
00173 CPWindowDidDeminiaturizeNotification = @"CPWindowDidDeminiaturizeNotification";
00174 
00175 CPWindowShadowStyleStandard = 0;
00176 CPWindowShadowStyleMenu     = 1;
00177 CPWindowShadowStylePanel    = 2;
00178 
00179 var SHADOW_MARGIN_LEFT      = 20.0,
00180     SHADOW_MARGIN_RIGHT     = 19.0,
00181     SHADOW_MARGIN_TOP       = 10.0,
00182     SHADOW_MARGIN_BOTTOM    = 10.0,
00183     SHADOW_DISTANCE         = 5.0,
00184 
00185     _CPWindowShadowColor    = nil;
00186 
00187 var CPWindowSaveImage       = nil,
00188     CPWindowSavingImage     = nil,
00189 
00190     CPWindowResizeTime      = 0.2;
00191 
00192 /*
00193     Keys for which action messages will be sent by default when unhandled, e.g. complete:.
00194 */
00195 var CPWindowActionMessageKeys = [
00196         CPLeftArrowFunctionKey,
00197         CPRightArrowFunctionKey,
00198         CPUpArrowFunctionKey,
00199         CPDownArrowFunctionKey,
00200         CPPageUpFunctionKey,
00201         CPPageDownFunctionKey,
00202         CPHomeFunctionKey,
00203         CPEndFunctionKey,
00204         CPEscapeFunctionKey
00205     ];
00206 
00253 @implementation CPWindow : CPResponder
00254 {
00255     CPPlatformWindow                    _platformWindow;
00256 
00257     int                                 _windowNumber;
00258     unsigned                            _styleMask;
00259     CGRect                              _frame;
00260     int                                 _level;
00261     BOOL                                _isVisible;
00262     BOOL                                _isMiniaturized;
00263     BOOL                                _isAnimating;
00264     BOOL                                _hasShadow;
00265     BOOL                                _isMovableByWindowBackground;
00266     BOOL                                _isMovable;
00267     unsigned                            _shadowStyle;
00268     BOOL                                _showsResizeIndicator;
00269 
00270     BOOL                                _isDocumentEdited;
00271     BOOL                                _isDocumentSaving;
00272 
00273     CPImageView                         _shadowView;
00274 
00275     CPView                              _windowView;
00276     CPView                              _contentView;
00277     CPView                              _toolbarView;
00278 
00279     CPArray                             _mouseEnteredStack;
00280     CPView                              _leftMouseDownView;
00281     CPView                              _rightMouseDownView;
00282 
00283     CPToolbar                           _toolbar;
00284     CPResponder                         _firstResponder;
00285     CPResponder                         _initialFirstResponder;
00286     id                                  _delegate;
00287 
00288     CPString                            _title;
00289 
00290     BOOL                                _acceptsMouseMovedEvents;
00291     BOOL                                _ignoresMouseEvents;
00292 
00293     CPWindowController                  _windowController;
00294 
00295     CGSize                              _minSize;
00296     CGSize                              _maxSize;
00297 
00298     CPUndoManager                       _undoManager;
00299     CPURL                               _representedURL;
00300 
00301     CPSet                               _registeredDraggedTypes;
00302     CPArray                             _registeredDraggedTypesArray;
00303     CPCountedSet                        _inclusiveRegisteredDraggedTypes;
00304 
00305     CPButton                            _defaultButton;
00306     BOOL                                _defaultButtonEnabled;
00307 
00308     BOOL                                _autorecalculatesKeyViewLoop;
00309     BOOL                                _keyViewLoopIsDirty;
00310 
00311     BOOL                                _sharesChromeWithPlatformWindow;
00312 
00313     // Bridge Support
00314 #if PLATFORM(DOM)
00315     DOMElement                          _DOMElement;
00316 #endif
00317 
00318     unsigned                            _autoresizingMask;
00319 
00320     BOOL                                _delegateRespondsToWindowWillReturnUndoManagerSelector;
00321 
00322     BOOL                                _isFullPlatformWindow;
00323     _CPWindowFullPlatformWindowSession  _fullPlatformWindowSession;
00324 
00325     CPDictionary                        _sheetContext;
00326     CPWindow                            _parentView;
00327     BOOL                                _isSheet;
00328 
00329     _CPWindowFrameAnimation             _frameAnimation;
00330 }
00331 
00332 /*
00333     Private initializer for Objective-J
00334     @ignore
00335 */
00336 + (void)initialize
00337 {
00338     if (self != [CPWindow class])
00339         return;
00340 
00341     var bundle = [CPBundle bundleForClass:[CPWindow class]];
00342 
00343     CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)]
00344 }
00345 
00346 - (id)init
00347 {
00348     return [self initWithContentRect:_CGRectMakeZero() styleMask:CPTitledWindowMask];
00349 }
00350 
00366 - (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
00367 {
00368     self = [super init];
00369 
00370     if (self)
00371     {
00372         var windowViewClass = [[self class] _windowViewClassForStyleMask:aStyleMask];
00373 
00374         _frame = [windowViewClass frameRectForContentRect:aContentRect];
00375 
00376         [self _setSharesChromeWithPlatformWindow:![CPPlatform isBrowser]];
00377 
00378         if ([CPPlatform isBrowser])
00379             [self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]];
00380         else
00381         {
00382             // give zero sized borderless bridge windows a default size if we're not in the browser so they show up in NativeHost.
00383             if ((aStyleMask & CPBorderlessBridgeWindowMask) && aContentRect.size.width === 0 && aContentRect.size.height === 0)
00384             {
00385                 var visibleFrame = [[[CPScreen alloc] init] visibleFrame];
00386                 _frame.size.height = MIN(768.0, visibleFrame.size.height);
00387                 _frame.size.width = MIN(1024.0, visibleFrame.size.width);
00388                 _frame.origin.x = (visibleFrame.size.width - _frame.size.width) / 2;
00389                 _frame.origin.y = (visibleFrame.size.height - _frame.size.height) / 2;
00390             }
00391             [self setPlatformWindow:[[CPPlatformWindow alloc] initWithContentRect:_frame]];
00392             [self platformWindow]._only = self;
00393         }
00394 
00395         _isFullPlatformWindow = NO;
00396         _registeredDraggedTypes = [CPSet set];
00397         _registeredDraggedTypesArray = [];
00398         _isSheet = NO;
00399         _acceptsMouseMovedEvents = YES;
00400         _isMovable = YES;
00401 
00402         // Set up our window number.
00403         _windowNumber = [CPApp._windows count];
00404         CPApp._windows[_windowNumber] = self;
00405 
00406         _styleMask = aStyleMask;
00407 
00408         [self setLevel:CPNormalWindowLevel];
00409 
00410         _minSize = CGSizeMake(0.0, 0.0);
00411         _maxSize = CGSizeMake(1000000.0, 1000000.0);
00412 
00413         // Create our border view which is the actual root of our view hierarchy.
00414         _windowView = [[windowViewClass alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) styleMask:aStyleMask];
00415 
00416         [_windowView _setWindow:self];
00417         [_windowView setNextResponder:self];
00418 
00419         [self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
00420 
00421         // Create a generic content view.
00422         [self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
00423         [self setInitialFirstResponder:[self contentView]];
00424 
00425         _firstResponder = self;
00426 
00427 #if PLATFORM(DOM)
00428         _DOMElement = document.createElement("div");
00429 
00430         _DOMElement.style.position = "absolute";
00431         _DOMElement.style.visibility = "visible";
00432         _DOMElement.style.zIndex = 0;
00433 
00434         if (![self _sharesChromeWithPlatformWindow])
00435         {
00436             CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame));
00437         }
00438 
00439         CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1);
00440         CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement);
00441 #endif
00442 
00443         [self setNextResponder:CPApp];
00444 
00445         [self setHasShadow:aStyleMask !== CPBorderlessWindowMask];
00446 
00447         if (aStyleMask & CPBorderlessBridgeWindowMask)
00448             [self setFullPlatformWindow:YES];
00449 
00450         _defaultButtonEnabled = YES;
00451         _keyViewLoopIsDirty = YES;
00452 
00453         [self setShowsResizeIndicator:_styleMask & CPResizableWindowMask];
00454     }
00455 
00456     return self;
00457 }
00458 
00459 - (CPPlatformWindow)platformWindow
00460 {
00461     return _platformWindow;
00462 }
00463 
00469 - (void)setPlatformWindow:(CPPlatformWindow)aPlatformWindow
00470 {
00471     var wasVisible = [self isVisible];
00472 
00473     // we have to close it first, otherwise we get a DOM exception.
00474     if (wasVisible)
00475         [self close];
00476 
00477     _platformWindow = aPlatformWindow;
00478     [_platformWindow _setTitle:_title window:self];
00479 
00480     if (wasVisible)
00481         [self orderFront:self];
00482 }
00483 
00484 
00488 + (Class)_windowViewClassForStyleMask:(unsigned)aStyleMask
00489 {
00490     if (aStyleMask & CPHUDBackgroundWindowMask)
00491         return _CPHUDWindowView;
00492 
00493     else if (aStyleMask === CPBorderlessWindowMask)
00494         return _CPBorderlessWindowView;
00495 
00496     else if (aStyleMask & CPDocModalWindowMask)
00497         return _CPDocModalWindowView;
00498 
00499     return _CPStandardWindowView;
00500 }
00501 
00502 + (Class)_windowViewClassForFullPlatformWindowStyleMask:(unsigned)aStyleMask
00503 {
00504     return _CPBorderlessBridgeWindowView;
00505 }
00506 
00507 - (void)awakeFromCib
00508 {
00509     _keyViewLoopIsDirty = ![self _hasKeyViewLoop];
00510 }
00511 
00512 - (void)_setWindowView:(CPView)aWindowView
00513 {
00514     if (_windowView === aWindowView)
00515         return;
00516 
00517     var oldWindowView = _windowView;
00518 
00519     _windowView = aWindowView;
00520 
00521     if (oldWindowView)
00522     {
00523         [oldWindowView _setWindow:nil];
00524         [oldWindowView noteToolbarChanged];
00525 
00526 #if PLATFORM(DOM)
00527         CPDOMDisplayServerRemoveChild(_DOMElement, oldWindowView._DOMElement);
00528 #endif
00529     }
00530 
00531     if (_windowView)
00532     {
00533 #if PLATFORM(DOM)
00534         CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement);
00535 #endif
00536 
00537         var contentRect = [_contentView convertRect:[_contentView bounds] toView:nil];
00538 
00539         contentRect.origin = [self convertBaseToGlobal:contentRect.origin];
00540 
00541         [_windowView _setWindow:self];
00542         [_windowView setNextResponder:self];
00543         [_windowView addSubview:_contentView];
00544         [_windowView setTitle:_title];
00545         [_windowView noteToolbarChanged];
00546         [_windowView setShowsResizeIndicator:[self showsResizeIndicator]];
00547 
00548         [self setFrame:[self frameRectForContentRect:contentRect]];
00549     }
00550 }
00551 
00558 - (void)setFullPlatformWindow:(BOOL)shouldBeFullPlatformWindow
00559 {
00560     if (![_platformWindow supportsFullPlatformWindows])
00561         return;
00562 
00563     shouldBeFullPlatformWindow = !!shouldBeFullPlatformWindow;
00564 
00565     if (_isFullPlatformWindow === shouldBeFullPlatformWindow)
00566         return;
00567 
00568     _isFullPlatformWindow = shouldBeFullPlatformWindow;
00569 
00570     if (_isFullPlatformWindow)
00571     {
00572         _fullPlatformWindowSession = _CPWindowFullPlatformWindowSessionMake(_windowView, [self contentRectForFrameRect:[self frame]], [self hasShadow], [self level]);
00573 
00574         var fullPlatformWindowViewClass = [[self class] _windowViewClassForFullPlatformWindowStyleMask:_styleMask],
00575             windowView = [[fullPlatformWindowViewClass alloc] initWithFrame:CGRectMakeZero() styleMask:_styleMask];
00576 
00577         [self _setWindowView:windowView];
00578 
00579         [self setLevel:CPBackgroundWindowLevel];
00580         [self setHasShadow:NO];
00581         [self setAutoresizingMask:CPWindowWidthSizable | CPWindowHeightSizable];
00582         [self setFrame:[_platformWindow visibleFrame]];
00583     }
00584     else
00585     {
00586         var windowView = _fullPlatformWindowSession.windowView;
00587 
00588         [self _setWindowView:windowView];
00589 
00590         [self setLevel:_fullPlatformWindowSession.level];
00591         [self setHasShadow:_fullPlatformWindowSession.hasShadow];
00592         [self setAutoresizingMask:CPWindowNotSizable];
00593 
00594         [self setFrame:[windowView frameRectForContentRect:_fullPlatformWindowSession.contentRect]];
00595     }
00596 }
00597 
00601 - (BOOL)isFullPlatformWindow
00602 {
00603     return _isFullPlatformWindow;
00604 }
00605 
00609 - (unsigned)styleMask
00610 {
00611     return _styleMask;
00612 }
00613 
00632 + (CGRect)frameRectForContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask
00633 {
00634     return [[[self class] _windowViewClassForStyleMask:aStyleMask] frameRectForContentRect:aContentRect];
00635 }
00636 
00641 - (CGRect)contentRectForFrameRect:(CGRect)aFrame
00642 {
00643     return [_windowView contentRectForFrameRect:aFrame];
00644 }
00645 
00651 - (CGRect)frameRectForContentRect:(CGRect)aContentRect
00652 {
00653     return [_windowView frameRectForContentRect:aContentRect];
00654 }
00655 
00659 - (CGRect)frame
00660 {
00661     return _CGRectMakeCopy(_frame);
00662 }
00663 
00671 - (void)_setClippedFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
00672 {
00673     aFrame.size.width = MIN(MAX(aFrame.size.width, _minSize.width), _maxSize.width)
00674     aFrame.size.height = MIN(MAX(aFrame.size.height, _minSize.height), _maxSize.height);
00675     [self setFrame:aFrame display:shouldDisplay animate:shouldAnimate];
00676 }
00677 
00685 - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
00686 {
00687     aFrame = _CGRectMakeCopy(aFrame);
00688 
00689     var value = aFrame.origin.x,
00690         delta = value - FLOOR(value);
00691 
00692     if (delta)
00693         aFrame.origin.x = value > 0.879 ? CEIL(value) : FLOOR(value);
00694 
00695     value = aFrame.origin.y;
00696     delta = value - FLOOR(value);
00697 
00698     if (delta)
00699         aFrame.origin.y = value > 0.879 ? CEIL(value) : FLOOR(value);
00700 
00701     value = aFrame.size.width;
00702     delta = value - FLOOR(value);
00703 
00704     if (delta)
00705         aFrame.size.width = value > 0.15 ? CEIL(value) : FLOOR(value);
00706 
00707     value = aFrame.size.height;
00708     delta = value - FLOOR(value);
00709 
00710     if (delta)
00711         aFrame.size.height = value > 0.15 ? CEIL(value) : FLOOR(value);
00712 
00713     if (shouldAnimate)
00714     {
00715         [_frameAnimation stopAnimation];
00716         _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
00717 
00718         [_frameAnimation startAnimation];
00719     }
00720     else
00721     {
00722         var origin = _frame.origin,
00723             newOrigin = aFrame.origin;
00724 
00725         if (!_CGPointEqualToPoint(origin, newOrigin))
00726         {
00727             origin.x = newOrigin.x;
00728             origin.y = newOrigin.y;
00729 
00730 #if PLATFORM(DOM)
00731             if (![self _sharesChromeWithPlatformWindow])
00732             {
00733                 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y);
00734             }
00735 #endif
00736 
00737             [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMoveNotification object:self];
00738         }
00739 
00740         var size = _frame.size,
00741             newSize = aFrame.size;
00742 
00743         if (!_CGSizeEqualToSize(size, newSize))
00744         {
00745             size.width = newSize.width;
00746             size.height = newSize.height;
00747 
00748             [_windowView setFrameSize:size];
00749 
00750             if (_hasShadow)
00751                 [_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + size.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + size.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)];
00752 
00753             if (!_isAnimating)
00754                 [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidResizeNotification object:self];
00755         }
00756 
00757         if ([self _sharesChromeWithPlatformWindow])
00758             [_platformWindow setContentRect:_frame];
00759     }
00760 }
00761 
00767 - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay
00768 {
00769     [self _setClippedFrame:aFrame display:shouldDisplay animate:NO];
00770 }
00771 
00776 - (void)setFrame:(CGRect)aFrame
00777 {
00778     [self _setClippedFrame:aFrame display:YES animate:NO];
00779 }
00780 
00785 - (void)setFrameOrigin:(CGPoint)anOrigin
00786 {
00787     [self _setClippedFrame:_CGRectMake(anOrigin.x, anOrigin.y, _CGRectGetWidth(_frame), _CGRectGetHeight(_frame)) display:YES animate:NO];
00788 }
00789 
00794 - (void)setFrameSize:(CGSize)aSize
00795 {
00796     [self _setClippedFrame:_CGRectMake(_CGRectGetMinX(_frame), _CGRectGetMinY(_frame), aSize.width, aSize.height) display:YES animate:NO];
00797 }
00798 
00803 - (void)orderFront:(id)aSender
00804 {
00805 #if PLATFORM(DOM)
00806     [_platformWindow orderFront:self];
00807     [_platformWindow order:CPWindowAbove window:self relativeTo:nil];
00808 #endif
00809 
00810     if (_firstResponder === self || !_firstResponder)
00811         [self makeFirstResponder:[self initialFirstResponder]];
00812 
00813     if (!CPApp._keyWindow)
00814         [self makeKeyWindow];
00815 
00816     if (!CPApp._mainWindow)
00817         [self makeMainWindow];
00818 }
00819 
00820 /*
00821     Makes the receiver the last window in the screen ordering.
00822     @param aSender the object that requested this
00823     @ignore
00824 */
00825 - (void)orderBack:(id)aSender
00826 {
00827     //[_platformWindow order:CPWindowBelow
00828 }
00829 
00834 - (void)orderOut:(id)aSender
00835 {
00836 #if PLATFORM(DOM)
00837     if ([self _sharesChromeWithPlatformWindow])
00838         [_platformWindow orderOut:self];
00839 #endif
00840 
00841     if ([_delegate respondsToSelector:@selector(windowWillClose:)])
00842         [_delegate windowWillClose:self];
00843 
00844 #if PLATFORM(DOM)
00845     [_platformWindow order:CPWindowOut window:self relativeTo:nil];
00846 #endif
00847 
00848     [self _updateMainAndKeyWindows];
00849 }
00850 
00856 - (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
00857 {
00858 #if PLATFORM(DOM)
00859     [_platformWindow order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
00860 #endif
00861 }
00862 
00867 - (void)setLevel:(int)aLevel
00868 {
00869     if (aLevel === _level)
00870         return;
00871 
00872     [_platformWindow moveWindow:self fromLevel:_level toLevel:aLevel];
00873 
00874     _level = aLevel;
00875 
00876     if ([self _sharesChromeWithPlatformWindow])
00877         [_platformWindow setLevel:aLevel];
00878 }
00879 
00883 - (int)level
00884 {
00885     return _level;
00886 }
00887 
00891 - (BOOL)isVisible
00892 {
00893     return _isVisible;
00894 }
00895 
00899 - (BOOL)showsResizeIndicator
00900 {
00901     return _showsResizeIndicator;
00902 }
00903 
00908 - (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
00909 {
00910     shouldShowResizeIndicator = !!shouldShowResizeIndicator;
00911 
00912     if (_showsResizeIndicator === shouldShowResizeIndicator)
00913         return;
00914 
00915     _showsResizeIndicator = shouldShowResizeIndicator;
00916     [_windowView setShowsResizeIndicator:[self showsResizeIndicator]];
00917 }
00918 
00922 - (CGSize)resizeIndicatorOffset
00923 {
00924     return [_windowView resizeIndicatorOffset];
00925 }
00926 
00931 - (void)setResizeIndicatorOffset:(CGSize)anOffset
00932 {
00933     [_windowView setResizeIndicatorOffset:anOffset];
00934 }
00935 
00941 - (void)setContentView:(CPView)aView
00942 {
00943     if (_contentView)
00944         [_contentView removeFromSuperview];
00945 
00946     var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
00947 
00948     // During init the initial first responder is set to the contentView
00949     // if it hasn't changed in the mean time we need to update that reference
00950     // to the new contentView
00951     if ([self initialFirstResponder] === _contentView)
00952         [self setInitialFirstResponder:aView];
00953 
00954     _contentView = aView;
00955     [_contentView setFrame:[self contentRectForFrameRect:bounds]];
00956 
00957     [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00958     [_windowView addSubview:_contentView];
00959 }
00960 
00964 - (CPView)contentView
00965 {
00966     return _contentView;
00967 }
00968 
00973 - (void)setAlphaValue:(float)aValue
00974 {
00975     [_windowView setAlphaValue:aValue];
00976 }
00977 
00981 - (float)alphaValue
00982 {
00983     return [_windowView alphaValue];
00984 }
00985 
00990 - (void)setBackgroundColor:(CPColor)aColor
00991 {
00992     [_windowView setBackgroundColor:aColor];
00993 }
00994 
00998 - (CPColor)backgroundColor
00999 {
01000     return [_windowView backgroundColor];
01001 }
01002 
01008 - (void)setMinSize:(CGSize)aSize
01009 {
01010     if (CGSizeEqualToSize(_minSize, aSize))
01011         return;
01012 
01013     _minSize = CGSizeCreateCopy(aSize);
01014 
01015     var size = CGSizeMakeCopy([self frame].size),
01016         needsFrameChange = NO;
01017 
01018     if (size.width < _minSize.width)
01019     {
01020         size.width = _minSize.width;
01021         needsFrameChange = YES;
01022     }
01023 
01024     if (size.height < _minSize.height)
01025     {
01026         size.height = _minSize.height;
01027         needsFrameChange = YES;
01028     }
01029 
01030     if (needsFrameChange)
01031         [self setFrameSize:size];
01032 }
01033 
01037 - (CGSize)minSize
01038 {
01039     return _minSize;
01040 }
01041 
01048 - (void)setMaxSize:(CGSize)aSize
01049 {
01050     if (CGSizeEqualToSize(_maxSize, aSize))
01051         return;
01052 
01053     _maxSize = CGSizeCreateCopy(aSize);
01054 
01055     var size = CGSizeMakeCopy([self frame].size),
01056         needsFrameChange = NO;
01057 
01058     if (size.width > _maxSize.width)
01059     {
01060         size.width = _maxSize.width;
01061         needsFrameChange = YES;
01062     }
01063 
01064     if (size.height > _maxSize.height)
01065     {
01066         size.height = _maxSize.height;
01067         needsFrameChange = YES;
01068     }
01069 
01070     if (needsFrameChange)
01071         [self setFrameSize:size];
01072 }
01073 
01077 - (CGSize)maxSize
01078 {
01079     return _maxSize;
01080 }
01081 
01085 - (BOOL)hasShadow
01086 {
01087     return _hasShadow;
01088 }
01089 
01090 - (void)_updateShadow
01091 {
01092     if ([self _sharesChromeWithPlatformWindow])
01093     {
01094         if (_shadowView)
01095         {
01096 #if PLATFORM(DOM)
01097             CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement);
01098 #endif
01099             _shadowView = nil;
01100         }
01101 
01102         [_platformWindow setHasShadow:_hasShadow];
01103 
01104         return;
01105     }
01106 
01107     if (_hasShadow && !_shadowView)
01108     {
01109         var bounds = [_windowView bounds];
01110 
01111         _shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
01112             SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)];
01113 
01114         if (!_CPWindowShadowColor)
01115         {
01116             var bundle = [CPBundle bundleForClass:[CPWindow class]];
01117 
01118             _CPWindowShadowColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
01119                 [
01120                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow0.png"] size:CGSizeMake(20.0, 19.0)],
01121                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow1.png"] size:CGSizeMake(1.0, 19.0)],
01122                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow2.png"] size:CGSizeMake(19.0, 19.0)],
01123 
01124                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow3.png"] size:CGSizeMake(20.0, 1.0)],
01125                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow4.png"] size:CGSizeMake(1.0, 1.0)],
01126                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow5.png"] size:CGSizeMake(19.0, 1.0)],
01127 
01128                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow6.png"] size:CGSizeMake(20.0, 18.0)],
01129                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow7.png"] size:CGSizeMake(1.0, 18.0)],
01130                     [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow8.png"] size:CGSizeMake(19.0, 18.0)]
01131                 ]]];
01132         }
01133 
01134         [_shadowView setBackgroundColor:_CPWindowShadowColor];
01135         [_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
01136 
01137 #if PLATFORM(DOM)
01138         CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
01139 #endif
01140     }
01141     else if (!_hasShadow && _shadowView)
01142     {
01143 #if PLATFORM(DOM)
01144         CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement);
01145 #endif
01146         _shadowView = nil;
01147     }
01148 }
01149 
01154 - (void)setHasShadow:(BOOL)shouldHaveShadow
01155 {
01156     if (_hasShadow === shouldHaveShadow)
01157         return;
01158 
01159     _hasShadow = shouldHaveShadow;
01160 
01161     [self _updateShadow];
01162 }
01163 
01175 - (void)setShadowStyle:(unsigned)aStyle
01176 {
01177     _shadowStyle = aStyle;
01178 
01179     [[self platformWindow] setShadowStyle:_shadowStyle];
01180 }
01181 
01186 - (void)setDelegate:(id)aDelegate
01187 {
01188     var defaultCenter = [CPNotificationCenter defaultCenter];
01189 
01190     [defaultCenter removeObserver:_delegate name:CPWindowDidResignKeyNotification object:self];
01191     [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeKeyNotification object:self];
01192     [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeMainNotification object:self];
01193     [defaultCenter removeObserver:_delegate name:CPWindowDidResignMainNotification object:self];
01194     [defaultCenter removeObserver:_delegate name:CPWindowDidMoveNotification object:self];
01195     [defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self];
01196 
01197     _delegate = aDelegate;
01198     _delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)];
01199 
01200     if ([_delegate respondsToSelector:@selector(windowDidResignKey:)])
01201         [defaultCenter
01202             addObserver:_delegate
01203                selector:@selector(windowDidResignKey:)
01204                    name:CPWindowDidResignKeyNotification
01205                  object:self];
01206 
01207     if ([_delegate respondsToSelector:@selector(windowDidBecomeKey:)])
01208         [defaultCenter
01209             addObserver:_delegate
01210                selector:@selector(windowDidBecomeKey:)
01211                    name:CPWindowDidBecomeKeyNotification
01212                  object:self];
01213 
01214     if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
01215         [defaultCenter
01216             addObserver:_delegate
01217                selector:@selector(windowDidBecomeMain:)
01218                    name:CPWindowDidBecomeMainNotification
01219                  object:self];
01220 
01221     if ([_delegate respondsToSelector:@selector(windowDidResignMain:)])
01222         [defaultCenter
01223             addObserver:_delegate
01224                selector:@selector(windowDidResignMain:)
01225                    name:CPWindowDidResignMainNotification
01226                  object:self];
01227 
01228     if ([_delegate respondsToSelector:@selector(windowDidMove:)])
01229         [defaultCenter
01230             addObserver:_delegate
01231                selector:@selector(windowDidMove:)
01232                    name:CPWindowDidMoveNotification
01233                  object:self];
01234 
01235     if ([_delegate respondsToSelector:@selector(windowDidResize:)])
01236         [defaultCenter
01237             addObserver:_delegate
01238                selector:@selector(windowDidResize:)
01239                    name:CPWindowDidResizeNotification
01240                  object:self];
01241 }
01242 
01246 - (id)delegate
01247 {
01248     return _delegate;
01249 }
01250 
01255 - (void)setWindowController:(CPWindowController)aWindowController
01256 {
01257     _windowController = aWindowController;
01258 }
01259 
01263 - (CPWindowController)windowController
01264 {
01265     return _windowController;
01266 }
01267 
01268 - (void)doCommandBySelector:(SEL)aSelector
01269 {
01270     if ([_delegate respondsToSelector:aSelector])
01271         [_delegate performSelector:aSelector];
01272     else
01273         [super doCommandBySelector:aSelector];
01274 }
01275 
01276 - (BOOL)acceptsFirstResponder
01277 {
01278     return NO;
01279 }
01280 
01281 - (CPView)initialFirstResponder
01282 {
01283     return _initialFirstResponder;
01284 }
01285 
01286 - (void)setInitialFirstResponder:(CPView)aView
01287 {
01288     _initialFirstResponder = aView;
01289 }
01290 
01298 - (BOOL)makeFirstResponder:(CPResponder)aResponder
01299 {
01300     if (_firstResponder === aResponder)
01301         return YES;
01302 
01303     if (![_firstResponder resignFirstResponder])
01304         return NO;
01305 
01306     if (!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
01307     {
01308         _firstResponder = self;
01309 
01310         return NO;
01311     }
01312 
01313     _firstResponder = aResponder;
01314 
01315     return YES;
01316 }
01317 
01321 - (CPResponder)firstResponder
01322 {
01323     return _firstResponder;
01324 }
01325 
01326 - (BOOL)acceptsMouseMovedEvents
01327 {
01328     return _acceptsMouseMovedEvents;
01329 }
01330 
01331 - (void)setAcceptsMouseMovedEvents:(BOOL)shouldAcceptMouseMovedEvents
01332 {
01333     _acceptsMouseMovedEvents = shouldAcceptMouseMovedEvents;
01334 }
01335 
01336 - (BOOL)ignoresMouseEvents
01337 {
01338     return _ignoresMouseEvents;
01339 }
01340 
01341 - (void)setIgnoresMouseEvents:(BOOL)shouldIgnoreMouseEvents
01342 {
01343     _ignoresMouseEvents = shouldIgnoreMouseEvents;
01344 }
01345 
01346 // Managing Titles
01347 
01351 - (CPString)title
01352 {
01353     return _title;
01354 }
01355 
01359 - (void)setTitle:(CPString)aTitle
01360 {
01361     _title = aTitle;
01362 
01363     [_windowView setTitle:aTitle];
01364     [_platformWindow _setTitle:_title window:self];
01365 
01366     [self _synchronizeMenuBarTitleWithWindowTitle];
01367 }
01368 
01372 - (void)setTitleWithRepresentedFilename:(CPString)aFilePath
01373 {
01374     [self setRepresentedFilename:aFilePath];
01375     [self setTitle:[aFilePath lastPathComponent]];
01376 }
01377 
01381 - (void)setRepresentedFilename:(CPString)aFilePath
01382 {
01383     // FIXME: urls vs filepaths and all.
01384     [self setRepresentedURL:aFilePath];
01385 }
01386 
01390 - (CPString)representedFilename
01391 {
01392     return _representedURL;
01393 }
01394 
01398 - (void)setRepresentedURL:(CPURL)aURL
01399 {
01400     _representedURL = aURL;
01401 }
01402 
01406 - (CPURL)representedURL
01407 {
01408     return _representedURL;
01409 }
01410 
01411 - (CPScreen)screen
01412 {
01413     return [[CPScreen alloc] init];
01414 }
01415 
01416 // Moving
01417 
01422 - (void)setMovableByWindowBackground:(BOOL)shouldBeMovableByWindowBackground
01423 {
01424     _isMovableByWindowBackground = shouldBeMovableByWindowBackground;
01425 }
01426 
01430 - (BOOL)isMovableByWindowBackground
01431 {
01432     return _isMovableByWindowBackground;
01433 }
01434 
01439 - (void)setMovable:(BOOL)shouldBeMovable
01440 {
01441     _isMovable = shouldBeMovable;
01442 }
01443 
01447 - (void)isMovable
01448 {
01449     return _isMovable;
01450 }
01451 
01455 - (void)center
01456 {
01457     if (_isFullPlatformWindow)
01458         return;
01459 
01460     var size = [self frame].size,
01461         containerSize = [CPPlatform isBrowser] ? [_platformWindow contentBounds].size : [[self screen] visibleFrame].size;
01462 
01463     var origin = CGPointMake((containerSize.width - size.width) / 2.0, (containerSize.height - size.height) / 2.0);
01464 
01465     if (origin.x < 0.0)
01466         origin.x = 0.0;
01467 
01468     if (origin.y < 0.0)
01469         origin.y = 0.0;
01470 
01471     [self setFrameOrigin:origin];
01472 }
01473 
01478 - (void)sendEvent:(CPEvent)anEvent
01479 {
01480     var type = [anEvent type],
01481         point = [anEvent locationInWindow];
01482 
01483     switch (type)
01484     {
01485         case CPFlagsChanged:        return [[self firstResponder] flagsChanged:anEvent];
01486 
01487         case CPKeyUp:               return [[self firstResponder] keyUp:anEvent];
01488 
01489         case CPKeyDown:             if ([anEvent charactersIgnoringModifiers] === CPTabCharacter)
01490                                     {
01491                                         if ([anEvent modifierFlags] & CPShiftKeyMask)
01492                                             [self selectPreviousKeyView:self];
01493                                         else
01494                                             [self selectNextKeyView:self];
01495 
01496                                         return;
01497                                     }
01498                                     else if ([anEvent charactersIgnoringModifiers] === CPBackTabCharacter)
01499                                         return [self selectPreviousKeyView:self];
01500 
01501                                     [[self firstResponder] keyDown:anEvent];
01502 
01503                                     // Trigger the default button if needed
01504                                     // FIXME: Is this only applicable in a sheet? See isse: #722.
01505                                     if (![self disableKeyEquivalentForDefaultButton])
01506                                     {
01507                                         var defaultButton = [self defaultButton],
01508                                             keyEquivalent = [defaultButton keyEquivalent],
01509                                             modifierMask = [defaultButton keyEquivalentModifierMask];
01510 
01511                                         if ([anEvent _triggersKeyEquivalent:keyEquivalent withModifierMask:modifierMask])
01512                                             [[self defaultButton] performClick:self];
01513                                     }
01514 
01515                                     return;
01516 
01517         case CPScrollWheel:         return [[_windowView hitTest:point] scrollWheel:anEvent];
01518 
01519         case CPLeftMouseUp:
01520         case CPRightMouseUp:        var hitTestedView = _leftMouseDownView,
01521                                         selector = type == CPRightMouseUp ? @selector(rightMouseUp:) : @selector(mouseUp:);
01522 
01523                                     if (!hitTestedView)
01524                                         hitTestedView = [_windowView hitTest:point];
01525 
01526                                     [hitTestedView performSelector:selector withObject:anEvent];
01527 
01528                                     _leftMouseDownView = nil;
01529 
01530                                     return;
01531         case CPLeftMouseDown:
01532         case CPRightMouseDown:      _leftMouseDownView = [_windowView hitTest:point];
01533 
01534                                     if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder])
01535                                         [self makeFirstResponder:_leftMouseDownView];
01536 
01537                                     [CPApp activateIgnoringOtherApps:YES];
01538 
01539                                     var theWindow = [anEvent window],
01540                                         selector = type == CPRightMouseDown ? @selector(rightMouseDown:) : @selector(mouseDown:);
01541 
01542                                     if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded] && ![_leftMouseDownView needsPanelToBecomeKey])
01543                                         return [_leftMouseDownView performSelector:selector withObject:anEvent];
01544                                     else
01545                                     {
01546                                         // FIXME: delayed ordering?
01547                                         [self makeKeyAndOrderFront:self];
01548 
01549                                         if ([_leftMouseDownView acceptsFirstMouse:anEvent])
01550                                             return [_leftMouseDownView performSelector:selector withObject:anEvent];
01551                                     }
01552                                     break;
01553 
01554         case CPLeftMouseDragged:
01555         case CPRightMouseDragged:   if (!_leftMouseDownView)
01556                                         return [[_windowView hitTest:point] mouseDragged:anEvent];
01557 
01558                                     var selector;
01559                                     if (type == CPRightMouseDragged)
01560                                     {
01561                                         selector = @selector(rightMouseDragged:)
01562                                         if (![_leftMouseDownView respondsToSelector:selector])
01563                                             selector = nil;
01564                                     }
01565 
01566                                     if (!selector)
01567                                         selector = @selector(mouseDragged:)
01568 
01569                                     return [_leftMouseDownView performSelector:selector withObject:anEvent];
01570 
01571         case CPMouseMoved:          if (!_acceptsMouseMovedEvents)
01572                                         return;
01573 
01574                                     if (!_mouseEnteredStack)
01575                                         _mouseEnteredStack = [];
01576 
01577                                     var hitTestView = [_windowView hitTest:point];
01578 
01579                                     if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
01580                                         return [hitTestView mouseMoved:anEvent];
01581 
01582                                     var view = hitTestView,
01583                                         mouseEnteredStack = [];
01584 
01585                                     while (view)
01586                                     {
01587                                         mouseEnteredStack.unshift(view);
01588 
01589                                         view = [view superview];
01590                                     }
01591 
01592                                     var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
01593 
01594                                     while (deviation--)
01595                                         if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
01596                                             break;
01597 
01598                                     var index = deviation + 1,
01599                                         count = _mouseEnteredStack.length;
01600 
01601                                     if (index < count)
01602                                     {
01603                                         var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
01604 
01605                                         for (; index < count; ++index)
01606                                             [_mouseEnteredStack[index] mouseExited:event];
01607                                     }
01608 
01609                                     index = deviation + 1;
01610                                     count = mouseEnteredStack.length;
01611 
01612                                     if (index < count)
01613                                     {
01614                                         var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
01615 
01616                                         for (; index < count; ++index)
01617                                             [mouseEnteredStack[index] mouseEntered:event];
01618                                     }
01619 
01620                                     _mouseEnteredStack = mouseEnteredStack;
01621 
01622                                     [hitTestView mouseMoved:anEvent];
01623     }
01624 }
01625 
01629 - (int)windowNumber
01630 {
01631     return _windowNumber;
01632 }
01633 
01638 - (void)becomeKeyWindow
01639 {
01640     CPApp._keyWindow = self;
01641 
01642     if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)])
01643         [_firstResponder becomeKeyWindow];
01644 
01645     [[CPNotificationCenter defaultCenter]
01646         postNotificationName:CPWindowDidBecomeKeyNotification
01647                       object:self];
01648 }
01649 
01654 - (BOOL)canBecomeKeyWindow
01655 {
01656     return YES;
01657 }
01658 
01662 - (BOOL)isKeyWindow
01663 {
01664     return [CPApp keyWindow] == self;
01665 }
01666 
01671 - (void)makeKeyAndOrderFront:(id)aSender
01672 {
01673     [self orderFront:self];
01674 
01675     [self makeKeyWindow];
01676     [self makeMainWindow];
01677 }
01678 
01682 - (void)makeKeyWindow
01683 {
01684     if ([CPApp keyWindow] === self || ![self canBecomeKeyWindow])
01685         return;
01686 
01687     [[CPApp keyWindow] resignKeyWindow];
01688     [self becomeKeyWindow];
01689 }
01690 
01694 - (void)resignKeyWindow
01695 {
01696     if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)])
01697         [_firstResponder resignKeyWindow];
01698 
01699     if (CPApp._keyWindow === self)
01700         CPApp._keyWindow = nil;
01701 
01702     [[CPNotificationCenter defaultCenter]
01703         postNotificationName:CPWindowDidResignKeyNotification
01704                       object:self];
01705 }
01706 
01717 - (void)dragImage:(CPImage)anImage at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
01718 {
01719     [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToGlobal:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
01720 }
01721 
01722 - (void)_noteRegisteredDraggedTypes:(CPSet)pasteboardTypes
01723 {
01724     if (!pasteboardTypes)
01725         return;
01726 
01727     if (!_inclusiveRegisteredDraggedTypes)
01728         _inclusiveRegisteredDraggedTypes = [CPCountedSet set];
01729 
01730     [_inclusiveRegisteredDraggedTypes unionSet:pasteboardTypes];
01731 }
01732 
01733 - (void)_noteUnregisteredDraggedTypes:(CPSet)pasteboardTypes
01734 {
01735     if (!pasteboardTypes)
01736         return;
01737 
01738     [_inclusiveRegisteredDraggedTypes minusSet:pasteboardTypes];
01739 
01740     if ([_inclusiveRegisteredDraggedTypes count] === 0)
01741         _inclusiveRegisteredDraggedTypes = nil;
01742 }
01743 
01754 - (void)dragView:(CPView)aView at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
01755 {
01756     [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToGlobal:viewLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
01757 }
01758 
01763 - (void)registerForDraggedTypes:(CPArray)pasteboardTypes
01764 {
01765     if (!pasteboardTypes)
01766         return;
01767 
01768     [self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
01769     [_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
01770     [self _noteRegisteredDraggedTypes:_registeredDraggedTypes];
01771 
01772     _registeredDraggedTypesArray = nil;
01773 }
01774 
01779 - (CPArray)registeredDraggedTypes
01780 {
01781     if (!_registeredDraggedTypesArray)
01782         _registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
01783 
01784     return _registeredDraggedTypesArray;
01785 }
01786 
01790 - (void)unregisterDraggedTypes
01791 {
01792     [self _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
01793 
01794     _registeredDraggedTypes = [CPSet set];
01795     _registeredDraggedTypesArray = [];
01796 }
01797 
01798 // Accessing Editing Status
01799 
01804 - (void)setDocumentEdited:(BOOL)isDocumentEdited
01805 {
01806     if (_isDocumentEdited == isDocumentEdited)
01807         return;
01808 
01809     _isDocumentEdited = isDocumentEdited;
01810 
01811     [CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
01812 
01813     [_windowView setDocumentEdited:isDocumentEdited];
01814 }
01815 
01819 - (BOOL)isDocumentEdited
01820 {
01821     return _isDocumentEdited;
01822 }
01823 
01824 - (void)setDocumentSaving:(BOOL)isDocumentSaving
01825 {
01826     if (_isDocumentSaving == isDocumentSaving)
01827         return;
01828 
01829     _isDocumentSaving = isDocumentSaving;
01830 
01831     [self _synchronizeSaveMenuWithDocumentSaving];
01832 
01833     [_windowView windowDidChangeDocumentSaving];
01834 }
01835 
01836 - (BOOL)isDocumentSaving
01837 {
01838     return _isDocumentSaving;
01839 }
01840 
01841 /* @ignore */
01842 - (void)_synchronizeSaveMenuWithDocumentSaving
01843 {
01844     if (![self isMainWindow])
01845         return;
01846 
01847     var mainMenu = [CPApp mainMenu],
01848         index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
01849 
01850     if (index == CPNotFound)
01851         return;
01852 
01853     var item = [mainMenu itemAtIndex:index];
01854 
01855     if (_isDocumentSaving)
01856     {
01857         CPWindowSaveImage = [item image];
01858 
01859         [item setTitle:@"Saving..."];
01860         [item setImage:CPWindowSavingImage];
01861         [item setEnabled:NO];
01862     }
01863     else
01864     {
01865         [item setTitle:@"Save"];
01866         [item setImage:CPWindowSaveImage];
01867         [item setEnabled:YES];
01868     }
01869 }
01870 
01871 // Minimizing Windows
01872 
01877 - (void)performMiniaturize:(id)aSender
01878 {
01879     //FIXME show stuff
01880     [self miniaturize:aSender];
01881 }
01882 
01887 - (void)miniaturize:(id)sender
01888 {
01889     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillMiniaturizeNotification object:self];
01890 
01891     [[self platformWindow] miniaturize:sender];
01892 
01893     [self _updateMainAndKeyWindows];
01894 
01895     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMiniaturizeNotification object:self];
01896 
01897     _isMiniaturized = YES;
01898 }
01899 
01903 - (void)deminiaturize:(id)sender
01904 {
01905     [[self platformWindow] deminiaturize:sender];
01906 
01907     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidDeminiaturizeNotification object:self];
01908 
01909     _isMiniaturized = NO;
01910 }
01911 
01915 - (void)isMiniaturized
01916 {
01917     return _isMiniaturized;
01918 }
01919 
01920 // Closing Windows
01921 
01926 - (void)performClose:(id)aSender
01927 {
01928     if (!(_styleMask & CPClosableWindowMask))
01929         return;
01930 
01931     if ([self isFullBridge])
01932     {
01933         var event = [CPApp currentEvent];
01934 
01935         if ([event type] === CPKeyDown && [event characters] === "w" && ([event modifierFlags] & CPPlatformActionKeyMask))
01936         {
01937             [[self platformWindow] _propagateCurrentDOMEvent:YES];
01938             return;
01939         }
01940     }
01941 
01942     // Only send ONE windowShouldClose: message.
01943     if ([_delegate respondsToSelector:@selector(windowShouldClose:)])
01944     {
01945         if (![_delegate windowShouldClose:self])
01946             return;
01947     }
01948 
01949     // Only check self is delegate does NOT implement this.  This also ensures this when delegate == self (returns true).
01950     else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self])
01951         return;
01952 
01953     var documents = [_windowController documents];
01954     if ([documents count])
01955     {
01956         var index = [documents indexOfObject:[_windowController document]];
01957 
01958         [documents[index] shouldCloseWindowController:_windowController
01959                                              delegate:self
01960                                   shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
01961                                           contextInfo:{documents:[documents copy], visited:0, index:index}];
01962     }
01963     else
01964         [self close];
01965 }
01966 
01967 - (void)_windowControllerContainingDocument:(CPDocument)document shouldClose:(BOOL)shouldClose contextInfo:(Object)context
01968 {
01969     if (shouldClose)
01970     {
01971         var windowController = [self windowController],
01972             documents = context.documents,
01973             count = [documents count],
01974             visited = ++context.visited,
01975             index = ++context.index % count;
01976 
01977         [document removeWindowController:windowController];
01978 
01979         if (visited < count)
01980         {
01981             [windowController setDocument:documents[index]];
01982 
01983             [documents[index] shouldCloseWindowController:_windowController
01984                                                  delegate:self
01985                                       shouldCloseSelector:@selector(_windowControllerContainingDocument:shouldClose:contextInfo:)
01986                                               contextInfo:context];
01987         }
01988         else
01989             [self close];
01990     }
01991 }
01992 
01997 - (void)close
01998 {
01999     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
02000 
02001     [self orderOut:nil];
02002 }
02003 
02004 // Managing Main Status
02008 - (BOOL)isMainWindow
02009 {
02010     return [CPApp mainWindow] == self;
02011 }
02012 
02016 - (BOOL)canBecomeMainWindow
02017 {
02018     // FIXME: Also check if we can resize and titlebar.
02019     if ([self isVisible])
02020         return YES;
02021 
02022     return NO;
02023 }
02024 
02028 - (void)makeMainWindow
02029 {
02030     if ([CPApp mainWindow] === self || ![self canBecomeMainWindow])
02031         return;
02032 
02033     [[CPApp mainWindow] resignMainWindow];
02034     [self becomeMainWindow];
02035 }
02036 
02040 - (void)becomeMainWindow
02041 {
02042     CPApp._mainWindow = self;
02043 
02044     [self _synchronizeMenuBarTitleWithWindowTitle];
02045     [self _synchronizeSaveMenuWithDocumentSaving];
02046 
02047     [[CPNotificationCenter defaultCenter]
02048         postNotificationName:CPWindowDidBecomeMainNotification
02049                       object:self];
02050 }
02051 
02055 - (void)resignMainWindow
02056 {
02057     [[CPNotificationCenter defaultCenter]
02058         postNotificationName:CPWindowDidResignMainNotification
02059                       object:self];
02060 
02061     if (CPApp._mainWindow === self)
02062         CPApp._mainWindow = nil;
02063 }
02064 
02065 - (void)_updateMainAndKeyWindows
02066 {
02067     var allWindows = [CPApp orderedWindows],
02068         windowCount = [allWindows count];
02069 
02070     if ([self isKeyWindow])
02071     {
02072         var keyWindow = [CPApp keyWindow];
02073         [self resignKeyWindow];
02074 
02075         if (keyWindow && keyWindow !== self && [keyWindow canBecomeKeyWindow])
02076             [keyWindow makeKeyWindow];
02077         else
02078         {
02079             var mainMenu = [CPApp mainMenu],
02080                 menuBarClass = objj_getClass("_CPMenuBarWindow"),
02081                 menuWindow;
02082 
02083             for (var i = 0; i < windowCount; i++)
02084             {
02085                 var currentWindow = allWindows[i];
02086 
02087                 if ([currentWindow isKindOfClass:menuBarClass])
02088                     menuWindow = currentWindow;
02089 
02090                 if (currentWindow === self || currentWindow === menuWindow)
02091                     continue;
02092 
02093                 if ([currentWindow isVisible] && [currentWindow canBecomeKeyWindow])
02094                 {
02095                     [currentWindow makeKeyWindow];
02096                     break;
02097                 }
02098             }
02099 
02100             if (![CPApp keyWindow])
02101                 [menuWindow makeKeyWindow];
02102         }
02103     }
02104 
02105     if ([self isMainWindow])
02106     {
02107         var mainWindow = [CPApp mainWindow];
02108         [self resignMainWindow];
02109 
02110         if (mainWindow && mainWindow !== self && [mainWindow canBecomeMainWindow])
02111             [mainWindow makeMainWindow];
02112         else
02113         {
02114             var mainMenu = [CPApp mainMenu],
02115                 menuBarClass = objj_getClass("_CPMenuBarWindow"),
02116                 menuWindow;
02117 
02118             for (var i = 0; i < windowCount; i++)
02119             {
02120                 var currentWindow = allWindows[i];
02121 
02122                 if ([currentWindow isKindOfClass:menuBarClass])
02123                     menuWindow = currentWindow;
02124 
02125                 if (currentWindow === self || currentWindow === menuWindow)
02126                     continue;
02127 
02128                 if ([currentWindow isVisible] && [currentWindow canBecomeMainWindow])
02129                 {
02130                     [currentWindow makeMainWindow];
02131                     break;
02132                 }
02133             }
02134         }
02135     }
02136 }
02137 
02138 // Managing Toolbars
02142 - (CPToolbar)toolbar
02143 {
02144     return _toolbar;
02145 }
02146 
02151 - (void)setToolbar:(CPToolbar)aToolbar
02152 {
02153     if (_toolbar === aToolbar)
02154         return;
02155 
02156     // If this has an owner, dump it!
02157     [[aToolbar _window] setToolbar:nil];
02158 
02159     // This is no longer out toolbar.
02160     [_toolbar _setWindow:nil];
02161 
02162     _toolbar = aToolbar;
02163 
02164     // THIS is our toolbar.
02165     [_toolbar _setWindow:self];
02166 
02167     [self _noteToolbarChanged];
02168 }
02169 
02170 - (void)toggleToolbarShown:(id)aSender
02171 {
02172     var toolbar = [self toolbar];
02173 
02174     [toolbar setVisible:![toolbar isVisible]];
02175 }
02176 
02177 - (void)_noteToolbarChanged
02178 {
02179     var frame = CGRectMakeCopy([self frame]),
02180         newFrame;
02181 
02182     [_windowView noteToolbarChanged];
02183 
02184     if (_isFullPlatformWindow)
02185         newFrame = [_platformWindow visibleFrame];
02186     else
02187     {
02188         newFrame = CGRectMakeCopy([self frame]);
02189 
02190         newFrame.origin = frame.origin;
02191     }
02192 
02193     [self setFrame:newFrame];
02194     /*
02195     [_windowView setAnimatingToolbar:YES];
02196     [self setFrame:frame];
02197     [self setFrame:newFrame display:YES animate:YES];
02198     [_windowView setAnimatingToolbar:NO];
02199     */
02200 }
02201 
02202 - (void)_setFrame:(CGRect)aFrame delegate:(id)delegate duration:(int)duration curve:(CPAnimationCurve)curve
02203 {
02204     [_frameAnimation stopAnimation];
02205     _frameAnimation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
02206     [_frameAnimation setDelegate:delegate];
02207     [_frameAnimation setAnimationCurve:curve];
02208     [_frameAnimation setDuration:duration];
02209     [_frameAnimation startAnimation];
02210 }
02211 
02212 - (CPTimeInterval)animationResizeTime:(CGRect)newWindowFrame
02213 {
02214     return CPWindowResizeTime;
02215 }
02216 
02217 /* @ignore */
02218 - (void)_setAttachedSheetFrameOrigin
02219 {
02220     // Position the sheet above the contentRect.
02221     var attachedSheet = [self attachedSheet];
02222     var contentRect = [[self contentView] frame],
02223         sheetFrame = CGRectMakeCopy([attachedSheet frame]);
02224 
02225     sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
02226     sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
02227 
02228     [attachedSheet setFrame:sheetFrame display:YES animate:NO];
02229 }
02230 
02231 /* @ignore */
02232 - (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
02233 {
02234     var sheetFrame = [aSheet frame];
02235 
02236     _sheetContext = {"sheet":aSheet, "modalDelegate":aModalDelegate, "endSelector":aDidEndSelector, "contextInfo":aContextInfo, "frame":CGRectMakeCopy(sheetFrame), "returnCode":-1, "opened": NO};
02237 
02238     [self _attachSheetWindow:aSheet];
02239 }
02240 
02241 /* @ignore */
02242 - (void)_attachSheetWindow:(CPWindow)aSheet
02243 {
02244     var sheetFrame = [aSheet frame],
02245         frame = [self frame],
02246         sheetContent = [aSheet contentView];
02247 
02248     [self _setUpMasksForView:sheetContent];
02249 
02250     aSheet._isSheet = YES;
02251     aSheet._parentView = self;
02252 
02253     var originx = frame.origin.x + FLOOR((frame.size.width - sheetFrame.size.width) / 2),
02254         originy = frame.origin.y + [[self contentView] frame].origin.y,
02255         startFrame = CGRectMake(originx, originy, sheetFrame.size.width, 0),
02256         endFrame = CGRectMake(originx, originy, sheetFrame.size.width, sheetFrame.size.height);
02257 
02258     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillBeginSheetNotification object:self];
02259     [CPApp runModalForWindow:aSheet];
02260 
02261     [aSheet orderFront:self];
02262     [aSheet setFrame:startFrame display:YES animate:NO];
02263     _sheetContext["opened"] = YES;
02264 
02265     [aSheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseOut];
02266 
02267     // Should run the main loop here until _isAnimating = FALSE
02268     [aSheet becomeKeyWindow];
02269 }
02270 
02271 /* @ignore */
02272 - (void)_detachSheetWindow
02273 {
02274     var sheet = [self attachedSheet],
02275         startFrame = [sheet frame],
02276         endFrame = CGRectMakeCopy(startFrame);
02277 
02278     endFrame.size.height = 0;
02279 
02280     _sheetContext["frame"] = startFrame;
02281 
02282     var sheetContent = [sheet contentView];
02283     [self _setUpMasksForView:sheetContent];
02284 
02285     _sheetContext["opened"] = NO;
02286     [sheet _setFrame:endFrame delegate:self duration:[self animationResizeTime:endFrame] curve:CPAnimationEaseIn];
02287 }
02288 
02289 /* @ignore */
02290 - (void)animationDidEnd:(id)anim
02291 {
02292     var sheet = _sheetContext["sheet"];
02293     if (anim._window != sheet)
02294         return;
02295 
02296     var sheetContent = [sheet contentView];
02297 
02298     if (_sheetContext["opened"] === YES)
02299     {
02300         [self _restoreMasksForView:sheetContent];
02301         return;
02302     }
02303 
02304     [CPApp stopModal];
02305     [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidEndSheetNotification object:self];
02306 
02307     [sheet orderOut:self];
02308 
02309     var lastFrame = _sheetContext["frame"];
02310     [sheet setFrame:lastFrame];
02311 
02312     [self _restoreMasksForView:sheetContent];
02313 
02314     var delegate = _sheetContext["modalDelegate"],
02315         endSelector = _sheetContext["endSelector"],
02316         returnCode = _sheetContext["returnCode"],
02317         contextInfo = _sheetContext["contextInfo"];
02318 
02319     _sheetContext = nil;
02320     sheet._parentView = nil;
02321 
02322     if (delegate != nil && endSelector != nil)
02323         objj_msgSend(delegate, endSelector, sheet, returnCode, contextInfo);
02324 }
02325 
02326 - (void)_setUpMasksForView:(CPView)aView
02327 {
02328     var views = [aView subviews];
02329 
02330     [views addObject:aView];
02331 
02332     for (var i = 0, count = [views count]; i < count; i++)
02333     {
02334         var view = [views objectAtIndex:i],
02335             mask = [view autoresizingMask],
02336             maskToAdd = (mask & CPViewMinYMargin) ? 128 : CPViewMinYMargin;
02337 
02338         [view setAutoresizingMask:(mask | maskToAdd)];
02339     }
02340 }
02341 
02342 - (void)_restoreMasksForView:(CPView)aView
02343 {
02344     var views = [aView subviews];
02345 
02346     [views addObject:aView];
02347 
02348     for (var i = 0, count = [views count]; i < count; i++)
02349     {
02350         var view = [views objectAtIndex:i],
02351             mask = [view autoresizingMask],
02352             maskToRemove = (mask & 128) ? 128 : CPViewMinYMargin;
02353 
02354         [view setAutoresizingMask:(mask & (~ maskToRemove))];
02355     }
02356 }
02357 
02361 - (CPWindow)attachedSheet
02362 {
02363     if (_sheetContext === nil)
02364         return nil;
02365 
02366    return _sheetContext["sheet"];
02367 }
02368 
02372 - (BOOL)isSheet
02373 {
02374     return _isSheet;
02375 }
02376 
02377 //
02378 /*
02379     Used privately.
02380     @ignore
02381 */
02382 - (BOOL)becomesKeyOnlyIfNeeded
02383 {
02384     return NO;
02385 }
02386 
02391 - (BOOL)worksWhenModal
02392 {
02393     return NO;
02394 }
02395 
02396 - (BOOL)performKeyEquivalent:(CPEvent)anEvent
02397 {
02398     // FIXME: should we be starting at the root, in other words _windowView?
02399     // The evidence seems to point to no...
02400     return [[self contentView] performKeyEquivalent:anEvent];
02401 }
02402 
02403 - (void)keyDown:(CPEvent)anEvent
02404 {
02405     // It's not clear why we do performKeyEquivalent again here...
02406     // Perhaps to allow something to happen between sendEvent: and keyDown:?
02407     if ([anEvent _couldBeKeyEquivalent] && [self performKeyEquivalent:anEvent])
02408         return;
02409 
02410     // Apple's documentation is inconsistent with their behavior here. According to the docs
02411     // an event going of the responder chain is passed to the input system as a last resort.
02412     // However, the only methods I could get Cocoa to call automatically are
02413     // moveUp: moveDown: moveLeft: moveRight: pageUp: pageDown: and complete:
02414     // Unhandled events just travel further up the responder chain _past_ the window.
02415     if (![self _processKeyboardUIKey:anEvent])
02416         [super keyDown:anEvent];
02417 }
02418 
02419 /*
02420     @ignore
02421     Interprets the key event for action messages and sends the action message down the responder chain
02422     Cocoa only sends moveDown:, moveUp:, moveLeft:, moveRight:, pageUp:, pageDown: and complete: messages.
02423     We deviate from this by sending (the default) scrollPageUp:, scrollPageDown:, scrollToBeginningOfDocument: and scrollToEndOfDocument: for pageUp, pageDown, home and end keys.
02424     @param anEvent the event to handle.
02425     @return YES if the key event was handled, NO if no responder handled the key event
02426 */
02427 - (BOOL)_processKeyboardUIKey:(CPEvent)anEvent
02428 {
02429     var character = [anEvent charactersIgnoringModifiers];
02430 
02431     if (![CPWindowActionMessageKeys containsObject:character])
02432         return NO;
02433 
02434     var selectors = [CPKeyBinding selectorsForKey:character modifierFlags:0];
02435 
02436     if ([selectors count] <= 0)
02437         return NO;
02438 
02439     if (character !== CPEscapeFunctionKey)
02440     {
02441         var selector = [selectors objectAtIndex:0];
02442         return [[self firstResponder] tryToPerform:selector with:self];
02443     }
02444     else
02445     {
02446         // Cocoa sends complete: for the escape key (in stead of the default cancelOperation:)
02447         // This is also the only action that is not sent directly to the first responder, but through doCommandBySelector.
02448         // The difference is that doCommandBySelector: will also send the action to the window and application delegates.
02449         [[self firstResponder] doCommandBySelector:@selector(complete:)];
02450     }
02451 
02452     return NO;
02453 }
02454 
02455 - (void)_dirtyKeyViewLoop
02456 {
02457     if (_autorecalculatesKeyViewLoop)
02458         _keyViewLoopIsDirty = YES;
02459 }
02460 
02461 - (BOOL)_hasKeyViewLoop
02462 {
02463     var views = allViews(self),
02464         index = [views count];
02465 
02466     while (index--)
02467         if ([views[index] nextKeyView])
02468             return YES;
02469 
02470     return NO;
02471 }
02472 
02473 - (void)recalculateKeyViewLoop
02474 {
02475     var views = allViews(self);
02476 
02477     [views sortUsingFunction:keyViewComparator context:nil];
02478 
02479     var index = 0,
02480         count = [views count];
02481 
02482     for (; index < count; ++index)
02483         [views[index] setNextKeyView:views[(index + 1) % count]];
02484 
02485     _keyViewLoopIsDirty = NO;
02486 }
02487 
02488 - (void)setAutorecalculatesKeyViewLoop:(BOOL)shouldRecalculate
02489 {
02490     if (_autorecalculatesKeyViewLoop === shouldRecalculate)
02491         return;
02492 
02493     _autorecalculatesKeyViewLoop = shouldRecalculate;
02494 
02495     if (_keyViewLoopIsDirty)
02496         [self recalculateKeyViewLoop];
02497     else if (_autorecalculatesKeyViewLoop)
02498         [self _dirtyKeyViewLoop];
02499 }
02500 
02501 - (BOOL)autorecalculatesKeyViewLoop
02502 {
02503     return _autorecalculatesKeyViewLoop;
02504 }
02505 
02506 - (void)selectNextKeyView:(id)sender
02507 {
02508     if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
02509         [self recalculateKeyViewLoop];
02510 
02511     var nextValidKeyView = nil;
02512 
02513     if ([_firstResponder isKindOfClass:[CPView class]])
02514         nextValidKeyView = [_firstResponder nextValidKeyView];
02515 
02516     if (!nextValidKeyView)
02517     {
02518         var initialFirstResponder = [self initialFirstResponder];
02519 
02520         if ([initialFirstResponder acceptsFirstResponder])
02521             nextValidKeyView = initialFirstResponder;
02522         else
02523             nextValidKeyView = [initialFirstResponder nextValidKeyView];
02524     }
02525 
02526     [self makeFirstResponder:nextValidKeyView];
02527 }
02528 
02529 - (void)selectPreviousKeyView:(id)sender
02530 {
02531     if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
02532         [self recalculateKeyViewLoop];
02533 
02534     var previousValidKeyView = nil;
02535 
02536     if ([_firstResponder isKindOfClass:[CPView class]])
02537         previousValidKeyView = [_firstResponder previousValidKeyView];
02538 
02539     if (!previousValidKeyView)
02540     {
02541         var initialFirstResponder = [self initialFirstResponder];
02542 
02543         if ([initialFirstResponder acceptsFirstResponder])
02544             previousValidKeyView = initialFirstResponder;
02545         else
02546             previousValidKeyView = [initialFirstResponder previousValidKeyView];
02547     }
02548 
02549     [self makeFirstResponder:previousValidKeyView];
02550 }
02551 
02552 - (void)selectKeyViewFollowingView:(CPView)aView
02553 {
02554     if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
02555         [self recalculateKeyViewLoop];
02556 
02557     var nextValidKeyView = [aView nextValidKeyView];
02558 
02559     if ([nextValidKeyView isKindOfClass:[CPView class]])
02560         [self makeFirstResponder:nextValidKeyView];
02561 }
02562 
02563 - (void)selectKeyViewPrecedingView:(CPView)aView
02564 {
02565     if (_keyViewLoopIsDirty && [self autorecalculatesKeyViewLoop])
02566         [self recalculateKeyViewLoop];
02567 
02568     var previousValidKeyView = [aView previousValidKeyView];
02569 
02570     if ([previousValidKeyView isKindOfClass:[CPView class]])
02571         [self makeFirstResponder:previousValidKeyView];
02572 }
02573 
02579 - (void)setDefaultButtonCell:(CPButton)aButton
02580 {
02581     [self setDefaultButton:aButton];
02582 }
02583 
02588 - (CPButton)defaultButtonCell
02589 {
02590     return [self defaultButton];
02591 }
02592 
02599 - (void)setDefaultButton:(CPButton)aButton
02600 {
02601     if (_defaultButton === aButton)
02602         return;
02603 
02604     if ([_defaultButton keyEquivalent] === CPCarriageReturnCharacter)
02605         [_defaultButton setKeyEquivalent:nil];
02606 
02607     _defaultButton = aButton;
02608 
02609     if ([_defaultButton keyEquivalent] !== CPCarriageReturnCharacter)
02610         [_defaultButton setKeyEquivalent:CPCarriageReturnCharacter];
02611 }
02612 
02616 - (CPButton)defaultButton
02617 {
02618     return _defaultButton;
02619 }
02620 
02624 - (void)enableKeyEquivalentForDefaultButton
02625 {
02626     _defaultButtonEnabled = YES;
02627 }
02628 
02633 - (void)enableKeyEquivalentForDefaultButtonCell
02634 {
02635     [self enableKeyEquivalentForDefaultButton];
02636 }
02637 
02641 - (void)disableKeyEquivalentForDefaultButton
02642 {
02643     _defaultButtonEnabled = NO;
02644 }
02645 
02650 - (void)disableKeyEquivalentForDefaultButtonCell
02651 {
02652     [self disableKeyEquivalentForDefaultButton];
02653 }
02654 
02655 @end
02656 
02657 var allViews = function(aWindow)
02658 {
02659     var views = [CPArray arrayWithObject:[aWindow contentView]];
02660 
02661     [views addObjectsFromArray:[[aWindow contentView] subviews]];
02662 
02663     var index = 0;
02664     for (; index < views.length; ++index)
02665         views = views.concat([views[index] subviews]);
02666 
02667     return views;
02668 }
02669 
02670 var keyViewComparator = function(lhs, rhs, context)
02671 {
02672     var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil],
02673         rhsBounds = [rhs convertRect:[rhs bounds] toView:nil],
02674         lhsY = _CGRectGetMinY(lhsBounds),
02675         rhsY = _CGRectGetMinY(rhsBounds),
02676         lhsX = _CGRectGetMinX(lhsBounds),
02677         rhsX = _CGRectGetMinX(rhsBounds),
02678         intersectsVertically = MIN(_CGRectGetMaxY(lhsBounds), _CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY);
02679 
02680     // If two views are "on the same line" (intersect vertically), then rely on the x comparison.
02681     if (intersectsVertically > 0)
02682     {
02683         if (lhsX < rhsX)
02684             return CPOrderedAscending;
02685 
02686         if (lhsX === rhsX)
02687             return CPOrderedSame;
02688 
02689         return CPOrderedDescending;
02690     }
02691 
02692     if (lhsY < rhsY)
02693         return CPOrderedAscending;
02694 
02695     if (lhsY === rhsY)
02696         return CPOrderedSame;
02697 
02698     return CPOrderedDescending;
02699 }
02700 
02701 @implementation CPWindow (MenuBar)
02702 
02703 - (void)_synchronizeMenuBarTitleWithWindowTitle
02704 {
02705     // Windows with Documents automatically update the native window title and the menu bar title.
02706     if (![_windowController document] || ![self isMainWindow])
02707         return;
02708 
02709     [CPMenu setMenuBarTitle:_title];
02710 }
02711 
02712 @end
02713 
02714 @implementation CPWindow (BridgeSupport)
02715 
02716 /*
02717     @ignore
02718 */
02719 - (void)resizeWithOldPlatformWindowSize:(CGSize)aSize
02720 {
02721     if ([self isFullPlatformWindow])
02722         return [self setFrame:[_platformWindow visibleFrame]];
02723 
02724     if (_autoresizingMask == CPWindowNotSizable)
02725         return;
02726 
02727     var frame = [_platformWindow contentBounds],
02728         newFrame = CGRectMakeCopy(_frame),
02729         dX = (CGRectGetWidth(frame) - aSize.width) /
02730             (((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)),
02731         dY = (CGRectGetHeight(frame) - aSize.height) /
02732             ((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0));
02733 
02734     if (_autoresizingMask & CPWindowMinXMargin)
02735         newFrame.origin.x += dX;
02736     if (_autoresizingMask & CPWindowWidthSizable)
02737         newFrame.size.width += dX;
02738 
02739     if (_autoresizingMask & CPWindowMinYMargin)
02740         newFrame.origin.y += dY;
02741     if (_autoresizingMask & CPWindowHeightSizable)
02742         newFrame.size.height += dY;
02743 
02744     [self setFrame:newFrame];
02745 }
02746 
02747 /*
02748     @ignore
02749 */
02750 - (void)setAutoresizingMask:(unsigned)anAutoresizingMask
02751 {
02752     _autoresizingMask = anAutoresizingMask;
02753 }
02754 
02755 /*
02756     @ignore
02757 */
02758 - (unsigned)autoresizingMask
02759 {
02760     return _autoresizingMask;
02761 }
02762 
02766 - (CGPoint)convertBaseToGlobal:(CGPoint)aPoint
02767 {
02768     return [CPPlatform isBrowser] ? [self convertBaseToPlatformWindow:aPoint] : [self convertBaseToScreen:aPoint];
02769 }
02770 
02774 - (CGPoint)convertGlobalToBase:(CGPoint)aPoint
02775 {
02776     return [CPPlatform isBrowser] ? [self convertPlatformWindowToBase:aPoint] : [self convertScreenToBase:aPoint];
02777 }
02778 
02782 - (CGPoint)convertBaseToPlatformWindow:(CGPoint)aPoint
02783 {
02784     if ([self _sharesChromeWithPlatformWindow])
02785         return aPoint;
02786 
02787     var origin = [self frame].origin;
02788 
02789     return _CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
02790 }
02791 
02795 - (CGPoint)convertPlatformWindowToBase:(CGPoint)aPoint
02796 {
02797     if ([self _sharesChromeWithPlatformWindow])
02798         return aPoint;
02799 
02800     var origin = [self frame].origin;
02801 
02802     return _CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y);
02803 }
02804 
02805 - (CGPoint)convertScreenToBase:(CGPoint)aPoint
02806 {
02807     return [self convertPlatformWindowToBase:[_platformWindow convertScreenToBase:aPoint]];
02808 }
02809 
02810 - (CGPoint)convertBaseToScreen:(CGPoint)aPoint
02811 {
02812     return [_platformWindow convertBaseToScreen:[self convertBaseToPlatformWindow:aPoint]];
02813 }
02814 
02815 - (void)_setSharesChromeWithPlatformWindow:(BOOL)shouldShareFrameWithPlatformWindow
02816 {
02817     // We canna' do it captain! We just don't have the power!
02818     if (shouldShareFrameWithPlatformWindow && [CPPlatform isBrowser])
02819         return;
02820 
02821     _sharesChromeWithPlatformWindow = shouldShareFrameWithPlatformWindow;
02822 
02823     [self _updateShadow];
02824 }
02825 
02826 - (BOOL)_sharesChromeWithPlatformWindow
02827 {
02828     return _sharesChromeWithPlatformWindow;
02829 }
02830 
02831 // Undo and Redo Support
02835 - (CPUndoManager)undoManager
02836 {
02837     // If we've ever created an undo manager, return it.
02838     if (_undoManager)
02839         return _undoManager;
02840 
02841     // If not, check to see if the document has one.
02842     var documentUndoManager = [[_windowController document] undoManager];
02843 
02844     if (documentUndoManager)
02845         return documentUndoManager;
02846 
02847     // If not, check to see if the delegate has one.
02848     if (_delegateRespondsToWindowWillReturnUndoManagerSelector)
02849         return [_delegate windowWillReturnUndoManager:self];
02850 
02851     // If not, create one.
02852     if (!_undoManager)
02853         _undoManager = [[CPUndoManager alloc] init];
02854 
02855     return _undoManager;
02856 }
02857 
02862 - (void)undo:(id)aSender
02863 {
02864     [[self undoManager] undo];
02865 }
02866 
02871 - (void)redo:(id)aSender
02872 {
02873     [[self undoManager] redo];
02874 }
02875 
02876 - (BOOL)containsPoint:(CGPoint)aPoint
02877 {
02878     return CGRectContainsPoint(_frame, aPoint);
02879 }
02880 
02881 @end
02882 
02883 @implementation CPWindow (Deprecated)
02888 - (void)setFullBridge:(BOOL)shouldBeFullBridge
02889 {
02890     [self setFullPlatformWindow:shouldBeFullBridge];
02891 }
02892 
02897 - (BOOL)isFullBridge
02898 {
02899     return [self isFullPlatformWindow];
02900 }
02901 
02902 /*
02903     @ignore
02904 */
02905 - (CGPoint)convertBaseToBridge:(CGPoint)aPoint
02906 {
02907     return [self convertBaseToPlatformWindow:aPoint];
02908 }
02909 
02910 /*
02911     @ignore
02912 */
02913 - (CGPoint)convertBridgeToBase:(CGPoint)aPoint
02914 {
02915     return [self convertPlatformWindowToBase:aPoint];
02916 }
02917 
02918 @end
02919 
02920 var interpolate = function(fromValue, toValue, progress)
02921 {
02922     return fromValue + (toValue - fromValue) * progress;
02923 }
02924 
02925 /* @ignore */
02926 @implementation _CPWindowFrameAnimation : CPAnimation
02927 {
02928     CPWindow    _window;
02929 
02930     CGRect      _startFrame;
02931     CGRect      _targetFrame;
02932 }
02933 
02934 - (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
02935 {
02936     self = [super initWithDuration:[aWindow animationResizeTime:aTargetFrame] animationCurve:CPAnimationLinear];
02937 
02938     if (self)
02939     {
02940         _window = aWindow;
02941 
02942         _targetFrame = CGRectMakeCopy(aTargetFrame);
02943         _startFrame = CGRectMakeCopy([_window frame]);
02944     }
02945 
02946     return self;
02947 }
02948 
02949 - (void)startAnimation
02950 {
02951     [super startAnimation];
02952 
02953     _window._isAnimating = YES;
02954 }
02955 
02956 - (void)setCurrentProgress:(float)aProgress
02957 {
02958     [super setCurrentProgress:aProgress];
02959 
02960     var value = [self currentValue];
02961 
02962     if (value == 1.0)
02963         _window._isAnimating = NO;
02964 
02965     var newFrame = CGRectMake(interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value),
02966                               interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value),
02967                               interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value),
02968                               interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value));
02969 
02970     [_window setFrame:newFrame display:YES animate:NO];
02971 }
02972 
02973 @end
02974 
02975 function _CPWindowFullPlatformWindowSessionMake(aWindowView, aContentRect, hasShadow, aLevel)
02976 {
02977     return { windowView:aWindowView, contentRect:aContentRect, hasShadow:hasShadow, level:aLevel };
02978 }
02979 
02980 CPStandardWindowShadowStyle = 0;
02981 CPMenuWindowShadowStyle     = 1;
02982 CPPanelWindowShadowStyle    = 2;
02983 CPCustomWindowShadowStyle   = 3;
02984 
02985 
 All Classes Files Functions Variables Defines