; $Id: rafins_pinfo.pro,v 1.3 2005/02/08 18:47:07 dimeo Exp $
;###############################################################################
;
; NAME:
;  RAFINS_PINFO
;
; PURPOSE:
;
; CATEGORY:
;  DAVE, Data Analysis, RAINS, surface fitting
;
; AUTHOR:
;   Robert M. Dimeo, Ph.D.
;   NIST Center for Neutron Research
;   100 Bureau Drive
;   Gaithersburg, MD 20899
;   Phone: (301) 975-8135
;   E-mail: robert.dimeo@nist.gov
;   http://www.ncnr.nist.gov/staff/dimeo
;
; LICENSE:
;  The software in this file is written by an employee of
;  National Institute of Standards and Technology
;  as part of the DAVE software project.
;
;  The DAVE software package is not subject to copyright protection
;  and is in the public domain. It should be considered as an
;  experimental neutron scattering data reduction, visualization, and
;  analysis system. As such, the authors assume no responsibility
;  whatsoever for its use, and make no guarantees, expressed or
;  implied, about its quality, reliability, or any other
;  characteristic. The use of certain trade names or commercial
;  products does not imply any endorsement of a particular product,
;  nor does it imply that the named product is necessarily the best
;  product for the stated purpose. We would appreciate acknowledgment
;  if the DAVE software is used of if the code in this file is
;  included in another product.
;
;###############################################################################
;+
;
;-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_cleanup,tlb
compile_opt idl2,hidden
widget_control,tlb,get_uvalue = pstate
ptr_free,pstate
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_send,event
compile_opt idl2,hidden
widget_control,event.top,get_uvalue = pstate
p_info =	{	RAFINS_PINFO_EVENT,				$
				id:(*pstate).notify_ids[0],		$
				top:(*pstate).notify_ids[1],	$
				handler:0L,						$
				cancel:(*pstate).cancel			$
			}

if widget_info((*pstate).notify_ids[0],/valid_id) then $
	widget_control,(*pstate).notify_ids[0],send_event = p_info
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_quit,event
compile_opt idl2,hidden
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_get_info,event
compile_opt idl2,hidden
widget_control,event.top,get_uvalue = pState
if (*pstate).n_single gt 0 then begin
	for i = 0,(*pstate).n_single-1 do begin
		widget_control,(*pstate).single_fields[i],get_value = val
		val = float(val[0])
		if i eq 0 then parms = val else parms = [parms,val]
	endfor
	ret = (*pstate).ofunction->get(params = params)
	params[0:(*pstate).n_single-1] = parms
	ret = (*pstate).ofunction->set(params = params)
endif
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_apply,event
compile_opt idl2,hidden
; The user has pressed the 'APPLY' button
widget_control,event.top,get_uvalue = pState
(*pstate).cancel = 0
rafins_pinfo_get_info,event
rafins_pinfo_send,event
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_dismiss,event
compile_opt idl2,hidden
; The user has pressed the 'ACCEPT' button
widget_control,event.top,get_uvalue = pState
(*pstate).cancel = 1
rafins_pinfo_send,event
rafins_pinfo_quit,event
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo_event,event
widget_control,event.top,get_uvalue = pstate
uname = widget_info(event.id,/uname)
case uname of
'APPLY':	$
	begin
		rafins_pinfo_apply,event
	end
'DISMISS':	$
	begin
		rafins_pinfo_dismiss,event
	end
'MULTI_FIELD':	$
	begin
		catch,the_error
		if the_error ne 0 then begin
			catch,/cancel
			return
		endif
		; Get the current slider value out
		widget_control,event.id,get_uvalue = uval
		slider_id = uval.slider_id
		set = widget_info(uval.fix_id,/button_set)
		index = uval.index
		if widget_info(slider_id,/uname) ne 'RAFINS_SLIDER' then return
		widget_control,slider_id,get_value = val & val = fix(val[0]-1)
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames)
		n_single = (*pstate).n_single
		ny = (*pstate).ny
		init = n_single
		i_start = init+index*ny
		i_finish = init+(index+1)*ny-1
		relevant_params = params[i_start:i_finish]

		widget_control,event.id,get_value = new_value
		a = dm_to_number(new_value[0])
		if not finite(a) then return else new_value = float(new_value[0])
		relevant_params[val] = new_value
		params[i_start:i_finish] = relevant_params
		ret = (*pstate).ofunction->set(	params = params )

	end
