; $Id: dcs_multiplot.pro,v 1.38 2007/11/30 21:53:24 jrdcopley Exp $
@dcs_multiplot_read
@dcs_multiplot_plot
@dcs_multiplot_clear


; Written by J.R.D. Copley
;************************************************************************************************
pro dcs_multiplot_Quit,event
;************************************************************************************************
; Trivial quit routine.
;
compile_opt strictarr
;
widget_control,event.top,/destroy
return
end


;************************************************************************************************
pro dcs_multiplot_Cleanup,tlb
;************************************************************************************************
; Cleanup routine.
;
compile_opt strictarr
;
widget_control,tlb,get_uvalue = pState,/no_copy
;
; revert to existing colors prior to exiting dcs_multiplot.
tvlct, (*pState).default_colors

; Send one or more events to "calling" widgets.
;s = size((*pState).notifyIDs)
;if s[0] eq 1 then count = 0 else count = s[2]-1
;for j = 0,count do begin
;  mdcInfo = {mdcEvent,$
;    ID:(*pState).notifyIDs[0,j],$
;    Top:(*pState).notifyIDs[1,j],$
;    Handler:0l,$
;    inPtr:ptr_new(*(*pState).inPtr)}
;  if widget_info((*pState).notifyIDs[0,j],/valid_id) then begin $
;    widget_control,(*pState).notifyIDs[0,j],send_event = mdcInfo
;  endif
;endfor
;
DEVICE,DECOMPOSED=(*PSTATE).OLD_DECOMP
;
; Free some pointers.
if (ptr_valid(pState)) then begin
    obj_destroy,(*pState).plotWin
	tags=tag_names(*pState)
    if (ptr_valid((*pState).pqty)) then ptr_free,(*pState).pqty
    if (ptr_valid((*pState).perr)) then ptr_free,(*pState).perr
    if (ptr_valid((*pState).px)) then ptr_free,(*pState).px
    if (ptr_valid((*pState).py)) then ptr_free,(*pState).py
    if (ptr_valid((*pState).tchansPtr)) then ptr_free,(*pState).tchansPtr
    if (ptr_valid((*pState).timesPtr)) then ptr_free,(*pState).timesPtr
    if (ptr_valid((*pState).energiesPtr)) then ptr_free,(*pState).energiesPtr
    if (ptr_valid((*pState).activePtr)) then ptr_free,(*pState).activePtr
    if (ptr_valid((*pState).hilitePtr)) then ptr_free,(*pState).hilitePtr
    if (ptr_valid((*pState).multiplierPtr)) then ptr_free,(*pState).multiplierPtr
    if (ptr_valid((*pState).constantsPtr)) then ptr_free,(*pState).constantsPtr
    if (ptr_valid((*pState).filesPtr)) then ptr_free,(*pState).filesPtr
    if (ptr_valid((*pState).durationsPtr)) then ptr_free,(*pState).durationsPtr
    if (ptr_valid((*pState).srdenomsPtr)) then ptr_free,(*pState).srdenomsPtr
    if (ptr_valid((*pState).temperaturesPtr)) then ptr_free,(*pState).temperaturesPtr
    if (ptr_valid((*pState).commentsPtr)) then ptr_free,(*pState).commentsPtr
    if (ptr_valid((*pState).ksPtr)) then ptr_free,(*pState).ksPtr
    if (ptr_valid((*pState).kePtr)) then ptr_free,(*pState).kePtr
    if (ptr_valid((*pState).abctthetaPtr)) then ptr_free,(*pState).abctthetaPtr
    index=where(tags eq strupcase('informationPtr'))
		if (index ge 0) then begin
    	if (ptr_valid((*pState).informationPtr)) then ptr_free,(*pState).informationPtr
    endif
;
    if (ptr_valid((*pState).pmask)) then ptr_free,(*pState).pmask
    if ((*pState).nodavePtr) then begin
       ptr_free,(*(*(*pState).davePtr).dataStrPtr).commonStr.histPtr
       ptr_free,(*(*(*pState).davePtr).dataStrPtr).commonStr.treatmentPtr
       ptr_free,(*(*(*pState).davePtr).dataStrPtr).specificPtr
       ptr_free,(*(*pState).davePtr).dataStrPtr
       ptr_free,(*pState).davePtr
    endif
    wdelete,(*pState).winstate.winPix
    ptr_free,pState
endif
;
return
end


;************************************************************************************************
pro dcs_multiplot_sensitivity,event,enable=enable
;************************************************************************************************
; This routine is used to save and then desensitize parts of the widget, or to restore their
;	sensitivities.
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=pState
;
res=where (tag_names(*pstate) eq "SENSITIVITY",count)
if (enable) then begin
	if (count eq 1) then begin
		widget_control,(*pState).filemenu,sensitive=(*pState).sensitivity.filemenu
		widget_control,(*pState).abscmenu,sensitive=(*pState).sensitivity.abscmenu
		widget_control,(*pState).grupmenu,sensitive=(*pState).sensitivity.grupmenu
		widget_control,(*pState).gnopmenu,sensitive=(*pState).sensitivity.gnopmenu
		widget_control,(*pState).rawxmenu,sensitive=(*pState).sensitivity.rawxmenu
		widget_control,(*pState).rawymenu,sensitive=(*pState).sensitivity.rawymenu
		widget_control,(*pState).dsetmenu,sensitive=(*pState).sensitivity.dsetmenu
		widget_control,(*pState).showmenu,sensitive=(*pState).sensitivity.showmenu
		widget_control,(*pState).prefmenu,sensitive=(*pState).sensitivity.prefmenu
		widget_control,(*pState).mainbase,sensitive=(*pState).sensitivity.mainbase
	endif else begin
		widget_control,(*pState).filemenu,sensitive=enable
		widget_control,(*pState).abscmenu,sensitive=enable
		widget_control,(*pState).grupmenu,sensitive=enable
		widget_control,(*pState).gnopmenu,sensitive=enable
		widget_control,(*pState).rawxmenu,sensitive=enable
		widget_control,(*pState).rawymenu,sensitive=enable
		widget_control,(*pState).dsetmenu,sensitive=enable
		widget_control,(*pState).showmenu,sensitive=enable
		widget_control,(*pState).prefmenu,sensitive=enable
		widget_control,(*pState).mainbase,sensitive=enable
	endelse
endif else begin
	if (count eq 1) then begin
		(*pState).sensitivity.filemenu=widget_info((*pState).filemenu,/sensitive)
		(*pState).sensitivity.abscmenu=widget_info((*pState).abscmenu,/sensitive)
		(*pState).sensitivity.grupmenu=widget_info((*pState).grupmenu,/sensitive)
		(*pState).sensitivity.gnopmenu=widget_info((*pState).gnopmenu,/sensitive)
		(*pState).sensitivity.rawxmenu=widget_info((*pState).rawxmenu,/sensitive)
		(*pState).sensitivity.rawymenu=widget_info((*pState).rawymenu,/sensitive)
		(*pState).sensitivity.dsetmenu=widget_info((*pState).dsetmenu,/sensitive)
		(*pState).sensitivity.showmenu=widget_info((*pState).showmenu,/sensitive)
		(*pState).sensitivity.prefmenu=widget_info((*pState).prefmenu,/sensitive)
		(*pState).sensitivity.mainbase=widget_info((*pState).mainbase,/sensitive)
	endif
	widget_control,(*pState).filemenu,sensitive=0
	widget_control,(*pState).abscmenu,sensitive=0
	widget_control,(*pState).grupmenu,sensitive=0
	widget_control,(*pState).gnopmenu,sensitive=0
	widget_control,(*pState).rawxmenu,sensitive=0
	widget_control,(*pState).rawymenu,sensitive=0
	widget_control,(*pState).dsetmenu,sensitive=0
	widget_control,(*pState).showmenu,sensitive=0
	widget_control,(*pState).prefmenu,sensitive=0
	widget_control,(*pState).mainbase,sensitive=0
endelse
;
widget_control,event.top,set_uvalue=pState
;
end


;************************************************************************************************
pro dcs_multiplot_Savedata,event
;************************************************************************************************
; This routine is used to save the data to a file. This is done by calling the
; plotting routine having first set the variable (*pState).savedata.
compile_opt strictarr
;
widget_control,event.top,get_uvalue = pState
;
; Set the "savedata" variable.
(*pState).savedata=1
;
; Update the plot.
;wset,(*pState).winstate.winPix
widget_control,event.top,set_uvalue = pState
dcs_multiplot_Plot,event
widget_control,event.top,get_uvalue = pState
;wset,(*pState).winstate.winVis
;device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winstate.winPix]
if (*pState).objectgraphics eq 0 then $
   wshow,(*pState).winstate.winVis
