; $Id: cw_progress.pro,v 1.13 2007/02/09 23:10:42 kneller Exp $
;###############################################################################
;
;FILENAME:
;cw_progress.pro
;
;PURPOSE:
;   THIS WIDGET IS A PROGRESS "BAR" WIDGET. IT DISPLAYS A COUNT-UP WHICH
;   THE USER MUST UPDATE WITH VALUES.
;
;CATEGORY:
;   GENERAL UTILITY.
;
;METHODS IN FILE:
;
;    cw_progress_set_value
;    cw_progress_get_value
;    cw_progress_realize
;    cw_progress_event_func
;    cw_progress_cleanup
;    cw_progress
;
;
; AUTHOR:
; Larry Kneller
; NIST Center for Neutron Research
; 100 Bureau Drive, Gaithersburg, MD 20899
; United States
; kneller@nist.gov  301-975-8839
; Jan 24,2005
;
; 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 of if the code in this file is
; included in another product.
;
;###############################################################################
;
; THIS COMPOUND WIDGET DISPLAYS THE PROGRESS
; OF THE STEPS OF A FOR LOOP.  IT WILL
; TAKE AS A VALUE AN ARBITRARY LENGTH ARRAY
; AND WILL DISPLAY TEXT WIDGETS WITH THE CURRENT
; VALUES IN THE FOR LOOPS IN THE FORMAT: step m of n
; OR m/n.
;
; THE VALUES WILL BE SET BY A CALL TO
;   widget_control,id,set_value=[i,j,k,...]
; AT EACH STEP OF THE LOOPS WHERE THE PROGRESS SHOULD
; BE DISPLAYED.
;
;
; THIS WIDGET IS FOR DISPLAY ONLY, SO THERE SHOULD BE
; NO EVENTS.  SIMPLY SWALLOW ANY X-EVENTS. ---  NEEDS TO BE FIXED
;                                               FOR THIS.
;
; INITIAL value=[imax,jmax,kmax,...]
; THEREAFTER THE set_value IS THE CURRENT
; VALUES OF THE INDICES
;


pro cw_progress_set_value,id,value
;
;NAME:
;        cw_progress_set_value
;
;PURPOSE:
;           set-value method
;PARAMETERS:
;           id      [in]    widget id for set
;           value   [in]    value to set
;KEYWORDS:
;           none

    ;UPDATE THE VALUES

    widget_control,widget_info(id,/child),get_uvalue=pstate

    ;THE FOLLOWING STATEMENTS SET THE VALUES, BUT THERE
    ;IS A CHECK AT EACH STEP TO CHECK THAT THE STATE POINTER
    ;IS VALID IN CASE THE parent IS X'ED OUT DURING THIS LOOP.
    ;
    if ptr_valid(pstate) gt 0 then begin
        if n_elements(value) eq n_elements((*pstate).value) then begin
            (*pstate).value = value

                for i=0,n_elements((*pstate).tw)-1 do begin
                    if ptr_valid(pstate) gt 0 then begin
                        widget_control,(*pstate).tw[i],$
                            set_value=(*pstate).title[i]+':'+ $
                                    strtrim(string(value[i]),2) $
                                    +'/'+strtrim(string((*pstate).range[i]),2)
                    endif
            endfor;i
        endif else begin
            print,'NEW VALUE HAS WRONG NUMBER OF ELEMENTS!'
        endelse
    endif;ptr_valid

end;cw_progress_set_value
function cw_progress_get_value,id,value=value
;
;NAME:
;        cw_progress_get_value
;
;PURPOSE:
;       get_value method
;PARAMETERS:
;       id  [in]:   widget id
;KEYWORDS:
;       value[out]: value to get.

;RETURN VALUE:
;       value:   The widget value.
;
    ;THE get_value FUNCTION IS NOT REALLY USED HERE,
    ;BUT I INCLUDE IT FOR MY OWN EDUCATION.

    widget_control,widget_info(id,/child),get_uvalue=pstate

    value = (*pstate).value
    return,value
end;cw_progress_get_value

pro cw_progress_realize,id
;
;NAME:
;        cw_progress_realize
;
;PURPOSE:
;       Realize method simply for completeness.
;PARAMETERS:
;       id  widget id.
;KEYWORDS:
;       none.

    ;THE get_value FUNCTION IS NOT REALLY USED HERE,
    ;BUT I INCLUDE IT FOR MY OWN EDUCATION.
end;cw_progress_realize

function cw_progress_event_func,event
;
;NAME:
;        cw_progress_event_func
;
;PURPOSE:
;       event handler for the widget
;PARAMETERS:
;       event: the event structure passed by the widget.
;KEYWORDS:
;       none.
;RETURN VALUE:
;       pseudoevent: An event structure to pass out of the widget following an event.

    ;THIS IS CALLED WHENEVER AN EVENT OCCURS
    ;
    ;THERE SHOULD BE NO EVENTS FOR THIS WIDGET.

    print,'74 cw_progress_event_func'
;    widget_control,widget_info(event.handler,/child),$
;                            get_uvalue=pstate
;
;    if event.id eq *pstate.stopbut then stopprog = 1
;
;    ;CREATE A PSEUDOEVENT THAT WILL BE RETURNED AND
;    ;PASSED UP THE WIDGET HIERARCHY.
;    pseudoevent = {CW_PROGRESS_EVENT,$
;                    id:(*pstate).base,$
;                    top:event.top,$
;                    handler:event.top,$
;                    stop:stopprog}
;
;
;    ;NOTIFY OUTSIDE WIDGETS OF EVENT
;    for i=0,n_elements((*pstate).notify_id)-1 do begin
;        if widget_info((*pstate).notify_id[i],/valid_id) then $
;            widget_control,(*pstate).notify_id, send_event=pseudoevent
;    endfor;i
;
;    return,pseudoevent

    return,event
