; $Id: dataBlaster.pro,v 1.2 2002/01/14 20:59:25 amunter Exp $
; dataBlaster.pro
;
; Demonstration of mouse button and motion events.
;
; Written by R.M.Dimeo (10/26/01)
; RMD - Modified to work within DAVE (11/11/01)
;
;;;;;;;;;;;;;;;
pro dataBlasterCleanup,tlb
widget_control,tlb,get_uvalue = pState,/no_copy
if (*pState).runFlag eq 1 then begin
  s = size((*pState).notifyIDs)
  if s[0] eq 1 then count = 0 else count = s[2]-1
  for j = 0,count do begin
      hfbsDBInfo =   {HFBSDATABLASTEREVENT,$
                              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 = hfbsDBInfo
      endif
  endfor
endif
wdelete,(*pState).winPix1
wdelete,(*pState).winPix2
ptr_free,(*pState).xPtr
ptr_free,(*pState).yPtr
ptr_free,(*pState).yerrPtr
ptr_free,pState
return
end
;;;;;;;;;;;;;;;
pro dataBlasterQuit,event
widget_control,event.top,get_uvalue = pState,/no_copy
if (*pState).runFlag eq 1 then begin
  s = size((*pState).notifyIDs)
  if s[0] eq 1 then count = 0 else count = s[2]-1
  for j = 0,count do begin
      hfbsDBInfo =   {HFBSDATABLASTEREVENT,$
                              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 = hfbsDBInfo
      endif
  endfor
endif
widget_control,event.top,set_uvalue = pState,/no_copy
widget_control,event.top,/destroy
return
end
;;;;;;;;;;;;;;;
pro dataBlasterPlotWin1,event
widget_control,event.top,get_uvalue = pState,/no_copy
plot,*(*pState).xPtr,*(*pState).yPtr,psym = 8,xrange = (*pState).xviewrange1,$
       yrange = (*pState).yviewrange1,xstyle = 1,ystyle = 1,$
       xtitle = 'x',ytitle = 'y'
errplot,*(*pState).xPtr,*(*pState).yPtr-*(*pState).yerrPtr,$
            *(*pState).yPtr+*(*pState).yerrPtr,width = 0.0
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;
pro dataBlasterPlotWin2,event
widget_control,event.top,get_uvalue = pState,/no_copy
plot,*(*pState).xPtr,*(*pState).yPtr,psym = 8,xrange = (*pState).xviewrange2,$
       yrange = (*pState).yviewrange2,xstyle = 1,ystyle = 1,$
       xtitle = 'x',ytitle = 'y'
errplot,*(*pState).xPtr,*(*pState).yPtr-*(*pState).yerrPtr,$
            *(*pState).yPtr+*(*pState).yerrPtr,width = 0.0
xc1 = !x.crange
yc1 = !y.crange[0]+0.5*(!y.crange[1]-!y.crange[0])
xc2 = !x.crange[0]+0.5*(!x.crange[1]-!x.crange[0])
yc2 = !y.crange
plots,xc1,yc1,/data
plots,xc2,yc2,/data
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;
pro dbFire,event
widget_control,event.top,get_uvalue = pState,/no_copy
; Draw the weapons firing at the crosshairs
llcoords = convert_coord(!x.crange[0],!y.crange[0],/data,/to_device)
urcoords = convert_coord(!x.crange[1],!y.crange[1],/data,/to_device)

wset,(*pState).winVis1
device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix1]
plots,[llcoords[0],(*pState).xCen],[llcoords[1],event.y],/device,thick = 2.0
plots,[urcoords[0],(*pState).xCen],[llcoords[1],event.y],/device, thick = 2.0

; Find if there is a data point close to the crosshairs.
; convert cursor location to data coordinates
cenCoords = convert_coord((*pState).xCen,(*pState).yCen,/device,/to_data)
xCen = cenCoords[0] & yCen = cenCoords[1]
xhitRadius = (*(*pState).xPtr)[1]-(*(*pState).xPtr)[0]
yrange = !y.crange
yhitRadius = 0.1*(yrange[1]-yrange[0])

whereClose = where(abs(*(*pState).xPtr-xCen) lt 1.0*xhitRadius and $
                   abs(*(*pState).yPtr-yCen) lt 1.0*yhitRadius,countClose)


if countClose gt 0 then begin
  (*(*pState).yPtr)[whereClose] = 0.0
  (*(*pState).yerrPtr)[whereClose] = 0.0
endif
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;
pro dbWin1Draw,event
widget_control,event.top,get_uvalue = pState,/no_copy
case event.type of
0:	begin	; button press
     (*pState).mouse = event.press
	 if event.press eq 1 then begin	; fire weapon at current cursor location
	   !x = (*pState).x1
	   !y = (*pState).y1
	   (*pState).xCen = event.x
	   (*pState).yCen = event.y
	   widget_control,event.top,set_uvalue = pState,/no_copy
	   dbFire,event
	   widget_control,event.top,get_uvalue = pState,/no_copy
       wset,(*pState).winPix1
	   widget_control,event.top,set_uvalue = pState,/no_copy
	   dataBlasterPlotWin1,event
	   widget_control,event.top,get_uvalue = pState,/no_copy
	   wset,(*pState).winVis1
	   device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix1]
       wset,(*pState).winPix2
	   widget_control,event.top,set_uvalue = pState,/no_copy
	   dataBlasterPlotWin2,event
	   widget_control,event.top,get_uvalue = pState,/no_copy
	   wset,(*pState).winVis2
	   device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix2]
	 endif
	 if event.press eq 4 then begin	; shrink or expand zoom box
       (*pState).xCen = event.x
       (*pState).yCen = event.y
	 endif
	 end
