Skip to main content
Inspiring
December 19, 2016
Answered

Is it possible to show a waiting message while a script is executing?

  • December 19, 2016
  • 3 replies
  • 2778 views

I have a few scripts that take quite a long time to execute (15 seconds typically) and I would like to display some sort of Waiting message (change cursor to hourglass for example).

I can change the tool to something like the Hand tool while the script is executing and then change it back to the selected tool ... which is sort of OK but not exactly very user-friendly (the Hand tool itself could well have already been selected!)

Thanks

Robert

This topic has been closed for replies.
Correct answer xbytor2

Here is code that I have used in one form another for close to a decade. It is also used in releases of ImageProcessorPro and CSX so it has been fairly well vetted.

//
// Function: createProgressPalette
// Description: Opens up a palette window with a progress bar that can be
//              'asynchronously' while the script continues running
// Input:
//   title     the window title
//   min       the minimum value for the progress bar
//   max       the maximum value for the progress bar
//   parent    the parent ScriptUI window (opt)
//   useCancel flag for having a Cancel button (opt)
//   msg        message that can be displayed and changed in the palette (opt)
//
//   onCancel  This method will be called when the Cancel button is pressed.
//             This method should return 'true' to close the progress window
// Return: The palette window
//

function createProgressPalette(title, min, max,
                                       parent, useCancel, msg) {
  var opts = {
    closeButton: false,
    maximizeButton: false,
    minimizeButton: false
  };
  var win = new Window('palette', title, undefined, opts);
  win.bar = win.add('progressbar', undefined, min, max);
  if (msg) {
    win.msg = win.add('statictext');
    win.msg.text = msg;
  }
  win.bar.preferredSize = [500, 20];

  win.parentWin = undefined;
  win.recenter = false;
  win.isDone = false;

  if (parent) {
    if (parent instanceof Window) {
      win.parentWin = parent;
    } else if (useCancel == undefined) {
      useCancel = !!parent;
    }
  }

  if (useCancel) {
    win.onCancel = function() {
      this.isDone = true;
      return true;  // return 'true' to close the window
    };

    win.cancel = win.add('button', undefined, localize("$$$/JavaScripts/psx/Cancel=Cancel"));

    win.cancel.onClick = function() {
      var win = this.parent;
      try {
        win.isDone = true;
        if (win.onCancel) {
          var rc = win.onCancel();
          if (rc != false) {
            if (!win.onClose || win.onClose()) {
              win.close();
            }
          }
        } else {
          if (!win.onClose || win.onClose()) {
            win.close();
          }
        }
      } catch (e) {
        LogFile.logException(e, '', true);
      }
    };
  }

  win.onClose = function() {
    this.isDone = true;
    return true;
  };

  win.updateProgress = function(val) {
    var win = this;

    if (val != undefined) {
      win.bar.value = val;
    }
//     else {
//       win.bar.value++;
//     }

    if (win.recenter) {
      win.center(win.parentWin);
    }

    win.update();
    win.show();
    // win.hide();
    // win.show();
  };

  win.recenter = true;
  win.center(win.parent);
  return win;
};

3 replies

JJMack
Community Expert
Community Expert
December 19, 2016

You may also be able to speed up the execution of your scripts by toggling Photoshop Palettes off so Photoshop does not need to update them while your script run.  Reducing the number of Photoshop steps your script does will also help. Shorten the code path length or use a faster method. Action Manager code may perform better then DOM code in places.

JJMack
Inspiring
December 19, 2016

Action Manager code will perform better then DOM code in all places.

FTFY

xbytor2Correct answer
Inspiring
December 19, 2016

Here is code that I have used in one form another for close to a decade. It is also used in releases of ImageProcessorPro and CSX so it has been fairly well vetted.

