mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
NEW: CPViewController -viewWill/DidAppear & -viewWill/DidDisappear
When a view belonging to a CPViewController is hidden, unhidden, added or removed, its viewController receives the appropriate message. Added AppKit/CPViewControllerTest.
This commit is contained in:
+36
-3
@@ -112,6 +112,11 @@ CPViewHeightSizable = 16;
|
||||
*/
|
||||
CPViewMaxYMargin = 32;
|
||||
|
||||
_CPViewWillAppearNotification = @"CPViewWillAppearNotification";
|
||||
_CPViewDidAppearNotification = @"CPViewDidAppearNotification";
|
||||
_CPViewWillDisappearNotification = @"CPViewWillDisappearNotification";
|
||||
_CPViewDidDisappearNotification = @"CPViewDidDisappearNotification";
|
||||
|
||||
CPViewBoundsDidChangeNotification = @"CPViewBoundsDidChangeNotification";
|
||||
CPViewFrameDidChangeNotification = @"CPViewFrameDidChangeNotification";
|
||||
|
||||
@@ -404,7 +409,6 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sets the tooltip for the receiver.
|
||||
|
||||
@@ -599,6 +603,7 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
// Remove the view from its previous superview.
|
||||
[aSubview _removeFromSuperview];
|
||||
|
||||
[aSubview _postViewWillAppearNotification];
|
||||
// Set ourselves as the superview.
|
||||
[aSubview _setSuperview:self];
|
||||
}
|
||||
@@ -685,6 +690,7 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
|
||||
[_superview willRemoveSubview:self];
|
||||
[self _postViewWillDisappearNotification];
|
||||
|
||||
[_superview._subviews removeObjectIdenticalTo:self];
|
||||
|
||||
@@ -1616,18 +1622,40 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
while (view = [view superview]);
|
||||
}
|
||||
|
||||
[self _postViewWillDisappearNotification];
|
||||
[self _recursiveGainedHiddenAncestor];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
[self _postViewWillAppearNotification];
|
||||
[self _recursiveLostHiddenAncestor];
|
||||
}
|
||||
|
||||
_isHidden = aFlag;
|
||||
}
|
||||
|
||||
- (void)_postViewWillAppearNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPViewWillAppearNotification object:self userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_postViewDidAppearNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPViewDidAppearNotification object:self userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_postViewWillDisappearNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPViewWillDisappearNotification object:self userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_postViewDidDisappearNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:_CPViewDidDisappearNotification object:self userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)_setSuperview:(CPView)aSuperview
|
||||
{
|
||||
var hasOldSuperview = (_superview !== nil),
|
||||
@@ -1636,12 +1664,18 @@ var CPViewHighDPIDrawingEnabled = YES;
|
||||
newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor];
|
||||
|
||||
if (!newSuperviewIsHidden && oldSuperviewIsHidden)
|
||||
[self _recursiveLostHiddenAncestor];
|
||||
[self _recursiveLostHiddenAncestor];
|
||||
|
||||
if (newSuperviewIsHidden && !oldSuperviewIsHidden)
|
||||
[self _recursiveGainedHiddenAncestor];
|
||||
|
||||
_superview = aSuperview;
|
||||
|
||||
if (hasOldSuperview)
|
||||
[self _postViewDidDisappearNotification];
|
||||
|
||||
if (hasNewSuperview)
|
||||
[self _postViewDidAppearNotification];
|
||||
}
|
||||
|
||||
- (void)_recursiveLostHiddenAncestor
|
||||
@@ -3669,7 +3703,6 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
|
||||
_window = [aCoder decodeObjectForKey:CPViewWindowKey];
|
||||
_superview = [aCoder decodeObjectForKey:CPViewSuperviewKey];
|
||||
|
||||
// We have to manually add the subviews so that they will receive
|
||||
// viewWillMoveToSuperview: and viewDidMoveToSuperview:
|
||||
_subviews = [];
|
||||
|
||||
@@ -213,7 +213,7 @@ var CPViewControllerCachedCibs;
|
||||
if (anError == nil)
|
||||
{
|
||||
var data = [CPData dataWithRawString:aData],
|
||||
aCib = [[CPCib alloc] _initWithData:data bundle:_cibBundle cibName:_cibName];
|
||||
aCib = [[CPCib alloc] _initWithData:data bundle:_cibBundle cibName:_cibName];
|
||||
|
||||
[CPViewControllerCachedCibs setObject:aCib forKey:_cibName];
|
||||
[aCib instantiateCibWithExternalNameTable:_cibExternalNameTable];
|
||||
@@ -286,13 +286,16 @@ var CPViewControllerCachedCibs;
|
||||
|
||||
- (void)_viewDidLoad
|
||||
{
|
||||
[self _viewDidLoadWithCompletionHandler:function() {
|
||||
[self viewDidLoad];
|
||||
}];
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
[self viewDidLoad];
|
||||
_isViewLoaded = YES;
|
||||
[self didChangeValueForKey:"isViewLoaded"];
|
||||
}
|
||||
|
||||
- (void)_viewDidLoadWithCompletionHandler:(Function)aHandler
|
||||
{
|
||||
[self _registerOrUnregister:YES notificationsForView:_view];
|
||||
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
aHandler(_view, nil);
|
||||
_isViewLoaded = YES;
|
||||
@@ -325,6 +328,9 @@ var CPViewControllerCachedCibs;
|
||||
{
|
||||
var willChangeIsViewLoaded = (_isViewLoaded == NO && aView != nil) || (_isViewLoaded == YES && aView == nil);
|
||||
|
||||
[self _registerOrUnregister:NO notificationsForView:_view];
|
||||
[self _registerOrUnregister:YES notificationsForView:aView];
|
||||
|
||||
if (willChangeIsViewLoaded)
|
||||
[self willChangeValueForKey:"isViewLoaded"];
|
||||
|
||||
@@ -340,6 +346,30 @@ var CPViewControllerCachedCibs;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)_registerOrUnregister:(BOOL)shouldRegister notificationsForView:(CPView)aView
|
||||
{
|
||||
if (aView === nil)
|
||||
return;
|
||||
|
||||
var center = [CPNotificationCenter defaultCenter],
|
||||
notifs_to_sel = @{_CPViewWillAppearNotification : @"viewWillAppear",
|
||||
_CPViewDidAppearNotification : @"viewDidAppear",
|
||||
_CPViewWillDisappearNotification : @"viewWillDisappear",
|
||||
_CPViewDidDisappearNotification : @"viewDidDisappear"};
|
||||
|
||||
[notifs_to_sel enumerateKeysAndObjectsUsingBlock:function(notif, selString, stop)
|
||||
{
|
||||
var selector = CPSelectorFromString(selString);
|
||||
if ([self implementsSelector:selector])
|
||||
{
|
||||
if (shouldRegister)
|
||||
[center addObserver:self selector:selector name:notif object:aView];
|
||||
else
|
||||
[center removeObserver:self name:notif object:aView];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Main cib file base name</key>
|
||||
<string>MainMenu.cib</string>
|
||||
<key>CPBundleName</key>
|
||||
<string>BundleTest</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1 @@
|
||||
280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;0E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;4E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;1;0E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;1;6E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;1;7E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;1;8E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;1;9E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;11E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;13E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;15E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;18E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;19E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;12E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;20E;E;D;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;11E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;18E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;21E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;22E;E;D;K;10;$classnameS;18;_CPCibClassSwapperK;8;$classesA;S;18;_CPCibClassSwapperS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;17E;K;18;CPResponderMenuKeyD;K;6;CP$UIDd;1;0E;K;12;CPViewTagKeyD;K;6;CP$UIDd;2;23E;K;14;CPViewFrameKeyD;K;6;CP$UIDd;2;24E;K;15;CPViewBoundsKeyD;K;6;CP$UIDd;2;24E;K;22;CPViewAutoresizingMaskD;K;6;CP$UIDd;2;25E;K;19;CPViewThemeClassKeyD;K;6;CP$UIDd;1;0E;K;19;CPViewThemeStateKeyD;K;6;CP$UIDd;2;26E;K;14;CPViewScaleKeyD;K;6;CP$UIDd;2;27E;K;18;CPViewSizeScaleKeyD;K;6;CP$UIDd;2;27E;K;17;CPViewIsScaledKeyD;K;6;CP$UIDd;2;28E;K;19;CPViewAppearanceKeyD;K;6;CP$UIDd;1;0E;K;22;CPViewTrackingAreasKeyD;K;6;CP$UIDd;2;29E;K;30;_CPCibClassSwapperClassNameKeyD;K;6;CP$UIDd;2;30E;K;38;_CPCibClassSwapperOriginalClassNameKeyD;K;6;CP$UIDd;2;31E;E;S;16;CPViewControllerD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;4;viewS;13;CPApplicationd;1;0S;20;{{0, 0}, {480, 272}}d;2;12S;6;normalS;6;{1, 1}F;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;6;NSViewS;6;CPViewE;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E;
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10116"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="CPViewController">
|
||||
<connections>
|
||||
<outlet property="view" destination="c22-O7-iKe" id="ABk-lK-Kp8"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="c22-O7-iKe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,89 @@
|
||||
@import <AppKit/CPViewController.j>
|
||||
@import <AppKit/CPApplication.j>
|
||||
|
||||
var methodsCalled;
|
||||
|
||||
@implementation CPViewControllerTest : OJTestCase
|
||||
{
|
||||
CPBundle bundle;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
bundle = [CPBundle bundleWithPath:@"Tests/AppKit/BundleTest"];
|
||||
[bundle loadWithDelegate:self];
|
||||
}
|
||||
|
||||
- (void)bundleDidFinishLoading:(CPBundle)aBundle
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)testViewControllerCallbacks
|
||||
{
|
||||
methodsCalled = @[];
|
||||
|
||||
var expectedResult = @[@"viewDidLoad",
|
||||
@"viewWillAppear",
|
||||
@"viewDidAppear",
|
||||
@"viewWillDisappear",
|
||||
@"viewDidDisappear"];
|
||||
|
||||
[self assertTrue:[bundle isLoaded]];
|
||||
var viewController = [[ViewController alloc] initWithCibName:@"NSViewController.cib" bundle:bundle];
|
||||
[self assertNotNull:viewController];
|
||||
|
||||
var superview = [[CPView alloc] initWithFrame:CGRectMakeZero()];
|
||||
var view = [viewController view];
|
||||
|
||||
[superview addSubview:view];
|
||||
[view removeFromSuperview];
|
||||
[self assert:expectedResult equals:methodsCalled];
|
||||
|
||||
// Explicitely change the view.
|
||||
methodsCalled = [];
|
||||
expectedResult = @[@"viewWillAppear",
|
||||
@"viewDidAppear",
|
||||
@"viewWillDisappear",
|
||||
@"viewDidDisappear"];
|
||||
|
||||
var newView = [[CPView alloc] initWithFrame:CGRectMake(0,0,100,100)];
|
||||
[viewController setView:newView];
|
||||
|
||||
[superview addSubview:newView];
|
||||
[newView removeFromSuperview];
|
||||
// Checks that with receive notifs from the new view and not from the old view.
|
||||
[self assert:expectedResult equals:methodsCalled];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ViewController : CPViewController
|
||||
{
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[methodsCalled addObject:_cmd];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear
|
||||
{
|
||||
[methodsCalled addObject:_cmd];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear
|
||||
{
|
||||
[methodsCalled addObject:_cmd];
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear
|
||||
{
|
||||
[methodsCalled addObject:_cmd];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear
|
||||
{
|
||||
[methodsCalled addObject:_cmd];
|
||||
}
|
||||
@end
|
||||
@@ -905,6 +905,21 @@ var updateTrackingAreasCalls,
|
||||
[self assert:expectedResult equals:methodCalled];
|
||||
}
|
||||
|
||||
- (void)testAddViewRemoveView
|
||||
{
|
||||
var expectedResult = [@"viewWillMoveToSuperview_view2",
|
||||
@"viewDidMoveToSuperview_view2",
|
||||
@"viewWillMoveToSuperview_view2",
|
||||
@"viewDidMoveToSuperview_view2",
|
||||
@"viewWillMoveToWindow_view2",
|
||||
@"viewDidMoveToWindow_view2"];
|
||||
|
||||
[view1 addSubview:view2];
|
||||
[view2 removeFromSuperview];
|
||||
|
||||
[self assert:expectedResult equals:methodCalled];
|
||||
}
|
||||
|
||||
- (void)testViewGainedHiddenAncestor
|
||||
{
|
||||
var expectedResult = [@"viewDidHide_view1",
|
||||
@@ -917,14 +932,16 @@ var updateTrackingAreasCalls,
|
||||
|
||||
[view1 setHidden:YES];
|
||||
[view2 addSubview:view3];
|
||||
CPLog.warn("will add view2");
|
||||
[view1 addSubview:view2];
|
||||
|
||||
[self assert:expectedResult equals:methodCalled];
|
||||
[self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"];
|
||||
[self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected " + [view2 identifier] + "isHiddenOrHasHiddenAncestor = YES"];
|
||||
[self assertTrue: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"];
|
||||
|
||||
[self assertFalse:[view2 isHidden]];
|
||||
[self assertFalse:[view3 isHidden]];
|
||||
|
||||
[self assert:expectedResult equals:methodCalled];
|
||||
}
|
||||
|
||||
- (void)testRemoveViewsHiddenByAncestor
|
||||
|
||||
Reference in New Issue
Block a user