; $Id: widget_selectgroups.pro,v 1.1 2006/07/28 23:26:32 azuah Exp $
;###############################################################################
;
; NAME:
;   widget_selectGroups
;
; PURPOSE:
;   A small utility modal widget program to obtain information about which
;   groups to extract from a 2D (DaveDat2D object) dataset.
;
; CATEGORY:
;   Data Browser
;
; AUTHOR:
;   Richard Tumanjong Azuah
;   NIST Center for Neutron Research
;   100 Bureau Drive, Gaithersburg, MD 20899
;   United States
;   azuah@nist.gov; (301) 9755604
;   Mar, 2003
;
; 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.
;
;###############################################################################



;===============================================================================
; widget_selectGroups_Event
;
; PURPOSE:
;   Main event handler for app.
;
; PARAMETERS:
;   event [in] - the event structure to be handled
;
pro widget_selectGroups_events, event

widget_control,event.top,get_uvalue = sPtr
uname = widget_info(event.id,/uname)

case uname of
    'ACCEPT': begin
        (*sPtr).cancel=0
        widget_control,event.top,/destroy
    end

    'CANCEL': begin
        (*sPtr).cancel=1
        widget_control,event.top,/destroy
    end

    'GROUPS': begin
        ;; Only accept numbers [0-9] and delimiters - and , in the
        ;; text field. Also, don't allow delimiters at the beginning.
        if (event.type eq 0) then begin
            res = where((*sPtr).valid_achar eq event.ch, isaValidChar)
            if (isaValidChar) then begin
                res = where((*sPtr).valid_adel eq event.ch, isaDelimiter)
                if ((strlen(strtrim((*sPtr).groups,2)) eq 0) and isaDelimiter) then begin
                    widget_control, event.id,set_value=(*sPtr).groups
                    break
                endif
                widget_control, event.id,get_value=value
                (*sPtr).groups = value
            endif else widget_control, event.id,set_value=(*sPtr).groups
        endif
    end

    else:

endcase

;print, 'Event handled...'

end
;-------------------------------------------------------------------------------


;===============================================================================
function widget_selectGroups_int2str, intSpec
if (n_elements(intSpec) eq 0) then return, ''

n = n_elements(intSpec)
if (n eq 1) then return, strtrim(string(intSpec[0]),2)

ntoks = 0
toks = strarr(n)
tbeg = strtrim(string(intSpec[0]),2)
tend = ''
tsize = 0 
for i=0,n-2 do begin
   if (tsize eq 0) then tbeg = strtrim(string(intSpec[i]),2)
   if (intSpec[i] eq intSpec[i+1] - 1) then begin
      tsize++
      if (i lt n-2) then continue
      tend = strtrim(string(intSpec[i+1]),2)
      toks[ntoks++] = (tsize eq 0)? tbeg : tbeg + '-' + tend
   endif else begin
      tend = strtrim(string(intSpec[i]),2)
      toks[ntoks++] = (tsize eq 0)? tbeg : tbeg + '-' + tend
      tsize = 0
      if (i eq n-2) then begin
         toks[ntoks++] = strtrim(string(intSpec[i+1]),2)
      endif
   endelse
endfor

return, strjoin(toks[0:ntoks-1],',',/single)

end
;-------------------------------------------------------------------------------


;===============================================================================
function widget_selectGroups_str2int, strSpec

if (n_elements(strSpec) eq 0) then return, ''

tokens = strsplit(strSpec,',',/extract)
ntok = (size(tokens))[1]
intSpec = -1
index = 0

for j = 0,ntok-1 do begin
    tok1 = strsplit(tokens[j],'-',/extract)
    if ((size(tok1))[1] eq 1) then begin
        i = fix(tok1[0])
        res = where(intSpec eq i, isNotaNewValue)
        if (isNotaNewValue) then continue
        intSpec = (index eq 0)? i : [intSpec,i]
        index = index + 1
    endif else begin
        for i = fix(tok1[0]),fix(tok1[1]) do begin
            res = where(intSpec eq i, isNotaNewValue)
            if (isNotaNewValue) then continue
            intSpec = (index eq 0)? i : [intSpec,i]
            index = index + 1
        endfor
    endelse       
endfor

return, intSpec[sort(intSpec)]

end
;-------------------------------------------------------------------------------


;===============================================================================
; widget_selectGroups
;
; PURPOSE:
;   Entry point and dialog builder for application.
;
; PARAMETERS
;   nosGrps [in] - total number of groups available
;
; KEYWORDS:
;   curGrps [in] - array specifying current group selection
;
;   group_leader [in] - the ID of the parent widget from which this
;                       dialog was launched.
;
; RETURN VALUE: 
;   A structure with information about the chosen groups. 
;     CANCEL:  0 if false, 1 if true
;     GROUPS: array of groups (1-based indices) to extract
;
function widget_selectGroups, nosGrps, curGrps=curGrps, group_leader=group_leader,title=title


label = 'There are '+strtrim(string(nosGrps),2)+' groups present'
label = [label,'']
label = [label,'Please, specify group selection below.']
label = [label,'Use comma as delimiter and dash for ranges.']
label = [label,'Thus 2-4,6,8 implies groups 2,3,4,6 and 8.']


; Widget definition module
if (n_elements(title )eq 0) then title = 'Specify Group Numbers' 
if (n_elements(group_leader) eq 0) then begin
    group_leader = 0L
    modal = 0
    wTLB = widget_base(/col,title=title,/align_center)
endif else begin
    modal = 1
    wTLB = widget_base(group_leader=group_leader,/col,title=title,modal=modal,/align_center)
endelse

wCB0 = widget_base(wTLB,/col,/frame,/align_center)
for i = 0,n_elements(label)-1 do $
   void = widget_label(wCB0, value=label[i])

void = widget_text(wCB0,/editable,/all_events,uname='GROUPS',xsize=60 $
                  ,value=widget_selectGroups_int2str(curGrps))

wCB1 = widget_base(wTLB,/row,/align_center)
acptTip = 'Save changes and exit'
cancTip = 'Discard changes and exit'
void = widget_button(wCB1,value='ACCEPT',uname='ACCEPT',tooltip=acptTip)
void = widget_button(wCB1,value='CANCEL',uname='CANCEL',tooltip=cancTip)

widget_control,wTLB,/realize
valid_ascii_chars = [44,45,48,49,50,51,52,53,54,55,56,57]
valid_ascii_delimiters = [44,45] 
sPtr = ptr_new({cancel:0, $
                groups:'', $
                valid_achar:valid_ascii_chars, $
                valid_adel:valid_ascii_delimiters $
               })

widget_control,wTLB, set_uvalue=sPtr

registerName = 'widget_selectGroups'
xmanager,registerName,wTLB,no_block=modal,event_handler='widget_selectGroups_events'

strSpec = strtrim((*sPtr).groups, 2)
if ((strlen(strSpec) le 0) or (*sPtr).cancel) then begin
    cancel = (*sPtr).cancel
    ptr_free, sPtr
    return, {cancel:cancel,groups:0}
endif

intSpec = widget_selectGroups_str2int(strSpec)

returnStr = {cancel:(*sPtr).cancel,groups:intSpec}

ptr_free, sPtr

return, returnStr

end
