; $Id: browsetasice.pro,v 1.6 2006/07/26 21:28:12 kneller Exp $
;###############################################################################
;
;FILENAME:
;        browsetasice.pro
;
;PURPOSE:
;       Simple file browser for TAS data files collected using ICE.
;CATEGORY:
;
;
;METHODS IN FILE:
;
;METHODS:
;    browseTASICE_event
;    browseTASICE_comboindex
;    browseTASICE_updatePlot
;    browseTASICE_moveNearestWidget
;    browseTASICE_open
;    browseTASICE_updateAxisCombos
;    browseTASICE_cleanup
;    browseTASICE
;
;
; AUTHOR:
; Larry Kneller
; NIST Center for Neutron Research
; 100 Bureau Drive, Gaithersburg, MD 20899
; United States
; kneller@nist.gov  301-975-8839
; Mon Jun 05 20:23:56 2006
;
; 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 or if the code in this file is
; included in another product.
;
;###############################################################################
;###############################################################################
;
;NAME:
;        browseTASICE_event
;
;PURPOSE:
;       Event handler.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_event,event
    widget_control,event.handler,get_uvalue=pstate

    case event.id of
    (*pstate).quit:begin
        widget_control,(*pstate).tlb,/destroy
    end;quit
    (*pstate).open:begin
        browseTASICE_open,event
    end;open
    (*pstate).stickybutton:begin
        sticky = (*pstate).stickywidgets
        (*pstate).stickywidgets = (sticky eq 0 ? 1 : 0)
        s = (sticky eq 0 ? '[X] Fix Widget Layout' : '[_] Fix Widget Layout')
        widget_control,(*pstate).stickybutton,set_value=s
    end;stickyButton
    (*pstate).table:begin
        print,tag_names(event,/structure_name)
        print,tag_names(event)
    end;table
    (*pstate).tablebase:begin
        widget_control,(*pstate).table,scr_xsize=event.x,scr_ysize=event.y
    end;tablebase
    (*pstate).combox:begin
        browseTASICE_updatePlot,event
    end;combox
    (*pstate).comboxbase:begin
        widget_control,(*pstate).combox,scr_xsize=event.x,scr_ysize=event.y
    end;comboxbase
    (*pstate).comboy:begin
        browseTASICE_updatePlot,event
    end;comboy
    (*pstate).comboybase:begin
        widget_control,(*pstate).comboy,scr_xsize=event.x,scr_ysize=event.y
    end;comboybase
    (*pstate).drawplot:begin

    end;drawplot
    (*pstate).drawplotbase:begin
        (*pstate).drawplotobj->resize,xsize=event.x,ysize=event.y
        widget_control,(*pstate).combox,scr_xsize=event.x,scr_ysize=event.y
    end;drawplotbase
    (*pstate).draw:begin

        if event.release ne 0 then (*pstate).pressed = 0
        if event.press   ne 0 then (*pstate).pressed = 1

        if (*pstate).pressed eq 1 then begin
            sticky = (*pstate).stickywidgets
            if sticky eq 0 then browseTASICE_moveNearestWidget,event
        endif
    end;draw
    (*pstate).tlb:begin
        widget_control,(*pstate).draw,scr_xsize=event.x,scr_ysize=event.y
        wset,(*pstate).winvis
        erase,(*pstate).color
        browseTASICE_refreshBackground,event
    end;tlb
    else:
    endcase

    if !version.os ne 'Win32' then browseTASICE_refreshBackground,event


end;browseTASICE_event


;###############################################################################
;
;NAME:
;        browseTASICE_comboindex
;
;PURPOSE:
;       Get index of current selection in combobox.
;PARAMETERS:
;
;KEYWORDS:
;
;RETURN VALUE:
;
;###############################################################################
function browseTASICE_comboindex,id
    if widget_info(id,/valid_id) then begin
        widget_control,id,get_value=val
        txt = widget_info(id,/combobox_gettext)
        return,where(val eq txt)
    endif else begin
        return,-1
    endelse
