;$Id: db_xrebin.pro,v 1.12 2006/08/29 20:22:41 azuah Exp $
;###############################################################################
;
; NAME:
;   DB_Xrebin
;
; PURPOSE:
;   Modal widget dialog that gets the data rebinning information from
;   the user, packages it up, and returns it to the calling program in
;   a structure.
;
; CATEGORY:
;   Data Browser
;
; AUTHORS:
;   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
;   Dec, 2002
;
;   Richard Tumanjong Azuah
;   azuah@nist.gov; (301) 9755604
;
; 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 or if the code in this file is
;  included in another product.
;
;###############################################################################



;===============================================================================
; DB_XR_UpdateFields
;
; PURPOSE:
;   Event handler. Update all fields in main dialog
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_UpdateFields,event
widget_control,event.top,get_uvalue = pState

end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_UpdateValues
;
; PURPOSE:
;   Event handler. Update all values in the main dialog with those
;   from the state structure.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_UpdateValues,event
widget_control,event.top,get_uvalue = pState
oContainer = (*pState).oContainer
oall = oContainer->get(/all)
;void = oall[(*pState).fileIndex]->get(dataref = o)
o = oall[(*pState).fileIndex] 
r = o->get(xVal=xVal,yVal=yVal)

class = obj_class(o)
if class eq 'DAVEDAT1D' then begin
	id_groupBase = widget_info(event.top,find_by_uname = 'GROUP_BASE')
	widget_control,id_groupBase,map = 0
endif else begin
	id_groupBase = widget_info(event.top,find_by_uname = 'GROUP_BASE')
	widget_control,id_groupBase,map = 1
endelse

; Which axis are we rebinning?
id_axis = widget_info(event.top,find_by_uname = 'REBIN_AXIS')
widget_control,id_axis,get_value = val
if fix(val[0]) eq 0 then begin
	thisValue = xVal
        minval = (*(*pState).pbin_min)[0,(*pState).fileIndex]
        maxval = (*(*pState).pbin_max)[0,(*pState).fileIndex]
        dval = (*(*pState).pbin_width)[0,(*pState).fileIndex]
endif else begin
	thisValue = yVal
        minval = (*(*pState).pbin_min)[1,(*pState).fileIndex]
        maxval = (*(*pState).pbin_max)[1,(*pState).fileIndex]
        dval = (*(*pState).pbin_width)[1,(*pState).fileIndex]
endelse

n = n_elements(thisValue)
x_min = min(thisValue) & x_max = max(thisValue)
dx = thisValue[1:n-1] - thisValue[0:n-2]
dx_min = min(dx, max=dx_max)

x_min_str = strtrim(string(x_min),2)
x_max_str = strtrim(string(x_max),2)
dx_min_str = strtrim(string(dx_min),2)
dx_max_str = strtrim(string(dx_max),2)

; Update the current value fields
id_cur_min = widget_info(event.top,find_by_uname = 'CUR_MIN')
id_cur_max = widget_info(event.top,find_by_uname = 'CUR_MAX')
id_cur_width = widget_info(event.top,find_by_uname = 'CUR_WIDTH')
id_cur_max_width = widget_info(event.top,find_by_uname = 'CUR_WIDTH_MAX')
widget_control,id_cur_min,set_value = x_min_str
widget_control,id_cur_max,set_value = x_max_str
widget_control,id_cur_width,set_value = dx_min_str
widget_control,id_cur_max_width,set_value = dx_max_str

; Update the new value fields
;x_min_str = strtrim(string((*(*pState).pbin_min)[(*pState).fileIndex]),2)
;x_max_str = strtrim(string((*(*pState).pbin_max)[(*pState).fileIndex]),2)
;dx_min_str = strtrim(string((*(*pState).pbin_width)[(*pState).fileIndex]),2)

id_new_min = widget_info(event.top,find_by_uname = 'NEW_MIN')
id_new_max = widget_info(event.top,find_by_uname = 'NEW_MAX')
id_new_width = widget_info(event.top,find_by_uname = 'NEW_WIDTH')

