From 5b794777aa03b25b59316a4867b55b9028b3e714 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 22 Apr 2016 18:25:53 +0200 Subject: [PATCH] Remove XSViewController Starting from OS X 10.10, NSViewController is part of a reponder chain. XSViewController was used only for that and now can be removed. Issue #209 --- Telephone.xcodeproj/project.pbxproj | 28 --- Telephone/ActiveCallViewController.h | 5 +- Telephone/ActiveCallViewController.m | 5 +- Telephone/CallController+Protected.h | 2 - Telephone/CallController.h | 3 +- Telephone/CallController.m | 28 +-- Telephone/CallTransferController.m | 8 - Telephone/EndedCallViewController.h | 9 +- Telephone/EndedCallViewController.m | 3 +- Telephone/IncomingCallViewController.h | 6 +- Telephone/IncomingCallViewController.m | 3 +- .../XSWindowController/XSViewController.h | 66 ------- .../XSWindowController/XSViewController.m | 176 ------------------ .../XSWindowController/XSWindowController.h | 55 ------ .../XSWindowController/XSWindowController.m | 135 -------------- 15 files changed, 22 insertions(+), 510 deletions(-) delete mode 100644 ThirdParty/XSWindowController/XSViewController.h delete mode 100644 ThirdParty/XSWindowController/XSViewController.m delete mode 100644 ThirdParty/XSWindowController/XSWindowController.h delete mode 100644 ThirdParty/XSWindowController/XSWindowController.m diff --git a/Telephone.xcodeproj/project.pbxproj b/Telephone.xcodeproj/project.pbxproj index bbb99c282..50937704c 100644 --- a/Telephone.xcodeproj/project.pbxproj +++ b/Telephone.xcodeproj/project.pbxproj @@ -222,8 +222,6 @@ AA86C86110FF928D00EF4E8A /* ActiveCallTransferViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA86C86010FF928D00EF4E8A /* ActiveCallTransferViewController.m */; }; AA8A5D2C0E91262500DB43C8 /* AKKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8A5D2B0E91262500DB43C8 /* AKKeychain.m */; }; AA8BA7F61C04D843008839F2 /* AudioDevices.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA8BA7F51C04D843008839F2 /* AudioDevices.swift */; }; - AA8FBAA410A56BD9000946F3 /* XSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8FBAA110A56BD9000946F3 /* XSViewController.m */; }; - AA8FBAA510A56BD9000946F3 /* XSWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8FBAA310A56BD9000946F3 /* XSWindowController.m */; }; AA92F8A41C2B02E700C378B6 /* Ringtone.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA92F8A31C2B02E700C378B6 /* Ringtone.swift */; }; AA97B47610D3A2CA00FC65DA /* CallTransferController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA97B47510D3A2CA00FC65DA /* CallTransferController.m */; }; AA9D081A1BFF7F700000F618 /* Domain.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9D08051BFF7E6F0000F618 /* Domain.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -631,10 +629,6 @@ AA8A5D2A0E91262500DB43C8 /* AKKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = AKKeychain.h; sourceTree = ""; tabWidth = 4; }; AA8A5D2B0E91262500DB43C8 /* AKKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = AKKeychain.m; sourceTree = ""; tabWidth = 4; }; AA8BA7F51C04D843008839F2 /* AudioDevices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioDevices.swift; sourceTree = ""; }; - AA8FBAA010A56BD9000946F3 /* XSViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSViewController.h; sourceTree = ""; }; - AA8FBAA110A56BD9000946F3 /* XSViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XSViewController.m; sourceTree = ""; wrapsLines = 1; }; - AA8FBAA210A56BD9000946F3 /* XSWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSWindowController.h; sourceTree = ""; }; - AA8FBAA310A56BD9000946F3 /* XSWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XSWindowController.m; sourceTree = ""; wrapsLines = 1; }; AA90D7581BC90F9F0059CC03 /* SystemAudioDeviceRepositoryStub.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemAudioDeviceRepositoryStub.swift; sourceTree = ""; }; AA92F8A31C2B02E700C378B6 /* Ringtone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Ringtone.swift; sourceTree = ""; }; AA97B47410D3A2CA00FC65DA /* CallTransferController.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = CallTransferController.h; sourceTree = ""; tabWidth = 4; }; @@ -890,7 +884,6 @@ AA9D08101BFF7E6F0000F618 /* DomainTests */, AAC4FF821C0214120060B186 /* DomainTestDoubles */, AAF298D70F57477C007B5036 /* AddressBookPlugIns */, - AA4D48FF1BB998EC004D1D4B /* ThirdParty */, 19C28FACFE9D520D11CA2CBB /* Products */, ); name = Telephone; @@ -1065,25 +1058,6 @@ name = "Audio Devices"; sourceTree = ""; }; - AA4D48FF1BB998EC004D1D4B /* ThirdParty */ = { - isa = PBXGroup; - children = ( - AA4D49011BB999B9004D1D4B /* XSWindowController */, - ); - path = ThirdParty; - sourceTree = ""; - }; - AA4D49011BB999B9004D1D4B /* XSWindowController */ = { - isa = PBXGroup; - children = ( - AA8FBAA010A56BD9000946F3 /* XSViewController.h */, - AA8FBAA110A56BD9000946F3 /* XSViewController.m */, - AA8FBAA210A56BD9000946F3 /* XSWindowController.h */, - AA8FBAA310A56BD9000946F3 /* XSWindowController.m */, - ); - path = XSWindowController; - sourceTree = ""; - }; AA4D490A1BB99DD6004D1D4B /* Frameworks */ = { isa = PBXGroup; children = ( @@ -1835,8 +1809,6 @@ AAD92139107A608B00F142A4 /* EndedCallViewController.m in Sources */, AA32F7FB1BC52A2A00FAC228 /* UserDefaultsKeys.m in Sources */, AA3FABAB1BBC183B0064B2C3 /* SystemAudioDevices.swift in Sources */, - AA8FBAA410A56BD9000946F3 /* XSViewController.m in Sources */, - AA8FBAA510A56BD9000946F3 /* XSWindowController.m in Sources */, 8A9175991CA59D5C00354E26 /* PJSUAOnIncomingCall.m in Sources */, AA97B47610D3A2CA00FC65DA /* CallTransferController.m in Sources */, AA86C86110FF928D00EF4E8A /* ActiveCallTransferViewController.m in Sources */, diff --git a/Telephone/ActiveCallViewController.h b/Telephone/ActiveCallViewController.h index ee58e2eb8..b367a45e9 100644 --- a/Telephone/ActiveCallViewController.h +++ b/Telephone/ActiveCallViewController.h @@ -19,12 +19,11 @@ #import #import "AKActiveCallView.h" -#import "XSViewController.h" @class AKResponsiveProgressIndicator, CallController; -@interface ActiveCallViewController : XSViewController +@interface ActiveCallViewController : NSViewController // Call controller the receiver belongs to. @property(nonatomic, weak) CallController *callController; @@ -57,6 +56,8 @@ // Initializes an ActiveCallViewController object with a given nib file and call controller. - (instancetype)initWithNibName:(NSString *)nibName callController:(CallController *)callController; +- (void)removeObservations; + // Hangs up call. - (IBAction)hangUpCall:(id)sender; diff --git a/Telephone/ActiveCallViewController.m b/Telephone/ActiveCallViewController.m index ee429c41d..a0cdc0c6f 100644 --- a/Telephone/ActiveCallViewController.m +++ b/Telephone/ActiveCallViewController.m @@ -30,7 +30,7 @@ @implementation ActiveCallViewController - (instancetype)initWithNibName:(NSString *)nibName callController:(CallController *)callController { - self = [super initWithNibName:nibName bundle:nil windowController:callController]; + self = [super initWithNibName:nibName bundle:nil]; if (self != nil) { _enteredDTMF = [[NSMutableString alloc] init]; @@ -48,8 +48,7 @@ - (instancetype)init { - (void)removeObservations { [[self displayedNameField] unbind:NSValueBinding]; [[self statusField] unbind:NSValueBinding]; - [super removeObservations]; -} + } - (void)awakeFromNib { [[[self displayedNameField] cell] setBackgroundStyle:NSBackgroundStyleRaised]; diff --git a/Telephone/CallController+Protected.h b/Telephone/CallController+Protected.h index ad1103d02..54fcb1e55 100644 --- a/Telephone/CallController+Protected.h +++ b/Telephone/CallController+Protected.h @@ -18,8 +18,6 @@ #import "CallController.h" -@class XSViewController; - @interface CallController (Protected) - (void)setCallInfoViewResizingWindow:(NSView *)newView; diff --git a/Telephone/CallController.h b/Telephone/CallController.h index 7c4cb42d5..5e358c466 100644 --- a/Telephone/CallController.h +++ b/Telephone/CallController.h @@ -19,7 +19,6 @@ #import #import "AKSIPCall.h" -#import "XSWindowController.h" #import "CallControllerDelegate.h" @@ -30,7 +29,7 @@ @protocol RingtonePlaybackInteractor; // A call controller. -@interface CallController : XSWindowController { +@interface CallController : NSWindowController { @protected ActiveCallViewController *_activeCallViewController; EndedCallViewController *_endedCallViewController; diff --git a/Telephone/CallController.m b/Telephone/CallController.m index 47a55cef8..6e15eac49 100644 --- a/Telephone/CallController.m +++ b/Telephone/CallController.m @@ -388,23 +388,14 @@ - (void)showIncomingCallView { [self showViewController:self.incomingCallViewController]; } -- (void)showViewController:(XSViewController *)viewController { +- (void)showViewController:(NSViewController *)viewController { if ([self shouldShowViewController:viewController]) { - [self removeCurrentViewControllerIfNeeded]; - [self addViewController:viewController]; [self setCallInfoViewResizingWindow:viewController.view]; } } -- (BOOL)shouldShowViewController:(XSViewController *)viewController { - return self.countOfViewControllers == 0 || ![[self objectInViewControllersAtIndex:0] isEqual:viewController]; -} - -- (void)removeCurrentViewControllerIfNeeded { - if (self.countOfViewControllers > 0) { - assert(self.countOfViewControllers == 1); - [self removeObjectFromViewControllersAtIndex:0]; - } +- (BOOL)shouldShowViewController:(NSViewController *)viewController { + return ![self.callInfoView isEqual:viewController.view]; } @@ -412,8 +403,6 @@ - (void)removeCurrentViewControllerIfNeeded { #pragma mark NSWindow delegate methods - (void)windowWillClose:(NSNotification *)notification { - [super windowWillClose:notification]; - if ([self isCallActive]) { [self setCallActive:NO]; [[self activeCallViewController] stopCallTimer]; @@ -435,13 +424,10 @@ - (void)windowWillClose:(NSNotification *)notification { [[NSApp delegate] updateDockTileBadgeLabel]; [self.delegate callControllerWillClose:self]; - - // View controllers must be nullified because of bindings to callController's |displayedName| and |status|. When - // this is done in -dealloc this is already too late, and KVO error about releaseing an object that is still being - // observied is issued. - _incomingCallViewController = nil; - _activeCallViewController = nil; - _endedCallViewController = nil; + + [_incomingCallViewController removeObservations]; + [_activeCallViewController removeObservations]; + [_endedCallViewController removeObservations]; } diff --git a/Telephone/CallTransferController.m b/Telephone/CallTransferController.m index 8ddf45f57..a08be0e6c 100644 --- a/Telephone/CallTransferController.m +++ b/Telephone/CallTransferController.m @@ -105,18 +105,10 @@ - (IBAction)showInitialState:(id)sender { [self closeSheet:self]; } - [self removeViewControllersIfNeeded]; [self showActiveAccountTransferView]; [self makeCallDestinationFieldFirstResponder]; } -- (void)removeViewControllersIfNeeded { - if ([self countOfViewControllers] > 0) { - [[self viewControllers] removeAllObjects]; - [self patchResponderChain]; - } -} - - (void)showActiveAccountTransferView { [self setCallInfoViewResizingWindow:[[self activeAccountTransferViewController] view]]; } diff --git a/Telephone/EndedCallViewController.h b/Telephone/EndedCallViewController.h index 39a8e1187..e52e7466e 100644 --- a/Telephone/EndedCallViewController.h +++ b/Telephone/EndedCallViewController.h @@ -18,12 +18,10 @@ #import -#import "XSViewController.h" - @class CallController; -@interface EndedCallViewController : XSViewController +@interface EndedCallViewController : NSViewController // Call controller the receiver belongs to. @property(nonatomic, weak) CallController *callController; @@ -41,8 +39,9 @@ // Designated initializer. // Initializes an EndedCallViewController object with a given nib file and call controller. -- (instancetype)initWithNibName:(NSString *)nibName - callController:(CallController *)callController; +- (instancetype)initWithNibName:(NSString *)nibName callController:(CallController *)callController; + +- (void)removeObservations; // Redials a call. - (IBAction)redial:(id)sender; diff --git a/Telephone/EndedCallViewController.m b/Telephone/EndedCallViewController.m index 313def3c4..03d6b8b45 100644 --- a/Telephone/EndedCallViewController.m +++ b/Telephone/EndedCallViewController.m @@ -24,7 +24,7 @@ @implementation EndedCallViewController - (instancetype)initWithNibName:(NSString *)nibName callController:(CallController *)callController { - self = [super initWithNibName:nibName bundle:nil windowController:callController]; + self = [super initWithNibName:nibName bundle:nil]; if (self != nil) { [self setCallController:callController]; @@ -41,7 +41,6 @@ - (instancetype)init { - (void)removeObservations { [[self displayedNameField] unbind:NSValueBinding]; [[self statusField] unbind:NSValueBinding]; - [super removeObservations]; } - (void)awakeFromNib { diff --git a/Telephone/IncomingCallViewController.h b/Telephone/IncomingCallViewController.h index bd99839cc..a8a2fdfba 100644 --- a/Telephone/IncomingCallViewController.h +++ b/Telephone/IncomingCallViewController.h @@ -18,12 +18,10 @@ #import -#import "XSViewController.h" - @class CallController; -@interface IncomingCallViewController : XSViewController +@interface IncomingCallViewController : NSViewController // Call controller the receiver belongs to. @property(nonatomic, weak) CallController *callController; @@ -44,6 +42,8 @@ // Initializes an IncomingCallViewController object with a given call controller. - (instancetype)initWithCallController:(CallController *)callController; +- (void)removeObservations; + // Accepts an incoming call. - (IBAction)acceptCall:(id)sender; diff --git a/Telephone/IncomingCallViewController.m b/Telephone/IncomingCallViewController.m index f901263f2..ba5b43c53 100644 --- a/Telephone/IncomingCallViewController.m +++ b/Telephone/IncomingCallViewController.m @@ -27,7 +27,7 @@ @implementation IncomingCallViewController @synthesize callController = callController_; - (instancetype)initWithCallController:(CallController *)callController { - self = [super initWithNibName:@"IncomingCallView" bundle:nil windowController:callController]; + self = [super initWithNibName:@"IncomingCallView" bundle:nil]; if (self != nil) { [self setCallController:callController]; @@ -44,7 +44,6 @@ - (instancetype)init { - (void)removeObservations { [[self displayedNameField] unbind:NSValueBinding]; [[self statusField] unbind:NSValueBinding]; - [super removeObservations]; } - (void)awakeFromNib { diff --git a/ThirdParty/XSWindowController/XSViewController.h b/ThirdParty/XSWindowController/XSViewController.h deleted file mode 100644 index 98e930fe6..000000000 --- a/ThirdParty/XSWindowController/XSViewController.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// XSViewController.h -// View Controllers -// -// Created by Jonathan Dann and Cathy Shive on 14/04/2008. -// -// Copyright (c) 2008 Jonathan Dann and Cathy Shive -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// If you use it, acknowledgement in an About Page or other appropriate place would be nice. -// For example, "Contains "View Conrtollers" by Jonathan Dann and Cathy Shive" will do. - -#import - -// XS for Xtra-Special! - -@class XSWindowController; -@interface XSViewController : NSViewController { -@private - XSViewController *__weak _parent; - XSWindowController *__weak _windowController; - NSMutableArray *_children; -} - -@property(weak) XSViewController *parent; -@property(weak) XSWindowController *windowController; -@property(readonly,copy) NSMutableArray *children; // there's no mutableCopy keyword so this will be @synthesized in the implementation to get the default getter, but we'll write our own setter, otherwise mutability is lost - -- (instancetype)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle windowController:(XSWindowController *)windowController; - -- (NSUInteger)countOfChildren; -- (XSViewController *)objectInChildrenAtIndex:(NSUInteger)index; - -- (void)addChild:(XSViewController *)viewController; -- (void)insertObject:(XSViewController *)viewController inChildrenAtIndex:(NSUInteger)index; -- (void)insertObjects:(NSArray *)viewControllers inChildrenAtIndexes:(NSIndexSet *)indexes; -- (void)insertObjects:(NSArray *)viewControllers inChildrenAtIndex:(NSUInteger)index; - -- (void)removeChild:(XSViewController *)viewController; -- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index; - -- (XSViewController *)rootController; -- (NSArray *)descendants; -- (void)removeObservations; - -@end diff --git a/ThirdParty/XSWindowController/XSViewController.m b/ThirdParty/XSWindowController/XSViewController.m deleted file mode 100644 index 460dca3e8..000000000 --- a/ThirdParty/XSWindowController/XSViewController.m +++ /dev/null @@ -1,176 +0,0 @@ -// -// XSViewController.m -// View Controllers -// -// Created by Jonathan Dann and Cathy Shive on 14/04/2008. -// -// Copyright (c) 2008 Jonathan Dann and Cathy Shive -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// If you use it, acknowledgement in an About Page or other appropriate place would be nice. -// For example, "Contains "View Conrtollers" by Jonathan Dann and Cathy Shive" will do. - -#import "XSViewController.h" -#import "XSWindowController.h" - -#pragma mark Private API - -@interface XSViewController (Private) -// This method is made private so users of the class can't (easily) set the children array whenever they want, they must use the indexed accessors provided. If this was public then our methods that mantain the responder chain and pass the represented object and window controller to the children would be subverted. Alternatively the setter could set all the required variables on the objects in the newChildren array, but the API then becomes a little clunkier. -- (void)setChildren:(NSMutableArray *)newChildren; -@end - -@implementation XSViewController (Private) -- (void)setChildren:(NSMutableArray *)newChildren; -{ - if (_children == newChildren) - return; - NSMutableArray *newChildrenCopy = [newChildren mutableCopy]; - _children = newChildrenCopy; -} -@end - -#pragma mark - -#pragma mark Public API - -@implementation XSViewController - -#pragma mark Accessors - -@synthesize parent = _parent; -@synthesize windowController = _windowController; -@synthesize children = _children; - -#pragma mark Designated Initialiser - -- (instancetype)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle windowController:(XSWindowController *)windowController; -{ - self = [super initWithNibName:name bundle:bundle]; - if (!self) - return nil; - self.windowController = windowController; // non-retained to avoid retain cycles - self.children = [NSMutableArray array]; // set up a blank mutable array - return self; -} - -// --------------------------------- -// This is the NSViewController's designated initialiser, which we override to call our own. Any subclasses that call this will then set up our intance variables properly. -// --------------------------------- -- (instancetype)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle; -{ -// [NSException raise:@"XSViewControllerException" format:[NSString stringWithFormat:@"An instance of an XSViewController concrete subclass was initialized using the NSViewController method -initWithNibName:bundle: all view controllers in the enusing tree will have no reference to an XSWindowController object and cannot be automatically added to the responder chain"]]; - @throw [NSException exceptionWithName:@"XSViewControllerException" - reason:@"An instance of an XSViewController concrete subclass was initialized using the NSViewController method -initWithNibName:bundle: all view controllers in the enusing tree will have no reference to an XSWindowController object and cannot be automatically added to the responder chain" - userInfo:nil]; - return nil; -} - - -#pragma mark Indexed Accessors - -- (NSUInteger)countOfChildren; -{ - return [self.children count]; -} - -- (XSViewController *)objectInChildrenAtIndex:(NSUInteger)index; -{ - return [self.children objectAtIndex:index]; -} - -// ------------------------------------------ -// This will add a new XSViewController subclass to the end of the children array. -// ------------------------------------------ -- (void)addChild:(XSViewController *)viewController; -{ - [self insertObject:viewController inChildrenAtIndex:[self.children count]]; -} - -- (void)removeChild:(XSViewController *)viewController; -{ - [self.children removeObject:viewController]; -} - -- (void)removeObjectFromChildrenAtIndex:(NSUInteger)index; -{ - [self.children removeObjectAtIndex:index]; - [(XSWindowController *)self.windowController patchResponderChain]; // each time a controller is removed then the repsonder chain needs fixing -} - -- (void)insertObject:(XSViewController *)viewController inChildrenAtIndex:(NSUInteger)index; -{ - [self.children insertObject:viewController atIndex:index]; - [viewController setParent:self]; - [self.windowController patchResponderChain]; -} - -- (void)insertObjects:(NSArray *)viewControllers inChildrenAtIndexes:(NSIndexSet *)indexes; -{ - [self.children insertObjects:viewControllers atIndexes:indexes]; - [viewControllers makeObjectsPerformSelector:@selector(setParent:) withObject:self]; - [self.windowController patchResponderChain]; -} - -- (void)insertObjects:(NSArray *)viewControllers inChildrenAtIndex:(NSUInteger)index; -{ - [self insertObjects:viewControllers inChildrenAtIndexes:[NSIndexSet indexSetWithIndex:index]]; -} - -# pragma mark Utilities - -// ------------------------------------------ -// This method is not used in the example but does demonstrates an important point of our setup: the root controller in the tree should have parent = nil. If you'd rather set the parent of the root node to the window controller, this method must be modified to check the class of the parent object. -// ------------------------------------------ -- (XSViewController *)rootController; -{ - XSViewController *root = self.parent; - if (!root) // we are the top of the tree - return self; - while (root.parent) // if this is nil then there is no parent, the whole system is based on the idea that the top of the tree has nil parent, not the windowController as its parent. - root = root.parent; - return root; -} - -// --------------------------------------- -// A top-down tree sorting method. Recursively calls itself to build up an array of all the nodes in the tree. If one thinks of a file and folder setup, then this would add all the contents of a folder to the array (ad infinitum) to the array before moving on to the next folder at the same level -// ---------------------------------------- -- (NSArray *)descendants; -{ - NSMutableArray *array = [NSMutableArray array]; - for (XSViewController *child in self.children) { - [array addObject:child]; - if ([child countOfChildren] > 0) - [array addObjectsFromArray:[child descendants]]; - } - return [array copy]; // return an immutable array -} - -// -------------------------------------- -// Any manual KVO or bindings that you have set up (other than to the representedObject) should be removed in this method. It is called by the window controller on in the -windowWillClose: method. After this the window controller can safely call -dealloc without any warnings that it is being deallocated while observers are still registered. -// -------------------------------------- -- (void)removeObservations -{ - [self.children makeObjectsPerformSelector:@selector(removeObservations)]; -} - -@end diff --git a/ThirdParty/XSWindowController/XSWindowController.h b/ThirdParty/XSWindowController/XSWindowController.h deleted file mode 100644 index 3fa986614..000000000 --- a/ThirdParty/XSWindowController/XSWindowController.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// XSWindowController.h -// View Controllers -// -// Created by Jonathan Dann and Cathy Shive on 14/04/2008. -// -// Copyright (c) 2008 Jonathan Dann and Cathy Shive -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// If you use it, acknowledgement in an About Page or other appropriate place would be nice. -// For example, "Contains "View Conrtollers" by Jonathan Dann and Cathy Shive" will do. - -#import - -@class XSViewController; -@interface XSWindowController : NSWindowController { - NSMutableArray *_viewControllers; -} -@property(nonatomic,copy,readonly) NSMutableArray *viewControllers; - -- (NSUInteger)countOfViewControllers; -- (XSViewController *)objectInViewControllersAtIndex:(NSUInteger)index; - -- (void)addViewController:(XSViewController *)viewController; -- (void)insertObject:(XSViewController *)viewController inViewControllersAtIndex:(NSUInteger)index; -- (void)insertObjects:(NSArray *)viewControllers inViewControllersAtIndexes:(NSIndexSet *)indexes; -- (void)insertObjects:(NSArray *)viewControllers inViewControllersAtIndex:(NSUInteger)index; - -- (void)removeViewController:(XSViewController *)viewController; -- (void)removeObjectFromViewControllersAtIndex:(NSUInteger)index; - -- (void)patchResponderChain; - -- (void)windowWillClose:(NSNotification *)notification; -@end diff --git a/ThirdParty/XSWindowController/XSWindowController.m b/ThirdParty/XSWindowController/XSWindowController.m deleted file mode 100644 index fa2588cc9..000000000 --- a/ThirdParty/XSWindowController/XSWindowController.m +++ /dev/null @@ -1,135 +0,0 @@ -// -// XSWindowController.m -// View Controllers -// -// Created by Jonathan Dann and Cathy Shive on 14/04/2008. -// -// Copyright (c) 2008 Jonathan Dann and Cathy Shive -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// If you use it, acknowledgement in an About Page or other appropriate place would be nice. -// For example, "Contains "View Conrtollers" by Jonathan Dann and Cathy Shive" will do. - -#import "XSWindowController.h" -#import "XSViewController.h" - -@interface XSWindowController () // class continuation allows us to redeclare the property as readwrite to we can privately use the setter -@property(nonatomic,copy) NSMutableArray *viewControllers; -@end - -@implementation XSWindowController -@synthesize viewControllers = _viewControllers; // using synthesize will make our getter, but we create our own setter to keep mutability of the array - -- (instancetype)initWithWindowNibName:(NSString *)nibName; -{ - self = [super initWithWindowNibName:nibName]; - if (!self) - return nil; - self.viewControllers = [NSMutableArray array]; - return self; -} - -- (void)setViewControllers:(NSMutableArray *)newViewControllers; -{ - if (_viewControllers == newViewControllers) - return; - NSMutableArray *newViewControllersCopy = [newViewControllers mutableCopy]; - _viewControllers = newViewControllersCopy; -} - -- (void)windowWillClose:(NSNotification *)notification; -{ - [self.viewControllers makeObjectsPerformSelector:@selector(removeObservations)]; -} - -- (NSUInteger)countOfViewControllers; -{ - return [self.viewControllers count]; -} - -- (XSViewController *)objectInViewControllersAtIndex:(NSUInteger)index; -{ - return [self.viewControllers objectAtIndex:index]; -} - -- (void)addViewController:(XSViewController *)viewController; -{ - [self.viewControllers insertObject:viewController atIndex:[self.viewControllers count]]; - [self patchResponderChain]; -} - -- (void)insertObject:(XSViewController *)viewController inViewControllersAtIndex:(NSUInteger)index; -{ - [self.viewControllers insertObject:viewController atIndex:index]; - [self patchResponderChain]; -} - -- (void)insertObjects:(NSArray *)viewControllers inViewControllersAtIndexes:(NSIndexSet *)indexes; -{ - [self.viewControllers insertObjects:viewControllers atIndexes:indexes]; - [self patchResponderChain]; -} - -- (void)insertObjects:(NSArray *)viewControllers inViewControllersAtIndex:(NSUInteger)index; -{ - [self insertObjects:viewControllers inViewControllersAtIndexes:[NSIndexSet indexSetWithIndex:index]]; -} - -// ------------------------------------------ -// It should be noted that if we remove an object from the view controllers array then the whole tree that descends from it will go too. -// ------------------------------------------ -- (void)removeViewController:(XSViewController *)viewController; -{ - [self.viewControllers removeObject:viewController]; - [self patchResponderChain]; -} - -- (void)removeObjectFromViewControllersAtIndex:(NSUInteger)index; -{ - [self.viewControllers removeObjectAtIndex:index]; - [self patchResponderChain]; -} - -// --------------------------------------------------- -// This method creates an array containing all the view controllers, then adds them to the responder chain in sequence. The last view controller in the array has nextResponder == nil. -// --------------------------------------------------- -- (void)patchResponderChain; -{ - if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_10) - return; - if ([self.viewControllers count] == 0) // we're being called by view controllers at the beginning of creating the tree, most likely load time and the root of the tree hasn't been added to our list of controllers. - return; - NSMutableArray *flatViewControllers = [NSMutableArray array]; - for (XSViewController *viewController in self.viewControllers) { // flatten the view controllers into an array - [flatViewControllers addObject:viewController]; - [flatViewControllers addObjectsFromArray:[viewController descendants]]; - } - [self setNextResponder:[flatViewControllers objectAtIndex:0]]; - NSUInteger index = 0; - NSUInteger viewControllerCount = [flatViewControllers count] - 1; - for (index = 0; index < viewControllerCount ; index++) { // set the next responder of each controller to the next, the last in the array has no next responder. - [[flatViewControllers objectAtIndex:index] setNextResponder:[flatViewControllers objectAtIndex:index + 1]]; - } -} - -@end