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; |