Fanning Software Consulting

Resizing a List Widget

QUESTION: I'm working on an IDL widget program that reads a number of images and outputs some of their features into a new window containing a scrollable list widget. Is it possible to drag-resize the list widget to a different size so the user will have more flexibility in how he or she uses the program?

ANSWER: In general, list widgets (like many IDL widgets) have no built-in capability to be resized. However, you can often add this kind of functionality to widget programs with some creative hacking. JD Smith offers one version of such a hack to give you an idea of how it is done.

Well, I don't know if this is a cross-platform solution (which, these days, simply means “does it support Windows?,” since all the other widget toolkits on all other architectures are exactly the same), but I have a method which works well for me.

It consists of computing the difference in pixels in screen size between a list widget and its containing TLB just after it has been realized, storing that difference, and then applying it to resize-generated TLB_SIZE_EVENTS sizes as they come in. It works quite generally, even if there are other widgets inside the same base above, adjacent, below, etc. It effectively “subtracts out” all the random and variable frame size, widget spacing, and other widget display difference which vary by OS, window manager, etc. As a result, it should, at least in principle, be cross-platform (untested). Compile and run the program below to judge for yourself.

    ;;--------------------------------------------------------------------------------
    ;; Resizeable List Widget Test, JDS, 04/2007
    pro resize_list_event,ev
      widget_control, ev.id,GET_UVALUE=uval
      if size(uval,/TYPE) eq 7 then begin
         if uval eq 'quit' then begin
            widget_control, ev.top,/DESTROY
            return
         endif
      endif else begin
         if tag_names(ev,/STRUCTURE_NAME) eq 'WIDGET_BASE' then begin
            widget_control, uval.list,SCR_XSIZE=ev.X+uval.diff[0], $
                            SCR_YSIZE=ev.Y+uval.diff[1]
         endif
      endelse
    end ; --------------------------------------------------------------

    pro resize_list
      b=widget_base(/COLUMN,SPACE=0)
     ; t=widget_label(b,VALUE='A Resizeable list widget by JDS')
      r=widget_base(b,/ROW,SPACE=2,/BASE_ALIGN_CENTER)
      d=widget_draw(r,UVALUE='draw',XSIZE=100,YSIZE=100)
      text=(byte('a'))[0]+byte(randomu(sd,50,100)*26)
      text[long(randomu(sd,5*100)*50*100)]=32b
      text=string(text)
      l=widget_list(r,XSIZE=40,YSIZE=10,UVALUE='list', VALUE=text)
      q=widget_button(b,VALUE='Quit',UVALUE='quit')
      widget_control, b,/REALIZE,/TLB_SIZE_EVENTS

      widget_control, d, GET_VALUE=dw
      wset,dw
      tvscl,dist(100)
      xyouts,50,10,'Random Graphic',/DEVICE,ALIGNMENT=0.5

      geom=widget_info(l,/GEOMETRY)
      bgeom=widget_info(b,/GEOMETRY)
      list_size_diff=[geom.SCR_XSIZE-bgeom.SCR_XSIZE,geom.SCR_YSIZE-bgeom.SCR_YSIZE]
      state={diff:list_size_diff,list:l}
      widget_control, b,SET_UVALUE=state
      XManager,'resize_list',b
    end ; --------------------------------------------------------------

When I ran the program on my Windows machine, running Windows XP Pro, the resulting window “snapped back” to be a bit smaller than I wanted it to be. I found empirically, that the window was about 26 pixels too small in Y and about 6 pixels too small in X. I took this to be the vertical size of the window title bar in Y and the extra padding in representing base widgets in X. My modified program to get perfect control over window size used this line in the event handler:

         if tag_names(ev,/STRUCTURE_NAME) eq 'WIDGET_BASE' then begin
            widget_control, uval.list,SCR_XSIZE=ev.X+uval.diff[0] + 6, $
                            SCR_YSIZE=ev.Y+uval.diff[1] + 26
         endif

Note that including these modifications in the X Windows version will cause the resized window to overshoot by this amount!

Further Modification

Kelly Dean points out that JD's example program gets bigger OK, but that doesn't shink so well, since the QUIT button gets in the way. In other words, the Quit button will get bigger, but it won't get smaller automatically on Windows. Here is an example of what it looks like when it is first stretched, then shrunk back to starting size.

The QUIT button doesn't shrink in size on Windows.
The QUIT button doesn't shrink automatically in size on Windows, like it does on X Windows.
 

Kelly supplies a modified file that works correctly on his Windows machine. (Note that this version has the Windows fudge factors, that will cause X Windows machines to overshoot!)

Google
 
Web Coyote's Guide to IDL Programming