
; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::getlabelid

; This method returns the ID of the text widget of the compound widget.

; Check if the no_label flag is set.  If it is then the widget does not have a label and so
; cannot return a label id.

IF self.no_label THEN RETURN, 0

; Otherwise return the ID of the widget label.

RETURN, self.lbl_id

END

; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::get_value

; This method returns the actual value of the compound widget.
; If the widget doesn't have a value for some reason, then the
; undefined value is returned.

IF self.itemlst NE PTR_NEW () THEN BEGIN


   RETURN, self.itemlst

ENDIF ELSE BEGIN

   RETURN, *self.undefined

ENDELSE

END

; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::clickevent, event

; A mouse click was detected in the select widget,

; Check if an event function or event procedure is defined.  If it is then
; we must return an event structure.

IF self.event_func NE "" OR self.event_pro NE "" THEN BEGIN

   compound_event = { LIST_DB_ITEM_EVENT,   $
                      self.tlb,             $
                      event.top,            $
                      0L,                   $
                      event.index,          $
                      event.clicks,         $
                      1,                    $
                      "CLICK"}

   RETURN, compound_event

ENDIF

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::selectevent, event

; The select button was pressed.  Get an array of indexes which correspond to
; list items that are currently selected.

items = WIDGET_INFO (self.lst_id, /LIST_SELECT)

; Check if the select button was pressed with no items selected.  If it was then
; just exit quietly.

IF items [0] EQ -1 THEN RETURN, 0

; Check if an event function or event procedure is defined.  If it is then
; we must return an event structure.

IF self.event_func NE "" OR self.event_pro NE "" THEN BEGIN

   compound_event = { LIST_DB_ITEM_EVENT,   $
                      self.tlb,             $
                      event.top,            $
                      0L,                   $
                      items [0],            $
                      0,                    $
                      N_ELEMENTS (items),   $
                      "SELECT"}

   RETURN, compound_event

ENDIF

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::clearevent, event

; The cancel button was pressed.  This does cause any internal action in
; the widget to occur (but an event may be generated).

; Check if an event function or event procedure is defined.  If it is then
; we must return an event structure.

IF self.event_func NE "" OR self.event_pro NE "" THEN BEGIN

   compound_event = { LIST_DB_ITEM_EVENT,   $
                      self.tlb,        $
                      event.top,      $
                      0L,      $
                      0,        $
                      0,         $
                      0,         $
                      "CANCEL"}

   RETURN, compound_event

ENDIF

RETURN, 0

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item::update

; Check if a dabase name is defined, if not then we have to make sure
; that we hava an open database.

IF self.database EQ "" THEN BEGIN

   IF DB_INFO ('OPEN') EQ 1 THEN BEGIN

; Get the number and name of the open database.

      num      = (DB_ITEM_INFO ('DBNUMBER')) [0]
      database = DB_INFO      ('NAME', num)

; Store the name of the database in the object.

      self.database = database

   ENDIF ELSE BEGIN

;  Oops.  No open database, and no specific databaase requested.
;  Write a message to the selection list.

       WIDGET_CONTROL, self.lst_id, SET_VALUE = 'No Database Is Currently Selected'

       RETURN

   ENDELSE

ENDIF

; Get the all the information that we can about the requested database

self.db_tools->get_db_info, self.database, DB_DESC = db_hdr, DB_ITEM = items

; Add the name of the database into the dbname label widget

WIDGET_CONTROL, self.dbname_id, SET_VALUE = STRUPCASE (self.database)

; Sort out the information about each item.

n_items = db_hdr.n_items

; Check if the expand property has been set.  If it has then we are going have to
; go and expand pointers to child databases into to their individual items.

IF (self.expand) THEN BEGIN

; Expand the pointer items into their individual database items

   lst = self.db_tools->exp_ptr_items (items)

; Combine the item name and database name into a sorted list of items

   names = lst.db_name + '::' + lst.name

; Create a description of each item in

   desc  = lst.description

ENDIF ELSE BEGIN

   names = items.name
   desc  = items.description

ENDELSE

ind   = SORT (names)

names = names [ind]
desc  = desc  [ind]

; Store the names array in the object

PTR_FREE, self.itemlst
self.itemlst = PTR_NEW (names)

; Create a list of values to go in the selection widget corresponding to each
; field in the database.

IF self.description THEN BEGIN

   lst = STRARR (n_items)

   FOR i = 0, n_items - 1 DO BEGIN

      lst [i] = STRING (names [i], desc [i], FORMAT = '(A, T22, A)')

   ENDFOR

