
;************************************************************************************************
; logAttribute
;	stores the name, size, and description of attribute into an array
;	for later use
; Parameters:
;	name - name of attribute
;	dataSize - size of attribute
;	dataType - description (normally a data type, like "float", "int", etc...)
;************************************************************************************************
function dave_DAVEFileExaminer::logAttribute,name,dataSize,dataType
	newNames = [*self.names, name]
	newSizes = [*self.dataSizes, dataSize]
	newTypes = [*self.descriptors, dataType]

	ptr_free,self.names
	ptr_free,self.dataSizes
	ptr_free,self.descriptors

	self.names = ptr_new(newNames)
	self.dataSizes = ptr_new(newSizes)
	self.descriptors = ptr_new(newTypes)

	return, n_elements(*self.names)-1
end


;************************************************************************************************
; treeEvent
;	event handler for tree widget.  Determines the kind of event
;	and reacts accordingly
; Parameters:
;	event - event object
;************************************************************************************************
function dave_DAVEFileExaminer::treeEvent,event
	;help,event,/structure
	widget_control,event.id,get_uvalue = cmd
	if(~widget_info(event.id, /tree_expanded)) then begin
		; get a list of the selected widgets
		selectedWidgets = widget_info(self.treeWidget,/tree_select)
		; if no widgets are selected, clear text box and return
		if(selectedWidgets[0] eq -1) then begin
			displayPane = widget_info(event.top,find_by_uname='displayPane')
			widget_control,displayPane,set_value=''
			return,1
		endif
		; pruning out the folder (non-attribute) selections
		nonFolderIndices = where( widget_info(selectedWidgets, /child) eq 0, count)
		if(count eq 0) then return,0		; if only folder, then we're done
		selectedWidgets = selectedWidgets[nonFolderIndices]
		davePtr=self.dataFiledavePtr
		text=""
		;if(widget_info(event.id, /child) ne 0) then return,1
		; go through the list of attribites and build the display data
		;print, "num elements: ", n_elements(selectedWidgets)
		for i=0, n_elements(selectedWidgets)-1 do begin
			widget_control,selectedWidgets[i],get_uvalue = cmd
			index = cmd.index
			; more checking for non attribute selections
			if(index eq -1) then continue
			;help,(*self.names),/structure
			r=execute("tempText="+(*self.names)[index])
			help,tempText, output=dataType
			;print,dataType
			; if the attribute is a pointer, descend to get its data
			if( stregex(dataType,'\<PtrHeapVar',/boolean) ) then begin
				r=execute("tempText=*"+(*self.names)[index])
			endif
			; get label and append with the size and data type
			widget_control,selectedWidgets[i],get_value=label
			label = label + " [" + (*self.dataSizes)[index] + " " + (*self.descriptors)[index] + "]"
			;print, "label: ", label
			help, label
			; if empty, let user know
			if(tempText[0] eq "") then begin
				tempText = "(empty)"
			endif
			; right now this code only (properly) handles 0, 1, or 2 dimensional arrays
			; anything else is dumped in a really ugly format
			arrayInfo = size(tempText)
			;print, "arrayInfo: ", arrayInfo
			;print, "tempText before: ", tempText
			; check size, and format data appropriately
			if( arrayInfo[0] gt 0 ) then begin
				if( arrayInfo[0] eq 0 ) then begin
					tempText = strtrim(string(reform(tempText,n_elements(tempText))),2)
				endif
				if( arrayInfo[0] eq 2 ) then begin
					if(widget_info(selectedWidgets[i],/uname) eq 'histQty' || $
							widget_info(selectedWidgets[i],/uname) eq 'histErr') then begin

						;print, arrayInfo
						tempText2 = "x: 0"
						tempText2 = [tempText2, string(tempText[*,0], format='(4G15)')]
						for j=1, arrayInfo[2]-1 do begin
							tempText2 = [tempText2, "x: " + strtrim(string(j),2)]
							tempText2 = [tempText2, string(tempText[*,j], format='(4G15)')]
						endfor
						tempText = tempText2

					endif else begin
						tempText2 = string(tempText[*,0], format='(4G15)')
						for j=1, arrayInfo[2]-1 do begin
							tempText2 = [tempText2, string(tempText[*,j], format='(4G15)')]
						endfor
						tempText = tempText2
					endelse
				endif
			endif
			;print, "tempText: ", tempText
			;print, "size: ", size(tempText)
			;for i=0, n_elements(tempText2) do begin
			text = [text, "", strtrim(string(label),2) + ':', string(tempText)]
		endfor
		; parse out beginning blank lines
		if( n_elements(text) gt 2) then begin
			text = text[2:*]
		endif
		displayPane = widget_info(event.top,find_by_uname='displayPane')
		widget_control,displayPane,set_value=string(text)
	endif
	return, 1
