; $Id: cw_maskmaker.pro,v 1.3 2005/01/24 22:36:17 kneller Exp $
;###############################################################################
;
;FILENAME:
;cw_maskmaker.pro
;
;PURPOSE:
;       THIS IS A COMPOUND WIDGET USED TO INTERACT WITH THE MASK
;       IN AN ooEcho OBJECT USED FOR THE SPIN ECHO DATA REDUCTION
;       SOFTWARE.  IT IS CALLED FROM ooDisplayEcho.
;
;CATEGORY:
;       DATA REDUCTION AND ANALYSIS.
;
;
;METHODS IN FILE:
;
;    cw_maskmaker_set_value
;    cw_maskmaker_get_value
;    cw_maskmaker_draw
;    cw_maskmaker_event_func
;    cw_maskmaker_cleanup
;    cw_maskmaker_realize
;    cw_maskmaker
;
;
; 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.
;
;###############################################################################
pro cw_maskmaker_set_value,id,value
;
;NAME:
;        cw_maskmaker_set_value
;
;PURPOSE:
;       set_value procedure callable from widget_control.
;
;PARAMETERS:
;       id [in]:    widget id
;       value [in]: value to place in the widget's value
;
;KEYWORDS:
;       none.


    ;print,'cw_maskmaker_set_value: Procedure called.'
    ;print,id
    ;print,value
    widget_control,widget_info(id,/child),get_uvalue=pstate

    if ptr_valid((*pstate).mask) gt 0 then ptr_free,((*pstate).mask)
    (*pstate).mask = ptr_new(value)


    ;print,'RESET MASK IMAGE'

    sz = size(*((*pstate).mask))
    (*pstate).xdim = sqrt(sz[1])
    (*pstate).ydim = sqrt(sz[1])

    cw_maskmaker_draw,pstate
    ;widget_control,widget_info(id,/child),set_value=value

end;cw_maskmaker_set_value
function cw_maskmaker_get_value,id,$
                            value=value,$
                            uvalue=uvalue,$
                            uname=uname,$
                            xsize=xsize,$
                            ysize=ysize
;
;NAME:
;        cw_maskmaker_get_value
;
;PURPOSE:
;
;PARAMETERS:
;
;KEYWORDS:
;
;_EXTRA - is used to pass keywords meant for the superclass.

;RETURN VALUE:
;

;    print,'cw_maskmaker_get_value: Function called.'
;    print,id

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

    value = *((*pstate).mask)
    return,value
end;cw_maskmaker_get_value

pro cw_maskmaker_draw,pstate
;
;NAME:
;        cw_maskmaker_draw
;
;PURPOSE:
;       draw method for the widget.
;PARAMETERS:
;       pstate[in]: state pointer with information for draw.
;KEYWORDS:
;       none.


    ;print,'cw_maskmaker_draw: Procedure called.'

    mask = *((*pstate).mask)


    wset,(*pstate).winpix

    refmask = reform(mask,(*pstate).xdim,(*pstate).ydim)

    refmasksize = size(refmask)

    plotimage,bytscl(refmask),yrange=[refmasksize[1],0];,$




    wset,(*pstate).winvis
    device,copy = [0,0,!d.x_size,!d.y_size,0,0,(*pstate).winpix]


    ;SET X AND Y POINTERS HERE.
    if ptr_valid((*pstate).xptr) gt 0 then ptr_free,(*pstate).xptr
    if ptr_valid((*pstate).yptr) gt 0 then ptr_free,(*pstate).yptr
    (*pstate).xptr = ptr_new(!x)   ;SET THESE VALUES AT POINT OF EVENT TO
    (*pstate).yptr = ptr_new(!y)   ;PREVENT AXIS CONFUSION


end;cw_maskmaker_draw
function cw_maskmaker_event_func,event
;
;NAME:
;        cw_maskmaker_event_func
;
;PURPOSE:
;       event handler for the cw_maskmaker widget.
;PARAMETERS:
;       event:  the event structure passed to this function.
;KEYWORDS:
;       none

