Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Side by Side Diff: pkg/immi_samples/lib/ios/ImmiSamples/SlidingWindowPresenter.mm

Issue 2035023003: Remove service-compiler related code. (Closed) Base URL: git@github.com:dartino/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 #import "SlidingWindowPresenter.h"
6
7 @interface SlidingWindowPresenter ()
8
9 @property id<CellPresenter> cellPresenter;
10 @property UITableView* tableView;
11
12 // Is the TableView of this sliding window currently scrolling.
13 @property bool scrolling;
14
15 // Internal properties for updating the sliding-window display range.
16 // These are not "presentation state" but are rather mostly-constant values
17 // representing the physical dimensions of the screen.
18
19 // Number of items in the sliding-window display.
20 // Must be > 2 * bufferAdvance + |visible items on screen|.
21 @property int bufferCount;
22
23 // Access to an item within 'slack' distance of the start or end of
24 // the sliding-window triggers a sliding-window shift.
25 // Must be > 1 (a zero value will result in no shifting).
26 @property int bufferSlack;
27
28 // Number of items to shift the buffer by when shifting.
29 // Must be >= bufferSlack.
30 @property int bufferAdvance;
31
32 @property SlidingWindowNode* root;
33
34 @end
35
36 @implementation SlidingWindowPresenter
37
38 - (id)initWithCellPresenter:(id<CellPresenter>)presenter
39 tableView:(UITableView*)tableView {
40 self.scrolling = false;
41 self.cellPresenter = presenter;
42 self.tableView = tableView;
43 [self setBufferParametersBasedOnViewSize];
44 return self;
45 }
46
47 - (void)setBufferParametersBasedOnViewSize {
48 CGFloat rowHeight = self.cellPresenter.minimumCellHeight;
49 CGFloat tableHeight = self.tableView.bounds.size.height;
50 int cellCount = (int) (tableHeight / rowHeight);
51
52 self.bufferSlack = 1;
53 self.bufferAdvance = cellCount;
54 self.bufferCount = 3 * self.bufferAdvance + cellCount;
55 }
56
57 - (void)presentSlidingWindow:(SlidingWindowNode*)node {
58 [self checkDisplayWindow:node];
59 dispatch_async(dispatch_get_main_queue(), ^{
60 [self presentOnMainThread:node];
61 });
62 }
63
64 - (void)patchSlidingWindow:(SlidingWindowPatch*)patch {
65 assert(patch.updated);
66 [self checkDisplayWindow:patch.current];
67 dispatch_async(dispatch_get_main_queue(), ^{
68 [self patchOnMainThread:patch];
69 });
70 }
71
72 - (void)checkDisplayWindow:(SlidingWindowNode*)node {
73 if (node.window.count == 0) {
74 node.display(0, self.bufferCount);
75 }
76 }
77
78 - (NSInteger)tableView:(UITableView*)tableView
79 numberOfRowsInSection:(NSInteger)section {
80 return self.root == nil ? 0 : self.root.minimumCount;
81 }
82
83 - (UITableViewCell*)tableView:(UITableView*)tableView
84 cellForRowAtIndexPath:(NSIndexPath*)indexPath {
85 Node* node = [self itemAtIndex:indexPath.row];
86 return [self.cellPresenter tableView:tableView
87 indexPath:indexPath
88 present:node];
89 }
90
91 // To track what items are visible on screen we rely on the fact that only
92 // visible items are accessed by cellForRowAtIndexPath. When accessing an index
93 // that is in the proximity of either the start or the end of the sliding
94 // window, we shift the window.
95 - (id)itemAtIndex:(int)index {
96 assert(self.root != nil);
97 if (index < self.windowStart + self.bufferSlack) {
98 [self shiftDown:index];
99 } else if (index + self.bufferSlack >= self.windowEnd) {
100 [self shiftUp:index];
101 }
102 int adjusted = [self windowIndex:index];
103 // Return nil if the adjusted index is outside the sliding window.
104 return (adjusted < 0) ? nil : [self.root.window objectAtIndex:adjusted];
105 }
106
107 - (void)shiftDown:(int)index {
108 int start = (index > self.bufferAdvance) ? index - self.bufferAdvance : 0;
109 if (start == self.windowStart) return;
110 [self refreshDisplayStart:start end:start + self.bufferCount];
111 }
112
113 - (void)shiftUp:(int)index {
114 int end = index + self.bufferAdvance + 1;
115 if (end > self.maximumCount) end = self.maximumCount;
116 if (end == self.windowEnd) return;
117 if (end > self.bufferCount) {
118 [self refreshDisplayStart:end - self.bufferCount end:end];
119 } else {
120 [self refreshDisplayStart:0 end:self.bufferCount];
121 }
122 }
123
124 - (void)refreshDisplayStart:(int)start end:(int)end {
125 self.root.display(start, end);
126 }
127
128 // Adjust the scroll position if the visible rows are outside the window buffer.
129 // Returns true if it is or if scroll position was adjusted.
130 - (bool)adjustScrollPosition {
131 // TODO(zerny): Identify "scroll to top" as scrolling and enable this again.
132 return false;
133 // TODO(zerny): Properly track the scroll position.
134 // If the current view is outside the visible view adjust the visible view.
135 if (!self.scrolling && self.tableView.indexPathsForVisibleRows.count > 0) {
136 int start = self.windowStart;
137 int end = self.windowEnd;
138 int row = [[self.tableView.indexPathsForVisibleRows objectAtIndex:0] row];
139 if (row < start || end <= row) {
140 // Adjust the start by buffer slack so we don't trigger a window shift.
141 if (start != 0) start += self.bufferSlack + 1;
142 NSIndexPath* path = [NSIndexPath indexPathForRow:start inSection:0];
143 [self.tableView reloadData];
144 if (start < end) {
145 [self.tableView scrollToRowAtIndexPath:path
146 atScrollPosition:UITableViewScrollPositionTop
147 animated:NO];
148 }
149 return true;
150 }
151 }
152 return false;
153 }
154
155 - (void)presentOnMainThread:(SlidingWindowNode*)node {
156 self.root = node;
157 if ([self adjustScrollPosition]) return;
158 [self.tableView reloadData];
159 }
160
161 - (void)patchOnMainThread:(SlidingWindowPatch*)patch {
162 self.root = patch.current;
163 if ([self adjustScrollPosition]) return;
164
165 int previousCount = patch.previous.minimumCount;
166 int currentCount = patch.current.minimumCount;
167 assert(previousCount == [self.tableView numberOfRowsInSection:0]);
168
169 // The stable range is positions in the view both before and after the patch.
170 int stableCount = MIN(previousCount, currentCount);
171
172 // Independently track if insert or removes have been made.
173 bool containsInserts = false;
174 bool containsRemoves = false;
175
176 // Find an update ranges:
177 NSMutableArray* updatePaths = [[NSMutableArray alloc] init];
178 for (int i = 0; i < patch.window.regions.count; ++i) {
179 ListRegionPatch* region = patch.window.regions[i];
180 if (!region.isUpdate) {
181 containsInserts = containsInserts || region.isInsert;
182 containsRemoves = containsRemoves || region.isRemove;
183 continue;
184 }
185 ListRegionUpdatePatch* update = (id)region;
186 for (int j = 0; j < update.updates.count; ++j) {
187 int position = [self windowIndexToTableIndex:update.index + j];
188 if (position >= stableCount) continue;
189 [updatePaths addObject:[NSIndexPath indexPathForRow:position inSection:0]] ;
190 }
191 }
192
193 // This patch routine assumes that the diff algorithm will not produce
194 // both an insertion and a deletion region in the same patch.
195 assert(!containsInserts || !containsRemoves);
196
197 // Find either the insert or the remove positions:
198 NSMutableArray* insertPaths;
199 NSMutableArray* removePaths;
200 if (stableCount < currentCount) {
201 insertPaths = [[NSMutableArray alloc] init];
202 for (int i = stableCount; i < currentCount; ++i) {
203 [insertPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
204 }
205 } else if (stableCount < previousCount) {
206 removePaths = [[NSMutableArray alloc] init];
207 for (int i = stableCount; i < previousCount; ++i) {
208 [removePaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
209 }
210 }
211
212 // Batch notify the table view of the changes.
213 [self.tableView beginUpdates];
214 [self.tableView reloadRowsAtIndexPaths:updatePaths
215 withRowAnimation:UITableViewRowAnimationNone];
216 if (insertPaths != nil) {
217 [self.tableView insertRowsAtIndexPaths:insertPaths
218 withRowAnimation:UITableViewRowAnimationNone];
219 }
220 if (removePaths != nil) {
221 [self.tableView deleteRowsAtIndexPaths:removePaths
222 withRowAnimation:UITableViewRowAnimationNone];
223 }
224 [self.tableView endUpdates];
225
226 assert(currentCount == [self.tableView numberOfRowsInSection:0]);
227 }
228
229 - (int)windowIndexToTableIndex:(int)index {
230 int indexDelta = index - self.root.windowOffset;
231 if (indexDelta < 0) indexDelta += self.root.window.count;
232 return [self windowStart] + indexDelta;
233 }
234
235 - (int)windowIndex:(int)index {
236 assert(self.root != nil);
237 if (index < self.windowStart || self.windowEnd <= index) return -1;
238 int i = self.root.windowOffset + index - self.windowStart;
239 return i % self.windowCount;
240 }
241
242 // The maximum number of items that can be in the list.
243 - (int)maximumCount {
244 return self.root.maximumCount < 0 ? INT_MAX : self.root.maximumCount;
245 }
246
247 - (int)windowCount {
248 return self.root.window.count;
249 }
250
251 - (int)windowEnd {
252 return self.root.startOffset + self.windowCount;
253 }
254
255 - (int)windowStart {
256 return self.root.startOffset;
257 }
258
259 - (void)tableView:(UITableView*)tableView
260 didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
261 self.root.toggle(indexPath.row);
262 }
263
264 - (CGFloat)tableView:(UITableView*)tableView
265 heightForRowAtIndexPath:(NSIndexPath*)indexPath {
266 return [self.cellPresenter tableView:tableView
267 heightForRowAtIndexPath:indexPath];
268 }
269
270 - (CGFloat)tableView:(UITableView*)tableView
271 estimatedHeightForRowAtIndexPath:(NSIndexPath*)indexPath {
272 return [self.cellPresenter tableView:tableView
273 estimatedHeightForRowAtIndexPath:indexPath];
274 }
275
276 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
277 self.scrolling = true;
278 }
279
280 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL )decelerate {
281 self.scrolling = false;
282 }
283
284 @end
OLDNEW
« no previous file with comments | « pkg/immi_samples/lib/ios/ImmiSamples/SlidingWindowPresenter.h ('k') | pkg/immi_samples/lib/ios/ImmiSamples/ViewPresenter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698