;+
; Project     : SOHO - CDS     
;                   
; Name        : LOCATE_FFCAL
;               
; Purpose     : Help locate the scan for FFCAL
;               
; Explanation : Widget interface to select the pointing for the FFCAL program.
;		A recent EIT image is displayed with the OPS scan pattern
;		overplotted.  This should help position the FFCAL scans to
;		avoid active regions.
;               
; Use         : IDL> LOCATE_FFCAL  [, XCEN, YCEN  [, OPS_L, OPS_R ]]
;    
; Inputs      : None.
;               
; Opt. Inputs : None.
;               
; Outputs     : None required.  If no parameters are passed, then the values
;		are printed to the screen.
;               
; Opt. Outputs: XCEN, YCEN = Center of scan pattern in arcseconds
;
;		OPS_L, OPS_R = Center of scan pattern in OPS coordinates
;               
; Keywords    : FILE = Recent EIT fits file.  If not passed, then the most
;		       recent 304 image will be used.
;
;		DATE_OBS = If passed, then will contain the start date/time of
;			   the FFCAL observation.  The coordinates from the EIT
;			   image will be rotated to this time, and the plot of
;			   the FFCAL scan pattern will be rotated to the
;			   appropriate positions on the EIT image.
;
;		ERRMSG = If defined and passed, then any error messages will be
;			 returned to the user in this parameter rather than
;			 depending on the MESSAGE routine in IDL.  If no errors
;			 are encountered, then a null string is returned.  In
;			 order to use this feature, ERRMSG must be defined
;			 first, e.g.
;
;				ERRMSG = ''
;				LOCATE_FFCAL, XCEN, YCEN, ERRMSG=ERRMSG
;				IF ERRMSG NE '' THEN ...
;
; Calls       : READFITS, MK_EIT_MAP, PLOT_MAP, GET_OPS_POS, CDSLR2XY, XLOADCT,
;		SETWINDOW, ROT_XY, LOCATE_FFCAL_PLOT (internal)
;
; Common      : The common block LOCATE_FFCAL is used internally to the
;		program.
;               
; Restrictions: None
;               
; Side effects: None
;               
; Category    : Operations
;               
; Prev. Hist. : None
;
; Written     : C D Pike, RAL, 
;               
; Modified    : Version 2, 09-Sep-1999, William Thompson, GSFC
;			Get most recent EIT 304 file.
;			Take slight curvature of paths into account.
;		Version 3, 04-Oct-1999, William Thompson, GSFC
;			Convert to widget program
;		Version 4, 29-Oct-1999, William Thompson, GSFC
;			Added keyword DATE_OBS
;               Version 5, 15-Sept-1999, Zarro (EIT/GSFC)
;                       Added MODAL/GROUP to protect calling code
;                       Added /KEEP to ROT_XY for speed and 
;                       WIDGET_CONTROL,/HOUR 
;                       Added checks for OPS limits
;
; Version     : Version 5.
;-            
;
;==============================================================================
;
	PRO LOCATE_FFCAL_PLOT
;
	COMMON LOCATE_FFCAL, SHOW_WIN, TEXT, MAP, X0, Y0, OLD_GR, XL, YL, $
		XR, YR, DATE_OBS
;
;  Plot the EIT image.
;
	DEVICE, SET_GRAPHICS=OLD_GR				;Turn off XOR
	PLOT_MAP, MAP, /SQUARE, MISSING=0, WINDOW=SHOW_WIN
;
;  Convert the center position into OPS coordinates.  Update the text box.
;
        ERR=''
	GET_OPS_POS, X0, Y0, L0, R0,ERR=ERR
        IF ERR NE '' THEN BEGIN
         XACK,ERR
         X0=0. & Y0=0.
         GET_OPS_POS, X0, Y0, L0, R0
        ENDIF
	WIDGET_CONTROL, TEXT, SET_VALUE='X/Y=(' + TRIM(ROUND(X0)) + ',' + $
		TRIM(ROUND(Y0)) + ')  OPS L/R=(' + TRIM(L0) + ',' +	$
		TRIM(R0) + ')'