'RAFINS_SLIDER':	$
	begin
		widget_control,event.id,get_uvalue = uval
		index = uval.index
		field_id = uval.field_id
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										fixed = fixed,					$
										high = high,					$
										hivalues = hivalues				)
		n_single = (*pstate).n_single
		ny = (*pstate).ny
		init = n_single
		i_start = init+index*ny
		i_finish = init+(index+1)*ny-1
		relevant_params = params[i_start:i_finish]

		widget_control,event.id,get_value = val & val = fix(val[0]-1)
		this_param = relevant_params[val]
		widget_control,field_id,set_value = strtrim(string(this_param),2)
		; Update the lower limit checkbox
		relevant_low_checks = low[i_start:i_finish]
		this_lo_check = relevant_low_checks[val]
		widget_control,uval.lo_checks,set_button = this_lo_check
		; Update the lower limit value
		relevant_low_values = lovalues[i_start:i_finish]
		this_low_value = relevant_low_values[val]
		widget_control,uval.low_value,set_value = this_low_value
		; Update the upper limit checkbox
		relevant_high_checks = high[i_start:i_finish]
		this_hi_check = relevant_high_checks[val]
		widget_control,uval.hi_checks,set_button = this_hi_check
		; Update the upper limit value
		relevant_high_values = hivalues[i_start:i_finish]
		this_high_value = relevant_high_values[val]
		widget_control,uval.high_value,set_value = this_high_value
		; Update the fixed checkbox
		relevant_fix_checks = fixed[i_start:i_finish]
		this_fix_check = relevant_fix_checks[val]
		widget_control,uval.fix_checks,set_button = this_fix_check
	end
'LOW_CHECK':	$
	begin
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										hivalues = hivalues				)
		widget_control,event.id,get_uvalue = uval
		n_single = (*pstate).n_single
		tags = tag_names(uval)
		wh = where(strupcase(tags) eq 'SLIDER_ID',count)
		if count gt 0 then begin
			ret = (*pstate).ofunction->get(	low = low)
			slider_id = uval.slider_id
			slider_index = uval.slider_index
			ny = (*pstate).ny
			init = n_single
			i_start = init+slider_index*ny
 			i_finish = init+(slider_index+1)*ny-1
			relevant_low_checks = low[i_start:i_finish]
			widget_control,slider_id,get_value = val & val = fix(val[0]-1)
			relevant_low_checks[val] = event.select
			low[i_start:i_finish] = relevant_low_checks
			ret = (*pstate).ofunction->set( low = low)
		endif else begin
			ret = (*pstate).ofunction->get(	low = low)
			low[uval.index] = event.select
			ret = (*pstate).ofunction->set( low = low)
		endelse
	end
'LOW_VALUE':	$
	begin
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										hivalues = hivalues				)
		widget_control,event.id,get_value = new_value
		a = dm_to_number(new_value[0])
		if not finite(a) then return else new_value = float(new_value[0])

		widget_control,event.id,get_uvalue = uval
		n_single = (*pstate).n_single
		tags = tag_names(uval)
		wh = where(strupcase(tags) eq 'SLIDER_ID',count)
		if count gt 0 then begin
			ret = (*pstate).ofunction->get(	lovalues = lovalues)
			slider_id = uval.slider_id
			slider_index = uval.slider_index
			ny = (*pstate).ny
			init = n_single
			i_start = init+slider_index*ny
 			i_finish = init+(slider_index+1)*ny-1
			relevant_low_values = lovalues[i_start:i_finish]
			widget_control,slider_id,get_value = val & val = fix(val[0]-1)
			relevant_low_values[val] = new_value
			lovalues[i_start:i_finish] = relevant_low_values
			ret = (*pstate).ofunction->set( lovalues = lovalues)
		endif else begin
			ret = (*pstate).ofunction->get(	lovalues = lovalues)
			lovalues[uval.index] = new_value
			ret = (*pstate).ofunction->set( lovalues = lovalues)
		endelse

	end
