27 @class _CPMenuItemView
33 @global appkit_tag_dom_elements
37 if (typeof(appkit_tag_dom_elements) !==
"undefined" && appkit_tag_dom_elements)
39 AppKitTagDOMElement =
function(owner, element)
41 element.setAttribute(
"data-cappuccino-view", [owner className]);
42 element.setAttribute(
"data-cappuccino-uid", [owner UID]);
47 AppKitTagDOMElement =
function(owner, element)
72 CPViewWidthSizable = 2;
90 CPViewHeightSizable = 16;
96 CPViewMaxYMargin = 32;
98 CPViewBoundsDidChangeNotification =
@"CPViewBoundsDidChangeNotification";
99 CPViewFrameDidChangeNotification =
@"CPViewFrameDidChangeNotification";
101 var CachedNotificationCenter = nil,
102 CachedThemeAttributes = nil;
105 var DOMElementPrototype = nil,
107 BackgroundTrivialColor = 0,
108 BackgroundVerticalThreePartImage = 1,
109 BackgroundHorizontalThreePartImage = 2,
110 BackgroundNinePartImage = 3,
111 BackgroundTransparentColor = 4;
114 var CPViewFlags = { },
115 CPViewHasCustomDrawRect = 1 << 0,
116 CPViewHasCustomLayoutSubviews = 1 << 1;
150 CGAffineTransform _boundsTransform;
151 CGAffineTransform _inverseBoundsTransform;
153 CPSet _registeredDraggedTypes;
154 CPArray _registeredDraggedTypesArray;
160 BOOL _postsFrameChangedNotifications;
161 BOOL _postsBoundsChangedNotifications;
162 BOOL _inhibitFrameAndBoundsChangedNotifications;
166 DOMElement _DOMElement;
167 DOMElement _DOMContentsElement;
169 CPArray _DOMImageParts;
170 CPArray _DOMImageSizes;
172 unsigned _backgroundType;
180 BOOL _autoresizesSubviews;
181 unsigned _autoresizingMask;
187 BOOL _isInFullScreenMode;
189 _CPViewFullScreenModeState _fullScreenModeState;
193 CGSize _hierarchyScaleSize;
198 JSObject _ephemeralSubviews;
203 JSObject _themeAttributes;
204 unsigned _themeState;
206 JSObject _ephemeralSubviewsForNames;
207 CPSet _ephereralSubviews;
213 unsigned _viewClassFlags;
217 Function _toolTipFunctionIn;
218 Function _toolTipFunctionOut;
219 BOOL _toolTipInstalled;
228 if (
self !== [
CPView class])
232 DOMElementPrototype = document.createElement(
"div");
234 var style = DOMElementPrototype.style;
236 style.overflow =
"hidden";
237 style.position =
"absolute";
238 style.visibility =
"visible";
245 + (Class)_binderClassForBinding:(
CPString)aBinding
247 if ([aBinding hasPrefix:CPHiddenBinding])
250 return [
super _binderClassForBinding:aBinding];
253 - (void)_setupViewFlags
255 var theClass = [
self class],
256 classUID = [theClass UID];
258 if (CPViewFlags[classUID] === undefined)
262 if ([theClass instanceMethodForSelector:
@selector(drawRect:)] !== [
CPView instanceMethodForSelector:
@selector(drawRect:)])
263 flags |= CPViewHasCustomDrawRect;
265 if ([theClass instanceMethodForSelector:
@selector(layoutSubviews)] !== [
CPView instanceMethodForSelector:
@selector(layoutSubviews)])
266 flags |= CPViewHasCustomLayoutSubviews;
268 CPViewFlags[classUID] = flags;
271 _viewClassFlags = CPViewFlags[classUID];
274 - (void)_setupToolTipHandlers
276 _toolTipInstalled = NO;
277 _toolTipFunctionIn =
function(e) { [_CPToolTip scheduleToolTipForView:self]; }
278 _toolTipFunctionOut =
function(e) { [_CPToolTip invalidateCurrentToolTipIfNeeded]; };
281 + (CPSet)keyPathsForValuesAffectingFrame
283 return [CPSet setWithObjects:@"frameOrigin", @"frameSize"];
286 + (CPSet)keyPathsForValuesAffectingBounds
288 return [CPSet setWithObjects:@"boundsOrigin", @"boundsSize"];
298 return [
self initWithFrame:CGRectMakeZero()];
305 - (id)initWithFrame:(CGRect)aFrame
311 var
width = CGRectGetWidth(aFrame),
312 height = CGRectGetHeight(aFrame);
315 _registeredDraggedTypes = [CPSet set];
316 _registeredDraggedTypesArray = [];
320 _frame = CGRectMakeCopy(aFrame);
321 _bounds = CGRectMake(0.0, 0.0, width, height);
323 _autoresizingMask = CPViewNotSizable;
324 _autoresizesSubviews = YES;
325 _clipsToBounds = YES;
331 _hierarchyScaleSize = CGSizeMake(1.0 , 1.0);
332 _scaleSize = CGSizeMake(1.0, 1.0);
336 _DOMElement = DOMElementPrototype.cloneNode(
false);
337 AppKitTagDOMElement(
self, _DOMElement);
339 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(aFrame), CGRectGetMinY(aFrame));
340 CPDOMDisplayServerSetStyleSize(_DOMElement, width, height);
346 _theme = [
CPTheme defaultTheme];
347 _themeState = CPThemeStateNormal;
349 [
self _setupToolTipHandlers];
350 [
self _setupViewFlags];
352 [
self _loadThemeAttributes];
364 - (void)setToolTip:(
CPString)aToolTip
366 if (_toolTip == aToolTip)
369 if (aToolTip && ![aToolTip isKindOfClass:
CPString])
370 aToolTip = [aToolTip description];
375 [
self _installToolTipEventHandlers];
377 [
self _uninstallToolTipEventHandlers];
384 - (void)_installToolTipEventHandlers
386 if (_toolTipInstalled)
390 if (_DOMElement.addEventListener)
392 _DOMElement.addEventListener(
"mouseover", _toolTipFunctionIn, YES);
393 _DOMElement.addEventListener(
"keypress", _toolTipFunctionOut, YES);
394 _DOMElement.addEventListener(
"mouseout", _toolTipFunctionOut, YES);
396 else if (_DOMElement.attachEvent)
398 _DOMElement.attachEvent(
"onmouseover", _toolTipFunctionIn);
399 _DOMElement.attachEvent(
"onkeypress", _toolTipFunctionOut);
400 _DOMElement.attachEvent(
"onmouseout", _toolTipFunctionOut);
404 _toolTipInstalled = YES;
411 - (void)_uninstallToolTipEventHandlers
413 if (!_toolTipInstalled)
417 if (_DOMElement.removeEventListener)
419 _DOMElement.removeEventListener(
"mouseover", _toolTipFunctionIn, YES);
420 _DOMElement.removeEventListener(
"keypress", _toolTipFunctionOut, YES);
421 _DOMElement.removeEventListener(
"mouseout", _toolTipFunctionOut, YES);
423 else if (_DOMElement.detachEvent)
425 _DOMElement.detachEvent(
"onmouseover", _toolTipFunctionIn);
426 _DOMElement.detachEvent(
"onkeypress", _toolTipFunctionOut);
427 _DOMElement.detachEvent(
"onmouseout", _toolTipFunctionOut);
431 _toolTipInstalled = NO;
449 return [_subviews copy];
464 - (void)addSubview:(
CPView)aSubview
466 [
self _insertSubview:aSubview atIndex:CPNotFound];
475 - (void)addSubview:(
CPView)aSubview positioned:(CPWindowOrderingMode)anOrderingMode relativeTo:(
CPView)anotherView
477 var index = anotherView ? [_subviews indexOfObjectIdenticalTo:anotherView] :
CPNotFound;
481 index = (anOrderingMode ===
CPWindowAbove) ? [_subviews count] : 0;
487 [
self _insertSubview:aSubview atIndex:index];
491 - (void)_insertSubview:(
CPView)aSubview atIndex:(
int)anIndex
493 if (aSubview ===
self)
496 if (!aSubview._superview && _subviews.indexOf(aSubview) !==
CPNotFound)
501 var count = _subviews.length;
504 [[
self window] _dirtyKeyViewLoop];
507 if (aSubview._superview ==
self)
509 var index = [_subviews indexOfObjectIdenticalTo:aSubview];
512 if (index === anIndex || index === count - 1 && anIndex === count)
515 [_subviews removeObjectAtIndex:index];
518 CPDOMDisplayServerRemoveChild(_DOMElement, aSubview._DOMElement);
530 [aSubview removeFromSuperview];
533 [aSubview _setWindow:_window];
536 [aSubview viewWillMoveToSuperview:self];
539 aSubview._superview =
self;
542 if (anIndex ===
CPNotFound || anIndex >= count)
544 _subviews.push(aSubview);
548 CPDOMDisplayServerAppendChild(_DOMElement, aSubview._DOMElement);
553 _subviews.splice(anIndex, 0, aSubview);
557 CPDOMDisplayServerInsertBefore(_DOMElement, aSubview._DOMElement, _subviews[anIndex + 1]._DOMElement);
561 [aSubview setNextResponder:self];
562 [aSubview _scaleSizeUnitSquareToSize:[
self _hierarchyScaleSize]];
566 if (![aSubview isHidden] && [
self isHiddenOrHasHiddenAncestor])
567 [aSubview _notifyViewDidHide];
569 [aSubview viewDidMoveToSuperview];
571 [
self didAddSubview:aSubview];
578 - (void)didAddSubview:(
CPView)aSubview
586 - (void)removeFromSuperview
592 [[
self window] _dirtyKeyViewLoop];
594 [_superview willRemoveSubview:self];
596 [_superview._subviews removeObjectIdenticalTo:self];
599 CPDOMDisplayServerRemoveChild(_superview._DOMElement, _DOMElement);
604 if (!_isHidden && [_superview isHiddenOrHasHiddenAncestor])
605 [
self _notifyViewDidUnhide];
609 [
self _setWindow:nil];
617 - (void)replaceSubview:(
CPView)aSubview with:(
CPView)aView
619 if (aSubview._superview !==
self)
622 var index = [_subviews indexOfObjectIdenticalTo:aSubview];
624 [aSubview removeFromSuperview];
626 [
self _insertSubview:aView atIndex:index];
629 - (void)setSubviews:(CPArray)newSubviews
632 [
CPException raise:CPInvalidArgumentException
reason:"newSubviews cannot be nil in -[CPView setSubviews:]"];
635 if ([_subviews
isEqual:newSubviews])
639 if ([_subviews count] === 0)
642 count = [newSubviews count];
644 for (; index < count; ++index)
645 [self addSubview:newSubviews[index]];
651 if ([newSubviews count] === 0)
653 var count = [_subviews count];
656 [_subviews[count] removeFromSuperview];
662 var removedSubviews = [
CPMutableSet setWithArray:_subviews];
664 [removedSubviews removeObjectsInArray:newSubviews];
665 [removedSubviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
668 var addedSubviews = [
CPMutableSet setWithArray:newSubviews];
670 [addedSubviews removeObjectsInArray:_subviews];
672 var addedSubview = nil,
673 addedSubviewEnumerator = [addedSubviews objectEnumerator];
675 while ((addedSubview = [addedSubviewEnumerator nextObject]) !== nil)
676 [
self addSubview:addedSubview];
679 if ([_subviews
isEqual:newSubviews])
682 _subviews = [newSubviews copy];
686 count = [_subviews count];
688 for (; index < count; ++index)
690 var subview = _subviews[index];
692 CPDOMDisplayServerRemoveChild(_DOMElement, subview._DOMElement);
693 CPDOMDisplayServerAppendChild(_DOMElement, subview._DOMElement);
699 - (void)_setWindow:(
CPWindow)aWindow
701 if (_window === aWindow)
704 [[
self window] _dirtyKeyViewLoop];
707 if ([_window firstResponder] ===
self)
708 [_window makeFirstResponder:nil];
711 [
self viewWillMoveToWindow:aWindow];
715 if (_registeredDraggedTypes)
717 [_window _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
718 [aWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
723 var count = [_subviews count];
726 [_subviews[count] _setWindow:aWindow];
728 [
self viewDidMoveToWindow];
730 [[
self window] _dirtyKeyViewLoop];
737 - (BOOL)isDescendantOf:(
CPView)aView
745 }
while(view = [view superview])
753 - (void)viewDidMoveToSuperview
756 [
self setNeedsDisplay:YES];
762 - (void)viewDidMoveToWindow
770 - (void)viewWillMoveToSuperview:(
CPView)aView
778 - (void)viewWillMoveToWindow:(
CPWindow)aWindow
786 - (void)willRemoveSubview:(
CPView)aView
798 while (view && ![view isKindOfClass:[_CPMenuItemView
class]])
799 view = [view superview];
802 return view._menuItem;
814 - (void)setTag:(CPInteger)aTag
824 - (
CPView)viewWithTag:(CPInteger)aTag
826 if ([
self tag] == aTag)
830 count = _subviews.length;
832 for (; index < count; ++index)
834 var view = [_subviews[index] viewWithTag:aTag];
859 - (void)setFrame:(CGRect)aFrame
861 if (CGRectEqualToRect(_frame, aFrame))
864 _inhibitFrameAndBoundsChangedNotifications = YES;
866 [
self setFrameOrigin:aFrame.origin];
867 [
self setFrameSize:aFrame.size];
869 _inhibitFrameAndBoundsChangedNotifications = NO;
871 if (_postsFrameChangedNotifications)
872 [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification
object:
self];
881 return CGRectMakeCopy(_frame);
884 - (CGPoint)frameOrigin
886 return CGPointMakeCopy(_frame.origin);
891 return CGSizeMakeCopy(_frame.size);
901 - (void)setCenter:(CGPoint)aPoint
903 [
self setFrameOrigin:CGPointMake(aPoint.x - _frame.size.width / 2.0, aPoint.y - _frame.size.height / 2.0)];
912 return CGPointMake(_frame.size.width / 2.0 + _frame.origin.x, _frame.size.height / 2.0 + _frame.origin.y);
922 - (void)setFrameOrigin:(CGPoint)aPoint
924 var origin = _frame.origin;
926 if (!aPoint || CGPointEqualToPoint(origin, aPoint))
932 if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
933 [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
936 var transform = _superview ? _superview._boundsTransform : NULL;
938 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, transform, origin.x, origin.y);
948 - (void)setFrameSize:(CGSize)aSize
950 var size = _frame.size;
952 if (!aSize || CGSizeEqualToSize(size, aSize))
955 var oldSize = CGSizeMakeCopy(size);
957 size.width = aSize.width;
958 size.height = aSize.height;
962 _bounds.size.width = aSize.width * 1 / _scaleSize.width;
963 _bounds.size.height = aSize.height * 1 / _scaleSize.height;
967 [_layer _owningViewBoundsChanged];
969 if (_autoresizesSubviews)
970 [
self resizeSubviewsWithOldSize:oldSize];
972 [
self setNeedsLayout];
973 [
self setNeedsDisplay:YES];
976 [
self _setDisplayServerSetStyleSize:size];
978 if (_DOMContentsElement)
980 CPDOMDisplayServerSetSize(_DOMContentsElement, size.width, size.height);
981 CPDOMDisplayServerSetStyleSize(_DOMContentsElement, size.width, size.height);
984 if (_backgroundType !== BackgroundTrivialColor)
986 if (_backgroundType === BackgroundTransparentColor)
988 CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
992 var images = [[_backgroundColor patternImage] imageSlices],
995 if (_backgroundType === BackgroundVerticalThreePartImage)
997 var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
998 bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
1003 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, top);
1006 if (_DOMImageSizes[1])
1008 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height - top - bottom);
1013 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, bottom);
1016 else if (_backgroundType === BackgroundHorizontalThreePartImage)
1018 var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1019 right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
1024 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, size.height);
1027 if (_DOMImageSizes[1])
1029 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width - left - right, size.height);
1034 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, size.height);
1037 else if (_backgroundType === BackgroundNinePartImage)
1039 var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1040 right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
1041 top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
1042 bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
1043 width = size.width - left - right,
1044 height = size.height - top - bottom;
1046 if (_DOMImageSizes[0])
1048 if (_DOMImageSizes[1])
1050 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, top);
1053 if (_DOMImageSizes[2])
1055 if (_DOMImageSizes[3])
1057 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
1060 if (_DOMImageSizes[4])
1062 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
1065 if (_DOMImageSizes[5])
1067 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
1070 if (_DOMImageSizes[6])
1072 if (_DOMImageSizes[7])
1074 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
1081 if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1082 [CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
1090 - (void)_setDisplayServerSetStyleSize:(CGSize)aSize
1093 var scale = [
self scaleSize];
1094 CPDOMDisplayServerSetStyleSize(_DOMElement, aSize.width * 1 / scale.width, aSize.height * 1 / scale.height);
1103 - (void)setBounds:(CGRect)bounds
1105 if (CGRectEqualToRect(_bounds, bounds))
1108 _inhibitFrameAndBoundsChangedNotifications = YES;
1110 [
self setBoundsOrigin:bounds.origin];
1111 [
self setBoundsSize:bounds.size];
1113 _inhibitFrameAndBoundsChangedNotifications = NO;
1115 if (_postsBoundsChangedNotifications)
1116 [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1125 return CGRectMakeCopy(_bounds);
1128 - (CGPoint)boundsOrigin
1130 return CGPointMakeCopy(_bounds.origin);
1133 - (CGSize)boundsSize
1135 return CGSizeMakeCopy(_bounds.size);
1144 - (void)setBoundsOrigin:(CGPoint)aPoint
1146 var origin = _bounds.origin;
1148 if (CGPointEqualToPoint(origin, aPoint))
1151 origin.x = aPoint.x;
1152 origin.y = aPoint.y;
1154 if (origin.x != 0 || origin.y != 0)
1161 _boundsTransform = nil;
1162 _inverseBoundsTransform = nil;
1166 var index = _subviews.length;
1170 var view = _subviews[index],
1171 origin = view._frame.origin;
1173 CPDOMDisplayServerSetStyleLeftTop(view._DOMElement, _boundsTransform, origin.x, origin.y);
1177 if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1178 [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1187 - (void)setBoundsSize:(CGSize)aSize
1189 var size = _bounds.size;
1191 if (CGSizeEqualToSize(size, aSize))
1194 var frameSize = _frame.size;
1196 if (!CGSizeEqualToSize(size, frameSize))
1198 var origin = _bounds.origin;
1200 origin.x /= size.width / frameSize.width;
1201 origin.y /= size.height / frameSize.height;
1204 size.width = aSize.width;
1205 size.height = aSize.height;
1207 if (!CGSizeEqualToSize(size, frameSize))
1209 var origin = _bounds.origin;
1211 origin.x *= size.width / frameSize.width;
1212 origin.y *= size.height / frameSize.height;
1215 if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
1216 [CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
1224 - (void)resizeWithOldSuperviewSize:(CGSize)aSize
1226 var mask = [
self autoresizingMask];
1228 if (mask == CPViewNotSizable)
1231 var
frame = _superview._frame,
1232 newFrame = CGRectMakeCopy(_frame),
1233 dX = frame.size.width - aSize.width,
1234 dY = frame.size.height - aSize.height,
1235 evenFractionX = 1.0 / ((mask & CPViewMinXMargin ? 1 : 0) + (mask & CPViewWidthSizable ? 1 : 0) + (mask & CPViewMaxXMargin ? 1 : 0)),
1236 evenFractionY = 1.0 / ((mask & CPViewMinYMargin ? 1 : 0) + (mask & CPViewHeightSizable ? 1 : 0) + (mask & CPViewMaxYMargin ? 1 : 0)),
1237 baseX = (mask & CPViewMinXMargin ? _frame.origin.x : 0) +
1238 (mask & CPViewWidthSizable ? _frame.size.width : 0) +
1239 (mask & CPViewMaxXMargin ? aSize.width - _frame.size.width - _frame.origin.x : 0),
1240 baseY = (mask & CPViewMinYMargin ? _frame.origin.y : 0) +
1241 (mask & CPViewHeightSizable ? _frame.size.height : 0) +
1242 (mask & CPViewMaxYMargin ? aSize.height - _frame.size.height - _frame.origin.y : 0);
1244 if (mask & CPViewMinXMargin)
1245 newFrame.origin.x += dX * (baseX > 0 ? _frame.origin.x / baseX : evenFractionX);
1247 if (mask & CPViewWidthSizable)
1248 newFrame.size.width += dX * (baseX > 0 ? _frame.size.width / baseX : evenFractionX);
1250 if (mask & CPViewMinYMargin)
1251 newFrame.origin.y += dY * (baseY > 0 ? _frame.origin.y / baseY : evenFractionY);
1253 if (mask & CPViewHeightSizable)
1254 newFrame.size.height += dY * (baseY > 0 ? _frame.size.height / baseY : evenFractionY);
1256 [
self setFrame:newFrame];
1263 - (void)resizeSubviewsWithOldSize:(CGSize)aSize
1265 var count = _subviews.length;
1268 [_subviews[count] resizeWithOldSuperviewSize:aSize];
1278 - (void)setAutoresizesSubviews:(BOOL)aFlag
1280 _autoresizesSubviews = !!aFlag;
1287 - (BOOL)autoresizesSubviews
1289 return _autoresizesSubviews;
1296 - (void)setAutoresizingMask:(
unsigned)aMask
1298 _autoresizingMask = aMask;
1304 - (unsigned)autoresizingMask
1306 return _autoresizingMask;
1314 - (BOOL)enterFullScreenMode
1316 return [
self enterFullScreenMode:nil withOptions:nil];
1326 _fullScreenModeState = _CPViewFullScreenModeStateMake(
self);
1328 var fullScreenWindow = [[
CPWindow alloc] initWithContentRect:[[
CPPlatformWindow primaryPlatformWindow] contentBounds] styleMask:CPBorderlessWindowMask];
1330 [fullScreenWindow setLevel:CPScreenSaverWindowLevel];
1331 [fullScreenWindow setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1333 var contentView = [fullScreenWindow contentView];
1336 [contentView addSubview:self];
1338 [
self setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
1339 [
self setFrame:CGRectMakeCopy([contentView bounds])];
1341 [fullScreenWindow makeKeyAndOrderFront:self];
1343 [fullScreenWindow makeFirstResponder:self];
1345 _isInFullScreenMode = YES;
1353 - (void)exitFullScreenMode
1355 [
self exitFullScreenModeWithOptions:nil];
1362 - (void)exitFullScreenModeWithOptions:(
CPDictionary)options
1364 if (!_isInFullScreenMode)
1367 _isInFullScreenMode = NO;
1369 [
self setFrame:_fullScreenModeState.frame];
1370 [
self setAutoresizingMask:_fullScreenModeState.autoresizingMask];
1371 [_fullScreenModeState.superview _insertSubview:self atIndex:_fullScreenModeState.index];
1373 [[
self window] orderOut:self];
1379 - (BOOL)isInFullScreenMode
1381 return _isInFullScreenMode;
1388 - (void)setHidden:(BOOL)aFlag
1392 if (_isHidden === aFlag)
1400 _DOMElement.style.display = _isHidden ?
"none" :
"block";
1405 var view = [_window firstResponder];
1407 if ([view isKindOfClass:[
CPView class]])
1413 [_window makeFirstResponder:[
self nextValidKeyView]];
1417 while (view = [view superview]);
1420 [
self _notifyViewDidHide];
1424 [
self setNeedsDisplay:YES];
1425 [
self _notifyViewDidUnhide];
1429 - (void)_notifyViewDidHide
1433 var count = [_subviews count];
1436 [_subviews[count] _notifyViewDidHide];
1439 - (void)_notifyViewDidUnhide
1441 [
self viewDidUnhide];
1443 var count = [_subviews count];
1446 [_subviews[count] _notifyViewDidUnhide];
1457 - (void)setClipsToBounds:(BOOL)shouldClip
1459 if (_clipsToBounds === shouldClip)
1462 _clipsToBounds = shouldClip;
1465 _DOMElement.style.overflow = _clipsToBounds ?
"hidden" :
"visible";
1469 - (BOOL)clipsToBounds
1471 return _clipsToBounds;
1479 - (void)setAlphaValue:(
float)anAlphaValue
1481 if (_opacity == anAlphaValue)
1484 _opacity = anAlphaValue;
1490 if (anAlphaValue === 1.0)
1491 try { _DOMElement.style.removeAttribute(
"filter") }
catch (anException) { }
1493 _DOMElement.style.filter =
"alpha(opacity=" + anAlphaValue * 100 + ")";
1496 _DOMElement.style.opacity = anAlphaValue;
1514 - (BOOL)isHiddenOrHasHiddenAncestor
1518 while (view && ![view isHidden])
1519 view = [view superview];
1521 return view !== nil;
1529 return ![
self isHiddenOrHasHiddenAncestor] && [[
self window] isVisible];
1555 - (void)viewDidUnhide
1565 - (BOOL)acceptsFirstMouse:(
CPEvent)anEvent
1583 - (void)setHitTests:(BOOL)shouldHitTest
1585 _hitTests = !!shouldHitTest;
1593 - (
CPView)hitTest:(CGPoint)aPoint
1595 if (_isHidden || !_hitTests)
1599 sizeScale = [
self _hierarchyScaleSize];
1606 if (!CGRectContainsPoint(frame, aPoint))
1610 i = _subviews.length,
1611 adjustedPoint = CGPointMake(aPoint.x - CGRectGetMinX(frame), aPoint.y - CGRectGetMinY(frame));
1613 if (_inverseBoundsTransform)
1619 affineTransform.tx *= [_superview _hierarchyScaleSize].width;
1620 affineTransform.ty *= [_superview _hierarchyScaleSize].height;
1624 affineTransform.tx *= sizeScale.width;
1625 affineTransform.ty *= sizeScale.height;
1633 if (view = [_subviews[i] hitTest:adjustedPoint])
1642 - (BOOL)needsPanelToBecomeKey
1651 - (BOOL)mouseDownCanMoveWindow
1653 return ![
self isOpaque];
1656 - (void)mouseDown:(
CPEvent)anEvent
1658 if ([
self mouseDownCanMoveWindow])
1659 [
super mouseDown:anEvent];
1662 - (void)rightMouseDown:(
CPEvent)anEvent
1664 var
menu = [
self menuForEvent:anEvent];
1668 else if ([[
self nextResponder] isKindOfClass:
CPView])
1669 [
super rightMouseDown:anEvent];
1671 [[[anEvent window] platformWindow] _propagateContextMenuDOMEvent:YES];
1676 return [
self menu] || [[
self class] defaultMenu];
1683 - (void)setBackgroundColor:(
CPColor)aColor
1685 if (_backgroundColor == aColor)
1688 if (aColor == [
CPNull null])
1691 _backgroundColor = aColor;
1694 var patternImage = [_backgroundColor patternImage],
1695 colorExists = _backgroundColor && ([_backgroundColor patternImage] || [_backgroundColor alphaComponent] > 0.0),
1696 colorHasAlpha = colorExists && [_backgroundColor alphaComponent] < 1.0,
1698 colorNeedsDOMElement = colorHasAlpha && !supportsRGBA,
1702 if ([patternImage isThreePartImage])
1704 _backgroundType = [patternImage isVertical] ? BackgroundVerticalThreePartImage : BackgroundHorizontalThreePartImage;
1707 else if ([patternImage isNinePartImage])
1709 _backgroundType = BackgroundNinePartImage;
1714 _backgroundType = colorNeedsDOMElement ? BackgroundTransparentColor : BackgroundTrivialColor;
1715 amount = (colorNeedsDOMElement ? 1 : 0) - _DOMImageParts.length;
1719 if (_backgroundType === BackgroundVerticalThreePartImage || _backgroundType === BackgroundHorizontalThreePartImage || _backgroundType === BackgroundNinePartImage)
1721 slices = [patternImage imageSlices];
1724 amount = MIN(amount, slices.length);
1726 for (var i = 0, count = slices.length; i < count; i++)
1728 var image = slices[i],
1729 size = [image size];
1731 if (!size || (size.width == 0 && size.height == 0))
1734 _DOMImageSizes[i] = size;
1742 amount -= _DOMImageParts.length;
1750 var DOMElement = DOMElementPrototype.cloneNode(
false);
1752 DOMElement.style.zIndex = -1000;
1754 _DOMImageParts.push(DOMElement);
1755 _DOMElement.appendChild(DOMElement);
1762 _DOMElement.removeChild(_DOMImageParts.pop());
1765 if (_backgroundType === BackgroundTrivialColor || _backgroundType === BackgroundTransparentColor)
1767 var colorCSS = colorExists ? [_backgroundColor cssString] :
"";
1769 if (colorNeedsDOMElement)
1771 _DOMElement.style.background =
"";
1772 _DOMImageParts[0].style.background = [_backgroundColor cssString];
1775 _DOMImageParts[0].style.filter =
"alpha(opacity=" + [_backgroundColor alphaComponent] * 100 +
")";
1777 _DOMImageParts[0].style.opacity = [_backgroundColor alphaComponent];
1779 var size = [
self bounds].size;
1780 CPDOMDisplayServerSetStyleSize(_DOMImageParts[0], size.width, size.height);
1783 _DOMElement.style.background = colorCSS;
1787 var frameSize = _frame.size,
1790 for (var i = 0; i < slices.length; i++)
1792 var size = _DOMImageSizes[i];
1797 var image = slices[i];
1802 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height);
1804 _DOMImageParts[partIndex].style.background =
"url(\"" + [image filename] + "\")";
1809 try { _DOMImageParts[partIndex].style.removeAttribute(
"filter") }
catch (anException) { }
1811 _DOMImageParts[partIndex].style.opacity = 1.0;
1817 if (_backgroundType == BackgroundNinePartImage)
1819 var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1820 right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0,
1821 top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
1822 bottom = _DOMImageSizes[6] ? _DOMImageSizes[6].height : 0,
1823 width = frameSize.width - left - right,
1824 height = frameSize.height - top - bottom;
1828 if (_DOMImageSizes[0])
1830 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1833 if (_DOMImageSizes[1])
1835 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
1836 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[1].height);
1839 if (_DOMImageSizes[2])
1841 CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1844 if (_DOMImageSizes[3])
1846 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
1847 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[3].width, height);
1850 if (_DOMImageSizes[4])
1852 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, top);
1853 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, height);
1856 if (_DOMImageSizes[5])
1858 CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, top);
1859 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], _DOMImageSizes[5].width, height);
1862 if (_DOMImageSizes[6])
1864 CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1867 if (_DOMImageSizes[7])
1869 CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, left, 0.0);
1870 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, _DOMImageSizes[7].height);
1873 if (_DOMImageSizes[8])
1875 CPDOMDisplayServerSetStyleRightBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1878 else if (_backgroundType == BackgroundVerticalThreePartImage)
1880 var top = _DOMImageSizes[0] ? _DOMImageSizes[0].height : 0,
1881 bottom = _DOMImageSizes[2] ? _DOMImageSizes[2].height : 0;
1888 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1889 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, top);
1892 if (_DOMImageSizes[1])
1894 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
1895 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, frameSize.height - top - bottom);
1900 CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1901 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, bottom);
1904 else if (_backgroundType == BackgroundHorizontalThreePartImage)
1906 var left = _DOMImageSizes[0] ? _DOMImageSizes[0].width : 0,
1907 right = _DOMImageSizes[2] ? _DOMImageSizes[2].width : 0;
1914 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1915 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, frameSize.height);
1918 if (_DOMImageSizes[1])
1920 CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
1921 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width - left - right, frameSize.height);
1926 CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
1927 CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, frameSize.height);
1939 return _backgroundColor;
1949 - (CGPoint)convertPoint:(CGPoint)aPoint fromView:(
CPView)aView
1962 - (CGPoint)convertPointFromBase:(CGPoint)aPoint
1964 return [
self convertPoint:aPoint fromView:nil];
1973 - (CGPoint)convertPoint:(CGPoint)aPoint toView:(
CPView)aView
1987 - (CGPoint)convertPointToBase:(CGPoint)aPoint
1989 return [
self convertPoint:aPoint toView:nil];
1998 - (CGSize)convertSize:(CGSize)aSize fromView:(
CPView)aView
2012 - (CGSize)convertSize:(CGSize)aSize toView:(
CPView)aView
2026 - (CGRect)convertRect:(CGRect)aRect fromView:(
CPView)aView
2039 - (CGRect)convertRectFromBase:(CGRect)aRect
2041 return [
self convertRect:aRect fromView:nil];
2050 - (CGRect)convertRect:(CGRect)aRect toView:(
CPView)aView
2063 - (CGRect)convertRectToBase:(CGRect)aRect
2065 return [
self convertRect:aRect toView:nil];
2080 - (void)setPostsFrameChangedNotifications:(BOOL)shouldPostFrameChangedNotifications
2082 shouldPostFrameChangedNotifications = !!shouldPostFrameChangedNotifications;
2084 if (_postsFrameChangedNotifications === shouldPostFrameChangedNotifications)
2087 _postsFrameChangedNotifications = shouldPostFrameChangedNotifications;
2093 - (BOOL)postsFrameChangedNotifications
2095 return _postsFrameChangedNotifications;
2110 - (void)setPostsBoundsChangedNotifications:(BOOL)shouldPostBoundsChangedNotifications
2112 shouldPostBoundsChangedNotifications = !!shouldPostBoundsChangedNotifications;
2114 if (_postsBoundsChangedNotifications === shouldPostBoundsChangedNotifications)
2117 _postsBoundsChangedNotifications = shouldPostBoundsChangedNotifications;
2125 - (BOOL)postsBoundsChangedNotifications
2127 return _postsBoundsChangedNotifications;
2140 - (void)dragImage:(
CPImage)anImage at:(CGPoint)aLocation offset:(CGSize)mouseOffset event:(
CPEvent)anEvent pasteboard:(
CPPasteboard)aPasteboard source:(
id)aSourceObject slideBack:(BOOL)slideBack
2142 [_window dragImage:anImage at:[
self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2155 - (void)dragView:(
CPView)aView at:(CGPoint)aLocation offset:(CGSize)mouseOffset event:(
CPEvent)anEvent pasteboard:(
CPPasteboard)aPasteboard source:(
id)aSourceObject slideBack:(BOOL)slideBack
2157 [_window dragView:aView at:[
self convertPoint:aLocation toView:nil] offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
2164 - (void)registerForDraggedTypes:(CPArray)pasteboardTypes
2166 if (!pasteboardTypes || ![pasteboardTypes count])
2169 var theWindow = [
self window];
2171 [theWindow _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2172 [_registeredDraggedTypes addObjectsFromArray:pasteboardTypes];
2173 [theWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
2175 _registeredDraggedTypesArray = nil;
2182 - (CPArray)registeredDraggedTypes
2184 if (!_registeredDraggedTypesArray)
2185 _registeredDraggedTypesArray = [_registeredDraggedTypes allObjects];
2187 return _registeredDraggedTypesArray;
2193 - (void)unregisterDraggedTypes
2195 [[
self window] _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
2197 _registeredDraggedTypes = [CPSet set];
2198 _registeredDraggedTypesArray = [];
2205 - (void)drawRect:(CGRect)aRect
2218 - (void)scaleUnitSquareToSize:(CGSize)aSize
2224 var bounds = CGRectMakeCopy([
self bounds]);
2225 bounds.size.width *= _scaleSize.width;
2226 bounds.size.height *= _scaleSize.height;
2228 [
self willChangeValueForKey:@"scaleSize"];
2229 _scaleSize = CGSizeMakeCopy([
self scaleSize]);
2230 _scaleSize.height *= aSize.height;
2231 _scaleSize.width *= aSize.width;
2232 [
self didChangeValueForKey:@"scaleSize"];
2235 _hierarchyScaleSize = CGSizeMakeCopy([
self _hierarchyScaleSize]);
2236 _hierarchyScaleSize.height *= aSize.height;
2237 _hierarchyScaleSize.width *= aSize.width;
2242 [
self setBounds:newBounds];
2244 [_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
2251 - (void)_scaleSizeUnitSquareToSize:(CGSize)aSize
2253 _hierarchyScaleSize = CGSizeMakeCopy([_superview _hierarchyScaleSize]);
2257 _hierarchyScaleSize.width *= _scaleSize.width;
2258 _hierarchyScaleSize.height *= _scaleSize.height;
2261 [_subviews makeObjectsPerformSelector:@selector(_scaleSizeUnitSquareToSize:) withObject:aSize];
2267 - (CGSize)_hierarchyScaleSize
2269 return _hierarchyScaleSize || CGSizeMake(1.0, 1.0);
2275 - (void)_applyCSSScalingTranformations
2280 var scale = [
self scaleSize],
2284 self._DOMElement.style[browserPropertyTransform] =
'scale(' + scale.width + ', ' + scale.height + ')';
2285 self._DOMElement.style[browserPropertyTransformOrigin] =
'0 0';
2287 [
self _setDisplayServerSetStyleSize:[
self frameSize]];
2297 - (void)setNeedsDisplay:(BOOL)aFlag
2301 [
self _applyCSSScalingTranformations];
2302 [
self setNeedsDisplayInRect:[
self bounds]];
2310 - (void)setNeedsDisplayInRect:(CGRect)aRect
2312 if (!(_viewClassFlags & CPViewHasCustomDrawRect))
2315 if (CGRectIsEmpty(aRect))
2318 if (_dirtyRect && !CGRectIsEmpty(_dirtyRect))
2319 _dirtyRect = CGRectUnion(aRect, _dirtyRect);
2321 _dirtyRect = CGRectMakeCopy(aRect);
2323 _CPDisplayServerAddDisplayObject(
self);
2326 - (BOOL)needsDisplay
2328 return _dirtyRect && !CGRectIsEmpty(_dirtyRect);
2334 - (void)displayIfNeeded
2336 if ([
self needsDisplay])
2337 [
self displayRect:_dirtyRect];
2345 [
self displayRect:[
self visibleRect]];
2348 - (void)displayIfNeededInRect:(CGRect)aRect
2350 if ([
self needsDisplay])
2351 [
self displayRect:aRect];
2358 - (void)displayRect:(CGRect)aRect
2360 [
self viewWillDraw];
2362 [
self displayRectIgnoringOpacity:aRect inContext:nil];
2367 - (void)displayRectIgnoringOpacity:(CGRect)aRect inContext:(
CPGraphicsContext)aGraphicsContext
2369 if ([
self isHidden])
2377 [
self drawRect:aRect];
2382 - (void)viewWillDraw
2391 if (!_graphicsContext)
2396 var width = CGRectGetWidth(_frame),
2397 height = CGRectGetHeight(_frame);
2399 _DOMContentsElement = graphicsPort.DOMElement;
2401 _DOMContentsElement.style.zIndex = -100;
2403 _DOMContentsElement.style.overflow =
"hidden";
2404 _DOMContentsElement.style.position =
"absolute";
2405 _DOMContentsElement.style.visibility =
"visible";
2407 CPDOMDisplayServerSetSize(_DOMContentsElement, width, height);
2409 CPDOMDisplayServerSetStyleLeftTop(_DOMContentsElement, NULL, 0.0, 0.0);
2410 CPDOMDisplayServerSetStyleSize(_DOMContentsElement, width, height);
2415 _DOMElement.style.webkitTransform =
'translateX(0)';
2417 CPDOMDisplayServerAppendChild(_DOMElement, _DOMContentsElement);
2437 - (void)setNeedsLayout
2439 if (!(_viewClassFlags & CPViewHasCustomLayoutSubviews))
2444 _CPDisplayServerAddLayoutObject(
self);
2447 - (void)layoutIfNeeded
2453 [
self layoutSubviews];
2457 - (void)layoutSubviews
2472 - (CGRect)visibleRect
2477 return CGRectIntersection([
self convertRect:[_superview visibleRect] fromView:_superview], _bounds);
2484 var superview = _superview,
2487 while (superview && ![superview isKindOfClass:clipViewClass])
2488 superview = superview._superview;
2497 - (void)scrollPoint:(CGPoint)aPoint
2499 var clipView = [
self _enclosingClipView];
2504 [clipView scrollToPoint:[
self convertPoint:aPoint toView:clipView]];
2512 - (BOOL)scrollRectToVisible:(CGRect)aRect
2515 aRect = CGRectIntersection(aRect, _bounds);
2518 if (CGRectIsEmpty(aRect))
2521 var enclosingClipView = [
self _enclosingClipView];
2524 if (!enclosingClipView)
2527 var documentView = [enclosingClipView documentView];
2534 var documentViewVisibleRect = [documentView visibleRect],
2535 rectInDocumentView = [
self convertRect:aRect toView:documentView];
2538 if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView))
2541 var scrollPoint = CGPointMakeCopy(documentViewVisibleRect.origin);
2544 if (CGRectGetMinX(rectInDocumentView) < CGRectGetMinX(documentViewVisibleRect))
2545 scrollPoint.x = CGRectGetMinX(rectInDocumentView);
2546 else if (CGRectGetMaxX(rectInDocumentView) > CGRectGetMaxX(documentViewVisibleRect))
2547 scrollPoint.x += CGRectGetMaxX(rectInDocumentView) - CGRectGetMaxX(documentViewVisibleRect);
2549 if (CGRectGetMinY(rectInDocumentView) < CGRectGetMinY(documentViewVisibleRect))
2550 scrollPoint.y = CGRectGetMinY(rectInDocumentView);
2551 else if (CGRectGetMaxY(rectInDocumentView) > CGRectGetMaxY(documentViewVisibleRect))
2552 scrollPoint.y += CGRectGetMaxY(rectInDocumentView) - CGRectGetMaxY(documentViewVisibleRect);
2554 [enclosingClipView scrollToPoint:scrollPoint];
2562 - (BOOL)autoscroll:(
CPEvent)anEvent
2564 return [[
self superview] autoscroll:anEvent];
2573 - (CGRect)adjustScroll:(CGRect)proposedVisibleRect
2575 return proposedVisibleRect;
2581 - (void)scrollRect:(CGRect)aRect by:(
float)anAmount
2592 var superview = _superview,
2595 while (superview && ![superview isKindOfClass:scrollViewClass])
2596 superview = superview._superview;
2606 - (void)scrollClipView:(
CPClipView)aClipView toPoint:(CGPoint)aPoint
2608 [aClipView scrollToPoint:aPoint];
2616 - (void)reflectScrolledClipView:(
CPClipView)aClipView
2623 - (BOOL)inLiveResize
2625 return _inLiveResize;
2637 - (void)viewWillStartLiveResize
2639 _inLiveResize = YES;
2652 - (void)viewDidEndLiveResize
2659 @implementation CPView (KeyView)
2675 - (BOOL)performKeyEquivalent:(
CPEvent)anEvent
2677 var count = [_subviews count];
2681 if ([_subviews[count] performKeyEquivalent:anEvent])
2687 - (BOOL)canBecomeKeyView
2689 return [
self acceptsFirstResponder] && ![
self isHiddenOrHasHiddenAncestor];
2694 return _nextKeyView;
2697 - (
CPView)nextValidKeyView
2699 var result = [
self nextKeyView],
2700 resultUID = [result UID],
2701 unsuitableResults = {};
2703 while (result && ![result canBecomeKeyView])
2705 unsuitableResults[resultUID] = 1;
2706 result = [result nextKeyView];
2708 resultUID = [result UID];
2711 if (unsuitableResults[resultUID])
2718 - (
CPView)previousKeyView
2720 return _previousKeyView;
2723 - (
CPView)previousValidKeyView
2725 var result = [
self previousKeyView],
2726 firstResult = result;
2728 while (result && ![result canBecomeKeyView])
2730 result = [result previousKeyView];
2733 if (result === firstResult)
2740 - (void)_setPreviousKeyView:(
CPView)previous
2744 var previousWindow = [previous window];
2746 if (!previousWindow || previousWindow === _window)
2748 _previousKeyView = previous;
2753 _previousKeyView = nil;
2756 - (void)setNextKeyView:(
CPView)next
2758 if (![next isEqual:
self])
2760 var nextWindow = [next window];
2762 if (!nextWindow || nextWindow === _window)
2764 _nextKeyView = next;
2765 [_nextKeyView _setPreviousKeyView:self];
2775 @implementation CPView (CoreAnimationAdditions)
2780 - (void)setLayer:(
CALayer)aLayer
2782 if (_layer == aLayer)
2787 _layer._owningView = nil;
2789 _DOMElement.removeChild(_layer._DOMElement);
2797 var bounds = CGRectMakeCopy([
self bounds]);
2799 [_layer _setOwningView:self];
2802 _layer._DOMElement.style.zIndex = 100;
2804 _DOMElement.appendChild(_layer._DOMElement);
2821 - (void)setWantsLayer:(BOOL)aFlag
2823 _wantsLayer = !!aFlag;
2838 @implementation CPView (Scaling)
2845 - (void)setScaleSize:(CGSize)aSize
2847 if (CGSizeEqualToSize(_scaleSize, aSize))
2850 var size = CGSizeMakeZero(),
2851 scale = CGSizeMakeCopy([
self scaleSize]);
2853 size.height = aSize.height / scale.height;
2854 size.width = aSize.width / scale.width;
2856 [
self scaleUnitSquareToSize:size];
2857 [
self setNeedsDisplay:YES];
2866 return _scaleSize || CGSizeMake(1.0, 1.0);
2871 @implementation CPView (Theming)
2872 #pragma mark Theme States
2874 - (unsigned)themeState
2879 - (BOOL)hasThemeState:(CPThemeState)aState
2882 if (aState === CPThemeStateNormal && _themeState === CPThemeStateNormal)
2885 return !!(_themeState & ((typeof aState ===
"string") ? CPThemeState(aState) : aState));
2888 - (BOOL)setThemeState:(CPThemeState)aState
2890 var newState = (typeof aState ===
"string") ? CPThemeState(aState) : aState;
2892 if (_themeState & newState)
2895 _themeState |= newState;
2897 [
self setNeedsLayout];
2898 [
self setNeedsDisplay:YES];
2903 - (BOOL)unsetThemeState:(CPThemeState)aState
2905 var newState = ((typeof aState ===
"string") ? CPThemeState(aState) : aState);
2907 if (!(_themeState & newState))
2910 _themeState &= ~newState;
2912 [
self setNeedsLayout];
2913 [
self setNeedsDisplay:YES];
2918 #pragma mark Theme Attributes
2920 + (CPString)defaultThemeClass
2925 - (CPString)themeClass
2930 return [[
self class] defaultThemeClass];
2933 - (void)setThemeClass:(CPString)theClass
2935 _themeClass = theClass;
2937 [
self _loadThemeAttributes];
2939 [
self setNeedsLayout];
2940 [
self setNeedsDisplay:YES];
2948 + (CPArray)_themeAttributes
2950 if (!CachedThemeAttributes)
2951 CachedThemeAttributes = {};
2953 var theClass = [
self class],
2954 CPViewClass = [
CPView class],
2958 for (; theClass && theClass !== CPViewClass; theClass = [theClass superclass])
2960 var cachedAttributes = CachedThemeAttributes[class_getName(theClass)];
2962 if (cachedAttributes)
2964 attributes = attributes.length ? attributes.concat(cachedAttributes) : attributes;
2965 CachedThemeAttributes[[
self className]] = attributes;
2970 var attributeDictionary = [theClass themeAttributes];
2972 if (!attributeDictionary)
2975 var attributeKeys = [attributeDictionary allKeys],
2976 attributeCount = attributeKeys.length;
2978 while (attributeCount--)
2980 var attributeName = attributeKeys[attributeCount],
2981 attributeValue = [attributeDictionary objectForKey:attributeName];
2983 attributes.push(attributeValue === nullValue ? nil : attributeValue);
2984 attributes.push(attributeName);
2991 - (void)_loadThemeAttributes
2993 var theClass = [
self class],
2994 attributes = [theClass _themeAttributes],
2995 count = attributes.length;
3000 var theme = [
self theme],
3001 themeClass = [
self themeClass];
3003 _themeAttributes = {};
3007 var attributeName = attributes[count--],
3008 attribute = [[_CPThemeAttribute alloc] initWithName:attributeName defaultValue:attributes[count]];
3010 [attribute setParentAttribute:[theme attributeWithName:attributeName forClass:themeClass]];
3012 _themeAttributes[attributeName] = attribute;
3016 - (void)setTheme:(
CPTheme)aTheme
3018 if (_theme === aTheme)
3023 [
self viewDidChangeTheme];
3026 - (void)_setThemeIncludingDescendants:(
CPTheme)aTheme
3028 [
self setTheme:aTheme];
3029 [[
self subviews] makeObjectsPerformSelector:@selector(_setThemeIncludingDescendants:) withObject:aTheme];
3037 - (void)viewDidChangeTheme
3039 if (!_themeAttributes)
3042 var theme = [
self theme],
3043 themeClass = [
self themeClass];
3045 for (var attributeName in _themeAttributes)
3046 if (_themeAttributes.hasOwnProperty(attributeName))
3047 [_themeAttributes[attributeName] setParentAttribute:[theme attributeWithName:attributeName forClass:themeClass]];
3049 [
self setNeedsLayout];
3050 [
self setNeedsDisplay:YES];
3055 var dictionary = @{};
3057 if (_themeAttributes)
3059 var theme = [
self theme];
3061 for (var attributeName in _themeAttributes)
3062 if (_themeAttributes.hasOwnProperty(attributeName))
3063 [dictionary setObject:_themeAttributes[attributeName] forKey:attributeName];
3069 - (void)setValue:(
id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState
3071 if (!_themeAttributes || !_themeAttributes[aName])
3072 [
CPException raise:CPInvalidArgumentException
reason:[
self className] + " does not contain theme attribute '" + aName + "'"];
3074 var currentValue = [
self currentValueForThemeAttribute:aName];
3076 [_themeAttributes[aName] setValue:aValue forState:aState];
3078 if ([
self currentValueForThemeAttribute:aName] === currentValue)
3081 [
self setNeedsDisplay:YES];
3082 [
self setNeedsLayout];
3085 - (void)setValue:(
id)aValue forThemeAttribute:(CPString)aName
3087 if (!_themeAttributes || !_themeAttributes[aName])
3088 [
CPException raise:CPInvalidArgumentException
reason:[
self className] + " does not contain theme attribute '" + aName + "'"];
3090 var currentValue = [
self currentValueForThemeAttribute:aName];
3092 [_themeAttributes[aName] setValue:aValue];
3094 if ([
self currentValueForThemeAttribute:aName] === currentValue)
3097 [
self setNeedsDisplay:YES];
3098 [
self setNeedsLayout];
3101 - (id)valueForThemeAttribute:(CPString)aName inState:(CPThemeState)aState
3103 if (!_themeAttributes || !_themeAttributes[aName])
3104 [
CPException raise:CPInvalidArgumentException
reason:[
self className] + " does not contain theme attribute '" + aName + "'"];
3106 return [_themeAttributes[aName] valueForState:aState];
3109 - (id)valueForThemeAttribute:(CPString)aName
3111 if (!_themeAttributes || !_themeAttributes[aName])
3112 [
CPException raise:CPInvalidArgumentException
reason:[
self className] + " does not contain theme attribute '" + aName + "'"];
3114 return [_themeAttributes[aName] value];
3117 - (id)currentValueForThemeAttribute:(CPString)aName
3119 if (!_themeAttributes || !_themeAttributes[aName])
3120 [
CPException raise:CPInvalidArgumentException
reason:[
self className] + " does not contain theme attribute '" + aName + "'"];
3122 return [_themeAttributes[aName] valueForState:_themeState];
3125 - (BOOL)hasThemeAttribute:(CPString)aName
3127 return (_themeAttributes && _themeAttributes[aName] !== undefined);
3138 - (void)registerThemeValues:(CPArray)themeValues
3140 for (var i = 0; i < themeValues.length; ++i)
3142 var attributeValueState = themeValues[i],
3143 attribute = attributeValueState[0],
3144 value = attributeValueState[1],
3145 state = attributeValueState[2];
3148 [
self setValue:value forThemeAttribute:attribute inState:state];
3150 [
self setValue:value forThemeAttribute:attribute];
3164 - (void)registerThemeValues:(CPArray)themeValues inherit:(CPArray)inheritedValues
3167 if (inheritedValues)
3168 [
self registerThemeValues:inheritedValues];
3171 [
self registerThemeValues:themeValues];
3174 - (
CPView)createEphemeralSubviewNamed:(CPString)aViewName
3179 - (CGRect)rectForEphemeralSubviewNamed:(CPString)aViewName
3181 return CGRectMakeZero();
3184 - (
CPView)layoutEphemeralSubviewNamed:(CPString)aViewName
3185 positioned:(CPWindowOrderingMode)anOrderingMode
3186 relativeToEphemeralSubviewNamed:(CPString)relativeToViewName
3188 if (!_ephemeralSubviewsForNames)
3190 _ephemeralSubviewsForNames = {};
3191 _ephemeralSubviews = [CPSet set];
3194 var frame = [
self rectForEphemeralSubviewNamed:aViewName];
3198 if (!_ephemeralSubviewsForNames[aViewName])
3200 _ephemeralSubviewsForNames[aViewName] = [
self createEphemeralSubviewNamed:aViewName];
3202 [_ephemeralSubviews addObject:_ephemeralSubviewsForNames[aViewName]];
3204 if (_ephemeralSubviewsForNames[aViewName])
3205 [
self addSubview:_ephemeralSubviewsForNames[aViewName] positioned:anOrderingMode relativeTo:_ephemeralSubviewsForNames[relativeToViewName]];
3208 if (_ephemeralSubviewsForNames[aViewName])
3209 [_ephemeralSubviewsForNames[aViewName] setFrame:frame];
3211 else if (_ephemeralSubviewsForNames[aViewName])
3213 [_ephemeralSubviewsForNames[aViewName] removeFromSuperview];
3215 [_ephemeralSubviews removeObject:_ephemeralSubviewsForNames[aViewName]];
3216 delete _ephemeralSubviewsForNames[aViewName];
3219 return _ephemeralSubviewsForNames[aViewName];
3222 - (
CPView)ephemeralSubviewNamed:(CPString)aViewName
3224 if (!_ephemeralSubviewsForNames)
3227 return (_ephemeralSubviewsForNames[aViewName] || nil);
3232 var CPViewAutoresizingMaskKey =
@"CPViewAutoresizingMask",
3233 CPViewAutoresizesSubviewsKey =
@"CPViewAutoresizesSubviews",
3234 CPViewBackgroundColorKey =
@"CPViewBackgroundColor",
3235 CPViewBoundsKey =
@"CPViewBoundsKey",
3236 CPViewFrameKey =
@"CPViewFrameKey",
3237 CPViewHitTestsKey =
@"CPViewHitTestsKey",
3238 CPViewToolTipKey =
@"CPViewToolTipKey",
3239 CPViewIsHiddenKey =
@"CPViewIsHiddenKey",
3240 CPViewOpacityKey =
@"CPViewOpacityKey",
3241 CPViewSubviewsKey =
@"CPViewSubviewsKey",
3242 CPViewSuperviewKey =
@"CPViewSuperviewKey",
3243 CPViewTagKey =
@"CPViewTagKey",
3244 CPViewThemeClassKey =
@"CPViewThemeClassKey",
3245 CPViewThemeStateKey =
@"CPViewThemeStateKey",
3246 CPViewWindowKey =
@"CPViewWindowKey",
3247 CPViewNextKeyViewKey =
@"CPViewNextKeyViewKey",
3248 CPViewPreviousKeyViewKey =
@"CPViewPreviousKeyViewKey",
3249 CPReuseIdentifierKey =
@"CPReuseIdentifierKey",
3250 CPViewScaleKey =
@"CPViewScaleKey",
3251 CPViewSizeScaleKey =
@"CPViewSizeScaleKey",
3252 CPViewIsScaledKey =
@"CPViewIsScaledKey";
3254 @implementation CPView (CPCoding)
3261 - (id)initWithCoder:(
CPCoder)aCoder
3268 _DOMElement = DOMElementPrototype.cloneNode(
false);
3269 AppKitTagDOMElement(
self, _DOMElement);
3273 _frame = [aCoder decodeRectForKey:CPViewFrameKey];
3274 _bounds = [aCoder decodeRectForKey:CPViewBoundsKey];
3276 self = [
super initWithCoder:aCoder];
3281 _tag = [aCoder containsValueForKey:CPViewTagKey] ? [aCoder decodeIntForKey:CPViewTagKey] : -1;
3282 _identifier = [aCoder decodeObjectForKey:CPReuseIdentifierKey];
3284 _window = [aCoder decodeObjectForKey:CPViewWindowKey];
3285 _superview = [aCoder decodeObjectForKey:CPViewSuperviewKey];
3291 var subviews = [aCoder decodeObjectForKey:CPViewSubviewsKey] || [];
3293 for (var i = 0, count = [subviews count]; i < count; ++i)
3296 subviews[i]._superview = nil;
3297 [
self addSubview:subviews[i]];
3301 _registeredDraggedTypes = [CPSet set];
3302 _registeredDraggedTypesArray = [];
3306 if (_autoresizingMask === nil)
3307 _autoresizingMask = [aCoder decodeIntForKey:CPViewAutoresizingMaskKey] || CPViewNotSizable;
3309 _autoresizesSubviews = ![aCoder containsValueForKey:CPViewAutoresizesSubviewsKey] || [aCoder decodeBoolForKey:CPViewAutoresizesSubviewsKey];
3311 _hitTests = ![aCoder containsValueForKey:CPViewHitTestsKey] || [aCoder decodeBoolForKey:CPViewHitTestsKey];
3313 [
self _setupToolTipHandlers];
3314 _toolTip = [aCoder decodeObjectForKey:CPViewToolTipKey];
3317 [
self _installToolTipEventHandlers];
3319 _scaleSize = [aCoder containsValueForKey:CPViewScaleKey] ? [aCoder decodeSizeForKey:CPViewScaleKey] : CGSizeMake(1.0, 1.0);
3320 _hierarchyScaleSize = [aCoder containsValueForKey:CPViewSizeScaleKey] ? [aCoder decodeSizeForKey:CPViewSizeScaleKey] : CGSizeMake(1.0, 1.0);
3321 _isScaled = [aCoder containsValueForKey:CPViewIsScaledKey] ? [aCoder decodeBoolForKey:CPViewIsScaledKey] : NO;
3325 _DOMImageParts = [];
3326 _DOMImageSizes = [];
3328 CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, CGRectGetMinX(_frame), CGRectGetMinY(_frame));
3329 [
self _setDisplayServerSetStyleSize:_frame.size];
3332 count = _subviews.length;
3334 for (; index < count; ++index)
3336 CPDOMDisplayServerAppendChild(_DOMElement, _subviews[index]._DOMElement);
3341 [
self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]];
3343 if ([aCoder containsValueForKey:CPViewOpacityKey])
3344 [
self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]];
3348 [
self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]];
3349 [
self _setupViewFlags];
3351 _theme = [
CPTheme defaultTheme];
3352 _themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
3353 _themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
3354 _themeAttributes = {};
3356 var theClass = [
self class],
3357 themeClass = [
self themeClass],
3358 attributes = [theClass _themeAttributes],
3359 count = attributes.length;
3363 var attributeName = attributes[count--];
3365 _themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass);
3368 [
self setNeedsDisplay:YES];
3369 [
self setNeedsLayout];
3379 - (void)encodeWithCoder:(
CPCoder)aCoder
3381 [
super encodeWithCoder:aCoder];
3384 [aCoder encodeInt:_tag forKey:CPViewTagKey];
3386 [aCoder encodeRect:_frame forKey:CPViewFrameKey];
3387 [aCoder encodeRect:_bounds forKey:CPViewBoundsKey];
3390 if (_window !== nil)
3391 [aCoder encodeConditionalObject:_window forKey:CPViewWindowKey];
3393 var count = [_subviews count],
3394 encodedSubviews = _subviews;
3396 if (count > 0 && [_ephemeralSubviews count] > 0)
3398 encodedSubviews = [encodedSubviews copy];
3401 if ([_ephemeralSubviews containsObject:encodedSubviews[count]])
3402 encodedSubviews.splice(count, 1);
3405 if (encodedSubviews.length > 0)
3406 [aCoder encodeObject:encodedSubviews forKey:CPViewSubviewsKey];
3409 if (_superview !== nil)
3410 [aCoder encodeConditionalObject:_superview forKey:CPViewSuperviewKey];
3412 if (_autoresizingMask !== CPViewNotSizable)
3413 [aCoder encodeInt:_autoresizingMask forKey:CPViewAutoresizingMaskKey];
3415 if (!_autoresizesSubviews)
3416 [aCoder encodeBool:_autoresizesSubviews forKey:CPViewAutoresizesSubviewsKey];
3418 if (_backgroundColor !== nil)
3419 [aCoder encodeObject:_backgroundColor forKey:CPViewBackgroundColorKey];
3421 if (_hitTests !== YES)
3422 [aCoder encodeBool:_hitTests forKey:CPViewHitTestsKey];
3424 if (_opacity !== 1.0)
3425 [aCoder encodeFloat:_opacity forKey:CPViewOpacityKey];
3428 [aCoder encodeBool:_isHidden forKey:CPViewIsHiddenKey];
3431 [aCoder encodeObject:_toolTip forKey:CPViewToolTipKey];
3433 var nextKeyView = [
self nextKeyView];
3435 if (nextKeyView !== nil && ![nextKeyView isEqual:
self])
3436 [aCoder encodeConditionalObject:nextKeyView forKey:CPViewNextKeyViewKey];
3438 var previousKeyView = [
self previousKeyView];
3440 if (previousKeyView !== nil && ![previousKeyView isEqual:
self])
3441 [aCoder encodeConditionalObject:previousKeyView forKey:CPViewPreviousKeyViewKey];
3443 [aCoder encodeObject:[
self themeClass] forKey:CPViewThemeClassKey];
3444 [aCoder encodeInt:CPThemeStateName(_themeState) forKey:CPViewThemeStateKey];
3446 for (var attributeName in _themeAttributes)
3447 if (_themeAttributes.hasOwnProperty(attributeName))
3448 CPThemeAttributeEncode(aCoder, _themeAttributes[attributeName]);
3451 [aCoder encodeObject:_identifier forKey:CPReuseIdentifierKey];
3453 [aCoder encodeSize:[
self scaleSize] forKey:CPViewScaleKey];
3454 [aCoder encodeSize:[
self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
3455 [aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
3460 var _CPViewFullScreenModeStateMake =
function(aView)
3462 var superview = aView._superview;
3464 return { autoresizingMask:aView._autoresizingMask, frame:CGRectMakeCopy(aView._frame), index:(superview ? [superview._subviews indexOfObjectIdenticalTo:aView] : 0), superview:superview };
3467 var _CPViewGetTransform =
function( fromView, toView)
3476 var view = fromView;
3481 while (view && view != toView)
3483 var frame = view._frame;
3491 transform.tx += CGRectGetMinX(frame);
3492 transform.ty += CGRectGetMinY(frame);
3494 if (view._boundsTransform)
3507 view = view._superview;
3511 if (view === toView)
3515 else if (fromView && toView)
3517 fromWindow = [fromView window];
3518 toWindow = [toView window];
3520 if (fromWindow && toWindow && fromWindow !== toWindow)
3529 while (view && view != fromView)
3531 var frame = CGRectMakeCopy(view._frame);
3536 transform2.a *= 1 / view._scaleSize.width;
3537 transform2.d *= 1 / view._scaleSize.height;
3540 transform2.tx += CGRectGetMinX(frame) * transform2.a;
3541 transform2.ty += CGRectGetMinY(frame) * transform2.d;
3543 if (view._boundsTransform)
3546 inverseBoundsTransform.tx -= view._inverseBoundsTransform.tx * transform2.a;
3547 inverseBoundsTransform.ty -= view._inverseBoundsTransform.ty * transform2.d;
3552 view = view._superview;
3555 transform2.tx = -transform2.tx;
3556 transform2.ty = -transform2.ty;
3558 if (view === fromView)
3592 @implementation CPView (CPSynthesizedAccessors)
3597 - (CPString)identifier
3605 - (void)setIdentifier:(CPString)aValue
3607 _identifier = aValue;