;
; Clear the "savedata" variable.
(*pState).savedata=0
widget_control,event.top,set_uvalue = pState
return
end


;************************************************************************************************
pro dcs_multiplot_Draw,event
;************************************************************************************************
; This relatively standard routine is used to handle zoom operations and to
;   detect and display the cursor coordinates.
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue = pState
;
if ((*pstate).ndatasets eq 0) then return
;
!x=(*pState).bangx
!y=(*pState).bangy
!p=(*pState).bangp
;
wset,(*pState).winState.winVis
;
minmousemove=3
;
; If plotting vs. x (y), index = 0 (1).
index=1-(*pState).plot_vs_x
;
; If cursor is exiting the region covered by the draw widget, replot with no cursor.
eventname=tag_names(event,/structure_name)
if (eventname eq 'WIDGET_TRACKING') then begin
    if (event.enter eq 0) then begin
    wset,(*pState).winState.winVis
    device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]
    endif
    return
endif
;
 case event.type of
; Respond to a button press.
0:  begin
      (*pState).winState.mouse = event.press
;
; If the right button was pressed, set the autoscale flag and exit.
       if (*pState).winState.mouse eq 4 then begin
        (*pState).winState.autoscale[index] = 1
         widget_control,event.top,set_uvalue = pState
        return
      endif
;
; If the left button was pressed, record the cursor's coordinates.
      if (*pState).winState.mouse eq 1 then begin
        (*pState).winState.xbox[0] = event.x
        (*pState).winState.ybox[0] = event.y
        wset,(*pState).winState.winVis
        device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]
        empty
        (*pState).winState.autoscale[index] = 0
      endif
    end
;
; Respond to a button release.
1:  begin
;
;	Ignore the event if the mouse was not moved or moved very little.
	if (abs((*pState).winState.xbox[0]-event.x) lt minmousemove and $
		abs((*pState).winState.ybox[0]-event.y) lt minmousemove) then begin
		(*pState).winState.mouse = 0B
		if (event.modifiers eq 1) then begin
			tlbs=find_tlb(name=(*pState).register_name)
			tlbs=tlbs[sort(tlbs)]
			ntlbs=n_elements(tlbs)
			ind=where(tlbs eq event.top)+1
			ind=ind mod ntlbs
			widget_control,tlbs[ind],/show,iconify=0
		endif
		return
	endif
;
; Determine lower left and upper right coordinates of zoom window.
      xll = (*pState).winState.xbox[0] < (*pState).winState.xbox[1]
      yll = (*pState).winState.ybox[0] < (*pState).winState.ybox[1]
      w = abs((*pState).winState.xbox[1] - (*pState).winState.xbox[0])
      h = abs((*pState).winState.ybox[1] - (*pState).winState.ybox[0])
      xur = xll + w
      yur = yll + h
      ll = convert_coord(xll,yll,/device,/to_data,/double)
      ur = convert_coord(xur,yur,/device,/to_data,/double)
;
; Define new ranges for abscissa and ordinate, and replot.
      (*pState).winState.xrange[*,index] = [ll[0],ur[0]]
      (*pState).winState.yrange[*,index] = [ll[1],ur[1]]
;
; Write the abscissa and ordinate extrema in appropriate places in the widget.
       widget_control,(*pState).butt_xmin,set_value=strcompress((*pState).winState.xrange[0,index])
       widget_control,(*pState).butt_xmax,set_value=strcompress((*pState).winState.xrange[1,index])
       widget_control,(*pState).butt_ymin,set_value=strcompress((*pState).winState.yrange[0,index])
       widget_control,(*pState).butt_ymax,set_value=strcompress((*pState).winState.yrange[1,index])
;
;      wset,(*pState).winState.winPix
      widget_control,event.top,set_uvalue = pState
      dcs_multiplot_Plot,event
      widget_control,event.top,get_uvalue = pState
;      wset,(*pState).winState.winVis
;      device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]
      (*pState).winState.mouse = 0B
    end
;
; Respond to mouse motion.
2:  begin
    result=convert_coord(event.x,event.y,/device,/to_data)
;
; Test whether the cursor is inside the plot. If so display its coordinates
; in data units. If desired show cursor cross hair.
       if (result[0] gt !x.crange[0] and result[0] lt !x.crange[1] and $
          result[1] gt !y.crange[0] and result[1] lt !y.crange[1] and $
          (*pState).ndatasets gt 0) then begin
         widget_control,(*pState).textcoord,set_value=["COORDINATES",string(result[0:1])]
         if ((*pState).cross_hair eq 1) then begin
            wset,(*pState).winState.winVis
             device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]
           plots,[result[0],result[0]],[!y.crange[0],!y.crange[1]],color=1,/data
             plots,[!x.crange[0],!x.crange[1]],[result[1],result[1]],color=1,/data
         endif
       endif else begin
         widget_control,(*pState).textcoord,set_value=""
         if ((*pState).cross_hair eq 1) then begin
            wset,(*pState).winState.winVis
             device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]
         endif
       endelse
;
; As long as the left button is depressed, determine the coordinates of
; the instantaneous zoom rectangle and plot it.
      if (*pState).winState.mouse eq 1 then begin
       (*pState).winState.xbox[1] = event.x
       (*pState).winState.ybox[1] = event.y
       xc = [(*pState).winState.xbox[0],event.x,event.x,(*pState).winState.xbox[0],$
             (*pState).winState.xbox[0]]
       yc = [(*pState).winState.ybox[0],(*pState).winState.ybox[0],event.y,event.y,$
             (*pState).winState.ybox[0]]
          wset,(*pState).winState.winVis
       device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winState.winPix]

       ; Setting colors
       device, get_decomposed=old_decomp
       (*pState).old_decomp=old_decomp
       default_colors=bindgen(256,3)
       tvlct,default_colors,/get
       (*pState).default_colors=default_colors
       device, decomposed=0
 ;      colorset
       tvlct,!dave_colors.red,!dave_colors.green,!dave_colors.blue
       plots,xc,yc,/device,color=1
       ; Recovering colors
       device, decomposed=old_decomp
       tvlct,default_colors

       empty
      endif
    end
else:
endcase
;
widget_control,event.top,set_uvalue = pState
;
return
end


;************************************************************************************************
pro dcs_multiplot_setops_handler,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=setupState
;
if (event.id eq setupState.all) then begin
    *(setupState.ptr)=indgen(setupState.n)
    widget_control,event.top,/destroy
    return
endif
if (event.id eq setupState.done) then begin
    *(setupState.ptr)=widget_info(setupState.list,/list_select)
    widget_control,event.top,/destroy
    return
endif
;
if (event.id eq setupState.quit) then begin
    *(setupState.ptr)=-2
    widget_control,event.top,/destroy
    return
endif
;
widget_control,event.top,set_uvalue=setupState
;
end


;************************************************************************************************
pro dcs_multiplot_setops,event
;************************************************************************************************
;
compile_opt strictarr
;
widget_control,event.top,get_uvalue=pState
;
n=n_elements(*(*pState).filesPtr)
;
; Obtain indices of active datasets. There must be at least one.
case event.id of
    (*pState).dsetbutton_activ: begin
       repeat begin
         tlb=widget_base(title="Select active sets (minimum 1)",$
          group_leader=event.top,/modal,/col)
         information=strcompress(string(indgen(n)+1))+"  "+*(*pState).filesPtr
          list=widget_list(tlb,value=information,/multiple,ysize=8)
          base=widget_base(tlb,/row)
              done=widget_button(base,value='Done')
              quit=widget_button(base,value='Cancel')
              all=widget_button(base,value='ALL')
         ptr=ptr_new(/allocate_heap)
         widget_control,list,set_list_select=where(*(*pState).activePtr)
         widget_control,tlb,/realize
         setupState={list:list,all:all,done:done,quit:quit,n:n,ptr:ptr}
         widget_control,tlb,set_uvalue=setupState
         xmanager,'dcs_multiplot_setops',tlb,$
          event_handler='dcs_multiplot_setops_handler'
         chosen=*(setupState.ptr)
         ptr_free,ptr
         if (chosen[0] eq -1) then $
          res=dialog_message("At least one dataset must be active.",/error)
       endrep until (chosen[0] ne -1)
       if (chosen[0] ge 0) then begin
         *(*pState).activePtr=intarr((*pState).ndatasets)
         (*(*pState).activePtr)[chosen]=1
         (*(*pState).hilitePtr)[*]=1
       endif
    end
