diff --git a/AppKit/CPView.j b/AppKit/CPView.j index ae8aeb595..e67dd263b 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -238,6 +238,11 @@ var CPViewFlags = { }, return [CPSet setWithObjects:@"frameOrigin", @"frameSize"]; } ++ (CPSet)keyPathsForValuesAffectingBounds +{ + return [CPSet setWithObjects:@"boundsOrigin", @"boundsSize"]; +} + - (id)init { return [self initWithFrame:CGRectMakeZero()]; @@ -308,7 +313,7 @@ var CPViewFlags = { }, */ - (CPArray)subviews { - return _subviews; + return [_subviews copy]; } /*! @@ -441,7 +446,7 @@ var CPViewFlags = { }, [_superview willRemoveSubview:self]; - [[_superview subviews] removeObject:self]; + [_superview._subviews removeObject:self]; #if PLATFORM(DOM) CPDOMDisplayServerRemoveChild(_superview._DOMElement, _DOMElement); @@ -468,6 +473,73 @@ var CPViewFlags = { }, [self _insertSubview:aView atIndex:index]; } +- (void)setSubviews:(CPArray)newSubviews +{ + if (!newSubviews) + [CPException raise:CPInvalidArgumentException reason:"newSubviews cannot be nil in -[CPView setSubviews:]"]; + + // Trivial Case 0: Same array somehow + if ([_subviews isEqual:newSubviews]) + return; + + // Trivial Case 1: No current subviews, simply add all new subviews. + if ([_subviews count] === 0) + { + var index = 0, + count = [newSubviews count]; + + for (; index < count; ++index) + [self addSubview:newSubviews[index]]; + + return; + } + + // Trivial Case 2: No new subviews, simply remove all current subviews. + if ([newSubviews count] === 0) + { + var count = [subviews count]; + + while (count--) + [_subviews[count] removeFromSuperview]; + + return; + } + + // Find out the views that were removed. + var removedSubviews = [CPMutableSet setWithArray:_subviews]; + + [removedSubviews removeObjectsInArray:newSubviews]; + [removedSubviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + // Find out which views need to be added. + var addedSubviews = [CPMutableSet setWithArray:newSubviews]; + + [addedSubviews removeObjectsInArray:_subviews]; + + var addedSubview = nil, + addedSubviewEnumerator = [addedSubviews objectEnumerator]; + + while (addedSubview = [addedSubviewEnumerator nextObject]) + [self addSubview:addedSubview]; + + // If the order is fine, no need to reorder. + if ([_subviews isEqual:newSubviews]) + return; + + _subviews = [newSubviews copy]; + + var index = 0, + count = [_subviews count]; + + for (; index < count; ++index) + { + var subview = _subviews[index]; + + CPDOMDisplayServerRemoveChild(_DOMElement, subview._DOMElement); + CPDOMDisplayServerAppendChild(_DOMElement, subview._DOMElement); + } +} + /* @ignore */ - (void)_setWindow:(CPWindow)aWindow { @@ -816,6 +888,16 @@ var CPViewFlags = { }, return _CGRectMakeCopy(_bounds); } +- (CGPoint)boundsOrigin +{ + return _CGPointMakeCopy(_bounds.origin); +} + +- (CGSize)boundsSize +{ + return _CGSizeMakeCopy(_bounds.size); +} + /*! Sets the location of the receiver inside its frame. The method posts a CPViewBoundsDidChangeNotification to the @@ -1863,12 +1945,11 @@ setBoundsOrigin: - (BOOL)performKeyEquivalent:(CPEvent)anEvent { - var subviews = [self subviews], - count = [subviews count]; + var count = [_subviews count]; // Is reverse iteration correct here? It matches the other (correct) code like hit testing. while (count--) - if ([subviews[count] performKeyEquivalent:anEvent]) + if ([_subviews[count] performKeyEquivalent:anEvent]) return YES; return NO; diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index c3f1fe0db..59f1c8c20 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -1999,7 +1999,8 @@ CPTexturedBackgroundWindowMask - (void)_setUpMasksForView:(CPView)aView { - var views = [CPArray arrayWithArray:[aView subviews]]; + var views = [aView subviews]; + [views addObject:aView]; for (var i = 0, count = [views count]; i < count; i++) @@ -2014,7 +2015,8 @@ CPTexturedBackgroundWindowMask - (void)_restoreMasksForView:(CPView)aView { - var views = [CPArray arrayWithArray:[aView subviews]]; + var views = [aView subviews]; + [views addObject:aView]; for (var i = 0, count = [views count]; i < count; i++) diff --git a/AppKit/Cib/_CPCibCustomView.j b/AppKit/Cib/_CPCibCustomView.j index 808cf85fc..e50f0cb58 100644 --- a/AppKit/Cib/_CPCibCustomView.j +++ b/AppKit/Cib/_CPCibCustomView.j @@ -37,7 +37,13 @@ - (void)setCustomClassName:(CPString)aClassName { + if (_className === aClassName) + return; + _className = aClassName; + + [self setNeedsDisplay:YES]; + [self setNeedsLayout]; } @end @@ -97,9 +103,7 @@ var _CPCibCustomViewClassNameKey = @"_CPCibCustomViewClassNameKey"; [view setBounds:[self bounds]]; // Since the object replacement logic hasn't had a chance to kick in yet, we need to do it manually: - - // we need to copy subviews since each time we add a subview to a different view its removed from the original subviews array - var subviews = [[self subviews] copy], + var subviews = [self subviews], index = 0, count = subviews.length; diff --git a/AppKit/Platform/CPPlatformWindow.j b/AppKit/Platform/CPPlatformWindow.j index 7c665e9bf..fa1917281 100644 --- a/AppKit/Platform/CPPlatformWindow.j +++ b/AppKit/Platform/CPPlatformWindow.j @@ -104,7 +104,7 @@ var PrimaryPlatformWindow = NULL; frame.origin = CGPointMakeZero(); - if ([CPMenu menuBarVisible]) + if ([CPMenu menuBarVisible] && [CPPlatformWindow primaryPlatformWindow] === self) { var menuBarHeight = [[CPApp mainMenu] menuBarHeight]; diff --git a/Foundation/CPObject.j b/Foundation/CPObject.j index d8e90512c..70a5bc23d 100644 --- a/Foundation/CPObject.j +++ b/Foundation/CPObject.j @@ -470,12 +470,12 @@ CPLog(@"Got some class: %@", inst); return [self UID]; } -- (unsigned)UID +- (CPString)UID { if (typeof self.__address === "undefined") self.__address = _objj_generateObjectHash(); - return __address; + return __address + ""; } /*!