File Coverage

blib/lib/Adapter/Async/OrderedList.pm
Criterion Covered Total %
statement 21 39 53.8
branch 0 2 0.0
condition n/a
subroutine 8 16 50.0
pod 7 7 100.0
total 36 64 56.2


line stmt bran cond sub pod time code
1             package Adapter::Async::OrderedList;
2             $Adapter::Async::OrderedList::VERSION = '0.018';
3 2     2   1300 use strict;
  2         3  
  2         64  
4 2     2   10 use warnings;
  2         3  
  2         923  
5              
6 2     2   12 use parent qw(Adapter::Async);
  2         2  
  2         15  
7              
8             =head1 NAME
9              
10             Adapter::Async::OrderedList - API for dealing with ordered lists
11              
12             =head1 VERSION
13              
14             version 0.018
15              
16             =head1 DESCRIPTION
17              
18             =head2 Accessing data
19              
20             =over 4
21              
22             =item * count - resolves with the number of items. If this isn't possible, an estimate may be acceptable.
23              
24             say "items: " . $adapter->count->get
25              
26             =item * get - accepts a list of indices
27              
28             $adapter->get(
29             items => [1,2,3],
30             on_item => sub { ... }
31             )->on_done(sub { warn "all done, full list of items: @{$_[0]}" })
32              
33             The returned list of items are guaranteed not to be modified further, if you want to store the arrayref directly.
34              
35             =back
36              
37             This means we have double-notify on get: a request for (1,2,3,4) needs to fire events for each of 1,2,3,4, and also return the list of all of them on completion (by resolving a Future).
38              
39             =head2 Modification
40              
41             =over 4
42              
43             =item * clear - remove all data
44              
45             =item * splice - modify by adding/removing items at a given point
46              
47             =item * modify - changes a single entry
48              
49             =back
50              
51             Helper methods provide the following:
52              
53             =over 4
54              
55             =item * insert - splice $idx, @data, 0
56              
57             =item * append - splice $idx + 1, @data, 0
58              
59             =back
60              
61             =head2 Events
62              
63             All events are shared over a common bus for each data source, in the usual fashion - adapters and views can subscribe to the ones they're interested in, and publish events at any time.
64              
65             The adapter raises these:
66              
67             =over 4
68              
69             =item * item_changed - the given item has been modified. by default only applies to elements that were marked as visible.
70              
71             =item * splice - changes to the array which remove or add elements
72              
73             =item * move - an existing element moves to a new position (some adapters may not be able to differentiate between this and splice: if in doubt, use splice instead, don't report as a move unless it's guaranteed to be existing items)
74              
75             index, length, offset (+/-)
76              
77             =back
78              
79             The view raises these:
80              
81             =over 4
82              
83             =item * visible - indicates visibility of one or more items. change events will start being sent for these items.
84              
85             visible => [1,2,3,4,5,6]
86              
87             Filters may result in a list with gaps:
88              
89             visible => [1,3,4,8,9,10]
90              
91             Note that "visible" means "the user is able to see this data", so they'd be a single page of data rather than the entire set when no filters are applied. Visibility changes often - scrolling will trigger a visible/hidden pair for example.
92              
93             Also note that ->get may be called on any element, regardless of visibility - prefetching is one common example here.
94              
95             =item * hidden - no longer visible.
96              
97             hidden => [1,2,4]
98              
99             =item * selected - this item is now part of an active selection. could be used to block deletes.
100              
101             selected => [1,4,5,6]
102              
103             =item * highlight - mouse over, cursor, etc.
104              
105             highlight => 1
106              
107             Some views won't raise this - if touch control is involved, for example
108              
109             =item * activate - some action has been performed.
110              
111             activate => [1]
112             activate => [1,2,5,6,7,8]
113              
114             Multi-activate will typically happen when items have been selected rather than just highlighted.
115              
116             The adapter itself doesn't do much with this.
117              
118             =back
119              
120             =cut
121              
122             =head1 METHODS
123              
124             =head2 insert
125              
126             Inserts data before the given position.
127              
128             $adapter->insert(3, [...])
129              
130             =cut
131              
132             sub insert {
133 5     5 1 2421 my ($self, $idx, $data) = @_;
134 5         22 $self->splice($idx, 0, $data)
135             }
136              
137             =head2 append
138              
139             Appends data after the given position.
140              
141             $adapter->append(3, [...])
142              
143             =cut
144              
145             sub append {
146 1     1 1 59 my ($self, $idx, $data) = @_;
147 1         6 $self->splice($idx + 1, 0, $data)
148             }
149              
150             =head2 push
151              
152             Appends data to the end of the list.
153              
154             =cut
155              
156             sub push {
157 10     10 1 1635 my ($self, $data) = @_;
158 10         14 my $f;
159             $f = $self->count->then(sub {
160 10     10   1039 my $count = shift;
161             $self->splice($count, 0, $data)->transform(
162             done => sub {
163 10         942 ($count, @_)
164             }
165 10         44 );
166 10     10   36 })->on_ready(sub { undef $f });
  10         879  
167 10         96 $f
168             }
169              
170             =head2 unshift
171              
172             Inserts data at the start of the list.
173              
174             =cut
175              
176             sub unshift {
177 0     0 1   my ($self, $data) = @_;
178 0           $self->splice(0, 0, $data)
179             }
180              
181             =head2 pop
182              
183             Removes the last element from the list, will resolve with the value.
184              
185             =cut
186              
187             sub pop {
188 0     0 1   my ($self, $data) = @_;
189 0           my $f;
190             $f = $self->count->then(sub {
191 0     0     $self->splice(shift() - 1, 1)
192 0     0     })->on_ready(sub { undef $f });
  0            
193 0           $f
194             }
195              
196             =head2 shift
197              
198             Removes the first element from the list, will resolve with the value.
199              
200             =cut
201              
202             sub shift {
203 0     0 1   my ($self, $data) = @_;
204 0           $self->splice(0, 1)
205             }
206              
207             =head2 all
208              
209             Returns all the items. Shortcut for calling
210             L then L.
211              
212             =cut
213              
214             sub all {
215 0     0 1   my ($self, %args) = @_;
216 0           my $f;
217             $f = $self->count->then(sub {
218 0     0     my ($count) = @_;
219 0 0         return Future->wrap([]) unless $count;
220 0           $self->get(
221             %args,
222             items => [0..$count-1],
223             )
224 0     0     })->on_ready(sub { undef $f });
  0            
225 0           $f
226             }
227              
228             1;
229              
230             __END__