Re: Implementing behavior for "make" appleevent in Cocoa App
Re: Implementing behavior for "make" appleevent in Cocoa App
- Subject: Re: Implementing behavior for "make" appleevent in Cocoa App
- From: "Neal A. Crocker" <email@hidden>
- Date: Mon, 3 Sep 2001 18:31:31 -0700
Thanks for taking the time to reply Brian.
On Sunday, September 2, 2001, at 11:27 PM, Neal A. Crocker wrote:
I'm not absolutely posittive, but I believe create/make commands
are actually sent to the current Applescript "tell target"
(assuming that that object has a method to handle it), which must,
of course be able to contain the kind of object which is to be
created. For instance, suppose the .scriptSuite file of the
application specifies NSCoreSuite.Create as a supported commmand
for the application/NSApplication object, indicating that it is to
be handled by the "handleCreateCommand:" method. Suppose also
that NSApplictation is given a "handleCreateCommand:" method (by
using the categories mechanism, or subclassing). The following
Applescript would cause a create/make event to be sent to the
application/NSApplication object (thus invoking
"handleCreateCommand:" method of NSApplication object) asking for
the creation of a document/(NSDocument subclass) object:
tell application "Some Cocoa App.app"
make new document at before front document
end tell
This hypothesis can be easily tested, of course, and I mean to do
it eventually.
I just tested this myself, and it does seem to work. It looks like
all create commands are sent to the application object, regardless
of the current tell target or even the insertion container. To do
it, I just added NSCoreSuite.Create to NSApplication's
SupportedCommands dictionary and specified a method,
handleCreateScriptCommand:, which is now declared as a category on
NSApplication. I did the same to SKTDrawDocument, but like I said,
it looks like NSApplication handles all create commands.
For tests, I ran the following scripts on Sketch, and all invoked
the same method on NSApplication:
tell application "Sketch" to make new document at end of documents
tell application "Sketch" to make new circle at end of graphics of
front document
tell front document of application "Sketch" to make new circle at
end of graphics
This is startling. Disturbing even. An obect which can contain some
other type of object should be given first crack at creating one,
since container objects might reasonably be expected to know how to
create objects that they contain (or where to delegate the task). It
seems unreasonable that the application object should be exepected to
know how create every kind of object which can be contained by any
container in its container hierarchy. That would lead to rewriting
or overloading the NSApplication "handleCreateCommand:" method every
time the container hierarchy was modified or extended. I'd like to
play around with this a little. Any chance you could email me the
project you made to test this, or post it somewhere (like your Itools
website)? Failing that, from your description of what you did, it
should be easy enough to recreate your example. Another question
that arises is whether the create command is given special handling
compared to other script commands at some internal cocoa level with
regards to deciding where it should be sent. If so, that's not only
bad, but not necessary, based on the argument I outlined above. If
all commands are handled as you discovered for the create command
(i.e. the command is sent to the application object regardless of the
tell target), implementing script command behavior for objects deep
in an application's container hierarchy could be tricky and/or messy.
I played around with the Sketch example project and the debugger
after my original post on this thread what I saw is entirely
consistent with your conclusions about NSCreateCommand.
Specifically, I put a break in the init method for the Sketch
document class and used Applescript to send a "make new document"
event to Sketch. Near as I can tell, NSCreateCommand does have a
(totally undocumented) "performDefaultImplementation:" method which
eventually calls the "init:" method for an instance of the kind of
object to be created.
I also found another way to override create commands by making my
own command class and declaring it in the Sketch scripting
dictionary. I basically put a duplicate of the Create entry in
NSCoreSuite's Commands dictionary, except with the CommandClass
being set to my own "SKTCreateCommand" subclass of NSCreateCommand.
Of course, to do this you also have to specify that AbstractObject
will respond to "Sketch.Create" and not just "NSCoreSuite.Create",
or you'll get an error saying that the receiver can't handle the
command.
That makes sense. What if, instead of specifying that AbstractObject
handles Sketch.Create, you simply specify that
document/SKTDrawDocument supports the Sketch.Create command with no
handler specified while insuring that your SKTCreateCommand command
is a totally transparent wrapper for NSCreateCommand?
Of particular interest, this documentation page says:
"The description of a class (in a suite definition) includes a
section for commands supported by the class. In this section you
can either indicate that the default implementation (WHICH IS BASED
ON KEY-VALUE CODING) for a command is sufficient, or you can
specify a method that you want to handle the command when it is
executed...." (The emphasis supplied by using all caps is mine.)
I think this is just saying that the default implementation
retrieves all of the objects pointed to by the object specifiers
passed into the command via key-value coding. In your own
implementation, you could choose to evaluate the object specifiers
manually instead of using key-value coding.
Perhaps. It sounds ambiguous to me. On the other hand, given the
total lack of any other statements supporting my interpretation
anywhere in the developer documentation (as far as I can find),
you're probably right.
--
Brian Webster
email@hidden
http://www.owlnet.rice.edu/~bwebster
Thanks,
Neal