Viewing contents of file '../idllib/contrib/buie/cw_tpmgr.pro'
;+
; NAME:
;    cw_tpmgr
; PURPOSE: (one line)
;    Photometry template manager for itool.
; DESCRIPTION:
;
; CATEGORY:
;    Compound Widgets
; CALLING SEQUENCE:
;    result = cw_tpmgr( parent )
; INPUTS:
;    parent = ID of parent base.
; OPTIONAL INPUT PARAMETERS:
;
; KEYWORD PARAMETERS:
;    TMPLFILE = Name of file containing templates.
;    UVALUE   = Optional user value.
; OUTPUTS:
;
; COMMON BLOCKS:
; SIDE EFFECTS:
;
; RESTRICTIONS:
;
; PROCEDURE:
;
; MODIFICATION HISTORY:
;    Written by Doug Loucks, Lowell Observatory, July, 1994. This version
; is completely new.
;  97/12/12, MWB, Changed behavior to sort the template list by name.
;-
; ------------------------------------------------------------------------------
; Procedure cw_tpmgr_add
; ------------------------------------------------------------------------------
PRO cw_tpmgr_add, state, name, objnam, x, y

WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list

IF state.nplates EQ 0 THEN BEGIN
   p = 0
   state.nplates = 1
   tp_list = [ {name:name, selected:0B, tlbid:0L, tpid:0L} ]
ENDIF ELSE BEGIN
   tp_list = [tp_list, tp_list[0]]
   p = N_ELEMENTS(tp_list) - 1
   tp_list[p].name = name
   idx=sort(strupcase(tp_list[*].name))
   IF state.selected ge 0 THEN oldselected = tp_list[state.selected].name
   tp_list=tp_list[idx]
   p = where(name eq tp_list[*].name)
   p = p[0]
   IF state.selected ge 0 THEN BEGIN
      z = where(oldselected eq tp_list[*].name)
      state.selected = z[0]
   ENDIF
   state.nplates = state.nplates + 1
ENDELSE

tp_list[p].tlbid = $
   WIDGET_BASE( TITLE=tp_list[p].name, GROUP_LEADER=state.topbase )

IF objnam[0] EQ '' THEN BEGIN
   numobj=0
   new = [1B]
   t_objnam = ['<default>']
ENDIF ELSE BEGIN
   numobj=N_ELEMENTS(objnam)
   new = BYTARR(numobj)
   t_objnam = objnam
ENDELSE

tplate = {numobj:numobj, mode:0B, modified:0B, new:new, $
          objnam:t_objnam, x:x, y:y }

tp_list[p].tpid = cw_tplat( tp_list[p].tlbid, VALUE=tplate )

;Refresh the template list widget.
WIDGET_CONTROL, state.tplistid, SET_VALUE=tp_list[*].name, $
                SET_LIST_SELECT=state.selected

WIDGET_CONTROL, tp_list[p].tlbid, MAP=0
WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list

END


; ------------------------------------------------------------------------------
; Procedure cw_tpmgr_load
; Loads a set of templates from a template file.
; ------------------------------------------------------------------------------
PRO cw_tpmgr_load, state
bel = STRING( 7B )

IF state.tmplfile EQ '' THEN BEGIN
   MESSAGE, 'No file.' + bel, /INFO
   RETURN
ENDIF

IF NOT exists( state.tmplfile ) THEN BEGIN
   MESSAGE, 'Template file ' + state.tmplfile + ' does not exist.' + $
   bel, /INFO
   RETURN
ENDIF

IF state.nplates GT 0 THEN BEGIN
   answer = qannounc( 'Warning. Existing templates will be purged.', $
   TRUELABEL='Purge templates and continue', $
   FALSELABEL='Cancel Load Request' )
   IF answer EQ 0 THEN RETURN

   WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list

   FOR j=0, state.nplates-1 DO BEGIN
      WIDGET_CONTROL, tp_list[j].tlbid, /DESTROY
   ENDFOR

   tp_list = tp_list[0]
   tp_list[0].name = ''
   tp_list[0].selected = 0B
   tp_list[0].tlbid = 0L
   tp_list[0].tpid  = 0L
   state.nplates = 0
   WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list
ENDIF

GET_LUN, lu
err = 0
OPENR, lu, state.tmplfile, ERROR=err
if err ne 0 then begin
   ; Problem with file.
   message, !error_state.msg + bel, /INFO
   free_lun, lu
   return
endif

ON_IOERROR, rderr

version = ''
READF, lu, version
IF version NE state.version THEN BEGIN
   MESSAGE, 'Old file version ' + version + '. Not loaded.', /INFO
   CLOSE, lu
   FREE_LUN, lu
   RETURN
ENDIF

