| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Tk::ChoicesSet; |
|
2
|
2
|
|
|
2
|
|
4858
|
use strict; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
101
|
|
|
3
|
2
|
|
|
2
|
|
12
|
use warnings; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
2428
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 NAME |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
Tk::ChoicesSet - display/edit a list of choices in a Set of single-selection Widgets. |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
require Tk::ChoicesSet; |
|
13
|
|
|
|
|
|
|
my $labels_and_values = [ |
|
14
|
|
|
|
|
|
|
{label => 'foo', value => 1}, |
|
15
|
|
|
|
|
|
|
{label => 'bar', value => 2}, |
|
16
|
|
|
|
|
|
|
{label => 'baz', value => 3}, |
|
17
|
|
|
|
|
|
|
]; |
|
18
|
|
|
|
|
|
|
my $instance = $main_window->ChoicesSet(-labels_and_values => |
|
19
|
|
|
|
|
|
|
$labels_and_values)->pack; |
|
20
|
|
|
|
|
|
|
$instance->configure(-valuelist_variable => \$valuelist); |
|
21
|
|
|
|
|
|
|
$instance->valuelist([1,3]); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Tk::ChoicesSet creates a Set of widgets to display/edit a list of choices. |
|
27
|
|
|
|
|
|
|
Each widget allows for a single selection out of a given list of |
|
28
|
|
|
|
|
|
|
options. The widget class is configurable. |
|
29
|
|
|
|
|
|
|
Per default Tk::ChoicesSet uses Tk::MatchingBE which is included in the |
|
30
|
|
|
|
|
|
|
Tk-EntrySet package. This can be changed to any widget that supports |
|
31
|
|
|
|
|
|
|
index based access to the selection. Tk::ChoicesSet adds/removes widgets |
|
32
|
|
|
|
|
|
|
to match the size of the valuelist. When a selection-widgets state becomes |
|
33
|
|
|
|
|
|
|
undef (deselected), the value is deleted from the valuelist and the widget |
|
34
|
|
|
|
|
|
|
is removed from the set on view update. |
|
35
|
|
|
|
|
|
|
View updates are by default bound to the widgets -selectcmd for integration |
|
36
|
|
|
|
|
|
|
with MatchingBE. This is configurable through the -callback_installer option. |
|
37
|
|
|
|
|
|
|
The last widget in the Set is always empty to allow users to |
|
38
|
|
|
|
|
|
|
append values to the list. |
|
39
|
|
|
|
|
|
|
(If you need editable values with an optionlist for 'suggestions' and value |
|
40
|
|
|
|
|
|
|
based access to the widgets in the set, you might want to use Tk::EntrySet.) |
|
41
|
|
|
|
|
|
|
Tk::ChoicesSet handles label/value pairs or simple choices lists. |
|
42
|
|
|
|
|
|
|
Tk::ChoicesSet is a Tk::EntrySet derived widget. |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 METHODS |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
B supports the following methods: |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=over 4 |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item B[qw/a list of selected values/]B<)> |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Get/Set the valuelist (arrayref). |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=item B[qw/a list of selected indexes/]B<)> |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
Get/Set the indexlist (arrayref). For internal use primarily. |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item B[{label=>'aLabel',value=>'aValue'},{},{}]B<)> |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Get/Set the options list (arrayref of hashes). Sets label and value of each |
|
63
|
|
|
|
|
|
|
element to the corresponding hash value. |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item B[qw/a list of options to choose from/]B<)> |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Get/Set the options list (arrayref). Sets label and value of each element |
|
68
|
|
|
|
|
|
|
to the value in the list. When used as a getter returns the list of option |
|
69
|
|
|
|
|
|
|
labels. |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=back |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 OPTIONS |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
B supports the following options: |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=over 4 |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item B<-entryclass> |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
A Tk widget class to be used for the entrywidgets. Defaults to 'MatchingBE'. |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item B<-entryoptions> |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Options to be passed to each entry on creation (arrayref). |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=item B<-getter> |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
A coderef which is used by Tk::ChoicesSet to read the Entrywidgets content. |
|
90
|
|
|
|
|
|
|
It gets passed the Entrywidget instance and is expected to return its |
|
91
|
|
|
|
|
|
|
selected index. |
|
92
|
|
|
|
|
|
|
Defaults to |
|
93
|
|
|
|
|
|
|
sub{ $_[0]->get_selected_index }, which is suitable for |
|
94
|
|
|
|
|
|
|
Tk::MatchingBE. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item B<-setter> |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
A coderef which is used by Tk::ChoicesSet to write the Entrywidgets content. |
|
99
|
|
|
|
|
|
|
It gets passed the Entrywidget instance and the new index value. Defaults to |
|
100
|
|
|
|
|
|
|
sub{ $_[0]->set_selected_index($_[1]) }, which is suitable for Tk::MatchingBE. |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item B<-callback_installer> |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
A coderef which is called after each Entrywidgets instantiation. |
|
105
|
|
|
|
|
|
|
The callback_installer gets passed the Entrywidget and a coderef that will |
|
106
|
|
|
|
|
|
|
update the Tk::ChoicesSet view when called. |
|
107
|
|
|
|
|
|
|
Defaults to |
|
108
|
|
|
|
|
|
|
sub{$_[0]->configure(-selectcmd => $_[1])}, which is suitable for |
|
109
|
|
|
|
|
|
|
Tk::MatchingBE. |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=item B<-unique_values> |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
If set to true (default) duplicate elements will be removed on view updates. |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=item B<-valuelist> |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Get/Set the list of selected values (arrayref). |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=item B<-valuelist_variable> |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Ties a variable (scalarref) to the -valuelist atribute. |
|
122
|
|
|
|
|
|
|
This is a Scalar Tie only. |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=back |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head1 Examples |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
See the examples/ subdirectory. |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head1 AUTHOR |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Christoph Lamprecht, ch.l.ngre@online.de |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Copyright (C) 2008 by Christoph Lamprecht |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
|
140
|
|
|
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.8.7 or, |
|
141
|
|
|
|
|
|
|
at your option, any later version of Perl 5 you may have available. |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=cut |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
our $VERSION = '0.11'; |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
require Tk::EntrySet; |
|
149
|
|
|
|
|
|
|
require Tk::MatchingBE; |
|
150
|
|
|
|
|
|
|
our @ISA = 'Tk::EntrySet'; |
|
151
|
|
|
|
|
|
|
Tk::Widget->Construct('ChoicesSet'); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub default_entryclass{ |
|
154
|
0
|
|
|
0
|
|
|
return 'MatchingBE'; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
sub default_getter{ |
|
157
|
0
|
|
|
0
|
|
|
return sub{$_[0]->get_selected_index}; |
|
|
0
|
|
|
0
|
|
|
|
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
sub default_setter{ |
|
160
|
0
|
|
|
0
|
|
|
return sub{$_[0]->set_selected_index($_[1])}; |
|
|
0
|
|
|
0
|
|
|
|
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
sub default_callback_installer{ |
|
163
|
0
|
|
|
0
|
|
|
return sub{$_[0]->configure(-selectcmd => $_[1])}; |
|
|
0
|
|
|
0
|
|
|
|
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
#sub autoLabel{0}; # keep Frames -label and related options |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub Populate{ |
|
169
|
0
|
|
|
0
|
|
|
my ($self,$args) = @_; |
|
170
|
0
|
|
|
|
|
|
$self->{_ChoicesSet}{entry_pool}= []; |
|
171
|
0
|
|
|
|
|
|
$self->{_ChoicesSet}{entries}= []; |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
# need to hide this from Tk::Frame::Populate... |
|
174
|
0
|
0
|
|
|
|
|
my $l_v = exists $args->{-labels_and_values} |
|
175
|
|
|
|
|
|
|
? delete $args->{-labels_and_values} |
|
176
|
|
|
|
|
|
|
: undef; |
|
177
|
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
$self->SUPER::Populate($args); |
|
179
|
|
|
|
|
|
|
|
|
180
|
0
|
0
|
|
|
|
|
if (defined $l_v){ |
|
181
|
0
|
|
|
|
|
|
$args->{-labels_and_values}= $l_v; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
0
|
|
|
|
|
|
my $empty = [{value => '',label => ''}]; |
|
184
|
0
|
|
|
|
|
|
$self->ConfigSpecs( |
|
185
|
|
|
|
|
|
|
-choices => ['METHOD',undef,undef,undef], |
|
186
|
|
|
|
|
|
|
-labels_and_values => ['METHOD',undef,undef,$empty], |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
); |
|
189
|
0
|
|
|
0
|
|
|
$self->afterIdle(sub{$self->valuelist}); |
|
|
0
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub new_entry{ |
|
193
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
194
|
0
|
|
|
|
|
|
my $entry = $self->SUPER::new_entry; |
|
195
|
|
|
|
|
|
|
# propagate our cw's choices(labels) to the actual entry subwidget |
|
196
|
0
|
|
|
|
|
|
my $labels = $self->get_labels; |
|
197
|
|
|
|
|
|
|
##print "configure entry with choices:\n"; |
|
198
|
|
|
|
|
|
|
##print Dumper $choices; |
|
199
|
0
|
|
|
|
|
|
$entry->configure(-choices => $labels); |
|
200
|
0
|
|
|
|
|
|
return $entry; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
sub choices{ |
|
205
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
206
|
0
|
|
|
|
|
|
my $choices = $_[0]; |
|
207
|
0
|
0
|
|
|
|
|
unless ($choices){ |
|
208
|
0
|
|
|
|
|
|
return $self->get_labels; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
#print "MBE choices: arg:\n"; |
|
211
|
|
|
|
|
|
|
#print Dumper $choices; |
|
212
|
0
|
|
|
|
|
|
my @labels_and_values = map {{value => $_, label => $_}} @$choices; |
|
|
0
|
|
|
|
|
|
|
|
213
|
0
|
|
|
|
|
|
$self->labels_and_values(\@labels_and_values); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub labels_and_values{ |
|
219
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
220
|
0
|
|
|
|
|
|
my $data = $_[0]; |
|
221
|
0
|
0
|
|
|
|
|
unless ($data){ |
|
222
|
0
|
|
|
|
|
|
return $self->{_ChoicesSet}{labels_and_values}; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# we expect an arrayref structure like |
|
226
|
|
|
|
|
|
|
# [ {value => 'aValue', label => 'aLabel'} , |
|
227
|
|
|
|
|
|
|
# {value => 'aValue', label => 'aLabel'}, |
|
228
|
|
|
|
|
|
|
# ... |
|
229
|
|
|
|
|
|
|
# ] |
|
230
|
|
|
|
|
|
|
|
|
231
|
0
|
|
|
|
|
|
$self->{_ChoicesSet}{labels_and_values} = $data; |
|
232
|
0
|
|
|
|
|
|
my $i = 0; |
|
233
|
0
|
|
|
|
|
|
my %value_to_index = map {($_->{value},$i++)} @$data; |
|
|
0
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
$self->{_ChoicesSet}{value_to_index} = \%value_to_index; |
|
235
|
|
|
|
|
|
|
# print Dumper \%value_to_index; |
|
236
|
|
|
|
|
|
|
|
|
237
|
0
|
|
|
|
|
|
$self->clear_valuelist; |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub get_labels{ |
|
242
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
243
|
0
|
|
|
|
|
|
my $labels_and_values = $self->labels_and_values; |
|
244
|
0
|
|
|
|
|
|
my @labels = map {$_->{label}} @{$labels_and_values}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
245
|
0
|
|
|
|
|
|
return \@labels; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# ChoicesSet deals with indexable Option lists, therefore the default |
|
249
|
|
|
|
|
|
|
# access via the -getter/-setter subs is per index - and that's how the |
|
250
|
|
|
|
|
|
|
# default -getter/-setter are defined. |
|
251
|
|
|
|
|
|
|
# We wrap the inherited 'valuelist' by 'indexlist' and define 'valuelist' |
|
252
|
|
|
|
|
|
|
# get/set to behave as expected and deal with 'values' |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub indexlist{ |
|
255
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
256
|
0
|
|
|
|
|
|
my ($indexlist) = $_[0]; |
|
257
|
0
|
0
|
|
|
|
|
if ($indexlist){ |
|
258
|
0
|
|
|
|
|
|
$self->SUPER::set_valuelist($indexlist); |
|
259
|
|
|
|
|
|
|
}else{ |
|
260
|
0
|
|
|
|
|
|
$indexlist = $self->SUPER::get_valuelist; |
|
261
|
|
|
|
|
|
|
} |
|
262
|
0
|
|
|
|
|
|
return $indexlist; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
### set_valuelist expects an arrayref of values |
|
266
|
|
|
|
|
|
|
### and maps it to indices |
|
267
|
|
|
|
|
|
|
sub set_valuelist{ |
|
268
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
269
|
0
|
|
|
|
|
|
my $values = $_[0]; |
|
270
|
0
|
|
|
|
|
|
my %value_to_index = %{$self->{_ChoicesSet}{value_to_index}}; |
|
|
0
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
my @selected = map {$value_to_index{$_}} @$values; |
|
|
0
|
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
|
$self->indexlist(\@selected); |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
### read selected indexlist and map to values |
|
276
|
|
|
|
|
|
|
sub get_valuelist{ |
|
277
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
278
|
0
|
|
|
|
|
|
my $selected = $self->indexlist; |
|
279
|
0
|
|
|
|
|
|
my $labels_and_values = $self->{_ChoicesSet}{labels_and_values}; |
|
280
|
0
|
|
|
|
|
|
my @values = map {$labels_and_values->[$_]{value}} @$selected; |
|
|
0
|
|
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
return \@values; |
|
282
|
|
|
|
|
|
|
} |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
1; |