end;browseTASICE_comboindex
;###############################################################################
;
;NAME:
;        browseTASICE_updatePlot
;
;PURPOSE:
;       Update the plot based on new data or combobox state.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_updatePlot,event,title=title
    widget_control,event.handler,get_uvalue=pstate

    if n_elements(title) eq 0 then (*pstate).drawplotobj->getproperty,title=title
    motors = *(*pstate).motors
    data   = *(*pstate).data

    xindex = browseTASICE_comboindex((*pstate).combox)
    yindex = browseTASICE_comboindex((*pstate).comboy)

    (*pstate).drawplotobj->setdata,data[xindex,*],data[yindex,*],$
                               color=0L,$
                               xtitle=motors[xindex],$
                               ytitle=motors[yindex],$
                               title =title
    (*pstate).drawplotobj->defaultdraw


end;browseTASICE_updateplot

;###############################################################################
;
;NAME:
;        browseTASICE_moveNearestWidget
;
;PURPOSE:
;       Allow user to customize the interface by
;       moving the internal widgets.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_moveNearestWidget,event

        widget_control,event.handler,get_uvalue=pstate

        geomtable = widget_info((*pstate).tablebase,/geometry)
        geomcombox = widget_info((*pstate).comboxbase,/geometry)
        geomcomboy = widget_info((*pstate).comboybase,/geometry)
        geomdrawplot = widget_info((*pstate).drawplotbase,/geometry)

        ids = [ (*pstate).tablebase,$
                (*pstate).comboxbase,$
                (*pstate).comboybase,$
                (*pstate).drawplotbase]

        xo = event.x
        tlbgeom = widget_info((*pstate).tlb,/geometry)
        yo = tlbgeom.ysize - event.y
        x = [geomtable.xoffset,geomcombox.xoffset,geomcomboy.xoffset,geomdrawplot.xoffset]
        y = [geomtable.yoffset,geomcombox.yoffset,geomcomboy.yoffset,geomdrawplot.yoffset]

        r = sqrt((x-xo)^2 + (y-yo)^2)

        minr = min(r,index)

        widget_control,ids[index],xoffset=xo,yoffset=yo


;        browseTASICE_refreshBackground,event
;        geomdraw = widget_info((*pstate).draw,/geometry)
;        window,/free,/pixmap,xsize = geomdraw.xsize,ysize=geomdraw.ysize
;        erase,(*pstate).color
;        tempwin = !d.window
;        wset,(*pstate).winvis
;        device,copy=[0,0,geomdraw.xsize,geomdraw.ysize,0,0,tempwin]
;        wdelete,tempwin

end;browseTASICE_moveNearestWidget
pro browseTASICE_refreshBackground,event

        widget_control,event.handler,get_uvalue=pstate
        geomdraw = widget_info((*pstate).draw,/geometry)
        window,/free,/pixmap,xsize = geomdraw.scr_xsize,ysize=geomdraw.scr_ysize
        erase,(*pstate).color
        tempwin = !d.window
        wset,(*pstate).winvis
        device,copy=[0,0,geomdraw.scr_xsize,geomdraw.scr_ysize,0,0,tempwin]
        wdelete,tempwin
end;browseTASICE_refreshBackground
;###############################################################################
;
;NAME:
;        browseTASICE_open
;
;PURPOSE:
;       Open and read a TAS data file collected with ICE.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_open,event

    widget_control,event.handler,get_uvalue=pstate

    fn = dialog_pickfile(filter='*.bt*',path=(*pstate).workdir)

;    print,fn

    if fn ne '' then begin

        (*pstate).workdir = file_dirname(fn)

        line  = ''
        lines = file_lines(fn)

        print,'Spurion2::updateScanPlot'
 ;       print,'lines=',lines
        s = strarr(lines)
        openr,lun,fn,/get_lun
        readf,lun,s
        free_lun,lun


        ;GET MOTORS
        wh=where(stregex(s,'#Columns',/fold_case,/boolean) gt 0,count)
        if count gt 0 then begin
            line = s[wh]
            segs = strsplit(line,/extract)
            ;print,n_elements(segs)
            motors = segs[1:*]
            ;print,motors
            nmotors = n_elements(motors)
        endif