widget_control,id_new_min,set_value = minval;_str
widget_control,id_new_max,set_value = maxval;_str
widget_control,id_new_width,set_value = dval;_str
end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_Init
;
; PURPOSE:
;   Event handler. Initialize all fields in dialog and state structure
;   from the datasets.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_Init,event
widget_control,event.top,get_uvalue = pState
oContainer = (*pState).oContainer
oall = oContainer->get(/all)
nfiles = oContainer->count()

rebAxis = replicate('x',nfiles)
*(*pState).pbin_min = fltarr(2,nfiles)
*(*pState).pbin_max = fltarr(2,nfiles)
*(*pState).pbin_width = fltarr(2,nfiles)
*(*pState).pbin_axis = rebAxis

for i = 0,nfiles-1 do begin
    ;void = oall[i]->get(dataref = o)
    o = oall[i]
    void = o->get(xVal = xVal,yVal=yVal)

    nx = n_elements(xVal)
    x_min = min(xVal,max=x_max)
    dx = xVal[1:nx-1] - xVal[0:nx-2]
    dx_min = min(dx, max=dx_max)

    (*(*pState).pbin_min)[0,i] = x_min
    (*(*pState).pbin_max)[0,i] = x_max
    (*(*pState).pbin_width)[0,i] = dx_max

    if (obj_class(o) eq 'DAVEDAT2D') then begin
        ny = n_elements(yVal)
        y_min = min(yVal,max=y_max)
        dy = yVal[1:ny-1] - yVal[0:ny-2]
        dy_min = min(dy, max=dy_max)
        
        (*(*pState).pbin_min)[1,i] = y_min
        (*(*pState).pbin_max)[1,i] = y_max
        (*(*pState).pbin_width)[1,i] = dy_max
    endif
endfor

end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_ChangeFiles
;
; PURPOSE:
;   Event handler. Change datasets to be modified.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_ChangeFiles,event
widget_control,event.top,get_uvalue = pState
(*pState).fileIndex = event.index[0]
(*pState).fileOut = (*pState).filenames[event.index[0]]
db_xr_updateValues,event
end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_ChangerebinAxis
;
; PURPOSE:
;   Event handler. Change rebin axis.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_ChangerebinAxis,event
widget_control,event.top,get_uvalue = pState
id_rebinAxis = widget_info(event.top,find_by_uname = 'CUT_AXIS')
widget_control,id_rebinAxis,get_value = val
val = val[0]
if val eq 0 then caxis = 'x' else caxis = 'y'
(*pState).rebinAxis = caxis
db_dc_updateArrays,event
db_dc_updateFields,event
db_dc_plotRegion,event
end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_UpdateAxis
;
; PURPOSE:
;   Event handler. Store rebin axis setting.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_UpdateAxis,event
widget_control,event.top,get_uvalue = pState
if event.value eq 0 then begin
	caxis = 'x'
endif else begin
	caxis = 'y'
endelse
(*(*pState).pbin_axis)[(*pState).fileIndex] = caxis
end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_XR_Events
;
; PURPOSE:
;   Event handler. Main event handler.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro DB_XR_Events,event
widget_control,event.top,get_uvalue = pState
uname = widget_info(event.id,/uname)

id = widget_info(event.top,find_by_uname='REBIN_AXIS')
widget_control,id,get_value=iaxis