count = 0
WHILE NOT EOF( lu ) DO BEGIN
   ; Read in the templates.
   name = ''
   READF, lu, name     ; Template name.
   numobj = 0
   READF, lu, numobj   ; # objects.
   aix = 0
   aiy = 0
   ax = 0.0
   ay = 0.0
   aobjnam = ''
   READF, lu, ax, ay, aobjnam   ; First (anchor) position.

   ;Initialize a temporary structure vector to hold the incoming objects
   ;(the first element will hold the anchor position).
   objnam = [STRTRIM(aobjnam,2)]
   x  = [ax]
   y  = [ay]

   ; Get the remaining coordinate pairs.
   tx = 0.0
   ty = 0.0
   tobjnam = ''

   FOR j = 1, numobj-1 DO BEGIN
      READF, lu, tx, ty, tobjnam
      x  = [x, tx]
      y  = [y, ty]
      objnam = [objnam, STRTRIM(tobjnam,2)]
   ENDFOR

   cw_tpmgr_add, state, name, objnam, x, y
   count = count + 1
ENDWHILE

FREE_LUN, lu

WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list, /NO_COPY
WIDGET_CONTROL, state.tplistid, SET_VALUE=tp_list[*].name
WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list, /NO_COPY

sc = STRCOMPRESS( STRING( count ) )
MESSAGE, sc + ' templates loaded from file ' + state.tmplfile, /INFO

RETURN

rderr:
FREE_LUN, lu
MESSAGE, !error_state.msg + bel, /INFO
END


; ------------------------------------------------------------------------------
; Function cw_tpmgr_gvl
; Get_value function.
; ------------------------------------------------------------------------------
FUNCTION cw_tpmgr_gvl, id

;This function returns the 'value' of the Template Manager, which is defined
;to be the template list array. It has the following structure:
;    {name:'', selected:0B, tlbid:0L, tpid:0L}
;
;Tag tlbid is the Top Level Base of the template.
;Tag tpid  is the id of the template widget.

