PS palettes

ScriptUI Window in Photoshop – Palette vs. Dialog

Davide Barranca — 

ExtendScript – one of the scripting languages supported by Creative Suite applications, and the only one cross-platform – has several extra features compared to Javascript. Besides Filesystem access (a notable addition), there’s the ScriptUI component: which allows you to add graphic user interfaces (GUI) to scripts.

Photoshop support is dated to CS2, according to the unofficial (yet essential) ScriptUI for Dummies guide made by Peter Kahrel. As it happens often in scripting CS applications, the implementation of some feature is version and platform dependent – i.e. PS CS5 on PC is different from PS CS6 on Mac. In this post I’m going to focus on one particular aspect of ScriptUI, namely the Window object.

Two of a kind

Windows can be either dialogs or palettes (at least in Photoshop). They look and are substantially different.

Palettes

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:

ESTK palette

The above is a palette, a non-modal window. Something that lets you interact either with the window itself (clicking buttons, dragging sliders, etc) and with the host program – here the ESTK (so you can select, say, menu items, other panels, etc.). It’s the Javascript equivalent of Panels and third party Extensions – they show up and wait there, letting you work with Photoshop.

Dialogs

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:

ESTK dialog

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.

Photoshop support

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:

 

PS dialogs

First row: Mac CS5, Mac CS6.
Second row: PC CS5, PC CS6.

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.

PS palettes

First row: Mac CS5, Mac CS6.
Second row: PC CS5, PC CS6.

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:

Behavior Table

Comparison of the ScriptUI Window type’s behavior (modal or non-modal) against Photoshop version and platform.

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.

Conclusion

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 app.refresh() or 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.

Print Friendly
Share

14 responses to ScriptUI Window in Photoshop – Palette vs. Dialog

  1. Thanks! I’ve just started trying to figure out making dialog boxes and this really helps with my early problems making a ‘palette’ type window. Just what I was looking for.

  2. Thanks! But why for waitng loop you didn’t use simpler:
    while(isDone)
    counter++

    • Hello Mikhail,
      without any app.refresh() or waitForRedraw() continuously keeping the palette up in the loop, it would close instantly. So to speak, the loop isn’t just “wait, wait..”, but “wait and stand up, wait and stand up…”.
      Davide

  3. I have a palette window with a cancel button. I use the Window.update() function to update a progress bar and panel text during the long process. But while my script is active, the cancel button becomes useless. Is there a way to use a palette window and still be able to interact with the window while the script is running? I want a cancel button for those instances that you start running the 2 minute script and think, “Oooh, should have done something before running that.”

    Thanks!

    • That’s strange: the Doc says: “Use this method to perform the necessary synchronous drawing updates, and also process certain mouse and keyboard events in order to allow a user to cancel the current operation (by clicking a Cancel button, for instance).“. Is your palette up because a BridgeTalk or a refresh() loop? In the fist case it could be the fact that BridgeTalk is asynchronous, so you may try to make the Cancel button throw an error (to see if the underlying script stops). Another test you can try is to switch momentarily to a ‘dialog’ window and see if the Cancel button actually stops the process.

  4. kind of a newb question but say I wanted to access the slider on your “PS palette working example”, I tried Window.sl.Slider.value but that doesnt seem to work?

    • Hello AJ,
      win.sliderPanel.sl.value should do the trick. You basically have to track the slider with the full path, so it’s within the win Window, the sliderPanel Panel, the sl Slider (and eventually its “.value”).
      Hope this helps!

      • Thanks that did help! One thing I notice, and maybe this is part of the limitations you were talking about, is that nothing updates as I use the slider. The value stays at the defined number in the script even when I move it and hit apply. Ideally I would like photoshop to update as I move the slider but maybe thats not possible?

        • Hi AJ,
          of course it doesn’t update because the lazy author didn’t put the event listener in the code!
          I just put up a dummy palette so there’s no slider-text binding. If you want to implement it, paste the following before the Button listeners:
          win.sliderPanel.sl.onChange = function() {
          win.sliderPanel.te.text = Math.round(this.value);
          }

          And you may figure out yourself what function to add in order to make the slider update when you input the text! 😉
          Or just look in the SnpCreateSlider.jsx which is in the ExtendScript Toolking SDK/Samples/Javascript folder for a full working example of a slider.
          (Lots of interesting snippets there too!)

  5. Matias Kiviniemi October 9, 2013 at 6:13 PM

    I have a problem that my palette works as expected in Win, but is left behind the Photohop window under Mac. Is that what you mean by “modal/non-modal”? I mean both are non-modal in the sense that win.show() does not stop the script. Any ideas how you could keep the palette from going behind Photoshop?

    • Hi Matias,
      yes, the modal means that you can’t do anything but interact with the dialog – if the script doesn’t halt and wait for the dialog result, it’s modeless. Yet it’s strange it hides behind PS. You can try this one: in theory, a palette can be hidden (not a dialog: when you hide it, it closes), so you could:
      win.hide();
      $.sleep(500);
      win.show();

      Alternatively, try to force a win.update().
      With CC, Palettes are even less functional so the best way is to use BridgeTalk as I’ve demoed here.

  6. Great info Davide, very helpful, thank-you.
    In return, I discovered this:
    In answer to “The Window that you expect to see just flashes briefly and disappear”, I found that just adding a null function keeps the palette open.

    eg.

    var w = new Window ("palette");
    w.show ();

    function keepMeOpen(){}

    There may be a reason as to why this isn’t viable, you’ll know better than myself, but it may prove to be a starting point on which to expand?
    I dunno, it works for me and thought I’d post it just in case its of use.

    Regards.
    MrTom.

Trackbacks and Pingbacks:

  1. 神器:帮助你在电脑屏幕将设计显示为真实尺寸的PS脚本 - March 10, 2013

    […] 使用Mac的用户。目前已经知道脚本窗口无法关闭的原因。有编程经验的可以参考这篇文章修改代码。http://t.cn/zYmNvSl 其他同学请关注代码更新。 […]