Responder chain

13 views
Skip to first unread message

Andy Balholm

unread,
Jul 3, 2009, 10:45:28 AM7/3/09
to cocotr...@googlegroups.com
(I sent a message about this before, but I think it got blocked by the spam filter.)

I noticed that the responder chain does not include the current document. Here is my idea for how to fix that. It also makes target-action handling more consistent, routing all actions with targetForAction:to:from:

We would add one method to NSApplication, and replace three others:

-_sameWindowTargetForAction:(SEL)action to:target {
  // Search just one window's responder chain.

  

  if ([target respondsToSelector:action])
    return target;

  

  if ([target respondsToSelector:@selector(nextResponder)]) 
    {
      target = [target nextResponder];
      while (target != nil
        {
          if ([target respondsToSelector:action])
            return target;

          

          if ([target isKindOfClass:[NSWindow class]]) 
            {
              if ([[target delegate] respondsToSelector:action])
                return [target delegate];
              if ([[target windowController] respondsToSelector:action])
                return [target windowController];
            }

          

          target = [target nextResponder];
        }
    }

  

  return nil;
}

-targetForAction:(SEL)action {
  return [self targetForAction:action to:nil from:nil];
}

-targetForAction:(SEL)action to:target from:sender {
  if (target == nil
    {
      target = [self _sameWindowTargetForAction:action to:[[self keyWindow] firstResponder]];
      if (target)
        return target;

      

      if ([self mainWindow] != [self keyWindow]) 
        {
          target = [self _sameWindowTargetForAction:action to:[[self mainWindow] firstResponder]];
          if (target)
            return target;
        }
    }
  else 
    {
      target = [self _sameWindowTargetForAction:action to:target];
      if (target)
        return target;
    }

  

  NSDocumentController *documentController = [NSDocumentController sharedDocumentController];
  if ([[documentController currentDocument] respondsToSelector:action])
    return [documentController currentDocument];

  

  if([self respondsToSelector:action])
    return self;

  

  if([[self delegate] respondsToSelector:action])
    return [self delegate];

  

  if([documentController respondsToSelector:action])
    return documentController;

  

  return nil
}

-(BOOL)sendAction:(SEL)action to:target from:sender {
  if([target respondsToSelector:action])
    {
      [target performSelector:action withObject:sender];
      return YES;
    }

  

  target=[self targetForAction:action to:target from:sender];
  if (target != nil
    {
      [target performSelector:action withObject:sender];
      return YES;
    }

  

  return NO;
}



Reply all
Reply to author
Forward
0 new messages