2020-07-06 12:15:34 +00:00
|
|
|
/* Implementation of class GSStoryboardTransform
|
|
|
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
By: Gregory John Casamento
|
|
|
|
Date: Sat 04 Jul 2020 03:48:15 PM EDT
|
|
|
|
|
|
|
|
This file is part of the GNUstep Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110 USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <Foundation/NSData.h>
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
#import <Foundation/NSMapTable.h>
|
|
|
|
#import <Foundation/NSXMLDocument.h>
|
|
|
|
#import <Foundation/NSXMLNode.h>
|
|
|
|
#import <Foundation/NSXMLElement.h>
|
|
|
|
#import <Foundation/NSUUID.h>
|
|
|
|
#import <Foundation/NSBundle.h>
|
|
|
|
#import <Foundation/NSKeyedArchiver.h>
|
2020-07-14 05:48:18 +00:00
|
|
|
#import <Foundation/NSException.h>
|
2020-07-06 12:15:34 +00:00
|
|
|
|
|
|
|
#import "AppKit/NSSeguePerforming.h"
|
|
|
|
#import "AppKit/NSStoryboard.h"
|
|
|
|
#import "AppKit/NSStoryboardSegue.h"
|
2020-07-06 12:44:57 +00:00
|
|
|
#import "AppKit/NSNibDeclarations.h"
|
2020-07-08 21:18:58 +00:00
|
|
|
#import "AppKit/NSViewController.h"
|
|
|
|
#import "AppKit/NSWindowController.h"
|
2020-07-06 12:15:34 +00:00
|
|
|
|
|
|
|
#import "GSStoryboardTransform.h"
|
|
|
|
#import "GSFastEnumeration.h"
|
|
|
|
|
2020-07-14 05:48:18 +00:00
|
|
|
#define APPLICATION @"application"
|
|
|
|
|
2020-07-08 21:18:58 +00:00
|
|
|
@interface NSStoryboardSegue (__private__)
|
|
|
|
- (void) _setDestinationController: (id)controller;
|
|
|
|
- (void) _setSourceController: (id)controller;
|
|
|
|
@end
|
|
|
|
|
2020-07-06 12:15:34 +00:00
|
|
|
@interface NSStoryboardSegue (__StoryboardPrivate__)
|
2020-07-08 21:18:58 +00:00
|
|
|
// Private to this class...
|
2020-07-06 12:15:34 +00:00
|
|
|
- (void) _setKind: (NSString *)k;
|
|
|
|
- (NSString *) _kind;
|
2020-07-22 05:37:08 +00:00
|
|
|
- (void) _setRelationship: (NSString *)r;
|
2020-07-06 12:15:34 +00:00
|
|
|
- (NSString *) _relationship;
|
2020-07-22 05:37:08 +00:00
|
|
|
- (void) _setPopoverAnchorView: (id)view;
|
|
|
|
- (id) _popoverAnchorView;
|
2020-07-28 11:44:47 +00:00
|
|
|
- (void) _setPopoverBehavior: (NSPopoverBehavior)behavior;
|
|
|
|
- (NSPopoverBehavior) _popoverBehavior;
|
2020-07-28 05:17:42 +00:00
|
|
|
- (void) _setPreferredEdge: (NSRectEdge)edge;
|
|
|
|
- (NSRectEdge) _preferredEdge;
|
2020-07-06 12:15:34 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
// this needs to be set on segues
|
|
|
|
@implementation NSStoryboardSegue (__StoryboardPrivate__)
|
|
|
|
- (void) _setKind: (NSString *)k
|
|
|
|
{
|
|
|
|
ASSIGN(_kind, k);
|
|
|
|
}
|
|
|
|
|
2020-07-22 05:37:08 +00:00
|
|
|
- (NSString *) _kind
|
2020-07-06 12:15:34 +00:00
|
|
|
{
|
2020-07-22 05:37:08 +00:00
|
|
|
return _kind;
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
|
2020-07-22 05:37:08 +00:00
|
|
|
- (void) _setRelationship: (NSString *)r
|
2020-07-06 12:15:34 +00:00
|
|
|
{
|
2020-07-22 05:37:08 +00:00
|
|
|
ASSIGN(_relationship, r);
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) _relationship
|
|
|
|
{
|
|
|
|
return _relationship;
|
|
|
|
}
|
2020-07-22 05:37:08 +00:00
|
|
|
|
|
|
|
- (void) _setPopoverAnchorView: (id)view
|
|
|
|
{
|
|
|
|
ASSIGN(_popoverAnchorView, view);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) _popoverAnchorView
|
|
|
|
{
|
|
|
|
return _popoverAnchorView;
|
|
|
|
}
|
|
|
|
|
2020-07-28 11:44:47 +00:00
|
|
|
- (void) _setPopoverBehavior: (NSPopoverBehavior)behavior
|
2020-07-22 05:37:08 +00:00
|
|
|
{
|
2020-07-28 11:44:47 +00:00
|
|
|
_popoverBehavior = behavior;
|
2020-07-22 05:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 11:44:47 +00:00
|
|
|
- (NSPopoverBehavior) _popoverBehavior
|
2020-07-22 05:37:08 +00:00
|
|
|
{
|
|
|
|
return _popoverBehavior;
|
|
|
|
}
|
|
|
|
|
2020-07-28 05:17:42 +00:00
|
|
|
- (void) _setPreferredEdge: (NSRectEdge)edge
|
2020-07-22 05:37:08 +00:00
|
|
|
{
|
2020-07-28 05:17:42 +00:00
|
|
|
_preferredEdge = edge;
|
2020-07-22 05:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 11:44:47 +00:00
|
|
|
- (NSRectEdge) _preferredEdge
|
2020-07-22 05:37:08 +00:00
|
|
|
{
|
|
|
|
return _preferredEdge;
|
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSStoryboardSeguePerformAction
|
|
|
|
- (id) target
|
|
|
|
{
|
|
|
|
return _target;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setTarget: (id)target
|
|
|
|
{
|
|
|
|
ASSIGN(_target, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (SEL) action
|
|
|
|
{
|
|
|
|
return _action;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setAction: (SEL)action
|
|
|
|
{
|
|
|
|
_action = action;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) selector
|
|
|
|
{
|
|
|
|
return NSStringFromSelector(_action);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setSelector: (NSString *)s
|
|
|
|
{
|
|
|
|
_action = NSSelectorFromString(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) sender
|
|
|
|
{
|
|
|
|
return _sender;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setSender: (id)sender
|
|
|
|
{
|
|
|
|
ASSIGN(_sender, sender);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) identifier
|
|
|
|
{
|
|
|
|
return _identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setIdentifier: (NSString *)identifier
|
|
|
|
{
|
|
|
|
ASSIGN(_identifier, identifier);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) kind
|
|
|
|
{
|
|
|
|
return _kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setKind: (NSString *)kind
|
|
|
|
{
|
|
|
|
ASSIGN(_kind, kind);
|
|
|
|
}
|
|
|
|
|
2020-07-22 05:37:08 +00:00
|
|
|
- (void) setPopoverAnchorView: (id)view
|
|
|
|
{
|
|
|
|
ASSIGN(_popoverAnchorView, view);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) popoverAnchorView
|
|
|
|
{
|
|
|
|
return _popoverAnchorView;
|
|
|
|
}
|
|
|
|
|
2020-07-14 08:31:08 +00:00
|
|
|
- (NSStoryboard *) storyboard
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-14 08:31:08 +00:00
|
|
|
return _storyboard;
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
|
|
|
|
2020-07-14 08:31:08 +00:00
|
|
|
- (void) setStoryboard: (NSStoryboard *)storyboard
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-14 08:31:08 +00:00
|
|
|
ASSIGN(_storyboard, storyboard);
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
|
|
|
|
2020-07-14 08:31:08 +00:00
|
|
|
- (NSStoryboardSegue *) storyboardSegue
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-14 08:31:08 +00:00
|
|
|
return _storyboardSegue;
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
|
|
|
|
2020-07-14 08:31:08 +00:00
|
|
|
- (void) setStoryboardSegue: (NSStoryboardSegue *)ss
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-14 08:31:08 +00:00
|
|
|
ASSIGN(_storyboardSegue, ss);
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
RELEASE(_storyboard);
|
|
|
|
RELEASE(_kind);
|
|
|
|
RELEASE(_identifier);
|
2020-07-22 05:37:08 +00:00
|
|
|
RELEASE(_popoverAnchorView);
|
2020-07-08 21:18:58 +00:00
|
|
|
RELEASE(_sender);
|
2020-07-14 08:31:08 +00:00
|
|
|
RELEASE(_storyboardSegue);
|
2020-07-08 21:18:58 +00:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2020-07-06 12:15:34 +00:00
|
|
|
- (IBAction) doAction: (id)sender
|
|
|
|
{
|
2020-07-15 08:55:34 +00:00
|
|
|
BOOL should = YES;
|
|
|
|
|
2020-07-15 12:08:27 +00:00
|
|
|
// If the instance we are testing is a controller, then the value of should is set by this method....
|
|
|
|
// if it is not, as it is possible to initiate a segue from an NSMenuItem, then we don't, but should
|
|
|
|
// remains set to YES so that the logic to replace the destination controller is still called.
|
2020-07-15 13:27:45 +00:00
|
|
|
if ([_sender respondsToSelector: @selector(shouldPerformSegueWithIdentifier:sender:)])
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-15 08:55:34 +00:00
|
|
|
should = [_sender shouldPerformSegueWithIdentifier: _identifier
|
|
|
|
sender: _sender];
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
2020-07-15 08:55:34 +00:00
|
|
|
|
|
|
|
if (should)
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-15 23:02:45 +00:00
|
|
|
id destCon = [_storyboardSegue destinationController];
|
|
|
|
if ([destCon isKindOfClass: [NSString class]])
|
2020-07-08 21:18:58 +00:00
|
|
|
{
|
2020-07-15 23:02:45 +00:00
|
|
|
// resolve the destination controller
|
|
|
|
destCon = [_storyboard instantiateControllerWithIdentifier: destCon];
|
|
|
|
[_storyboardSegue _setDestinationController: destCon]; // replace with actual controller...
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
2020-07-15 08:55:34 +00:00
|
|
|
[_storyboardSegue _setSourceController: _sender];
|
|
|
|
|
2020-07-15 13:27:45 +00:00
|
|
|
if (_sender != nil &&
|
|
|
|
[_sender respondsToSelector: @selector(performSegueWithIdentifier:sender:)])
|
2020-07-15 08:55:34 +00:00
|
|
|
{
|
|
|
|
[_sender performSegueWithIdentifier: _identifier
|
|
|
|
sender: _sender];
|
|
|
|
}
|
2020-07-15 21:09:59 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
[_storyboardSegue perform];
|
|
|
|
}
|
2020-07-08 21:18:58 +00:00
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone *)z
|
|
|
|
{
|
|
|
|
NSStoryboardSeguePerformAction *pa = [[NSStoryboardSeguePerformAction allocWithZone: z] init];
|
|
|
|
[pa setTarget: _target];
|
|
|
|
[pa setSelector: [self selector]];
|
|
|
|
[pa setSender: _sender];
|
|
|
|
[pa setIdentifier: _identifier];
|
2020-07-22 05:37:08 +00:00
|
|
|
[pa setPopoverAnchorView: _popoverAnchorView];
|
2020-07-14 08:31:08 +00:00
|
|
|
[pa setStoryboardSegue: _storyboardSegue];
|
2020-07-08 21:18:58 +00:00
|
|
|
[pa setStoryboard: _storyboard];
|
2020-07-06 12:15:34 +00:00
|
|
|
return pa;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype) initWithCoder: (NSCoder *)coder
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if ([coder allowsKeyedCoding])
|
|
|
|
{
|
|
|
|
if ([coder containsValueForKey: @"NSTarget"])
|
|
|
|
{
|
|
|
|
[self setTarget: [coder decodeObjectForKey: @"NSTarget"]];
|
|
|
|
}
|
|
|
|
if ([coder containsValueForKey: @"NSSelector"])
|
|
|
|
{
|
|
|
|
[self setSelector: [coder decodeObjectForKey: @"NSSelector"]];
|
|
|
|
}
|
|
|
|
if ([coder containsValueForKey: @"NSSender"])
|
|
|
|
{
|
|
|
|
[self setSender: [coder decodeObjectForKey: @"NSSender"]];
|
|
|
|
}
|
|
|
|
if ([coder containsValueForKey: @"NSIdentifier"])
|
|
|
|
{
|
|
|
|
[self setIdentifier: [coder decodeObjectForKey: @"NSIdentifier"]];
|
|
|
|
}
|
|
|
|
if ([coder containsValueForKey: @"NSKind"])
|
|
|
|
{
|
|
|
|
[self setKind: [coder decodeObjectForKey: @"NSKind"]];
|
|
|
|
}
|
2020-07-22 05:37:08 +00:00
|
|
|
if ([coder containsValueForKey: @"NSPopoverAnchorView"])
|
|
|
|
{
|
|
|
|
[self setPopoverAnchorView: [coder decodeObjectForKey: @"NSPopoverAnchorView"]];
|
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder *)coder
|
|
|
|
{
|
|
|
|
// this is never encoded directly...
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSControllerPlaceholder
|
|
|
|
|
|
|
|
- (NSString *) storyboardName
|
|
|
|
{
|
|
|
|
return _storyboardName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setStoryboardName: (NSString *)name
|
|
|
|
{
|
|
|
|
ASSIGNCOPY(_storyboardName, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone *)z
|
|
|
|
{
|
|
|
|
NSControllerPlaceholder *c = [[NSControllerPlaceholder allocWithZone: z] init];
|
|
|
|
[c setStoryboardName: _storyboardName];
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype) initWithCoder: (NSCoder *)coder
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if ([coder allowsKeyedCoding])
|
|
|
|
{
|
|
|
|
if ([coder containsValueForKey: @"NSStoryboardName"])
|
|
|
|
{
|
|
|
|
[self setStoryboardName: [coder decodeObjectForKey: @"NSStoryboardName"]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) encodeWithCoder: (NSCoder *)coder
|
|
|
|
{
|
|
|
|
// this is never encoded directly...
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) instantiate
|
|
|
|
{
|
|
|
|
NSStoryboard *sb = [NSStoryboard storyboardWithName: _storyboardName
|
|
|
|
bundle: [NSBundle mainBundle]];
|
|
|
|
return [sb instantiateInitialController];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GSStoryboardTransform
|
|
|
|
|
|
|
|
- (instancetype) initWithData: (NSData *)data
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (self != nil)
|
|
|
|
{
|
|
|
|
NSXMLDocument *xml = [[NSXMLDocument alloc] initWithData: data
|
|
|
|
options: 0
|
|
|
|
error: NULL];
|
|
|
|
|
|
|
|
_scenesMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
|
|
|
|
_controllerMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
|
|
|
|
_identifierToSegueMap = [[NSMutableDictionary alloc] initWithCapacity: 10];
|
|
|
|
|
|
|
|
[self processStoryboard: xml];
|
|
|
|
RELEASE(xml);
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
RELEASE(_initialViewControllerId);
|
|
|
|
RELEASE(_applicationSceneId);
|
|
|
|
RELEASE(_scenesMap);
|
|
|
|
RELEASE(_controllerMap);
|
|
|
|
RELEASE(_identifierToSegueMap);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) initialViewControllerId
|
|
|
|
{
|
|
|
|
return _initialViewControllerId;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) applicationSceneId
|
|
|
|
{
|
|
|
|
return _applicationSceneId;
|
|
|
|
}
|
|
|
|
|
2020-07-08 21:18:58 +00:00
|
|
|
- (NSMapTable *) segueMapForIdentifier: (NSString *)identifier
|
2020-07-06 12:15:34 +00:00
|
|
|
{
|
2020-07-08 21:18:58 +00:00
|
|
|
return [_identifierToSegueMap objectForKey: identifier];
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSXMLElement *) createCustomObjectWithId: (NSString *)ident
|
|
|
|
userLabel: (NSString *)userLabel
|
|
|
|
customClass: (NSString *)className
|
|
|
|
{
|
|
|
|
NSXMLElement *customObject =
|
|
|
|
[[NSXMLElement alloc] initWithName: @"customObject"];
|
|
|
|
NSXMLNode *idValue =
|
|
|
|
[NSXMLNode attributeWithName: @"id"
|
|
|
|
stringValue: ident];
|
|
|
|
NSXMLNode *usrLabel =
|
|
|
|
[NSXMLNode attributeWithName: @"userLabel"
|
|
|
|
stringValue: userLabel];
|
|
|
|
NSXMLNode *customCls =
|
|
|
|
[NSXMLNode attributeWithName: @"customClass"
|
|
|
|
stringValue: className];
|
|
|
|
|
|
|
|
[customObject addAttribute: idValue];
|
|
|
|
[customObject addAttribute: usrLabel];
|
|
|
|
[customObject addAttribute: customCls];
|
|
|
|
|
|
|
|
AUTORELEASE(customObject);
|
|
|
|
|
|
|
|
return customObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSData *) dataForIdentifier: (NSString *)identifier
|
|
|
|
{
|
|
|
|
NSString *sceneId = [_controllerMap objectForKey: identifier];
|
|
|
|
NSXMLDocument *xml = [_scenesMap objectForKey: sceneId];
|
|
|
|
return [xml XMLData];
|
|
|
|
}
|
|
|
|
|
2020-07-15 21:43:34 +00:00
|
|
|
- (void) addStandardObjects: (NSXMLElement *)objects
|
|
|
|
classString: (NSString *) customClassString
|
|
|
|
connections: (NSXMLNode *)appCons
|
2020-07-19 05:24:28 +00:00
|
|
|
firstResponderId: (NSString *)firstResponderId
|
2020-07-15 21:43:34 +00:00
|
|
|
{
|
|
|
|
NSXMLElement *customObject = nil;
|
|
|
|
|
|
|
|
customObject =
|
|
|
|
[self createCustomObjectWithId: @"-3"
|
|
|
|
userLabel: @"Application"
|
|
|
|
customClass: @"NSObject"];
|
|
|
|
[objects insertChild: customObject
|
|
|
|
atIndex: 0];
|
|
|
|
customObject =
|
2020-07-19 05:24:28 +00:00
|
|
|
[self createCustomObjectWithId: firstResponderId
|
2020-07-15 21:43:34 +00:00
|
|
|
userLabel: @"First Responder"
|
|
|
|
customClass: @"FirstResponder"];
|
|
|
|
[objects insertChild: customObject
|
|
|
|
atIndex: 0];
|
|
|
|
customObject =
|
|
|
|
[self createCustomObjectWithId: @"-2"
|
|
|
|
userLabel: @"File's Owner"
|
|
|
|
customClass: customClassString];
|
|
|
|
if (appCons != nil)
|
|
|
|
{
|
|
|
|
[customObject addChild: appCons];
|
|
|
|
}
|
|
|
|
[objects insertChild: customObject
|
|
|
|
atIndex: 0];
|
|
|
|
}
|
|
|
|
|
2020-07-16 09:21:21 +00:00
|
|
|
- (void) processChild: (NSXMLElement *)objects
|
2020-07-10 17:00:27 +00:00
|
|
|
withDoc: (NSXMLElement *)doc
|
|
|
|
withAppNode: (NSXMLNode *)appNode
|
|
|
|
sceneId: (NSString *)sceneId
|
2020-07-19 05:24:28 +00:00
|
|
|
firstResponderId: (NSString *)firstResponderId
|
2020-07-10 17:00:27 +00:00
|
|
|
{
|
|
|
|
NSString *customClassString = nil;
|
2020-07-16 09:21:21 +00:00
|
|
|
NSXMLNode *appCons = nil;
|
|
|
|
|
2020-07-10 17:00:27 +00:00
|
|
|
if (appNode != nil)
|
|
|
|
{
|
|
|
|
NSArray *appConsArr = [appNode nodesForXPath: @"connections" error: NULL];
|
2020-07-16 09:21:21 +00:00
|
|
|
|
|
|
|
appCons = [appConsArr objectAtIndex: 0];
|
2020-07-10 17:00:27 +00:00
|
|
|
if (appCons != nil)
|
|
|
|
{
|
|
|
|
[appCons detach];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assign application scene...
|
|
|
|
ASSIGN(_applicationSceneId, sceneId);
|
|
|
|
[_controllerMap setObject: _applicationSceneId
|
2020-07-14 05:48:18 +00:00
|
|
|
forKey: APPLICATION];
|
2020-07-10 17:00:27 +00:00
|
|
|
|
|
|
|
// Move all application children to objects...
|
2020-07-14 09:38:31 +00:00
|
|
|
NSArray *appChildren = [appNode children];
|
|
|
|
FOR_IN(NSXMLElement*, ae, appChildren)
|
2020-07-19 05:24:28 +00:00
|
|
|
[ae detach];
|
|
|
|
[objects addChild: ae];
|
2020-07-14 09:38:31 +00:00
|
|
|
END_FOR_IN(appChildren);
|
2020-07-10 17:00:27 +00:00
|
|
|
|
|
|
|
// Remove the appNode
|
|
|
|
[appNode detach];
|
|
|
|
|
|
|
|
// create a customObject entry for NSApplication reference...
|
2020-07-16 09:21:21 +00:00
|
|
|
NSXMLNode *appCustomClass = [(NSXMLElement *)appNode
|
|
|
|
attributeForName: @"customClass"];
|
2020-07-10 17:00:27 +00:00
|
|
|
customClassString = ([appCustomClass stringValue] == nil) ?
|
|
|
|
@"NSApplication" : [appCustomClass stringValue];
|
|
|
|
}
|
2020-07-16 09:21:21 +00:00
|
|
|
|
|
|
|
[self addStandardObjects: objects
|
|
|
|
classString: customClassString
|
2020-07-19 05:24:28 +00:00
|
|
|
connections: appCons
|
|
|
|
firstResponderId: firstResponderId];
|
2020-07-16 09:21:21 +00:00
|
|
|
|
|
|
|
// Add it to the document
|
|
|
|
[objects detach];
|
|
|
|
[doc addChild: objects];
|
2020-07-10 17:00:27 +00:00
|
|
|
}
|
2020-07-19 06:00:48 +00:00
|
|
|
|
|
|
|
- (NSArray *) subclassesOfClass: (Class)clz
|
2020-07-14 09:12:50 +00:00
|
|
|
{
|
|
|
|
NSMutableArray *subclasses = [GSObjCAllSubclassesOfClass(clz) mutableCopy];
|
2020-07-19 06:00:48 +00:00
|
|
|
NSMutableArray *result = [NSMutableArray arrayWithCapacity: [subclasses count]];
|
2020-07-14 09:12:50 +00:00
|
|
|
|
|
|
|
[subclasses insertObject: clz atIndex: 0];
|
|
|
|
FOR_IN(Class, cls, subclasses)
|
|
|
|
{
|
|
|
|
NSString *className = NSStringFromClass(cls);
|
|
|
|
NSString *classNameNoNamespace = [className substringFromIndex: 2];
|
|
|
|
NSString *xmlClassName = [NSString stringWithFormat: @"%@%@",
|
|
|
|
[[classNameNoNamespace substringToIndex: 1] lowercaseString],
|
|
|
|
[classNameNoNamespace substringFromIndex: 1]];
|
2020-07-27 12:58:57 +00:00
|
|
|
NSString *lowerCaseName = [xmlClassName lowercaseString];
|
2020-07-19 06:00:48 +00:00
|
|
|
|
|
|
|
[result addObject: xmlClassName];
|
2020-07-27 12:58:57 +00:00
|
|
|
[result addObject: lowerCaseName];
|
2020-07-19 06:00:48 +00:00
|
|
|
}
|
|
|
|
END_FOR_IN(subclasses);
|
2020-07-14 09:12:50 +00:00
|
|
|
|
2020-07-19 06:00:48 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) findSubclassesOf: (Class)clz
|
|
|
|
inDocument: (NSXMLDocument *)document
|
|
|
|
{
|
|
|
|
NSArray *result = nil;
|
|
|
|
NSArray *xmlClassNames = [self subclassesOfClass: clz];
|
|
|
|
|
|
|
|
FOR_IN(NSString*, xmlClassName, xmlClassNames)
|
|
|
|
{
|
|
|
|
NSString *xpath = [NSString stringWithFormat: @"//%@",xmlClassName];
|
|
|
|
result = [document nodesForXPath: xpath error: NULL];
|
2020-07-14 09:12:50 +00:00
|
|
|
if ([result count] > 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-07-19 06:19:29 +00:00
|
|
|
END_FOR_IN(xmlClassNames);
|
2020-07-14 09:12:50 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-10 17:09:22 +00:00
|
|
|
- (NSString *) controllerIdWithDocument: (NSXMLDocument *)document
|
|
|
|
{
|
|
|
|
NSString *controllerId = nil;
|
2020-07-14 09:12:50 +00:00
|
|
|
NSArray *windowControllers = [self findSubclassesOf: [NSWindowController class]
|
|
|
|
inDocument: document];
|
|
|
|
NSArray *viewControllers = [self findSubclassesOf: [NSViewController class]
|
|
|
|
inDocument: document];
|
|
|
|
NSArray *controllerPlaceholders = [document nodesForXPath: @"//controllerPlaceholder"
|
|
|
|
error: NULL];
|
2020-07-10 17:09:22 +00:00
|
|
|
|
|
|
|
if ([windowControllers count] > 0)
|
|
|
|
{
|
|
|
|
NSXMLElement *ce = [windowControllers objectAtIndex: 0];
|
|
|
|
NSXMLNode *attr = [ce attributeForName: @"id"];
|
|
|
|
controllerId = [attr stringValue];
|
|
|
|
|
2020-07-14 09:38:31 +00:00
|
|
|
FOR_IN(NSXMLElement*, o, windowControllers)
|
2020-07-10 17:09:22 +00:00
|
|
|
{
|
|
|
|
NSXMLElement *objects = (NSXMLElement *)[o parent];
|
|
|
|
NSArray *windows = [o nodesForXPath: @"//window" error: NULL];
|
2020-07-14 09:38:31 +00:00
|
|
|
FOR_IN(NSXMLNode*, w, windows)
|
2020-07-10 17:09:22 +00:00
|
|
|
{
|
|
|
|
[w detach];
|
|
|
|
[objects addChild: w];
|
|
|
|
}
|
2020-07-14 09:38:31 +00:00
|
|
|
END_FOR_IN(windows);
|
2020-07-10 17:09:22 +00:00
|
|
|
}
|
2020-07-14 09:38:31 +00:00
|
|
|
END_FOR_IN(windowControllers);
|
2020-07-10 17:09:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ([viewControllers count] > 0)
|
|
|
|
{
|
|
|
|
NSXMLElement *ce = [viewControllers objectAtIndex: 0];
|
|
|
|
NSXMLNode *attr = [ce attributeForName: @"id"];
|
|
|
|
controllerId = [attr stringValue];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([controllerPlaceholders count] > 0)
|
|
|
|
{
|
|
|
|
NSXMLElement *ce = [controllerPlaceholders objectAtIndex: 0];
|
|
|
|
NSXMLNode *attr = [ce attributeForName: @"id"];
|
|
|
|
controllerId = [attr stringValue];
|
|
|
|
}
|
|
|
|
|
|
|
|
return controllerId;
|
|
|
|
}
|
|
|
|
|
2020-07-14 05:48:18 +00:00
|
|
|
- (void) processStoryboard: (NSXMLDocument *)xml
|
2020-07-06 12:15:34 +00:00
|
|
|
{
|
2020-07-14 05:48:18 +00:00
|
|
|
NSArray *docNodes = [xml nodesForXPath: @"document" error: NULL];
|
2020-07-06 12:15:34 +00:00
|
|
|
|
|
|
|
if ([docNodes count] > 0)
|
|
|
|
{
|
|
|
|
NSXMLElement *docNode = [docNodes objectAtIndex: 0];
|
|
|
|
NSArray *array = [docNode nodesForXPath: @"//scene" error: NULL];
|
2020-07-19 05:24:28 +00:00
|
|
|
NSArray *firstResponderIdNodes = [docNode nodesForXPath: @"//objects/customObject[@sceneMemberID =\"firstResponder\"]/@id"
|
2020-07-19 09:01:13 +00:00
|
|
|
error: NULL];
|
2020-07-19 05:24:28 +00:00
|
|
|
NSString *firstResponderId = @"-1";
|
|
|
|
|
|
|
|
if([firstResponderIdNodes count] > 0)
|
|
|
|
{
|
|
|
|
firstResponderId = [[firstResponderIdNodes objectAtIndex: 0] stringValue];
|
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
|
|
|
|
// Set initial view controller...
|
|
|
|
ASSIGN(_initialViewControllerId, [[docNode attributeForName: @"initialViewController"] stringValue]);
|
|
|
|
FOR_IN(NSXMLElement*, e, array)
|
|
|
|
{
|
|
|
|
NSXMLElement *doc = [[NSXMLElement alloc] initWithName: @"document"];
|
|
|
|
NSArray *children = [e children];
|
|
|
|
NSXMLDocument *document = nil;
|
|
|
|
NSString *sceneId = [[e attributeForName: @"sceneID"] stringValue];
|
|
|
|
NSString *controllerId = nil;
|
|
|
|
// Move children...
|
|
|
|
FOR_IN(NSXMLElement*, child, children)
|
|
|
|
{
|
|
|
|
if ([[child name] isEqualToString: @"point"] == YES)
|
|
|
|
continue; // go on if it's a point element, we don't use that in the app...
|
|
|
|
|
|
|
|
NSArray *subnodes = [child nodesForXPath: @"//application" error: NULL];
|
|
|
|
NSXMLNode *appNode = [subnodes objectAtIndex: 0];
|
2020-07-10 17:00:27 +00:00
|
|
|
[self processChild: child
|
|
|
|
withDoc: doc
|
|
|
|
withAppNode: appNode
|
2020-07-19 05:24:28 +00:00
|
|
|
sceneId: sceneId
|
|
|
|
firstResponderId: firstResponderId];
|
2020-07-10 17:00:27 +00:00
|
|
|
|
2020-07-06 12:15:34 +00:00
|
|
|
// fix other custom objects
|
2020-07-19 03:58:50 +00:00
|
|
|
document = [[NSXMLDocument alloc] initWithRootElement: doc];
|
2020-07-10 17:09:22 +00:00
|
|
|
controllerId = [self controllerIdWithDocument: document];
|
2020-07-14 05:48:18 +00:00
|
|
|
controllerId = (controllerId != nil) ? controllerId : APPLICATION;
|
2020-07-06 12:15:34 +00:00
|
|
|
RELEASE(doc);
|
2020-07-19 05:24:28 +00:00
|
|
|
|
2020-07-06 12:15:34 +00:00
|
|
|
// Create document...
|
|
|
|
[_scenesMap setObject: document
|
|
|
|
forKey: sceneId];
|
|
|
|
|
|
|
|
// Map controllerId's to scenes...
|
|
|
|
if (controllerId != nil)
|
|
|
|
{
|
|
|
|
[_controllerMap setObject: sceneId
|
|
|
|
forKey: controllerId];
|
2020-07-14 05:48:18 +00:00
|
|
|
|
|
|
|
[self processSegues: document
|
|
|
|
forControllerId: controllerId];
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
RELEASE(document);
|
|
|
|
}
|
|
|
|
END_FOR_IN(children);
|
|
|
|
}
|
|
|
|
END_FOR_IN(array);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-14 05:48:18 +00:00
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"No document element found in storyboard file"];
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-10 16:26:06 +00:00
|
|
|
- (BOOL) isProcessedDocument: (NSXMLDocument *)xmlIn
|
|
|
|
{
|
|
|
|
NSArray *docArray = [xmlIn nodesForXPath: @"document" error: NULL];
|
|
|
|
if ([docArray count] > 0)
|
|
|
|
{
|
|
|
|
NSXMLElement *docElem = (NSXMLElement *)[docArray objectAtIndex: 0];
|
2020-07-14 09:30:44 +00:00
|
|
|
NSXMLNode *a = [docElem attributeForName: @"processed"];
|
2020-07-10 16:26:06 +00:00
|
|
|
NSString *value = [a stringValue];
|
|
|
|
if (value != nil)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-14 09:30:44 +00:00
|
|
|
NSXMLNode *new_attr = [NSXMLNode attributeWithName: @"processed"
|
|
|
|
stringValue: @"true"];
|
|
|
|
[docElem addAttribute: new_attr];
|
2020-07-10 16:26:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSXMLElement *) createStoryboardProxyElementWithSelector: (NSString *)selector
|
|
|
|
target: (NSString *)dst
|
|
|
|
segueIdentifier: (NSString *)ident
|
|
|
|
sender: (NSString *)src
|
|
|
|
kind: (NSString *)kind
|
2020-07-22 05:37:08 +00:00
|
|
|
anchorView: (NSString *)anchorView
|
2020-07-10 16:26:06 +00:00
|
|
|
{
|
|
|
|
NSXMLElement *sbproxy = [NSXMLElement elementWithName: @"storyboardSeguePerformAction"];
|
|
|
|
|
|
|
|
NSXMLNode *pselector
|
|
|
|
= [NSXMLNode attributeWithName: @"selector"
|
|
|
|
stringValue: selector];
|
|
|
|
NSXMLNode *ptarget
|
|
|
|
= [NSXMLNode attributeWithName: @"target"
|
|
|
|
stringValue: dst];
|
|
|
|
NSString *pident_value = [[NSUUID UUID] UUIDString];
|
|
|
|
NSXMLNode *pident
|
|
|
|
= [NSXMLNode attributeWithName: @"id"
|
|
|
|
stringValue: pident_value];
|
|
|
|
NSXMLNode *psegueIdent
|
|
|
|
= [NSXMLNode attributeWithName: @"identifier"
|
|
|
|
stringValue: ident];
|
|
|
|
NSXMLNode *psender
|
|
|
|
= [NSXMLNode attributeWithName: @"sender"
|
|
|
|
stringValue: src];
|
|
|
|
NSXMLNode *pkind
|
|
|
|
= [NSXMLNode attributeWithName: @"kind"
|
|
|
|
stringValue: kind];
|
2020-07-22 05:37:08 +00:00
|
|
|
NSXMLNode *panchorview
|
|
|
|
= [NSXMLNode attributeWithName: @"popoverAnchorView"
|
|
|
|
stringValue: anchorView];
|
2020-07-06 12:15:34 +00:00
|
|
|
|
2020-07-10 16:26:06 +00:00
|
|
|
[sbproxy addAttribute: pselector];
|
|
|
|
[sbproxy addAttribute: ptarget];
|
|
|
|
[sbproxy addAttribute: pident];
|
|
|
|
[sbproxy addAttribute: psegueIdent];
|
|
|
|
[sbproxy addAttribute: psender];
|
|
|
|
[sbproxy addAttribute: pkind];
|
2020-07-22 05:37:08 +00:00
|
|
|
[sbproxy addAttribute: panchorview];
|
2020-07-10 16:26:06 +00:00
|
|
|
|
|
|
|
return sbproxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMapTable *) processConnections: (NSArray *)connectionsArray
|
|
|
|
withObjects: (NSXMLElement *)objects
|
2020-07-10 16:29:10 +00:00
|
|
|
controllerId: (NSString *)src
|
2020-07-10 16:26:06 +00:00
|
|
|
{
|
|
|
|
NSMapTable *mapTable = [NSMapTable strongToWeakObjectsMapTable];
|
2020-07-10 16:45:21 +00:00
|
|
|
|
2020-07-19 03:23:45 +00:00
|
|
|
FOR_IN (NSXMLElement*, connections, connectionsArray)
|
2020-07-06 12:15:34 +00:00
|
|
|
{
|
2020-07-10 16:45:21 +00:00
|
|
|
NSArray *children = [connections children]; // there should be only one per set.
|
|
|
|
|
2020-07-19 03:58:50 +00:00
|
|
|
FOR_IN (NSXMLElement*, obj, children)
|
|
|
|
if ([[obj name] isEqualToString: @"segue"])
|
|
|
|
{
|
|
|
|
// get the information from the segue.
|
2020-07-19 06:06:25 +00:00
|
|
|
id connections_parent = [[obj parent] parent];
|
|
|
|
id segue_parent = connections; // [obj parent];
|
|
|
|
NSString *connections_parent_name = [connections_parent name];
|
2020-07-19 03:58:50 +00:00
|
|
|
NSXMLNode *attr = [obj attributeForName: @"destination"];
|
|
|
|
NSString *dst = [attr stringValue];
|
|
|
|
attr = [obj attributeForName: @"kind"];
|
|
|
|
NSString *kind = [attr stringValue];
|
|
|
|
attr = [obj attributeForName: @"relationship"];
|
|
|
|
NSString *rel = [attr stringValue];
|
|
|
|
attr = [obj attributeForName: @"id"];
|
|
|
|
NSString *uid = [attr stringValue];
|
|
|
|
attr = [obj attributeForName: @"identifier"];
|
|
|
|
NSString *ident = [attr stringValue];
|
|
|
|
if (ident == nil)
|
|
|
|
{
|
|
|
|
ident = [[NSUUID UUID] UUIDString];
|
|
|
|
}
|
2020-07-22 05:37:08 +00:00
|
|
|
attr = [obj attributeForName: @"popoverAnchorView"];
|
|
|
|
NSString *av = [attr stringValue];
|
|
|
|
attr = [obj attributeForName: @"popoverBehavior"];
|
|
|
|
NSString *pb = [attr stringValue];
|
2020-07-28 11:44:47 +00:00
|
|
|
NSPopoverBehavior behavior = NSPopoverBehaviorApplicationDefined;
|
|
|
|
if ([pb isEqualToString: @"a"])
|
|
|
|
{
|
|
|
|
behavior = NSPopoverBehaviorApplicationDefined;
|
|
|
|
}
|
|
|
|
else if ([pb isEqualToString: @"t"])
|
|
|
|
{
|
|
|
|
behavior = NSPopoverBehaviorTransient;
|
|
|
|
}
|
|
|
|
else if ([pb isEqualToString: @"s"])
|
|
|
|
{
|
|
|
|
behavior = NSPopoverBehaviorSemitransient;
|
|
|
|
}
|
|
|
|
|
2020-07-22 05:37:08 +00:00
|
|
|
attr = [obj attributeForName: @"preferredEdge"];
|
|
|
|
NSString *pe = [attr stringValue];
|
2020-07-28 05:17:42 +00:00
|
|
|
NSRectEdge edge = NSMinXEdge;
|
|
|
|
if ([pe isEqualToString: @"maxY"])
|
|
|
|
{
|
|
|
|
edge = NSMaxYEdge;
|
|
|
|
}
|
|
|
|
else if ([pe isEqualToString: @"minY"])
|
|
|
|
{
|
|
|
|
edge = NSMinYEdge;
|
|
|
|
}
|
|
|
|
else if ([pe isEqualToString: @"maxX"])
|
|
|
|
{
|
|
|
|
edge = NSMaxXEdge;
|
|
|
|
}
|
|
|
|
else if ([pe isEqualToString: @"minX"])
|
|
|
|
{
|
|
|
|
edge = NSMinXEdge;
|
|
|
|
}
|
2020-07-22 05:37:08 +00:00
|
|
|
[obj detach]; // segue can't be in the archive since it doesn't conform to NSCoding
|
2020-07-19 03:58:50 +00:00
|
|
|
|
|
|
|
// Create proxy object to invoke methods on the window controller
|
|
|
|
NSXMLElement *sbproxy = [self createStoryboardProxyElementWithSelector: @"doAction:"
|
|
|
|
target: dst
|
|
|
|
segueIdentifier: ident
|
|
|
|
sender: src
|
2020-07-22 05:37:08 +00:00
|
|
|
kind: kind
|
|
|
|
anchorView: av];
|
2020-07-19 03:58:50 +00:00
|
|
|
|
|
|
|
NSUInteger count = [[objects children] count];
|
|
|
|
[objects insertChild: sbproxy
|
|
|
|
atIndex: count - 1];
|
|
|
|
|
|
|
|
// add action to parent ONLY if it is NOT a controller..
|
2020-07-19 06:06:25 +00:00
|
|
|
if (![[self subclassesOfClass: [NSWindowController class]] containsObject: connections_parent_name] &&
|
|
|
|
![[self subclassesOfClass: [NSViewController class]] containsObject: connections_parent_name])
|
2020-07-19 03:58:50 +00:00
|
|
|
{
|
|
|
|
// Create action...
|
|
|
|
NSXMLElement *action = [NSXMLElement elementWithName: @"action"];
|
|
|
|
NSXMLNode *selector
|
|
|
|
= [NSXMLNode attributeWithName: @"selector"
|
|
|
|
stringValue: @"doAction:"];
|
|
|
|
NSXMLNode *target
|
|
|
|
= [NSXMLNode attributeWithName: @"target"
|
|
|
|
stringValue: [[sbproxy attributeForName: @"id"] stringValue]];
|
|
|
|
NSXMLNode *controller_ident
|
|
|
|
= [NSXMLNode attributeWithName: @"id"
|
|
|
|
stringValue: uid];
|
|
|
|
[action addAttribute: selector];
|
|
|
|
[action addAttribute: target];
|
|
|
|
[action addAttribute: controller_ident];
|
|
|
|
[segue_parent addChild: action];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the segue...
|
|
|
|
NSStoryboardSegue *ss = [[NSStoryboardSegue alloc] initWithIdentifier: ident
|
|
|
|
source: src
|
|
|
|
destination: dst];
|
|
|
|
[ss _setKind: kind];
|
|
|
|
[ss _setRelationship: rel];
|
2020-07-28 11:44:47 +00:00
|
|
|
[ss _setPopoverBehavior: behavior];
|
2020-07-28 05:17:42 +00:00
|
|
|
[ss _setPreferredEdge: edge];
|
2020-07-22 05:37:08 +00:00
|
|
|
|
2020-07-19 03:58:50 +00:00
|
|
|
// Add to maptable...
|
|
|
|
[mapTable setObject: ss
|
|
|
|
forKey: ident];
|
|
|
|
|
|
|
|
} // only process segue objects...
|
2020-07-10 16:45:21 +00:00
|
|
|
END_FOR_IN(children);
|
|
|
|
} // iterate over connection objs
|
|
|
|
END_FOR_IN(connectionsArray);
|
|
|
|
|
|
|
|
return mapTable;
|
2020-07-10 16:26:06 +00:00
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
|
2020-07-14 05:48:18 +00:00
|
|
|
- (void) processSegues: (NSXMLDocument *)xml
|
|
|
|
forControllerId: (NSString *)identifier
|
2020-07-10 16:26:06 +00:00
|
|
|
{
|
2020-07-14 09:30:44 +00:00
|
|
|
BOOL processed = [self isProcessedDocument: xml];
|
2020-07-20 04:53:40 +00:00
|
|
|
if (!processed)
|
2020-07-10 16:26:06 +00:00
|
|
|
{
|
2020-07-14 05:48:18 +00:00
|
|
|
NSArray *array = [xml nodesForXPath: @"//objects[1]"
|
|
|
|
error: NULL];
|
2020-07-10 16:26:06 +00:00
|
|
|
NSXMLElement *objects = [array objectAtIndex: 0]; // get the "objects" section
|
2020-07-14 05:48:18 +00:00
|
|
|
NSArray *connectionsArray = [xml nodesForXPath: @"//connections"
|
|
|
|
error: NULL];
|
2020-07-10 16:29:10 +00:00
|
|
|
NSMapTable *mapTable = [self processConnections: connectionsArray
|
|
|
|
withObjects: objects
|
2020-07-19 05:52:19 +00:00
|
|
|
controllerId: identifier];
|
2020-07-06 12:15:34 +00:00
|
|
|
[_identifierToSegueMap setObject: mapTable
|
|
|
|
forKey: identifier];
|
2020-07-10 16:26:06 +00:00
|
|
|
}
|
2020-07-06 12:15:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|