2
2
# BrowseEntry is a stripped down version of ComboBox.tcl from Tix4.0
4
# Some additions by Slaven Rezic <slaven@rezic.de> to make the widget
5
# look like the Windows' Combobox. There are also additional options.
4
8
package Tk::BrowseEntry;
6
10
use vars qw($VERSION);
7
$VERSION = '3.030'; # $Id: //depot/Tk8/Tixish/BrowseEntry.pm#30 $
11
$VERSION = '3.033'; # $Id: //depot/Tk8/Tixish/BrowseEntry.pm#33 $
16
17
use base qw(Tk::Frame);
17
18
Construct Tk::Widget 'BrowseEntry';
22
sub LabEntryWidget { "LabEntry" }
23
sub ButtonWidget { "Button" }
24
sub ListboxWidget { "Listbox" }
20
27
my ($w, $args) = @_;
22
$w->SUPER::Populate($args);
29
$w->Tk::Frame::Populate($args);
24
31
# entry widget and arrow button
25
32
my $lpack = delete $args->{-labelPack};
26
33
if (not defined $lpack) {
27
34
$lpack = [-side => 'left', -anchor => 'e'];
36
$w->{_BE_Style} = delete $args->{-style} || $Tk::platform;
37
my $LabEntry = $w->LabEntryWidget;
38
my $Listbox = $w->ListboxWidget;
39
my $Button = $w->ButtonWidget;
40
# XXX should this be retained?
41
# if (defined $args->{-state} and $args->{-state} eq 'readonly') { # XXX works only at construction time
42
# $LabEntry = "NoSelLabEntry";
43
# require Tk::NoSelLabEntry;
30
my $e = $w->LabEntry(-labelPack => $lpack,
31
-label => delete $args->{-label},
32
-textvariable => \$var,);
33
my $b = $w->Button(-bitmap => '@' . Tk->findINC('cbxarrow.xbm'));
47
my @LabEntry_args = (-textvariable => \$var);
48
if (exists $args->{-label}) {
49
$e = $w->$LabEntry(-labelPack => $lpack,
50
-label => delete $args->{-label},
54
$e = $w->$LabEntry(@LabEntry_args);
56
my $b = $w->$Button(-bitmap => '@' . Tk->findINC($w->{_BE_Style} eq 'MSWin32' ? 'arrowdownwin.xbm' : 'cbxarrow.xbm'));
34
57
$w->Advertise('entry' => $e);
35
58
$w->Advertise('arrow' => $b);
36
59
$b->pack(-side => 'right', -padx => 1);
37
$e->pack(-side => 'right', -fill => 'x', -expand => 1, -padx => 1);
60
$e->pack(-side => 'right', -fill => 'x', -expand => 1); #XXX, -padx => 1);
39
62
# popup shell for listbox with values.
40
my $c = $w->Toplevel(-bd => 2, -relief => 'raised');
63
my $c = $w->Toplevel(-bd => 2,
64
-relief => ($w->{_BE_Style} eq 'MSWin32'
65
? "solid" : "raised"));
41
66
$c->overrideredirect(1);
43
my $sl = $c->Scrolled( qw/Listbox -selectmode browse -scrollbars oe/ );
68
my $sl = $c->Scrolled( $Listbox, qw/-selectmode browse -scrollbars oe/ );
69
if ($w->{_BE_Style} eq 'MSWin32' and $Tk::platform eq 'MSWin32') {
70
$sl->configure(-bg => 'SystemWindow', -relief => "flat");
44
72
$w->Advertise('choices' => $c);
45
73
$w->Advertise('slistbox' => $sl);
46
74
$sl->pack(-expand => 1, -fill => 'both');
76
$sl->Subwidget("scrolled")->bind("<Motion>",sub {
77
return unless ($w->{_BE_Style} eq 'MSWin32');
78
my $e = $_[0]->XEvent;
80
my $inx = $sl->nearest($y);
82
$sl->selectionClear(0, "end");
83
$sl->selectionSet($inx);
48
87
# other initializations
51
$w->Delegates('insert' => $sl, 'delete' => $sl, get => $sl, DEFAULT => $e);
89
$w->{'_BE_popped'} = 0;
90
$w->Delegates(get => $sl, DEFAULT => $e);
53
92
-listwidth => [qw/PASSIVE listWidth ListWidth/, undef],
93
-listheight => [{-height => $sl}, qw/listHeight ListHeight/, undef],
54
94
-listcmd => [qw/CALLBACK listCmd ListCmd/, undef],
95
-autolistwidth => [qw/PASSIVE autoListWidth AutoListWidth/, undef],
96
-autolimitheight => [qw/PASSIVE autoLimitHeight AutoLimitHeight 0/],
55
97
-browsecmd => [qw/CALLBACK browseCmd BrowseCmd/, undef],
98
-browse2cmd => [qw/CALLBACK browse2Cmd Browse2Cmd/, undef],
56
99
-choices => [qw/METHOD choices Choices/, undef],
57
100
-state => [qw/METHOD state State normal/],
58
101
-arrowimage => [ {-image => $b}, qw/arrowImage ArrowImage/, undef],
59
-variable => '-textvariable',
102
-variable => [ {'-textvariable' => $e} ],
60
103
-colorstate => [qw/PASSIVE colorState ColorState/, undef],
61
104
-command => '-browsecmd',
62
105
-options => '-choices',
106
-label => [qw/PASSIVE label Label/, undef],
107
-labelPack => [qw/PASSIVE labelPack LabelPack/, undef],
108
#-background => [$e, qw/background Background/, undef],
109
#-foreground => [$e, qw/foreground Foreground/, undef],
110
-buttontakefocus => [{-takefocus => $b}, 'buttonTakefocus',
111
'ButtonTakefocus', 1],
63
112
DEFAULT => [$e] );
118
167
return if $w->cget( '-state' ) eq 'disabled';
120
if ($w->{'popped'}) {
169
if ($w->{'_BE_popped'}) {
122
$w->{'buttonHack'} = 0;
171
$w->{'_BE_buttonHack'} = 0;
124
173
$w->PopupChoices;
125
$w->{'buttonHack'} = 1;
174
$w->{'_BE_buttonHack'} = 1;
129
178
sub PopupChoices {
132
if (!$w->{'popped'}) {
133
$w->Callback(-listcmd => $w);
181
if (!$w->{'_BE_popped'}) {
182
$w->Callback(-listcmd => $w);
134
183
my $e = $w->Subwidget('entry');
135
184
my $c = $w->Subwidget('choices');
136
185
my $s = $w->Subwidget('slistbox');
137
186
my $a = $w->Subwidget('arrow');
138
my $y1 = $e->rooty + $e->height + 3;
187
my $y1 = ($w->{_BE_Style} eq 'MSWin32'
188
? $a->rooty + $a->height
189
: $e->rooty + $e->height + 3
139
191
my $bd = $c->cget(-bd) + $c->cget(-highlightthickness);
140
my $ht = $s->reqheight + 2 * $bd;
192
# using the real listbox reqheight rather than the
193
# container frame one, which does not change after resizing the
195
my $ht = $s->Subwidget("scrolled")->reqheight + 2 * $bd;
196
my $x1 = ($w->{_BE_Style} eq 'MSWin32'
197
? $e->Subwidget("entry")->rootx
142
200
my ($width, $x2);
143
201
if (defined $w->cget(-listwidth)) {
144
202
$width = $w->cget(-listwidth);
175
233
# if listbox is below bottom of screen, pull it up.
234
# check the Win32 taskbar, if possible
236
if ($Tk::platform eq 'MSWin32' and $^O eq 'MSWin32') {
238
require Win32Util; # XXX should not use a non-CPAN widget
239
$rootheight = (Win32Util::screen_region($w))[3];
242
if (!defined $rootheight) {
243
$rootheight = $w->vrootheight;
176
246
my $y2 = $y1 + $ht;
177
if ($y2 > $w->vrootheight) {
247
if ($y2 > $rootheight) {
178
248
$y1 = $y1 - $ht - ($e->height - 5);
181
250
$c->geometry(sprintf('%dx%d+%d+%d', $rw, $ht, $x1, $y1));
254
$w->{'_BE_popped'} = 1;
256
# highlight current selection
257
my $current_sel = $e->get;
258
if (defined $current_sel) {
260
foreach my $str ($s->get(0, "end")) {
261
if ($str eq $current_sel) {
262
$s->selectionClear(0, "end");
263
$s->selectionSet($i);
187
270
$c->configure(-cursor => 'arrow');
271
$w->{'_BE_grabinfo'} = $w->grabSave;