end

;************************************************************************************************
; analyzeBeast
;	modification of John Copley's code.  Analyzes davePtr recursively
; Parameters:
;	beast - the dave pointer
;	title - the name of the current attribute being examined
;	lines - remaining attributes to examine
;	bptrs - something that's not used and will probably be taken out
;	level - keeps track of the how far down the member is in the hierarchy (will probably be removed)
;	levelListing - keeps track of levels (will probablt remove)
;	analysis - will probably be removed as well
;************************************************************************************************
function dave_DAVEFileExaminer::analyzeBeast,beast,title,lines,flags,bptrs,level,levelListing,analysis=analysis
	;************************************************************************************************
	; This procedure analyzes a "beast" recursively.
	; It returns, inter alia, a flag which is:
	; 0 if the "beast" is not a pointer and not a structure, e.g. a scalar, array, or string.
	; 1 if the "beast" is a structure.
	; 2 if the "beast" is a pointer.
	;
	;
	localLevel = level
	flag=0
	;
	help,beast,output=helpmsg
	;
	isstructure = float(strpos(helpmsg,"STRUCT")) ge 0
	ispointer = float(strpos(helpmsg,"POINTER")) ge 0
	;
	if (isstructure[0]) then begin
		flag=1
		tags=tag_names(beast)
		for i=0,n_tags(beast)-1 do begin
			;print, "level: ", level, ", tags[",i,"]: ", tags[i]
			void = self->analyzeBeast(beast.(i),title+"."+tags[i],lines,flags,bptrs,level,levelListing,analysis=analysis)
		endfor
	endif
	;
	if (ispointer[0]) then begin
		valid=ptr_valid(beast)
		if (not valid[0]) then begin
			flag=99
		endif else begin
			flag=2
			bptrs=[bptrs,beast]
			;print, "level: ", level, ", *beast","(*",title,")"
			void = self->analyzeBeast(*beast,"(*"+title+")",lines,flags,bptrs,level+1,levelListing,analysis=analysis)
		endelse
	endif

	if (~isstructure[0] AND ~ispointer[0]) then localLevel = localLevel + 1
	;
	if (analysis) then print,flag," ",title

	;print,"title[",flag,"]: ", title

	lines=[lines,title]
	levelListing=[levelListing,localLevel]
	flags=[flags,flag]
	;
	return, 1
end

;************************************************************************************************
; closeDAVEFile
;	closes the DAVE file.  Basically memory cleanup
; Parameters:
;	event: event object
;************************************************************************************************
function dave_DAVEFileExaminer::closeDAVEFile, event

	help, event, /structure

	; if a tree is currently there, destroy it
	davePtr = widget_info(self.tlb, find_by_uname='davePtr')
	if(davePtr ne 0) then begin
		widget_control,davePtr,/destroy
	endif
	; clear the text pane as well
	displayPane = widget_info(self.tlb,find_by_uname='displayPane')
	widget_control,displayPane,set_value=''

	; free up the memory
	heap_free,self.dataFileDavePtr
	ptr_free,self.names
	ptr_free,self.dataSizes
	ptr_free,self.descriptors

	someThing = ""
	self.names = ptr_new(something)
	self.dataSizes = ptr_new(SOMETHING)
	self.descriptors = ptr_new(someThing)

	return,1

end