;
; Obtain multipliers and constants for each dataset.
    (*pState).dsetbutton_renorm: begin
       title="Enter a multiplier and a constant for each dataset"
       ndatasets=(*pState).ndatasets
       text=[strarr(ndatasets)+"Dataset"+strcompress(indgen(ndatasets)+1)+" multiplier:",$
         strarr(ndatasets)+"Dataset"+strcompress(indgen(ndatasets)+1)+" constant:"]
       value=[*(*pState).multiplierPtr,*(*pState).constantsPtr]
       help=["The ordinate and its error are multiplied by the multiplier.",$
         "The constant is then SUBTRACTED (from the ordinate only)."]
       dave_get_values,title,text,value,group_leader=event.top,checkall=1,help=help
       *(*pState).multiplierPtr=float(value[0:ndatasets-1])
       *(*pState).constantsPtr=float(value[ndatasets:2*ndatasets-1])
    end
;
;
; Obtain modified temperatures for each dataset.
    (*pState).dsetbutton_temper: begin
       title="Enter a temperature for each dataset"
       ndatasets=(*pState).ndatasets
       text=strarr(ndatasets)+"Dataset"+strcompress(indgen(ndatasets)+1)+" temperature:"
       value=*(*pState).temperaturesPtr
       help="Temperatures are in degrees K."
       dave_get_values,title,text,value,group_leader=event.top,checkall=1,help=help
       *(*pState).temperaturesPtr=float(value[0:ndatasets-1])
    end
;
; Obtain modified value of tsdmin. Save the change in tsdmin in pState.
    (*pState).dsetbutton_rotate: begin
       title="Original tsdmin ="+$
         strcompress(string((*pState).tsdmin,format='(f8.1)'))+" us."
       tcwid=(*(*pState).tchansPtr)[0]
       helpmsg=[$
         "The original value of tsdmin is"+$
          strcompress(string((*pState).tsdmin,format='(f8.1)'))+" us.",$
         "",$
         "The current value of tsdmin is"+$
          strcompress(string((*pState).tsdmin+(*pState).delta_tsdmin,format='(f8.1)'))+" us.",$
         "",$
         "You are asked to enter the new value of tsdmin.",$
         "",$
         "It is assumed that exactly 1000 time channels are active.",$
         "",$
         "The change in tsdmin will be rounded to the nearest integer multiple ",$
         "of the (fixed) time channel width, which is"+$
          strcompress(string(tcwid,format='(f5.1)'))+" us."$
         ]
       value=strcompress(string((*pState).tsdmin+(*pState).delta_tsdmin,format='(f8.1)'))
       text="New tsdmin:" ; this line must be in the loop otherwise text gets longer each time around!
       dave_get_values,title,text,value,group_leader=event.top,checkall=1,help=helpmsg
       delta_tsdmin=fix(value[0])-(*pState).tsdmin
       (*pState).delta_tsdmin=tcwid*float(round(delta_tsdmin/tcwid))
    end
;
; Obtain indices of highlighted datasets. There must be at least one.
    (*pState).dsetbutton_hilite: begin
       repeat begin
         tlb=widget_base(title="Select sets to be highlighted",$
          group_leader=event.top,/modal,/col)
         indices=where(*(*pState).activePtr,count)
         information=strcompress(string(indices+1))+"  "+(*(*pState).filesPtr)[indices]
          list=widget_list(tlb,value=information,/multiple,ysize=8)
          base=widget_base(tlb,/row)
              done=widget_button(base,value='Done')
              quit=widget_button(base,value='Cancel')
              all=widget_button(base,value='ALL')
         ptr=ptr_new(/allocate_heap)
         widget_control,list,set_list_select=where((*(*pState).hilitePtr)[indices])
         widget_control,tlb,/realize
         setupState={list:list,all:all,done:done,quit:quit,n:n,ptr:ptr}
         widget_control,tlb,set_uvalue=setupState
         xmanager,'dcs_multiplot_setops',tlb,$
          event_handler='dcs_multiplot_setops_handler'
         chosen=*(setupState.ptr)
         ptr_free,ptr
         if (chosen[0] eq -1) then $
          res=dialog_message("At least one dataset must be highlighted.",/error)
       endrep until (chosen[0] ne -1)
       if (chosen[0] ge 0) then begin
         *(*pState).hilitePtr=intarr((*pState).ndatasets)
         (*(*pState).hilitePtr)[indices[chosen]]=1
       endif
    end
    else:
endcase
;
; Update the plot.
;wset,(*pState).winstate.winPix
widget_control,event.top,set_uvalue=pState
dcs_multiplot_Plot,event
widget_control,event.top,get_uvalue=pState
;wset,(*pState).winstate.winVis
;device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winstate.winPix]
if (*pState).objectgraphics eq 0 then $
   wshow,(*pState).winstate.winVis
widget_control,event.top,set_uvalue=pState
;
end


;************************************************************************************************
pro dcs_multiplot_handler,event
;************************************************************************************************
; Handle miscellaneous button presses etc.
;
compile_opt strictarr
;
if tag_names(event,/structure_name) eq 'DM_PLOT_MOTION' then event.id = -1  ;send it to case else:
widget_control,event.top,get_uvalue=pState
;
if obj_valid((*pState).plotWin) then $
   (*pState).plotWin->getproperty,xrange=xrange,yrange=yrange
; If plotting vs. x (y), index = 0 (1).
index=1-(*pState).plot_vs_x
;
case event.id of
;
; Handle switching direct & object graphics
    (*pState).prefbutton_dirobj:begin
        (*pState).objectgraphics=1-(*pState).objectgraphics
        widget_control,event.id,set_value=(['Switch to object graphics','Switch to direct graphics'])[(*pState).objectgraphics]
        widget_control,(*pState).filebutton_printer,sensitive=(*pState).objectgraphics
        widget_control,(*pState).gnopbutton_crosshair,sensitive=1-(*pState).objectgraphics
        tlbgeom=widget_info(event.top,/geometry)
        winxsize=tlbgeom.xsize-(*pState).restofwidth
        winysize=tlbgeom.ysize-(*pState).restofheight
        if (*pState).objectgraphics then begin  ;switch from direct to object graphics
           wdelete,(*pState).winState.winPix
           widget_control,(*pState).winState.drawwindow,/destroy
           (*pState).plotWin=obj_new('dm_plot',/compound,widgetbase=(*pState).drawbase,group_leader=event.top,$
                xsize=winxsize,ysize=winysize,/draw_motion_events)
        endif else begin                        ;switch from object to direct graphics
           obj_destroy,(*pState).plotWin
           (*pState).winState.drawwindow=widget_draw((*pState).drawbase,xsize=winxsize,ysize=winysize,$
                /button_events,/motion_events,/tracking_events,keyboard_events=2,$
                event_pro="dcs_multiplot_draw")
           ; Create a pixmap window for later use, the same size as the screen window.
           window,/free,/pixmap,xsize=winxsize,ysize=winysize
           ; Get IDs of pixmap and drawwindow.
           (*pState).winState.winPix=!d.window
           widget_control,(*pState).winState.drawwindow,get_value=winVis
           (*pState).winState.winVis=winVis
        endelse
        (*pState).winstate.autoscale=[1,1]
        (*pState).symsize=([0.8,0.006])[(*pState).objectgraphics]
    end
;
; Handle the do bitflips menu item.
    (*pState).prefbutton_dobitflips: begin
       (*pState).dobitflips=-(*pState).dobitflips
       if ((*pState).dobitflips eq 1) then $
         widget_control,(*pState).prefbutton_dobitflips,set_value="Do not correct for bitflips"
       if ((*pState).dobitflips eq -1) then $
         widget_control,(*pState).prefbutton_dobitflips,set_value="Correct for bitflips"
    end
;
; Handle print to printer event
    (*pState).filebutton_printer:   (*pState).plotWin->saveas,'printer'
;
; Handle print to postscript file event
    (*pState).filebutton_ps: begin
        if (*pState).objectgraphics then $
           (*pState).plotWin->saveas,'ps' $
        else begin
           thisDevice = !d.name
           ;deviceKeywords = ps_form(Cancel = canceled,parent = event.top)
           device_keywords = PSConfig(Cancel=canceled,group_leader = event.top,$
                DefaultSetup="Centered (Landscape)")
           if canceled ne 1 then begin
              SET_PLOT, 'PS'
              DEVICE, _Extra = device_keywords
              dcs_multiplot_Plot,event
              DEVICE, /CLOSE_FILE
              SET_PLOT,thisDevice
           endif
        endelse
    end
;
; Handle the individual detector bank masking menu item.
	(*pState).prefbutton_masking: begin
		(*pState).dmask=1-widget_info((*pState).prefbutton_masking,/button_set)
		if ((*pState).dmask) then begin
			widget_control,(*pState).prefbutton_masking,set_button=1
		endif else begin
			widget_control,(*pState).prefbutton_masking,set_button=0
		endelse
	end