1:   begin	; button release
       (*pState).mouse = 0B
     end
2:  begin	; mouse motion
       if (*pState).mouse eq 4 then begin
        !x = (*pState).x1 & !y = (*pState).y1
        wset,(*pState).winVis1
        device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix1]
        widDevice = convert_coord((*pState).w2x,(*pState).w2y,/data,/to_device)
        w2xDevice = 2.0*abs(event.x-(*pState).xCen)
        w2yDevice = 2.0*abs(event.y-(*pState).yCen)
        xlo = (*pState).xCen-0.5*w2xDevice
        xhi = (*pState).xCen+0.5*w2xDevice
        ylo = (*pState).yCen-0.5*w2yDevice
        yhi = (*pState).yCen+0.5*w2yDevice
        viewlo = convert_coord(xlo,ylo,/device,/to_data)
        viewhi = convert_coord(xhi,yhi,/device,/to_data)
        (*pState).w2x = viewhi[0]-viewlo[0]
        (*pState).w2y = viewhi[1]-viewlo[1]
        (*pState).xviewrange2 = [viewlo[0],viewhi[0]]
         (*pState).yviewrange2 = [viewlo[1],viewhi[1]]
         ; plot the zoom box
         xc = [xlo,xhi,xhi,xlo,xlo]
         yc = [ylo,ylo,yhi,yhi,ylo]
         plots,xc,yc,/device


       endif else begin
       (*pState).xcen = event.x
       (*pState).ycen = event.y
       !x = (*pState).x1 & !y = (*pState).y1
       wset,(*pState).winVis1
       device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix1]
       llcoords = convert_coord(!x.crange[0],!y.crange[0],/data,/to_device)
       urcoords = convert_coord(!x.crange[1],!y.crange[1],/data,/to_device)
       if (event.x ge llcoords[0]) and (event.x le urcoords[0]) and $
          (event.y gt llcoords[1]) and (event.y le urcoords[1]) then begin
         plots,[llcoords[0],urcoords[0]],[event.y,event.y],/device
         plots,[event.x,event.x],[llcoords[1],urcoords[1]],/device
         ; now plot the magnified view in the right hand window
         !x = (*pState).x1 & !y = (*pState).y1
         cenCoords = convert_coord(event.x,event.y,/device,/to_data)
         xCen = cenCoords[0] & yCen = cenCoords[1]

         xlo = xCen-0.5*(*pState).w2x
         xhi = xCen+0.5*(*pState).w2x
        (*pState).xviewrange2 = [xlo,xhi]
         ylo = yCen-0.5*(*pState).w2y
         yhi = yCen+0.5*(*pState).w2y
         (*pState).yviewrange2 = [ylo,yhi]
         ; plot the zoom box
         xc = [xlo,xhi,xhi,xlo,xlo]
         yc = [ylo,ylo,yhi,yhi,ylo]
         plots,xc,yc,/data
         !x = (*pState).x2 & !y = (*pState).y2
         wset,(*pState).winPix2
         widget_control,event.top,set_uvalue = pState,/no_copy
         dataBlasterPlotWin2,event
         widget_control,event.top,get_uvalue = pState,/no_copy
         wset,(*pState).winVis2
         device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pState).winPix2]
       endif
     endelse
     end
else:
endcase
widget_control,event.top,set_uvalue = pState,/no_copy
return
end
;;;;;;;;;;;;;;;
pro dataBlaster_event,event
return
end
;;;;;;;;;;;;;;;
pro dataBlaster,notifyIDs,inPtr,group_leader = group_leader
loadct,0,/silent
;if n_elements(notifyIDs) eq 0 and n_elements(inPtr) eq 0 then begin
;  tlb = widget_base(/col,title = 'Data Blaster',tlb_frame_attr = 1, mbar = bar)
;  runFlag = 0	; running as standalone
;  notifyIDs = [0L,0L] & inPtr = 0.0	; give these some dummy values
;endif else begin
  tlb = widget_base(/col,title = 'Data Blaster',tlb_frame_attr = 1, mbar = bar,$
        group_leader = group_leader)
  runFlag = 1	; running from other application
;endelse

