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/CPNotificationCenter.j>
00024 @import <Foundation/CPUndoManager.j>
00025
00026 @import "CGGeometry.j"
00027 @import "CPAnimation.j"
00028 @import "CPResponder.j"
00029
00030 #include "Platform/Platform.h"
00031 #include "Platform/DOM/CPDOMDisplayServer.h"
00032
00033 #include "CoreGraphics/CGGeometry.h"
00034
00035
00036
00037
00038
00039
00040
00041 CPBorderlessWindowMask = 0;
00042
00043
00044
00045
00046
00047 CPTitledWindowMask = 1 << 0;
00048
00049
00050
00051
00052
00053 CPClosableWindowMask = 1 << 1;
00054
00055
00056
00057
00058
00059 CPMiniaturizableWindowMask = 1 << 2;
00060
00061
00062
00063
00064
00065 CPResizableWindowMask = 1 << 3;
00066
00067
00068
00069
00070
00071 CPTexturedBackgroundWindowMask = 1 << 8;
00072
00073
00074
00075
00076 CPBorderlessBridgeWindowMask = 1 << 20;
00077
00078
00079
00080
00081 CPHUDBackgroundWindowMask = 1 << 21;
00082
00083 CPWindowNotSizable = 0;
00084 CPWindowMinXMargin = 1;
00085 CPWindowWidthSizable = 2;
00086 CPWindowMaxXMargin = 4;
00087 CPWindowMinYMargin = 8;
00088 CPWindowHeightSizable = 16;
00089 CPWindowMaxYMargin = 32;
00090
00091
00092
00093
00094
00095
00096 CPNormalWindowLevel = 4;
00097
00098
00099
00100
00101
00102 CPFloatingWindowLevel = 5;
00103
00104
00105
00106
00107
00108 CPSubmenuWindowLevel = 6;
00109
00110
00111
00112
00113
00114 CPTornOffMenuWindowLevel = 6;
00115
00116
00117
00118
00119
00120 CPMainMenuWindowLevel = 8;
00121
00122
00123
00124
00125
00126 CPStatusWindowLevel = 9;
00127
00128
00129
00130
00131
00132 CPModalPanelWindowLevel = 10;
00133
00134
00135
00136
00137
00138 CPPopUpMenuWindowLevel = 11;
00139
00140
00141
00142
00143
00144 CPDraggingWindowLevel = 12;
00145
00146
00147
00148
00149
00150 CPScreenSaverWindowLevel = 13;
00151
00152
00153
00154
00155
00156
00157 CPWindowOut = 0;
00158
00159
00160
00161
00162
00163 CPWindowAbove = 1;
00164
00165
00166
00167
00168
00169 CPWindowBelow = 2;
00170
00171 CPWindowWillCloseNotification = @"CPWindowWillCloseNotification";
00172 CPWindowDidBecomeMainNotification = @"CPWindowDidBecomeMainNotification";
00173 CPWindowDidResignMainNotification = @"CPWindowDidResignMainNotification";
00174
00175
00176 var SHADOW_MARGIN_LEFT = 20.0,
00177 SHADOW_MARGIN_RIGHT = 19.0,
00178 SHADOW_MARGIN_TOP = 10.0,
00179 SHADOW_MARGIN_BOTTOM = 10.0,
00180 SHADOW_DISTANCE = 5.0,
00181
00182 _CPWindowShadowColor = nil;
00183
00184 var CPWindowSaveImage = nil,
00185 CPWindowSavingImage = nil;
00186
00231 @implementation CPWindow : CPResponder
00232 {
00233 int _windowNumber;
00234 unsigned _styleMask;
00235 CGRect _frame;
00236 int _level;
00237 BOOL _isVisible;
00238 BOOL _isAnimating;
00239 BOOL _hasShadow;
00240 BOOL _isMovableByWindowBackground;
00241
00242 BOOL _isDocumentEdited;
00243 BOOL _isDocumentSaving;
00244
00245 CPNinePartImageView _shadowView;
00246
00247 CPView _windowView;
00248 CPView _contentView;
00249 CPView _toolbarView;
00250
00251 CPView _mouseOverView;
00252 CPView _leftMouseDownView;
00253 CPView _rightMouseDownView;
00254
00255 CPToolbar _toolbar;
00256 CPResponder _firstResponder;
00257 id _delegate;
00258
00259 CPString _title;
00260
00261 BOOL _acceptsMouseMovedEvents;
00262
00263 CPWindowController _windowController;
00264
00265 CGSize _minSize;
00266 CGSize _maxSize;
00267
00268 CGRect _resizeFrame;
00269 CGPoint _mouseDraggedPoint;
00270
00271 CPUndoManager _undoManager;
00272 CPURL _representedURL;
00273
00274
00275 #if PLATFORM(DOM)
00276 DOMElement _DOMElement;
00277 #endif
00278 CPDOMWindowBridge _bridge;
00279 unsigned _autoresizingMask;
00280
00281 BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
00282 }
00283
00284
00285
00286
00287
00288 + (void)initialize
00289 {
00290 if (self != [CPWindow class])
00291 return;
00292
00293 var bundle = [CPBundle bundleForClass:[CPWindow class]];
00294
00295 CPWindowResizeIndicatorImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindowResizeIndicator.png"] size:CGSizeMake(12.0, 12.0)];
00296
00297 CPWindowSavingImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPProgressIndicator/CPProgressIndicatorSpinningStyleRegular.gif"] size:CGSizeMake(16.0, 16.0)]
00298 }
00299
00315 - (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask
00316 {
00317 return [self initWithContentRect:aContentRect styleMask:aStyleMask bridge:[CPDOMWindowBridge sharedDOMWindowBridge]];
00318 }
00319
00337 - (id)initWithContentRect:(CGRect)aContentRect styleMask:(unsigned int)aStyleMask bridge:(CPDOMWindowBridge)aBridge
00338 {
00339 self = [super init];
00340
00341 if (self)
00342 {
00343
00344 _windowNumber = [CPApp._windows count];
00345 CPApp._windows[_windowNumber] = self;
00346
00347 _styleMask = aStyleMask;
00348
00349 _frame = [self frameRectForContentRect:aContentRect];
00350
00351 _level = CPNormalWindowLevel;
00352 _hasShadow = NO;
00353
00354 _minSize = CGSizeMake(0.0, 0.0);
00355 _maxSize = CGSizeMake(1000000.0, 1000000.0);
00356
00357 if (_styleMask & CPBorderlessBridgeWindowMask)
00358 _autoresizingMask = CPWindowWidthSizable | CPWindowHeightSizable;
00359
00360
00361 _windowView = [[_CPWindowView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame)) forStyleMask:_styleMask];
00362
00363 [_windowView _setWindow:self];
00364 [_windowView setNextResponder:self];
00365
00366 [self setMovableByWindowBackground:aStyleMask & CPHUDBackgroundWindowMask];
00367
00368
00369 [self setContentView:[[CPView alloc] initWithFrame:CGRectMakeZero()]];
00370
00371 _firstResponder = self;
00372
00373 #if PLATFORM(DOM)
00374 _DOMElement = document.createElement("div");
00375
00376 _DOMElement.style.position = "absolute";
00377 _DOMElement.style.visibility = "visible";
00378 _DOMElement.style.zIndex = 0;
00379
00380 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(_frame), _CGRectGetMinY(_frame));
00381 CPDOMDisplayServerSetStyleSize(_DOMElement, 1, 1);
00382
00383 CPDOMDisplayServerAppendChild(_DOMElement, _windowView._DOMElement);
00384 #endif
00385
00386 [self setBridge:aBridge];
00387
00388 [self setNextResponder:CPApp];
00389 }
00390
00391 return self;
00392 }
00393
00397 - (unsigned)styleMask
00398 {
00399 return _styleMask;
00400 }
00401
00408 + (CGRect)frameRectForContentRect:(CGRect)aContentRect styleMask:(unsigned)aStyleMask
00409 {
00410 var frame = CGRectMakeCopy(aContentRect);
00411
00412 return frame;
00413 }
00414
00419 - (CGRect)contentRectForFrameRect:(CGRect)aFrame
00420 {
00421
00422 var contentRect = CGRectMakeCopy([_windowView bounds]);
00423
00424 if (_styleMask & CPHUDBackgroundWindowMask)
00425 {
00426 contentRect.origin.x += 7.0;
00427 contentRect.origin.y += 30.0;
00428 contentRect.size.width -= 14.0;
00429 contentRect.size.height -= 40.0;
00430 }
00431
00432 else if (_styleMask & CPBorderlessBridgeWindowMask)
00433 {
00434
00435 }
00436
00437 if ([_toolbar isVisible])
00438 {
00439 var toolbarHeight = CGRectGetHeight([_toolbarView frame]);
00440
00441 contentRect.origin.y += toolbarHeight;
00442 contentRect.size.height -= toolbarHeight;
00443 }
00444
00445 return contentRect;
00446 }
00447
00453 - (CGRect)frameRectForContentRect:(CGRect)aContentRect
00454 {
00455 if (_styleMask & CPBorderlessBridgeWindowMask)
00456 return _bridge ? [_bridge visibleFrame] : CGRectMakeZero();
00457
00458 var frame = [[self class] frameRectForContentRect:aContentRect styleMask:_styleMask];
00459
00460 return frame;
00461 }
00462
00466 - (CGRect)frame
00467 {
00468 return _frame;
00469 }
00470
00478 - (void)setFrame:(CGRect)aFrame display:(BOOL)shouldDisplay animate:(BOOL)shouldAnimate
00479 {
00480 if (shouldAnimate)
00481 {
00482 var animation = [[_CPWindowFrameAnimation alloc] initWithWindow:self targetFrame:aFrame];
00483
00484 [animation startAnimation];
00485 }
00486 else
00487 {
00488 [self setFrameOrigin:aFrame.origin];
00489 [self setFrameSize:aFrame.size];
00490 }
00491 }
00492
00496 - (void)setFrame:(CGRect)aFrame
00497 {
00498 [self setFrame:aFrame display:YES animate:NO];
00499 }
00500
00505 - (void)setFrameOrigin:(CGPoint)anOrigin
00506 {
00507 var origin = _frame.origin;
00508
00509 if (_CGPointEqualToPoint(origin, anOrigin))
00510 return;
00511
00512 origin.x = anOrigin.x;
00513 origin.y = anOrigin.y;
00514
00515 #if PLATFORM(DOM)
00516 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, origin.x, origin.y);
00517 #endif
00518 }
00519
00524 - (void)setFrameSize:(CGSize)aSize
00525 {
00526 aSize = _CGSizeMake(MIN(MAX(aSize.width, _minSize.width), _maxSize.width), MIN(MAX(aSize.height, _minSize.height), _maxSize.height));
00527
00528 if (_CGSizeEqualToSize(_frame.size, aSize))
00529 return;
00530
00531 _frame.size = aSize;
00532
00533 [_windowView setFrameSize:aSize];
00534
00535 if (_hasShadow)
00536 [_shadowView setFrameSize:_CGSizeMake(SHADOW_MARGIN_LEFT + aSize.width + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_BOTTOM + aSize.height + SHADOW_MARGIN_TOP + SHADOW_DISTANCE)];
00537
00538 if (!_isAnimating && [_delegate respondsToSelector:@selector(windowDidResize:)])
00539 [_delegate windowDidResize:self];
00540 }
00541
00542
00543
00544
00545 - (void)trackMoveWithEvent:(CPEvent)anEvent
00546 {
00547 var type = [anEvent type];
00548
00549 if (type == CPLeftMouseUp)
00550 return;
00551
00552 else if (type == CPLeftMouseDown)
00553 _mouseDraggedPoint = [self convertBaseToBridge:[anEvent locationInWindow]];
00554
00555 else if (type == CPLeftMouseDragged)
00556 {
00557 var location = [self convertBaseToBridge:[anEvent locationInWindow]];
00558
00559 [self setFrameOrigin:CGPointMake(_CGRectGetMinX(_frame) + (location.x - _mouseDraggedPoint.x), _CGRectGetMinY(_frame) + (location.y - _mouseDraggedPoint.y))];
00560
00561 _mouseDraggedPoint = location;
00562 }
00563
00564 [CPApp setTarget:self selector:@selector(trackMoveWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
00565 }
00566
00567
00568
00569
00570 - (void)trackResizeWithEvent:(CPEvent)anEvent
00571 {
00572 var location = [anEvent locationInWindow],
00573 type = [anEvent type];
00574
00575 if (type == CPLeftMouseUp)
00576 return;
00577
00578 else if (type == CPLeftMouseDown)
00579 _resizeFrame = CGRectMake(location.x, location.y, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
00580
00581 else if (type == CPLeftMouseDragged)
00582 [self setFrameSize:CGSizeMake(CGRectGetWidth(_resizeFrame) + location.x - CGRectGetMinX(_resizeFrame), CGRectGetHeight(_resizeFrame) + location.y - CGRectGetMinY(_resizeFrame))];
00583
00584 [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
00585 }
00586
00591 - (void)orderFront:(id)aSender
00592 {
00593 [_bridge order:CPWindowAbove window:self relativeTo:nil];
00594 }
00595
00596
00597
00598
00599
00600
00601 - (void)orderBack:(id)aSender
00602 {
00603
00604 }
00605
00610 - (void)orderOut:(id)aSender
00611 {
00612 if ([_delegate respondsToSelector:@selector(windowWillClose:)])
00613 [_delegate windowWillClose:self];
00614
00615 [_bridge order:CPWindowOut window:self relativeTo:nil];
00616
00617 if ([CPApp keyWindow] == self)
00618 {
00619 [self resignKeyWindow];
00620
00621 CPApp._keyWindow = nil;
00622 }
00623 }
00624
00630 - (void)orderWindow:(CPWindowOrderingMode)aPlace relativeTo:(int)otherWindowNumber
00631 {
00632 [_bridge order:aPlace window:self relativeTo:CPApp._windows[otherWindowNumber]];
00633 }
00634
00639 - (void)setLevel:(int)aLevel
00640 {
00641 _level = aLevel;
00642 }
00643
00647 - (int)level
00648 {
00649 return _level;
00650 }
00651
00655 - (BOOL)isVisible
00656 {
00657 return _isVisible;
00658 }
00659
00663 - (BOOL)showsResizeIndicator
00664 {
00665 return [_windowView showsResizeIndicator];
00666 }
00667
00672 - (void)setShowsResizeIndicator:(BOOL)shouldShowResizeIndicator
00673 {
00674 [_windowView setShowsResizeIndicator:shouldShowResizeIndicator];
00675 }
00676
00680 - (CGSize)resizeIndicatorOffset
00681 {
00682 return [_windowView resizeIndicatorOffset];
00683 }
00684
00689 - (void)setResizeIndicatorOffset:(CGSize)anOffset
00690 {
00691 [_windowView setResizeIndicatorOffset:anOffset];
00692 }
00693
00699 - (void)setContentView:(CPView)aView
00700 {
00701 if (_contentView)
00702 [_contentView removeFromSuperview];
00703
00704 _contentView = aView;
00705 [_contentView setFrame:[self contentRectForFrameRect:_frame]];
00706
00707 [_contentView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00708 [_windowView addSubview:_contentView positioned:CPWindowBelow relativeTo:nil];
00709 }
00710
00714 - (CPView)contentView
00715 {
00716 return _contentView;
00717 }
00718
00723 - (void)setBackgroundColor:(CPColor)aColor
00724 {
00725 [_windowView setBackgroundColor:aColor];
00726 }
00727
00731 - (CPColor)backgroundColor
00732 {
00733 return [_windowView backgroundColor];
00734 }
00735
00741 - (void)setMinSize:(CGSize)aSize
00742 {
00743 if (CGSizeEqualToSize(_minSize, aSize))
00744 return;
00745
00746 _minSize = CGSizeCreateCopy(aSize);
00747
00748 var size = CGSizeMakeCopy([self frame].size),
00749 needsFrameChange = NO;
00750
00751 if (size.width < _minSize.width)
00752 {
00753 size.width = _minSize.width;
00754 needsFrameChange = YES;
00755 }
00756
00757 if (size.height < _minSize.height)
00758 {
00759 size.height = _minSize.height;
00760 needsFrameChange = YES;
00761 }
00762
00763 if (needsFrameChange)
00764 [self setFrameSize:size];
00765 }
00766
00770 - (CGSize)minSize
00771 {
00772 return _minSize;
00773 }
00774
00781 - (void)setMaxSize:(CGSize)aSize
00782 {
00783 if (CGSizeEqualToSize(_maxSize, aSize))
00784 return;
00785
00786 _maxSize = CGSizeCreateCopy(aSize);
00787
00788 var size = CGSizeMakeCopy([self frame].size),
00789 needsFrameChange = NO;
00790
00791 if (size.width > _maxSize.width)
00792 {
00793 size.width = _maxSize.width;
00794 needsFrameChange = YES;
00795 }
00796
00797 if (size.height > _maxSize.height)
00798 {
00799 size.height = _maxSize.height;
00800 needsFrameChange = YES;
00801 }
00802
00803 if (needsFrameChange)
00804 [self setFrameSize:size];
00805 }
00806
00810 - (CGSize)maxSize
00811 {
00812 return _maxSize;
00813 }
00814
00818 - (BOOL)hasShadow
00819 {
00820 return _hasShadow;
00821 }
00822
00827 - (void)setHasShadow:(BOOL)shouldHaveShadow
00828 {
00829 if (_hasShadow == shouldHaveShadow)
00830 return;
00831
00832 _hasShadow = shouldHaveShadow;
00833
00834 if (_hasShadow)
00835 {
00836 var bounds = [_windowView bounds];
00837
00838 _shadowView = [[CPView alloc] initWithFrame:CGRectMake(-SHADOW_MARGIN_LEFT, -SHADOW_MARGIN_TOP + SHADOW_DISTANCE,
00839 SHADOW_MARGIN_LEFT + CGRectGetWidth(bounds) + SHADOW_MARGIN_RIGHT, SHADOW_MARGIN_TOP + CGRectGetHeight(bounds) + SHADOW_MARGIN_BOTTOM)];
00840
00841 if (!_CPWindowShadowColor)
00842 {
00843 var bundle = [CPBundle bundleForClass:[self class]];
00844
00845 _CPWindowShadowColor = [CPColor colorWithPatternImage:[[CPNinePartImage alloc] initWithImageSlices:
00846 [
00847 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow0.png"] size:CGSizeMake(20.0, 19.0)],
00848 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow1.png"] size:CGSizeMake(1.0, 19.0)],
00849 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow2.png"] size:CGSizeMake(19.0, 19.0)],
00850
00851 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow3.png"] size:CGSizeMake(20.0, 1.0)],
00852 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow4.png"] size:CGSizeMake(1.0, 1.0)],
00853 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow5.png"] size:CGSizeMake(19.0, 1.0)],
00854
00855 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow6.png"] size:CGSizeMake(20.0, 18.0)],
00856 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow7.png"] size:CGSizeMake(1.0, 18.0)],
00857 [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPWindow/CPWindowShadow8.png"] size:CGSizeMake(19.0, 18.0)]
00858 ]]];
00859 }
00860
00861 [_shadowView setBackgroundColor:_CPWindowShadowColor];
00862 [_shadowView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
00863
00864 #if PLATFORM(DOM)
00865 CPDOMDisplayServerInsertBefore(_DOMElement, _shadowView._DOMElement, _windowView._DOMElement);
00866 #endif
00867 }
00868 else
00869 {
00870 #if PLATFORM(DOM)
00871 CPDOMDisplayServerRemoveChild(_DOMElement, _shadowView._DOMElement);
00872 #endif
00873 _shadowView = nil;
00874 }
00875 }
00876
00881 - (void)setDelegate:(id)aDelegate
00882 {
00883 _delegate = aDelegate;
00884
00885 _delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)];
00886
00887 var defaultCenter = [CPNotificationCenter defaultCenter];
00888
00889 if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)])
00890 [defaultCenter
00891 addObserver:_delegate
00892 selector:@selector(windowDidBecomeMain:)
00893 name:CPWindowDidBecomeMainNotification
00894 object:self];
00895
00896 if ([_delegate respondsToSelector:@selector(windowDidResignMain:)])
00897 [defaultCenter
00898 addObserver:_delegate
00899 selector:@selector(windowDidResignMain:)
00900 name:CPWindowDidResignMainNotification
00901 object:self];
00902 }
00903
00907 - (id)delegate
00908 {
00909 return _delegate;
00910 }
00911
00916 - (void)setWindowController:(CPWindowController)aWindowController
00917 {
00918 _windowController = aWindowController;
00919 }
00920
00924 - (CPWindowController)windowController
00925 {
00926 return _windowController;
00927 }
00928
00929 - (void)doCommandBySelector:(SEL)aSelector
00930 {
00931 if ([_delegate respondsToSelector:aSelector])
00932 [_delegate performSelector:aSelector];
00933 else
00934 [super doCommandBySelector:aSelector];
00935 }
00936
00937 - (BOOL)acceptsFirstResponder
00938 {
00939 return YES;
00940 }
00941
00949 - (void)makeFirstResponder:(CPResponder)aResponder
00950 {
00951 if (_firstResponder == aResponder)
00952 return YES;
00953
00954 if(![_firstResponder resignFirstResponder])
00955 return NO;
00956
00957 if(!aResponder || ![aResponder acceptsFirstResponder] || ![aResponder becomeFirstResponder])
00958 {
00959 _firstResponder = self;
00960
00961 return NO;
00962 }
00963
00964 _firstResponder = aResponder;
00965
00966 return YES;
00967 }
00968
00972 - (CPResponder)firstResponder
00973 {
00974 return _firstResponder;
00975 }
00976
00977 - (BOOL)acceptsMouseMovedEvents
00978 {
00979 return _acceptsMouseMovedEvents;
00980 }
00981
00982 - (void)setAcceptsMouseMovedEvents:(BOOL)shouldAcceptMouseMovedEvents
00983 {
00984 _acceptsMouseMovedEvents = shouldAcceptMouseMovedEvents;
00985 }
00986
00987
00988
00992 - (CPString)title
00993 {
00994 return _title;
00995 }
00996
01000 - (void)setTitle:(CPString)aTitle
01001 {
01002 _title = aTitle;
01003
01004 [_windowView setTitle:aTitle];
01005
01006 [self _synchronizeMenuBarTitleWithWindowTitle];
01007 }
01008
01012 - (void)setTitleWithRepresentedFilename:(CPString)aFilePath
01013 {
01014 [self setRepresentedFilename:aFilePath];
01015 [self setTitle:[aFilePath lastPathComponent]];
01016 }
01017
01021 - (void)setRepresentedFilename:(CPString)aFilePath
01022 {
01023
01024 [self setRepresentedURL:aFilePath];
01025 }
01026
01030 - (CPString)representedFilename
01031 {
01032 return _representedURL;
01033 }
01034
01038 - (void)setRepresentedURL:(CPURL)aURL
01039 {
01040 _representedURL = aURL;
01041 }
01042
01046 - (CPURL)representedURL
01047 {
01048 return _representedURL;
01049 }
01050
01051
01052
01057 - (void)setMovableByWindowBackground:(BOOL)shouldBeMovableByWindowBackground
01058 {
01059 _isMovableByWindowBackground = shouldBeMovableByWindowBackground;
01060 }
01061
01065 - (BOOL)isMovableByWindowBackground
01066 {
01067 return _isMovableByWindowBackground;
01068 }
01069
01073 - (void)center
01074 {
01075 var size = [self frame].size,
01076 bridgeSize = [_bridge contentBounds].size;
01077
01078 [self setFrameOrigin:CGPointMake((bridgeSize.width - size.width) / 2.0, (bridgeSize.height - size.height) / 2.0)];
01079 }
01080
01085 - (void)sendEvent:(CPEvent)anEvent
01086 {
01087 var type = [anEvent type],
01088 point = [anEvent locationInWindow];
01089
01090 switch (type)
01091 {
01092 case CPKeyUp: return [[self firstResponder] keyUp:anEvent];
01093 case CPKeyDown: return [[self firstResponder] keyDown:anEvent];
01094
01095 case CPScrollWheel: return [[_windowView hitTest:point] scrollWheel:anEvent];
01096
01097 case CPLeftMouseUp: if (!_leftMouseDownView)
01098 return [[_windowView hitTest:point] mouseUp:anEvent];
01099
01100 [_leftMouseDownView mouseUp:anEvent]
01101
01102 _leftMouseDownView = nil;
01103
01104 return;
01105 case CPLeftMouseDown: _leftMouseDownView = [_windowView hitTest:point];
01106
01107 if (_leftMouseDownView != _firstResponder && [_leftMouseDownView acceptsFirstResponder])
01108 [self makeFirstResponder:_leftMouseDownView];
01109
01110 var theWindow = [anEvent window];
01111
01112 if ([theWindow isKeyWindow] || [theWindow becomesKeyOnlyIfNeeded])
01113 return [_leftMouseDownView mouseDown:anEvent];
01114 else
01115 {
01116
01117 [self makeKeyAndOrderFront:self];
01118
01119 if ([_leftMouseDownView acceptsFirstMouse:anEvent])
01120 return [_leftMouseDownView mouseDown:anEvent]
01121 }
01122 break;
01123 case CPLeftMouseDragged: if (!_leftMouseDownView)
01124 return [[_windowView hitTest:point] mouseDragged:anEvent];
01125
01126 return [_leftMouseDownView mouseDragged:anEvent];
01127
01128 case CPRightMouseUp: return [_rightMouseDownView mouseUp:anEvent];
01129 case CPRightMouseDown: _rightMouseDownView = [_windowView hitTest:point];
01130 return [_rightMouseDownView mouseDown:anEvent];
01131 case CPRightMouseDragged: return [_rightMouseDownView mouseDragged:anEvent];
01132
01133 case CPMouseMoved: if (!_acceptsMouseMovedEvents)
01134 return;
01135
01136 var hitTestView = [_windowView hitTest:point];
01137
01138 if (hitTestView != _mouseOverView)
01139 {
01140 if (_mouseOverView)
01141 [_mouseOverView mouseExited:[CPEvent mouseEventWithType:CPMouseExited location:point
01142 modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0]];
01143
01144 if (hitTestView)
01145 [hitTestView mouseEntered:[CPEvent mouseEventWithType:CPMouseEntered location:point
01146 modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0]];
01147
01148 _mouseOverView = hitTestView;
01149 }
01150
01151 [_mouseOverView mouseMoved:anEvent];
01152 }
01153 }
01154
01158 - (int)windowNumber
01159 {
01160 return _windowNumber;
01161 }
01162
01167 - (void)becomeKeyWindow
01168 {
01169 if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)])
01170 [_firstResponder becomeKeyWindow];
01171 }
01172
01177 - (BOOL)canBecomeKeyWindow
01178 {
01179 return YES;
01180 }
01181
01185 - (BOOL)isKeyWindow
01186 {
01187 return [CPApp keyWindow] == self;
01188 }
01189
01194 - (void)makeKeyAndOrderFront:(id)aSender
01195 {
01196 [self orderFront:self];
01197
01198 [self makeKeyWindow];
01199 [self makeMainWindow];
01200 }
01201
01205 - (void)makeKeyWindow
01206 {
01207 if (![self canBecomeKeyWindow])
01208 return;
01209
01210 [CPApp._keyWindow resignKeyWindow];
01211
01212 CPApp._keyWindow = self;
01213
01214 [self becomeKeyWindow];
01215 }
01216
01220 - (void)resignKeyWindow
01221 {
01222 if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)])
01223 [_firstResponder resignKeyWindow];
01224
01225 if ([_delegate respondsToSelector:@selector(windowDidResignKey:)])
01226 [_delegate windowDidResignKey:self];
01227 }
01228
01239 - (void)dragImage:(CPImage)anImage at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
01240 {
01241 [[CPDragServer sharedDragServer] dragImage:anImage fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
01242 }
01243
01254 - (void)dragView:(CPView)aView at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(CPEvent)anEvent pasteboard:(CPPasteboard)aPasteboard source:(id)aSourceObject slideBack:(BOOL)slideBack
01255 {
01256 [[CPDragServer sharedDragServer] dragView:aView fromWindow:self at:[self convertBaseToBridge:imageLocation] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
01257 }
01258
01259
01260
01265 - (void)setDocumentEdited:(BOOL)isDocumentEdited
01266 {
01267 if (_isDocumentEdited == isDocumentEdited)
01268 return;
01269
01270 _isDocumentEdited = isDocumentEdited;
01271
01272 [CPMenu _setMenuBarIconImageAlphaValue:_isDocumentEdited ? 0.5 : 1.0];
01273 }
01274
01278 - (BOOL)isDocumentEdited
01279 {
01280 return _isDocumentEdited;
01281 }
01282
01283 - (void)setDocumentSaving:(BOOL)isDocumentSaving
01284 {
01285 if (_isDocumentSaving == isDocumentSaving)
01286 return;
01287
01288 _isDocumentSaving = isDocumentSaving;
01289
01290 [self _synchronizeSaveMenuWithDocumentSaving];
01291
01292 [_windowView windowDidChangeDocumentSaving];
01293 }
01294
01295 - (BOOL)isDocumentSaving
01296 {
01297 return _isDocumentSaving;
01298 }
01299
01300
01301 - (void)_synchronizeSaveMenuWithDocumentSaving
01302 {
01303 if (![self isMainWindow])
01304 return;
01305
01306 var mainMenu = [CPApp mainMenu],
01307 index = [mainMenu indexOfItemWithTitle:_isDocumentSaving ? @"Save" : @"Saving..."];
01308
01309 if (index == CPNotFound)
01310 return;
01311
01312 var item = [mainMenu itemAtIndex:index];
01313
01314 if (_isDocumentSaving)
01315 {
01316 CPWindowSaveImage = [item image];
01317
01318 [item setTitle:@"Saving..."];
01319 [item setImage:CPWindowSavingImage];
01320 [item setEnabled:NO];
01321 }
01322 else
01323 {
01324 [item setTitle:@"Save"];
01325 [item setImage:CPWindowSaveImage];
01326 [item setEnabled:YES];
01327 }
01328 }
01329
01330
01331
01336 - (void)performClose:(id)aSender
01337 {
01338
01339 if ([_delegate respondsToSelector:@selector(windowShouldClose:)])
01340 {
01341 if (![_delegate windowShouldClose:self])
01342 return;
01343 }
01344
01345
01346 else if ([self respondsToSelector:@selector(windowShouldClose:)] && ![self windowShouldClose:self])
01347 return;
01348
01349 [self close];
01350 }
01351
01356 - (void)close
01357 {
01358 [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
01359
01360 [self orderOut:nil];
01361 }
01362
01363
01367 - (BOOL)isMainWindow
01368 {
01369 return [CPApp mainWindow] == self;
01370 }
01371
01375 - (BOOL)canBecomeMainWindow
01376 {
01377
01378 if ([self isVisible])
01379 return YES;
01380
01381 return NO;
01382 }
01383
01387 - (void)makeMainWindow
01388 {
01389 if (![self canBecomeMainWindow])
01390 return;
01391
01392 [CPApp._mainWindow resignMainWindow];
01393
01394 CPApp._mainWindow = self;
01395
01396 [self becomeMainWindow];
01397 }
01398
01402 - (void)becomeMainWindow
01403 {
01404 [self _synchronizeMenuBarTitleWithWindowTitle];
01405 [self _synchronizeSaveMenuWithDocumentSaving];
01406
01407 [[CPNotificationCenter defaultCenter]
01408 postNotificationName:CPWindowDidBecomeMainNotification
01409 object:self];
01410 }
01411
01415 - (void)resignMainWindow
01416 {
01417 [[CPNotificationCenter defaultCenter]
01418 postNotificationName:CPWindowDidResignMainNotification
01419 object:self];
01420 }
01421
01422
01426 - (CPToolbar)toolbar
01427 {
01428 return _toolbar;
01429 }
01430
01435 - (void)setToolbar:(CPToolbar)aToolbar
01436 {
01437 if (_toolbar == aToolbar)
01438 return;
01439
01440
01441 if (_toolbar)
01442 {
01443 [self _setToolbarVisible:NO];
01444
01445 _toolbar._window = nil;
01446 _toolbarView = nil;
01447 }
01448
01449 if (_toolbar = aToolbar)
01450 {
01451
01452 _toolbar = aToolbar;
01453 _toolbar._window = self;
01454
01455 if ([_toolbar isVisible])
01456 [self _setToolbarVisible:YES];
01457
01458 [_toolbar _reloadToolbarItems];
01459 }
01460 }
01461
01462
01463 - (void)_setToolbarVisible:(BOOL)aFlag
01464 {
01465 if (aFlag)
01466 {
01467 if (!_toolbarView)
01468 _toolbarView = [_toolbar _toolbarView];
01469
01470 [_toolbarView setFrame:CGRectMake(0.0, 0.0, CGRectGetWidth([_windowView bounds]), CGRectGetHeight([_toolbarView frame]))];
01471 [_windowView addSubview:_toolbarView];
01472 }
01473 else
01474 [_toolbarView removeFromSuperview];
01475
01476 [_contentView setFrame:[self contentRectForFrameRect:[_windowView bounds]]];
01477 }
01478
01479
01480
01481
01482 - (void)_setAttachedSheetFrameOrigin
01483 {
01484
01485 var contentRect = [[self contentView] frame],
01486 sheetFrame = CGRectMakeCopy([_attachedSheet frame]);
01487
01488 sheetFrame.origin.y = CGRectGetMinY(_frame) + CGRectGetMinY(contentRect);
01489 sheetFrame.origin.x = CGRectGetMinX(_frame) + FLOOR((CGRectGetWidth(_frame) - CGRectGetWidth(sheetFrame)) / 2.0);
01490
01491 [_attachedSheet setFrameOrigin:sheetFrame.origin];
01492 }
01493
01494
01495 - (void)_animateAttachedSheet
01496 {
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517 }
01518
01519
01520 - (void)_attachSheet:(CPWindow)aSheet modalDelegate:(id)aModalDelegate didEndSelector:(SEL)aDidEndSelector contextInfo:(id)aContextInfo
01521 {
01522
01523 _attachedSheet = aSheet;
01524
01525
01526 aSheet._isSheet = YES;
01527
01528 [self _setAttachedSheetFrameOrigin];
01529
01530
01531 [_bridge order:CPWindowAbove window:aSheet relativeTo:self];
01532 }
01533
01537 - (CPWindow)attachedSheet
01538 {
01539 return _attachedSheet;
01540 }
01541
01545 - (BOOL)isSheet
01546 {
01547 return _isSheet;
01548 }
01549
01550
01551
01552
01553
01554
01555 - (BOOL)becomesKeyOnlyIfNeeded
01556 {
01557 return NO;
01558 }
01559
01564 - (BOOL)worksWhenModal
01565 {
01566 return NO;
01567 }
01568
01569 @end
01570
01571 @implementation CPWindow (MenuBar)
01572
01573 - (void)_synchronizeMenuBarTitleWithWindowTitle
01574 {
01575
01576 if (![_windowController document] || ![self isMainWindow])
01577 return;
01578
01579 [CPMenu setMenuBarTitle:_title];
01580 }
01581
01582 @end
01583
01584 @implementation CPWindow (BridgeSupport)
01585
01586
01587
01588
01589
01590 - (void)setBridge:(CPDOMWindowBridge)aBridge
01591 {
01592 if (_bridge == aBridge)
01593 return;
01594
01595 if (_bridge)
01596 {
01597 [self orderOut:self];
01598
01599 }
01600
01601 _bridge = aBridge;
01602
01603 if (_styleMask & CPBorderlessBridgeWindowMask)
01604 [self setFrame:[aBridge contentBounds]];
01605 }
01606
01607
01608
01609
01610 - (void)resizeWithOldBridgeSize:(CGSize)aSize
01611 {
01612 if (_styleMask & CPBorderlessBridgeWindowMask)
01613 return [self setFrame:[_bridge visibleFrame]];
01614
01615 if (_autoresizingMask == CPWindowNotSizable)
01616 return;
01617
01618 var frame = [_bridge contentBounds],
01619 newFrame = CGRectMakeCopy(_frame),
01620 dX = (CGRectGetWidth(frame) - aSize.width) /
01621 (((_autoresizingMask & CPWindowMinXMargin) ? 1 : 0) + (_autoresizingMask & CPWindowWidthSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxXMargin ? 1 : 0)),
01622 dY = (CGRectGetHeight(frame) - aSize.height) /
01623 ((_autoresizingMask & CPWindowMinYMargin ? 1 : 0) + (_autoresizingMask & CPWindowHeightSizable ? 1 : 0) + (_autoresizingMask & CPWindowMaxYMargin ? 1 : 0));
01624
01625 if (_autoresizingMask & CPWindowMinXMargin)
01626 newFrame.origin.x += dX;
01627 if (_autoresizingMask & CPWindowWidthSizable)
01628 newFrame.size.width += dX;
01629
01630 if (_autoresizingMask & CPWindowMinYMargin)
01631 newFrame.origin.y += dY;
01632 if (_autoresizingMask & CPWindowHeightSizable)
01633 newFrame.size.height += dY;
01634
01635 [self setFrame:newFrame];
01636 }
01637
01638
01639
01640
01641 - (void)setAutoresizingMask:(unsigned)anAutoresizingMask
01642 {
01643 _autoresizingMask = anAutoresizingMask;
01644 }
01645
01646
01647
01648
01649 - (unsigned)autoresizingMask
01650 {
01651 return _autoresizingMask;
01652 }
01653
01654
01655
01656
01657 - (CGPoint)convertBaseToBridge:(CGPoint)aPoint
01658 {
01659 var origin = [self frame].origin;
01660
01661 return CGPointMake(aPoint.x + origin.x, aPoint.y + origin.y);
01662 }
01663
01664
01665
01666
01667 - (CGPoint)convertBridgeToBase:(CGPoint)aPoint
01668 {
01669 var origin = [self frame].origin;
01670
01671 return CGPointMake(aPoint.x - origin.x, aPoint.y - origin.y);
01672 }
01673
01674
01678 - (CPUndoManager)undoManager
01679 {
01680 if (_delegateRespondsToWindowWillReturnUndoManagerSelector)
01681 return [_delegate windowWillReturnUndoManager:self];
01682
01683 if (!_undoManager)
01684 _undoManager = [[CPUndoManager alloc] init];
01685
01686 return _undoManager;
01687 }
01688
01693 - (void)undo:(id)aSender
01694 {
01695 [[self undoManager] undo];
01696 }
01697
01702 - (void)redo:(id)aSender
01703 {
01704 [[self undoManager] redo];
01705 }
01706
01707 @end
01708
01709 var interpolate = function(fromValue, toValue, progress)
01710 {
01711 return fromValue + (toValue - fromValue) * progress;
01712 }
01713
01714
01715 @implementation _CPWindowFrameAnimation : CPAnimation
01716 {
01717 CPWindow _window;
01718
01719 CGRect _startFrame;
01720 CGRect _targetFrame;
01721 }
01722
01723 - (id)initWithWindow:(CPWindow)aWindow targetFrame:(CGRect)aTargetFrame
01724 {
01725 self = [super initWithDuration:0.2 animationCurve:CPAnimationLinear];
01726
01727 if (self)
01728 {
01729 _window = aWindow;
01730
01731 _targetFrame = CGRectMakeCopy(aTargetFrame);
01732 _startFrame = CGRectMakeCopy([_window frame]);
01733 }
01734
01735 return self;
01736 }
01737
01738 - (void)startAnimation
01739 {
01740 [super startAnimation];
01741
01742 _window._isAnimating = YES;
01743 }
01744
01745 - (void)setCurrentProgress:(float)aProgress
01746 {
01747 [super setCurrentProgress:aProgress];
01748
01749 var value = [self currentValue];
01750
01751 if (value == 1.0)
01752 _window._isAnimating = NO;
01753
01754 [_window setFrameOrigin:CGPointMake(interpolate(CGRectGetMinX(_startFrame), CGRectGetMinX(_targetFrame), value), interpolate(CGRectGetMinY(_startFrame), CGRectGetMinY(_targetFrame), value))];
01755 [_window setFrameSize:CGSizeMake(interpolate(CGRectGetWidth(_startFrame), CGRectGetWidth(_targetFrame), value), interpolate(CGRectGetHeight(_startFrame), CGRectGetHeight(_targetFrame), value))];
01756 }
01757
01758 @end
01759
01760 @import "CPDragServer.j"
01761 @import "CPDOMWindowBridge.j"
01762 @import "_CPWindowView.j"
01763 @import "CPView.j"