function dave_DAVEFileExaminer::specificPtrCreator,tagnames,descriptor,datasize,rootWidget,rootName

	;print, "rootName: ", rootName

	indicesToIgnore = [-1]
	; three part search:
	;	1) find all the sub-attributes for the given structure, rootName
	;	2) find all the structures in the sub-attribute list
	;	3) find all the structures that belong to the root Structure, and not another structure down the line
	help,descriptor
	allAttributes = where( (stregex(tagnames, rootName, /boolean) eq 1), count )
	;print, "allAttributes: ", tagnames[allAttributes]
	if(count eq 0) then return,-1
	allStructures = where( strtrim(descriptor,2) eq 'Structure', count, complement=allNotStructure)
	;print, "allStructures: ", allStructures
	if(count eq 0) then return,-1
	notTooDeep = where( strpos(strmid(tagnames,strlen(rootName)), '.') eq -1, count )
	if(count eq 0) then return,-1

	; matching the results between all the attributes and the all the structures
	potentialStructures = [-1]
	for i=0, n_elements(allStructures)-1 do begin
		void = where(allAttributes eq allStructures[i], count)
		if(count eq 1) then potentialStructures = [potentialStructures, allStructures[i]]
	endfor
	if(n_elements(potentialStructures) eq 1) then return, -1
	potentialStructures = potentialStructures[1:*]
	;print, "potentialStructures: ", potentialStructures

	; ditto here, except we're checking to make sure it's an attribute that's only one level down
	actualStructures = [-1]
	for i=0, n_elements(notTooDeep)-1 do begin
		void = where(potentialStructures eq notTooDeep[i], count)
		if(count eq 1) then actualStructures = [actualStructures, notTooDeep[i]]
	endfor
	if(n_elements(actualStructures) eq 1) then return, -1
	actualStructures = actualStructures[1:*]

	; going through all the attributes again, but this
	; time searching for the ones that aren't structures
	notStructure = [-1]
	for i=0, n_elements(allAttributes)-1 do begin
		void = where(allNotStructure eq allAttributes[i], count)
		if(count eq 1) then notStructure = [notStructure, allAttributes[i]]
	endfor
	if(n_elements(notStructure) eq 1) then return, -1
	notStructure = notStructure[1:*]


	;print, "actualStructures: ", tagnames[actualStructures]

	; loop through all the resulting structures
	; create the widget for the structure, then recursively call this loop
	; to look for that element's attributes
	for i=0, n_elements(actualStructures)-1 do begin
		dotLocation = strpos(tagnames[ actualStructures[i] ], '.', /reverse_search)
		someWidget = widget_tree(rootWidget, value=strmid(tagnames[ actualStructures[i] ], dotLocation+1), /folder, $
									uvalue = {object:self, method:'treeEvent', index:-1})
		indicesToIgnore = [indicesToIgnore, actualStructures[i]]
		;print, strmid(tagnames[ actualStructures[i] ], dotLocation)

		tempIndicesToIgnore = self->specificPtrCreator(tagnames, descriptor, datasize, $
														someWidget, $
												rootName + strmid(tagnames[ actualStructures[i] ], dotLocation+1) + '\.')
		; keep list of indices already used somewhere else
		indicesToIgnore = [indicesToIgnore,tempIndicesToIgnore]
	endfor

	; loop through the remaining elements, those that aren't structures
	; and create them as sub widgets of the structure
	for i=0, n_elements(notStructure)-1 do begin
		; make sure not to include items that belong to some other widget
		void = where(indicesToIgnore eq notStructure[i], count)
		if(count eq 0) then begin
			dotLocation = strpos(tagnames[ notStructure[i] ], '.', /reverse_search)
			; store location in index and create
			index = self->logAttribute(tagnames[ notStructure[i] ], $
									datasize[ notStructure[i] ], descriptor[ notStructure[i] ])
			someOtherWidget = widget_tree(someWidget, value=strmid(tagnames[ notStructure[i] ], dotLocation+1), $
											uvalue = {object:self, method:'treeEvent', index:index})
			indicesToIgnore = [IndicesToIgnore, notStructure[i]]
		endif
	endfor

	return,indicesToIgnore
end


