Viewing contents of file '../idllib/jhuapls1r/usr/box2b.pro'
;-------------------------------------------------------------
;+
; NAME:
; BOX2B
; PURPOSE:
; Simple two mouse button interactive box on image display.
; CATEGORY:
; CALLING SEQUENCE:
; box2b, x1, x2, y1, y2
; INPUTS:
; KEYWORD PARAMETERS:
; Keywords:
; /STATUS means display box size and position.
; MENU=txtarr Text array with exit menu options.
; Def=['OK','Abort','Continue']. 'Continue is added.'
; /NOMENU Inhibits exit menu.
; EXITCODE=code. 0=normal exit, 1=alternate exit.
; If MENU is given then code is option index.
; OUTPUTS:
; x1, x2 = min and max X. out
; y1, y2 = min and max Y. out
; COMMON BLOCKS:
; NOTES:
; Notes: Works in device coordinates.
; Drag open a new box. Corners or sides may be dragged.
; Box may be dragged by clicking inside.
; Click any other button to exit.
; A returned value of -1 means box undefined.
; MODIFICATION HISTORY:
; R. Sterner, 1997 Nov 10
; R. Sterner, 1998 Feb 5 --- Fixed first erase box problem.
; Better but not perfect.
;
; Copyright (C) 1997, Johns Hopkins University/Applied Physics Laboratory
; This software may be used, copied, or redistributed as long as it is not
; sold and this copyright notice is reproduced on each copy made. This
; routine is provided as is without any express or implied warranties
; whatsoever. Other limitations apply as described in the file disclaimer.txt.
;-
;-------------------------------------------------------------
pro box2b, x10, x20, y10, y20, status=stat, help=hlp, $
exitcode=exit, menu=menu, nomenu=nomenu
if keyword_set(hlp) then begin
print,' Simple two mouse button interactive box on image display.'
print,' box2b, x1, x2, y1, y2'
print,' x1, x2 = min and max X. out'
print,' y1, y2 = min and max Y. out'
print,' Keywords:'
print,' /STATUS means display box size and position.'
print,' MENU=txtarr Text array with exit menu options.'
print," Def=['OK','Abort','Continue']. 'Continue is added.'
print,' /NOMENU Inhibits exit menu.'
print,' EXITCODE=code. 0=normal exit, 1=alternate exit.'
print,' If MENU is given then code is option index.'
print,' Notes: Works in device coordinates.'
print,' Drag open a new box. Corners or sides may be dragged.'
print,' Box may be dragged by clicking inside.'
print,' Click any other button to exit.'
print,' A returned value of -1 means box undefined.'
return
endif
tol = 5 ; Closeness tolerence (5 pixels).
xmx = !d.x_size ; Max X coord.
ymx = !d.y_size ; Max Y coord.
xcl=-1 & ycl=-1 ; Define last cursor position.
noerase = 1 ; Don't erase old box first time.
;---- Make sure exit menu is setup ---------
if n_elements(menu) eq 0 then menu=['OK','Abort']
mvals = indgen(n_elements(menu))
;------- Set up status display? -----------
if keyword_set(stat) then begin
xbb,wid=wid,nid=nid,res=[0,1,2],lines=[$
'X1 X2 DX = 000 000 000',$
'Y1 Y2 DY = 000 000 000',$
'CX CY = 000 000']
endif
;------- Use entry box if available ------------
if n_elements(x10) eq 0 then x10=-1 ; Make sure box values
if n_elements(x20) eq 0 then x20=-1 ; are not undefined.
if n_elements(y10) eq 0 then y10=-1
if n_elements(y20) eq 0 then y20=-1
if min([x10,x20,y10,y20]) ge 0 then begin
x1 = (x10<x20)>0<(xmx-1) ; Use given values but keep in range.
x2 = (x10>x20)>0<(xmx-1)
y1 = (y10<y20)>0<(ymx-1)
y2 = (y10>y20)>0<(ymx-1)
tvbox,x1,y1,x2-x1,y2-y1,-2 ; Plot entry box.
if keyword_set(stat) then begin ; Update status.
widget_control,nid(0),set_val='X1 X2 DX = '+strtrim(x1,2)+$
' '+strtrim(x2,2)+' '+strtrim(x2-x1+1,2)
widget_control,nid(1),set_val='Y1 Y2 DY = '+strtrim(y1,2)+$
' '+strtrim(y2,2)+' '+strtrim(y2-y1+1,2)
widget_control,nid(2),set_val='CX CY = '+strtrim((x1+x2)/2,2)+$
' '+strtrim((y1+y2)/2,2)
endif
goto, loop ; Go intereactive.
endif
;------- Init box to first point ----------
cursor, x1, y1, 3, /device ; Wait for a button down.
if !mouse.button gt 1 then return ; Other button.
x2=x1 & y2=y1 ; Got one, set box to single point.
xcl = x1 & ycl = y1 ; Last cursor position.
;================================================
; Main cursor loop
;================================================
loop:
cursor, xc, yc, 0, /device ; Look for new values.
if ((xc eq xcl) and (yc eq ycl)) or $xi ; Not moved, or
((xc eq -1) and (yc eq -1)) then $ ; moved out of window:
cursor,xc,yc,2,/device ; wait for a change.
xcl=xc & ycl=yc ; Save last position.
;------- Exit box routine ------------
if !mouse.button gt 1 then begin ; Other button.
;---- Exit options: OK, Abort, Continue.
if keyword_set(nomenu) then begin
exit = 0
endif else begin
exit = xoption([menu,'Continue'],val=[mvals,-1],def=0)
endelse
if exit ne -1 then begin
tvbox,x1,y1,x2-x1,y2-y1,-1 ; Erase box and exit.
x10=x1 & x20=x2 & y10=y1 & y20=y2 ; Return box.
if keyword_set(stat) then widget_control,wid,/dest
return
endif
tvcrs, xcl, ycl
goto, loop
endif
;------- First point of a drag command ----------
if !mouse.button eq 1 then $
wait,.2 $ ; Debounce.
else goto, loop
;------ Check if at a box corner --------------
ic = 0
if inbox(xc,yc,x1-tol,x1+tol,y1-tol,y1+tol) then ic=1
if inbox(xc,yc,x2-tol,x2+tol,y1-tol,y1+tol) then ic=2
if inbox(xc,yc,x2-tol,x2+tol,y2-tol,y2+tol) then ic=3
if inbox(xc,yc,x1-tol,x1+tol,y2-tol,y2+tol) then ic=4
;------ Was at a corner, drag it ---------------
if ic gt 0 then begin ; Move a corner.
while !mouse.button eq 1 do begin ; Drag current corner.
cursor, xc, yc, 0, /device ; Look for new values.
if ((xc eq xcl) and (yc eq ycl)) or $xi ; Not moved, or
((xc eq -1) and (yc eq -1)) then $ ; moved out of window:
repeat begin
cursor,xc,yc,2,/device ; wait for a change.
endrep until (xc gt -1) and (yc gt -1)
xcl=xc & ycl=yc ; Save last position.
case ic of ; Process a corner move.
1: begin
x1=xc & y1=yc
if (x1 gt x2) and (y1 gt y2) then begin ; Handle any crossover.
swap, x1, x2 & swap, y1,y2 & ic=3 ; 1 --> 3
endif else if x1 gt x2 then begin
swap, x1, x2 & ic=2 ; 1 --> 2
endif else if y1 gt y2 then begin
swap, y1, y2 & ic=4 ; 1 --> 4
endif
end
2: begin
x2=xc & y1=yc
if (x2 lt x1) and (y1 gt y2) then begin ; Handle any crossover.
swap, x1, x2 & swap, y1,y2 & ic=4 ; 2 --> 4
endif else if x2 lt x1 then begin
swap, x1, x2 & ic=1 ; 2 --> 1
endif else if y1 gt y2 then begin
swap, y1, y2 & ic=3 ; 2 --> 3
endif
end
3: begin
x2=xc & y2=yc
if (x2 lt x1) and (y2 lt y1) then begin ; Handle any crossover.
swap, x1, x2 & swap, y1,y2 & ic=1 ; 3 --> 1
endif else if x2 lt x1 then begin
swap, x1, x2 & ic=4 ; 3 --> 4
endif else if y2 lt y1 then begin
swap, y1, y2 & ic=2 ; 3 --> 2
endif
end
4: begin
x1=xc & y2=yc
if (x1 gt x2) and (y2 lt y1) then begin ; Handle any crossover.
swap, x1, x2 & swap, y1,y2 & ic=2 ; 4 -- 2
endif else if x1 gt x2 then begin
swap, x1, x2 & ic=3 ; 4 --> 3
endif else if y2 lt y1 then begin
swap, y1, y2 & ic=1 ; 4 --> 1
endif
end
endcase
tvbox,x1,y1,x2-x1,y2-y1,-2,noerase=noerase ; Plot new box.
noerase = 0 ; Erase from now on.
if keyword_set(stat) then begin ; Update status.
widget_control,nid(0),set_val='X1 X2 DX = '+strtrim(x1,2)+$
' '+strtrim(x2,2)+' '+strtrim(x2-x1+1,2)
widget_control,nid(1),set_val='Y1 Y2 DY = '+strtrim(y1,2)+$
' '+strtrim(y2,2)+' '+strtrim(y2-y1+1,2)
widget_control,nid(2),set_val='CX CY = '+strtrim((x1+x2)/2,2)+$
' '+strtrim((y1+y2)/2,2)
endif
endwhile ; Keep dragging.
goto, loop ; Go look for another drag operation.
endif
;------ Check if at a box side -----------------
is = 0
if inbox(xc,yc,x1-tol,x2+tol,y1-tol,y1+tol) then is=1
if inbox(xc,yc,x2-tol,x2+tol,y1-tol,y2+tol) then is=2
if inbox(xc,yc,x1-tol,x2+tol,y2-tol,y2+tol) then is=3
if inbox(xc,yc,x1-tol,x1+tol,y1-tol,y2+tol) then is=4
;------ Was at a side, drag it ---------------
if is gt 0 then begin ; Move a corner.
while !mouse.button eq 1 do begin ; Drag current corner.
cursor, xc, yc, 0, /device ; Look for new values.
if ((xc eq xcl) and (yc eq ycl)) or $xi ; Not moved, or
((xc eq -1) and (yc eq -1)) then $ ; moved out of window:
repeat begin
cursor,xc,yc,2,/device ; wait for a change.
endrep until (xc gt -1) and (yc gt -1)
xcl=xc & ycl=yc ; Save last position.
case is of ; Process a side move.
1: begin
y1 = yc
if y1 gt y2 then begin ; Handle any crossover.
swap, y1,y2 & is=3 ; 1 --> 3
endif
end
2: begin
x2 = xc
if x2 lt x1 then begin ; Handle any crossover.
swap, x1, x2 & is=4 ; 2 --> 4
endif
end
3: begin
y2 = yc
if y2 lt y1 then begin ; Handle any crossover.
swap, y1,y2 & is=1 ; 3 --> 1
endif
end
4: begin
x1 = xc
if x1 gt x2 then begin ; Handle any crossover.
swap, x1, x2 & is=2 ; 4 -- 2
endif
end
endcase
tvbox,x1,y1,x2-x1,y2-y1,-2 ; Plot new box.
if keyword_set(stat) then begin ; Update status.
widget_control,nid(0),set_val='X1 X2 DX = '+strtrim(x1,2)+$
' '+strtrim(x2,2)+' '+strtrim(x2-x1+1,2)
widget_control,nid(1),set_val='Y1 Y2 DY = '+strtrim(y1,2)+$
' '+strtrim(y2,2)+' '+strtrim(y2-y1+1,2)
widget_control,nid(2),set_val='CX CY = '+strtrim((x1+x2)/2,2)+$
' '+strtrim((y1+y2)/2,2)
endif
endwhile ; Keep dragging.
goto, loop ; Go look for another drag operation.
endif
;------ Inside box -----------------------------
if outbox(xc,yc,x1,x2,y1,y2) then goto, loop
while !mouse.button eq 1 do begin ; Drag current corner.
cursor, xc, yc, 0, /device ; Look for new values.
if ((xc eq xcl) and (yc eq ycl)) or $ ; Not moved, or
((xc eq -1) and (yc eq -1)) then $ ; moved out of window:
repeat begin
cursor,xc,yc,2,/device ; wait for a change.
endrep until (xc gt -1) and (yc gt -1)
dcx=xc-xcl & dcy=yc-ycl ; Move in pixels.
xcl=xc & ycl=yc ; Save last position.
if ((x1+dcx) ge 0) and ((x2+dcx) lt xmx) then begin
x1 = x1+dcx & x2 = x2+dcx ; New box position.
endif
if ((y1+dcy) ge 0) and ((y2+dcy) lt ymx) then begin
y1 = y1+dcy & y2 = y2+dcy
endif
tvbox,x1,y1,x2-x1,y2-y1,-2 ; Plot new box.
if keyword_set(stat) then begin ; Update status.
widget_control,nid(0),set_val='X1 X2 DX = '+strtrim(x1,2)+$
' '+strtrim(x2,2)+' '+strtrim(x2-x1+1,2)
widget_control,nid(1),set_val='Y1 Y2 DY = '+strtrim(y1,2)+$
' '+strtrim(y2,2)+' '+strtrim(y2-y1+1,2)
widget_control,nid(2),set_val='CX CY = '+strtrim((x1+x2)/2,2)+$
' '+strtrim((y1+y2)/2,2)
endif
endwhile
goto, loop
end