;
; Handle the alternative detector numbering menu item.
	(*pState).prefbutton_detnumb: begin
		(*pState).dnumb=1-widget_info((*pState).prefbutton_detnumb,/button_set)
		if ((*pState).dnumb) then begin
			widget_control,(*pState).prefbutton_detnumb,set_button=1
		endif else begin
			widget_control,(*pState).prefbutton_detnumb,set_button=0
		endelse
	end
;
; Handle the error bars menu item.
    (*pState).gnopbutton_errorbar: begin
       (*pState).plot_eb=1-(*pState).plot_eb
       if ((*pState).plot_eb) then $
         widget_control,(*pState).gnopbutton_errorbar,set_value="Hide error bars" $
       else widget_control,(*pState).gnopbutton_errorbar,set_value="Show error bars"
    end
;
; Handle the join points menu item.
    (*pState).gnopbutton_joinpts: begin
       (*pState).join_pts=-(*pState).join_pts
       if ((*pState).join_pts eq 1) then $
         widget_control,(*pState).gnopbutton_joinpts,set_value="Do not join points"
       if ((*pState).join_pts eq -1) then $
         widget_control,(*pState).gnopbutton_joinpts,set_value="Join points"
    end
;
; Handle the show grid menu item.
    (*pState).gnopbutton_showgrid: begin
       (*pState).show_grid=-(*pState).show_grid
       if ((*pState).show_grid eq 1) then $
         widget_control,(*pState).gnopbutton_showgrid,set_value="Do not show grid"
       if ((*pState).show_grid eq -1) then $
         widget_control,(*pState).gnopbutton_showgrid,set_value="Show grid"
    end
;
; Handle the ymin=0 menu item.
    (*pState).gnopbutton_yminzero: begin
       (*pState).winstate.autoscale[index]=0
       (*pState).winstate.yrange[0,index]=0.0
       widget_control,(*pState).butt_ymin,set_value=' 0.0'
       if (*pState).objectgraphics then begin
          if finite(yrange[1]) then begin
             (*pState).winstate.yrange[1,index]=yrange[1]
             widget_control,(*pState).butt_ymax,set_value=strcompress(yrange[1])
          endif
          (*pState).plotWin->setproperty,yrange=(*pState).winstate.yrange[*,index],/nodraw
       endif
    end
;
; Handle the cross hair menu item.
    (*pState).gnopbutton_crosshair: begin
       (*pState).cross_hair=-(*pState).cross_hair
       if ((*pState).cross_hair eq 1) then $
         widget_control,(*pState).gnopbutton_crosshair,set_value="Hide cursor cross hair"
       if ((*pState).cross_hair eq -1) then $
         widget_control,(*pState).gnopbutton_crosshair,set_value="Show cursor cross hair"
    end
;
; Handle the normalize to duration menu item.
    (*pState).gnopbutton_normalize: begin
       (*pState).norm_d=1-(*pState).norm_d
       if ((*pState).norm_d) then $
         widget_control,(*pState).gnopbutton_normalize,set_value="Do not normalize to duration" $
       else widget_control,(*pState).gnopbutton_normalize,set_value="Normalize to duration"
    end
;
; Handle the plot settings menu item.
    (*pState).gnopbutton_plotsettings: begin
       title='Choose plot settings'
       text=['Line thickness','Symbol size','Initial symbol (c/C or o/O)','Fade factor']
       value=[string((*pState).thick),string((*pState).symsize),(*pState).initsym,string((*pState).fadefactor)]
       value=strcompress(value)
      dave_get_values,title,text,value,group_leader=event.top
      (*pState).thick=float(value[0])
       (*pState).symsize=float(value[1])
       value[2]=strupcase(value[2])
       if (value[2] ne "C" and value[2] ne "O") then value[2]="C"
       (*pState).initsym=value[2]
       (*pState).fadefactor=fix(value[3])
    end
;
; Handle the plot settings menu item.
    (*pState).gnopbutton_plotsetdefs: begin
       (*pState).thick=(*pState).defthick
       (*pState).symsize=(*pState).defsymsize
       (*pState).initsym=(*pState).definitsym
       (*pState).fadefactor=(*pState).deffadefactor
    end
;
; Handle the show durations menu item.
    (*pState).showbutton_duration: begin
       md=strjoin(['Durations:   ',string(long(*(*pState).durationsPtr),format='(i8)')])
       ms=strjoin(['SR denoms:   ',string(*(*pState).srdenomsPtr,format='(i8)')])
       mt=strjoin(['Temperatures:',string(*(*pState).temperaturesPtr,format='(f8.2)')])
       message=[md,ms,mt]
       if (1-(*pState).norm_d) then begin
         message=[message,"N.B.  Data are not normalized"]
       endif
       res=dialog_message(message,/information)
    end
;
;   Handle the Plot dsdt vs T_SD menu item.
    (*pState).rawxbutton_plotvst: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=1
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end
;
;   Handle the Plot dsdt vs E transfer menu item.
    (*pState).rawxbutton_plotvsE: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=1
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end
;
;   Handle the Plot t^4*dsdt vs E transfer menu item.
    (*pState).rawxbutton_plott4E: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=1
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end
;
;   Handle the Plot t^4*dsdt vs E transfer (DB) menu item.
    (*pState).rawxbutton_plott4EDB: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=1
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end
;
;   Handle the Plot E_transfer^2*t^4*dsdt vs E transfer menu item.
    (*pState).rawxbutton_plotdos: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=1
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end

;   Handle the Plot E_transfer^2*t^4*dsdt vs E transfer (DB) menu item.
    (*pState).rawxbutton_plotdosDB: begin
       abscbutton_x=(*pState).abscbutton_x
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=1
       (*pState).winstate.autoscale[0]=1
    end

;   Handle the "x revert" menu item.
    (*pState).rawxbutton_revert: begin
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[0]=1
    end
;
;   Handle the plot vs 2theta menu item.
    (*pState).rawybutton_plotv2th: begin
       abscbutton_y=(*pState).abscbutton_y
       (*pState).plotv2th=1
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[1]=1
    end
;
;   Handle the plot vs abs(2theta) menu item.
    (*pState).rawybutton_plotva2th: begin
       abscbutton_y=(*pState).abscbutton_y
       (*pState).plotv2th=0
       (*pState).plota2th=1
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[1]=1
    end
;
;   Handle the "y revert" menu item.
    (*pState).rawybutton_revert: begin
       (*pState).plotv2th=0
       (*pState).plota2th=0
       (*pState).plotvst=0
       (*pState).plotvsE=0
       (*pState).plott4E=0
       (*pState).plott4EDB=0
       (*pState).plotdos=0
       (*pState).plotdosDB=0
       (*pState).winstate.autoscale[1]=1
    end
;
;   Handle the "y BPs" menu item.
    (*pState).rawybutton_BPs: begin
    	(*pState).plothkls=1-(*pState).plothkls
      if ((*pState).plothkls eq 1) then $
        widget_control,(*pState).rawybutton_BPs,set_value="Do not show Bragg peaks"
      if ((*pState).plothkls eq 0) then $
        widget_control,(*pState).rawybutton_BPs,set_value="Show Bragg peaks"
    end

;   Handle the "y abc" menu item.
    (*pState).rawybutton_abc: begin
   		pst=ptr_new(/allocate_heap)
			getlattice_params,pst,(*pState).abc,(*pState).lambda0,group_leader=event.top
			for k=0,5 do (*pState).abc.(k)=(*pst).quans[k]
			(*pState).lambda0=(*pst).quans[6]
			ptr_free,pst
    	genpeak_positions,(*pState).abc,(*pState).lambda0,abcttheta,/unique
;    	print,"Number of visible unique 2theta values is",n_elements(abcttheta)/4
    	(*(*pState).abctthetaPtr)=abcttheta
    end
;
; Handle the group center slider button.
    (*pState).butt_groupcenter: begin
       if ((*pState).plot_vs_x) then begin
         (*pState).yvalue=event.value
       endif else begin
         (*pState).xvalue=event.value
       endelse
    end
;
; Handle the group half-width slider button.
    (*pState).butt_grouphwidth: begin
       width=event.value
       if ((*pState).plot_vs_x) then (*pState).ywidth=width
       if ((*pState).plot_vs_y) then (*pState).xwidth=width
    end
;
; Handle the abscissa rebinning slider button.
    (*pState).butt_abscrebin: begin
       if ((*pState).plot_vs_x) then begin
         (*pState).xrebin=event.value
       endif else begin
         (*pState).yrebin=event.value
       endelse
    end
;
; Handle the menu item that makes x the abscissa.
    (*pState).abscbutton_x: begin
       widget_control,(*pState).abscbutton_x,get_value=tmp
       if (strmid(tmp,0,1) ne '[') then begin
         widget_control,(*pState).abscbutton_x,set_value='['+tmp+']'
       endif
       widget_control,(*pState).abscbutton_y,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).abscbutton_y,set_value=tmp
       endif