//
// Function: createProgressPalette
// Description: Opens up a palette window with a progress bar that can be
//              'asynchronously' while the script continues running
// Input:
//   title     the window title
//   min       the minimum value for the progress bar
//   max       the maximum value for the progress bar
//   parent    the parent ScriptUI window (opt)
//   useCancel flag for having a Cancel button (opt)
//   msg        message that can be displayed and changed in the palette (opt)
//
//   onCancel  This method will be called when the Cancel button is pressed.
//             This method should return 'true' to close the progress window
// Return: The palette window
//

function createProgressPalette(title, min, max,
                                       parent, useCancel, msg) {
  var opts = {
    closeButton: false,
    maximizeButton: false,
    minimizeButton: false
  };
  var win = new Window('palette', title, undefined, opts);
  win.bar = win.add('progressbar', undefined, min, max);
  if (msg) {
    win.msg = win.add('statictext');
    win.msg.text = msg;
  }
  win.bar.preferredSize = [500, 20];

  win.parentWin = undefined;
  win.recenter = false;
  win.isDone = false;

  if (parent) {
    if (parent instanceof Window) {
      win.parentWin = parent;
    } else if (useCancel == undefined) {
      useCancel = !!parent;
    }
  }

  if (useCancel) {
    win.onCancel = function() {
      this.isDone = true;
      return true;  // return 'true' to close the window
    };

    win.cancel = win.add('button', undefined, localize("$$$/JavaScripts/psx/Cancel=Cancel"));

    win.cancel.onClick = function() {
      var win = this.parent;
      try {
        win.isDone = true;
        if (win.onCancel) {
          var rc = win.onCancel();
          if (rc != false) {
            if (!win.onClose || win.onClose()) {
              win.close();
            }
          }
        } else {
          if (!win.onClose || win.onClose()) {
            win.close();
          }
        }
      } catch (e) {
        LogFile.logException(e, '', true);
      }
    };
  }

  win.onClose = function() {
    this.isDone = true;
    return true;
  };

  win.updateProgress = function(val) {
    var win = this;

    if (val != undefined) {
      win.bar.value = val;
    }
//     else {
//       win.bar.value++;
//     }

    if (win.recenter) {
      win.center(win.parentWin);
    }

    win.update();
    win.show();
    // win.hide();
    // win.show();
  };

  win.recenter = true;
  win.center(win.parent);
  return win;
};

RA5040ARDAuthor
Inspiring
December 19, 2016

Many thanks! I'll give your script a go. A couple of questions:

- is the only way of ending the progress palette to terminate the script (or for the user to press cancel)? The reason I ask is that my script handles several separate longish tasks with user input in between the tasks. I would like to have the progress palette show for each one separately. I guess I could make createProgressPalette as a class...

- would it be asking too much for you to give me an example of calling the function? It might save me quite a bit of messing. This seems to be the minimum: createProgressPalette("Please Wait", min, max,,, ) ... but i'm not sure what min and max values are for.

Thanks!

Robert

Inspiring
December 20, 2016

It's used in ImageProcessorPro (ps-scripts - Browse /Image Processor Pro/v3_2 betas at SourceForge.net). It's actually used twice in the script: once for startup window creation, the other for iteration over the file being processed. The latter is probably of most interest.

You don't really need to create a class. It's a function that creates a 'palette' window that I've added stuff to. When you are done with it, just close it.

JJMack
Community Expert
Community Expert
December 19, 2016
RA5040ARDAuthor
Inspiring
December 19, 2016

Thanks ... but doProgress is not available pre CC2015 (I think) and my customers use everything from CS upwards.

JJMack
Community Expert
Community Expert
December 19, 2016

I do not know when the support was added to Photoshop scripting.  CS is 13 years old and many features have been added to Photoshop scripting since then.  Also some old scripting bugs have been fixed  after CS.  Scripting was a PS 7 optional Plug-in and CS was the first release to have scripting.  If you want to use scripting you should move to a newer version of Photoshop CS6 or a creative cloud subscription.

Some on my scripts test Photoshop version to code around CS2 scripting bugs.    I have also coded some Plug-ins scripts.  These can not be used in version of Photoshop prior to CS3.  There are new bugs in CC 2015.5 and CC 2017 scriting.

JJMack