Book HomeMastering Perl/TkSearch this book

23.6. The BrowseEntry Widget

BrowseEntry is a composite widget created to be like a combo box (also known as a drop-down listbox on some platforms) using an Entry widget, a Listbox, and a small arrow button. The combination of these three widgets in the BrowseEntry is very powerful.

Before we list the options and methods for a BrowseEntry, let's look at an example:

use Tk;
use Tk::ROText;
use Tk::BrowseEntry;

$mw = MainWindow->new(-title => "Text search using BrowseEntry");

# Create Browse Entry to enter search text in, and save off 
# already entered text that you've searched for.
$f = $mw->Frame(-relief => 'ridge', -borderwidth => 2)
  ->pack(-fill => 'x');
# Use ROText so user can't change speech
$t = $mw->Scrolled('ROText', -scrollbars => 'osoe')
  ->pack(-expand => 1, -fill => 'both');

$t->insert('end', <<'EOD'
"Give Me Liberty or Give Me Death"
March 23, 1775
By Patrick Henry
No man thinks more highly than I do of the patriotism, as well as abilities, of the 
very worthy gentlemen who have just addressed the house. But different
<snipped...> I 
know not what course others may take; but as for me, give me liberty or give me death!

EOD
);

# define a new tag to use on selected text 
# (making it look just like normal selection)
# This way the Text widget doesn't need focus to show selection
$t->tagConfigure('curSel', -background => $t->cget(-selectbackground),
                  -borderwidth => $t->cget(-selectborderwidth),
                  -foreground => $t->cget(-selectforeground));

my $search_string = "";

# If user selects item from list manually, invoke do_search
$be = $f->BrowseEntry(-variable => \$search_string,
                      -browsecmd => \&do_search)->pack(-side => 'left');
# If user types in word and hits return, invoke do_search
$be->bind("<Return>", \&do_search);
$be->focus;  # Start w/focus on BrowseEntry

# Clicking the Search button will invoke do_search
$f->Button(-text => 'Search', -command => \&do_search)
    ->pack(-side => 'left');
$f->Button(-text => 'Exit', -command => \&do_exit)
    ->pack(-side => 'right');

sub do_search {
  # Add search string to list if it's not already there
  if (! exists $searches{$search_string}) {
    $be->insert('end', $search_string);
  }
  $searches{$search_string}++;
  
  # Calculate where to search from, and what to highlight next  
  my $startindex = 'insert';
  if (defined $t->tagRanges('curSel')) { 
    $startindex = 'curSel.first + 1 chars'; 
  }    
  my $index = $t->search('-nocase', $search_string, $startindex);
  if ($index ne '') {
    $t->tagRemove('curSel', '1.0', 'end');
    my $endindex = "$index + " .  (length $search_string) . " chars";
    $t->tagAdd('curSel', $index, $endindex);
    $t->see($index);
  } else { $mw->bell; }
  
  $be->selectionRange(0, 'end'); # Select word we just typed/selected
}

# print stats on searching before we exit.
sub do_exit {
  print "Count	Word\n";
  foreach (sort keys %searches) {
    print "$searches{$_}	$_\n";
  }  
  exit;
}

MainLoop;

Take a look at Figure 23-13 to see the screenshot of this application. The BrowseEntry is in the upper-left corner. We have shown it with the list part of the BrowseEntry down (after the down arrow button has been pressed).

Figure 23-13

Figure 23-13. BrowseEntry used to perform searches in a Text widget

In this example, we are using the BrowseEntry with mostly default settings. We added a callback so that when the user selected an entry from the list manually, the search subroutine was invoked as well. The easiest way to know what the user has selected/typed is to use the -variable option. Most of the code for this example has to do with figuring out where the word is in the Text widget.

The BrowseEntry supports all the options a LabEntry does (see Chapter 5, "Label and Entry Widgets"), except -textvariable. Additional BrowseEntry options are:

-arrowimage => image
This option changes the picture on the little button.

-browsecmd => callback
This callback will be invoked whenever the user selects something from the list. BrowseEntry already performs the work to display the new selection in the edit box.

-choices => list
You can put choices in the list using this option. Examples are: -choices => [ qw/one two three/ ] or -choices => @init_choices. You can also add items to the list using the insert method ($be->insert('end', 'newchoice'); ).

-listcmd => callback
Specify a callback to be invoked when the arrow button is pushed. This will be called before the list is displayed, so if you need to change the contents of the drop-down list, this is a great place to do so.

-listwidth => amount
The width of the popup listbox. The listbox will not automatically grow to fit your choices if you have long strings in it.

-variable => \$scalar
Place the user's selection in $scalar.

-state => 'normal' | 'readonly' | 'disabled'
A state of 'normal' that the user can type in new entries and select entries from the list. A 'readonly' state limits the user to only selecting items from the list. A state of 'disabled' will not allow any interaction with the user at all.

In addition to all the methods of Tk::Entry, the BrowseEntry widget supports its own insert and delete methods:

$be->insert('index', 'string');
$be->delete('index1', 'index2');

The insert method adds a new item into the list at the specified index. The delete method removes list entries that are between the two indexes.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.