'HIGH_CHECK':	$
	begin
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										hivalues = hivalues				)
		widget_control,event.id,get_uvalue = uval
		n_single = (*pstate).n_single
		tags = tag_names(uval)
		wh = where(strupcase(tags) eq 'SLIDER_ID',count)
		if count gt 0 then begin
			ret = (*pstate).ofunction->get(	high = high)
			slider_id = uval.slider_id
			slider_index = uval.slider_index
			ny = (*pstate).ny
			init = n_single
			i_start = init+slider_index*ny
 			i_finish = init+(slider_index+1)*ny-1
			relevant_high_checks = high[i_start:i_finish]
			widget_control,slider_id,get_value = val & val = fix(val[0]-1)
			relevant_high_checks[val] = event.select
			high[i_start:i_finish] = relevant_high_checks
			ret = (*pstate).ofunction->set( high = high)
		endif else begin
			ret = (*pstate).ofunction->get(	high = high)
			high[uval.index] = event.select
			ret = (*pstate).ofunction->set( high = high)
		endelse
	end
'HIGH_VALUE':	$
	begin
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										hivalues = hivalues				)
		widget_control,event.id,get_value = new_value
		a = dm_to_number(new_value[0])
		if not finite(a) then return else new_value = float(new_value[0])

		widget_control,event.id,get_uvalue = uval
		n_single = (*pstate).n_single
		tags = tag_names(uval)
		wh = where(strupcase(tags) eq 'SLIDER_ID',count)
		if count gt 0 then begin
			ret = (*pstate).ofunction->get(	hivalues = hivalues)
			slider_id = uval.slider_id
			slider_index = uval.slider_index
			ny = (*pstate).ny
			init = n_single
			i_start = init+slider_index*ny
 			i_finish = init+(slider_index+1)*ny-1
			relevant_high_values = hivalues[i_start:i_finish]
			widget_control,slider_id,get_value = val & val = fix(val[0]-1)
			relevant_high_values[val] = new_value
			hivalues[i_start:i_finish] = relevant_high_values
			ret = (*pstate).ofunction->set( hivalues = hivalues)
		endif else begin
			ret = (*pstate).ofunction->get(	hivalues = hivalues)
			hivalues[uval.index] = new_value
			ret = (*pstate).ofunction->set( hivalues = hivalues)
		endelse
	end
'FIX_CHECK':	$
	begin
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										fixed = fixed,					$
										hivalues = hivalues				)
		widget_control,event.id,get_uvalue = uval
		n_single = (*pstate).n_single
		tags = tag_names(uval)
		wh = where(strupcase(tags) eq 'SLIDER_ID',count)
		if count gt 0 then begin
			ret = (*pstate).ofunction->get(	high = high)
			slider_id = uval.slider_id
			slider_index = uval.slider_index
			ny = (*pstate).ny
			init = n_single
			i_start = init+slider_index*ny
 			i_finish = init+(slider_index+1)*ny-1
			relevant_fix_checks = fixed[i_start:i_finish]
			widget_control,slider_id,get_value = val & val = fix(val[0]-1)
			relevant_fix_checks[val] = event.select
			fixed[i_start:i_finish] = relevant_fix_checks
			ret = (*pstate).ofunction->set( fixed = fixed)
		endif else begin
			ret = (*pstate).ofunction->get(	fixed = fixed)
			fixed[uval.index] = event.select
			ret = (*pstate).ofunction->set( fixed = fixed)
		endelse
	end
'FIX_ALL':	$
	begin
		; Get the current slider position
		widget_control,event.id,get_uvalue = uval
		widget_control,uval.slider_id,get_value = val & val = fix(val[0]-1)
		ret = (*pstate).ofunction->get(	params = params,	$
										multi_parmnames = m_parmnames, $
										single_parmnames = s_parmnames,	$
										low = low,						$
										lovalues = lovalues,			$
										high = high,					$
										fixed = fixed,					$
										hivalues = hivalues				)

		n_single = (*pstate).n_single
		slider_id = uval.slider_id
		slider_index = uval.slider_index
		ny = (*pstate).ny
		init = n_single
		i_start = init+slider_index*ny
 		i_finish = init+(slider_index+1)*ny-1
		relevant_params = params[i_start:i_finish]
		relevant_checks = fixed[i_start:i_finish]
		if event.select eq 1 then begin
			params[i_start:i_finish] = relevant_params[val]
			fixed[i_start:i_finish] = 1
			ret = (*pstate).ofunction->set(	params = params,fixed = fixed)
		endif
		if event.select eq 0 then begin
			params[i_start:i_finish] = relevant_params[val]
			fixed[i_start:i_finish] = 0
			ret = (*pstate).ofunction->set(	params = params,fixed = fixed)
		endif
		; Update the current fixed check box
		widget_control,uval.fix_checks,set_button = event.select
	end