;;;     if (1-(*pState).plot_vs_x) then (*pState).winstate.autoscale=1
       (*pState).plot_vs_x=1
       (*pState).plot_vs_y=0
       widget_control,(*pState).rawxmenu,sensitive=(*pState).readingDCS
       widget_control,(*pState).rawymenu,sensitive=0
       widget_control,(*pState).butt_groupcenter,set_value=(*pState).yvalue
       widget_control,(*pState).butt_grouphwidth,set_value=(*pState).ywidth
       widget_control,(*pState).butt_abscrebin,set_value=(*pState).xrebin
       widget_control,(*pState).butt_groupcenter,set_slider_max=(*pState).ydim
       widget_control,(*pState).butt_grouphwidth,set_slider_max=(*pState).ydim
       widget_control,(*pState).butt_abscrebin,set_slider_max=(*pState).xdim/10 > 6
       widget_control,(*pState).butt_numgroups,set_slider_max=(*pState).ydim; (used to be 31)
       widget_control,(*pState).butt_numgroups,set_value=(*pState).yngroups
       widget_control,(*pState).butt_groupnumber,set_slider_max=(*pState).yngroups
       widget_control,(*pState).butt_groupnumber,set_value=(*pState).ygroupnum
       widget_control,(*pState).butt_xmin,set_value=strcompress((*pState).winState.xrange[0,0])
       widget_control,(*pState).butt_xmax,set_value=strcompress((*pState).winstate.xrange[1,0])
       widget_control,(*pState).butt_ymin,set_value=strcompress((*pState).winstate.yrange[0,0])
       widget_control,(*pState).butt_ymax,set_value=strcompress((*pState).winstate.yrange[1,0])
    end
;
; Handle the menu item that makes y the abscissa.
    (*pState).abscbutton_y: begin
       widget_control,(*pState).abscbutton_y,get_value=tmp
       if (strmid(tmp,0,1) ne '[') then begin
         widget_control,(*pState).abscbutton_y,set_value='['+tmp+']'
       endif
       widget_control,(*pState).abscbutton_x,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).abscbutton_x,set_value=tmp
       endif
;;;     if (1-(*pState).plot_vs_y) then (*pState).winstate.autoscale=1
       (*pState).plot_vs_x=0
       (*pState).plot_vs_y=1
       widget_control,(*pState).rawxmenu,sensitive=0
       widget_control,(*pState).rawymenu,sensitive=(*pState).readingDCS
       widget_control,(*pState).butt_groupcenter,set_value=(*pState).xvalue
       widget_control,(*pState).butt_grouphwidth,set_value=(*pState).xwidth
       widget_control,(*pState).butt_abscrebin,set_value=(*pState).yrebin
       widget_control,(*pState).butt_groupcenter,set_slider_max=(*pState).xdim
       widget_control,(*pState).butt_grouphwidth,set_slider_max=(*pState).xdim
       widget_control,(*pState).butt_abscrebin,set_slider_max=(*pState).ydim/10 > 6
       widget_control,(*pState).butt_numgroups,set_slider_max=(*pState).xdim; (used to be 31)
       widget_control,(*pState).butt_numgroups,set_value=(*pState).xngroups
       widget_control,(*pState).butt_groupnumber,set_slider_max=(*pState).xngroups
       widget_control,(*pState).butt_groupnumber,set_value=(*pState).xgroupnum
       widget_control,(*pState).butt_xmin,set_value=strcompress((*pState).winstate.xrange[0,1])
       widget_control,(*pState).butt_xmax,set_value=strcompress((*pState).winstate.xrange[1,1])
       widget_control,(*pState).butt_ymin,set_value=strcompress((*pState).winstate.yrange[0,1])
       widget_control,(*pState).butt_ymax,set_value=strcompress((*pState).winstate.yrange[1,1])
    end
;
; Handle the single group menu item.
    (*pState).grupbutton_single: begin
       widget_control,(*pState).grupbutton_single,get_value=tmp
       if (strmid(tmp,0,1) ne '[') then begin
         widget_control,(*pState).grupbutton_single,set_value='['+tmp+']'
       endif
       widget_control,(*pState).grupbutton_several,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_several,set_value=tmp
       endif
       widget_control,(*pState).grupbutton_all,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_all,set_value=tmp
       endif
       (*pState).one=1
       (*pState).some=0
       (*pState).all=0
    end
;
; Handle the multiple group menu item.
    (*pState).grupbutton_several: begin
       widget_control,(*pState).grupbutton_several,get_value=tmp
       if (strmid(tmp,0,1) ne '[') then begin
         widget_control,(*pState).grupbutton_several,set_value='['+tmp+']'
       endif
       widget_control,(*pState).grupbutton_all,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_all,set_value=tmp
       endif
       widget_control,(*pState).grupbutton_single,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_single,set_value=tmp
       endif
       (*pState).one=0
       (*pState).some=1
       (*pState).all=0
    end
;
; Handle the all-in-one group menu item.
    (*pState).grupbutton_all: begin
       widget_control,(*pState).grupbutton_all,get_value=tmp
       if (strmid(tmp,0,1) ne '[') then begin
         widget_control,(*pState).grupbutton_all,set_value='['+tmp+']'
       endif
       widget_control,(*pState).grupbutton_single,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_single,set_value=tmp
       endif
       widget_control,(*pState).grupbutton_several,get_value=tmp
       if (strmid(tmp,0,1) eq '[') then begin
         tmp=strmid(tmp,1,strlen(tmp)-2)
         widget_control,(*pState).grupbutton_several,set_value=tmp
       endif
       (*pState).one=0
       (*pState).some=0
       (*pState).all=1
    end
;
; Handle the minimum abscissa value box.
    (*pState).butt_xmin: begin
       if (event.type eq 0) then begin
         widget_control,(*pState).butt_xmin,get_value=tmpval
         (*pState).winstate.autoscale[index]=0
         (*pState).winstate.xrange[0,index]=tmpval
         if (*pState).objectgraphics then begin
            if finite(xrange[1]) then begin
               (*pState).winstate.xrange[1,index]=xrange[1]
               widget_control,(*pState).butt_xmax,set_value=strcompress(xrange[1])
            endif
            (*pState).plotWin->setproperty,xrange=(*pState).winstate.xrange[*,index],/nodraw
         endif
       endif
    end
;
; Handle the maximum abscissa value box.
    (*pState).butt_xmax: begin
       if (event.type eq 0) then begin
         widget_control,(*pState).butt_xmax,get_value=tmpval
         (*pState).winstate.autoscale[index]=0
         (*pState).winstate.xrange[1,index]=tmpval
       endif
       if (*pState).objectgraphics then begin
          if finite(xrange[0]) then begin
             (*pState).winstate.xrange[0,index]=xrange[0]
             widget_control,(*pState).butt_xmin,set_value=strcompress(xrange[0])
          endif
          (*pState).plotWin->setproperty,xrange=(*pState).winstate.xrange[*,index],/nodraw
       endif
    end
;
; Handle the minimum ordinate value box.
    (*pState).butt_ymin: begin
       if (event.type eq 0) then begin
         widget_control,(*pState).butt_ymin,get_value=tmpval
         (*pState).winstate.autoscale[index]=0
         (*pState).winstate.yrange[0,index]=tmpval
       endif
       if (*pState).objectgraphics then begin
          if finite(yrange[1]) then begin
             (*pState).winstate.yrange[1,index]=yrange[1]
             widget_control,(*pState).butt_ymax,set_value=strcompress(yrange[1])
          endif
          (*pState).plotWin->setproperty,yrange=(*pState).winstate.yrange[*,index],/nodraw
       endif
    end
;
; Handle the maximum ordinate value box.
    (*pState).butt_ymax: begin
       if (event.type eq 0) then begin
         widget_control,(*pState).butt_ymax,get_value=tmpval
         (*pState).winstate.autoscale[index]=0
         (*pState).winstate.yrange[1,index]=tmpval
         if (*pState).objectgraphics then begin
            if finite(yrange[0]) then begin
               (*pState).winstate.yrange[0,index]=yrange[0]
               widget_control,(*pState).butt_ymin,set_value=strcompress(yrange[0])
            endif
           (*pState).plotWin->setproperty,yrange=(*pState).winstate.yrange[*,index],/nodraw
         endif
       endif
    end
;
; Handle the number of groups slider.
    (*pState).butt_numgroups: begin
       widget_control,event.id,get_value=ngroups
       if ((*pState).plot_vs_x) then begin
         (*pState).yngroups=ngroups[0]
       endif else begin
         (*pState).xngroups=ngroups[0]
       endelse
      widget_control,(*pState).butt_groupnumber,set_slider_max=ngroups[0]
    end
