; $Id: rmdplot.pro,v 1.4 2005/02/08 18:24:44 azuah Exp $
; RMDPlot.pro
;
; This is a re-usable plotting widget program that
; plots two or three column data depending on whether
; or not there are error bars.
;
; Written by R.M.Dimeo (08/18/01)
;###############################################################################
; 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.
;
;###############################################################################
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlotCleanup,tlb
widget_control,tlb,get_uvalue = pState,/no_copy
wdelete,(*pState).winPix
ptr_free,pState
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro doneRMDPlot,event
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlotPrint,event
widget_control,event.top,get_uvalue = pState,/no_copy

datSize = size(*(*pState).dataPtr)
ncols = datSize[1]
npts = datSize[2]
thisDevice = !d.name


  deviceKeywords = ps_form(Cancel = canceled,parent = event.top)
  if canceled ne 1 then begin
    SET_PLOT, 'PS'
    DEVICE, _EXTRA = deviceKeywords

	if (*pState).autoscale eq 1 then begin
  		x = (*(*pState).dataPtr)[0,*]
  		y = (*(*pState).dataPtr)[1,*]
	    xlo = min(x) & xhi = max(x)
	    ylo = min(y) & yhi = max(y)
	    dy = 0.1*(yhi - ylo)
	  	plot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*],psym = 8,$
       		xrange = [xlo,xhi],yrange = [ylo-dy,yhi+dy],$
       		xstyle = 1,ystyle = 1

	endif else begin
  		plot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*],psym = 8,$
       		xrange = [(*pState).xlo,(*pState).xhi],yrange = [(*pState).ylo,(*pState).yhi],$
       		xstyle = 1,ystyle = 1
	endelse
	if ncols eq 3 then begin
  		errplot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*]-(*(*pState).dataPtr)[2,*],$
        		  (*(*pState).dataPtr)[1,*]+(*(*pState).dataPtr)[2,*],width = 0.0
	endif

    DEVICE, /CLOSE_FILE
    set_plot,thisDevice
  endif

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlotPlot,event
widget_control,event.top,get_uvalue = pState,/no_copy
datSize = size(*(*pState).dataPtr)
ncols = datSize[1]
npts = datSize[2]

wset,(*pState).winPix
if (*pState).autoscale eq 1 then begin
  x = (*(*pState).dataPtr)[0,*]
  y = (*(*pState).dataPtr)[1,*]
  xlo = min(x) & xhi = max(x)
  ylo = min(y) & yhi = max(y)
  dy = 0.1*(yhi - ylo)
  plot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*],psym = -8,$
       xrange = [xlo,xhi],yrange = [ylo-dy,yhi+dy],$
       xstyle = 1,ystyle = 1
endif else begin

  plot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*],psym = -8,$
       xrange = [(*pState).xlo,(*pState).xhi],yrange = [(*pState).ylo,(*pState).yhi],$
       xstyle = 1,ystyle = 1
endelse
if ncols eq 3 then begin
  errplot,(*(*pState).dataPtr)[0,*],(*(*pState).dataPtr)[1,*]-(*(*pState).dataPtr)[2,*],$
          (*(*pState).dataPtr)[1,*]+(*(*pState).dataPtr)[2,*],width = 0.0
endif

wset,(*pState).winVis
device,copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlotWinDraw,event
widget_control,event.top,get_uvalue = pState,/no_copy

case event.type of
0: begin  ; button press
	(*pState).mouse = event.press
	if (*pState).mouse eq 4 then begin
	  (*pState).autoscale = 1
	  widget_control,event.top,set_uvalue = pState,/no_copy
	   RMDPlotPlot,event
	  widget_control,event.top,get_uvalue = pState,/no_copy
   	  (*pState).mouse = 0
   	  widget_control,event.top,set_uvalue = pState,/no_copy
	  return
	endif
	(*pState).xp1 = event.x
	(*pState).yp1 = event.y
	wset, (*pState).winVis
	device, copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]
   end