;************************************************************************************************
; openDAVEFile
;	gives user a dialog window to select a DAVE file.  Does the basic stuff
;	like checking if they actually selected a file, if the file is valid, etc...
;	after that, passes it on to be parsed
; Parameters:
;	event: event object
;************************************************************************************************
function dave_DAVEFileExaminer::openDAVEFile, event

	fileName = dialog_pickfile(/read, title='Open DAVE file', filter='*.dave', path=(*!dave_defaults).workDir)
	; if no file is selected, then we're done
	if(strlen(fileName) eq 0) then begin
		return, 1
	endif
	; restore the file.  Catch possible exception for being invalid file
	catch, error
	if (error ne 0) then begin
		void = dialog_message("The file you selected is not a valid DAVE file.")
		return, 0
	endif

	; if a tree is currently there, destroy it
	davePtr = widget_info(self.tlb, find_by_uname='davePtr')
	if(davePtr ne 0) then widget_control,davePtr,/destroy
	; clear the text pane as well
	displayPane = widget_info(self.tlb,find_by_uname='displayPane')
	widget_control,displayPane,set_value=''


	; this was in john's code, don't know if I need it
	; but am using it for now
	; TODO: test code without the line below
	free_all_ptrs,davePtr
	;print,"filename", filename
	restore, fileName, restored_objects=someObjects
	; deleting any rogue objects that might be in the SAVE file
	heap_free,someObjects
	ptr_free,self.dataFiledavePtr
	self.dataFiledavePtr = davePtr
	catch,/cancel

	;******
	; begin executing John Copley's preexisting code
	lines=""
	levelListing=0
	flags=0
	bptrs=ptr_new()
	dave_beast_ops,"get_ptrs",davePtr,bpointers=dummy
	void = self->analyzeBeast(davePtr,"davePtr",lines,flags,bptrs,0,levelListing,analysis=0)
	;dave_analyze_beast,davePtr,"davePtr",lines,flags,bptrs,analysis=0