ENDIF ELSE lst = names

; Check if the resize flag is set.  If it is then reset the XSIZE of the list
; widget to accomadate the

IF self.resize EQ 1 THEN BEGIN

   self.lst_xsize = MAX (STRLEN (lst)) + 4

   WIDGET_CONTROL, self.lst_id, XSIZE = self.lst_xsize

ENDIF

; Copy the list to the selection widget.

WIDGET_CONTROL, self.lst_id, SET_VALUE = lst

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item::getproperty, $
;
; This method allows you to obtain various properties of
; the compound widget via output keywords.
;

   LST_XSIZE = lst_xsize,      $ ; Maximum number of characters displayed in the list widget.
   DATABASE = database,        $ ; Name of the database to interogate.
   EXPAND = expand,            $ ; Set to 1, when item listing should be expanded to children.
   DESCRIPTION = description,  $ ; Set to TRUE (1) if descriptions are to be displayed.
   RESIZE = resize,            $ ; Set to enable resizing the list widget to accomadate long text.
   VALUE = value,              $ ; The "value" of the compound widget.
   _EXTRA = extra                ; Passes along extra keywords to this method.

; Call the default widget version of this method to get those properties which are common
; to all widgets.

self->def_widget_obj::getproperty, _EXTRA = extra

; Get the properties.

lst_xsize   = self.lst_xsize
database    = self.database
expand      = self.expand
description = self.description
resize      = self.resize
value       = self.value

RETURN

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item::setproperty, $
;
; This method allows you to set various properties of the compound widget.
;
   LST_XSIZE = list_xsize,     $ ; Maximum number of characters displayed in the list widget.
   DATABASE = database,        $ ; Name of the database to interogate.
   EXPAND = expand,            $ ; Set to 1, when item listing should be expanded to children.
   DESCRIPTION = description,  $ ; Set to TRUE (1) if descriptions are to be displayed.
   RESIZE = resize,            $ ; Set to enable resizing the list widget to accomadate long text.
   _EXTRA = extra                ; Passes along extra keywords to this method.

; Call the default widget version of this method to set those properties which are common
; to all widgets.

self->def_widget_obj::setproperty, _EXTRA = extra

; Set the update flag to 0 (FALSE).  If the widget needs to be updated, then
; it will be set to 1 (TRUE)

update = 0

; Set the properties, if needed.


IF N_ELEMENTS (resize) NE 0 THEN self.resize = KEYWORD_SET (resize)


IF N_ELEMENTS (database) NE 0 THEN BEGIN

   self.database = database
   update = 1

ENDIF

IF N_ELEMENTS (description) NE 0 THEN BEGIN

   self.description = KEYWORD_SET (description)
   update = 1

ENDIF

IF N_ELEMENTS (expand) NE 0 THEN BEGIN

   self.expand = KEYWORD_SET (expand)
   update = 1

ENDIF

IF N_ELEMENTS (lst_xsize) NE 0 THEN BEGIN

   self.lst_xsize = lst_xsize

   WIDGET_CONTROL, self.lst_id, XSIZE = lst_xsize

   update = 1

ENDIF

IF update THEN self->update

END

; ------------------------------------------------------------------------------------------------

FUNCTION list_db_item::init,    $ ; The compound widget LIST_DB_ITEM INIT method..
   parent,                      $ ; The parent widget.  Required for all compound widgets.
   NO_LABEL = no_label,         $ ; If set, then the widget will be drawn without a label.
   LST_XSIZE = list_xsize,      $ ; Maximum number of characters displayed in the list widget.
   DATABASE = database,         $ ; Name of the database to interogate.
   DB_TOOLS = db_tools,         $ ; Pointer to a database object.
   EXPAND = expand,             $ ; Set to 1, when item listing should be expanded to children.
   DESCRIPTION = description,   $ ; Set to TRUE (1) if descriptions are to be displayed.
   RESIZE = resize,             $ ; Set to enable resizing the list widget to accomadate long text.
   COLUMN = column,             $ ; Hint to the object that the widget should align in columns.
   ROW = row,                   $ ; Hint to the object that the widget should align in rows.
   _EXTRA = extra                 ; Passes along extra keywords to the text widget.

; Preprocess the row and column keywords.

row    = KEYWORD_SET (row)
column = KEYWORD_SET (column)

; Make sure that either row x/or column is enabled (row is default).

IF row EQ 1 AND column EQ 1 THEN column = 0
IF row EQ 0 AND column EQ 0 THEN row = 1

; Call the default widget intitialization routine

