• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: AppleScript Challenge
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AppleScript Challenge


  • Subject: Re: AppleScript Challenge
  • From: Axel Luttgens <email@hidden>
  • Date: Sun, 03 Oct 2004 17:12:06 +0200

Brett Kirksey wrote:
Okay, my first post of this didn't get a response, so I thought I'd just issue a challenge in the subject line to get someone's (anyone's) attention. :-)

I'm working on a script library saved as an application. I've
ran into something I can't figure out, so I thought one of you
guys may know what's going on.

Here's an example. Let's say you make a script with only the
following code:

    on makeFinderWindow()
        tell application "Finder"
            set bar to make new Finder window
            return bar
        end tell
    end makeFinderWindow

Now save it as a script _application_ named "Foo".

This means that you have defined a script object.
In an attempt to translate this in an object-oriented jargon, that script object will behave, when running, as an instance of an application class "foo".

Now make another script with only this code:

    set newWindow to makeFinderWindow() of application "Foo"
    tell application "Finder" to close newWindow

Run this script. It generates an error that <<class brow>>
doesn't understand the close command. If you comment out the
"close window" command, you can see the result of the script is
"Finder window id nn of application 'Foo'".
With the above, this seems to be rather logical.
Variable newWindow is set to some "Finder window" object belonging to application foo; even if its displayed class and ID sound familiar, this is an illusion: newWindow must be viewed as some kind of opaque object brought by and known through foo.
When the Finder is told to close that object, it notes that it is not one of its own objects; the Finder thus sends the close command to the object, which obviously doesn't know how to handle it (because we have not defined a handler for that command) [1].

But if you run the handler makeFinderWindow() from within "Foo",
the result is "Finder window id nn of application 'Finder'".
Yes, because "foo" got that reference directly from the Finder application.
 So,
when "Foo" passes the new finder window of "Finder" to the
calling script, it becomes a finder window of "Foo" instead and
then you can't work with it.

I've tried this with several different apps and several
different classes of objects, and it does the same thing. I just
know I'm missing something obvious, so I'm feeling pretty dumb.
Can someone enlighten me?
It is a consequence of the object paradigm (as implemented by AppleScript, would some people add).
An object is either of a well-known nature, that knowledge being brought by a set a basic classes (AppleScript being in the inheritance chain of every script, these are for example integers, lists, strings, records...).
Or it is just an object stemming from/belonging to another one (and it is then assumed that the latter knows what to do with the first).

Shouldn't it be that way, any script would need to have an instantaneous universal knowledge of every object of every possible application, existing or to be written.

So, what are the workarounds?

First, there is Emmanuel's proposal to use window IDs.
In fact, this relies upon the fact that numbers (numeric objects) are known by every application by means of AppleScript itself; you may think about them as "integer of script applescript".
In counterpart, that approach requires that YOU tell the correct app (the Finder) to use such a number as a window ID.

Another way is to go further with the object logics.
Since foo's makeFinderWindow() returns a kind of opaque object, one could be tempted to ask foo to close that object too; let's thus try:
-- This is an attempt

on makeFinderWindow()
    tell application "Finder"
        set bar to make new Finder window
        return bar
    end tell
end makeFinderWindow

on closeFinderWindow(W)
    close W
end closeFinderWindow
and rewrite the calling script as:
set newWindow to makeFinderWindow() of application "foo"
tell application "foo" to closeFinderWindow(newWindow)
The close command doesn't work much better :-(
In fact, closeFinderWindow() is unable to even fetch an object `«class brow» id NNN`.
Note that when requested to create a window, foo returns that window and immediately forgets it.
Moreover, when passed back to foo, any relationship to the Finder is now lost.

No problem ;-)
Let's rewrite foo as [2]:
-- This is script foo v2

property parent : application "Finder"

on makeFinderWindow()
    make new «class brow»
end makeFinderWindow

on closeFinderWindow(W)
    close W
end closeFinderWindow
This works because foo now knows where to find a `«class brow» id NNN` object and what to do with a close command sent to it: just ask the parent.

But it then becomes clear that there was no need to let the window reference go outside of foo; the whole thing may be rewritten as [3]:
-- This is script foo v3

property parent : application "Finder"
property bar : ""

on makeFinderWindow()
    set bar to make new  «class brow»
end makeFinderWindow

on closeFinderWindow()
    close bar
end closeFinderWindow

-- This is the calling script

tell application "foo"
    makeFinderWindow()
    closeFinderWindow()
end tell
Hmm... not sure I managed to say something clever.
HTH anyway,
Axel


[1] It is not obvious to see that the close command is sent to that elusive "Finder window". One may try to "demonstrate" that point by returning a slightly richer object:
-- Script foo revisited

script |Finder window|
end script

on close
    display dialog "Close event"
end close

on makeFinderWindow()
    tell application "Finder" to make new Finder window
    return a reference to |Finder window|
end makeFinderWindow
The result of the `set newWindow to makeFinderWindow() of application "foo"` statement is then:
    |Finder window| of application "foo"
while the `tell application "Finder" to close newWindow` statement will raise a dialog box.

[2] One needs to write "«class brow»" instead of "Finder window", because properties are set at run time, thus too late for the compiler to know that it has to look into Finder's dictionary.

[3] Of course, it may happen that you don't want the Finder to be foo's parent:
-- This is script foo v4

property bar : ""

on makeFinderWindow()
    tell application "Finder"
        set bar to make new Finder window
    end tell
end makeFinderWindow

on closeFinderWindow()
    close bar
end closeFinderWindow
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Applescript-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Prev by Date: Re: AppleScript Formatting - Strings
  • Next by Date: Re: Variable Ponderance
  • Previous by thread: Re: Happy endings
  • Next by thread: Re: AppleScript Challenge
  • Index(es):
    • Date
    • Thread