;
; Handle the group number slider.
    (*pState).butt_groupnumber: begin
       widget_control,event.id,get_value=groupnum
       if ((*pState).plot_vs_x) then begin
         (*pState).ygroupnum=groupnum[0]
       endif else begin
         (*pState).xgroupnum=groupnum[0]
       endelse
    end
;
; Handle resizing events.
    event.top: begin
;   Compute new width and height of drawwindow, change dimensions of tlb and drawwindow
       newxsize=(event.x-(*pState).restofwidth) > (*pState).fixedwidth
       newysize=(event.y-(*pState).restofheight) > (*pState).fixedheight
       widget_control,event.top,xsize=newxsize+(*pState).restofwidth,ysize=newysize+(*pState).fixedheight
       if (*pState).objectgraphics then begin
          event.x=newxsize & event.y=newysize
          (*pState).plotWin->resize,event
       endif else begin
          widget_control,(*pState).winstate.drawwindow,draw_xsize=newxsize,draw_ysize=newysize
          wdelete,(*pState).winstate.winPix
          window,/free,/pixmap,xsize=newxsize,ysize=newysize
          (*pState).winstate.winPix=!d.window
       endelse
    end
;
    (*pState).filebutton_mplot: begin
       if (*pState).objectgraphics then begin
          (*pState).plotWin->getproperty,xsize=xsize,ysize=ysize
          geom={xsize:xsize,ysize:ysize}
       endif else $
          geom=widget_info((*pState).winstate.drawwindow,/geom)
       if (geom.xsize eq (*pState).oldxsize and geom.ysize eq (*pState).oldysize) then begin
	      newxsize=(*pState).fixedwidth
  	      newysize=(*pState).fixedheight
  	      value='Revert to original plot size'
  	   endif else begin
	      newxsize=(*pState).oldxsize
  	      newysize=(*pState).oldysize
  	      value='Minimize plot dimensions'
  	   endelse
  	   widget_control,(*pState).filebutton_mplot,set_value=value
       widget_control,event.top,xsize=newxsize+(*pState).restofwidth,ysize=newysize+(*pState).fixedheight
       if (*pState).objectgraphics then $
          (*pState).plotWin->resize,{x:newxsize,y:newysize} $
       else begin
          widget_control,(*pState).winstate.drawwindow,draw_xsize=newxsize,draw_ysize=newysize
          wdelete,(*pState).winstate.winPix
          window,/free,/pixmap,xsize=newxsize,ysize=newysize
          (*pState).winstate.winPix=!d.window
       endelse
	end
;
; plotWin motion events
    else:if tag_names(event,/structure_name) eq 'DM_PLOT_MOTION' then begin
        if ((*pState).ndatasets eq 0) then break
        if finite(event.xval) and finite(event.yval) then $
           widget_control,(*pState).textcoord,set_value=["COORDINATES",$
                string([event.xval,event.yval])] $
        else $
           widget_control,(*pState).textcoord,set_value=""
        return
    end
endcase
;
; As needed, modify sensitivities of buttons.
if ((*pState).one) then begin
    widget_control,(*pState).butt_groupcenter,sensitive=1
    widget_control,(*pState).butt_grouphwidth,sensitive=1
    widget_control,(*pState).base2row1,sensitive=0
endif
;
if ((*pState).some) then begin
    widget_control,(*pState).butt_groupcenter,sensitive=0
    widget_control,(*pState).butt_grouphwidth,sensitive=0
    widget_control,(*pState).base2row1,sensitive=1
endif
;
if ((*pState).all) then begin
    widget_control,(*pState).butt_groupcenter,sensitive=0
    widget_control,(*pState).butt_grouphwidth,sensitive=0
    widget_control,(*pState).base2row1,sensitive=0
endif
;
; If there is something to plot, plot it.
if (*pState).ndatasets gt 0 then begin
   if (*pState).objectgraphics then $
      dcs_multiplot_Plot,event $
   else begin
;     wset,(*pState).winstate.winPix
      widget_control,event.top,set_uvalue=pState
      dcs_multiplot_Plot,event
      widget_control,event.top,get_uvalue=pState
;     wset,(*pState).winstate.winVis
;     device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winstate.winPix]
      wshow,(*pState).winstate.winVis
   endelse
endif
;
widget_control,event.top,set_uvalue=pState
;
end


;************************************************************************************************
 pro dcs_multiplot,$
         group_leader = group_leader,$
         notify_ids = notify_ids,$
         register_name = register_name,$
         objectgraphics = objectgraphics
;************************************************************************************************
; This is the widget definition module
;
compile_opt strictarr
;
;
common multiplot_common,multiplot_tlb_number
;
DEVICE,GET_DECOMPOSED=OLD_DECOMP
;
;;;;;;;added following 4 lines for non-modal widget action
if n_elements(group_leader) eq 0 then group_leader = 0L
if n_elements(notify_ids) eq 0 then notify_ids = [0L,0L]
if n_elements(register_name) eq 0 then register_name = 'DCS_multiplot'
if n_elements(objectgraphics) eq 0 then objectgraphics = 0  ;default use direct graphics
;
; Add this statement to determine number of instances so far.
nregistered=xregistered(register_name)
if (nregistered eq 0) then multiplot_tlb_number=0
;
DEVICE,DECOMPOSED=0
;
nodavePtr=1-dave_valid(davePtr)
;
dave_makeDavePtr,davePtr=davePtr
;
davesysvars
;
dcs_sysvars,davePtr=davePtr
;
; Use Alan's routine to load some colors.
default_colors=bindgen(256,3)
colorset
tvlct,default_colors,/get       ; get current color settings
tvlct,!dave_colors.red,!dave_colors.green,!dave_colors.blue
;
screensize=get_screen_size()
;
tlbsize=screensize*[0.85,0.75]
; Define top level widget.
tlb=widget_base(title=strcompress(multiplot_tlb_number,/remove_all)+$
	"plot (DCS multiplot #"+strcompress(multiplot_tlb_number,/remove_all)+$
		")",/col,xsize=tlbsize[0],ysize=tlbsize[1],/tlb_size_events,$
		mbar = bar,group_leader=group_leader)
;
; Define file menu.
filemenu = widget_button(bar,value = 'File',/menu)
;
; Define user preferences submenu.
	prefmenu = widget_button(filemenu,value = 'Preferences',/menu)
    prefbutton_dirobj  = widget_button(prefmenu,value=(['Switch to object graphics',$
        'Switch to direct graphics'])[objectgraphics])
    prefbutton_masking = widget_button(prefmenu,/checked_menu,$
    	value = 'Individual detector bank masking',/separator)
    prefbutton_detnumb = widget_button(prefmenu,/checked_menu,$
    	value = 'Alternative detector numbering')
    prefbutton_dobitflips = widget_button(prefmenu,/checked_menu,$
    	value = 'Do not correct for bitflips',/separator)
;
;	Remaining buttons.
    void = widget_button(filemenu,value = 'Read individual DAVE data files',$
       event_pro = 'dcs_multiplot_Read',uname='readDAVE')
    void = widget_button(filemenu,value = 'Read summed DAVE data files',$
       event_pro = 'dcs_multiplot_Read',uname='readDAVEsum')
    void = widget_button(filemenu,value = 'Read individual DCS raw data files',$
       event_pro = 'dcs_multiplot_Read',uname='readDCS')
    void = widget_button(filemenu,value = 'Read summed DCS raw data files',$
       event_pro = 'dcs_multiplot_Read',uname='readDCSsum')
    void = widget_button(filemenu,value = 'Read DCS histohigh raw data file',$
       event_pro = 'dcs_multiplot_Read',uname='readDCShigh')
    filebutton_print = widget_button(filemenu,value = 'Print',sensitive=0,/menu)
    filebutton_printer = widget_button(filebutton_print,value = 'To a printer')
    filebutton_ps = widget_button(filebutton_print,value = 'To a postscript file')
    filebutton_splot = widget_button(filemenu,value = 'Save plot',$
       event_pro = 'dcs_multiplot_Saveplot',sensitive=0)
    filebutton_rplot = widget_button(filemenu,value = 'Restore plot',$
       event_pro = 'dcs_multiplot_Restoreplot')
    filebutton_sdata = widget_button(filemenu,value = 'Save plotted data',$
       event_pro = 'dcs_multiplot_Savedata',sensitive=0)
    filebutton_mplot = widget_button(filemenu,value = 'Minimize plot dimensions')
    void = widget_button(filemenu,value = 'Clear/reset',event_pro = 'dcs_multiplot_Clear')
    void = widget_button(filemenu,value = 'Quit',event_pro = 'dcs_multiplot_Quit')
;
; Define abscissa menu.
abscmenu=widget_button(bar,value='Abscissa',/menu,sensitive=0)
    abscbutton_x=widget_button(abscmenu,value='x: (not yet defined)')
    abscbutton_y=widget_button(abscmenu,value='y: (not yet defined)')
