X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

6/3/2025

Rethinking the Reliability of Type 1a Supernovae   How do astronomers measure the universe? It all starts with distance. From gauging the size of a galaxy to calculating how fast the universe is expanding, measuring cosmic distances is essential to understanding everything in the sky. For nearby stars, astronomers use... Read More >

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

5/26/2025

Whether you’re new to remote sensing or a seasoned expert, there is no doubt that large language models (LLMs) like OpenAI’s ChatGPT or Google’s Gemini can be incredibly useful in many aspects of research. From exploring the electromagnetic spectrum to creating object detection models using the latest deep learning... Read More >

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

4/28/2025

When every second counts, the ability to process geospatial data rapidly and accurately isn’t just helpful, it’s critical. Geospatial Intelligence (GEOINT) has always played a pivotal role in defense, security, and disaster response. But in high-tempo operations, traditional workflows are no longer fast enough. Analysts are... Read More >

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

4/24/2025

This blog was written by Eli Dwek, Emeritus, NASA Goddard Space Flight Center, Greenbelt, MD and Research Fellow, Center for Astrophysics, Harvard & Smithsonian, Cambridge, MA. It is the fifth blog in a series showcasing our IDL® Fellows program which supports passionate retired IDL users who may need support to continue their work... Read More >

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

2/25/2025

This blog was written in collaboration with Adam O’Connor from Wyvern.   As hyperspectral imaging (HSI) continues to grow in importance, access to high-quality satellite data is key to unlocking new insights in environmental monitoring, agriculture, forestry, mining, security, energy infrastructure management, and more.... Read More >

1345678910Last
13326 Rate this article:
No rating

Aligning widgets

Anonym

(Note: Today, since I’m giving a webinar, we have another guest post by Jim Pendleton, an Advisory Consultant in the Exelis VIS Professional Services Group. I indented his code for him. –MP) Working with IDL’s widget geometry can be challenging at times. There are many platform- and font-specific issues that often need to be taken into account when writing a UI that will present well across all IDL’s target devices. Additionally, your end user will often have their desktop customized in such a way that you never dreamt possible or desirable. The upshot is that you can waste a lot of energy tweaking an interface to be exactly the way you want it on your box via bulletin board bases and specific pixel offsets, but it’ll render in nightmarish fashion on another box. Some customers are willing to pay a lot of money for pretty and they should be encouraged to continue doing so. Others would rather have their development budget directed toward having their problem solved. One approach for an 80% solution is to align widgets based on their calculated geometries at runtime. Consider the following example which displays 5 rows of widgets within the context of a column base. The rows will have differing numbers of items, one row of 2 items, one row of 3 items, and three rows of 4 items.

 pro ExampleBase, ALIGN = ALIGN compile_opt idl2 TLB = widget_base(/COLUMN, TITLE = $ (['Poorly', 'Properly'])[keyword_set(ALIGN)] + ' Aligned Base') ; Row 0 = 2 columns row0 = widget_base(TLB, /ROW) label = widget_label(row0, VALUE = 'Parameter') label = widget_label(row0, VALUE = 'Value') ; Row 1 = 3 columns row1 = widget_base(TLB, /ROW) label = widget_label(row1, VALUE = 'Select a file') t1 = widget_text(row1, VALUE = 'a/filename/here') b1 = widget_button(row1, /BITMAP, $ VALUE = filepath('open.bmp', SUBDIR=['resource', 'bitmaps']), $ /ALIGN_LEFT) ; Row 2 = 4 columns row2 = widget_base(TLB, /ROW) label = widget_label(row2, VALUE = 'Select one from among many') t = widget_combobox(row2, $ VALUE = ['primary option', 'a much longer option here']) blank = widget_label(row2, VALUE = '') label = widget_label(row2, VALUE = 'Additional expository text') ; Row 3 = 4 columns row3 = widget_base(TLB, /ROW) label = widget_label(row3, VALUE = '') label = widget_label(row3, VALUE = '') label = widget_label(row3, VALUE = '') label = widget_label(row3, VALUE = 'broken into two lines.') ; Row 4 = 4 columns row4 = widget_base(TLB, /ROW) label = widget_label(row4, VALUE = 'Status = READY', /SUNKEN_FRAME) blank = widget_label(row4, VALUE = '') blank = widget_label(row4, VALUE = '') button = widget_button(row4, VALUE = 'Cancel') if (keyword_set(ALIGN)) then begin AlignColumns, TLB endif widget_control, TLB, /REALIZE end 

