OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/browser/ui/stack_view/card_stack_layout_manager.h" | 5 #import "ios/chrome/browser/ui/stack_view/card_stack_layout_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "ios/chrome/browser/ui/rtl_geometry.h" | 11 #include "ios/chrome/browser/ui/rtl_geometry.h" |
12 #import "ios/chrome/browser/ui/stack_view/card_view.h" | |
13 #import "ios/chrome/browser/ui/stack_view/stack_card.h" | 12 #import "ios/chrome/browser/ui/stack_view/stack_card.h" |
14 #import "ios/chrome/browser/ui/stack_view/title_label.h" | |
15 #import "ios/chrome/browser/ui/ui_util.h" | 13 #import "ios/chrome/browser/ui/ui_util.h" |
16 | 14 |
17 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
18 #error "This file requires ARC support." | |
19 #endif | |
20 | |
21 namespace { | 15 namespace { |
22 | 16 |
23 // The maximum number of cards that should be staggered at a collapse point. | 17 // The maximum number of cards that should be staggered at a collapse point. |
24 const NSInteger kMaxVisibleStaggerCount = 4; | 18 const NSInteger kMaxVisibleStaggerCount = 4; |
25 // The amount that each of the staggered cards in a stack should be staggered | 19 // The amount that each of the staggered cards in a stack should be staggered |
26 // when fully collapsed. | 20 // when fully collapsed. |
27 const CGFloat kMinStackStaggerAmount = 4.0; | 21 const CGFloat kMinStackStaggerAmount = 4.0; |
28 // The amount that a card should overlap with a previous/subsequent card when | 22 // The amount that a card should overlap with a previous/subsequent card when |
29 // it is extended the maximum distance away (e.g., after a multitouch event). | 23 // it is extended the maximum distance away (e.g., after a multitouch event). |
30 const CGFloat kFullyExtendedCardOverlap = 8.0; | 24 const CGFloat kFullyExtendedCardOverlap = 8.0; |
31 // The amount that a card's position is allowed to drift toward overextension | 25 // The amount that a card's position is allowed to drift toward overextension |
32 // before the card is considered to be overextended (i.e., an epsilon to allow | 26 // before the card is considered to be overextended (i.e., an epsilon to allow |
33 // for floating-point imprecision). | 27 // for floating-point imprecision). |
34 const CGFloat kDistanceBeforeOverextension = 0.0001; | 28 const CGFloat kDistanceBeforeOverextension = 0.0001; |
35 // The factor by which scroll is decayed on overscroll. | 29 // The factor by which scroll is decayed on overscroll. |
36 const CGFloat kOverextensionDecayFactor = 2.0; | 30 const CGFloat kOverextensionDecayFactor = 2.0; |
37 // The amount by which a card is scrolled when asked to scroll it away from its | 31 // The amount by which a card is scrolled when asked to scroll it away from its |
38 // preceding neighbor. | 32 // preceding neighbor. |
39 const CGFloat kScrollAwayFromNeighborAmount = 200; | 33 const CGFloat kScrollAwayFromNeighborAmount = 200; |
40 | 34 |
41 } // namespace | 35 } // namespace |
42 | 36 |
43 @interface CardStackLayoutManager () { | 37 @interface CardStackLayoutManager () |
44 NSMutableArray* cards_; | |
45 // YES if the previous call to one of {|scrollCardAtIndex|, | |
46 // |handleMultitouchWithFirstDelta|} was to the former method; NO otherwise. | |
47 BOOL treatOverExtensionAsScroll_; | |
48 NSUInteger previousFirstPinchCardIndex_; | |
49 NSUInteger previousSecondPinchCardIndex_; | |
50 } | |
51 | 38 |
52 // Exposes |kMinStackStaggerAmount| for tests. | 39 // Exposes |kMinStackStaggerAmount| for tests. |
53 - (CGFloat)minStackStaggerAmount; | 40 - (CGFloat)minStackStaggerAmount; |
54 // Exposes |kScrollAwayFromNeighborAmount| for tests. | 41 // Exposes |kScrollAwayFromNeighborAmount| for tests. |
55 - (CGFloat)scrollCardAwayFromNeighborAmount; | 42 - (CGFloat)scrollCardAwayFromNeighborAmount; |
56 // Returns the current start stack limit allowing for overextension as follows: | 43 // Returns the current start stack limit allowing for overextension as follows: |
57 // - If the card at |index| is not overextended toward the start, returns | 44 // - If the card at |index| is not overextended toward the start, returns |
58 // |startLimit_|. | 45 // |startLimit_|. |
59 // - Otherwise, returns the value of the start limit such that the position of | 46 // - Otherwise, returns the value of the start limit such that the position of |
60 // the card at |index| in the start stack is its current position (with the | 47 // the card at |index| in the start stack is its current position (with the |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 @synthesize maximumOverextensionAmount = maximumOverextensionAmount_; | 187 @synthesize maximumOverextensionAmount = maximumOverextensionAmount_; |
201 @synthesize endLimit = endLimit_; | 188 @synthesize endLimit = endLimit_; |
202 @synthesize layoutAxisPosition = layoutAxisPosition_; | 189 @synthesize layoutAxisPosition = layoutAxisPosition_; |
203 @synthesize startLimit = startLimit_; | 190 @synthesize startLimit = startLimit_; |
204 @synthesize layoutIsVertical = layoutIsVertical_; | 191 @synthesize layoutIsVertical = layoutIsVertical_; |
205 @synthesize lastStartStackCardIndex = lastStartStackCardIndex_; | 192 @synthesize lastStartStackCardIndex = lastStartStackCardIndex_; |
206 @synthesize firstEndStackCardIndex = firstEndStackCardIndex_; | 193 @synthesize firstEndStackCardIndex = firstEndStackCardIndex_; |
207 | 194 |
208 - (id)init { | 195 - (id)init { |
209 if ((self = [super init])) { | 196 if ((self = [super init])) { |
210 cards_ = [[NSMutableArray alloc] init]; | 197 cards_.reset([[NSMutableArray alloc] init]); |
211 layoutIsVertical_ = YES; | 198 layoutIsVertical_ = YES; |
212 lastStartStackCardIndex_ = -1; | 199 lastStartStackCardIndex_ = -1; |
213 firstEndStackCardIndex_ = -1; | 200 firstEndStackCardIndex_ = -1; |
214 } | 201 } |
215 return self; | 202 return self; |
216 } | 203 } |
217 | 204 |
218 - (CGFloat)minStackStaggerAmount { | 205 - (CGFloat)minStackStaggerAmount { |
219 return kMinStackStaggerAmount; | 206 return kMinStackStaggerAmount; |
220 } | 207 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 lastStartStackCardIndex_ = -1; | 240 lastStartStackCardIndex_ = -1; |
254 firstEndStackCardIndex_ = -1; | 241 firstEndStackCardIndex_ = -1; |
255 [cards_ removeAllObjects]; | 242 [cards_ removeAllObjects]; |
256 } | 243 } |
257 | 244 |
258 - (void)setCardSize:(CGSize)size { | 245 - (void)setCardSize:(CGSize)size { |
259 cardSize_ = size; | 246 cardSize_ = size; |
260 NSUInteger i = 0; | 247 NSUInteger i = 0; |
261 CGFloat previousFirstCardOffset = 0; | 248 CGFloat previousFirstCardOffset = 0; |
262 CGFloat newFirstCardOffset = 0; | 249 CGFloat newFirstCardOffset = 0; |
263 for (StackCard* card in cards_) { | 250 for (StackCard* card in cards_.get()) { |
264 CGFloat offset = [self cardOffsetOnLayoutAxis:card]; | 251 CGFloat offset = [self cardOffsetOnLayoutAxis:card]; |
265 card.size = cardSize_; | 252 card.size = cardSize_; |
266 CGFloat newOffset = offset; | 253 CGFloat newOffset = offset; |
267 | 254 |
268 // Attempt to preserve card positions, but ensure that the deck starts | 255 // Attempt to preserve card positions, but ensure that the deck starts |
269 // within overextension limits and that all cards not in the start stack are | 256 // within overextension limits and that all cards not in the start stack are |
270 // within minimum/maximum separation limits of their preceding neighbors. | 257 // within minimum/maximum separation limits of their preceding neighbors. |
271 if (i == 0) { | 258 if (i == 0) { |
272 newOffset = std::max(newOffset, [self limitOfOverextensionTowardStart]); | 259 newOffset = std::max(newOffset, [self limitOfOverextensionTowardStart]); |
273 newOffset = std::min(newOffset, [self limitOfOverscrollTowardEnd]); | 260 newOffset = std::min(newOffset, [self limitOfOverscrollTowardEnd]); |
(...skipping 21 matching lines...) Expand all Loading... |
295 for (NSUInteger i = 0; i < [cards_ count]; i++) { | 282 for (NSUInteger i = 0; i < [cards_ count]; i++) { |
296 LayoutRectPosition position = [[cards_ objectAtIndex:i] layout].position; | 283 LayoutRectPosition position = [[cards_ objectAtIndex:i] layout].position; |
297 CGFloat prevLayoutAxisOffset = | 284 CGFloat prevLayoutAxisOffset = |
298 layoutIsVertical_ ? position.leading : position.originY; | 285 layoutIsVertical_ ? position.leading : position.originY; |
299 [self moveOriginOfCardAtIndex:i toOffset:prevLayoutAxisOffset]; | 286 [self moveOriginOfCardAtIndex:i toOffset:prevLayoutAxisOffset]; |
300 } | 287 } |
301 } | 288 } |
302 | 289 |
303 - (void)setLayoutAxisPosition:(CGFloat)position { | 290 - (void)setLayoutAxisPosition:(CGFloat)position { |
304 layoutAxisPosition_ = position; | 291 layoutAxisPosition_ = position; |
305 for (StackCard* card in cards_) { | 292 for (StackCard* card in cards_.get()) { |
306 LayoutRect layout = card.layout; | 293 LayoutRect layout = card.layout; |
307 if (layoutIsVertical_) | 294 if (layoutIsVertical_) |
308 layout.position.leading = position - 0.5 * layout.size.width; | 295 layout.position.leading = position - 0.5 * layout.size.width; |
309 else | 296 else |
310 layout.position.originY = position - 0.5 * layout.size.height; | 297 layout.position.originY = position - 0.5 * layout.size.height; |
311 card.layout = layout; | 298 card.layout = layout; |
312 } | 299 } |
313 } | 300 } |
314 | 301 |
315 - (NSArray*)cards { | 302 - (NSArray*)cards { |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1134 CGFloat edgeOffset = endLimit_ - labelOffset; | 1121 CGFloat edgeOffset = endLimit_ - labelOffset; |
1135 return cardOffset >= edgeOffset; | 1122 return cardOffset >= edgeOffset; |
1136 } else { | 1123 } else { |
1137 CGFloat separation = | 1124 CGFloat separation = |
1138 [self distanceBetweenCardAtIndex:index andCardAtIndex:(index + 1)]; | 1125 [self distanceBetweenCardAtIndex:index andCardAtIndex:(index + 1)]; |
1139 return separation <= labelOffset; | 1126 return separation <= labelOffset; |
1140 } | 1127 } |
1141 } | 1128 } |
1142 | 1129 |
1143 - (void)setSynchronizeCardViews:(BOOL)synchronizeViews { | 1130 - (void)setSynchronizeCardViews:(BOOL)synchronizeViews { |
1144 for (StackCard* card in cards_) { | 1131 for (StackCard* card in cards_.get()) { |
1145 card.synchronizeView = synchronizeViews; | 1132 card.synchronizeView = synchronizeViews; |
1146 } | 1133 } |
1147 } | 1134 } |
1148 | 1135 |
1149 - (BOOL)isInStartStack:(NSUInteger)index { | 1136 - (BOOL)isInStartStack:(NSUInteger)index { |
1150 DCHECK(index < [cards_ count]); | 1137 DCHECK(index < [cards_ count]); |
1151 return ((NSInteger)index <= lastStartStackCardIndex_); | 1138 return ((NSInteger)index <= lastStartStackCardIndex_); |
1152 } | 1139 } |
1153 | 1140 |
1154 - (BOOL)isInEndStack:(NSUInteger)index { | 1141 - (BOOL)isInEndStack:(NSUInteger)index { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 return 0; | 1188 return 0; |
1202 return std::abs([self cardOffsetOnLayoutAxis:[cards_ firstObject]] - | 1189 return std::abs([self cardOffsetOnLayoutAxis:[cards_ firstObject]] - |
1203 startLimit_); | 1190 startLimit_); |
1204 } | 1191 } |
1205 | 1192 |
1206 - (NSUInteger)fannedStackCount { | 1193 - (NSUInteger)fannedStackCount { |
1207 return floor((endLimit_ - startLimit_) / maxStagger_); | 1194 return floor((endLimit_ - startLimit_) / maxStagger_); |
1208 } | 1195 } |
1209 | 1196 |
1210 @end | 1197 @end |
OLD | NEW |