stash = WIDGET_INFO( id, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY

WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list

WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

RETURN, tp_list
END


; ------------------------------------------------------------------------------
; Function cw_tpmgr_eve
; Main event handler.
; ------------------------------------------------------------------------------
FUNCTION cw_tpmgr_eve, event

WIDGET_CONTROL, event.id, /HOURGLASS

stash = WIDGET_INFO( event.handler, /CHILD )
WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY

bel = STRING(7B)

out_event = 0

CASE event.id OF
   state.delid : BEGIN
      IF state.selected GE 0 THEN BEGIN
         WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list
         con = qannounc( TITLE='Delete Template Confirmation', $
               'Delete template '+tp_list[state.selected].name+'?', $
               TRUELABEL='Yes, continue', $
               FALSELABEL='No, cancel request' )

         IF NOT con THEN BEGIN
            ;Don't delete the template.
            WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
            RETURN, 0
         ENDIF

         ;Destroy the template.
         WIDGET_CONTROL, tp_list[state.selected].tlbid, /DESTROY

         ;Clear some tags.
         tp_list[state.selected].name = ''
         tp_list[state.selected].selected = 0B
         tp_list[state.selected].tlbid = 0L
         tp_list[state.selected].tpid = 0L

         ;Extract all but the deleted template and re-build the list.
         w = WHERE( tp_list[*].name NE '', count )
         IF count NE 0 THEN BEGIN
            tp_list = tp_list[w]
            state.nplates = count
         ENDIF ELSE BEGIN
            tp_list = tp_list[state.selected]
            state.nplates = 0
         ENDELSE
         WIDGET_CONTROL, state.tplistid, SET_VALUE=tp_list[*].name
         WIDGET_CONTROL, state.tpnameid, SET_VALUE=''
         WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list
         state.selected = -1
      ENDIF
   END

   state.dismissid : BEGIN
      ;Access the template list.
      WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list, /NO_COPY

      IF state.selected GE 0 THEN BEGIN
         ;A template is selected. Un-map it, reset the list and name edit
         ;widgets.
         WIDGET_CONTROL, tp_list[state.selected].tlbid, MAP=0
         WIDGET_CONTROL, state.tplistid, SET_VALUE=tp_list[*].name
         WIDGET_CONTROL, state.tpnameid, SET_VALUE=''
      ENDIF

      WIDGET_CONTROL, event.top, MAP=0

      WIDGET_CONTROL, event.top, GET_UVALUE=status, /NO_COPY
      status.active = 0B
      WIDGET_CONTROL, event.top, SET_UVALUE=status, /NO_COPY

      WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list, /NO_COPY
   END

   state.fnselid : BEGIN
      f = DIALOG_PICKFILE(TITLE='Select a template file')
      fn = STRTRIM( f, 2 )
      IF fn NE '' THEN BEGIN
         WIDGET_CONTROL, state.fntxtid, SET_VALUE=fn
         state.tmplfile = fn
         cw_tpmgr_load, state
      ENDIF
   END

   state.fntxtid : BEGIN
      WIDGET_CONTROL, event.id, GET_VALUE=value
      state.tmplfile = STRTRIM( value[0], 2 )
      MESSAGE, 'Filename set to ' + state.tmplfile, /INFO
   END

   state.loadid : BEGIN
      cw_tpmgr_load, state
   END

   state.newid : BEGIN
      newname = qinput( PROMPT='Please enter new template name:' )
      IF newname NE '' THEN BEGIN
         cw_tpmgr_add, state, newname, [''], [0.0], [0.0]
      ENDIF
   END

   state.purgid : BEGIN
      IF state.nplates GT 0 THEN BEGIN
         con = qannounc( 'Purge all templates?', $
               TITLE='Template Purge Confirmation', TRUE='Yes, Continue', $
               FALSE='No, Cancel Request', XSIZE=40 )
         IF con THEN BEGIN
            WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list
            FOR j=0, state.nplates-1 DO BEGIN
               IF tp_list[j].tlbid NE 0L THEN BEGIN
                  IF tp_list[j].tlbid NE 0L THEN BEGIN
                     WIDGET_CONTROL, tp_list[j].tlbid, /DESTROY
                  ENDIF
                  tp_list[j].name  = ''
                  tp_list[j].selected = 0B
                  tp_list[j].tlbid = 0L
                  tp_list[j].tpid  = 0L
               ENDIF
            ENDFOR
            tp_list = [ tp_list[0] ]
            WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list
            WIDGET_CONTROL, state.tplistid, SET_VALUE=''
            WIDGET_CONTROL, state.tpnameid, SET_VALUE=''
            state.nplates = 0
         ENDIF
      ENDIF
   END

   state.saveid : BEGIN
      ; The template file has the following format for each template entry:
      ; First line     : File version code (text).
      ; Second line    : Template name (text).
      ; Third line     : n     ; Number of objects (numeric).
      ; Fourth line    : x y   ; First object absolute position (numeric).
      ; Next n-1 lines : x y   ; Object positions relative to first.
      ; etc...

      IF state.tmplfile EQ '' THEN BEGIN
         MESSAGE, 'Error. Template file not defined.' + bel, /INFO
         WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
         RETURN, 0
      ENDIF

      IF state.nplates EQ 0 THEN BEGIN
         MESSAGE, 'Error. Empty template list.' + bel, /INFO
         WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
         RETURN, 0
      ENDIF

      IF exists( state.tmplfile ) THEN BEGIN
         t = ['  File ' + state.tmplfile + ' exists.', $
              '  It will be overwritten, unless you choose to cancel and', $
              'change the name of the file.' ]
         con = qannounc( t, TITLE='File Overwrite Confirmation', $
               FALSE='Cancel', TRUE='Overwrite File' )
         IF NOT con THEN BEGIN
            WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY
            RETURN, 0
         ENDIF
      ENDIF

      WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list, /NO_COPY

      count = 0
      GET_LUN, lu
      OPENW, lu, state.tmplfile, ERROR=err
      IF err EQ 0 THEN BEGIN
         PRINTF, lu, state.version
         FOR j = 0, state.nplates-1 DO BEGIN
            WIDGET_CONTROL, tp_list[j].tpid, GET_VALUE=tplate, /NO_COPY
            IF tplate.numobj GT 0 THEN BEGIN
               ; Write the template to the file.
               PRINTF, lu, tp_list[j].name
               PRINTF, lu, tplate.numobj
               FOR k = 0, tplate.numobj-1 DO BEGIN
                  PRINTF, lu, tplate.x[k],  tplate.y[k], '  ', $
                              tplate.objnam[k], FORMAT='(2F10.3,A,A)'
               ENDFOR
               tplate.modified = 0B
               count = count + 1
            ENDIF ELSE BEGIN
               MESSAGE, 'Warning. Null template - not saved.', /INFO
            ENDELSE
            WIDGET_CONTROL, tp_list[j].tpid, SET_VALUE=tplate, /NO_COPY
         ENDFOR
         CLOSE, lu
         FREE_LUN, lu
         IF count GT 0 THEN BEGIN
            sc = STRCOMPRESS( STRING( count ) )
            MESSAGE, sc + ' templates saved to file ' + state.tmplfile, /INFO
         ENDIF
      ENDIF ELSE BEGIN
         MESSAGE, !error_state.msg + STRING(7B), /INFO
      ENDELSE
      WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list, /NO_COPY
   END

   state.tplistid : BEGIN
      ;Open access to the list of templates.
      WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list, /NO_COPY

      ;See if a template is selected.
      IF state.selected GE 0 THEN BEGIN
         ;Clear the selected status of the template.
         WIDGET_CONTROL, tp_list[state.selected].tlbid, MAP=0
         tp_list[state.selected].selected = 0B
         state.selected = 0
      ENDIF

      ;Map the newly selected template.
      WIDGET_CONTROL, tp_list[event.index].tlbid, /REALIZE, MAP=1
      ;Set the edit name text widget to the new name.
      WIDGET_CONTROL, state.tpnameid, SET_VALUE=tp_list[event.index].name
      state.selected = event.index
      tp_list[event.index].selected = 1B

      WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list, /NO_COPY
   END

   state.tpnameid : BEGIN
      ;New template name.
      WIDGET_CONTROL, state.tplistid, GET_UVALUE=tp_list, /NO_COPY
      IF state.selected GE 0 THEN BEGIN
         WIDGET_CONTROL, event.id, GET_VALUE=text
         name = STRTRIM( text[0], 2 )
         tp_list[state.selected].name = name
         WIDGET_CONTROL, state.tplistid, SET_VALUE=tp_list[*].name, $
                         SET_LIST_SELECT=state.selected
         WIDGET_CONTROL, tp_list[state.selected].tlbid, TLB_SET_TITLE=name
      ENDIF ELSE BEGIN
         MESSAGE, 'Error. ' + $
            'Empty template list, or template not selected.'+bel, /INFO
         WIDGET_CONTROL, event.id, SET_VALUE=''
      ENDELSE
      WIDGET_CONTROL, state.tplistid, SET_UVALUE=tp_list, /NO_COPY
   END

   ELSE : BEGIN
   END
ENDCASE

WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

RETURN, out_event
END

; ------------------------------------------------------------------------------
; Function cw_tpmgr
; Photometry Template Manager.
; ------------------------------------------------------------------------------
FUNCTION cw_tpmgr, parent, TMPLFILE=tmplfile, UVALUE=uvalue

;Define the state structure.
state = { $
   debugid:0L, $
   delid:0L, $
   dismissid:0L, $
   fnselid:0L, $
   fntxtid:0L, $
   loadid:0L, $
   newid:0L, $
   nplates:0, $
   purgid:0L, $
   saveid:0L, $
   selected:-1, $
   tmplfile:'', $
   topbase:parent, $
   tplistid:0L, $
   tpnameid:0L, $
   version:'phottemp_v02' $
   }

IF KEYWORD_SET( tmplfile ) THEN state.tmplfile=tmplfile

;Define the main base.
IF KEYWORD_SET( uvalue ) THEN BEGIN
   mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_FUNC='cw_tpmgr_eve', $
      FUNC_GET_VALUE='cw_tpmgr_gvl', PRO_SET_VALUE='cw_tpmgr_svl', $
      UVALUE=uvalue )