tlb = widget_base(/col,title = 'Data Blaster',tlb_frame_attr = 1, mbar = bar,group_leader = group_leader)
void = widget_label(tlb,value = 'Mouse: aim, Left button: fire, Right button: change zoom box size')
base = widget_base(tlb,/row)
filemenu = widget_button(bar,value = 'File')
void = widget_button(filemenu,value = 'Quit',event_pro = 'dataBlasterQuit')


winxsize = 350 & winysize = 300
plotWin1 = widget_draw(base,xsize = winxsize,ysize = winysize,/button_events,$
                                     /motion_events,event_pro = 'dbWin1Draw')
plotWin2 = widget_draw(base,xsize = winxsize,ysize = winysize)

device,get_screen_size = screenSize
geom = widget_info(tlb,/geometry)
widget_control,tlb,xoff = (screenSize[0]/2)-(geom.scr_xsize/2),$
                   yoff = (screenSize[1]/2)-(geom.scr_ysize/2)

widget_control,tlb,/realize

widget_control,plotWin1,get_value = winVis1
widget_control,plotWin2,get_value = winVis2
window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPix1 = !d.window
window,/free,/pixmap,xsize = winxsize,ysize = winysize
winPix2 = !d.window

; define circle symbols
nth = 30
thlo = 0.0 & thhi = 2.0*!pi & dth = (thhi-thlo)/(nth-1.)
th = fltarr(nth)
th = thlo+dth*findgen(nth)
thisSize = 0.75
xsym = thisSize*cos(th) & ysym = thisSize*sin(th)
usersym,xsym,ysym,/fill

; Generate the fake data
if (runFlag eq 1) or (n_tags(*(*(*inPtr).dataStrPtr).commonStr.histPtr) eq 0) then begin
  npts = 200
  xlo = -10.0 & xhi = 10.0 & dx = (xhi-xlo)/(npts-1.)
  x = xlo+dx*findgen(npts)
  y = fltarr(npts)
  y = hfbs_gaussian(x,area = 800.0,cen = 0.0,wid = 1.0) + $
       hfbs_lorentzian(x,area = 600.0,cen = 3.0,wid = 2.0) + 20.0
  yscat = fltarr(npts)
  for i = 0,npts-1 do begin
    yscat[i] = randomn(s,1,poisson = y[i])
  endfor
  yerr = fltarr(npts)
  yerr = sqrt(yscat)
endif else begin
  x =(*(*(*inPtr).dataStrPtr).commonStr.histPtr).x
  yscat = (*(*(*inPtr).dataStrPtr).commonStr.histPtr).qty[0,*]
  yerr = (*(*(*inPtr).dataStrPtr).commonStr.histPtr).err[0,*]
endelse

xviewrange1 = [min(x),max(x)]
yviewrange1 = [0.0,1.2*max(yscat)]

wset,winPix1
plot,x,yscat,psym = 8,xrange = xviewrange1,yrange = yviewrange1,$
xstyle = 1,ystyle = 1,xtitle = 'x',ytitle = 'y'
errplot,x,yscat-yerr,yscat+yerr,width = 0.0
wset,winVis1
device,copy = [0,0,!d.x_size,!d.y_size,0,0,winPix1]
x1 = !x & y1 = !y
w1x = xviewrange1[1]-xviewrange1[0]
w1y = yviewrange1[1]-yviewrange1[0]
w2x = 0.5*w1x
w2y = 0.5*w1y
xlo = xviewrange1[0]+0.5*(w1x-w2x)
xhi = xlo+w2x
xviewrange2 = [xlo,xhi]
ylo = yviewrange1[0]+0.5*(w1y-w2y)
yhi = ylo+w2y
yviewrange2 = [ylo,yhi]

wset,winPix2
plot,x,yscat,psym = 8,xrange = xviewrange2,yrange = yviewrange2,$
xstyle = 1,ystyle = 1,xtitle = 'x',ytitle = 'y'
errplot,x,yscat-yerr,yscat+yerr,width = 0.0
wset,winVis2
device,copy = [0,0,!d.x_size,!d.y_size,0,0,winPix2]
x2 = !x & y2 = !y

state = {notifyIDs:notifyIDs,$
         inPtr:inPtr,$
         runFlag:runFlag,$	; 0 for standalone, 1 for callable
         winVis1:winVis1,$
         winVis2:winVis2,$
         winPix1:winPix1,$
         winPix2:winPix2,$
         xPtr:ptr_new(x),$
         yPtr:ptr_new(yscat),$
         yerrPtr:ptr_new(yerr),$
         xviewrange1:xviewrange1,$
         yviewrange1:yviewrange1,$
         xviewrange2:xviewrange2,$
         yviewrange2:yviewrange2,$
         xcen:0,$
         ycen:0,$
         mouse:0B,$
         x1:x1,$
         y1:y1,$
         x2:x2,$
         y2:y2,$
         w1x:w1x,$
         w1y:w1y,$
         w2x:w2x,$
         w2y:w2y}

widget_control,tlb,set_uvalue = ptr_new(state),/no_copy
xmanager,'dataBlaster',tlb,/no_block,cleanup = 'dataBlasterCleanup'

end