NAME
   Tk::JBrowseEntry - Full-featured "Combo-box" (Text-entry combined with
   drop-down listbox) derived from Tk::BrowseEntry with many additional
   features and options.

SYNOPSIS
           use Tk;
           use Tk::JBrowseEntry;

           my $mw = MainWindow->new;
           my $var;

           my $widget = $mw->JBrowseEntry(
                   -label => 'Normal:',
                   -variable => \$var,
                   -state => 'normal',
                   -choices => [qw(pigs cows foxes goats)],
                   -width  => 12
           )->pack(
                   -side   => 'top',
                   -pady => '10',
                   -anchor => 'w');

           MainLoop;

DESCRIPTION
   Tk::JBrowseEntry is a derived widget from Tk::BrowseEntry, but adds
   numerous features and options. Among them are hash lists (one set of
   values is displayed for the user, but another is used as data), ability
   to disable either the text entry widget or the listbox, ability to allow
   user to delete items from the list, additional keyboard bindings, and
   much more.

   JBrowseEntry widgets allow one to specify a full combo-box, a "readonly"
   box (text field allows user to type the 1st letter of an item to search
   for, but user may only ultimately select one of the items in the list);
   a "textonly" version (drop-down list and list pattern-matching
   disabled); a "text" version (drop-down list disabled), but the up, down,
   and right arrows will still do text-completion by matching against the
   choices in the list; or a completely disabled widget.

   This widget is similar to other combo-boxes, ie. JComboBox, but has
   better keyboard bindings and allows for quick lookup/search within the
   listbox. pressing <RETURN> in entry field displays the drop-down box
   with the first entry most closly matching whatever's in the entry field
   highlighted. Pressing <RETURN> or <SPACE> in the listbox selects the
   highlighted entry and copies it to the text field and removes the
   listbox. <ESC> removes the listbox from view. <UP> and <DOWN> arrows
   work the listbox as well as pressing a key, which will move the
   highlight to the next item starting with that letter/number, etc. <UP>
   and <DOWN> arrows pressed within the entry field circle through the
   various list options as well (unless "-state" is set to 'textonly'). Set
   "-state" to "text" to disable the drop-down list, but allow <UP> and
   <DOWN> to cycle among the choices. Setting "-state" to 'textonly'
   completely hides the choices list from the user - he must type in his
   choice just like a normal entry widget.

   One may also specify whether or not the button which activates the
   drop-down list via the mouse can take focus or not (-btntakesfocus) or
   whether the widget itself can take focus or is skipped in the focusing
   order. The developer can also specify alternate bitmap images for the
   button (-arrowimage and / or -farrowimage). The developer can also
   specify the maximum length of the drop-down list such that if more than
   that number of items is added, a vertical scrollbar is automatically
   added (-height). A fixed width in characters (-width) can be specified,
   or the widget can be allowed to resize itself to the width of the
   longest string in the list. The listbox and text entry field are
   automatically kept to the same width.

   One can optionally specify a label (-label), similar to the "LabEntry"
   widget. By default, the label appears packed to the left of the widget.
   The positioning can be specified via the "-labelPack" option. For
   example, to position the label above the widget, use "-labelPack =>
   [-side => 'top']".