case uname of
    'DATASELECTION': $
      begin
        db_xr_changeFiles,event
    end
    'REBIN_AXIS': $
      begin
        db_xr_updateAxis,event
        db_xr_updateValues,event
    end
    'NEW_MIN': $
      begin
        widget_control,event.id,get_value = newval
                                ;newval = float(newval)
        (*(*pState).pbin_min)[iaxis,(*pState).fileIndex] = newval
        db_xr_updateValues,event
    end
    'NEW_MAX': $
      begin
        widget_control,event.id,get_value = newval
                                ;newval = float(newval)
        (*(*pState).pbin_max)[iaxis,(*pState).fileIndex] = newval
        db_xr_updateValues,event
    end
    'NEW_WIDTH': $
      begin
        widget_control,event.id,get_value = newval
                                ;newval = float(newval)
        id_curmin = widget_info(event.top,find_by_uname = 'CUR_WIDTH')
        widget_control,id_curmin,get_value = curval
                                ;curval = float(curval[0])
        newval = newval > curval
        (*(*pState).pbin_width)[iaxis,(*pState).fileIndex] = newval
        db_xr_updateValues,event
    end
    'APPLY_TO_ALL': begin
        id = widget_info(event.top,find_by_uname='NEW_MIN')
        widget_control,id,get_value=newmin
        id = widget_info(event.top,find_by_uname='NEW_MAX')
        widget_control,id,get_value=newmax
        id = widget_info(event.top,find_by_uname='NEW_WIDTH')
        widget_control,id,get_value=newwidth
        for i=0,n_elements(*(*pState).pbin_axis) - 1 do begin
            (*(*pState).pbin_axis)[i] = (iaxis eq 0)? 'x' : 'y'
            (*(*pState).pbin_min)[iaxis,i] = newmin
            (*(*pState).pbin_max)[iaxis,i] = newmax
            (*(*pState).pbin_width)[iaxis,i] = newwidth
        endfor 
    end
    'TRUNCATE': $
      begin
        (*pState).truncate = event.select
    end
    'ACCEPT': $
      begin
        widget_control,event.top,/destroy
    end
    'CANCEL': $
      begin
        (*pState).cancel = 1
        widget_control,event.top,/destroy
    end

    else:
endcase

end
;-------------------------------------------------------------------------------



;===============================================================================
; DB_dataCuts
;
; PURPOSE:
;   Modal widget dialog that gets the data cutting information from
;   the user, packages it up, and returns it to the calling program in
;   a structure.
;
; PARAMETERS:
;   oContainer [in;req] - A container of dataset objects to be rebinned
;
; KEYWORDS:
;   group_leader [in] - the ID of the parent widget from which this
;                       dialog was launched.
;
; RETURN VALUE
;   A structure containing the specified rebin parameters:
;     CANCEL:      0 if false, 1 if true
;     BIN_MIN:     array of minimum values of rebin range
;     BIN_MAX:     array of maximum values of rebin range
;     BIN_WIDTH:   array of bin widths
;     BIN_AXIS:    array of rebin axes: 'x' or 'y'
;     NO_TRUNCATE: if not set (0) then data should be rebinned only
;                  over the range spanning [BIN_MIN,BIN_MAX]
;
function DB_Xrebin, group_leader=group_leader,oContainer
; Pull out all of the "available" files
oall = oContainer->get(/all)
n_objects = oContainer->count()
for i = 0,n_objects-1 do begin
    ;void = oall[i]->get(dataref = o)
    void = (oall[i])->get(nameTag=nameTag,xVal=xVal,yVal=yVal)
    if i eq 0 then begin
        nameTags = nameTag
        nx = n_elements(xVal)
        ny = n_elements(yVal)
    endif else begin
        nameTags = [nameTags,nameTag]
        nx = [nx,n_elements(xVal)]
        ny = [ny,n_elements(yVal)]
    endelse
endfor
nx = nx[0]
ny = ny[0]

; Widget definition module
title='DATABROWSER: Rebin Data'
if n_elements(group_leader) eq 0 then begin
	group_leader = 0L
	modal = 0
        tlb = widget_base(/col, title=title,/align_right)
endif else begin
	modal = 1
        tlb = widget_base(group_leader = group_leader, /col, $
	title=title,modal = modal,/align_right)
endelse

rowBase1 = widget_base(tlb,/row,/align_center)
selections = ['select data',nameTags]
drop = widget_droplist(rowBase1,value = nameTags,uname = 'DATASELECTION', $
		title = 'Select data')

; If the active data file is a 1-dimensional data set then do not map
; the base containing the rebin axis selection.  User should not have
; a choice if the data is one-dimensional!
;void = oall[0]->get(dataref = o,xVal = xVal)
void = oall[0]->get(xVal=xVal)
if obj_class(oall[0]) eq 'DAVEDAT1D' then map = 0 else map = 1
groupBase = widget_base(rowBase1,/row,map = map,uname = 'GROUP_BASE')
rebinAxisName = ['x','y']
void = cw_bgroup(groupBase,rebinAxisName,/row,/exclusive, $
	label_left = 'rebin axis',/no_release, $
	frame = 1,set_value = 0,/return_index, $
	uname = 'REBIN_AXIS')

