; ------------------------------------------------------------------------------------------------


FUNCTION ecat_search::get_value

; This method returns the actual value of the compound widget.

; Check which radio button is set.

IF self.usr_mode EQ 1 THEN BEGIN


; The usr_mode flag is TRUE, therefore we need to get the search string from
; the user text entry box.

   WIDGET_CONTROL, self.str_id, GET_VALUE = text

; Check if the empty string was retreived from the text entry box.
; If it was, then return it as the result of this function.

   IF text [0] EQ "" THEN RETURN, ""

; Check the search string to make sure that there are no syntax errors.

   status = self.db_tools->check_querry (text, ERRMSG = errmsg, ERRPOS = errpos, DB_ITEM = *self.db_item)

; Check if their there were any errors in the search string.  If there were, put up
; an informative text box describing them.

   IF status NE 0 THEN BEGIN

      msg1 = text

      msg2 = BLANK (errpos  + 1)

;     msg3 = STRING (status, errmsg, FORMAT = '("Detected Error : ", I0, "::", A)')
      msg3 = errmsg

      STRPUT, msg2, '^', errpos

      msg1 = "  " + msg1 + "  "
      msg2 = "  " + msg2 + "  "
      msg3 = "  " + msg3 + "  "

      xack,  ["", msg3, "", msg1, msg2],      $
             result,              $
             GROUP = self.tlb,          $
             /STOP_ICON,          $

             TITLE = 'Error In Database Querry',    $
         SPACE = 0

      text = ""

   ENDIF

ENDIF ELSE BEGIN

; Otherwise get the search string from the database field entry boxes, if any exist.

   text = self.search_id->get_value ()

ENDELSE

; Make sure that text is a scaler variable.

text = text [0]

; Trim any leading or trailing blanks off the user search string.  Also pretty it up a bit.

text = STRTRIM (STRCOMPRESS (text), 2)

; Were done, return.

RETURN, text

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::applyevent, event

; The APPLY button was pressed.


; Check if the pass_ext_events flag is set.  If it is, then set
; compound_event to the apply button event.  Otherwise
; compound_event just gets set to 0.

IF self.pass_ext_events THEN BEGIN

; Get value of the widget.

   val = self->get_value ()

print, 'ECAT SEARCH STR:',  val
print, 'ECAT SEARCH DB: ',  self.database

; Check if the empty string is set as the value of the widget.  If it is, just eat the
; event so that no further processing will occur.

   IF val EQ "" THEN RETURN, 0

; Create the OK event.

   compound_event = { ECAT_SEARCH_EVENT,    $
                      self.tlb,             $
                      event.top,            $
                      0L,                   $
                      self.database,        $
                      val,                  $
                      "",                   $
                      1 }

ENDIF ELSE compound_event = 0

RETURN, compound_event

END


; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::db_btn_event, event

; Get the name of the database that the user just selected.
WIDGET_CONTROL, event.id, GET_VALUE = db

; Set the new value for the database.
self.database = db

; Tell the database item selection object which database to use.
self.select_id->setproperty, DATABASE = db

; Clear any stored database item names.
self.search_id->del_all_field


RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::btn1event, event

; Radio button 1 was pressed.

; Unset radio button 2.

WIDGET_CONTROL, self.bt2_id, SET_BUTTON = 0

; Set the user mode to 1 (TRUE)

self.usr_mode = 1

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::btn2event, event

; Radio button 2 was pressed.

; Unset radio button 1.

WIDGET_CONTROL, self.bt1_id, SET_BUTTON = 0

; Set the user mode to 0 (FALSE)

self.usr_mode = 0

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::cancelevent, event

; The cancel button was pressed.

; Check if the pass_ext_events flag is set.  If it is, then set
; compound_event to the cancel button event.  Otherwise
; compound_event just gets set to 0.