end;cw_progress_event_func
function cw_progress_event_pro,event
;
;NAME:
;        cw_progress_event_pro
;
;PURPOSE:
;       event handler for the widget
;PARAMETERS:
;       event: the event structure passed by the widget.
;KEYWORDS:
;       none.

    ;THIS IS CALLED WHENEVER AN EVENT OCCURS
    ;
    ;THERE SHOULD BE NO EVENTS FOR THIS WIDGET.

    print,'213 cw_progress_event_pro'
    print,tag_names(event,/structure_name)
    print,event

end;cw_progress_event_pro

pro cw_progress_cleanup,id
;
;NAME:
;        cw_progress_cleanup
;
;PURPOSE:
;       clean routine for the widget to clean up pstate.
;PARAMETERS:
;       id: widget id.
;KEYWORDS:
;       none.


    ;THIS PROCEDURE IS CALLED WHEN THE WIDGET IS KILLED

    ;print,'cw_progress_cleanup'

    stash = id

    widget_control,stash,get_uvalue=pstate

    ptr_free,pstate
end;cw_progress_cleanup


function cw_progress,parent,$
                        notify_id = notify_id,$
                        kill_notify = kill_notify,$
                        value=value,$
                        uvalue=uvalue,$
                        uname=uname,$
                        xsize=xsize,$
                        ysize=ysize,$
                        title=title,$
                        stopbutton=stopbutton
;
;NAME:
;        cw_progress
;
;PURPOSE:
;       function to create the compound widget.
;PARAMETERS:
;       parent[in]: The cw's parent
;KEYWORDS:
;            notify_id[in]: widgets to nitify of events.
;            value[in]:     value of cw
;            uvalue[in]     uvalue of cw
;            uname[in]      uname of cw
;            xsize[in]      xsize of tlb of cw
;            ysize[in]      ysize of tlb of cw
;            title[in]      title of cw
;
;RETURN VALUE:
;           base:   value of the tlb of the cw.
;
    if n_elements(value) ne 0 then begin


        if n_elements(title) ne n_elements(value) then begin
            title = 'Index '+strtrim(string(indgen(n_elements(value))),2)
        endif

        if n_elements(stopbutton) eq 0 then stopbutton=0
        ;IF A PARENT VALUE HAS BEEN RECEIVED, CREATE A BASE FOR THE CW
        if keyword_set(parent) then begin
            base = widget_base(parent,/column,$
                                kill_notify=kill_notify,$
                                $;value=value,$
                                uname=uname,$
                                uvalue=uvalue,$
                                xsize=xsize,$
                                ysize=ysize,$
                                /tlb_size_events,$
                                pro_set_value = 'cw_progress_set_value',$
                                func_get_value = 'cw_progress_get_value',$
                                event_pro=cw_progress_event_pro,$;event_func = 'cw_progress_event_func',$
                                notify_realize='cw_progress_realize')
        endif else begin
            return,0L
        endelse


        ;CREATE THE 'FUNCTIONAL' PART OF THE CW
        ;THESE TEXT WIDGETS WILL DISPLAY THE
        ;PROGRESS STEPS.
        tw = lonarr(n_elements(value))
        tw[0] = widget_text(base,$
                            value=title[0]+':'+strtrim(0,2) +$
                                  '/' +$
                                  strtrim(string(value[0]),2),$
                            kill_notify='cw_progress_cleanup')
        for i = 1,n_elements(value)-1 do begin
            tw[i] = widget_text(base,$
                                  value = title[i]+':'+strtrim(0,2) +$
                                          '/' +$
                                          strtrim(string(value[i]),2))
        endfor;i


        ;print,stopbutton
        ;IF A STOP BUTTON IS REQUESTED, THE CALLING PROGRAM MUST LOOK FOR
        ;STOP EVENTS ITSELF VIA THE widget_event FUNCTION.
        if stopbutton eq 0 then begin
            stopbut = 0L
        endif else begin
            stopbut = widget_button(base,value='Stop',$
                                    uname='STOPBUT'+strtrim(string(base),2));,$;);,$
                                    ;$;event_pro = 'cw_progress_event_pro')
                                    ;event_func = 'cw_progress_event_func')
        endelse

        ;print,'base=',base
        ;print,'test widgets = ',tw

        stash = tw[0]

        ;SEE IF THERE ARE ANY WIDGETS TO NOTIFY OF EVENTS
        if n_elements(notify_id) eq 0 then notify_id = 0L


        ;CREATE A STATE STRUCTURE TO PASS AROUND IN THIS CW
        state = {parent:parent,$
                    top:parent,$
                    base:base,$
                    handler:base,$
                    stash:stash,$
                    id:stash,$
                    tw:tw,$
                    stopbut:stopbut,$
                    notify_id:notify_id,$
                    value:value,$
                    range:value,$
                    title:title $
                    }

        ;CREATE STATE POINTER AND STASH IT IN THE BUTTON/FIRST CHILD
        ;OF THE CW's BASE.
        pstate = ptr_new(state)
        widget_control,stash,set_uvalue = pstate

        ;021805
        ;ADD THE FOLLOWING LINE:


        ;HAVING AN XMANAGER HERE CRASHES ooDisplayEcho STARTUP AT THE XMANAGER CALL.
;        xmanager,'cw_progress',base,event_handler='cw_progress_event_pro'
;        widget_control,base,event_func='cw_progress_event_func'

        ;RETURN BASE VALUE TO THE CALLING PROGRAM.
        return,base
    endif else begin
        print,'NO VALUES ENTERED FOR CW_PROGRESS.'
        return,0L
    endelse

end;cw_progress