;	help, flags, /structure
	;print, flags
	; getting rid of the ""
	nlines=n_elements(lines)-1
	lines=lines[1:nlines]
	levelListing=levelListing[1:nlines]
	flags=flags[1:nlines]

	; getting rid of any empty elements in the array and storing in tagnames
	tagnames=""
	for j=0,nlines-1 do	$
		if ( (flags[j] eq 0) || (flags[j] eq 1) || (flags[j] eq 2) ) then tagnames=[tagnames,lines[j]]
	;print,"listing AFTER: ", tagnames
	; getting rid of "" and creating an array to store the data types
	; corresponding to each of the entries in tagnames
	ntags=n_elements(tagnames)-1
	tagnames=tagnames[1:ntags]
	sns=strarr(ntags)

	; Generate corresponding descriptions.
	idl_type=[" Undefined",$
		" Byte",$
		" Int",$
		" Longint",$
		" Float",$
		" DP float",$
		" Complex float",$
		" String",$
		" Structure",$
		" DP complex",$
		" Pointer",$
		" Object reference",$
		" U Int",$
		" U Longint",$
		" 64-bit Integer",$
		" Unsigned 64-bit Integer"]
	;
	datasize=strarr(ntags)
	descriptor=strarr(ntags)
	datanels=strarr(ntags)
	totel=0l
	; John's code.  Figures out the size of the objects
	; stored in datasize
	; also does something and stores i into datanels
	; not sure what that is yet
	for j=0,ntags-1 do begin
		com="sz=size("+tagnames[j]+")"
		result=execute(com)
		;sns[j]=strmid(tagnames[j],strpos(tagnames[j],'.',/reverse_search)+1)
		;lsns=strlen(sns[j])
		;if (lsns gt 4 and strpos(strupcase(sns[j]),"PTR)")+4 eq lsns) then $
		;	sns[j]=strmid(sns[j],0,lsns-4)
		lsz=n_elements(sz)
		dim=sz[0]
		typ=sz[lsz-2]
		nel=sz[lsz-1]
		if (dim gt 0) then $
			datasize[j]=strcompress(strjoin(sz[1:lsz-3],"*"),/remove_all)$
		else datasize[j]=strcompress(1,/remove_all)
		descriptor[j]=idl_type[typ]
		datanels[j]=sz[lsz-1]
	endfor

	; error catching.  Searching for and removing any object references
	objectIndices = where(descriptor eq " Object reference", count, complement=notObjectIndices)
	if (count ne 0) then begin
		tagnames = tagnames[notObjectIndices]
		descriptor = descriptor[notObjectIndices]
		datanels = datanels[notObjectIndices]
	endif

	; ok, from here, I'm going to try and figure out the hierarchy of the tree I need to build
	; first, find the root of the tree, davePtr
	errorFlag = 0				; used to record any serious errors
	davePtrIndex = where( stregex(tagnames, '^\(\*davePtr\)$', /boolean) eq 1 )
	;print, "davePtr index: ", davePtrIndex
	; ASSUMPTION: there will always be a davePtr in the data file
	treeRoot = widget_info(self.tlb, find_by_uname='treeWidget')
	davePtr = widget_tree(treeRoot, value='davePtr', uname='davePtr', $
							/folder, uvalue = {object:self, method:'treeEvent', index:davePtrIndex})

	; looking for the elements in davePtr
	; first, dataStrPtr
	dataStrPtrIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR)$', /boolean) eq 1, count )
	;print, "dataStrPtrIndex: ", dataStrPtrIndex
	; if it's not a 0 or 1, then either I've written some bad code or the data file is f-ed up
	if( (count ne 1) && (count ne 0) ) then errorFlag=1
	if(count eq 1) then begin
		dataStrPtr = widget_tree(davePtr, value='dataStrPtr', $
									uvalue = {object:self, method:'treeEvent', index:-1}, /folder)
		; if dataStrPtr exists, then look for its members

		; commonStr
		commonStrIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR$', /boolean) eq 1, count )
		if( (count ne 1) && (count ne 0) ) then errorFlag=1
		if(count eq 1) then begin
			commonStr = widget_tree(dataStrPtr, value='commonStr', $
									uvalue = {object:self, method:'treeEvent', index:-1}, /folder)
			; look for histPtr
			histPtrIndex = where( stregex(tagnames, '\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTPTR$', $
											/boolean) eq 1, count )
			if( (count ne 1) && (count ne 0) ) then errorFlag=1
			if(count eq 1) then begin
				histPtr = widget_tree(commonStr, value='histPtr', $
										uvalue = {object:self, method:'treeEvent', index:-1}, /folder)
				; look for histPtr's attributes
				qtyIndex = where( stregex(tagnames, '^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTPTR\)\.QTY$', $
											/boolean) eq 1, count )
				index = self->logAttribute(tagnames[qtyIndex], datasize[qtyIndex], descriptor[qtyIndex])
				histQty = widget_tree(histPtr, value='qty', uname='histQty', $
										uvalue = {object:self, method:'treeEvent', index:index})
				errIndex = where( stregex(tagnames, '^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTPTR\)\.ERR$', $
											/boolean) eq 1, count )
				index = self->logAttribute(tagnames[errIndex], datasize[errIndex], descriptor[errIndex])
				histErr = widget_tree(histPtr, value='err', uname='histErr', $
										uvalue = {object:self, method:'treeEvent', index:index})
				xIndex = where( stregex(tagnames, '^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTPTR\)\.X$', $
											/boolean) eq 1, count )
				index = self->logAttribute(tagnames[xIndex], datasize[xIndex], descriptor[xIndex])
				histX = widget_tree(histPtr, value='x', $
										uvalue = {object:self, method:'treeEvent', index:index})
				yIndex = where( stregex(tagnames, '^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTPTR\)\.Y$', $
											/boolean) eq 1, count )
				index = self->logAttribute(tagnames[yIndex], datasize[yIndex], descriptor[yIndex])
				histY = widget_tree(histPtr, value='y', $
										uvalue = {object:self, method:'treeEvent', index:index})
			endif

			; commonStr's attributes
			treatmentPtrIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.TREATMENTPTR$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[treatmentPtrIndex], datasize[treatmentPtrIndex], descriptor[treatmentPtrIndex])
			commonTreatmentPtr = widget_tree(commonStr, value='treatment', $
												uvalue = {object:self, method:'treeEvent', index:index})
			instrumentIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.INSTRUMENT$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[instrumentIndex], datasize[instrumentIndex], descriptor[instrumentIndex])
			commonInstrument = widget_tree(commonStr, value='instrument', $
												uvalue = {object:self, method:'treeEvent', index:index})
			xTypeIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.XTYPE$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[xTypeIndex], datasize[xTypeIndex], descriptor[xTypeIndex])
			commonXType = widget_tree(commonStr, value='xType', $
												uvalue = {object:self, method:'treeEvent', index:index})
			xLabelIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.XLABEL$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[xLabelIndex], datasize[xLabelIndex], descriptor[xLabelIndex])
			commonXLabel = widget_tree(commonStr, value='xLabel', $
												uvalue = {object:self, method:'treeEvent', index:index})
			xUnitsIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.XUNITS$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[xUnitsIndex], datasize[xUnitsIndex], descriptor[xUnitsIndex])
			commonXUnits = widget_tree(commonStr, value='xUnits', $
												uvalue = {object:self, method:'treeEvent', index:index})
			yTypeIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.YTYPE$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[yTypeIndex], datasize[yTypeIndex], descriptor[yTypeIndex])
			commonYType = widget_tree(commonStr, value='yType', $
												uvalue = {object:self, method:'treeEvent', index:index})
			yUnitsIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.YUNITS$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[yUnitsIndex], datasize[yUnitsIndex], descriptor[yUnitsIndex])
			commonYUnits = widget_tree(commonStr, value='yUnits', $
												uvalue = {object:self, method:'treeEvent', index:index})
			yLabelIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.YLABEL$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[yLabelIndex], datasize[yLabelIndex], descriptor[yLabelIndex])
			commonYLabel = widget_tree(commonStr, value='yLabel', $
												uvalue = {object:self, method:'treeEvent', index:index})
			histLabelIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTLABEL$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[histLabelIndex], datasize[histLabelIndex], descriptor[histLabelIndex])
			commonHistLabel = widget_tree(commonStr, value='histLabel', $
												uvalue = {object:self, method:'treeEvent', index:index})
			histUnitsIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DATASTRPTR\)\.COMMONSTR\.HISTUNITS$', $
												/boolean) eq 1, count )
			index = self->logAttribute(tagnames[histUnitsIndex], datasize[histUnitsIndex], descriptor[histUnitsIndex])
			commonHistUnits = widget_tree(commonStr, value='histUnits', $
												uvalue = {object:self, method:'treeEvent', index:index})

		endif

		specificPtrIndex = where( stregex(tagnames, '\(\*\(\*davePtr\)\.DATASTRPTR\)\.SPECIFICPTR$', $
										/boolean) eq 1, count )
		if( (count ne 1) && (count ne 0) ) then errorFlag=1
		attributes = where( stregex(tagnames, '^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.SPECIFICPTR\)\.', $
												/boolean) eq 1,  count2 )
		;print,tagnames
		;print,descriptor
		;print, count2
		if( (count eq 1) && (count2 ne 0) )then begin
			specificPtr = widget_tree(dataStrPtr, value='specificPtr', /folder, $
										uvalue = {object:self, method:'treeEvent', index:-1})
			indicestoIgnore = self->specificPtrCreator(tagnames,descriptor,datasize, $
														specificPtr,'^\(\*\(\*\(\*davePtr\)\.DATASTRPTR\)\.SPECIFICPTR\)\.')
			for j=0, n_elements(attributes)-1 do begin
				void = where(indicesToIgnore eq attributes[j], count3)
				if(count3 eq 0) then begin
					index = self->logAttribute(tagnames[attributes[j]], datasize[attributes[j]], descriptor[attributes[j]])
					someWidget = widget_tree(specificPtr, value=strmid(tagnames[attributes[j]],40), $
												uvalue = {object:self, method:'treeEvent', index:index})
				endif
			endfor
		endif
	endif

	; second, descriPtr
	descriPtrIndex = where( stregex(tagnames, '^\(\*davePtr\)\.DESCRIPTR$', /boolean) eq 1, count )
	if( (count ne 1) && (count ne 0) ) then errorFlag=1
	if(count eq 1) then begin
		descriPtr = widget_tree(davePtr, value='descriPtr', /folder, $
									uvalue = {object:self, method:'treeEvent', index:-1})
		nameIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DESCRIPTR\)\.NAME$', /boolean) eq 1, count )
		if(count eq 1) then begin
			index = self->logAttribute(tagnames[nameIndex], datasize[nameIndex], descriptor[nameIndex])
			descriName = widget_tree(descriPtr, value='name', $
										uvalue = {object:self, method:'treeEvent', index:index})
		endif
		unitsIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DESCRIPTR\)\.UNITS$', /boolean) eq 1, count )
		if(count eq 1) then begin
			index = self->logAttribute(tagnames[unitsIndex], datasize[unitsIndex], descriptor[unitsIndex])
			descriUnits = widget_tree(descriPtr, value='units', $
										uvalue = {object:self, method:'treeEvent', index:index})
		endif
		legendIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DESCRIPTR\)\.LEGEND$', /boolean) eq 1, count )
		if(count eq 1) then begin
			index = self->logAttribute(tagnames[legendIndex], datasize[legendIndex], descriptor[legendIndex])
			descriLegend = widget_tree(descriPtr, value='legend', $
										uvalue = {object:self, method:'treeEvent', index:index})
		endif
		qtyIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DESCRIPTR\)\.QTY$', /boolean) eq 1, count )
		if(count eq 1) then begin
			index = self->logAttribute(tagnames[qtyIndex], datasize[qtyIndex], descriptor[qtyIndex])
			descriQty = widget_tree(descriPtr, value='qty', $
										uvalue = {object:self, method:'treeEvent', index:index})
		endif
		errIndex = where( stregex(tagnames, '^\(\*\(\*davePtr\)\.DESCRIPTR\)\.ERR$', /boolean) eq 1, count )
		if(count eq 1) then begin
			index = self->logAttribute(tagnames[errIndex], datasize[errIndex], descriptor[errIndex])
			descriErr = widget_tree(descriPtr, value='err', $
										uvalue = {object:self, method:'treeEvent', index:index})
		endif
	endif

	defined=where(descriptor ne " Undefined" and $
		descriptor ne " Pointer" and $
		descriptor ne " Object reference",ntags)
	tagnames=tagnames[defined]
	sns=sns[defined]
	datasize=datasize[defined]
	descriptor=descriptor[defined]
	datanels=datanels[defined]

	;free_all_ptrs,self.davePtr
	;help, davePtr
	;self.davePtr = davePtr
	;ncols=5
	;ntags=n_elements(tagnames)
	;maxnrows=(ntags-1)/ncols+1
	; ***** end executing John Copley's preexisting code
	;print, "tagnames: ", tagnames
	;print, "sns: ", sns
	;print, "datasize: ", datasize
	;print, "descripter: ", descriptor
	;print, "datanels: ", datanels

	; Generating the tree


	return,1