ENDIF ELSE BEGIN
   mainbase = WIDGET_BASE( parent, COLUMN=1, EVENT_FUNC='cw_tpmgr_eve', $
      FUNC_GET_VALUE='cw_tpmgr_gvl', PRO_SET_VALUE='cw_tpmgr_svl' )
ENDELSE

;Define the button widgets.
wb = WIDGET_BASE( mainbase, ROW=1 )
state.dismissid = WIDGET_BUTTON( wb, VALUE='Dismiss' )
state.loadid = WIDGET_BUTTON( wb, VALUE='Load' )
state.saveid = WIDGET_BUTTON( wb, VALUE='Save' )
state.newid  = WIDGET_BUTTON( wb, VALUE='Add Template' )
state.delid  = WIDGET_BUTTON( wb, VALUE='Delete Template' )
state.purgid = WIDGET_BUTTON( wb, VALUE='Purge' )

;Debug.
;state.debugid = WIDGET_BUTTON( wb, VALUE='Debug' )

; Filename widget.
wb = WIDGET_BASE( mainbase, /ROW )
w1 = WIDGET_LABEL( wb, VALUE='Filename:' )
state.fnselid = WIDGET_BUTTON( wb, VALUE='Select' )
state.fntxtid = WIDGET_TEXT( wb, VALUE=state.tmplfile, XSIZE=26, $
   /EDITABLE )

; Templates label.
w1 = WIDGET_LABEL(mainbase, VALUE='Template Name List (Click-left to select):')

;Template list widget.
tp_list = [{name:'', selected:0B, tlbid:0L, tpid:0L}]
state.tplistid = WIDGET_LIST( mainbase, YSIZE=5, UVALUE=tp_list )

;Template name edit.
state.tpnameid = cw_field( mainbase, $
                 TITLE='Change name of selected template:', /RETURN_EVENTS )

;Load photometry templates from a file?
IF state.tmplfile NE '' THEN cw_tpmgr_load, state

stash = WIDGET_INFO( mainbase, /CHILD )
WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

RETURN, mainbase
END