Notice that this code does not attempt to tweak any of the widget sizes to specific widths and heights. By and large, doing so would be total waste of your time unless you have total control over the final display environment and/or a large budget. By itself it produces the following UI, which is quite awful if I do say so myself. IDL> examplebase Jim Pendleton: a poorly aligned widget base Our goal is to align the output into a grid. The GRID_LAYOUT keyword to WIDGET_BASE is not applicable in this case because the items with which we’re working are embedded in other bases. Additionally, we don’t want all the items to be the same width. Feel free to give GRID_LAYOUT a try as an independent exercise. Consider the following utility routine which takes as input the widget ID of a column base and assumes it is populated by row bases whose items we want to align. The base ID does not need to be that of a top-level base. For each row (the X direction), we want to find the width of each item. We’ll call this a column entry. Over the columns (the Y direction), we want to find the maximum width in each. Finally, we’ll make a second pass back over our rows and adjust each item to be the maximum width for that column.

 pro AlignColumns, ColumnBase compile_opt idl2 ; The outer loop iterates over the rows in the column base. columnmaxwidths = [] child = widget_info(ColumnBase, /CHILD) while (widget_info(child, /VALID_ID)) do begin ; The inner loop iterates over the widgets in each row. ; The number of widgets in this base is interpreted ; as the number of columns. columncount = 0L grandchild = widget_info(child, /CHILD) while (widget_info(grandchild, /VALID_ID)) do begin ; What is the screen width in pixels of this widget? width = (widget_info(grandchild, /GEOMETRY)).scr_xsize ; If this is a new column, record its width, otherwise ; take the maximum of this width and the previous ; recorded maximum width. if (n_elements(columnmaxwidths) lt columncount + 1) then begin columnmaxwidths = [columnmaxwidths, width] endif else begin columnmaxwidths[columncount] >= width endelse columncount++ grandchild = widget_info(grandchild, /SIBLING) endwhile child = widget_info(child, /SIBLING) endwhile ; Pass 2: Set the screen width of each widget equal ; to the maximum width found per column child = widget_info(ColumnBase, /CHILD) while (widget_info(child, /VALID_ID)) do begin columncount = 0L grandchild = widget_info(child, /CHILD) while (widget_info(grandchild, /VALID_ID)) do begin widget_control, grandchild, SCR_XSIZE = columnmaxwidths[columncount] columncount++ grandchild = widget_info(grandchild, /SIBLING) endwhile child = widget_info(child, /SIBLING) endwhile end

The “magic” here is encapsulated in the following:

  • WIDGET_INFO can be used to return a GEOMETRY structure of a widget
  • The geometry’s SCR_XSIZE returns the screen size, in pixels, of a widget
  • The SCR_XSIZE keyword to WIDGET_CONTROL can be used to explicitly set the width of a widget

We don’t add any new functionality to our original user interface, but we greatly increase its ease of comprehension. IDL> examplebase, /align Jim Pendleton: a properly aligned widget base Feel free to modify the code for more general cases. Note that:

  • This example only looks one level deep for child widgets. You might consider recursion.
  • It doesn’t account for widget heights, which may also be important to you.
  • It doesn’t take into account other geometry items such as spacing and padding.
  • You may also see different results if the utility is called post-realization rather than pre-realization. (That is, WIDGET_CONTROL, /REALIZE is called before AlignColumns rather than after.)
  • Consider a mechanism to indicate to the utility routine that a widget should occupy more than one column, such as the “status” label in the bottom-most row.

(Thanks, Jim! –MP)

Please login or register to post comments.