end

;************************************************************************************************
; resizeWindow
;	resets the inner widget dimensions to properly fit the new window size
; Parameters:
;	event: event object
;************************************************************************************************
function dave_DAVEFileExaminer::resizeWindow, event

	; don't even bother using event.  Everything else represents
	; size in pixels, but event doesn't (way to go, RSI)
	geometry = widget_info(self.tlb, /geometry)
	newX = geometry.scr_xsize
	newY = geometry.scr_ysize
	; get the diff in size.  Divide by two for x since we have two widgets side by side
	diffX = (newX - self.currXSize)/2
	diffY = (newY - self.currYSize)

	treeWidget = widget_info(self.tlb, find_by_uname='treeWidget')
	treeGeom = widget_info(treeWidget, /geometry)
	displayPane = widget_info(self.tlb, find_by_uname='displayPane')
	displayGeom = widget_info(displayPane, /geometry)

;	print, "old x: ", self.currXSize
;	print, "old y: ", self.currYSize
;	print, "newX: ", newX
;	print, "newY: ", newY
;	print, "tree x: ", treeGeom.scr_xsize
;	print, "tree y: ", treeGeom.scr_ysize
;	print, "display x: ", displayGeom.scr_xsize
;	print, "display y: ", displayGeom.scr_ysize
;	print, "diffX: ", diffX
;	print, "diffY: ", diffY

	; resize
	widget_control,treeWidget,scr_xsize=(treeGeom.scr_xsize + diffX), scr_ysize=(treeGeom.scr_ysize + diffY)
	widget_control,displayPane,scr_xsize=(displayGeom.scr_xsize + diffX), scr_ysize=(displayGeom.scr_ysize + diffY)
	; reset the curr values
	geometry = widget_info(self.tlb, /geometry)
	self.currXSize = geometry.scr_xsize
	self.currYSize = geometry.scr_ysize

	return,1
