As per our conversation on the KSIntegration thread, I've edited the code leaving only the relevant part. This is it:
// didn't bother to clean these up
#include <pjsr/Sizer.jsh>
#include <pjsr/FrameStyle.jsh>
#include <pjsr/NumericControl.jsh>
#include <pjsr/TextAlign.jsh>
#include <pjsr/StdButton.jsh>
#include <pjsr/StdIcon.jsh>
#include <pjsr/ColorSpace.jsh>
#include <pjsr/SampleType.jsh>
#include <pjsr/UndoFlag.jsh>
function kappa_sigma_dialog() {
this.__base__ = Dialog;
this.__base__();
// sequence of spaces to be prepended to debug stmts, to visually show the
// increasing "depth" of the code flow
this.strpad = "";
this.target_List = new TreeBox (this);
this.target_List.setMinSize (400, 200);
this.target_List.font = new Font ("monospace", 10); // best to show tabulated data
this.target_List.numberOfColumns = 2;
this.target_List.headerVisible = true;
this.target_List.headerSorting = true;
this.target_List.setHeaderText (0, "Views");
this.target_List.setHeaderText (1, "Dimensions");
this.target_List.setHeaderAlignment (0, Align_Left);
this.target_List.setHeaderAlignment (1, Align_Left);
this.target_List.onNodeUpdated = function() {
var node = this.dialog.target_List.currentNode;
var foo=0;
this.dialog.strpad += " "; // add padding before entering loop
for (bar in node) if (!foo++) { // beware of the dog!
// walk the list and set the similar images to the state of the just-clicked one
console.writeln (format ("%snode (%s) updated", this.dialog.strpad, node.text (0)));
for (i = 0; i < this.dialog.target_List.numberOfChildren; i++) {
console.writeln (format ("%sin loop, iteration (%d)", this.dialog.strpad, i));
if (this.dialog.target_List.child (i).text (1) == node.text (1)) {
// If onNodeUpdated is called now, we will enter this function again without
// trimming strpad, so the following debug stmts will appear more padded.
//
// If not, we will exit this loop and some padding will be removed.
console.writeln (format ("%sabout to tick a box", this.dialog.strpad));
this.dialog.target_List.child (i).checked = node.checked;
console.writeln (format ("%sticked and still alive!", this.dialog.strpad));
}
}
}
// remove padding after loop
this.dialog.strpad = this.dialog.strpad.substr (0, this.dialog.strpad.length - 2);
}
// Node creation helper
function addViewNode (parent, view) {
var node = new TreeBoxNode (parent);
node.checkable = true;
node.checked = false;
node.setText (0, view.fullId);
var image = view.image;
var metadata = format ("%5d x %5d x %d", image.width, image.height, image.numberOfChannels);
node.setText (1, metadata);
return node;
}
// Build the view tree structure
var windows = ImageWindow.windows;
for (var i = 0; i < windows.length; ++i) {
var node = addViewNode (this.target_List, windows[i].mainView);
node.expanded = false; // or true to initially expand all preview lists
var previews = windows[i].previews;
for (var j = 0; j < previews.length; ++j)
addViewNode (this.target_List, previews[j]);
}
this.target_List.sort();
// Ensure that all columns are initially visible
this.target_List.adjustColumnWidthToContents (0);
this.target_List.adjustColumnWidthToContents (1);
this.adjustToContents();
}
kappa_sigma_dialog.prototype = new Dialog;
var dialog = new kappa_sigma_dialog();
dialog.execute();
(This code actually reveals two bugs. I'll talk about the "dog"
in another report).
The output I get from this script with two images open, when selecting the first of them in the script interface is the following. I've manually labeled some of the lines for reference after pasting them here.
node (Image01) updated
in loop, iteration (0)
about to tick a box
ticked and still alive! [1]
in loop, iteration (1)
about to tick a box [2]
node (Image01) updated [3]
in loop, iteration (0)
about to tick a box
ticked and still alive! [4]
in loop, iteration (1)
about to tick a box
ticked and still alive! [5]
ticked and still alive!
I think we get to [1] without recursion because the engine knows we are working with that image, so it shouldn't call onNodeUpdated again. In [2] we're in the second iteration of the loop, about to enable the second box. Then we find ourselves in [3], i.e. onNodeUpdated was called. Note that the image name is still Image01 and the indentation of the output (called "padding" in the code) is bigger. Again, in [4] the engine knows that this object is in some way related to our current situation, so doesn't enter the function again. Same in [5].
If I click the second image instead of the first, this is the output:
node (Image02) updated
in loop, iteration (0)
about to tick a box
node (Image02) updated
in loop, iteration (0)
about to tick a box
ticked and still alive!
in loop, iteration (1)
about to tick a box
ticked and still alive!
ticked and still alive!
The indentation grows in the first pass of the loop because the first image has not been "seen" yet. From then on, everything should be self-explanatory by now.
Of course, trying this with more than two images makes the output much longer, but completely predictable otherwise.