EXAMPLES
    It is easiest to illustrate this widget's capabilities via examples:

    use Tk;
    use Tk::JBrowseEntry;

    $MainWin = MainWindow->new;

    #SET UP SOME DEFAULT VALUES.

    $dbname1 = 'cows';
    $dbname2 = 'foxes';
    $dbname3 = 'goats';
    $dbname5 = 'default';

    #HERE'S A NORMAL COMBO-BOX.

    $jb1 = $MainWin->JBrowseEntry(
           -label => 'Normal:',
           -variable => \$dbname1,
           -state => 'normal',
           -choices => [qw(pigs cows foxes goats)],
           -width  => 12);
    $jb1->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #THIS ONE HAS THE DROP-DOWN LIST DISABLED.

    $jb2 = $MainWin->JBrowseEntry(
           -label => 'TextOnly:',
           -variable => \$dbname2,
           -state => 'text',
           -choices => [qw(pigs cows foxes goats)],
           -width  => 12);
    $jb2->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #THIS ONE'S "READONLY" (USER MUST PICK FROM THE LIST, TEXT BOX ALLOWS QUICK
    #SEARCH.

    $jb3 = $MainWin->JBrowseEntry(
           -label => 'ReadOnly:',
           -variable => \$dbname3,
           -choices => [qw(pigs cows foxes goats)],
           -state => 'readonly',
           -width  => 12);
    $jb3->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #THIS ONE'S COMPLETELY DISABLED!

    $jb4 = $MainWin->JBrowseEntry(
           -label => 'Disabled:',
           -variable => \$dbname3,
           -state => 'disabled',
           -choices => [qw(pigs cows foxes goats)],
           -width  => 12);
    $jb4->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #HERE'S ONE WITH A SCROLLBAR (NOTE THE "-height" ATTRIBUTE).

    $jb5 = $MainWin->JBrowseEntry(
           -label => 'Scrolled List:',
           -width => 12,
           -default => $dbname5,
           -height => 4,
           -variable => \$dbname5,
           -browsecmd => sub {print "-browsecmd!\n";},
           -listcmd => sub {print "-listcmd!\n";},
           -state => 'normal',
           -choices => [qw(pigs cows foxes goats horses sheep dogs cats ardvarks default)]);
    $jb5->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #HERE'S ONE THAT THE BUTTON TAKES KEYBOARD FOCUS.

    $jb6 = $MainWin->JBrowseEntry(
           -label => 'Button Focus:',
           -btntakesfocus => 1,
           -arrowimage => $MainWin->Getimage('balArrow'),   #SPECIFY A DIFFERENT BUTTON IMAGE.
           -farrowimage => $MainWin->Getimage('cbxarrow'),  #OPTIONAL 2ND IMAGE FOR BUTTON WHEN FOCUSED.
           -width => 12,
           -height => 4,
           -variable => \$dbname6,
           -browsecmd => sub {print "-browsecmd!\n";},
           -listcmd => sub {print "-listcmd!\n";},
           -state => 'normal',
           -choices => [qw(pigs cows foxes goats horses sheep dogs cats ardvarks default)]);
    $jb6->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    #HERE'S ONE THAT DOWS NOT TAKE KEYBOARD FOCUS.

    $jb7 = $MainWin->JBrowseEntry(
           -label => 'Skip Focus:',
           -takefocus => 0,
           -width => 12,
           -height => 4,
           -variable => \$dbname7,
           -browsecmd => sub {print "-browsecmd!\n";},
           -listcmd => sub {print "-listcmd!\n";},
           -state => 'normal',
           -choices => [qw(pigs cows foxes goats horses sheep dogs cats ardvarks default)]);
    $jb7->pack(
           -side   => 'top', -pady => '10', -anchor => 'w');

    $jb7->choices([qw(First Second Fifth Sixth)]);   #REPLACE LIST CHOICES!
    $jb7->insert(2, 'Third', 'Fourth');              #ADD MORE AFTER 1ST 2.
    $jb7->insert('end', [qw(Seventh Oops Eighth)]);  #ADD STILL MORE AT END.
    $jb7->delete(7);                                 #REMOVE ONE.

    $b = $MainWin->Button(-text => 'Quit', -command => sub {exit(); });
    $b->pack(-side => 'top');
    $jb1->focus;   #PICK ONE TO START WITH KEYBOARD FOCUS.

    MainLoop;

SEE ALSO
   Tk::JComboBox Tk::BrowseEntry Tk::Listbox Tk::Entry