rowBase2 = widget_base(tlb,/row,/align_center)
void = widget_label(rowBase2,value = 'current settings')

fsize = 10
void = cw_field(rowBase2,title = 'minimum',/row,value = '0.0',/string, $
		uname = 'CUR_MIN',/noedit,xsize = fsize)
void = cw_field(rowBase2,title = 'maximum',/row,value = '0.0',/string, $
		uname = 'CUR_MAX',/noedit,xsize = fsize)
void = cw_field(rowBase2,title = 'min width',/row,value = '0.0',/string, $
		uname = 'CUR_WIDTH',/noedit,xsize = fsize)
void = cw_field(rowBase2,title = 'max width',/row,value = '0.0',/string, $
		uname = 'CUR_WIDTH_MAX',/noedit,xsize = fsize)

editBase = widget_base(tlb,/col,/align_center,/frame)
void = widget_label(editBase,value= $
                    'Note: after editing a text field, you must use carriage return to keep modified value!')
rowBase3 = widget_base(editBase,/row,/align_center)
void = widget_label(rowBase3,value = 'new settings')

fsize = 20
void = cw_field(rowBase3,title = 'minimum',/row,value = '1',/float, $
		uname = 'NEW_MIN',/return_events,xsize = fsize)
void = cw_field(rowBase3,title = 'maximum',/row,value = '1',/float, $
		uname = 'NEW_MAX',/return_events,xsize = fsize)
void = cw_field(rowBase3,title = 'width',/row,value = '1',/float, $
		uname = 'NEW_WIDTH',/return_events,xsize = fsize)

rowBase4 = widget_base(editBase,/col,/align_center)
if (n_objects gt 1) then begin
    void = widget_button(rowBase4,value='Apply these settings to all datasets',uname='APPLY_TO_ALL')
endif
trunc_base = widget_base(rowBase4,/row,/nonexclusive)
truncate = widget_button(trunc_base,value = 'Truncate data over specified bin range', $
	uname = 'TRUNCATE')
rowBase5 = widget_base(tlb,/row,/align_center)
acptTip = 'Save changes and exit'
cancTip = 'Discard changes and exit'
void = widget_button(rowBase5,value='Accept',uname='ACCEPT',tooltip=acptTip)
void = widget_button(rowBase5,value='Cancel',uname='CANCEL',tooltip=cancTip)

widget_control,tlb,/realize
widget_control,truncate,set_button = 1
truncate = 1

state = {	cancel:0, 							$
			filenames:nameTags,				$
			fileOut:nameTags[0], 				$
			truncate:truncate,					$
			rebinAxis:'x',						$
			bin_min:0.0,						$
			bin_max:0.0,						$
			bin_width:0.0,						$
			pbin_min:ptr_new(/allocate_heap),	$
			pbin_max:ptr_new(/allocate_heap),	$
			pbin_width:ptr_new(/allocate_heap),	$
			pbin_axis:ptr_new(/allocate_heap),	$
			fileIndex:0,						$
			oContainer:oContainer 				$
		}

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

ev = {event,id:void,top:tlb,handler:0L}
db_xr_init,ev
db_xr_updateValues,ev

registerName = 'db_xr'
xmanager,registerName,tlb,no_block=modal,event_handler = 'db_xr_events'

no_truncate = ((*pState).truncate eq 1) ? 0 : 1
;print,no_truncate
db_xr_structure = 	{	cancel:(*pState).cancel,			$
						bin_min:*(*pState).pbin_min,		$
						bin_max:*(*pState).pbin_max,		$
						bin_width:*(*pState).pbin_width,	$
						no_truncate:no_truncate,			$
						bin_axis:*(*pState).pbin_axis		$
					}

ptr_free,(*pState).pbin_min,(*pState).pbin_width,(*pState).pbin_max
ptr_free,(*pState).pbin_axis
ptr_free,pState
return,db_xr_structure
end
