; $Id: cw_treestructure.pro,v 1.9 2004/01/21 15:54:51 scottm Exp $ ; Copyright (c) 2002-2004, Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. ;+ ; NAME: ; CW_TREESTRUCTURE ; ; PURPOSE: ; This function implements a compound widget for the treeview ; of an IDL structure with nested substructures. ; ; ; CALLING SEQUENCE: ; Result = CW_TREESTRUCTURE(Parent [, VALUE=value]) ; ; ; RETURN VALUE: ; The result is the widget ID of the newly-created widget. ; ; ; INPUTS: ; Parent: Set this argument to the widget ID of the parent base. ; ; ; KEYWORD PARAMETERS: ; VALUE = Set this keyword to a structure to be traversed. ; ; If VALUE has a tag "_NAME" which is a scalar string, then ; this will be used for the tree label. ; If VALUE has a tag "_ICONTYPE" which is a scalar string, ; then this will be used as the name of a bitmap file to ; be used for the icon. ; If a tag within VALUE contains another structure, then ; a new branch is constructed and the substructure is ; traversed. ; Note: If the tagname for the tag containing the structure ; is "_DATA" then a new branch is not constructed. ; This allows you to skip tags while traversing. ; ; All keywords to WIDGET_TREE except FUNC_GET_VALUE and PRO_SET_VALUE ; are passed on to the tree widget. ; ; ; Keywords to WIDGET_CONTROL and WIDGET_INFO: ; ; The widget ID returned by CW_TREESTRUCTURE is the ID of the ; WIDGET_TREE root. This means that many keywords to the WIDGET_CONTROL ; and WIDGET_INFO routines that affect or return information on ; WIDGET_TREE can be used. ; ; In addition, you can use the GET_VALUE and SET_VALUE keywords to ; WIDGET_CONTROL to retrieve or set the structure value. ; ; The GET_VALUE keyword returns the structure corresponding to the ; current selection within the widget tree. This structure contains ; only those tags and substructures at the selected level and below. ; If nothing is selected then a scalar zero is returned. ; ; The SET_VALUE keyword adds a structure to the tree at the root level. ; If SET_VALUE is not a structure variable then the tree is emptied. ; ; ; Widget Events Returned by the CW_TREESTRUCTURE Widget: ; ; The CW_TREESTRUCTURE widget returns WIDGET_TREE_SEL and ; WIDGET_TREE_EXPAND events. ; ; ; MODIFICATION HISTORY: ; Written by: CT, RSI, June 2002 ; Modified: ; ;- ;------------------------------------------------------------------------- ; Add structure(s) to the tree, starting at wParent. ; Substructures are recursively added. ; ; _BITMAPS: Internal structure array used to cache bitmaps from files. ; Avoids having to read the same bitmap multiple times. ; pro cw_treestructure_addlevel, wParent, sTrees, $ _BITMAPS=_bitmaps compile_opt idl2, hidden ; Initialize the bitmap cache. if (N_ELEMENTS(_bitmaps) eq 0) then $ _bitmaps = {ICONTYPE: '', BITMAP: BYTARR(16,16,3)} background = (WIDGET_INFO(wParent, /SYSTEM_COLORS)).window_bk for i=0, N_ELEMENTS(sTrees)-1 do begin sTree = sTrees[i] ; Tag names _NAME and _ICONTYPE have special meaning. ; NAME will be used for the tree value. ; ICON_TYPE will be used for adding a bitmap file. tagNames = TAG_NAMES(sTree) ; Retrieve the bitmap name if any. iconType = TOTAL(tagNames eq '_ICONTYPE') ? sTree._icontype : '' if (iconType ne '') then begin ; See if we've already read this bitmap. cached = (WHERE(_bitmaps.icontype eq iconType))[0] if (cached ge 0) then begin ; The bitmap has already been loaded. bitmap = _bitmaps[cached].bitmap endif else begin ; Need to read the bitmap from the file. iconFile = FILEPATH(iconType + '.bmp', $ SUBDIR=['resource','bitmaps']) if (FILE_TEST(iconFile, /READ)) then begin bm = READ_BMP(iconFile, R, G, B) bitmap = [[[R[bm]]], [[G[bm]]], [[B[bm]]]] for c=0,2 do begin channel = bitmap[*,*,c] ; Find all values that match the lower left pixel, ; and set them to the background. channel[WHERE(channel eq channel[0,0])] = background[c] bitmap[0,0,c] = channel endfor ; Append the new bitmap to the cached list. _bitmaps = [_bitmaps, $ {ICONTYPE: iconType, BITMAP: bitmap} ] endif endelse endif ; Check for substructures within ourself. isFolder = 0 for tag=0,N_ELEMENTS(tagNames)-1 do begin if ((tagNames[tag] ne '_DATA') and $ (SIZE(sTree.(tag), /TYPE) eq 8)) then begin isFolder = 1 break ; no need to check further endif endfor hasName = TOTAL(tagNames eq '_NAME') gt 0 ; Use name field or default name. if hasName then begin name = sTree._name endif else begin ; Use structure name unless anonymous. sName = TAG_NAMES(sTree, /STRUCTURE_NAME) name = (sName ne '') ? sName : $ (isFolder ? 'Struct' : 'Field') endelse ; Retrieve the path either from the structure itself, or from ; our parent. path = (TOTAL(tagNames eq '_PATH') gt 0) ? $ sTree._path : WIDGET_INFO(wParent, /uname) ; Be sure to tack on a trailing slash if there isn't one. if (STRMID(path, STRLEN(path)-1) ne '/') then $ path = path + '/' ; Store our structure in the UVALUE so we can ; retrieve it later with WIDGET_CONTROL, GET_VALUE. ; Store the full path field + name in the UNAME ; of the widget to be able to retrieve the structure ; when following links or getting info from non-selected ; leafs or nodes. if (isFolder) then begin ; Branch node. wTree = WIDGET_TREE(wParent, /FOLDER, $ BITMAP=bitmap, $ VALUE=name, $ UNAME=path + name, $ UVALUE=sTree) for tag=0,N_ELEMENTS(tagNames)-1 do begin ; If the tag is a structure, construct a branch. if ((tagNames[tag] ne '_DATA') and $ (SIZE(sTree.(tag), /TYPE) eq 8)) then $ CW_TREESTRUCTURE_ADDLEVEL, wTree, sTree.(tag), $ _BITMAPS=_bitmaps endfor endif else begin ; Leaf node. wTree = WIDGET_TREE(wParent, BITMAP=bitmap, $ VALUE=name, $ UNAME=path + name, $ UVALUE=sTree) endelse endfor end ;----------------------------------------------------------------------------- ; Retrieve the structure corresponding to the current tree selection. ; function cw_treestructure_getvalue, wTree compile_opt hidden ON_ERROR, 2 ;return to caller ; Be sure to start at the root for the selection. wTreeRoot = WIDGET_INFO(wTree, /TREE_ROOT) wSelect = (WIDGET_INFO(wTreeRoot, /TREE_SELECT))[0] ; Nothing was selected. if (wSelect eq -1) then $ return, 0 ; Retrieve the structure stored in the UVALUE. WIDGET_CONTROL, wSelect[0], GET_UVALUE=value return, (N_ELEMENTS(value) gt 0) ? value : 0 end ;----------------------------------------------------------------------------- ; Add a new structure to the tree hierarchy. ; pro cw_treestructure_setvalue, wTree, sTree compile_opt hidden ON_ERROR, 2 ;return to caller ; If not a structure, clean out the tree widget. if (N_TAGS(sTree) eq 0) then begin wBranch = WIDGET_INFO(wTree, /CHILD) while (WIDGET_INFO(wBranch,/VALID_ID)) do begin wTmp = WIDGET_INFO(wBranch, /SIBLING) WIDGET_CONTROL, wBranch, /DESTROY wBranch = wTmp endwhile endif else begin ; Add new tree CW_TREESTRUCTURE_ADDLEVEL, wTree, sTree endelse end ;------------------------------------------------------------------------- function cw_treestructure, wParent, $ VALUE=sTree, $ FUNC_GET_VALUE=swallow1, $ PRO_SET_VALUE=swallow2, $ _REF_EXTRA=_extra ; pass directly to WIDGET_TREE compile_opt idl2 ON_ERROR, 2 ; Check arguments. if (N_PARAMS() lt 1) then $ MESSAGE, 'Incorrect number of arguments.' if (not WIDGET_INFO(wParent, /VALID)) then $ MESSAGE, 'Invalid widget identifier.' myname = 'cw_treestructure' wTree = WIDGET_TREE(wParent, $ PRO_SET_VALUE= myname+'_setvalue', $ FUNC_GET_VALUE= myname+'_getvalue', $ _EXTRA=_extra) ; Populate tree with structure. if (N_ELEMENTS(sTree) gt 0) then $ WIDGET_CONTROL, wTree, SET_VALUE=sTree return, wTree end