From 0a20f77b0862696a3a93634eec0c106042f634e5 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 13 Jun 2015 21:06:17 +0200 Subject: [PATCH 1/9] FIXED: In CPView, the transformation matrix was set at each drawing pass, even if the matrix was the identity matrix. Now we check if the highDPI ratio is == 1 and skip the setTransform call in this case. --- AppKit/CPView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 36ed408bb..bf90801d4 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -2594,7 +2594,7 @@ setBoundsOrigin: } #if PLATFORM(DOM) - if (_needToSetTransformMatrix) + if (_needToSetTransformMatrix && _highDPIRatio !== 1) [_graphicsContext graphicsPort].setTransform(_highDPIRatio, 0, 0 , _highDPIRatio, 0, 0); #endif From 42c3c7bc48624a688a5903f831a8b312032073cd Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 25 Aug 2015 16:46:00 -0700 Subject: [PATCH 2/9] Fixed: crash when using a viewBased CPTableView with appearance Previously, when using a viewBased CPTableView Cappuccino just crashed. This was due to the new appearance feature. Indeed, at the end of the method initWithCoder: of CPView, we set the appearance of the current view and the themeStates of the view and its subviews. For an unknown reason some of these subviews were not completely initialized (see comment line 3742), this made crashed cappuccino because _themeState was null. To fix this issue, we send the method setAppearance when the current stack was performed. (Magic setTimeout...). This is for sure not the ultimate best fix, but it's prevent to have a broken master. We will need in the future to fix this issue in a better way. --- AppKit/CPView.j | 10 ++++++- AppKit/CPVisualEffectView.j | 53 +++---------------------------------- 2 files changed, 13 insertions(+), 50 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index d40d1ad6f..ca467a1d0 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -3737,7 +3737,15 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass); } - [self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]]; + var appearance = [aCoder decodeObjectForKey:CPViewAppearanceKey]; + + // TODO : find a way to fix this horrible things + // We only set the appearance here when everything and every subviews were unarchived. + // Otherwise this causes a crash with some subviews not unarchived but already created (how ? init is not called, neither initWithFrame or initWithCoder) in the coder (I have no idea why these views are present in _objects of the coder) + // To reproduce, uncomment the timeout and open the test Tests/Manual/TableTests/ViewBasedCib + window.setTimeout(function() { + [self setAppearance:appearance]; + },0); [self setNeedsDisplay:YES]; [self setNeedsLayout]; diff --git a/AppKit/CPVisualEffectView.j b/AppKit/CPVisualEffectView.j index ece566562..2618b611f 100644 --- a/AppKit/CPVisualEffectView.j +++ b/AppKit/CPVisualEffectView.j @@ -89,7 +89,8 @@ CPVisualEffectStateInactive = 2; [CPException raise:CPInvalidArgumentException reason:"Appearance can only be CPAppearanceNameVibrantDark or CPAppearanceNameVibrantLight in CPVisualEffectView, but is " + anAppearance]; [super setAppearance:anAppearance]; - [self _applyVibrancyState]; + + [self setNeedsLayout:YES]; } /*! Sets the received effect state. @@ -109,7 +110,7 @@ CPVisualEffectStateInactive = 2; _state = aState; [self didChangeValueForKey:"state"]; - [self _applyVibrancyState]; + [self setNeedsLayout:YES]; } @@ -131,7 +132,7 @@ CPVisualEffectStateInactive = 2; } -- (void)_applyVibrancyState +- (void)layoutSubviews { switch (_state) { @@ -155,52 +156,6 @@ CPVisualEffectStateInactive = 2; } -#pragma mark - -#pragma mark Overrides - -- (BOOL)setThemeState:(ThemeState)aState -{ - if (aState.isa && [aState isKindOfClass:CPArray]) - aState = CPThemeState.apply(null, aState); - - var r = [super setThemeState:aState]; - - if (r) - [self _applyVibrancyState]; - - return r; -} - -- (BOOL)unsetThemeState:(ThemeState)aState -{ - if (aState.isa && [aState isKindOfClass:CPArray]) - aState = CPThemeState.apply(null, aState); - - var r = [super unsetThemeState:aState]; - - if (r) - [self _applyVibrancyState]; - - return r; -} - -- (void)viewDidMoveToSuperview -{ - [super viewDidMoveToSuperview]; - - if (_superview) - [self _applyVibrancyState]; -} - -- (void)viewDidMoveToWindow -{ - [super viewDidMoveToWindow]; - - if (_window) - [self _applyVibrancyState]; -} - - #pragma mark - #pragma mark CPCoding From b30103c790bed4cbb259eaef6c98796c894b5d98 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Fri, 28 Aug 2015 11:11:28 -0700 Subject: [PATCH 3/9] New: added methods viewWillLayout and viewDidLayout Previously, when a view was about to layout, only layoutSubviews was called. Now the methods viewWillLayout and viewDidLayout are called as well. This is like in Cocoa. This PR fixed the issue with the appearance and the view based tableView. We now handle everything related with appearance when making the layout of a view. This PR removed a small optimization in CPView. Now when making setNeedsLayout and setNeedsDisplay, the methods drawRect: and layoutSubviews are always called even if there are not override. (As in cocoa) --- AppKit/CPView.j | 77 ++++++++++++--------------------------- Tests/AppKit/CPViewTest.j | 11 +++++- 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index ca467a1d0..82db0b74c 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -231,8 +231,6 @@ var CPViewHighDPIDrawingEnabled = YES; CPView _nextKeyView; CPView _previousKeyView; - unsigned _viewClassFlags; - // ToolTips CPString _toolTip @accessors(getter=toolTip); Function _toolTipFunctionIn; @@ -295,27 +293,6 @@ var CPViewHighDPIDrawingEnabled = YES; return CPViewHighDPIDrawingEnabled; } -- (void)_setupViewFlags -{ - var theClass = [self class], - classUID = [theClass UID]; - - if (CPViewFlags[classUID] === undefined) - { - var flags = 0; - - if ([theClass instanceMethodForSelector:@selector(drawRect:)] !== [CPView instanceMethodForSelector:@selector(drawRect:)]) - flags |= CPViewHasCustomDrawRect; - - if ([theClass instanceMethodForSelector:@selector(layoutSubviews)] !== [CPView instanceMethodForSelector:@selector(layoutSubviews)]) - flags |= CPViewHasCustomLayoutSubviews; - - CPViewFlags[classUID] = flags; - } - - _viewClassFlags = CPViewFlags[classUID]; -} - + (CPSet)keyPathsForValuesAffectingFrame { return [CPSet setWithObjects:@"frameOrigin", @"frameSize"]; @@ -331,12 +308,6 @@ var CPViewHighDPIDrawingEnabled = YES; return nil; } -- (void)awakeFromCib -{ - [super awakeFromCib]; - - [self _recomputeAppearance]; -} - (id)init { @@ -391,8 +362,6 @@ var CPViewHighDPIDrawingEnabled = YES; _DOMImageSizes = []; #endif - [self _setupViewFlags]; - [self _loadThemeAttributes]; } @@ -850,8 +819,7 @@ var CPViewHighDPIDrawingEnabled = YES; */ - (void)viewDidMoveToSuperview { - [self _recomputeAppearance]; - + [self setNeedsLayout:YES]; [self setNeedsDisplay:YES]; } @@ -2489,9 +2457,6 @@ setBoundsOrigin: */ - (void)setNeedsDisplayInRect:(CGRect)aRect { - if (!(_viewClassFlags & CPViewHasCustomDrawRect)) - return; - if (CGRectIsEmpty(aRect)) return; @@ -2632,7 +2597,7 @@ setBoundsOrigin: - (void)setNeedsLayout:(BOOL)needLayout { - if (!(_viewClassFlags & CPViewHasCustomLayoutSubviews) || !needLayout) + if (!needLayout) { _needsLayout = NO; return; @@ -2654,12 +2619,31 @@ setBoundsOrigin: { _needsLayout = NO; + [self viewWillLayout]; [self layoutSubviews]; + [self viewDidLayout]; } } +/*! + @ignore +*/ +- (void)viewWillLayout +{ + +} + +/*! + @ignore +*/ +- (void)viewDidLayout +{ + [self _recomputeAppearance]; +} + - (void)layoutSubviews { + } /*! @@ -3544,19 +3528,13 @@ setBoundsOrigin: _appearance = anAppearance; [self didChangeValueForKey:@"appearance"]; - [self _recomputeAppearance]; + [self setNeedsLayout:YES]; } /*! @ignore */ - (void)_recomputeAppearance { - // if we don't have a themeState, it means - // the view is not decoding from a cib, so we just return. - // this method will be called again in awakeFromCib - if (!_themeState) - return; - var effectiveAppearance = [self effectiveAppearance]; if ([effectiveAppearance isEqual:[CPAppearance appearanceNamed:CPAppearanceNameAqua]]) @@ -3718,7 +3696,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _opacity = 1.0; [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; - [self _setupViewFlags]; _theme = [CPTheme defaultTheme]; _themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey]; @@ -3737,15 +3714,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _themeAttributes[attributeName] = CPThemeAttributeDecode(aCoder, attributeName, attributes[count], _theme, themeClass); } - var appearance = [aCoder decodeObjectForKey:CPViewAppearanceKey]; - - // TODO : find a way to fix this horrible things - // We only set the appearance here when everything and every subviews were unarchived. - // Otherwise this causes a crash with some subviews not unarchived but already created (how ? init is not called, neither initWithFrame or initWithCoder) in the coder (I have no idea why these views are present in _objects of the coder) - // To reproduce, uncomment the timeout and open the test Tests/Manual/TableTests/ViewBasedCib - window.setTimeout(function() { - [self setAppearance:appearance]; - },0); + [self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]]; [self setNeedsDisplay:YES]; [self setNeedsLayout]; diff --git a/Tests/AppKit/CPViewTest.j b/Tests/AppKit/CPViewTest.j index b3f1b80e2..9c11b4de5 100644 --- a/Tests/AppKit/CPViewTest.j +++ b/Tests/AppKit/CPViewTest.j @@ -773,6 +773,8 @@ var methodCalled; - (void)testAppearanceDefaultvalue { + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; + [self assert:nil equals:[view appearance]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; @@ -782,9 +784,10 @@ var methodCalled; - (void)testAppearanceWithVibrantDark { [view setAppearance:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark]]; - [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view appearance]]; [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view effectiveAppearance]]; + + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; [self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; } @@ -795,6 +798,8 @@ var methodCalled; [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view appearance]]; [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view effectiveAppearance]]; + + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; [self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; } @@ -806,6 +811,8 @@ var methodCalled; [self assert:nil equals:[view appearance]]; [self assert:nil equals:[view effectiveAppearance]]; + + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; } @@ -833,12 +840,14 @@ var methodCalled; [viewA addSubview:view]; + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantLight] equals:[view effectiveAppearance]]; [self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; [viewB addSubview:view]; + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; [self assert:[CPAppearance appearanceNamed:CPAppearanceNameVibrantDark] equals:[view effectiveAppearance]]; [self assertFalse:[view hasThemeState:CPThemeStateAppearanceVibrantLight]]; [self assertTrue:[view hasThemeState:CPThemeStateAppearanceVibrantDark]]; From 3fcc37e0869685771bf6c819b9e974a1899ef106 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 22 Sep 2015 14:33:14 -0700 Subject: [PATCH 4/9] Fixed: CPTabView did not accept first mouse event Previously, the CPTabView did not react with the first mouse event (for instance when a CPTabView was in a not focused window). Now it does as in cocoa. To do that, the CPTavView override the method acceptsFirstMouse. Previously, the tabView had a CPBox, it now has a _CPTabViewBox. This new box reacts differently than the CPBox for the method hitTests. It now returns nil when the click was performed on the segmentedControl of the CPTabView, previously this same click would be handle byt the CPBox. --- AppKit/CPTabView.j | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTabView.j b/AppKit/CPTabView.j index baefde563..a99ee9c9d 100644 --- a/AppKit/CPTabView.j +++ b/AppKit/CPTabView.j @@ -34,6 +34,8 @@ CPNoTabsBezelBorder = 4; //Displays no tabs and has a bezeled border. CPNoTabsLineBorder = 5; //Has no tabs and displays a line border. CPNoTabsNoBorder = 6; //Displays no tabs and no border. +@class _CPTabViewBox + var CPTabViewDidSelectTabViewItemSelector = 1 << 1, CPTabViewShouldSelectTabViewItemSelector = 1 << 2, CPTabViewWillSelectTabViewItemSelector = 1 << 3, @@ -64,7 +66,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1, CPArray _items; CPSegmentedControl _tabs; - CPBox _box; + _CPTabViewBox _box; CPNumber _selectedIndex; @@ -98,7 +100,8 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1, var height = [_tabs valueForThemeAttribute:@"min-size"].height; [_tabs setFrameSize:CGSizeMake(0, height)]; - _box = [[CPBox alloc] initWithFrame:[self bounds]]; + _box = [[_CPTabViewBox alloc] initWithFrame:[self bounds]]; + [_box setTabView:self]; [self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]]; [self addSubview:_box]; @@ -496,6 +499,18 @@ var CPTabViewDidSelectTabViewItemSelector = 1 << 1, [self selectFirstTabViewItem:self]; } + +#pragma mark - +#pragma mark Override + +/*! + Enabled controls accept first mouse by default. +*/ +- (BOOL)acceptsFirstMouse:(CPEvent)anEvent +{ + return YES; +} + @end var CPTabViewItemsKey = "CPTabViewItemsKey", @@ -571,3 +586,26 @@ var CPTabViewItemsKey = "CPTabViewItemsKey", } @end + +@implementation _CPTabViewBox : CPBox +{ + CPTabView _tabView @accessors(property=tabView); +} + + +#pragma mark - +#pragma mark Override + +- (CPView)hitTest:(CGPoint)aPoint +{ + // Here we check if we have clicked on the segmentedControl of the tabView or not + // If YES, the CPBox should not handle the click + var segmentIndex = [_tabView._tabs testSegment:[_tabView._tabs convertPoint:aPoint fromView:[self superview]]]; + + if (segmentIndex != CPNotFound) + return nil; + + return [super hitTest:aPoint]; +} + +@end \ No newline at end of file From 7a0b2c958b2d94d9e3c83f4cfa6c38cace75d68f Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 22 Sep 2015 15:01:19 -0700 Subject: [PATCH 5/9] Fixed: crash with CPRuleEditor when dragging the first row Previously, cappuccinos crashed when dragging to the top the first row of a CPRuleEditor. --- AppKit/CPRuleEditor/CPRuleEditor.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPRuleEditor/CPRuleEditor.j b/AppKit/CPRuleEditor/CPRuleEditor.j index 404c5546e..141e06d63 100644 --- a/AppKit/CPRuleEditor/CPRuleEditor.j +++ b/AppKit/CPRuleEditor/CPRuleEditor.j @@ -2121,7 +2121,7 @@ TODO: implement return; var point = [self convertPoint:[event locationInWindow] fromView:nil], - view = [_slices objectAtIndex:FLOOR(point.y / _sliceHeight)]; + view = [_slices objectAtIndex:FLOOR(MAX(0, point.y) / _sliceHeight)]; if ([self _dragShouldBeginFromMouseDown:view]) [self _performDragForSlice:view withEvent:event]; From 4ac63950adeba3196c649a46706bac3cbc47bdc2 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Tue, 22 Sep 2015 15:58:53 -0700 Subject: [PATCH 6/9] Fixed: toolTip does not work on a external window Previously, the toolTip created for an external window where shown on the primary platform window. We now display it on the desired platformWindow. --- AppKit/_CPToolTip.j | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AppKit/_CPToolTip.j b/AppKit/_CPToolTip.j index 6268f8ab4..296293d02 100644 --- a/AppKit/_CPToolTip.j +++ b/AppKit/_CPToolTip.j @@ -176,6 +176,8 @@ var _CPToolTipHeight = 24.0, _toolTipWindow = aWindow; _constrainsToUsableScreen = NO; + [self setPlatformWindow:[_toolTipWindow platformWindow]]; + textFrameSize.height += 4; _content = [CPTextField labelWithTitle:aString]; @@ -193,6 +195,7 @@ var _CPToolTipHeight = 24.0, [self setAlphaValue:0.9]; [_windowView setNeedsDisplay:YES]; + } return self; From f2f4fa1b98f625fab2dddd0c1e5b5c9b3ce6c64e Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Wed, 23 Sep 2015 15:00:40 -0700 Subject: [PATCH 7/9] Fixed: readded _viewClassFlags. We only displayRect the view if drawRect: or viewWillDraw is implemented. layoutSubviews is still called even if the subclass does not implement it --- AppKit/CPView.j | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index e1b0fcaa2..2821a8147 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -231,6 +231,8 @@ var CPViewHighDPIDrawingEnabled = YES; CPView _nextKeyView; CPView _previousKeyView; + unsigned _viewClassFlags; + // ToolTips CPString _toolTip @accessors(getter=toolTip); Function _toolTipFunctionIn; @@ -308,6 +310,24 @@ var CPViewHighDPIDrawingEnabled = YES; return nil; } +- (void)_setupViewFlags +{ + var theClass = [self class], + classUID = [theClass UID]; + + if (CPViewFlags[classUID] === undefined) + { + var flags = 0; + + if ([theClass instanceMethodForSelector:@selector(drawRect:)] !== [CPView instanceMethodForSelector:@selector(drawRect:)] + || [theClass instanceMethodForSelector:@selector(viewWillDraw)] !== [CPView instanceMethodForSelector:@selector(viewWillDraw)]) + flags |= CPViewHasCustomDrawRect; + + CPViewFlags[classUID] = flags; + } + + _viewClassFlags = CPViewFlags[classUID]; +} - (id)init { @@ -362,6 +382,7 @@ var CPViewHighDPIDrawingEnabled = YES; _DOMImageSizes = []; #endif + [self _setupViewFlags]; [self _loadThemeAttributes]; } @@ -2457,6 +2478,9 @@ setBoundsOrigin: */ - (void)setNeedsDisplayInRect:(CGRect)aRect { + if (!(_viewClassFlags & CPViewHasCustomDrawRect)) + return; + if (CGRectIsEmpty(aRect)) return; From 8599ad4a3c38c1030ca9b878e73a25d9e449fa2e Mon Sep 17 00:00:00 2001 From: Martin Carlberg Date: Fri, 25 Sep 2015 17:07:15 +0200 Subject: [PATCH 8/9] =?UTF-8?q?Fixed:=20The=20init=20method=20=E2=80=99ini?= =?UTF-8?q?tWithObjects:count:=E2=80=99=20for=20CPArray=20did=20not=20work?= =?UTF-8?q?=20on=20native=20CPJavaScriptArray=20when=20=E2=80=99count?= =?UTF-8?q?=E2=80=99=20is=20not=20the=20same=20as=20the=20length=20on=20th?= =?UTF-8?q?e=20provided=20array.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A test case for this is also added in the test class CPArrayTest --- Foundation/CPArray/_CPJavaScriptArray.j | 2 +- Tests/Foundation/CPArrayTest.j | 25 +++++++++++++++++++++++++ Tests/Foundation/CPMutableArrayTest.j | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Foundation/CPArray/_CPJavaScriptArray.j b/Foundation/CPArray/_CPJavaScriptArray.j index 0246790dd..d0ed91782 100644 --- a/Foundation/CPArray/_CPJavaScriptArray.j +++ b/Foundation/CPArray/_CPJavaScriptArray.j @@ -91,7 +91,7 @@ var concat = Array.prototype.concat, - (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount { if ([objects isKindOfClass:_CPJavaScriptArray]) - return slice.call(objects, 0); + return slice.call(objects, 0, aCount); var array = [], index = 0; diff --git a/Tests/Foundation/CPArrayTest.j b/Tests/Foundation/CPArrayTest.j index d3d1bb3b8..3b113fe00 100644 --- a/Tests/Foundation/CPArrayTest.j +++ b/Tests/Foundation/CPArrayTest.j @@ -11,6 +11,16 @@ return ConcreteArray; } +- (void)test_initWithObjects_count_ +{ + var arrayClass = [[self class] arrayClass], + array = [[arrayClass alloc] initWithObjects:[@"hello", @"bye", @"goodnight", @"seeya"] count:2]; + + [self assert:[array count] equals:2]; + [self assert:[array objectAtIndex:0] equals:@"hello"]; + [self assert:[array objectAtIndex:1] equals:@"bye"]; +} + - (void)test_containsObject_ { var arrayClass = [[self class] arrayClass], @@ -763,6 +773,21 @@ return self; } +- (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount +{ + self = [super init]; + + if (self) + { + array = []; + + for (var index = 0; index < aCount; ++index) + array.push([objects objectAtIndex:index]); + } + + return self; +} + - (CPUInteger)count { return array.length; diff --git a/Tests/Foundation/CPMutableArrayTest.j b/Tests/Foundation/CPMutableArrayTest.j index cdc75b7b4..03d8129b3 100644 --- a/Tests/Foundation/CPMutableArrayTest.j +++ b/Tests/Foundation/CPMutableArrayTest.j @@ -555,6 +555,21 @@ return self; } +- (id)initWithObjects:(CPArray)objects count:(CPUInteger)aCount +{ + self = [super init]; + + if (self) + { + array = []; + + for (var index = 0; index < aCount; ++index) + array.push([objects objectAtIndex:index]); + } + + return self; +} + - (CPUInteger)count { return array.length; From 36cdcbc3c145d6a6066786e13f7ca0491ac04051 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Mon, 28 Sep 2015 11:37:37 -0700 Subject: [PATCH 9/9] Fixed: setupViewFlags was not called when creating a view from a xib Previously, the method setupViewFlags was not called when creating from a xib. This issue was introduced by the commit #448c2a2 Fixed #2380 --- AppKit/CPView.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 2821a8147..089b6d07e 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -3720,6 +3720,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", _opacity = 1.0; [self setBackgroundColor:[aCoder decodeObjectForKey:CPViewBackgroundColorKey]]; + [self _setupViewFlags]; _theme = [CPTheme defaultTheme]; _themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];