IF self.pass_ext_events THEN BEGIN

   compound_event = { ECAT_SEARCH_EVENT,    $
                      self.tlb,             $
                      event.top,            $
                      0L,                   $
                      "",                   $
                      "",                   $
                      "",                   $
                      0 }

    RETURN, compound_event

ENDIF

; Otherwise,  destroy the widget.

WIDGET_CONTROL, self.tlb, /DESTROY

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::listevent, event

; An event was generated by the database item list box.

; Check what type of event was generated.

IF event.type EQ "CLICK" THEN BEGIN     ; CLICK event

; Make sure that it is a double click.  Single clicks are ignored.

   IF event.clicks EQ 1 THEN RETURN, 0

; Get the list of data base items that are in the selection list box.

   ptr = self.select_id->get_value ()

; Find out which item the user double clicked on in the list widget

   item = (*ptr) [event.index]

; Add the item into the list or selected database fields

   self.search_id->add_search_field, item

; Were done.

   RETURN, 0

ENDIF

IF event.type EQ "CANCEL" THEN BEGIN       ; CANCEL event

; Clear any stored database item names.

   self.search_id->del_all_field

; Were done.

   RETURN, 0

ENDIF

IF event.type EQ "SELECT" THEN BEGIN       ; SELECT event

; Get the list of data base items that are in the selection list box.

   ptr = self.select_id->get_value ()

; Loop to add each selected item into the list of selected database fields.

   FOR i = 0, event.num - 1 DO BEGIN

; Get the next database field name from the list widget

      item = (*ptr) [event.index + i]

; Add the item into the list or selected database fields

      self.search_id->add_search_field, item

   ENDFOR

; Were done.

   RETURN, 0

ENDIF

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION ecat_search::init,     $ ; The compound widget ECAT_SEARCH INIT method..
   parent,                      $ ; The parent widget.  Required for all compound widgets.
   REALIZE = realize,           $ ; When set, causes the widget to automaticly be realized.
   DB_TOOLS = db_tools,         $ ; Pointer to a database object.
   _EXTRA = extra,              $ ; Passes along extra keywords to the text widget.
   DB_LIST  = db_list,          $ ; List of possible databases to search.
   DATABASE = database            ; Name of default database to interogate.

; Call the default widget intitialization routine

res = self->def_widget_obj::init (parent, _EXTRA = extra, COLUMN = 1, ROW = 0)

   ; Check keyword values.

IF N_ELEMENTS (database) EQ 0 THEN database = ""

; Check if a valid database object pointer was passed to us.

IF NOT OBJ_VALID (db_tools) THEN BEGIN

   MESSAGE, "Object started without valid database pointer.  Exiting.", /INFO

   RETURN, 0

ENDIF

; Check that a list of database names was passed to us.  There has to be at least
; one name in the list for this object to work.

IF N_ELEMENTS (db_list) EQ 0 THEN BEGIN

   MESSAGE, "Object started without list of databases to create " + $
            "search queries for.  Exiting.",                         $
            /INFO

   RETURN, 0

ENDIF

; Populate the object.

; Store the list of allowed databases in the object..
self.db_list = PTR_NEW (STRUPCASE (db_list))


; Check if database is defined.  If it is not, then set it to the 0th element of the
; db_list array.  If it is defined, then make sure that is is the same as one of
; the elements of the db_list array.
IF STRLEN (database) GT 0 THEN BEGIN

   ; Make sure database is all in caps.
   database = STRUPCASE (database)

   ; Check to make sure the requested database is in the list of databases.
   r = WHERE (*self.db_list EQ database)

   ; If we found database in the list of databases, then store it in the
   ; object.  Otherwise return an error.
   IF r[0] NE -1 THEN BEGIN

      self.database = database

   ENDIF ELSE BEGIN

      MESSAGE, "Requested default database is not in the list of available " + $
               "databases.  Exiting.",                                         $
               /INFO

      RETURN, 0

   ENDELSE


ENDIF ELSE BEGIN

   self.database = (*self.db_list) [0]

ENDELSE