;
; Define grouping menu.
grupmenu=widget_button(bar,value='Grouping',/menu,sensitive=0)
    grupbutton_single=widget_button(grupmenu,value='Single group')
    grupbutton_several=widget_button(grupmenu,value='Several groups')
    grupbutton_all=widget_button(grupmenu,value='[All in one group]')
;
; Define general options menu.
gnopmenu = widget_button(bar,value = 'Options',/menu,sensitive=0)
    gnopbutton_errorbar = widget_button(gnopmenu,value = 'Show error bars')
    gnopbutton_joinpts = widget_button(gnopmenu,value = 'Join points')
    gnopbutton_showgrid = widget_button(gnopmenu,value = 'Show grid')
    gnopbutton_yminzero = widget_button(gnopmenu,value = 'Set ymin = 0')
    gnopbutton_crosshair = widget_button(gnopmenu,value = 'Show cursor cross hair')
    gnopbutton_normalize = widget_button(gnopmenu,value = 'Normalize to duration')
    gnopbutton_plotsettings = widget_button(gnopmenu,value = 'Modify plot settings')
    gnopbutton_plotsetdefs = widget_button(gnopmenu,value = 'Default plot settings')
;
; Define raw data x options menu.
rawxmenu = widget_button(bar,value = 't,E plots',/menu,sensitive=0)
    rawxbutton_plotvst = widget_button(rawxmenu,value = 'Plot dsdt vs T_SD')
    rawxbutton_plotvsE = widget_button(rawxmenu,value = 'Plot dsdt vs E transfer')
    rawxbutton_plott4E = widget_button(rawxmenu,value = 'Plot t^4*dsdt vs E transfer')
    rawxbutton_plott4EDB = widget_button(rawxmenu,value = 'Plot t^4*dsdt vs E transfer (DB)')
    rawxbutton_plotdos = widget_button(rawxmenu,value = 'Plot omega^2*t^4*dsdt vs E transfer')
    rawxbutton_plotdosDB = widget_button(rawxmenu,value = 'Plot omega^2*t^4*dsdt vs E transfer (DB)')
    rawxbutton_revert = widget_button(rawxmenu,value = 'Revert to normal plot')
;
; Define raw data y options menu.
rawymenu = widget_button(bar,value = 'Angle plots',/menu,sensitive=0)
    rawybutton_plotv2th = widget_button(rawymenu,value = 'Plot vs 2theta')
    rawybutton_plotva2th = widget_button(rawymenu,value = 'Plot vs abs(2theta)')
    rawybutton_revert = widget_button(rawymenu,value = 'Revert to normal plot')
    rawybutton_BPs = widget_button(rawymenu,value = 'Show Bragg peaks')
    rawybutton_abc = widget_button(rawymenu,value = 'Define lattice parameters')
;
; Define dataset operations menu.
dsetmenu = widget_button(bar,value = 'Operations',/menu,sensitive=0)
    dsetbutton_activ = widget_button(dsetmenu,value = 'Activate',$
       event_pro = 'dcs_multiplot_setops')
    dsetbutton_hilite = widget_button(dsetmenu,value = 'Highlight',$
       event_pro = 'dcs_multiplot_setops')
    dsetbutton_renorm = widget_button(dsetmenu,value = 'Renormalize',$
       event_pro = 'dcs_multiplot_setops')
    dsetbutton_rotate = widget_button(dsetmenu,value = 'Rotate in time',$
       event_pro = 'dcs_multiplot_setops')
    dsetbutton_temper = widget_button(dsetmenu,value = 'Modify temperatures',$
       event_pro = 'dcs_multiplot_setops')
;
; Define show information menu.
showmenu = widget_button(bar,value = 'Show',/menu,sensitive=0)
    showbutton_duration = widget_button(showmenu,value = 'Show durations etc')
;
; Create a widget base.
    mainbase=widget_base(tlb,/row)
;
;   Create some sliders, plus text widgets that define x and y limits.
       base1=widget_base(mainbase,/col)
         base1row1=widget_base(base1,/row,sensitive=1,/frame)
          butt_groupcenter=widget_slider(base1row1,title="Single group center",minimum=1,value=1)
          butt_grouphwidth=widget_slider(base1row1,title="Halfwidth of group",minimum=0,value=0)
          butt_abscrebin=widget_slider(base1row1,title="Abscissa rebinning",minimum=1,value=1)
         base1row2=widget_base(base1,/row,/frame)
          xminbase=widget_base(base1row2,/col)
              xllab=widget_label(xminbase,value='xmin')
              butt_xmin=widget_text(xminbase,xsize=10,/editable)
          xmaxbase=widget_base(base1row2,/col)
              xrlab=widget_label(xmaxbase,value='xmax')
              butt_xmax=widget_text(xmaxbase,xsize=10,/editable)
          yminbase=widget_base(base1row2,/col)
              ydlab=widget_label(yminbase,value='ymin')
              butt_ymin=widget_text(yminbase,xsize=10,/editable)
          ymaxbase=widget_base(base1row2,/col)
              yulab=widget_label(ymaxbase,value='ymax')
              butt_ymax=widget_text(ymaxbase,xsize=10,/editable)
;
;   Create some more widgets.
       base2=widget_base(mainbase,/col)
         base2row1=widget_base(base2,sensitive=0,/frame,/row)
          butt_numgroups=widget_slider(base2row1,title="Number of groups",minimum=1,value=1)
          butt_groupnumber=widget_slider(base2row1,title="Group number",minimum=0,value=0)
         spacer=widget_base(base2,ysize=4) ; (spacer)
         base2row2=widget_base(base2,/row)
          textcoord=widget_text(base2row2,xsize=12,ysize=3,/frame)
          textgroup=widget_text(base2row2,ysize=3,/frame)
;
; Create an information base.
    infobase=widget_base(tlb,/row)
       infowindow=widget_text(infobase,xsize=104,ysize=4,/editable,/scroll)
;
; Create the plot window itself.
    geometry=widget_info(tlb,/geometry)
    winxsize=geometry.xsize
    winysize=geometry.ysize
    geometry=widget_info(mainbase,/geometry)
    winysize=winysize-geometry.ysize
    geometry=widget_info(infobase,/geometry)
    winysize=winysize-geometry.ysize
    drawbase=widget_base(tlb,/row)
    if objectgraphics then begin
       plotWin=obj_new('dm_plot',/compound,widgetbase=drawbase,group_leader=tlb,$
            xsize=winxsize,ysize=winysize,/draw_motion_events)
       drawwindow=0L
       winPix=0L
       winVis=0L
    endif else begin
       plotWin=obj_new()
       drawwindow=widget_draw(drawbase,xsize=winxsize,ysize=winysize,$
         /button_events,/motion_events,/tracking_events,keyboard_events=2,$
         event_pro="dcs_multiplot_draw")
    endelse
    oldxsize=winxsize
    oldysize=winysize
;
; Center the widget and realize it.
centertlb,tlb
widget_control,tlb,/realize
;
; Define quantities for use when resizing the widget.
tlbgeom=widget_info(tlb,/geometry)
mainbasegeom=widget_info(mainbase,/geometry)
infobasegeom=widget_info(infobase,/geometry)
restofwidth=tlbgeom.xsize-winxsize
restofheight=tlbgeom.ysize-winysize
fixedwidth=mainbasegeom.xsize > infobasegeom.xsize
fixedheight=mainbasegeom.ysize+infobasegeom.ysize
;
; Define some sensitivities.
widget_control,butt_groupcenter,sensitive=0
widget_control,butt_grouphwidth,sensitive=0
sensitivity={$
	filemenu:1,$
	abscmenu:0,$
	grupmenu:0,$
	gnopmenu:0,$
	rawxmenu:0,$
	rawymenu:0,$
	dsetmenu:0,$
	showmenu:0,$
	prefmenu:0,$
	mainbase:1}
;
if objectgraphics eq 0 then begin
   ; Create a pixmap window for later use, the same size as the screen window.
   window,/free,/pixmap,xsize=winxsize,ysize=winysize
   ;
   ; Get IDs of pixmap and drawwindow.
   winPix = !d.window
   widget_control,drawwindow,get_value = winVis
endif
;
; Default plot settings
defthick=1.0
defsymsize=([0.8,0.006])[objectgraphics]
definitsym="C"
deffadefactor=5
;
; Define limits on DCS file names
use_yiming=0
if (use_yiming) then begin
    files=file_search((*!dave_defaults).datdir+"*",/test_regular)
    nfiles=n_elements(files)
    file=files[0]
    file=strmid(file,strpos(file,!delimiter,/reverse_search)+1)
    limitfrom_dcs=strmid(file,0,strpos(file,'_'))
    file=files[nfiles-1]
    file=strmid(file,strpos(file,!delimiter,/reverse_search)+1)
    limitto_dcs=strmid(file,0,strpos(file,'_'))