;        wh=where(stregex(s,'#ncolumns',/fold_case,/boolean) gt 0,count)
;        if count gt 0 then begin
;            line = s[wh]
;            segs = strsplit(line,/extract)
;            ;print,segs[1]
;        endif


        for i=0,lines-1 do begin
            segs = strsplit(s[i],/extract)
        endfor;i

        ;GET ACTUAL NUMBER OF POINTS COLLECTED
        wh = where(stregex(s,'#',/fold_case,/boolean) gt 0,count)
        if count ne 0 then npts = lines - n_elements(wh)
        print,npts

        ;GET NOMINAL NUMBER OF POINTS COLLECTED
        wh = where(stregex(s,'#npoints',/fold_case,/boolean) gt 0,count)
        if count ne 0 then npoints = s[wh]
        ;print,npoints

        segs = strsplit(s[wh],/extract)
        npoints = fix(segs[1])
        if npoints eq npts then print,'SCAN COMPLETE' else print,'SCAN INCOMPLETE'

        ;READ THE DATA INTO THE DATA ARRAY
        wh = where(stregex(s,'#',/fold_case,/boolean) eq 0,count)
        if count gt 0 then begin
            data = dblarr(nmotors,npts)

            for i=0,npts-1 do begin
                segs = strsplit(s[wh[i]],/extract)
                for j=0,nmotors-1 do begin
                    if (strcmp(segs[j],'N/A') eq 1) or $
                       (strcmp(segs[j],'OUT') eq 1) or $
                       (strcmp(segs[j],'OPEN') eq 1) then begin
                        temp = double('NaN')
                        ;print,i,segs[j]
                    endif else begin
                        temp = double(segs[j])
                    endelse
                    data[j,i] = temp
                endfor;j
            endfor;i
        endif;count

        ;UPDATE THE DATA TABLE
        value=data
        fc = intarr(3,nmotors)
        fc[2,*] = fix(255*randomu(seed,nmotors))
        fc[1,*] = fix(255*randomu(seed,nmotors))
        fc[0,*] = fix(255*randomu(seed,nmotors))

        geom = widget_info((*pstate).table,/geometry)
        widget_control,(*pstate).table,/destroy
        t = widget_table((*pstate).tablebase,$
                            column_labels=motors,$
                            value=value,$
                            foreground_color=fc,$
                            scr_xsize=geom.scr_xsize,$
                            scr_ysize=geom.scr_ysize)
        (*pstate).table = t

        ;UPDATE THE MOTOR COMBOBOXES
        widget_control,(*pstate).combox,set_value=motors
        widget_control,(*pstate).comboy,set_value=motors

        ;UPDATE THE DATA AND MOTORS POINTERS
        if ptr_valid((*pstate).motors) then ptr_free,(*pstate).motors
        (*pstate).motors = ptr_new(motors)
        if ptr_valid((*pstate).data)   then ptr_free,(*pstate).data
        (*pstate).data = ptr_new(data)

        ;SET THE AXIS CHOICES BASED ON THE AVAILABLE MOTORS.
        browseTASICE_updateAxisCombos,event

        ;UPDATE THE PLOT
        browseTASICE_updatePlot,event,title=file_basename(fn)

    endif;fn ne ''

end;browseTASICE_open

;###############################################################################
;
;NAME:
;        browseTASICE_updateAxisCombos
;
;PURPOSE:
;       Update the comboxes for axis selection.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_updateAxisCombos,event

        widget_control,event.handler,get_uvalue=pstate

        data   = *(*pstate).data
        motors = *(*pstate).motors
        (*pstate).drawplotobj->getproperty,xtitle=xmotor,ytitle=ymotor

        yindex = where(strcmp(motors,'Detector') eq 1);ymotor) eq 1)
        if yindex eq -1 then yindex = 7

        xindex = [-1]

        sz = size(data)
        for i=sz[1]-1,0 do begin
            if min(data[i,*]) ne max(data[i,*]) and $
                    strcmp(motors[i],'Detector') ne 1 and $
                        strcmp(motors[i],'Monitor') ne 1 then $
                            xindex = [i,xindex]
        endfor;i

        xindex = where(strcmp(motors,xmotor) eq 1)
        if xindex[0] eq -1 then xindex[0] = 0

        widget_control,(*pstate).combox,set_combobox_select=xindex[0]
        widget_control,(*pstate).comboy,set_combobox_select=yindex