res = self->def_widget_obj::init (parent, _EXTRA = extra, COLUMN = column, ROW = row)

; Check keyword values.

resize = KEYWORD_SET (resize)
IF N_ELEMENTS (value) EQ 0 THEN value = ""
IF N_ELEMENTS (lst_xsize) EQ 0 THEN lst_xsize = 40
IF N_ELEMENTS (database) EQ 0 THEN database = ""
IF N_ELEMENTS (expand) EQ 0 THEN expand = 0
IF N_ELEMENTS (description) EQ 0 THEN description = 0


; Populate the object.

self.database = database
self.expand = expand
self.resize = resize
self.description = description
self.lst_xsize = lst_xsize
self.db_tools  = db_tools

; Create the widgets.

; Check if the no_label flag is set.  If it is not set then create a label
; widget with the title as its value.

IF NOT KEYWORD_SET (no_label) THEN BEGIN

   self.lbl_id = WIDGET_LABEL ( self.tlb, VALUE =  self.title, FONT =  self.buttonfnt)

ENDIF

srch = WIDGET_BASE (self.align, /COLUMN)

db   = WIDGET_LABEL (srch, FONT  = self.buttonfnt, VALUE = 'NO DATABASE SELECTED', /FRAME)

self.dbname_id = db

lst  = WIDGET_LIST  (srch,                                         $
                     /MULTIPLE,                                    $
                     FONT = self.fieldfont,                        $
                     XSIZE = lst_xsize,                            $
                     YSIZE = 10,                                   $
                     VALUE = "",                                   $
                     EVENT_FUNC = 'def_widget_event_handler',      $
                     UVALUE = {method: "clickevent", object:self}  $
                     )

self.lst_id = lst

btns = WIDGET_BASE (self.align, /COLUMN)

sel  = WIDGET_BUTTON (btns,                                         $
                      /FRAME,                                       $
                      VALUE = 'Select',                             $
                      FONT = self.buttonfnt,                        $
                      EVENT_FUNC = 'def_widget_event_handler',      $
                      UVALUE = {method: "selectevent", object:self} $
                      )

self.select_id = sel

can  = WIDGET_BUTTON (btns,                                         $
                      /FRAME,                                       $
                      VALUE = 'Clear Items',                        $
                      FONT = self.buttonfnt,                        $
                      EVENT_FUNC = 'def_widget_event_handler',      $
                      UVALUE = {method: "clearevent", object:self}  $
                      )

self.clear_id = can

self.itemlst = PTR_NEW ()

; Call the update method to complete the initialization

self->update

RETURN, 1

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item::cleanup

; This method makes sure there are not any pointers left on the heap.

OBJ_DESTROY, self.value

; Call the default widget cleanup routine

self->def_widget_obj::cleanup

RETURN

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item_event__define

; The LIST_DB_ITEM 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 = { LIST_DB_ITEM_EVENT,           $ ; The name of the event structure.
          INHERITS DEF_WIDGET_EVENT,    $ ; Default Widget Events Structure
          INDEX:   0,                   $ ; Returns the index of the selected item.
          CLICKS:  0,                   $ ; Returns either 1 or 2 depending on how the item was selected.
          NUM:     0,                   $ ; Returns the number of selected items.
          TYPE:    ""                   $ ; Event type: either "SELECT" or "CANCEL" or "CLICK".
        }

END

; ------------------------------------------------------------------------------------------------

PRO list_db_item__define

obj = { LIST_DB_ITEM,        $ ; The object class name.
        lst_id: 0L,          $ ; The list widget ID containing list of database fields.
        select_id: 0L,       $ ; The select button widget ID.
        clear_id: 0L,        $ ; The clear button widget ID.
        dbname_id: 0L,       $ ; The label widget ID containing the name of the database.
        no_label: 0,         $ ; When set, the widget will not have a label.
        value: OBJ_NEW (),   $ ; The value of the search widget.
        itemlst: PTR_NEW (), $ ; The names of the database items displayed in the list widget.
        lst_xsize:0,         $ ; Maximum number of characters displayed in the list widget.
        database:"",         $ ; Name of the database to interogate.
        db_tools : OBJ_NEW (),$ ; Database tools object
        expand: 0,           $ ; Set to 1, when item listing should be expanded to children.
        resize:0,            $ ; Set to enable resizing the list widget to accomadate long text.
        open:0,              $ ; Flag is set to TRUE (1) if the database is open.
        description:0,       $ ; Set to TRUE (1) if descriptions are to be displayed.
        INHERITS DEF_WIDGET_OBJ $; Default window object.
      }

END