;+
; NAME:
;       HW_HELP__DEFINE
;
; PURPOSE:
;       Defines the class HW_HELP. 
;       This object displays information about any object that includes a reference to this 
;       object, the display_all and display_mehtods methods and instatiates it. All objects
;       in the EIS tree of SSW now do this by default.
;       Eg:         idl> data=obj_new('eis_data')
;                   idl> data->display_all 
;       will show the entire source code text for the eis_data object, including a box where
;       one may search for a given string in that source code.
;                   idl> data->display_methods
;       will show all methods defined for the eis_data object, including methods defined in 
;       other source files and eventual methods defined the superclass object.
;       
; CATEGORY:
;       Hansteen/Wikstol Data analysis SW (and general usage?)
;
; CALLING SEQUENCE:
;       
; INPUTS:
;       None
;
; KEYWORD PARAMETERS:
;
; OUTPUTS:
;
; CALLS:
;       eis_xtext
;
; COMMON BLOCKS:
;       
;
; PROCEDURE:
;       Defines the structure of help class objects.
;
; RESTRICTIONS:
;       Cannot yet display the code for the methods residing in other source files nor
;       in the superclass object. An (ok, inconvenient) fix for the latter is to instatiate
;       a dummy superclass object.
;       Eg:         idl> data2=obj_new('hw_data')
;                   idl> data2->display_all                  
;
; MODIFICATION HISTORY:
;       09-Feb-2007: Viggo Hansteen
;       29-Sep-2007: A. Gardini      - Pointers freed.
;        4-Jul-2008: A. Gardini      - Added HELP and INIT_HW_HELP_METHODS.

;
; $Id: hw_help__define.pro 405 2010-07-04 11:21:38Z viggoh $
;-
;
function hw_help::init,routinename,level=level
  self->init_hw_help_methods ; initialization of the help method
  forward_function scope_traceback
  self.minrel='6.2'
  if !version.release lt self.minrel then begin
    message,'IDL version too old, you need release 6.2 or higher to run help',/info
    return,-1
  endif
  if n_elements(level) eq 0 then level=2
  if n_elements(routinename) eq 0 then begin
    scope=scope_traceback()
    routinename=stregex(scope[(n_elements(scope)-level)>1],'[^<]*.pro',/extract,/fold_case)
  endif
  dum=strsplit(routinename,path_sep(),/extract)
  head=(strsplit(dum[n_elements(dum)-1],'(__)',/extract,/regex))[0]
  path=strmid(routinename,0,strlen(routinename)-strlen(dum[n_elements(dum)-1]))
  self.routinename=routinename
  self.path=path
  self.head=head
  self.other_methods=ptr_new(file_search(path+head+'*.pro'))
;
  self.text=ptr_new(rd_tfile(routinename))
  return,1
end

pro hw_help::cleanup
  ptr_free,self.other_methods
  ptr_free,self.text
end

pro hw_help::display_all,init=init
  if n_elements(init) eq 1 then return
  if !version.release lt self.minrel then begin
    message,'IDL version too old, you need release 6.2 or higher to run help',/info
    return
  endif
  eis_xtext,*self.text
  return
end

pro hw_help::display_methods,init=init
  if n_elements(init) eq 1 then return
  if !version.release lt self.minrel then begin
    message,'IDL version too old, you need release 6.2 or higher to run help',/info
    return
  endif
  semi=';'
  pattern="[a-z,0-9,_,:,=,\,,\ ,\(,\),\.,\',/"+semi+']*'
  text1=stregex(*self.text,'^function '+pattern,/extract,/fold_case)
  text1=text1[where(text1 ne '')]
  text2=stregex(*self.text,'^pro '+pattern,/extract,/fold_case)
  text2=text2[where(text2 ne '')]
  text=[[' ','Methods in '+self.routinename,' ','Functions:'],text1,[' ','Procedures:'],text2]
  if n_elements(*self.other_methods) gt 1 then text=[text,[' ','Methods in separate routines:',' ']]
  for i=0,n_elements(*self.other_methods)-1 do begin
    if (*self.other_methods)[i] ne self.routinename then begin
      texto=rd_tfile((*self.other_methods)[i])
      opattern=self.head+pattern
      text3=stregex(texto,'^function '+opattern,/extract,/fold_case)
      sub=where(text3 ne '')
      if sub[0] ne -1 then text3=text3[sub] else text3=''
      text4=stregex(texto,'^pro '+opattern,/extract,/fold_case)
      sub=where(text4 ne '')
      if sub[0] ne -1 then text4=text4[sub] else text4=''
      case '' of
        text3: text=[text,text4]
        text4: text=[text,text3]
        else: text=[text,text3,text4]
      endcase
    endif
  endfor
  inherit=stregex(*self.text,'^\ *(inherits) [a-z,0-9,_,\ ]*\}',/extract,/fold_case)
  sub=where(inherit ne '')
  if sub[0] ne -1 then inherit=inherit[sub] else inherit=''
  if inherit[0] ne '' then begin
    inheritname=self.path+(strsplit(inherit,' }',/extract))[1]+'__define.pro'
    texti=rd_tfile(inheritname)
    text1=stregex(texti,'^function '+pattern,/extract,/fold_case)
    text1=text1[where(text1 ne '')]
    text2=stregex(texti,'^pro '+pattern,/extract,/fold_case)
    text2=text2[where(text2 ne '')]
    text=[text,[' ','Methods in superclass '+inheritname,' ', $
           'Functions:'],text1,[' ','Procedures:'],text2]
  endif
  eis_xtext,text
  return
end

function hw_help::gettext,init=init
  if n_elements(init) eq 1 then return, -1
  if !version.release lt self.minrel then begin
    message,'IDL version too old, you need release 6.2 or higher to run help',/info
    return,-1
  endif
  return,*self.text
end

pro hw_help::help
  help,self,/obj
  return
end

pro hw_help::init_hw_help_methods

  self->display_all,/init
  self->display_methods,/init
  a=self->gettext(/init)

  return
end

pro hw_help__define
  struct={hw_help, routinename:' ', $
                   head:' ', $
                   other_methods:ptr_new(), $
                   path:' ', $
                   minrel:'6.2',$
                   text:ptr_new()}
end