;
;  Plot the OPS scans, first scanning through R.
;
        WIDGET_CONTROL,/HOUR
	RR = 1000 + 100*INDGEN(21)
	COLOR = !D.TABLE_SIZE - 1
	FOR LL = L0-50,L0+50,25 DO BEGIN
	    XY = CDSLR2XY(REPLICATE(LL,21), RR)
	    IF N_ELEMENTS(DATE_OBS) EQ 1 THEN BEGIN
		TEMP = ROT_XY(XY(*,0), XY(*,1), TSTART=DATE_OBS,	$
			TEND=MAP.TIME, /SOHO, INDEX=INDEX,/KEEP)
		XY(INDEX,*) = TEMP(INDEX,*)
	    ENDIF
	    OPLOT, XY(*,0), XY(*,1), COLOR=COLOR
	ENDFOR
;
;  And then scanning through L.
;
        WIDGET_CONTROL,/HOUR
	FOR LL = R0-50,R0+50,25 DO BEGIN
	    XY = CDSLR2XY(RR, REPLICATE(LL,21))
	    IF N_ELEMENTS(DATE_OBS) EQ 1 THEN BEGIN
		TEMP = ROT_XY(XY(*,0), XY(*,1), TSTART=DATE_OBS,	$
			TEND=MAP.TIME, /SOHO, INDEX=INDEX,/KEEP)
		XY(INDEX,*) = TEMP(INDEX,*)
	    ENDIF
	    OPLOT, XY(*,0), XY(*,1), COLOR=COLOR
	ENDFOR
;
	DEVICE, SET_GRAPHICS=6					;Turn on XOR
	RETURN
	END
;
;==============================================================================
;
	PRO LOCATE_FFCAL_EVENT, EV
;
	ON_ERROR, 2
	COMMON LOCATE_FFCAL
;
	WIDGET_CONTROL, EV.ID, GET_UVALUE=VALUE
	IF N_ELEMENTS(VALUE) EQ 0 THEN VALUE = ''
	CASE VALUE OF
;
;  If the EXIT button was pressed, then exit the widget.
;
	    'EXIT': BEGIN
		DEVICE, SET_GRAPHICS=OLD_GR		;Turn off XOR
		WIDGET_CONTROL, /DESTROY, EV.TOP
		END
;
;  If the "Adjust Color" button was pressed, then call XLOADCT.
;
	    'ADJUST': XLOADCT
;
;  If a draw event was pressed, then get the position, and redraw the plot.
;
	    'DRAW': BEGIN
		IF EV.PRESS NE 0 THEN BEGIN
		    POS = CONVERT_COORD(EV.X, EV.Y, /DEVICE, /TO_DATA)
		    X0 = POS(0)
		    Y0 = POS(1)
;
;  If DATE_OBS is set, then rotate the coordinates to the time of the FFCAL
;  observation.
;
                    WIDGET_CONTROL,/HOUR
		    IF N_ELEMENTS(DATE_OBS) EQ 1 THEN BEGIN
			TEMP = ROT_XY(X0, Y0, TSTART=MAP.TIME,	$
				TEND=DATE_OBS, /SOHO,/KEEP)
			X0 = TEMP(0)
			Y0 = TEMP(1)
		    ENDIF
		    LOCATE_FFCAL_PLOT
		    DELVARX, XL, YL, XR, YR
;
;  Otherwise, draw the active cursor.  Start by erasing the old cursor, if
;  drawn.
;
		END ELSE BEGIN
		    IF N_ELEMENTS(XL) NE 0 THEN BEGIN
			OPLOT, XL, YL
			OPLOT, XR, YR
		    ENDIF
		    POS = CONVERT_COORD(EV.X, EV.Y, /DEVICE, /TO_DATA)
		    XL = !X.CRANGE
		    YL = POS(1) + (XL - POS(0))
		    XR = XL
		    YR = POS(1) - (XL - POS(0))
		    OPLOT, XL, YL
		    OPLOT, XR, YR
		ENDELSE
		WAIT, 0.1
		END
	ENDCASE
;
	RETURN
	END
;
;==============================================================================
;
	PRO LOCATE_FFCAL, XCEN, YCEN, OPS_L, OPS_R, FILE=FILE,	$
		DATE_OBS=K_DATE_OBS, ERRMSG=ERRMSG, MODAL=MODAL, GROUP=GROUP
;
	ON_ERROR, 2
	COMMON LOCATE_FFCAL
	MESSAGE = ''
;
;  If the observation time was passed, then save it in the common block.
;  Otherwise, set the common block variable to undefined.
;
	IF N_ELEMENTS(K_DATE_OBS) EQ 1 THEN DATE_OBS = K_DATE_OBS ELSE	$
		DELVARX, DATE_OBS