end


;************************************************************************************************
; destroy
;	the actual destructor, since I can't seem to freakin' access the objects
;	unless it's a method of said object, and xmanager won't let me call
;	a class function
;************************************************************************************************
function dave_DAVEFileExaminer::destroy, event

	; pretty straight forward.  Destroy pointers and kill widget
	heap_free,self.dataFileDavePtr
	ptr_free,self.names
	ptr_free,self.dataSizes
	ptr_free,self.descriptors
	widget_control,self.tlb,/destroy

	return, 1

end

;************************************************************************************************
; PopupAbout
;	Pops up a dialog window giving the basic about info of the tool
; Parameters:
;	event: event object
;************************************************************************************************
function dave_DAVEFileExaminer::PopupAbout, event
	infoText = 'DAVE Datafile Examiner version 1.0'
	infoText = [infoText, 'Written by Edwin Bachetti']
	void = dialog_message(infoText, /information)

	return, 1
end

;************************************************************************************************
; openHelpFile
;	opens the PDF file with the help information
; Parameters:
;	event: event object
;************************************************************************************************
function dave_DAVEFileExaminer::openHelpFile, event
	;widget_control,event.top,get_uvalue = pState
	void = launch_help(!DAVE_AUXILIARY_DIR+'DAVEdatafileexaminer.pdf',tlb = event.top)
	return, 1
