Fanning Software Consulting

Jumping Widgets

QUESTION: I have built a dialog widget that pops up in the center of the display. Normally, this is convenient, but yesterday I wanted to move it out of the way before I used it. When I did use it, the program continually re-positioned itself in the center of the display every time I touched it! I've never encountered a widget program with such a strong homing instinct. Is this normal?

ANSWER: No, it is not “normal”, but it is possible to see this behavior on UNIX machines (including Macs) under certain circumstances. I have never seen this behavior on Windows machines. I believe this is a bug, but I have not received official word of that from the good folks at ITTVis.

I ran across the problem and tracked it to a line of code that was changing the text on a label widget! I'll describe what I learned about that problem, but I think it is likely that other, seemingly unrelated, actions could also tickle this bug. It seems to be a problem with the code that updates widgets on the display.

In the particular case I encountered, several actions were prerequisites for the problem to occur. First, you must be positioning the top-level base widget on the display using the XOFFSET and YOFFSET keywords. You can either be doing this at the time you create your top-level base, or you can do it later with Widget_Control. Since your widget is appearing in the center of the display, we can assume you are doing this. If you are not positioning your widget program, you will not see this problem.

Second, in my particular case, the label widget I was creating had to be defined in its natural size (that is, without using any of the sizing keywords) and it had to have the DYNAMIC_RESIZE keyword set for it. If my label widget was set up like this, then any action that caused the label widget to trigger the dynamic resize property, such as setting the text on the label to a string that is longer or shorter than the current string by some appreciable amount, would cause my entire widget program to jump back to its original position on the display. That is to say, to the position I gave the widget originally with the offset keywords.

In the course of tracking this problem down, I discovered another way to trigger this jumping behavior. If I simply position the widget with the offset keywords, and then in any event handler I turn top-level base updating off and then on again, as with the two commands below, the widget also jumps back to its original position.

    Widget_Control, event.top, UPDATE=0
   Widget_Control, event.top, UPDATE=1 

This is what leads me to conclude that any number of actions might trigger this behavior, if the action causes a widget update.

Problem Work-Arounds

I discovered several work-arounds to this problem, some more palatable than others.

First, I could refrain from positioning the widget on the display, and let it appear in its natural position (usually in the upper left-hand corner of the display). This is not my preferred position for a pop-up dialog widget.

Second, I could not set the DYNAMIC_RESIZE keyword for the label widget. This would have worked if the label widget appeared initially with the longest text in it, but unfortunately in my case it was just the opposite. It appeared initially with the shortest text. So when I changed the text to something longer, some of it was cut off. So this was a non-starter for me.

Third, I could simply size the label widget to a size that would accommodate the largest text string I wanted to put on it. Thus, even with the DYNAMIC_RESIZE keyword set (so the text would resize and not get cut off), the actual widget would not resize itself and generate an update event. Since my program design was such that I had plenty of room to do this, it was my preferred solution.

If you would like to experiment with this yourself, you can download my test program, named JumpyWidget. To see the problem, run the program as below, move it to a new location on the display, then click the Do It button. The program will jump to its original location.

    IDL> void = jumpywidget() 

To see the program work correctly, set the NOJUMPING keyword, like this.

    IDL> void = jumpywidget(/NoJumping) 

Version of IDL used to prepare this article: IDL 7.0.3.

Google
 
Web Coyote's Guide to IDL Programming