;RETURN VALUE:
;       pseudoevent:    An event with more information to be used by the event
;                       handler in the calling program.

    ;THIS IS CALLED WHENEVER AN EVENT OCCURS

    ;print,'cw_maskmaker_event_func: Event occurred.'
    ;print,tag_names(event)
    ;print,event

    ;print,event.top



    widget_control,widget_info(event.handler,/child),$
                            get_uvalue=pstate
    uname = widget_info(event.id,/uname)

    ;print,uname

    ;ON MOUSE PRESS FLIP THE VALUE OF THE MASK PIXEL
    if event.type eq 0 then begin


        ;GET INDEX OF EVENT AND FLIP THE MASK VALUE
        help,!x
        !x = *((*pstate).xptr)
        !y = *((*pstate).yptr)
        print,!d.window
        wset,(*pstate).winvis
        print,!d.window
        ;!d.window = (*pstate).winvis
        print,event.x,event.y


        ;NOW HAVE A PROBLEM WITH AXIS CONFUSION HERE!!!!!

        dcoords = convert_coord(event.x,event.y,/device,/to_data)
        print,'dcoords=',dcoords

        sz = size(*((*pstate).mask))
        sz1 = sqrt(sz[1])
        sz2 = sqrt(sz[1])
        ;print,sz

        ;CONVERT COORDINATES TO INDICES ON IMAGE
        xindex = min([fix(dcoords[0]),sz1-1])
        xindex = max([xindex,0])
        yindex = min([fix(dcoords[1]),sz2-1])
        yindex = max([yindex,0])

        ;print,xindex,yindex,(*(*pstate).mask)[xindex,yindex]

        ;UPDATE THE MASK ON THE MOUSE CLICK

    ;THESE NEXT INDICES HAVE TO BE SET TO REFER TO THE CORRECT
    ;PLACE IN MEMORY

        print,xindex,yindex
        if fix((*(*pstate).mask)[xindex+yindex*(*pstate).xdim]) gt 0 then begin
            (*(*pstate).mask)[xindex+yindex*(*pstate).xdim] = 0
        endif else begin
            (*(*pstate).mask)[xindex+yindex*(*pstate).xdim] = 1
        endelse
    endif;event.type = 0

    cw_maskmaker_draw,pstate



    ;print,'event.id =    ',event.id
    ;print,'event.top =   ',event.top
    ;print,'event.handler=',event.handler

    ;print,(*(*pstate).mask)
    ;print,'base=',(*pstate).base
    pseudoevent = {MASKMAKER_EVENT,$
                    id:(*pstate).base,$;id:event.handler,$
                    top:event.top,$
                    handler:event.handler,$
                    type:event.type};,$
                    ;mask:(*(*pstate).mask)}
    print,'pseudoevent in cw_maskmaker event handler'
    ;print,pseudoevent

;    pseudoevent = {MASKMAKER_EVENT,$
;                    id:event.handler,$
;                    top:event.top,$
;                    handler:event.handler,$
;                    maskmaker_id:event.handler,$
;                    maskmaker_top:event.top,$
;                    maskmaker_handler:event.handler,$
;                    type:event.type,$
;                    mask:(*pstate).mask}

    ;SET EVENT ID TO THE BASE
    event.id = (*pstate).base

    ;print,tag_names(pseudoevent)
    ;print,pseudoevent

    ;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
;            widget_control,(*pstate).notify_id, send_event=event
    endfor;i

    ;return,event
    return,pseudoevent
end;cw_maskmaker_event_func



pro cw_maskmaker_cleanup,id
;
;NAME:
;        cw_maskmaker_cleanup
;
;PURPOSE:
;       clean up the state pointer for this widget.
;PARAMETERS:
;       id:     the id of the widget.
;KEYWORDS:
;       none.


    ;THIS PROCEDURE IS CALLED WHEN THE WIDGET IS KILLED

    print,'cw_maskmaker_cleanup'
    print,id
    stash = id;widget_info(id,/child)
    print,stash

    widget_control,stash,get_uvalue=pstate

    if ptr_valid((*pstate).xptr) gt 0 then ptr_free,(*pstate).xptr
    if ptr_valid((*pstate).yptr) gt 0 then ptr_free,(*pstate).yptr
    if ptr_valid((*pstate).mask) gt 0 then ptr_free,(*pstate).mask
    if ptr_valid((*pstate).value) gt 0 then ptr_free,(*pstate).value
    if ptr_valid(pstate) gt 0 then ptr_free,pstate

end;cw_maskmaker_cleanup


pro cw_maskmaker_realize,id
;
;NAME:
;        cw_maskmaker_realize
;
;PURPOSE:
;       Gather information when the widget is realized.
;PARAMETERS:
;       id[in]: The id of the widget.
;KEYWORDS:
;       none.

    ;INITIALIZE WIDGETS AND STATE VALUES
    ;WHEN CALLING WIDGET IS REALIZED

    ;print,'cw_maskmaker_realize: Procedure called.'
    ;print,id

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

    ;GET WINDOW VALUES NOW THAT BASE IS REALIZED
    widget_control,stash,get_value=winvis
    (*pstate).winvis = winvis



    geom = widget_info(stash,/geometry)

    window,/free,/pixmap,xsize=geom.xsize,$
                         ysize=geom.ysize
    (*pstate).winpix = !d.window


    cw_maskmaker_draw,pstate

