File Coverage

blib/lib/Tk/ChoicesSet.pm
Criterion Covered Total %
statement 6 71 8.4
branch 0 10 0.0
condition n/a
subroutine 2 18 11.1
pod n/a
total 8 99 8.0


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;