Make use of NSInvocation

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@17346 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2003-07-26 06:27:50 +00:00
parent b21fa21aa1
commit 5db7bc0ebd
3 changed files with 71 additions and 6 deletions

View file

@ -1,3 +1,10 @@
2003-07-26 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSApplication.m: Use NSInvocation to perform actions, so
we can handle cases where the action method returns a non-id or
misses an argument.
* Source/NSResponder.m: ditto
2003-07-26 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSImage.m

View file

@ -1568,22 +1568,45 @@ IF_NO_GC(NSAssert([event retainCount] > 0, NSInternalInconsistencyException));
DPSPostEvent(GSCurrentServer(), event, flag);
}
/*
* Sending action messages
/**
* Sends the aSelector message to the receiver returned by the
* -targetForAction:to:from: method (to which the aTarget and sender
* arguments are passed).<br />
* The method in the receiver must expect a single argument ...
* the sender.<br />
* Any value returned by the method in the receiver is ignored.<br />
* This method returns YES on success, NO on failure (when no receiver
* can be found for aSelector).
*/
- (BOOL) sendAction: (SEL)aSelector to: (id)aTarget from: (id)sender
{
id resp = [self targetForAction: aSelector to: aTarget from: sender];
if (resp)
if (resp != nil)
{
[resp performSelector: aSelector withObject: sender];
NSInvocation *inv;
NSMethodSignature *sig;
sig = [resp methodSignatureForSelector: aSelector];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv setSelector: aSelector];
if ([sig numberOfArguments] > 2)
{
[inv setArgument: &sender atIndex: 2];
}
[inv invokeWithTarget: resp];
return YES;
}
return NO;
}
/**
* If theTarget responds to theAction it is returned, otherwise
* the application searches for an object which will handle
* theAction and returns the first object found.<br />
* Returns nil on failure.
*/
- (id) targetForAction: (SEL)theAction to: (id)theTarget from: (id)sender
{
/*
@ -1693,6 +1716,12 @@ IF_NO_GC(NSAssert([event retainCount] > 0, NSInternalInconsistencyException));
return nil;
}
/**
* Attempts to perform aSelector using [NSResponder-tryToPerform:with:]
* and if that is not possible, attempts to get the application
* delegate to perform the aSelector.<br />
* Returns YES if an object was found to perform aSelector, NO otherwise.
*/
- (BOOL) tryToPerform: (SEL)aSelector with: (id)anObject
{
if ([super tryToPerform: aSelector with: anObject] == YES)
@ -1701,7 +1730,17 @@ IF_NO_GC(NSAssert([event retainCount] > 0, NSInternalInconsistencyException));
}
if (_delegate != nil && [_delegate respondsToSelector: aSelector])
{
[_delegate performSelector: aSelector withObject: anObject];
NSInvocation *inv;
NSMethodSignature *sig;
sig = [_delegate methodSignatureForSelector: aSelector];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv setSelector: aSelector];
if ([sig numberOfArguments] > 2)
{
[inv setArgument: &anObject atIndex: 2];
}
[inv invokeWithTarget: _delegate];
return YES;
}
return NO;

View file

@ -28,6 +28,7 @@
#include "gnustep/gui/config.h"
#include <Foundation/NSCoder.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSInvocation.h>
#include "AppKit/NSResponder.h"
#include "AppKit/NSApplication.h"
#include "AppKit/NSMenu.h"
@ -96,12 +97,30 @@
return NO;
}
/**
* If the receiver responds to anAction, it performs that method with
* anObject as its argument, discards any return value, and return YES.<br />
* Otherwise, the next responder in the chain is asked to perform
* anAction and the result of that is returned.<br />
* If no responder in the chain is able to respond to anAction, then
* NO is returned.
*/
- (BOOL) tryToPerform: (SEL)anAction with: (id)anObject
{
/* Can we perform the action -then do it */
if ([self respondsToSelector: anAction])
{
[self performSelector: anAction withObject: anObject];
NSInvocation *inv;
NSMethodSignature *sig;
sig = [self methodSignatureForSelector: anAction];
inv = [NSInvocation invocationWithMethodSignature: sig];
[inv setSelector: anAction];
if ([sig numberOfArguments] > 2)
{
[inv setArgument: &anObject atIndex: 2];
}
[inv invokeWithTarget: self];
return YES;
}
else