# BrowseEntry is a stripped down version of ComboBox.tcl from Tix4.0
$VERSION = '3.030'; # $Id: //depot/Tk8/Tixish/BrowseEntry.pm#30 $
Construct Tk
::Widget
'BrowseEntry';
$w->SUPER::Populate
($args);
# entry widget and arrow button
my $lpack = delete $args->{-labelPack
};
if (not defined $lpack) {
$lpack = [-side
=> 'left', -anchor
=> 'e'];
my $e = $w->LabEntry(-labelPack
=> $lpack,
-label
=> delete $args->{-label
},
-textvariable
=> \
$var,);
my $b = $w->Button(-bitmap
=> '@' . Tk
->findINC('cbxarrow.xbm'));
$w->Advertise('entry' => $e);
$w->Advertise('arrow' => $b);
$b->pack(-side
=> 'right', -padx
=> 1);
$e->pack(-side
=> 'right', -fill
=> 'x', -expand
=> 1, -padx
=> 1);
# popup shell for listbox with values.
my $c = $w->Toplevel(-bd
=> 2, -relief
=> 'raised');
my $sl = $c->Scrolled( qw
/Listbox -selectmode browse -scrollbars oe/ );
$w->Advertise('choices' => $c);
$w->Advertise('slistbox' => $sl);
$sl->pack(-expand
=> 1, -fill
=> 'both');
$w->Delegates('insert' => $sl, 'delete' => $sl, get
=> $sl, DEFAULT
=> $e);
-listwidth
=> [qw
/PASSIVE listWidth ListWidth/, undef],
-listcmd
=> [qw
/CALLBACK listCmd ListCmd/, undef],
-browsecmd
=> [qw
/CALLBACK browseCmd BrowseCmd/, undef],
-choices
=> [qw
/METHOD choices Choices/, undef],
-state => [qw
/METHOD state State normal/],
-arrowimage
=> [ {-image
=> $b}, qw
/arrowImage ArrowImage/, undef],
-variable
=> '-textvariable',
-colorstate
=> [qw
/PASSIVE colorState ColorState/, undef],
-command
=> '-browsecmd',
my $e = $w->Subwidget('entry');
my $b = $w->Subwidget('arrow');
$w->bindtags([$w, 'Tk::BrowseEntry', $w->toplevel, 'all']);
$e->bindtags([$e, $e->toplevel, 'all']);
# bindings for the button and entry
$b->bind('<1>',[$w,'BtnDown']);
$b->toplevel->bind('<ButtonRelease-1>',[$w,'ButtonHack']);
$b->bind('<space>',[$w,'space']);
my $sl = $w->Subwidget('slistbox');
my $l = $sl->Subwidget('listbox');
$l->bind('<ButtonRelease-1>',[$w,'ListboxRelease',Ev
('x'),Ev
('y')]);
$l->bind('<Escape>' => [$w,'LbClose']);
$l->bind('<Return>' => [$w,'Return',$l]);
# allow click outside the popped up listbox to pop it down.
$w->bind('<1>','BtnDown');
$w->{'savefocus'} = $w->focusCurrent;
$w->Subwidget('slistbox')->focus;
my($x, $y) = $l->bbox($l->curselection);
return if $w->cget( '-state' ) eq 'disabled';
$w->Callback(-listcmd
=> $w);
my $e = $w->Subwidget('entry');
my $c = $w->Subwidget('choices');
my $s = $w->Subwidget('slistbox');
my $a = $w->Subwidget('arrow');
my $y1 = $e->rooty + $e->height + 3;
my $bd = $c->cget(-bd
) + $c->cget(-highlightthickness
);
my $ht = $s->reqheight + 2 * $bd;
if (defined $w->cget(-listwidth
)) {
$width = $w->cget(-listwidth
);
$x2 = $a->rootx + $a->width;
if ($rw > $w->vrootwidth) {
# if listbox is too far right, pull it back to the left
if ($x2 > $w->vrootwidth) {
$x1 = $w->vrootwidth - $width;
# if listbox is too far left, pull it back to the right
# if listbox is below bottom of screen, pull it up.
if ($y2 > $w->vrootheight) {
$y1 = $y1 - $ht - ($e->height - 5);
$c->geometry(sprintf('%dx%d+%d+%d', $rw, $ht, $x1, $y1));
$c->configure(-cursor
=> 'arrow');
# choose value from listbox if appropriate
my $l = $w->Subwidget('slistbox')->Subwidget('listbox');
if ((($x < 0) || ($x > $l->Width)) ||
(($y < 0) || ($y > $l->Height))) {
# mouse was clicked outside the listbox... close the listbox
# select appropriate entry and close the listbox
$w->Callback(-browsecmd
=> $w, $w->Subwidget('entry')->get);
# close the listbox after clearing selection
my $l = $w->Subwidget('slistbox')->Subwidget('listbox');
$l->selection('clear', 0, 'end');
# copy the selection to the entry and close listbox
$w->{'curIndex'} = $index;
my $l = $w->Subwidget('slistbox')->Subwidget('listbox');
my $var_ref = $w->cget( '-textvariable' );
$$var_ref = $l->get($index);
my $sel = $w->Subwidget('slistbox')->Subwidget('listbox')->curselection;
if (defined $flag && ($flag eq 'emptyOK')) {
if ($w->{'savefocus'} && Tk
::Exists
($w->{'savefocus'})) {
$w->{'savefocus'}->focus;
delete $w->{'savefocus'};
my $c = $w->Subwidget('choices');
# This hack is to prevent the ugliness of the arrow being depressed.
my $b = $w->Subwidget('arrow');
if ($w->{'buttonHack'}) {
my $var = $w->cget('-textvariable');
foreach my $val (@
$choices)
$w->insert( 'end', $val);
$old = (@
$choices) ?
$choices->[0] : undef unless exists $hash{$old};
return( $w->get( qw
/0 end/ ) );
my $entry = $w->Subwidget( 'entry' );
my $button = $w->Subwidget( 'arrow' );
if ($w->cget( '-colorstate' )) {
if( $state eq 'normal' ) { # Editable
$color = $w->cget( -background
) || 'lightgray';
$entry->Subwidget( 'entry' )->configure( -background
=> $color );
if( $state eq 'readonly' ) {
$entry->configure( -state => 'disabled' );
$button->configure( -state => 'normal' );
$entry->configure( -state => $state );
$button->configure( -state => $state );
return( $w->{Configure
}{-state} );
$w->{Configure
}{-state} = $state;
$w->_set_edit_state( $state );
$max = $val if $max < $val;
unless( defined $size ) {
$size = _max
( map( length, $w->get( qw
/0 end/ ) ) ) || 0;;
my $lb = $w->Subwidget( 'slistbox' )->Subwidget( 'listbox' );
$w->configure( -width
=> $size );
$lb->configure( -width
=> $size );