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