endif else begin
    limitfrom_dcs=""
    limitto_dcs=""
endelse
;
; Define winstate.
winState={$
    winPix:winPix,$
    winVis:winVis,$
    drawwindow:drawwindow,$
    xbox:[0.0,1.0],$
    xrange:[[0.0d0,1.0d0],[0.0d0,1.0d0]],$
    ybox:[0.0,1.0],$
    yrange:[[0.0d0,1.0d0],[0.0d0,1.0d0]],$
    xtitle:'',$
    ytitle:'',$
    title:'',$
    mouse:0B,$
    autoscale:[1,1]}
;
; Define the state variable.
state={winstate:winstate,$
    plotWin:plotWin,$
; Widget IDs
    drawbase:drawbase,$
    filemenu:filemenu,$
       filebutton_print:filebutton_print,$
       filebutton_printer:filebutton_printer,$
       filebutton_ps:filebutton_ps,$
       filebutton_splot:filebutton_splot,$
       filebutton_rplot:filebutton_rplot,$
       filebutton_sdata:filebutton_sdata,$
       filebutton_mplot:filebutton_mplot,$
;
    abscmenu:abscmenu,$
       abscbutton_x:abscbutton_x,$
       abscbutton_y:abscbutton_y,$
;
    grupmenu:grupmenu,$
       grupbutton_single:grupbutton_single,$
       grupbutton_several:grupbutton_several,$
       grupbutton_all:grupbutton_all,$
;
    gnopmenu:gnopmenu,$
       gnopbutton_errorbar:gnopbutton_errorbar,$
       gnopbutton_joinpts:gnopbutton_joinpts,$
       gnopbutton_showgrid:gnopbutton_showgrid,$
       gnopbutton_yminzero:gnopbutton_yminzero,$
       gnopbutton_crosshair:gnopbutton_crosshair,$
       gnopbutton_normalize:gnopbutton_normalize,$
       gnopbutton_plotsettings:gnopbutton_plotsettings,$
       gnopbutton_plotsetdefs:gnopbutton_plotsetdefs,$
;
    rawxmenu:rawxmenu,$
       rawxbutton_plotvst:rawxbutton_plotvst,$
       rawxbutton_plotvsE:rawxbutton_plotvsE,$
       rawxbutton_plott4E:rawxbutton_plott4E,$
       rawxbutton_plott4EDB:rawxbutton_plott4EDB,$
       rawxbutton_plotdos:rawxbutton_plotdos,$
       rawxbutton_plotdosDB:rawxbutton_plotdosDB,$
       rawxbutton_revert:rawxbutton_revert,$
;
    rawymenu:rawymenu,$
       rawybutton_plotv2th:rawybutton_plotv2th,$
       rawybutton_plotva2th:rawybutton_plotva2th,$
       rawybutton_revert:rawybutton_revert,$
       rawybutton_BPs:rawybutton_BPs,$
       rawybutton_abc:rawybutton_abc,$
;
    dsetmenu:dsetmenu,$
       dsetbutton_activ:dsetbutton_activ,$
       dsetbutton_hilite:dsetbutton_hilite,$
       dsetbutton_renorm:dsetbutton_renorm,$
       dsetbutton_rotate:dsetbutton_rotate,$
       dsetbutton_temper:dsetbutton_temper,$
;
    showmenu:showmenu,$
       showbutton_duration:showbutton_duration,$
;
    prefmenu:prefmenu,$
       prefbutton_dirobj :prefbutton_dirobj,$
       prefbutton_masking:prefbutton_masking,$
       prefbutton_detnumb:prefbutton_detnumb,$
       prefbutton_dobitflips:prefbutton_dobitflips,$
;
    mainbase:mainbase,$
       base1row1:base1row1,$
         butt_groupcenter:butt_groupcenter,$
         butt_grouphwidth:butt_grouphwidth,$
         butt_abscrebin:butt_abscrebin,$
       base1row2:base1row2,$
         butt_xmin:butt_xmin,$
         butt_xmax:butt_xmax,$
         butt_ymin:butt_ymin,$
         butt_ymax:butt_ymax,$
       base2row1:base2row1,$
         butt_numgroups:butt_numgroups,$
         butt_groupnumber:butt_groupnumber,$
       base2row2:base2row2,$
         textcoord:textcoord,$
         textgroup:textgroup,$
;
    infobase:infobase,$
       infowindow:infowindow,$
;
; Initial values
    objectgraphics:objectgraphics,$
    readingDCS:1,$
    readingDCShigh:1,$
    xvalue:1,$
    yvalue:1,$
    xwidth:0,$
    ywidth:0,$
    xrebin:1,$
    yrebin:1,$
    plot_vs_x:1,$
    plot_vs_y:0,$
    plot_eb:0,$
    join_pts:-1,$
    show_grid:-1,$
    dobitflips:1,$
    cross_hair:-1,$
    norm_d:0,$
    dmask:0,$
    dnumb:0,$
    plotv2th:0,$
    plota2th:0,$
    plothkls:0,$
    plotvst:0,$
    plotvsE:0,$
    plott4E:0,$
    plott4EDB:0,$
    plotdos:0,$
    plotdosDB:0,$
    one:0,$
    some:0,$
    all:1,$
    xngroups:1,$
    xgroupnum:0,$
    yngroups:1,$
    ygroupnum:0,$
    thick:defthick,$
    symsize:defsymsize,$
    initsym:definitsym,$
    fadefactor:deffadefactor,$
    defthick:defthick,$
    defsymsize:defsymsize,$
    definitsym:definitsym,$
    deffadefactor:deffadefactor,$
    oldxsize:oldxsize,$
    oldysize:oldysize,$
    bangx:!x,$
    bangy:!y,$
    bangp:!p,$
  	sensitivity:sensitivity,$
;
    xdim:1,$
    ydim:1,$
;
    restofwidth:restofwidth,$
    restofheight:restofheight,$
    fixedwidth:fixedwidth,$
    fixedheight:fixedheight,$

;   Defined when data are read in.
    pqty:ptr_new(/allocate_heap),$
    perr:ptr_new(/allocate_heap),$
    px:ptr_new(/allocate_heap),$
    py:ptr_new(/allocate_heap),$
    xlabel:'',$
    ylabel:'',$
    histlabel:'',$
    xunits:'',$
    yunits:'',$
    histunits:'',$
    xtype:'',$
    ytype:'',$
    tchansPtr:ptr_new(/allocate_heap),$
    timesPtr:ptr_new(/allocate_heap),$
    energiesPtr:ptr_new(/allocate_heap),$
    elastic_time:4000.0,$
    tsdmin:500.0,$
    equaltimes:1,$
    e0:0.0,$
    lambda0:0.0,$
    ndatasets:0,$
    activePtr:ptr_new(/allocate_heap),$
    hilitePtr:ptr_new(/allocate_heap),$
    multiplierPtr:ptr_new(/allocate_heap),$
    delta_tsdmin:0.0,$
    constantsPtr:ptr_new(/allocate_heap),$
    filesPtr:ptr_new(/allocate_heap),$
    durationsPtr:ptr_new(/allocate_heap),$
    srdenomsPtr:ptr_new(/allocate_heap),$
    temperaturesPtr:ptr_new(/allocate_heap),$
    commentsPtr:ptr_new(/allocate_heap),$
    ksPtr:ptr_new(/allocate_heap),$
    kePtr:ptr_new(/allocate_heap),$
    informationPtr:ptr_new(/allocate_heap),$
;
		abc:{a:0.0,b:0.0,c:0.0,al:90.0,be:90.0,ga:90.0,tthmin:5.0,tthmax:140.0},$
		abctthetaPtr:ptr_new(/allocate_heap),$
		pmask:ptr_new(/allocate_heap),$
    register_name:register_name,$
    notify_ids:notify_ids,$
    savedata:0,$
;    inPtr:inPtr, $
    default_colors:default_colors,$
    OLD_DECOMP:OLD_DECOMP,$
    davePtr:davePtr,$
    nodavePtr:nodavePtr,$
    limitfrom_DAVE:'',$
    limitto_DAVE:'',$
    limitfrom_dcs:limitfrom_dcs,$
    limitto_dcs:limitto_dcs}
;
widget_control,tlb,set_uvalue=ptr_new(state)
;
multiplot_tlb_number=multiplot_tlb_number+1
;
; added register_name variable to the call to xmanager.
xmanager,register_name,tlb,/no_block,cleanup='DCS_multiplot_cleanup',$
	event_handler="DCS_multiplot_handler"
;
end