end;cw_maskmaker_realize
function cw_maskmaker,parent,mask,$
                        notify_id = notify_id,$
                        value=value,$
                        uvalue=uvalue,$
                        uname=uname,$
                        xsize=xsize,$
                        ysize=ysize
;
;NAME:
;        cw_maskmaker
;
;PURPOSE:
;       This is called to create the compound widget.
;PARAMETERS:
;       parent[in]:
;       mask[in]
;KEYWORDS:
;        notify_id: list of widget id's to notify events
;        value:     value to place in the base's value field.
;        uvalue:    uvalue to place in the base's uvalue field.
;        uname:     uname to place in the base's uname field.
;        xsize:     xsize of the base
;        ysize      ysize of the base
;

;RETURN VALUE:
;       base is the value of the top level base for the cw.


    ;NOTE THAT THE mask/value IS NOT A POINTER!!!
    ;TO PUT IN A NEW MASK THE WIDGET NEEDS TO BE
    ;DESTROYED AND REINSTANTIATED.  THIS IS JUST
    ;A SYNTAX ISSUE, BUT PERHAPS IT WILL EVENTUALLY
    ;BE IMPORTANT TO ALLOW A SIZE CHANGE IN THE MASK
    ;VIA widget_control,id,set_value=new_mask
    ;
    ;YES THIS IS THE ROUTE TO GO.

    print,'MAKING CW_MASKMAKER NOW'

    if not keyword_set(mask) then begin
        print,'NO MASK'
        return,0L
    endif else begin
        sz = size(mask)
        xdim = sqrt(sz[1])
        ydim = xdim
        for i=0,xdim-1 do begin
            for j=0,xdim-1 do begin
                if mask[i+j*xdim] gt 0 then begin
                    mask[i+j*xdim] = 1
                endif else begin
                    mask[i+j*xdim] = 0
                endelse
            endfor;j
        endfor;i

        value = ptr_new(mask)
        themask = ptr_new(*value)
    endelse


    ;IF A PARENT VALUE HAS BEEN RECEIVED, CREATE A BASE FOR THE CW

    ;IF NO PARENT SET, THEN PROGRAM SHOULD CREATE A NEW BASE
    ;FOR DISPLAY.

    if keyword_set(parent) then begin
        base = widget_base(parent,$
                            uname=uname,$
                            uvalue=uvalue,$
                            xsize=xsize,$
                            ysize=ysize,$
                            /tlb_size_events,$
                            pro_set_value = 'cw_maskmaker_set_value',$
                            func_get_value = 'cw_maskmaker_get_value',$
                            event_func = 'cw_maskmaker_event_func',$
                            notify_realize='cw_maskmaker_realize')
    endif else begin

        ;WILL THIS WORK OK?
        ;
        ;WHEN WILL THE XMANAGER GET CALLED?

;        tlb = widget_base()
;        base = widget_base(parent,$
;                            uname=uname,$
;                            uvalue=uvalue,$
;                            xsize=xsize,$
;                            ysize=ysize,$
;                            /tlb_size_events,$
;                            pro_set_value = 'cw_maskmaker_set_value',$
;                            func_get_value = 'cw_maskmaker_get_value',$
;                            event_func = 'cw_maskmaker_event_func',$
;                            notify_realize='cw_maskmaker_realize')
        return,0L
    endelse


    ;CREATE THE FUNCTIONAL PART OF THE CW.
    ;FOR THIS CW I AM USING A DRAW WINDOW.
    ;
    ;ON KILLING THIS DRAW WIDGET THE STATE WILL BE DESTROYED
    ;IN THE CLEANUP PROCEEDURE.
    draw = widget_draw(base,$
                        xsize=xsize,$
                        ysize=ysize,$
                        /button_events,$
                        uname = 'CW_MASKMAKER_DRAW',$
                        kill_notify='cw_maskmaker_cleanup')



    ;print,'base=',base
    ;print,'draw=',draw

    stash = draw

    ;SEE IF THERE ARE ANY WIDGETS TO NOTIFY OF EVENTS
    ;
    ;SHOULD I ALWAYS NOTIFY THE PARENT?  DEPENDS.
    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,$
                draw:stash,$
                winvis:0L,$
                xptr:ptr_new(),$
                yptr:ptr_new(),$
                winpix:0L,$
                notify_id:notify_id,$
                value:value,$
                xdim:fix(xdim),$
                ydim:fix(ydim),$
                mask:themask}


    ;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

    ;RETURN BASE VALUE TO THE CALLING PROGRAM.
    print,'maskmaker base = ',base,widget_info(base,/parent)

    return,base
end;cw_maskmaker