end

;************************************************************************************************
; eventHandler
;	event handler.  Calls the appropriate method for a given event
; Parameters:
;	event: event object
;************************************************************************************************
pro dave_DAVEFileExaminer_eventHandler, event
	;help, event, /structure
	widget_control,event.id,get_uvalue = cmd
	if tag_names(event,/structure_name) eq 'WIDGET_BASE' then begin
		ret = (cmd.object)->resizeWindow(event)
	   return
	endif
	;print,cmd.method
	;help, event, /structure
	ret = call_method(cmd.method,cmd.object,event)
end


;************************************************************************************************
; cleanup
;	destructor
;************************************************************************************************
pro dave_DAVEFileExaminer_cleanup,event

	widget_control,event,get_uvalue=cmd
	ret = call_method(cmd.method,cmd.object, event)
	obj_destroy,cmd.object

end


;************************************************************************************************
; init
;	constructor for object.  Creates window and sets davePtr in object
; Parameters:
;	davePtr - pointer to the DAVE object to be inspected
;	groupLeader - widget ID to the main Dave program window
;************************************************************************************************
function dave_DAVEFileExaminer::init, davePtr, groupLeader

	; creating simple window.  Tree widget with display pane
	tlb = widget_base(/row,title="DAVE Datafile Examiner", mbar = bar, group_leader=groupLeader, /tlb_size_events, $
						uvalue = {object:self, method:'destroy'})
	invisi = widget_base(/row)
	; file menu.  Opening, closing, and exiting
	filemenu = widget_button(bar,value = 'File',/menu)
	void = widget_button(filemenu,value = 'Open DAVE file', $
							uvalue = {object:self, method:'openDAVEFile'})
	void = widget_button(filemenu,value = 'Close DAVE file', $
							uvalue = {object:self, method:'closeDAVEFile'})
	void = widget_button(filemenu,value = 'Exit', $
							uvalue = {object:self, method:'destroy'});
	; help menu.  About and help contents
	helpMenu = widget_button(bar, value = 'Help', /menu)
	void = widget_button(helpMenu, value='Contents', $
							uvalue= {object:self, method:'openHelpFile'})
	void = widget_button(helpMenu, value='About', $
							uvalue={object:self, method:'PopupAbout'})

	treeWidget = widget_tree(tlb, /multiple, uname='treeWidget', $
								uvalue = {object:self, method:'treeEvent'})
	;blah = widget_tree(treeWidget, value="blah", uname='blah')
	;whee = widget_tree(treeWidget, value="whee")

	; determine the OS and set the proper font
	; using a fixed format font to get spacing right in text widget
	case (!version.os_family eq 'Windows') of
	    1: font = 'Courier New*14'
	    else: font = '-adobe-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1'
	endcase

	displayPane = widget_text(tlb, uname="displayPane", ysize=20, xsize=50, /scroll, font=font)

	; make visible
	widget_control,tlb,/realize

	; initializing class attributes
	geometry = widget_info(tlb,/geometry)
	self.tlb = tlb
	self.treeWidget = treeWidget
	self.currXSize = geometry.scr_xsize
	self.currYSize = geometry.scr_ysize

	ptr_free,self.names
	ptr_free,self.dataSizes
	ptr_free,self.descriptors
	someThing = ""
	self.names = ptr_new(something)
	self.dataSizes = ptr_new(SOMETHING)
	self.descriptors = ptr_new(someThing)


	help,davePtr
	dcs_sysvars,davePtr=davePtr
	free_all_ptrs,self.davePtr
	self.davePtr = davePtr

	; let the show begin
	xmanager,"dave_DAVEFileExaminer",tlb,event_handler = 'dave_DAVEFileExaminer_eventHandler', $
		cleanup = 'dave_DAVEFileExaminer_cleanup',/no_block

	return, 1
end



; definition
pro dave_DAVEFileExaminer__define
	define =	{	dave_DAVEFileExaminer, $
					davePtr:ptr_new(), $
					dataFileDavePtr:ptr_new(), $

					tlb:0L, $
					treeWidget:0l, $
					currXSize:0L, $
					currYSize:0L, $

					names:ptr_new(""), $
					dataSizes:ptr_new(""), $
					descriptors:ptr_new("") $
				}
end