self.db_tools = db_tools

   ; Create the widgets.

; Set desc_1 to a descriptive string describing the use dababase field selection
; widget.

desc_1 = "Select individual database fields From the list below."

; Set desc_2 to a descriptive string describing the use of text entry widget.

desc_2 = "OR enter a search string to query the database:"

; Set desc_3 to a descriptive string to briefly describe database field query widgets.

desc_3 = "Use the select button on the left to define the query operation"

self.lbl_id = WIDGET_LABEL ( self.align,                $
                             VALUE =  self.title,       $
                             FONT =  self.buttonfnt,    $
                             /FRAME                     $
                           )

; Create a base to hold the text and buttons to select which database should be
; Querried.
db_sel= WIDGET_BASE (self.align, /COLUMN, /ALIGN_LEFT)

tmp   = WIDGET_LABEL (db_sel,                                                           $
                      VALUE = 'Please select which database you would like to query:',  $
                      FONT  = self.buttonfnt                                            $
                      )

b_base= WIDGET_BASE (db_sel, /EXCLUSIVE, /COLUMN)

n_db_list  = N_ELEMENTS (*self.db_list)
button_id  = LONARR (n_db_list)

; Create one radio button of each database in the list of available databases.
FOR i = 0, n_db_list - 1 DO BEGIN

    db_name = (*self.db_list) [i]

    button_id [i] = WIDGET_BUTTON (b_base,                                        $
                                   VALUE = db_name,                               $
                                   FONT = self.buttonfnt,                         $
                                   EVENT_FUNC = 'def_widget_event_handler',       $
                                   UVALUE = {method: "db_btn_event", object:self} $
                                   )


ENDFOR

; Store the list of button widget ID's in the object.
self.db_sel_id = PTR_NEW (button_id)

; Set the correct button for the database that was selected.
r = WHERE (*self.db_list EQ database)

r = r [0]

WIDGET_CONTROL, (*self.db_sel_id) [r], /SET_BUTTON


but  = WIDGET_BASE (self.align, /EXCLUSIVE)

but  = WIDGET_BUTTON (but,                              $
         VALUE = desc_1,                                $
         FONT = self.buttonfnt,                         $
         EVENT_FUNC = 'def_widget_event_handler',       $
         UVALUE = {method: "btn2event", object:self}    $
         )

self.bt2_id = but

slc  = OBJ_NEW ('list_db_item',                              $
         self.align,                                         $
         DATABASE = self.database,                           $
         DB_TOOLS = self.db_tools,                           $
         EXPAND   = 0,                                       $
         /ROW,                                               $
         /NO_LABEL,                                          $
         DESCRIPTION = 1,                                    $
         FLDFONT = self.fieldfont,                           $
         LBLFONT = self.labelfont,                           $
         BTNFONT = self.buttonfnt,                           $
         EVENT_FUNC = 'def_widget_event_handler',            $
         UVALUE = {method: "listevent", object:self}         $
         )

self.select_id = slc

lst = OBJ_NEW ('search_db_item',         $
         self.align,                     $
         TITLE = desc_3,                 $
         FLDFONT = self.fieldfont,       $
         LBLFONT = self.labelfont,       $
         BTNFONT = self.buttonfnt        $
         )

self.search_id = lst

srch = WIDGET_BASE (self.align, /COLUMN)

but  = WIDGET_BASE (srch, /EXCLUSIVE)

but  = WIDGET_BUTTON (but,                              $
         VALUE = desc_2,                                $
         FONT = self.buttonfnt,                         $
         EVENT_FUNC = 'def_widget_event_handler',       $
         UVALUE = {method: "btn1event", object:self}    $
         )

self.bt1_id = but

str  = WIDGET_TEXT  (srch,                              $
         /EDITABLE,                                     $
         FONT = self.fieldfont,                         $
         XSIZE = 40,                                    $
         VALUE = "",                                    $
         EVENT_FUNC = 'def_widget_event_handler',       $
         UVALUE = {method: "applyevent", object:self}   $
         )