WIDGET-SPECIFIC OPTIONS
   -state => *normal | readonly | text | textonly | disabled*
       Default: normal

       JBrowseEntry supports 5 different states:

           *normal*: Default operation -- Both text entry field and
           drop-down list button function normally.

           *readonly*: Drop-down list functions normally. When text entry
           field has focus, user may type in a letter, and the drop-down
           list immediately drops down and the first/ next matching item
           becomes highlighted. The user must ultimately select from the
           list of valid entries and may not enter anything else.

           *text*: Text entry functions normally, but drop-down list button
           is disabled. User must type in an entry or use the up and down
           arrows to choose from among the list items.

           *textonly*: Similar to "text": Text entry functions normally,
           but drop-down list button is disabled. User must type in an
           entry. The list choices are completely hidden from the user.

           *disabled*: Widget is completely disabled and greyed out. It
           will not activate or take focus.

   -altbinding
       Allows one to specify alternate binding schema for certain keys.
       Each binding pair may be separated by a comma, semicolon, colon,
       space, or virtical bar. Case is insensitive. Currently valid values
       are:

       "Return=Go" - causes [Return] key to roll up the drop-down list and
       invoke the *-browsecmd* callback, if any.

       "Return=NonEmptyGo" - same as "Return=Go" if the text field is
       non-empty, otherwises pops up the drop-down list.

       "Return=SingleGo" - same as "Return=Go" if there are no choices in
       the drop-down list (instead of popping up the drop-down list).

       "Return=Next" - causes pressing the [Return] key to advance the
       focus to the next widget in the main window.

       "Right=NoSearch" - Do not complete the text in the text field with
       the next matching value found in the choices list when the
       [Right-arrow] key is pressed in the entry field, rather leave it
       unchanged.

       "Down=Popup" - causes the [Down-arrow] key pressed in the entry
       field to pop up the selection listbox. Useful particularly if the
       [arrow-button] isn't displayed, ie. (*-nobutton* => 1) and/or the
       [Return] key is bound with an *-altbinding*, etc. to do something
       other than pop up the drop-down list.

       "Nolistbox=actions" - causes certain *actions* to NOT invoke the
       *-browsecmd* callback when activated within the listbox widget, ie.
       "Nolistbox=listbox.space" means don't invoke *-browsecmd* callback
       if <spacebar> pressed in the listbox. Valid values are
       ([listbox.]{space|return|button1|*button1|mod[.{shift|Control|alt|*}
       -]button1}:
       "space,button1,return,mod.Shift-button1,mod.Control-button1,mod.Alt-
       button1,mod,*button1", etc. Multiple values can be separated by
       commas. "mod" means any modifier (Shift|Control|Alt), "*button1"
       means button1 regardless of modifier.

       "Tab=PopList" - Normally, if the [Tab] key is pressed while the
       drop-down list is displayed, the focus simply returns to the text
       entry field and the listbox remains displayed. Modern combo-boxes
       generally don't do this and many users don't expect it. Specifying
       "Tab=PopList" makes Tk::JBrowseEntry behave like most modern
       combo-boxes by simply undisplaying the drop-down list and restoring
       focus to the text entry field. Either way, the listbox is
       undisplayed anyway when the JBrowseEntry widget itself goes out of
       focus, or either the [Enter] or [Esc] key is pressed.

       "Down=None", "Up=None", "Right=None", "Esc=None", "Return=None",
       "Space=None" - causes pressing that respective key to NOT perform
       it's default binding action. User can still add their own bindings
       within their calling program though.

   -arrowimage
       Allows one to specify an image for the the button which activates
       the drop-down list when the button has the keyboard focus. The
       default is: $MainWin->Getimage('cbxarrow') on Linux and a custom
       bitmap on M$-Windows. Also see the "-farrowimage" option below, as
       well as the "-arrowimage" option under Standard BrowseEntry options
       for more details. On Linux, this is used regardless of the focus
       status of the button, which is indicated by the border, unless a
       "-farrowimage" image is specified. On M$-Windows, a separate custom
       bitmap is provided for the focused version, since Windows does not
       change the border color when the button takes focus.

   -browse
       Adds several additional triggering events which invoke the
       -browsecmd callback: entry.tab, frame.tab, and
       key.<character-typed>, if set to 1. Default is 0. This likely is
       rarely needed in practice, but allows the calling program to know
       whenever a key is typed into the entry field or if the field is
       tabbed away from. The one case the author uses this option on is the
       "drive-letter" field in the M$-Windows version of his
       Tk::JFileDialog widget.

   -browsecmd
       Specifies a callback function to call when a selection is made in
       the popped up listbox. It is passed the widget and the text of the
       entry selected. This function is called after the entry variable has
       been assigned the value, (so the programmer can validate and
       override the user's entry if desired).

       The function is passed the widget reference itself (self), the
       content of the entry field (not necessarily equal to the -variable
       reference value), and the triggering "event" as described below.

       Specific cases (events) where it is invoked:
       entry.[-mod.{Shift|Control|Alt}]return[.{go|browse}],
       listbox.return, listbox.space, or
       listbox.[-mod.{Shift|Control|Alt}]button1. If -browse is set to 1,
       then additional triggering events are: entry.tab, frame.tab, and
       key.<character-typed>.

   -btntakesfocus
       The drop-down list button is normally activated with the mouse and
       is skipped in the focusing circuit. If this option is set, then the
       button will take keyboard focus. Pressing <Return>, <Spacebar>, or
       <Downarrow> will cause the list to be dropped down, repeating causes
       the list to be removed again. Normally, the text entry widget
       receives the keyboard focus. This option can be used in combination
       with "-takefocus" so that either the text entry widget, the button,
       or both or neither receive keyboard focus. If both options are set,
       the entry field first receives focus, then pressing <Tab> causes the
       button to be focused.

   -deleteitemsok
       If set, allows user to delete individual items in the drop-down list
       by pressing the <Delete> key to delete the current (active) item. No
       effect if the state is "text" or "textonly".

   -deletecmd
       (ADDED v4.9): Specifies a callback function to call when the user
       deletes an entry (if -deleteitemsok is set to true) in the popped up
       listbox. It is passed the widget and either the index of the entry
       being deleted OR -1. This function is called BOTH before AND after
       the entry is deleted. The entry parameter is -1 on the second call,
       and the first call if $_[1] (the index to be deleted) >= 0, the
       function should return false/undef to permit the delete or true to
       SUPPRESS the delete (in which case, the callback will NOT be called
       a second time)! No effect if the state is "text" or "textonly".

   -farrowimage
       Allows one to specify a second, alternate bitmap for the image on
       the button which activates the drop-down list when the button has
       the keyboard focus. The default is to use the "-arrowimage" image,
       EXCEPT in M$-Windows, in which case, the default remains the default
       "focused" bitmap, since Windows does not use a focus border, but
       rather, the image itself must change to indicate focus status. See
       the "-arrowimage" option under Standard BrowseEntry options for more
       details. The default image for Linux is:
       $MainWin->Getimage('cbxarrow') and a custom bitmap for M$-Windows.

   -labelPack
       Specify alternate packing options for the label. The default is:
       "[-side => 'left', -anchor => 'e']". The argument is an arrayref.
       Note: if no label is specified, none is packed or displayed.

   -labelrelief
       Default "flat"

       Allow relief of the label portion of the widget to be specified.

   -listcmd
       Specifies a callback function to call when the button next to the
       entry is pressed to popup the choices in the listbox. This is called
       before popping up the listbox, so can be used to populate the
       entries in the listbox.

   -listfont
       Specify an alternate font for the text in the listbox. Use "-font"
       to change the text of the text entry field. For best results,
       "-font" and "-listfont" should specify fonts of similar size.

   -listrelief
       Specifies relief for the drop-down list (default is "sunken").

   -listwidth
       Specifies the width of the popup listbox.

   -nobutton
       Default 0 (display the button) NOTE: Regardless of setting, the
       button is not displayed if the state is "text" or "textonly".

       Prevents drop-down list button from being displayed if set to 1
       (true).

   -noselecttext
       Normally, when the widget has the focus and is set by listbox
       selection, the text will then be "selected" (highlighted and in the
       cut-buffer). Some consider this annoying. Setting this option will
       cause the text to not be selected. The user can still select the
       text themself, ie. for pasting somewhere else.

   -tabcomplete
       If set to "1", pressing the "<Tab>" key will cause the string in the
       entry field to be "auto-completed" to the next matching item in the
       list. If there is no match, the typed text is not changed. If it
       already matches a list item, then the listbox is removed from view
       and keyboard focus transfers to the next widget. If set to "2" and
       there is no match in the list, then entry is set to the default
       value or empty string. If set to "0", focus is simply advanced to
       the next widget in the main window.

INHERITED OPTIONS
   -choices
       Specifies the list of initial choices to pop up. This is a reference
       to an array or hash of strings specifying the choices. If a
       *hashref* is specified, the keys represent the actual data values
       and the values represent the corresponding values the user sees
       displayed in the listbox. NOTE: If a *hashref* is specified, the
       -variable should be initialized to one of the hash VALUES rather
       than it's corresponding key.

   -colorstate
       Depreciated -- Appears to force the background of the entry widget
       on the Unix version to "grey95" if state is normal and a
       "-background" color is not specified.

   -height
       Specify the maximum number of items to be displayed in the listbox
       before a vertical scrollbar is automatically added. Default is
       infinity (listbox will not be given a scrollbar regardless of the
       number of items added).

   -maxwidth
       Specifies the maximum width the entry and listbox widgets can expand
       to in characters. The default is zero, meaning expand to the width
       to accomodate the widest string in the list.

   -variable
       Specifies a scalar reference to the variable in which the entered
       value is to be stored/retrieved (tied).

   -width
       The number of characters (average if proportional font used) wide to
       make the entry field. The drop-down list will be set the same width
       as the entry widget plus the width of the button. If not specified,
       the default is to calculate the width to the width of the longest
       item in the choices list and if items are later added or removed the
       width will be recalculated.

WIDGET METHODS
   $widget->activate(index)
       activate() invokes the activate() option on the listbox to make the
       item with the index specified by the first argument "active". Unless
       a second argument is passed containing a false value, the value of
       the "-textvariable" variable is also set to this now active value.

   $widget->choices([listref])
       Sets the drop-down list listbox to the list of values referenced by
       *listref*, if specified. Returns the current list of choices in the
       listbox if no arguments provided. If a *hashref* is specified, the
       keys represent the actual data values and the values represent the
       corresponding values the user sees displayed in the listbox. NOTE:
       If a *hashref* is specified, the -variable should be initialized to
       one of the hash VALUES rather than it's corresponding key.

   $widget->curselection()
       Returns the currently-selected element in the listbox, if any,
       otherwise, undef.

   $widget->delete(first [, last])
       Deletes one or more elements of the listbox. First and last are
       indices specifying the first and last elements in the range to
       delete. If last isn't specified it defaults to first, i.e. a single
       element is deleted.

   $widget->delete_byvalue(hashkey)
       Deletes one or more elements of the listbox. "hashkey" specifies the
       element to be deleted by the value visible to the user.

   $widget->reference(hashkey)
       Returns the value (displayed in the listbox) that corresponds to the
       choice key specified by "hashkey". If the key is not one of the
       valid choices or the choices are a list instead of a hash, then the
       hashkey itself is returned. If the choices are a list rather than a
       hash, then the value is returned as is. Returns undef on error.

   $widget->dereference(hashvalue)
       Returns the actual option key value that corresponds to the choice
       value displayed in the listbox. (undef if there is none). (Opposite
       of reference() and referenceOnly(). Use this function on the
       -variable reference variable to get the actual data (hash key),
       since the reference variable will contain the VALUE displayed to the
       user! If the choices are a list rather than a hash, then the value
       is returned as is. Returns undef on error.

   $widget->dereferenceOnly(hashkey)
       Returns 1 if the key specified by "hashkey" is one of the valid
       choices and the list of choices is a hash, otherwise undef is
       returned.

   $widget->get_hashref_byname()
       Returns a reference to the current hash of choices (keyed by the
       option visable to the user) if the choice list is a hash (reversed
       from the hash passed to choices()), otherwise, undef is returned.

   $widget->get_hashref_byvalue()
       Returns a reference to the current hash of choices (keyed by actual
       option value) if the choice list is a hash (same as the hash passed
       to choices()), otherwise, undef is returned.

   $widget->get([first [, last])
       get() with no arguments returns the current value of the
       "-textvariable" variable. If any arguments are passed, they are
       passed directly to the listbox->get() function, ie. "0", "end" to
       return all values of the listbox. For choice hashes, the value
       returned is what is displayed to the user. The arguments are
       indices.

   $widget->get_icursor(index)
       Return the location of *index* in the *text-entry* field. Values
       known to be valid are: "insert" and "end", which return the
       character position of the insertion cursor and the location of the
       "end" of the current input string (ie. it's length). The cursor is
       set by the $widget->icursor function.

   $widget->get_index(value)
       Returns the index number in the list (zero-based) that can be used
       by get() of the value specified by "value", or undef if "value" is
       not in the list of choices. If the choice list is a hash, then
       "value" should be the value displayed (stored in the -variable
       reference variable), not the hash key. This function is the reverse
       of the get() function.

   $widget->hasreference(hashkey)
       Returns the value (displayed in the listbox) that corresponds to the
       choice key specified by "hashkey". If the key is not one of the
       valid choices or the choices are a list instead of a hash, then
       undef is returned.

   $widget->icursor(index)
       Sets the location of the text-entry field's text cursor to *index*.
       Valid values are numeric (zero for beginning) and "end" for placing
       the cursor at the end of the text. The index can be retrieved by
       using the $widget->get_icursor(index) function.

   $widget->index(index)
       Invokes and returns the result of the listbox->index() function.

   $widget->insert(index, [item | list | listref | hashref])
       Inserts one or more elements in the list just before the element
       given by index. If *index* is specified as "end" then the new
       elements are added to the end of the list. List can be a reference
       to a list (*listref*). If a hash reference is specified, then the
       values are displayed to the user in the drop-down list, but the
       values returned by the "-textvariable" variable or the get()
       function are the corresponding hash key(s).

   $widget->selectionRange(index1, index2)
       Select (highlight) the text in the text-entry field between *index1*
       and *index2*. Valid values are numeric (zero for beginning),
       "insert" and "end".

   $widget->size()
       Invokes and returns the result of the listbox size() function (the
       number of items in the list).

   $widget->state([normal | readonly | text | textonly | disabled])
       Get or set the state of the widget.

   $widget->Popdown([nofocusrestore])
       Roll up (undisplay) the drop-down list. If *nofocusrestore* is
       specified and is true, no attempt will be made to refocus the
       previous widget focused when the drop-down list was popped up. This
       is useful when the developer intends to immediately focus somewhere
       else.

   $widget->PressButton()
       Activates drop-down list as if user pressed the button (unless state
       is "text" or "textonly" or "disabled". Returns 1 if drop-down list
       activated, zero otherwise. If the drop-down list is already visible,
       then removes it (pops it back down) and returns zero. Available in
       versions 5.0 and later.

AUTHOR
   Jim Turner, "<https://metacpan.org/author/TURNERJW>".

COPYRIGHT
   Copyright (c) 2001-2018 Jim Turner "<mailto:[email protected]>". All
   rights reserved.

   This program is free software; you can redistribute it and/or modify it
   under the same terms as Perl itself.

   This is a derived work from Tk::Listbox and Tk::HList.

   This code may be distributed under the same conditions as Perl itself.

   This is a derived work from Tk::BrowseEntry. Tk::BrowseEntry is
   copyrighted by Rajappa Iyer