end;browseTASICE_updateAxisCombos



;###############################################################################
;
;NAME:
;        browseTASICE_cleanup
;
;PURPOSE:
;       Clean up pointers on exiting.
;PARAMETERS:
;
;KEYWORDS:
;
;###############################################################################
pro browseTASICE_cleanup,id

    print,'browseTASICE_cleanup'
    widget_control,id,get_uvalue=pstate
    ptr_free,(*pstate).data
    ptr_free,(*pstate).motors
    ptr_free,pstate

end;browseTASICE_cleanup


;###############################################################################
;
;NAME:
;        browseTASICE
;
;PURPOSE:
;       Start the application.
;PARAMETERS:
;
;KEYWORDS:
;       group_leader    Allow optional group leader in case called by another
;                       application (e.g. DAVE.)
;###############################################################################
pro browseTASICE,group_leader=group_leader


    basexsize = 700
    baseysize = 500

    if n_elements(group_leader) eq 0 then begin
        tlb = widget_base(title='browseTASICE',xoffset=200,yoffset=200,$
                                               xsize=basexsize,ysize=baseysize,$
                                               /tlb_size_events,$
                                               mbar=bar)
    endif else begin
        tlb = widget_base(title='browseTASICE',xoffset=200,yoffset=200,$
                                               xsize=500,ysize=500,$
                                               /tlb_size_events,$
                                               group_leader=group_leader,$
                                               mbar=bar)
    endelse

    File = widget_button(bar, value='File',/menu)
    open = widget_button(file,value='Open')
    quit = widget_button(file,value='Quit')

    WidgetOptions = widget_button(bar,value='Options',/menu)
    stickyButton  = widget_button(WidgetOptions,value='[_] Fix Widget Layout')

    tablebase = widget_base(tlb,xoffset=20,yoffset=20,frame=1)
    table = widget_table(tablebase,scr_xsize=600,scr_ysize=150)

    drawplotbase = widget_base(tlb,xoffset=200,yoffset=180,/tlb_size_events)
    drawplot = cwo_drawplot(drawplotbase,xsize = 400,$
                                         ysize = 300,$
                                         obj=drawplotobj)

    comboxbase = widget_base(tlb,xoffset=20,yoffset=350,/row)
    xlab = widget_label(comboxbase,value='X Axis')
    combox = widget_combobox(comboxbase)
    comboybase = widget_base(tlb,xoffset=20,yoffset=380,/row)
    ylab = widget_label(comboybase,value='Y Axis')
    comboy = widget_combobox(comboybase)

    ;SET UP BACKGROUND DRAW WIDGET TO ESTABLISH COORDINATE SYSTEM
    draw = widget_draw(tlb,xsize=basexsize,ysize=baseysize,$
                           /button_events,/motion_events)

    state = {   tlb:tlb,$
                workdir:'',$
                stickywidgets:0,$
                stickybutton:stickybutton,$
                winpix:0,$
                winvis:0,$
                color:100L+256L*100L +256L*256L*200L,$
                open:open,$
                quit:quit,$
                combox:combox,$
                comboxbase:comboxbase,$
                comboy:comboy,$
                comboybase:comboybase,$
                drawplot:drawplot,$
                drawplotobj:drawplotobj,$
                drawplotbase:drawplotbase,$
                draw:draw,$
                table:table,$
                tablebase:tablebase,$
                pressed:0,$
                data:ptr_new(),$
                motors:ptr_new()}

    pstate = ptr_new(state)
    widget_control,tlb,/realize,set_uvalue=pstate
    widget_control,draw,get_value=winvis
    (*pstate).winvis = winvis
    wset,(*pstate).winvis
    erase,(*pstate).color
    xmanager,'browseTASICE',tlb,/no_block,cleanup='browseTASICE_cleanup'

end;browseTasICE

