Fix special case segue from application scene.

This commit is contained in:
Gregory John Casamento 2020-07-08 17:18:58 -04:00
parent 349cace509
commit 1465b10cde
5 changed files with 103 additions and 49 deletions

View file

@ -44,9 +44,11 @@ DEFINE_BLOCK_TYPE(NSStoryboardControllerCreator, NSCoder*, id);
{
id _transform;
}
#if OS_API_VERSION(MAC_OS_X_VERSION_10_13, GS_API_LATEST)
+ (NSStoryboard *) mainStoryboard;
#endif
+ (instancetype) storyboardWithName: (NSStoryboardName)name
bundle: (NSBundle *)bundle;

View file

@ -32,7 +32,7 @@
#if defined(__cplusplus)
extern "C" {
#endif
typedef NSString *NSStoryboardSegueIdentifier;
DEFINE_BLOCK_TYPE_NO_ARGS(GSStoryboardSeguePerformHandler, void);

View file

@ -54,12 +54,11 @@ extern "C" {
- (NSDictionary *) controllerMap;
- (NSString *) initialViewControllerId;
- (NSString *) applicationSceneId;
- (NSDictionary *) identifierToSegueMap;
- (NSData *) dataForIdentifier: (NSString *)identifier;
- (NSData *) dataForSceneId: (NSString *)sceneId;
- (NSData *) dataForApplicationScene;
- (NSMapTable *) segueMapForIdentifier: (NSString *)identifier;
- (NSDictionary *) identifierToSegueMap;
- (void) processSegues: (NSXMLDocument *)xmlIn
forId: (NSString *)identifier;
@ -70,11 +69,13 @@ extern "C" {
// Private classes used when parsing the XIB generated by the transformer...
@interface NSStoryboardSeguePerformAction : NSObject <NSCoding, NSCopying>
{
id _target;
SEL _action;
id _sender;
NSString *_identifier;
NSString *_kind;
id _target;
SEL _action;
id _sender;
NSString *_identifier;
NSString *_kind;
NSDictionary *_identifierToSegueMap;
NSStoryboard *_storyboard;
}
- (id) target;
@ -95,6 +96,12 @@ extern "C" {
- (NSString *) kind;
- (void) setKind: (NSString *)kind;
- (NSDictionary *) identifierToSegueMap;
- (void) setIdentifierToSegueMap: (NSDictionary *)table;
- (NSStoryboard *) storyboard;
- (void) setStoryboard: (NSStoryboard *)storyboard;
- (IBAction) doAction: (id)sender;
@end

View file

@ -37,11 +37,19 @@
#import "AppKit/NSStoryboard.h"
#import "AppKit/NSStoryboardSegue.h"
#import "AppKit/NSNibDeclarations.h"
#import "AppKit/NSViewController.h"
#import "AppKit/NSWindowController.h"
#import "GSStoryboardTransform.h"
#import "GSFastEnumeration.h"
@interface NSStoryboardSegue (__private__)
- (void) _setDestinationController: (id)controller;
- (void) _setSourceController: (id)controller;
@end
@interface NSStoryboardSegue (__StoryboardPrivate__)
// Private to this class...
- (void) _setKind: (NSString *)k;
- (void) _setRelationship: (NSString *)r;
- (NSString *) _kind;
@ -132,15 +140,67 @@
ASSIGN(_kind, kind);
}
- (NSDictionary *) identifierToSegueMap
{
return _identifierToSegueMap;
}
- (void) setIdentifierToSegueMap: (NSDictionary *)table
{
ASSIGN(_identifierToSegueMap, table);
}
- (NSStoryboard *) storyboard
{
return _storyboard;
}
- (void) setStoryboard: (NSStoryboard *)storyboard
{
ASSIGN(_storyboard, storyboard);
}
- (id) nibInstantiate
{
return self;
}
- (void) dealloc
{
RELEASE(_storyboard);
RELEASE(_identifierToSegueMap);
RELEASE(_kind);
RELEASE(_identifier);
RELEASE(_sender);
[super dealloc];
}
- (IBAction) doAction: (id)sender
{
[_sender performSegueWithIdentifier: _identifier
sender: _sender];
if (_sender != nil)
{
[_sender performSegueWithIdentifier: _identifier
sender: _sender];
}
else // This is a special case where there is no source controller and we don't ask "should"
{
NSMapTable *mapTable = [_identifierToSegueMap objectForKey: @"application"];
NSStoryboardSegue *segue = [mapTable objectForKey: _identifier];
id destCon = nil;
if ([[segue destinationController] isKindOfClass: [NSViewController class]] ||
[[segue destinationController] isKindOfClass: [NSWindowController class]])
{
destCon = [segue destinationController];
}
else
{
NSString *destId = [segue destinationController];
destCon = [_storyboard instantiateControllerWithIdentifier: destId];
}
[segue _setSourceController: nil];
[segue _setDestinationController: destCon]; // replace with actual controller...
[segue perform];
}
}
- (id) copyWithZone: (NSZone *)z
@ -150,6 +210,8 @@
[pa setSelector: [self selector]];
[pa setSender: _sender];
[pa setIdentifier: _identifier];
[pa setIdentifierToSegueMap: _identifierToSegueMap];
[pa setStoryboard: _storyboard];
return pa;
}
@ -292,16 +354,16 @@
return _documentsMap;
}
- (NSDictionary *) identifierToSegueMap
{
return _identifierToSegueMap;
}
- (NSMapTable *) segueMapForIdentifier: (NSString *)identifier
{
return [_identifierToSegueMap objectForKey: identifier];
}
- (NSDictionary *) identifierToSegueMap
{
return _identifierToSegueMap;
}
- (NSXMLElement *) createCustomObjectWithId: (NSString *)ident
userLabel: (NSString *)userLabel
customClass: (NSString *)className
@ -336,16 +398,9 @@
return [xml XMLData];
}
- (NSData *) dataForSceneId: (NSString *)sceneId
{
NSXMLDocument *xml = [_scenesMap objectForKey: _applicationSceneId];
NSData *xmlData = [xml XMLData];
return xmlData;
}
- (NSData *) dataForApplicationScene
{
return [self dataForSceneId: _applicationSceneId];
return [self dataForIdentifier: @"application"];
}
- (void) processStoryboard: (NSXMLDocument *)storyboardXml
@ -392,7 +447,9 @@
// Assign application scene...
ASSIGN(_applicationSceneId, sceneId);
[_controllerMap setObject: _applicationSceneId
forKey: @"application"];
// Move all application children to objects...
while ((ae = [ace nextObject]) != nil)
{
@ -464,8 +521,6 @@
[doc addChild: child];
}
// Add other custom objects...
// fix other custom objects
document = [[NSXMLDocument alloc] initWithRootElement: doc]; // put it into the document, so we can use Xpath.
NSArray *windowControllers = [document nodesForXPath: @"//windowController" error: NULL];
@ -659,10 +714,10 @@
attr = [obj attributeForName: @"id"];
NSString *uid = [attr stringValue];
attr = [obj attributeForName: @"identifier"];
NSString *identifier = [attr stringValue];
if (identifier == nil)
NSString *ident = [attr stringValue];
if (ident == nil)
{
identifier = [[NSUUID UUID] UUIDString];
ident = [[NSUUID UUID] UUIDString];
}
// Create proxy object to invoke methods on the window controller
@ -679,7 +734,7 @@
stringValue: pident_value];
NSXMLNode *psegueIdent
= [NSXMLNode attributeWithName: @"identifier"
stringValue: identifier];
stringValue: ident];
NSXMLNode *psender
= [NSXMLNode attributeWithName: @"sender"
stringValue: src];
@ -709,17 +764,17 @@
NSXMLNode *target
= [NSXMLNode attributeWithName: @"target"
stringValue: pident_value];
NSXMLNode *ident
NSXMLNode *controller_ident
= [NSXMLNode attributeWithName: @"id"
stringValue: uid];
[action addAttribute: selector];
[action addAttribute: target];
[action addAttribute: ident];
[action addAttribute: controller_ident];
[segue_parent addChild: action];
}
// Create the segue...
NSStoryboardSegue *ss = [[NSStoryboardSegue alloc] initWithIdentifier: identifier
NSStoryboardSegue *ss = [[NSStoryboardSegue alloc] initWithIdentifier: ident
source: src
destination: dst];
[ss _setKind: kind];
@ -727,7 +782,7 @@
// Add to maptable...
[mapTable setObject: ss
forKey: identifier];
forKey: ident];
} // only process segue objects...
} // iterate over objects in each set of connections

View file

@ -147,19 +147,7 @@ static NSStoryboard *__mainStoryboard = nil;
- (void) _instantiateApplicationScene
{
NSDictionary *table;
table = [NSDictionary dictionaryWithObject: NSApp
forKey: NSNibOwner];
GSModelLoader *loader = [GSModelLoaderFactory modelLoaderForFileType: @"xib"];
BOOL success = [loader loadModelData: [_transform dataForApplicationScene]
externalNameTable: table
withZone: [self zone]];
if (!success)
{
NSLog(@"Unabled to load Application scene");
}
[self instantiateControllerWithIdentifier: @"application"];
}
- (id) instantiateInitialController
@ -240,6 +228,8 @@ static NSStoryboard *__mainStoryboard = nil;
{
NSStoryboardSeguePerformAction *ssa = (NSStoryboardSeguePerformAction *)o;
[ssa setSender: result]; // resolve controller here...
[ssa setIdentifierToSegueMap: [_transform identifierToSegueMap]];
[ssa setStoryboard: self];
if ([[ssa kind] isEqualToString: @"relationship"]) // if it is a relationship, perform immediately
{
[seguesToPerform addObject: ssa];