self.str_id = str

; Set the db list object to return an empty string as its NULL value.

self.search_id->setproperty, UNDEFINED = ""

btns = WIDGET_BASE (self.align, /ROW)

app  = WIDGET_BUTTON (btns,                             $
         /FRAME,                                        $
         VALUE = 'Apply',                               $
         FONT = self.buttonfnt,                         $
         EVENT_FUNC = 'def_widget_event_handler',       $
         UVALUE = {method: "applyevent", object:self}   $
         )

self.app_id = app

can  = WIDGET_BUTTON (btns,                             $
         /FRAME,                                        $
         VALUE = 'Cancel',                              $
         FONT = self.buttonfnt,                         $
         EVENT_FUNC = 'def_widget_event_handler',       $
         UVALUE = {method: "cancelevent", object:self}  $
         )

self.can_id = can

; Get the item list for the new database.

self.db_tools->get_db_info, database, DB_ITEM = lst

; Explode the item list for the selected database and at the same time create a heap
; variable to reference it.

self.db_item = PTR_NEW (self.db_tools->exp_ptr_items (lst))

; Set the default type of search to database field search

WIDGET_CONTROL, self.bt1_id, SET_BUTTON = 0
WIDGET_CONTROL, self.bt2_id, SET_BUTTON = 1

self.usr_mode = 0

; Realize the widget if the keyword REALIZE has been set.

IF KEYWORD_SET (realize) THEN WIDGET_CONTROL, self.tlb, /REALIZE

RETURN, 1

END

; ------------------------------------------------------------------------------------------------

PRO ecat_search::cleanup

; Get rid of the DB_TOOLS object, but only if we created it ourselves.

IF self.orphan_tools_obj THEN OBJ_DESTROY, self.db_tools

; Get rid of any database item list we may have hanging around

PTR_FREE, self.db_item

; Call the default widget cleanup routine

self->def_widget_obj::cleanup

RETURN

END

; ------------------------------------------------------------------------------------------------

PRO ecat_search_event__define

; The ECAT_SEARCH Event Structure. Sent only if EVENT_PRO or EVENT_FUNC keywords
; have defined an event handler for the top-level base of the compound widget.

event = { ECAT_SEARCH_EVENT,            $ ; The name of the event structure.
          INHERITS DEF_WIDGET_EVENT,    $ ; Default Widget Events Structure
          DB:         "",               $ ; Database to apply the search string to.
          SRCH_STRING:"",               $ ; The search string to use for searching the database.
          VALUE:      "",               $ ; Obsolete, exist only for testing
          TYPE:       0                 $ ; Event Type: 0 CANCEL, 1 OK, 2 APPLY.
        }

END

; ------------------------------------------------------------------------------------------------

PRO ecat_search__define

obj = { ECAT_SEARCH,            $ ; The object class name.
        str_id: 0L,             $ ; The text widget ID containing the search string.
        can_id: 0L,             $ ; The cancel button widget ID.
        app_id: 0L,             $ ; The apply button widget ID.
        bt1_id: 0L,             $ ; Select Button 1
        bt2_id: 0L,             $ ; Select Button 2
        db_tools : OBJ_NEW (),  $ ; Database tools object
        orphan_tools_obj: 0,    $ ; Flag to indicate whether to we created our own db_tools object.
        usr_mode : 1,           $ ; Set to one if the user text will be used for db querries.
        db_sel_id: PTR_NEW (),  $ ; Array of db selection buttons IDs.
        select_id: OBJ_NEW (),  $ ; The database item selection widget
        search_id: OBJ_NEW (),  $ ; The database item search widget
        db_list :  PTR_NEW (),  $ ; Array containing the list of possible databases to search.
        db_item :  PTR_NEW (),  $ ; The item list from the selected database.
        database: "",           $ ; The name of the database to query.
        INHERITS DEF_WIDGET_OBJ $ ; Default window object
      }

END
