UI progressbar example

Photoshop Script Snippets - Note: Full Scripts go in the Photoshop Scripts Forum

Moderators: Tom, Kukurykus

Holograph

UI progressbar example

Post by Holograph »

No problem Patrick. Thanks to you for getting us all started on the topic!
xbytor

UI progressbar example

Post by xbytor »

Here's my contribution to this thread.

Code: Select all//
// createProgressWindow
//   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)
//   
//   onCancel  This method will be called when the Cancel button is pressed.
//             This method should return 'true' to close the progress window
//
function createProgressWindow(title, min, max, parent, useCancel) {
  var win = new Window('palette', title);
  win.bar = win.add('progressbar', undefined, min, max);
  win.bar.preferredSize = [300, 20];

  win.parent = undefined;

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

  if (useCancel) {
    win.cancel = win.add('button', undefined, 'Cancel');
    win.cancel.onClick = function() {
      try {
        if (win.onCancel) {
          var rc = win.onCancel();
          if (rc || rc == undefined) {
            win.close();
          }
        } else {
          win.close();
        }
      } catch (e) {
        alert(e);
      }
    }
  }

  win.updateProgress = function(val) {
    var win = this;
    win.bar.value = val;
    // recenter the progressWindow if desired
    // win.center(win.parent);
    win.show();
    win.hide();
    win.show();
  }
  win.center(win.parent);
  return win;
};


And here's an example of how it would be used:


Code: Select all  // we have to process an array of files

  var progressWindow = createProgressWindow("Progress...",
                                            0, files.length, true);
  progressWindow.isDone = false;
  progressWindow.onCancel = function() {
    this.isDone = true;
    return true;  // return 'true' to close the window
  }

  try {
    for (var i = 0; i < files.length; i++) {
      if (progressWindow.isDone) {
        break;
      }
      progressWindow.text = ("Processing file " + (i+1) + " of " + files.length + "...");
      progressWindow.updateProgress(i);

       // now process the next file
       processFile(files);
    }
  } catch (e) {
    alert(e);

  } finally {
    progressWindow.close();
  }


The big addition here is the Cancel button. This lets us use the progress window to stop processing prematurely.

I'll be adding this to GenericUI in xtools.

Edit:
I've added this functionality to CSX and tested it in both CS2 and CS3. I have not yet tested this on the Mac...

-X
Holograph

UI progressbar example

Post by Holograph »

Hey X,

Nice work...it's really clean code.

I actually have a related question. The cancel button...does it really cancel the script? If so, how? That would be useful. I know you can cancel the current process by hitting escape during any script run, but if it's in a big loop or something, it will only cancel the current loop iteration.

Along those lines, it is possible to override the Esc key cancel functionality to make a full hard break or something (to ensure an immediate full cancel of any script process)?

Thanks in advance.

-Brian-
xbytor

UI progressbar example

Post by xbytor »

Holograph wrote:Nice work...it's really clean code.

Thanks. After seeing variants of the idea a few times, writing it was pretty easy.

I actually have a related question. The cancel button...does it really cancel the script? If so, how? That would be useful. I know you can cancel the current process by hitting escape during any script run, but if it's in a big loop or something, it will only cancel the current loop iteration.

The Cancel button, as it's used in the sample code, only stops the loop where it's used. That's what this code does:

Code: Select all      if (progressWindow.isDone) {
        break;
      }


The JS interpreter is apparently interleaving the onClick function with the loop so I'm able to set the progressWindow.isDone variable to true asynchronously. And this is the perfect use of that capability. I really needed something like this in CSX so I"m glad I was able to get this all worked out.

Along those lines, it is possible to override the Esc key cancel functionality to make a full hard break or something (to ensure an immediate full cancel of any script process)?

As far as I can tell, the only way to immediately terminate the execution of a script is to have the script reach completion (as is normally the case) or to shutdown Photoshop completely ala File->Quit. There is no other mechanism, unless you want to use

Code: Select all$.level = 1; debugger;

to dump the user into the debugger. But, as with the File->Quit event, you have to be at a known place in the script in order to do this.

-X
Holograph

UI progressbar example

Post by Holograph »

Thanks X. I kinda thought I'd explored all possible options to do it neatly/cleanly (exit on Esc no matter where it's at within the script), but I thought it was worth asking you.

-Brian-
Larry Ligon

UI progressbar example

Post by Larry Ligon »

Xbytor,

Your function and example code causes my Photoshop window to flicker really bad! Is that how it works?
xbytor

UI progressbar example

Post by xbytor »

What OS/PS versions is this happening on?

-X
Larry Ligon

UI progressbar example

Post by Larry Ligon »

I'm using Photoshop CS3 on Windows XP.

Also, where is the function :
// now process the next file
processFile(files);

The Photoshop CS3 documentation states that Photoshop CS3 does not support 'palette"! How does this work?

Also, the 'cancel' button doesn't work.
xbytor

UI progressbar example

Post by xbytor »

I'll try to put together a more fully functional demo.

This code is actually the basis for the progress bar that's in CSX v1.3, if you want to see what it looks like in a production script.

-X
Patrick

UI progressbar example

Post by Patrick »

I did some more work with this and thought I would share what I used. I have a script that loops through all the layers in a layerset and exports them one by one. Below snippit will determine the right % to jump to based on the total number of steps, and animate the bar for every progression.

Code: Select all// build window to show progress
var win = new Window("palette{text:'Export .tif files for catalog',bounds:[100,100,860,170],\
panel0:Panel{bounds:[5,5,755,65] , text:'' ,properties:{borderStyle:'black',su1PanelCoordinates:true},\
    progbar1:Progressbar{bounds:[5,5,740,50] , value:0,maxvalue:100}\
}\
};");

// show palette
win.center();
win.show();

// function to grow the progress bar
function animate(bar, end)
{   

    var p = bar.value;

    while (p <= end) {
       bar.value = p;
       p++;
       $.sleep(10);
    };
}

// incriment per image
var progress = 100 / (docRef.layerSets['alts'].layers.length);

// grow progress meter by one incriment
animate(win.panel0.progbar1, win.panel0.progbar1.value + progress);   

Patrick