On 21 Nov 2013, at 22:29, jonat...@mugginsoft.com wrote:

> Looking at the action responder chain for a document based app (fig 1-10):
> https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/EventArchitecture/EventArchitecture.html
> 
> This shows that the action responder chain extends past the window controller 
> up to the document controller.
> 
> Sometimes I want to respond to an action and then forward it on up the 
> responder chain like so:
> [self.nextResponder tryToPerform:selector with:sender];
> 
> However, in this case the responder chain followed terminates at the window 
> controller (as does the event message window controller).
> This means that higher level items like NSDocument etc are never queued as 
> part of the chain search.
> 
> Will I have to manually patch up the responder chain to include the higher 
> level items when doing this sort of thing? 
> 
I guess the answer is yes.
The following has been included in 
https://github.com/mugginsoft/XSViewController

Jonathan

#import "NSResponder+XSViewController.h"

NSString *XSVChainTypeKey = @"ChainType";

@implementation NSResponder (XSViewController)

#pragma mark -
#pragma mark Event responder chain

- (NSArray *)xsv_eventResponderChain
{
   return [self xsv_eventResponderChainFromResponder:nil];
}

- (NSArray *)xsv_eventResponderChainFromSelf
{
   return [self xsv_eventResponderChainFromResponder:self];
}

- (NSArray *)xsv_eventResponderChainFromResponder:(NSResponder *)responder
{
   return [self xsv_responderChainFromResponder:responder 
options:@{XSVChainTypeKey: @(XSVEventChainType)}];
}

#pragma mark -
#pragma mark Action responder chain

- (NSArray *)xsv_actionResponderChain
{
   return [self xsv_actionResponderChainFromResponder:nil];
}

- (NSArray *)xsv_actionResponderChainFromSelf
{
   return [self xsv_actionResponderChainFromResponder:self];
}

- (NSArray *)xsv_actionResponderChainFromResponder:(NSResponder *)responder
{
   return [self xsv_responderChainFromResponder:responder 
options:@{XSVChainTypeKey: @(XSVActionChainType)}];
}

#pragma mark -
#pragma mark Responder chain construction

- (NSArray *)xsv_responderChainFromResponder:(id)initialResponder 
options:(NSDictionary *)options
{
   // Chain should conform to description given here:
   // 
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW2

   NSMutableArray *chain = [NSMutableArray arrayWithCapacity:10];

   // If no initial responder then use the window first responder
   if (!initialResponder) {
       if (![self respondsToSelector:@selector(window)]) {
           return chain;
       }
       NSWindow *window = [(id)self window];

       initialResponder = [window firstResponder];
   }

   // This is going nowhere...
   if (!initialResponder) {
       return chain;
   }

   // Probe the accessible chain. By default this will be the event chain
   NSResponder *responder = initialResponder;
   do {
       [chain addObject:responder];
   } while ((responder = responder.nextResponder));

   responder = [chain lastObject];

   // Append action responder chain items
   if ([options[XSVChainTypeKey] integerValue] == XSVActionChainType) {

       // A window is required
       if (![self respondsToSelector:@selector(window)]) {
           return chain;
       }
       NSWindow *window = [(id)responder window];
       if (!window) {
           return chain;
       }

       // Append the top level action responder chain
       NSArray *actionTopLevelChain = [self 
xsv_actionResponderChainAboveControllerForWindow:window];
       [chain addObjectsFromArray:actionTopLevelChain];
   }

   return chain;
}

- (NSArray *)xsv_actionResponderChainAboveControllerForWindow:(NSWindow *)window
{
   // Chain should conform to description given here:
   // 
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/eventoverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW2

   id windowDelegate  = [window delegate];
   NSWindowController *windowController = [window windowController];
   NSDocument *document = [windowController document];
   id appDelegate = [NSApp delegate];
   NSMutableArray *chain = [NSMutableArray arrayWithCapacity:5];

   if (!window) {
       return chain;
   }

   if (windowDelegate) {
       [chain addObject:windowDelegate];
   }

   if (document) {
       [chain addObject:document];
   }

   [chain addObject:NSApp];

   if (appDelegate) {
       [chain addObject:appDelegate];
   }

   if (document) {
       [chain addObject:[NSDocumentController sharedDocumentController]];
   }

   return chain;
}
@end


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to