1# contains: 2# CheckList 3 4package Prima::ExtLists; 5use strict; 6use warnings; 7use Prima::Const; 8use Prima::Classes; 9use Prima::Lists; 10use Prima::StdBitmap; 11 12package Prima::CheckList; 13use vars qw(@ISA); 14@ISA = qw(Prima::ListBox); 15 16my (@images, @imgSize); 17 18Prima::Application::add_startup_notification( sub { 19 @images = ( 20 Prima::StdBitmap::image(sbmp::CheckBoxUnchecked), 21 Prima::StdBitmap::image(sbmp::CheckBoxChecked), 22 ); 23 @imgSize = (0,0); 24 @imgSize = $images[0]-> size if $images[0]; 25}); 26 27sub profile_default 28{ 29 my $def = $_[ 0]-> SUPER::profile_default; 30 my %prf = ( 31 vector => '', 32 ); 33 @$def{keys %prf} = values %prf; 34 return $def; 35} 36 37 38sub init 39{ 40 my $self = shift; 41 $self-> {vector} = 0; 42 my %profile = $self-> SUPER::init(@_); 43 $self-> {fontHeight} = $self-> font-> height; 44 $self-> recalc_icons; 45 $self-> vector( $profile{vector}); 46 return %profile; 47} 48 49sub on_measureitem 50{ 51 my ( $self, $index, $sref) = @_; 52 $$sref = $self-> get_text_width( $self-> {items}-> [$index]) + $imgSize[0] + 4; 53} 54 55sub recalc_icons 56{ 57 return unless $imgSize[0]; 58 my $self = $_[0]; 59 my $hei = $self-> font-> height + 2; 60 $hei = $imgSize[1] + 2 if $hei < $imgSize[1] + 2; 61 $self-> itemHeight( $hei); 62} 63 64sub on_fontchanged 65{ 66 my $self = shift; 67 $self-> recalc_icons; 68 $self-> {fontHeight} = $self-> font-> height; 69 $self-> SUPER::on_fontchanged(@_); 70} 71 72 73sub draw_items 74{ 75 shift-> std_draw_text_items( @_); 76} 77 78sub draw_text_items 79{ 80 my ( $self, $canvas, $first, $last, $step, $x, $y, $textShift, $clipRect) = @_; 81 my ( $i, $j); 82 for ( $i = $first, $j = 1; $i <= $last; $i += $step, $j++) { 83 next if $self-> {widths}-> [$i] + $self-> {offset} + $x + 1 < $clipRect-> [0]; 84 $canvas-> text_shape_out( $self-> {items}-> [$i], $x + 2 + $imgSize[0], 85 $y + $textShift - $j * $self-> {itemHeight} + 1); 86 $canvas-> put_image( $x + 1, 87 $y + int(( $self-> {itemHeight} - $imgSize[1]) / 2) - 88 $j * $self-> {itemHeight} + 1, 89 $images[ vec($self-> {vector}, $i, 1)], 90 ); 91 } 92} 93 94sub on_mouseclick 95{ 96 my ( $self, $btn, $mod, $x, $y, $dbl) = @_; 97 $self-> SUPER::on_mouseclick( $btn, $mod, $x, $y); 98 return if $btn != mb::Left; 99 my $foc = $self-> focusedItem; 100 return if $foc < 0; 101 my $f = vec( $self-> {vector}, $foc, 1) ? 0 : 1; 102 vec( $self-> {vector}, $foc, 1) = $f; 103 $self-> notify(q(Change), $foc, $f); 104 $self-> invalidate_rect( $self-> item2rect( $foc)); 105} 106 107sub on_click 108{ 109 my $self = $_[0]; 110 my $foc = $self-> focusedItem; 111 return if $foc < 0; 112 my $f = vec( $self-> {vector}, $foc, 1) ? 0 : 1; 113 vec( $self-> {vector}, $foc, 1) = $f; 114 $self-> notify(q(Change), $foc, $f); 115 $self-> invalidate_rect( $self-> item2rect( $foc)); 116} 117 118 119sub vector 120{ 121 my $self = $_[0]; 122 return $self-> {vector} unless $#_; 123 $self-> {vector} = $_[1]; 124 $self-> repaint; 125} 126 127sub clear_all_buttons 128{ 129 my $self = $_[0]; 130 my $c = int($self-> {count} / 32) + (($self-> {count} % 32) ? 1 : 0); 131 vec( $self-> {vector}, $c, 32) = 0 while $c--; 132 $self-> notify(q(Change), -1, 1); 133 $self-> repaint; 134}; 135 136sub set_all_buttons 137{ 138 my $self = $_[0]; 139 my $c = int($self-> {count} / 32) + (($self-> {count} % 32) ? 1 : 0); 140 vec( $self-> {vector}, $c, 32) = 0xffffffff while $c--; 141 $self-> notify(q(Change), -1, 0); 142 $self-> repaint; 143}; 144 145sub button 146{ 147 my ( $self, $index, $state) = @_; 148 return 0 if $index < 0 || $index >= $self-> {count}; 149 my $current = vec( $self-> {vector}, $index, 1); 150 return $current unless defined $state; 151 $state = ( $state < 0) ? !$current : ( $state ? 1 : 0); 152 return $current if $current == $state; 153 vec( $self-> {vector}, $index, 1) = $state; 154 $self-> notify(q(Change), $index, $state); 155 $self-> redraw_items( $index); 156 return $state; 157} 158 159#sub on_change 160#{ 161# my ( $self, $index, $state) = @_; 162#} 163 1641; 165 166=pod 167 168=head1 NAME 169 170Prima::ExtLists - extended functionality for list boxes 171 172=head1 SYNOPSIS 173 174 use Prima qw(ExtLists Application); 175 176 my $vec = ''; 177 vec( $vec, 0, 8) = 0x55; 178 Prima::CheckList-> new( 179 items => [1..10], 180 vector => $vec, 181 ); 182 run Prima; 183 184=for podview <img src="extlist.gif"> 185 186=for html <p><img src="https://raw.githubusercontent.com/dk/Prima/master/pod/Prima/extlist.gif"> 187 188=head1 DESCRIPTION 189 190The module is intended to be a collection of list boxes with 191particular enhancements. Currently the only package is contained 192is C<Prima::CheckList> class. 193 194=head1 Prima::CheckList 195 196Provides a list box, where each item is equipped with a check box. 197The check box state can interactively be toggled by the enter key; 198also the list box reacts differently by click and double click. 199 200=head2 Properties 201 202=over 203 204=item button INDEX, STATE 205 206Runtime only. Sets INDEXth button STATE to 0 or 1. 207If STATE is -1, the button state is toggled. 208 209Returns the new state of the button. 210 211=item vector VEC 212 213VEC is a vector scalar, where each bit corresponds to the check state 214of each list box item. 215 216See also: L<perlfunc/vec>. 217 218=back 219 220=head2 Methods 221 222=over 223 224=item clear_all_buttons 225 226Sets all buttons to state 0 227 228=item set_all_buttons 229 230Sets all buttons to state 1 231 232=back 233 234=head1 AUTHOR 235 236Dmitry Karasik, E<lt>dmitry@karasik.eu.orgE<gt>. 237 238=head1 SEE ALSO 239 240L<Prima>, L<Prima::Lists>, F<examples/extlist.pl> 241 242=cut 243 244