else:
endcase
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro rafins_pinfo,	ofunction,								$
					group_leader = group_leader,			$
					notify_ids = notify_ids
compile_opt idl2,hidden
if n_params() eq 0 then return
; Now pull out all of the information from the function object
ret = ofunction->get(	parmnames = parmnames,				$
						single_parmnames = s_parmnames,		$
						multi_parmnames = m_parmnames,		$
						all_y = all_y,						$
						yvalues = yvalues,					$
						low = low,							$
						lovalues = lovalues,				$
						high = high,						$
						hivalues = hivalues,				$
						fixed = fixed,						$
						params = params						$
					)
if s_parmnames[0] ne '' then n_single = n_elements(s_parmnames) else n_single = 0
if m_parmnames[0] ne '' then n_multi = n_elements(params) - n_single else n_multi = 0
ny = n_elements(yvalues)
tlb = widget_base(group_leader = group_leader,/tlb_frame_attr,/col,	$
	title = 'Parameter Modification Entry')
nrows = n_single+n_multi
single_fields = 0L
multi_fields = 0L
count_widgets = 0L
field_size = 10
if m_parmnames[0] eq '' then n_this_multi = 0 else n_this_multi = n_elements(m_parmnames)
lo_checks = lonarr(n_single+n_this_multi)
hi_checks = lonarr(n_single+n_this_multi)
fix_checks = lonarr(n_single+n_this_multi)
lo_value = lonarr(n_single+n_this_multi)
hi_value = lonarr(n_single+n_this_multi)
if n_single gt 0 then begin
	single_fields = lonarr(n_single)
	single_row_base = lonarr(n_single)
	for i = 0,n_single-1 do begin
		single_row_base[i] = widget_base(tlb,/row,/align_right)
		this_title = strtrim(s_parmnames[i],2)
		single_fields[i] = cw_field(single_row_base[i],	$
			value = params[i],title = this_title,xsize = field_size)
		fix_base = widget_base(single_row_base[i],/row,/nonexclusive)
		fix_checks[count_widgets] = widget_button(fix_base,value = 'Fixed', $
			uname = 'FIX_CHECK',uvalue = {index:count_widgets})
		lo_base = widget_base(single_row_base[i],/row,/frame)
		lo_value[count_widgets] = cw_field(lo_base,title = 'Low', $
			uname = 'LOW_VALUE',value = strtrim(string(lovalues[i]),2), $
			uvalue = {index:count_widgets},/all_events,xsize = field_size)
		non_ex_base_a = widget_base(lo_base,/row,/nonexclusive)
		lo_checks[count_widgets] = widget_button(non_ex_base_a,value = 'Set lower bound', $
			uname = 'LOW_CHECK',uvalue = {index:count_widgets})
		hi_base = widget_base(single_row_base[i],/row,/frame)
		hi_value[count_widgets] = cw_field(hi_base,title = 'High', $
			uname = 'HIGH_VALUE',value = strtrim(string(hivalues[i]),2), $
			uvalue = {index:count_widgets},/all_events,xsize = field_size)
		non_ex_base_b = widget_base(hi_base,/row,/nonexclusive)
		hi_checks[count_widgets] = widget_button(non_ex_base_b,value = 'Set upper bound', $
			uname = 'HIGH_CHECK',uvalue = {index:count_widgets})
		widget_control,hi_checks[count_widgets],set_button = high[count_widgets]
		widget_control,fix_checks[count_widgets],set_button = fixed[count_widgets]
		widget_control,lo_checks[count_widgets],set_button = low[count_widgets]
		count_widgets = count_widgets + 1L
	endfor
