Two of a kind
Windows can be either dialogs or palettes (at least in Photoshop). They look and are substantially different.
Open the ExtendScript ToolKit (ESTK) and run the following code:
The result (it runs in ESTK, since the first line is the preprocessing directive
#target estoolkit) is as follows:
In ESTK run the following code:
Compared to the first script, there’s little difference (the windowResource string contains
dialog instead of
palette) and the Window looks like this:
We’re still within ESTK: the red, closing button is disappeared, the titlebar is bigger, but the main difference is that dialogs are modal: that is, the focus is on them and you can not interact with the host application. If you try to select, say, a menu item the program complains with a beep.
In the ScriptUI for Dummies guide it’s asserted that Photoshop doesn’t support palette windows. While the more hours I spend debugging unwanted behaviors the more I tend to agree with Peter Kahrel, I would personally express the statement as follows:
Photoshop supports both dialog and palette Windows; while the former kind’s behavior is consistent with other CS applications, palette implementation in PS is peculiar and version/platform dependent.
PS dialogs implementation
It’s basically what you’d expect - a modal window (which aspect depends on the PS version and platform). Yet the behavior is exactly the same no matter what is the combination, PC/Mac - CS5/CS6. In order to test it, just change the first line of the two scripts above:
One thing to notice is that PC versions have a red X closing button, while Mac versions do not (for some reason, CS5 rendering of the slider bar is thicker compared to CS6).
PS palettes implementation
Here things get “interesting”. First, if you run the palette example with
#target photoshop you’re not going to see very much. The Window that you expect to see just flashes briefly and disappear. This is what will happen to every Snp*.jsx examples provided alongside with the ESTK application, not just my code. The answer lies in the fact that palettes keep showing only if there’s something going on in the script, they can not stay idle waiting for the user to do something like modal dialogs do.
In the above example, after the
win.show() the script is busy creating a new document, applying and blurring some noise just to kill some time. In the meantime, the palette window shows and keep showing; when the script is done with the task, the palette is automatically closed with no need of user interaction whatsoever, nor explicit
win.close(). In order to keep Photoshop busy, I’ve found two working alternatives (because a straight
$.sleep() loop makes PS quite non-responsive) involving the following functions:
The comments in the code should be self-explanatory. As far as I know,
waitForRedraw() should work also in earlier PS versions - it’s not documented, it’s just used in one Reference’s demo scripts.
PS palette working example
One possible way to implement working palette Windows in Photoshop has the following logic:
The key point is the
isDone variable, which is set false at the beginning. After the Window is shown, a while loop keeps checking for this sentinel value and call
app.refresh(), or alternatively
waitForRedraw() in order to keep the palette showing. Instead of an explicit call to
win.close(), it’s a better option to attach to the buttons’
onClick() functions a sentinel value’s switch to true. This way the while loop breaks and the Window automatically closes.
Mind you, it’s crucial to set
isDone = true even in the
win.onClose() function, otherwise Photoshop will keep evaluating the variable even after the Window has been closed clicking the red dismiss button (see following screenshot) - resulting in some degree of non-responsiveness.
Few cosmetic differences are present this time too, including the position of the dismiss button (top-left for Mac, top-right for PC). This button is taken into account with the
onClose() function as shown in the code example.
Platform specific behaviors (aka bugs)
Things are getting weird if you start to compare Mac and PC implementations of ScriptUI windows in Photoshop CS5 and CS6 (the tests on the PC side have been made on a virtualized Window7 system running in Parallels Desktop). It happens that, depending on how you mix platform, version and Window type, you end up with different behaviors (modal and non-modal), as follows:
While dialog’s behavior is nicely uniform between Mac and PC, CS5 and CS6; palettes are a fiasco. Mac behavior is always non-modal (as it should be - palettes are non-modal by definition), while PC’s one depends on the Photoshop version and function used. Basically, only CS5 with app.refresh() works as it’s supposed to do, while in CS6 both functions fail. From my personal standpoint, this is a bug - and I haven’t found any workaround yet.
To sum up:
- Palettes are defined within Creative Suite applications as non-modal Windows that can wait idle.
- The Photoshop implementation misses entirely the “can wait idle” part - palettes keep showing only if there’s some code running in background.
- There’s a workaround to make palettes behave as they’re supposed to do, involving either
waitForRedraw()loops and a sentinel variable.
- On Mac the workaround, no matter on CS5 and CS6 or what function is used, makes the palettes non-modal (as they’re supposed to be by definition)
- On PC, only app.refresh() in CS5 returns a non-modal Window - CS6 ones are always modal.
Which is quite a pain in the neck, especially if you need your palettes to work as they’re supposed to do in a platform and version independent way.