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!



Mapping Earthquake Deformation in Taiwan With ENVI

Mapping Earthquake Deformation in Taiwan With ENVI

12/15/2025

Unlocking Critical Insights With ENVI® Tools Taiwan sits at the junction of major tectonic plates and regularly experiences powerful earthquakes. Understanding how the ground moves during these events is essential for disaster preparedness, public safety, and building community resilience. But traditional approaches like field... Read More >

Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

12/3/2025

Large commercial SAR satellite constellations have opened a new era for persistent Earth monitoring, giving analysts the ability to move beyond simple two-image comparisons into robust time series analysis. By acquiring SAR data with near-identical geometry every 24 hours, Ground Track Repeat (GTR) missions minimize geometric decorrelation,... Read More >

Empowering D&I Analysts to Maximize the Value of SAR

Empowering D&I Analysts to Maximize the Value of SAR

12/1/2025

Defense and intelligence (D&I) analysts rely on high-resolution imagery with frequent revisit times to effectively monitor operational areas. While optical imagery is valuable, it faces limitations from cloud cover, smoke, and in some cases, infrequent revisit times. These challenges can hinder timely and accurate data collection and... Read More >

Easily Share Workflows With the Analytics Repository

Easily Share Workflows With the Analytics Repository

10/27/2025

With the recent release of ENVI® 6.2 and the Analytics Repository, it’s now easier than ever to create and share image processing workflows across your organization. With that in mind, we wrote this blog to: Introduce the Analytics Repository Describe how you can use ENVI’s interactive workflows to... Read More >

Deploy, Share, Repeat: AI Meets the Analytics Repository

Deploy, Share, Repeat: AI Meets the Analytics Repository

10/13/2025

The upcoming release of ENVI® Deep Learning 4.0 makes it easier than ever to import, deploy, and share AI models, including industry-standard ONNX models, using the integrated Analytics Repository. Whether you're building deep learning models in PyTorch, TensorFlow, or using ENVI’s native model creation tools, ENVI... Read More >

1345678910Last
15901 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.