File Coverage

blib/lib/Wx/Perl/ListCtrl.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Wx::Perl::ListCtrl;
2              
3             =head1 NAME
4              
5             Wx::Perl::ListCtrl - a sensible API for Wx::ListCtrl
6              
7             =head1 SYNOPSIS
8              
9             use Wx::Perl::ListCtrl;
10              
11             my $lc = Wx::Perl::ListCtrl->new( $parent, -1 );
12              
13             # add columns...
14              
15             # get/set item text easily
16             $lc->InsertStringItem( 0, 'dummy' );
17             $lc->SetItemText( 0, 0, 'row 0, col 0' );
18             $lc->SetItemText( 0, 1, 'row 0, col 1' );
19             $lc->GetItemText( 0, 1 ) # 'row 0, col 1'
20              
21             # use structured data, not plain integers
22             $lc->SetItemData( 0, { complex =>1, data => 2 } );
23             my $data = $lc->GetItemData( 0 );
24              
25             # sensible way of getting the selection
26             my $selection = $lc->GetSelection; # single selection
27             my @selections = $lc->GetSelections; # multiple selections
28              
29             =head1 DESCRIPTION
30              
31             The C API is terrible. This module goes further than
32             C in providing a sane api for C.
33              
34             B and
35             C >.
36              
37             C derives from C, however some of
38             C methods are overridden with more sensible,
39             and sometimes API-incompatible, implementations.
40              
41             =cut
42              
43 1     1   993 use strict;
  1         3  
  1         67  
44              
45             our $VERSION = '0.03';
46              
47 1     1   441 use Wx qw(:listctrl);
  0            
  0            
48             use base 'Wx::ListView';
49              
50             # assume a 4 byte long value giving a max of 2147483647 and set the
51             # max index a little below.
52             sub _max_itemdata_idx() { 2147483640 }
53             sub _carp { require Carp; goto &Carp::carp; }
54              
55             =head1 METHODS
56              
57             =head2 GetSelection
58              
59             my $selection = $lc->GetSelection;
60              
61             Returns the single selected line. Only works with a single-selection
62             list control.
63              
64             =cut
65              
66             sub GetSelection {
67             my $self = shift;
68              
69             _carp( "GetSelection must be used on single selection Wx::Perl::ListCtrl" )
70             unless $self->GetWindowStyleFlag & wxLC_SINGLE_SEL;
71              
72             return $self->GetFirstSelected;
73             }
74              
75             =head2 GetSelections
76              
77             my @selections = $lc->GetSelections;
78              
79             Returns a list with all the selected lines. Only works with a multi-selection
80             list control.
81              
82             =cut
83              
84             sub GetSelections {
85             my $self = shift;
86              
87             _carp( "GetSelections must be used on multi selection Wx::Perl::ListCtrl" )
88             if $self->GetWindowStyleFlag & wxLC_SINGLE_SEL;
89              
90             my $selection = $self->GetFirstSelected;
91              
92             return if $selection == -1;
93              
94             my @selections = ( $selection );
95              
96             while( ( $selection = $self->GetNextSelected( $selection ) ) != -1 ) {
97             push @selections, $selection;
98             }
99              
100             return @selections;
101             }
102              
103             =head2 GetItemText
104              
105             my $text = $lc->GetItemText( $row, $col );
106              
107             B >. Returns the text of the
108             given item.
109              
110             =cut
111              
112             sub GetItemText {
113             my( $self, $item, $col ) = @_; $col ||= 0;
114              
115             return $self->SUPER::GetItemText( $item ) if $col == 0;
116             my $it = $self->GetItem( $item, $col );
117              
118             return $it ? $it->GetText : '';
119             }
120              
121             =head2 SetItemText
122              
123             $lc->SetItemText( $row, $col, 'Text' );
124              
125             B >. Sets the text of the
126             given item.
127              
128             =cut
129              
130             *SetItemText = \&Wx::ListCtrl::SetItemString;
131              
132             =head2 SetItemData
133              
134             $lc->SetItemData( $item, { complex => [ qw(data is allowed) ] } );
135              
136             Sets the client data for the given row. Complex data structures are allowed.
137             Setting the data to C deletes the data for the given row.
138              
139             =cut
140              
141             sub SetItemData {
142             use integer;
143              
144             my( $self, $item, $data ) = @_;
145             my $stash = $self->{_wx_data} ||= {};
146             my $idx = sprintf "%u", $self->SUPER::GetItemData( $item ) || 0;
147              
148             unless( defined $data ) {
149             delete $stash->{$idx};
150             return;
151             }
152              
153             unless( $idx ) {
154             $idx = _get_new_idx( $self );
155             # reset where $stash points
156             $stash = $self->{_wx_data};
157             }
158              
159             $stash->{$idx} = $data;
160              
161             $self->SUPER::SetItemData( $item, $idx );
162             }
163              
164             sub _get_new_idx {
165             use integer;
166              
167             my( $self ) = @_;
168             my $idx = sprintf "%u", ++$self->{_wx_count};
169              
170             return $idx if $idx < _max_itemdata_idx();
171              
172             # reset stash and item data
173             my $oldstash = $self->{_wx_data};
174             $self->{_wx_count} = 0;
175             my $newstash = {};
176             for( my $item = $self->SUPER::GetNextItem( -1 );
177             $item != -1;
178             $item = $self->SUPER::GetNextItem( $item ) ) {
179             my $oldindex = $self->SUPER::GetItemData( $item ) || 0;
180             if( $oldindex && exists $oldstash->{$oldindex} ) {
181             my $newindex = sprintf "%u", ++$self->{_wx_count};
182             $newstash->{$newindex} = $oldstash->{$oldindex};
183             $self->SUPER::SetItemData( $item, $newindex );
184             }
185             }
186             $self->{_wx_data} = $newstash;
187              
188             return _get_new_idx( $self );
189             }
190              
191             =head2 GetItemData
192              
193             my $data = $lc->GetItemData( $data );
194              
195             Retrieves the data set with C<$lc->SetItemData>.
196              
197             =cut
198              
199             sub GetItemData {
200             use integer;
201              
202             my( $self, $item ) = @_;
203             my $stash = $self->{_wx_data};
204             return unless $stash;
205              
206             return $stash->{$self->SUPER::GetItemData( $item ) || 0};
207             }
208              
209             # overridden to correctly handle the custom item data,
210             # they do not change user-visible behaviour
211              
212             sub DeleteAllItems {
213             my $self = shift;
214             my $ret = $self->SUPER::DeleteAllItems;
215              
216             if( $ret ) {
217             delete $self->{_wx_data};
218             delete $self->{_wx_count};
219             }
220              
221             return $ret;
222             }
223              
224             sub ClearAll {
225             my $self = shift;
226              
227             $self->SUPER::ClearAll;
228              
229             delete $self->{_wx_data};
230             delete $self->{_wx_count};
231             }
232              
233             sub DeleteItem {
234             my( $self, $item ) = @_;
235             my $key = $self->SUPER::GetItemData( $item );
236             my $ret = $self->SUPER::DeleteItem( $item );
237              
238             delete $self->{_wx_data}{$key} if $ret;
239              
240             return $ret;
241             }
242              
243             1;
244              
245             __END__