but for some reason this fails to draw correctly on Windows! If the edit box is active and the cursor is in it, the text is not drawn but the cursor blinks at correct position at the end of that invisible text. Moving the cursor or typing in something makes the text pop back into view. (Sorry, should have thought of making a 'shot of that as well.) A real shame, because on my Mac it works as I meant it to: placeholder text shows when the field is inactive and empty, placeholder disappears when you enter the field and type anything in it. Delete text and leave box makes it appear again.

Is this an error in my code (silently corrected on the Mac but showing up on 'the other platform'), or is it an error on the Windows' Side of the world? Or is this just something one should not be messing with using ScriptUI? (A fairly reasonable explanation.) Or might it work correctly on CS5 for both platforms? (In which case I could put in a platform/version check -- "no fancy dialog for you, you Older Version on a Microsoft Platform!").

I also have a variant of same code that would underline static text, which also shows up correctly on Mac and not-at-all on Windows -- but then it may be failing for the very same reason.

In CS5.5, your script breaks on this.parent.onDraw(d). The error message is "this.parent.onDraw is not a function", which is fair enough, because onDraw is a callback. So the question is not "Why does it not work on Windows?", but rather, "Why does it work on a Mac?". When I take out that line the script shows exactly the behaviour you describe. Looks like a bug to me.

On Windows there are some other display problems with edittext controls, but their solution, using this.layout.layout(), wouldn't work in your script. Can you not do something with editbox.onActivate and editbox.onDeactivate? After all, you want the contents to change when the user activates another control, not every time the mouse cursor moves away from the edit field.

Did I ask for 4s? I mentioned that there seemed to a problem with onDraw(), that is the parentheses following onDraw.

4's are just an example. The point I am trying to make is that you absolutely can call the onDraw handler, exactly as Jongware did in this posted code, as long as such a handler exists. (It appears that perhaps it exists in CS4 if you don't define it, and that behavior changed in CS5).

That is, I took issue with::

onDraw is a function but not one that you call like x.onDraw(). But you're right, that error message isn't precise.

onDraw is indeed a function (as long as it exists), and you can call it, and the error message seems fine.

As long as his code uses:

if (this.parent && this.parent.onDraw) {
this.parent.onDraw(d);
}

then it is safe.

(you could also write it as this.parent && this.parent.onDraw && this.parent.onDraw(x); if you felt like it.)

You said that you cannot call a callback directly, and I am saying that's not the case. You certainly can. Though you have to make sure it exists.

His oriignal will fail in CS5. It fails not because you cannot call a callback, but rather because you cannot call a nonexistent callback. If you add to the end of the script:

w.children[0].onDraw = function() { $.writeln(4); } ;

then there is now a callback for the Group, and then it can be called by the edittext's onDraw method.

Unfortunately that's not a useful thing to do, because it doesn't cause the Group to redraw. There doesn't seem to be a way to do that, presumably

because in CS5, the code was restructured internally so you couldn't call the internal drawing mechanism by invoking the onDraw handler.

So a different approach is required. One is to just disable the onDraw handler (set it to undefined), and then the next cycle later, the internal method will do its own thing. Another might be to call .notify("onDraw") on the parent, though I could not get that to work.

which appears to work as well, but I noticed this sometimes leads to 'double drawing'. (Or that's what I assumed based on a similar code that draws static text -- it's slightly bolder than "usual".)

Peter is right, though, that my calling of this.parent.onDraw is a mistake, and the ESTK marks it as 'no such thing'.

BUT (1) this.parent ought to be the window itself or its containing group or parent, so I assumed in all naivety that would lead to re-drawing the control "as usual" -- I'm willing to claim No Particular Knowledge of ScriptUI on this --, and

(...) In CS5.5, your script breaks on this.parent.onDraw(d). The error message is "this.parent.onDraw is not a function", which is fair enough, because onDraw is a callback. (...)

The reason why this.parent.onDraw is not a function in Jongware's code, is just that this.parent.onDraw is undefined—as John supposed. When we call x( ) from an undefined x var, the interpreter prompts a not-a-function error.

Why is this.parent.onDraw undefined? Because there is no line in the code which sets up such member on this.parent—which by the way is a (ScriptUI) Group object, considering the context. What we call 'callback' functions are optional custom methods that are supposed to connect to events, usually, but widget prototypes do not provide any default callbacks. myWidget.onDraw, myWidget.onClick, etc., are simply undefined as long as we don't set them.

In addition, the onDraw callback, when defined, does not work the same way that other event callbacks (which are high-level fake event listeners and could generally be developed through an addEventListener() setter providing much more precision). Indeed, onDraw has no actual event counterpart (or, if any, it is not exposed to scripters as 'show', 'focus', 'blur', 'change', 'click', etc., are.) As documented, onDraw is automatically called when a widget needs to be (re)drawn, but this 'when' is highly unpredictable as it depends on the user interactions, the OS, and probably a number of low-level events.

We also know that custom layout—i.e. myContainer.layout.layout(1)—triggers such drawing stages (from containers). Also, there are crazy paths to get a non-container widget redrawn, for example:

wg.visible=false; wg.visible=true;

or sometimes:

wg.size = [wg.size[0],wg.size[1]];

The issue with manually calling a custom onDraw() method is we generally don't know when it is safe to call it and whether it may conflict with the automatic calls. I found circumstances where manual onDraw() simply fails due to a temporary invalidation of the widget.graphics property (I believe this depends on the object type). This may explain why Peter wrote:

(...) onDraw is a function but not one that you call like x.onDraw()

However, onDraw is indeed a simple (callable) function if the script did it so. What matters is that a custom onDraw() overrides and bypasses, as much as possible, the native drawing stage. So, in many cases, an empty onDraw() callback makes the widget totally undrawn (hidden) although room has been reserved to it during layout. (That's not true for composite or very interactive widgets—such as scrollbar or listbox—which still inherit from low-level painting events, at least partially.)

ANYWAY, in Jongware's script I don't see any reason to make this.onDraw() attempt to call a hypothetical parent onDraw method—which for the time being does not exist—or even to trigger the native drawing stage on the parent. Why? I guess there is a confusion between drawing and layout (?)

What is sure is that the statement this.parent.onDraw(d) fails. And, since ScriptUI is known for hushing errors up in many event handlers, you get unaccountable side effects in your EditText control.

To me, a valid approach would be to invoke the ScriptUIGraphics.drawOSControl() method when you need to produce the default widget skin before further customization.

The following snippets should provide better results (unfortunately, I can't test this on all systems):

Wow, Marc, that cleared up a few lingering issues I had been having in the back of my mind! I'll try your code on Mac, CS3, CS4, 5, and 5.5, and Windows, CS4 (only ;( -- I lost all of my previous installations due to an unfortunate system wide "updrade), and will report back with any inconsistent, consistent, or otherwise bizarre behavior.

Marc's code works Or at least, it does with CS4, both on Mac Lion and on Windows 7.

Anyone else willing to give it a go with the more modern versions? I got the general idea right so the image in my initial post shows what it's supposed to look like: without text and inactive, a <placeholder text>; with text or activated, the normal behavior.