endif
if n_multi gt 0 then begin
	n_multi_diff_parms = n_elements(m_parmnames)
	multi_fields = lonarr(n_multi_diff_parms)
	multi_row_base = lonarr(n_multi_diff_parms)
	slider_id = lonarr(n_multi_diff_parms)
	fix_id = lonarr(n_multi_diff_parms)
	for i = 0,n_multi_diff_parms-1 do begin
		multi_row_base[i] = widget_base(tlb,/row,/align_right)
		fix_ex_base = widget_base(multi_row_base[i],/row,/nonexclusive)
		fix_id[i] =	widget_button(fix_ex_base,value = 'Fix all values', $
					uname = 'FIX_ALL',uvalue =		{	index:count_widgets,	$
														slider_id:0L,	$
														slider_index:i, $
														fix_checks:0L})
		this_title = strtrim(m_parmnames[i],2)
		this_title = 'Group'
		slider_id[i] = widget_slider(multi_row_base[i],value = 1,min = 1,max = ny, $
						uname = 'RAFINS_SLIDER',title = this_title)
		widget_control,fix_id[i],get_uvalue = uval
		uval.slider_id = slider_id[i]
		widget_control,fix_id[i],set_uvalue = uval
		multi_fields[i] = cw_field(multi_row_base[i],value = params[n_single+i*ny], $
			title = m_parmnames[i], uname = 'MULTI_FIELD',/all_events,xsize = field_size)
		fix_base = widget_base(multi_row_base[i],/row,/nonexclusive)
		fix_checks[count_widgets] = widget_button(fix_base,value = 'Fixed', $
			uname = 'FIX_CHECK',uvalue =	{	index:count_widgets,	$
												slider_id:slider_id[i],	$
												slider_index:i})
		widget_control,fix_id[i],get_uvalue = uval
		uval.fix_checks = fix_checks[count_widgets]
		widget_control,fix_id[i],set_uvalue = uval
		this_base = widget_base(multi_row_base[i],/row,/frame)
		lo_value[count_widgets] = cw_field(this_base,title = 'Low', $
			uname = 'LOW_VALUE',value = strtrim(string(lovalues[n_single+i*ny]),2), /all_events,$
			uvalue =	{	index:count_widgets,	$
							slider_id:slider_id[i],	$
							slider_index:i},xsize = field_size)
		non_ex_base_a = widget_base(this_base,/row,/nonexclusive)
		lo_checks[count_widgets] = widget_button(non_ex_base_a,value = 'Set lower bound', $
			uname = 'LOW_CHECK',uvalue =	{	index:count_widgets,	$
												slider_id:slider_id[i],	$
												slider_index:i})
		hi_base = widget_base(multi_row_base[i],/row,/frame)
		hi_value[count_widgets] = cw_field(hi_base,title = 'High', $
			uname = 'HIGH_VALUE',value = strtrim(string(hivalues[n_single+i*ny]),2), /all_events,$
			uvalue =	{	index:count_widgets,	$
							slider_id:slider_id[i],	$
							slider_index:i},xsize = field_size)
		non_ex_base_b = widget_base(hi_base,/row,/nonexclusive)
		hi_checks[count_widgets] = widget_button(non_ex_base_b,value = 'Set upper bound', $
			uname = 'HIGH_CHECK',uvalue =	{	index:count_widgets,	$
												slider_id:slider_id[i],	$
												slider_index:i})
		widget_control,lo_checks[count_widgets],set_button = low[n_single+i*ny]
		widget_control,fix_checks[count_widgets],set_button = fixed[n_single+i*ny]
		widget_control,hi_checks[count_widgets],set_button = high[n_single+i*ny]

		; Exchange widget ids in the user-values so that we can associate one
		; with the other when we handle the events
		widget_control,slider_id[i],set_uvalue = {field_id:multi_fields[i],index:i, $
			lo_checks:lo_checks[count_widgets],low_value:lo_value[count_widgets], $
			hi_checks:hi_checks[count_widgets],high_value:hi_value[count_widgets], $
			fix_checks:fix_checks[count_widgets]}
		widget_control,multi_fields[i],set_uvalue = {slider_id:slider_id[i],index:i,$
			lo_checks:lo_checks[count_widgets],fix_id:fix_id[i]}
		count_widgets = count_widgets + 1L
	endfor
endif

ctrl_row_base = widget_base(tlb,/row)
void = widget_button(ctrl_row_base,value = 'Apply',uname = 'APPLY')
void = widget_button(ctrl_row_base,value = 'Dismiss',uname = 'DISMISS')
centertlb,tlb
widget_control,tlb,/realize

state =	{	ofunction:ofunction,								$
			notify_ids:notify_ids,								$
			ny:ny,												$
			fix_id:fix_id,										$
			n_single:n_single,									$
			n_multi:n_multi,									$
			lo_checks:lo_checks,								$
			hi_checks:hi_checks,								$
			single_fields:single_fields,						$
			multi_fields:multi_fields,							$
			cancel:1											}

pState = ptr_new(state,/no_copy)
widget_control,tlb,set_uvalue = pState


xmanager,'rafins_pinfo',tlb,/no_block,cleanup = 'rafins_pinfo_cleanup', $
	event_handler = 'rafins_pinfo_event'
end