1: begin	; button release
	if ((*pState).mouse eq 1) then begin
		x = (*pState).xp1 < (*pState).xp2
		y = (*pState).yp1 < (*pState).yp2
		w = abs((*pState).xp1 - (*pState).xp2)
		h = abs((*pState).yp1 - (*pState).yp2)
		x2 = x+w
		y2 = y+h
		lc = convert_coord(x, y, /device, /to_data)
		uc = convert_coord(x2, y2, /device, /to_data)
		wset,(*pState).winVis
		(*pState).xlo = lc[0] & (*pState).xhi = uc[0]
		(*pState).ylo = lc[1] & (*pState).yhi = uc[1]
		(*pState).autoscale = 0
		widget_control,event.top,set_uvalue = pState,/no_copy
		RMDPlotPlot,event
		widget_control,event.top,get_uvalue = pState,/no_copy
	endif
	(*pState).mouse = 0
   end
2: begin	; mouse motion
    if ((*pState).mouse eq 1) then begin
    	(*pState).xp2 = event.x
    	(*pState).yp2 = event.y
    	xc = [(*pState).xp1, event.x, event.x, (*pState).xp1, (*pState).xp1]
    	yc = [(*pState).yp1, (*pState).yp1, event.y, event.y, (*pState).yp1]
    	wset, (*pState).winVis
    	device, copy = [0,0,(*pState).winxsize,(*pState).winysize,0,0,(*pState).winPix]
    	plots, xc, yc, /device
    endif
   end
else:
endcase

widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pro RMDPlot_event,event
return
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
function RMDPlot,group_leader = group_leader,dataPtr
loadct,0,/silent
if not ptr_valid(dataPtr) then return,0
data = *dataPtr
datSize = size(data)
ncols = datSize[1]
npts = datSize[2]

if n_elements(group_leader) ne 0 then begin
  tlb = widget_base(/col,title = 'Plot Utility',group_leader = group_leader,$
         /modal,/floating,/base_align_center)
endif else begin
  tlb = widget_base(/col,title = 'Plot Utility',/base_align_center)
endelse

winxsize = 600
winysize = 550
winval = widget_draw(tlb,xsize = winxsize,ysize = winysize,/motion_events,$
         /button_events,event_pro = 'RMDPlotWinDraw')

buttonBase = widget_base(tlb,/row,/base_align_center)

void = widget_button(buttonBase,value = 'Print (postscript file)',event_pro = 'RMDPlotPrint')
void = widget_button(buttonBase,value = 'Dismiss',event_pro = 'doneRMDPlot')

centertlb,tlb
widget_control,tlb,/realize

; Define the plotting symbol..a filled circle
theta = findgen(30)/29.*360.
scale = 1.0
xsym = cos(theta * !dtor) * scale
ysym = sin(theta * !dtor) * scale
usersym, xsym,ysym;,/fill

widget_control,winval,get_value = winVis


window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPix = !d.window

x = reform(data[0,*])
y = reform(data[1,*])
sortx = sort(x)
x = x[sortx] & y = y[sortx]

if ncols eq 3 then begin
  yerr = reform(data[2,*])
  data[2,*] = yerr[sortx]
endif
data[0,*] = x
data[1,*] = y
*dataPtr = data

wset,winPix
plot,data[0,*],data[1,*],psym = -8
if ncols eq 3 then begin
  errplot,data[0,*],data[1,*]-data[2,*],data[1,*]+data[2,*],width = 0.0
endif
wset,winVis
device,copy = [0,0,winxsize,winysize,0,0,winPix]

state = {dataPtr:dataPtr,$
         winxsize:winxsize,$
         winPix:winPix,$
         winVis:winVis,$
         xp1:0.0,$
         yp1:0.0,$
         xp2:0.0,$
         yp2:0.0,$
         xlo:0.0,$
         ylo:0.0,$
         xhi:0.0,$
         yhi:0.0,$
         mouse:0,$
         autoscale:1,$
         winysize:winysize}

widget_control,tlb,set_uvalue = ptr_new(state,/no_copy)
xmanager,'RMDPlot',tlb,cleanup = 'RMDPlotCleanup'

return,0
end