;
;  If FILE was not passed, then find a recent EIT image.
;
	IF N_ELEMENTS(FILE) EQ 0 THEN BEGIN
	    GET_UTC, T1
	    T1.TIME = 0
	    FILE = GET_RECENT_EIT(T1,COUNT=COUNT,/QUIET,ERR=MESSAGE,/FULL)
	    IF MESSAGE NE '' THEN GOTO, HANDLE_ERROR
	ENDIF
;
;  Read in the FITS file, and form a map out of the data.
;
	FXREAD, FILE, DATA, HEAD, NANVALUE=0, ERRMSG=MESSAGE
	IF MESSAGE NE '' THEN GOTO, HANDLE_ERROR
	MAP = MK_EIT_MAP(DATA, HEAD)
	MAP.DATA = SIGRANGE(MAP.DATA, MISSING=0)
;
;  Make sure that LOCATE_FFCAL is not already running.
;
	IF (XREGISTERED("locate_ffcal") NE 0) THEN BEGIN
	    MESSAGE = 'LOCATE_FFCAL is already running'
	    GOTO, HANDLE_ERROR
	ENDIF
;
;  Save the coordinate system for the current window.
;
	SAVE_WINDOW = !D.WINDOW
	IF SAVE_WINDOW GE 0 THEN BEGIN
	    DEVICE, WINDOW_STATE=WIN_STATE
	    IF WIN_STATE(SAVE_WINDOW) THEN SETWINDOW
	ENDIF
;
;  Set up the widgets.
;
	MAIN = WIDGET_MBASE(TITLE="Locate FFCAL", /COLUMN,MODAL=MODAL,GROUP=GROUP)
	SHOW = WIDGET_DRAW(MAIN, XSIZE=512, YSIZE=512, /FRAME, RETAIN=2, $
		UVALUE='DRAW', /BUTTON_EVENTS, /MOTION_EVENTS)
;
	PBASE = WIDGET_BASE(MAIN, /ROW)
	DUMMY = WIDGET_BUTTON(PBASE, UVALUE="EXIT", VALUE="Exit")
	DUMMY = WIDGET_BUTTON(PBASE, UVALUE='ADJUST', VALUE='Adjust Color')
	TEXT = WIDGET_TEXT(PBASE,XSIZE=50,YSIZE=1)
;
;  Realize the whole widget
;
	WIDGET_CONTROL, MAIN, /REALIZE
	WIDGET_CONTROL, SHOW, GET_VALUE=SHOW_WIN
;
;  Plot the image in the window.  Overplot the scan pattern.
;
	IF N_ELEMENTS(XCEN) EQ 1 THEN X0 = XCEN ELSE X0 = 0.0
	IF N_ELEMENTS(YCEN) EQ 1 THEN Y0 = YCEN ELSE Y0 = 0.0
	DEVICE, GET_GRAPHICS=OLD_GR
	LOCATE_FFCAL_PLOT
	DELVARX, XL, YL, XR, YR
;
;  Start the whole thing going.
;
	XMANAGER, 'locate_ffcal', MAIN
;
;  Reset the window to the previous value.
;
	IF SAVE_WINDOW GE 0 THEN BEGIN
	    DEVICE, WINDOW_STATE=WIN_STATE
	    IF WIN_STATE(SAVE_WINDOW) THEN SETWINDOW, SAVE_WINDOW, /RESTORE
	ENDIF
;
;  Get the selected XCEN, YCEN values.  Convert them into OPS values, and
;  return.
;
	XCEN = X0
	YCEN = Y0
        ERR=''
	GET_OPS_POS, XCEN, YCEN, OPS_L, OPS_R,ERR=ERR
        IF ERR NE '' THEN BEGIN
         XACK,ERR        
         XCEN=0. & YCEN=0.
         GET_OPS_POS, XCEN, YCEN, OPS_L, OPS_R
        ENDIF

	PRINT, 'X/Y=(' + TRIM(ROUND(XCEN)) + ',' + TRIM(ROUND(YCEN)) +	$
		')  OPS L/R=(' + TRIM(OPS_L) + ',' + TRIM(OPS_R) + ')'
	RETURN
;
;  Error handling point.
;
HANDLE_ERROR:
	IF N_ELEMENTS(ERRMSG) NE 0 THEN ERRMSG = MESSAGE ELSE MESSAGE, MESSAGE
;
	END
