bm-core-ui 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1624 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/build/@types/index.d.ts +14078 -0
- package/build/BMCodeEditor/BMCodeEditor.js +707 -0
- package/build/BMCollectionView/BMCollectionView.js +5861 -0
- package/build/BMCollectionView/BMCollectionViewCell.js +688 -0
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +4467 -0
- package/build/BMCollectionView/BMCollectionViewLayout.js +830 -0
- package/build/BMCollectionView/BMCollectionViewLayoutAttributes.js +673 -0
- package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +491 -0
- package/build/BMCollectionView/BMCollectionViewStackLayout.js +634 -0
- package/build/BMCollectionView/BMCollectionViewTileLayout.js +1121 -0
- package/build/BMCoreUI.css +2833 -0
- package/build/BMView/BMAttributedLabelView.js +310 -0
- package/build/BMView/BMLayoutConstraint_v2.5.js +1813 -0
- package/build/BMView/BMLayoutGuide.js +192 -0
- package/build/BMView/BMLayoutSizeClass.js +466 -0
- package/build/BMView/BMMenu.js +574 -0
- package/build/BMView/BMScrollView.js +247 -0
- package/build/BMView/BMTextField.js +512 -0
- package/build/BMView/BMTextFieldDelegate.js +71 -0
- package/build/BMView/BMView_v2.5.js +3572 -0
- package/build/BMView/BMViewport.js +221 -0
- package/build/BMViewLayoutEditor/BMLayoutEditor.js +6117 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorConstraintSettings.js +417 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorDelegate.js +59 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +1653 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettings.js +1480 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingsComplexCells.js +431 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingsDelegate.js +46 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorVariablesController.js +460 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorViewGroupSettings.js +293 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorViewSettings.js +382 -0
- package/build/BMViewLayoutEditor/BMLayoutVariableProvider.js +202 -0
- package/build/BMWindow/BMConfirmationPopup.js +477 -0
- package/build/BMWindow/BMKeyboardShortcut.js +151 -0
- package/build/BMWindow/BMPopover/BMPopover.js +492 -0
- package/build/BMWindow/BMToolWindow.js +71 -0
- package/build/BMWindow/BMWindow.js +2000 -0
- package/build/Core/BMAnimationContext.js +1181 -0
- package/build/Core/BMColor.js +991 -0
- package/build/Core/BMCoreUI.js +470 -0
- package/build/Core/BMFunctionCollection.js +110 -0
- package/build/Core/BMIndexPath.js +165 -0
- package/build/Core/BMInset.js +138 -0
- package/build/Core/BMKeyPath.js +100 -0
- package/build/Core/BMPoint.js +291 -0
- package/build/Core/BMRect.js +556 -0
- package/build/Core/BMSize.js +137 -0
- package/build/iScroll/LICENSE +22 -0
- package/build/iScroll/iscroll-probe.js +2154 -0
- package/build/images/AlignBottom.png +0 -0
- package/build/images/AlignCenterX.png +0 -0
- package/build/images/AlignCenterY.png +0 -0
- package/build/images/AlignLeading.png +0 -0
- package/build/images/AlignTop.png +0 -0
- package/build/images/AlignTrailing.png +0 -0
- package/build/images/AllConstraints.png +0 -0
- package/build/images/BottomConstraint.png +0 -0
- package/build/images/CenterXConstraint.png +0 -0
- package/build/images/CenterYConstraint.png +0 -0
- package/build/images/CoreUI2.png +0 -0
- package/build/images/CoreUI2@2x.png +0 -0
- package/build/images/Desktop.png +0 -0
- package/build/images/DesktopMini.png +0 -0
- package/build/images/EqualHeight.png +0 -0
- package/build/images/EqualHorizontalSpacing.png +0 -0
- package/build/images/EqualHorizontalSpacingInSuperview.png +0 -0
- package/build/images/EqualVerticalSpacing.png +0 -0
- package/build/images/EqualVerticalSpacingInSuperview.png +0 -0
- package/build/images/EqualWidth.png +0 -0
- package/build/images/HeightConstraint.png +0 -0
- package/build/images/InactiveConstraints.png +0 -0
- package/build/images/Layout.png +0 -0
- package/build/images/LayoutVariables.png +0 -0
- package/build/images/LeftConstraint.png +0 -0
- package/build/images/OwnConstraints.png +0 -0
- package/build/images/Phone.png +0 -0
- package/build/images/PhoneLandscape.png +0 -0
- package/build/images/PhoneLandscapeMini.png +0 -0
- package/build/images/PhoneMini.png +0 -0
- package/build/images/PhonePortrait.png +0 -0
- package/build/images/PhonePortraitMini.png +0 -0
- package/build/images/Properties.png +0 -0
- package/build/images/RightConstraint.png +0 -0
- package/build/images/SubviewConstraints.png +0 -0
- package/build/images/Tablet.png +0 -0
- package/build/images/TabletLandscape.png +0 -0
- package/build/images/TabletLandscapeMini.png +0 -0
- package/build/images/TabletMini.png +0 -0
- package/build/images/TabletPortrait.png +0 -0
- package/build/images/TabletPortraitMini.png +0 -0
- package/build/images/TopConstraint.png +0 -0
- package/build/images/WidthConstraint.png +0 -0
- package/build/index.js +40 -0
- package/lib/@types/BMCoreUI.min.d.ts +14078 -0
- package/lib/BMCoreUI.min.js +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {YES, NO, BMExtend, BMNumberByInterpolatingNumbersWithFraction, BMScrollingDirectionVertical} from '../Core/BMCoreUI'
|
|
4
|
+
import {BMInsetMake} from '../Core/BMInset'
|
|
5
|
+
import {BMPointMake} from '../Core/BMPoint'
|
|
6
|
+
import {BMSizeMake} from '../Core/BMSize'
|
|
7
|
+
import {BMRectMakeWithX} from '../Core/BMRect'
|
|
8
|
+
import {BMCollectionViewLayoutAttributesMakeForCellAtIndexPath} from './BMCollectionViewLayoutAttributes'
|
|
9
|
+
import {BMCollectionViewLayout} from './BMCollectionViewLayout'
|
|
10
|
+
|
|
11
|
+
// @type BMCollectionViewStackLayout extends BMCollectionViewLayout
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The stack layout is a vertically scrolling layout that presents cells as a stack, where the current cell appears above the other cells.
|
|
15
|
+
* In the stack layout, previous cells appear behind the current cell, while upcoming cells are hidden.
|
|
16
|
+
*
|
|
17
|
+
* When scrolling in the stack layout, the scroll position will always snap back to fully show a single cell.
|
|
18
|
+
*
|
|
19
|
+
* The stack layout does not support sections or supplementary views.
|
|
20
|
+
*/
|
|
21
|
+
export function BMCollectionViewStackLayout() {}; // <constructor>
|
|
22
|
+
|
|
23
|
+
BMCollectionViewStackLayout.prototype = BMExtend({}, BMCollectionViewLayout.prototype, {
|
|
24
|
+
|
|
25
|
+
// @override - BMCollectionViewLayout
|
|
26
|
+
get supportsCopying() {
|
|
27
|
+
return YES;
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Controls how the stack layout will appear when there is a single cell in the data set.
|
|
32
|
+
* When this property is set to YES, insets are ignored when there is a single cell and that cell will occupy
|
|
33
|
+
* the collection view's entire area.
|
|
34
|
+
* If it is set to NO, the single cell will have the usual insets applied to it.
|
|
35
|
+
*/
|
|
36
|
+
_showsSingleCellFullScreen: NO, // <Boolean>
|
|
37
|
+
|
|
38
|
+
get showsSingleCellFullScreen() { return this._showsSingleCellFullScreen; },
|
|
39
|
+
set showsSingleCellFullScreen(shows) {
|
|
40
|
+
this._showsSingleCellFullScreen = shows;
|
|
41
|
+
this.invalidateLayout();
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* When enabled, stack layout will only show the first cell in the data set, without any padding.
|
|
46
|
+
*/
|
|
47
|
+
_showsSingleCell: NO, // <Boolean>
|
|
48
|
+
|
|
49
|
+
get showsSingleCell() { return this._showsSingleCell; },
|
|
50
|
+
set showsSingleCell(shows) {
|
|
51
|
+
this._showsSingleCell = shows;
|
|
52
|
+
this.invalidateLayout();
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Controls the edges between the content and the collection view.
|
|
57
|
+
*/
|
|
58
|
+
_insets: BMInsetMake(88, 88, 88, 88), // <BMInset>
|
|
59
|
+
|
|
60
|
+
get insets() { return this._insets.copy(); },
|
|
61
|
+
set insets(insets) {
|
|
62
|
+
this._insets = insets.copy();
|
|
63
|
+
this.invalidateLayout();
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Controls the spread between background cells.
|
|
68
|
+
*/
|
|
69
|
+
_spread: 22, // <Number>
|
|
70
|
+
|
|
71
|
+
get spread() { return this._spread; },
|
|
72
|
+
set spread(spread) {
|
|
73
|
+
this._spread = spread;
|
|
74
|
+
this.invalidateLayout();
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Controls how many background cells will be shown.
|
|
79
|
+
*/
|
|
80
|
+
_numberOfBackgroundCells: 3, // <Number>
|
|
81
|
+
|
|
82
|
+
get numberOfBackgroundCells() { return this._numberOfBackgroundCells; },
|
|
83
|
+
set numberOfBackgroundCells(number) {
|
|
84
|
+
this._numberOfBackgroundCells = number;
|
|
85
|
+
this.invalidateLayout();
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Controls the minimum scale for background cells.
|
|
90
|
+
*/
|
|
91
|
+
_minimumScale: .9, // <Number>
|
|
92
|
+
|
|
93
|
+
get minimumScale() { return this._minimumScale; },
|
|
94
|
+
set minimumScale(scale) {
|
|
95
|
+
this._minimumScale = scale;
|
|
96
|
+
this.invalidateLayout();
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Controls whether cells behind the topmost cell are blurred.
|
|
101
|
+
*/
|
|
102
|
+
_blursBackgroundCells: NO, // <Boolean>
|
|
103
|
+
|
|
104
|
+
get blursBackgroundCells() { return this._blursBackgroundCells; },
|
|
105
|
+
set blursBackgroundCells(blurs) {
|
|
106
|
+
this._blursBackgroundCells = blurs;
|
|
107
|
+
this.invalidateLayout();
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Controls the maximum blur of background cells.
|
|
112
|
+
*/
|
|
113
|
+
_maximumBlur: 15, // <Number>
|
|
114
|
+
|
|
115
|
+
get maximumBlur() { return this._maximumBlur; },
|
|
116
|
+
set maximumBlur(blur) {
|
|
117
|
+
this._maximumBlur = blur;
|
|
118
|
+
this.invalidateLayout();
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Controls whether new cells scroll in with a rotation effect.
|
|
123
|
+
*/
|
|
124
|
+
_rotatesCells: NO, // <Boolean>
|
|
125
|
+
|
|
126
|
+
get rotatesCells() { return this._rotatesCells; },
|
|
127
|
+
set rotatesCells(rotates) {
|
|
128
|
+
this._rotatesCells = rotates;
|
|
129
|
+
this.invalidateLayout();
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Controls the maximum rotation of cells, in degrees.
|
|
134
|
+
*/
|
|
135
|
+
_rotation: -90, // <Number>
|
|
136
|
+
|
|
137
|
+
get rotation() { return this._rotation; },
|
|
138
|
+
set rotation(rotation) {
|
|
139
|
+
this._rotation = rotation;
|
|
140
|
+
this.invalidateLayout();
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Cached number of items in the current data set.
|
|
145
|
+
*/
|
|
146
|
+
_numberOfObjects: 0, // <Number>
|
|
147
|
+
|
|
148
|
+
// @override - BMCollectionViewLayout
|
|
149
|
+
shouldInvalidateLayoutForFrameChange: function () {
|
|
150
|
+
return YES;
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
// @override - BMCollectionViewLayout
|
|
154
|
+
shouldInvalidateLayoutForBoundsChange: function () {
|
|
155
|
+
return YES;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
// @override - BMCollectionViewLayout
|
|
159
|
+
collectionViewWillStartUpdates: function () {
|
|
160
|
+
this.prepareLayout();
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
prepareLayout: function () {
|
|
164
|
+
var numberOfObjects = 0;
|
|
165
|
+
var numberOfSections = this.collectionView.numberOfSections();
|
|
166
|
+
|
|
167
|
+
for (var i = 0; i < numberOfSections; i++) {
|
|
168
|
+
numberOfObjects += this.collectionView.numberOfObjectsInSectionAtIndex(i);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this._numberOfObjects = numberOfObjects;
|
|
172
|
+
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
contentSize: function () {
|
|
176
|
+
if (this._showsSingleCell) {
|
|
177
|
+
return this.collectionView.frame.size.copy();
|
|
178
|
+
}
|
|
179
|
+
return BMSizeMake(this.collectionView.frame.size.width, this.collectionView.frame.size.height * this._numberOfObjects);
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Returns the index path that appears before the given index path in the data set.
|
|
184
|
+
* If the given index path is the first index path in the data set, the result will be undefined.
|
|
185
|
+
* @param indexPath <BMIndexPath> The current index path.
|
|
186
|
+
* @return <BMIndexPath> The previous index path if it could be found, undefiend otherwise.
|
|
187
|
+
*/
|
|
188
|
+
previousIndexPathWithIndexPath: function (indexPath) {
|
|
189
|
+
if (indexPath.row) {
|
|
190
|
+
return this.collectionView.indexPathForObjectAtRow(indexPath.row - 1, {inSectionAtIndex: indexPath.section});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
var section = indexPath.section - 1;
|
|
194
|
+
while (section >= 0) {
|
|
195
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(section);
|
|
196
|
+
|
|
197
|
+
if (numberOfObjects) {
|
|
198
|
+
return this.collectionView.indexPathForObjectAtRow(numberOfObjects - 1, {inSectionAtIndex: section});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
section--;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Returns the index path that appears after the given index path in the data set.
|
|
207
|
+
* If the given index path is the last index path in the data set, the result will be undefined.
|
|
208
|
+
* @param indexPath <BMIndexPath> The current index path.
|
|
209
|
+
* @return <BMIndexPath> The next index path if it could be found, undefiend otherwise.
|
|
210
|
+
*/
|
|
211
|
+
nextIndexPathWithIndexPath: function (indexPath) {
|
|
212
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(indexPath.section);
|
|
213
|
+
if (indexPath.row < numberOfObjects - 1) {
|
|
214
|
+
return this.collectionView.indexPathForObjectAtRow(indexPath.row + 1, {inSectionAtIndex: indexPath.section});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
var numberOfSections = this.collectionView.numberOfSections();
|
|
218
|
+
var section = indexPath.section + 1;
|
|
219
|
+
while (section < numberOfSections) {
|
|
220
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(section);
|
|
221
|
+
|
|
222
|
+
if (numberOfObjects) {
|
|
223
|
+
return this.collectionView.indexPathForObjectAtRow(0, {inSectionAtIndex: section});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
section++;
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
// @override - BMCollectionViewLayout
|
|
231
|
+
attributesForElementsInRect: function (rect) {
|
|
232
|
+
if (this._showsSingleCell) {
|
|
233
|
+
var attributes = [];
|
|
234
|
+
|
|
235
|
+
if (this.collectionView.numberOfSections() && this.collectionView.numberOfObjectsInSectionAtIndex(0)) {
|
|
236
|
+
var attribute = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(
|
|
237
|
+
this.collectionView.indexPathForObjectAtRow(0, {inSectionAtIndex: 0})
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
attribute.frame = this.collectionView.frame.copy();
|
|
241
|
+
attribute.frame.origin = BMPointMake();
|
|
242
|
+
|
|
243
|
+
attributes.push(attribute);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return attributes;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
var scrollOffset = this.collectionView.scrollOffset;
|
|
250
|
+
var collectionViewHeight = this.collectionView.frame.size.height;
|
|
251
|
+
var collectionViewWidth = this.collectionView.frame.size.width;
|
|
252
|
+
|
|
253
|
+
var topVisibleMargin = scrollOffset.y;
|
|
254
|
+
var bottomVisibleMargin = scrollOffset.y + collectionViewHeight;
|
|
255
|
+
|
|
256
|
+
var cellWidth = collectionViewWidth - this.insets.left - this.insets.right;
|
|
257
|
+
var cellHeight = collectionViewHeight - this.insets.top - this.insets.bottom;
|
|
258
|
+
|
|
259
|
+
var attributes = [];
|
|
260
|
+
|
|
261
|
+
var currentOffset = 0;
|
|
262
|
+
|
|
263
|
+
// Find the current topmost cell. This will be the first cell whose bottom edge is within the visible area
|
|
264
|
+
var indexPath;
|
|
265
|
+
var numberOfSections = this.collectionView.numberOfSections();
|
|
266
|
+
for (var i = 0; i < numberOfSections; i++) {
|
|
267
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(i);
|
|
268
|
+
|
|
269
|
+
for (var j = 0; j < numberOfObjects; j++) {
|
|
270
|
+
currentOffset += collectionViewHeight;
|
|
271
|
+
|
|
272
|
+
if (currentOffset >= topVisibleMargin && currentOffset <= bottomVisibleMargin) {
|
|
273
|
+
indexPath = this.collectionView.indexPathForObjectAtRow(j, {inSectionAtIndex: i});
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// If the index path was found, stop looking
|
|
279
|
+
if (indexPath) break;
|
|
280
|
+
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// If no index path was found, return an empty array.
|
|
284
|
+
if (!indexPath) return attributes;
|
|
285
|
+
|
|
286
|
+
var spread = this._spread;
|
|
287
|
+
|
|
288
|
+
// The displacement percentage represents how far away the topmost cell is from the scroll offset.
|
|
289
|
+
var displacementPercentage = (collectionViewHeight - currentOffset + topVisibleMargin) / collectionViewHeight;
|
|
290
|
+
|
|
291
|
+
var displacementPixels = (this._spread * displacementPercentage) | 0;
|
|
292
|
+
|
|
293
|
+
var scalePerCell = (1 - this._minimumScale) / (this._numberOfBackgroundCells + 1);
|
|
294
|
+
var opacityPerCell = 1 / (this._numberOfBackgroundCells + 1);
|
|
295
|
+
var blurPerCell = this._maximumBlur / (this._numberOfBackgroundCells + 1);
|
|
296
|
+
|
|
297
|
+
// Create the attributes for the topmost cell.
|
|
298
|
+
var currentCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(indexPath);
|
|
299
|
+
currentCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
300
|
+
// The topmost cell's position is adjusted so it appears in the center of the view
|
|
301
|
+
y: topVisibleMargin + this.insets.top - displacementPixels,
|
|
302
|
+
width: cellWidth,
|
|
303
|
+
height: cellHeight
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
currentCellAttributes.style.zIndex = 2 * this._numberOfBackgroundCells + 4;
|
|
307
|
+
currentCellAttributes.style.scaleX = 1 - scalePerCell * displacementPercentage;
|
|
308
|
+
currentCellAttributes.style.scaleY = 1 - scalePerCell * displacementPercentage;
|
|
309
|
+
currentCellAttributes.style.opacity = 1 - opacityPerCell * displacementPercentage;
|
|
310
|
+
if (this._blursBackgroundCells) currentCellAttributes.style.blur = (displacementPercentage * blurPerCell) + 'px';
|
|
311
|
+
|
|
312
|
+
if (this._rotatesCells) {
|
|
313
|
+
currentCellAttributes.style.rotateX = (this.numberOfBackgroundCells - 1) / 10000 + 'deg';
|
|
314
|
+
currentCellAttributes.style.transformOriginX = '50%';
|
|
315
|
+
currentCellAttributes.style.transformOriginY = '100%';
|
|
316
|
+
currentCellAttributes.style.translateZ = 2 * this._numberOfBackgroundCells + 4 + 'px';
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
attributes.push(currentCellAttributes);
|
|
320
|
+
|
|
321
|
+
// Create the attributes for the next cell
|
|
322
|
+
var nextIndexPath = this.nextIndexPathWithIndexPath(indexPath);
|
|
323
|
+
if (nextIndexPath) {
|
|
324
|
+
let baseY = currentOffset - this.insets.bottom + this.insets.top / 3;
|
|
325
|
+
let expectedY = currentOffset + this.insets.top;
|
|
326
|
+
|
|
327
|
+
// Adjust the Y so the next cell is visible when the current cell is on screen
|
|
328
|
+
var nextCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(nextIndexPath);
|
|
329
|
+
nextCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
330
|
+
y: BMNumberByInterpolatingNumbersWithFraction(baseY, expectedY, displacementPercentage),
|
|
331
|
+
width: cellWidth,
|
|
332
|
+
height: cellHeight
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
nextCellAttributes.style.zIndex = this._numberOfBackgroundCells * 2 + 6;
|
|
336
|
+
|
|
337
|
+
if (this._rotatesCells) {
|
|
338
|
+
nextCellAttributes.style.rotateX = BMNumberByInterpolatingNumbersWithFraction(this._rotation, 0, displacementPercentage) + 'deg';
|
|
339
|
+
nextCellAttributes.style.transformOriginX = '50%';
|
|
340
|
+
nextCellAttributes.style.transformOriginY = '100%';
|
|
341
|
+
nextCellAttributes.style.translateZ = this._numberOfBackgroundCells * 2 + 6 + 'px';
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
attributes.push(nextCellAttributes);
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
// Create the attributes for the upcoming cell
|
|
348
|
+
let upcomingIndexPath = this.nextIndexPathWithIndexPath(nextIndexPath);
|
|
349
|
+
if (upcomingIndexPath) {
|
|
350
|
+
//let upcomingDisplacement = displacementPercentage >= 1 ? displacementPercentage - 1 : displacementPercentage;
|
|
351
|
+
let upcomingOffset = currentOffset + this.collectionView.frame.size.height;
|
|
352
|
+
|
|
353
|
+
let baseY = upcomingOffset - this.insets.bottom + this.insets.top / 3;
|
|
354
|
+
let expectedY = upcomingOffset + this.insets.top;
|
|
355
|
+
|
|
356
|
+
// Adjust the Y so the next cell is visible when the current cell is on screen
|
|
357
|
+
var nextCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(upcomingIndexPath);
|
|
358
|
+
nextCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
359
|
+
y: baseY, //BMNumberByInterpolatingNumbersWithFraction(baseY, expectedY, 1 - displacementPercentage),
|
|
360
|
+
width: cellWidth,
|
|
361
|
+
height: cellHeight
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
nextCellAttributes.style.zIndex = this._numberOfBackgroundCells * 2 + 8;
|
|
365
|
+
|
|
366
|
+
if (this._rotatesCells) {
|
|
367
|
+
nextCellAttributes.style.rotateX = this._rotation + 'deg';
|
|
368
|
+
nextCellAttributes.style.transformOriginX = '50%';
|
|
369
|
+
nextCellAttributes.style.transformOriginY = '100%';
|
|
370
|
+
nextCellAttributes.style.translateZ = this._numberOfBackgroundCells * 2 + 8 + 'px';
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
attributes.push(nextCellAttributes);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Create the attributes for the previous cells
|
|
378
|
+
for (var i = 0; i < this._numberOfBackgroundCells; i++) {
|
|
379
|
+
var previousIndexPath = this.previousIndexPathWithIndexPath(indexPath);
|
|
380
|
+
|
|
381
|
+
if (!previousIndexPath) return attributes;
|
|
382
|
+
|
|
383
|
+
var previousCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(previousIndexPath);
|
|
384
|
+
previousCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
385
|
+
y: topVisibleMargin + this.insets.top - displacementPixels - (i + 1) * this._spread,
|
|
386
|
+
width: cellWidth,
|
|
387
|
+
height: cellHeight
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
previousCellAttributes.style.zIndex = 2 * (this._numberOfBackgroundCells + 1 - i);
|
|
391
|
+
previousCellAttributes.style.scaleX = 1 - scalePerCell * displacementPercentage - scalePerCell * (i + 1);
|
|
392
|
+
previousCellAttributes.style.scaleY = 1 - scalePerCell * displacementPercentage - scalePerCell * (i + 1);
|
|
393
|
+
previousCellAttributes.style.opacity = 1 - opacityPerCell * displacementPercentage - opacityPerCell * (i + 1);
|
|
394
|
+
if (this._blursBackgroundCells) previousCellAttributes.style.blur = ((displacementPercentage + i + 1) * blurPerCell) + 'px';
|
|
395
|
+
|
|
396
|
+
if (this._rotatesCells) {
|
|
397
|
+
previousCellAttributes.style.rotateX = (this.numberOfBackgroundCells + i) / 10000 + 'deg';
|
|
398
|
+
previousCellAttributes.style.transformOriginX = '50%';
|
|
399
|
+
previousCellAttributes.style.transformOriginY = '100%';
|
|
400
|
+
previousCellAttributes.style.translateZ = 2 * (this._numberOfBackgroundCells + 1 - i) + 'px';
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
attributes.push(previousCellAttributes);
|
|
404
|
+
|
|
405
|
+
indexPath = previousIndexPath;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return attributes;
|
|
409
|
+
},
|
|
410
|
+
|
|
411
|
+
// @override - BMCollectionViewLayout
|
|
412
|
+
attributesForCellAtIndexPath: function (indexPath) {
|
|
413
|
+
if (this._showsSingleCell) {
|
|
414
|
+
var attribute = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(indexPath);
|
|
415
|
+
|
|
416
|
+
attribute.frame = this.collectionView.frame.copy();
|
|
417
|
+
attribute.frame.origin = BMPointMake();
|
|
418
|
+
|
|
419
|
+
if (indexPath.row != 0 || indexPath.section != 0) {
|
|
420
|
+
attribute.isHidden = YES;
|
|
421
|
+
attribute.style.opacity = 0;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return attribute;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
var scrollOffset = this.collectionView.scrollOffset;
|
|
428
|
+
var collectionViewHeight = this.collectionView.frame.size.height;
|
|
429
|
+
var collectionViewWidth = this.collectionView.frame.size.width;
|
|
430
|
+
|
|
431
|
+
var topVisibleMargin = scrollOffset.y;
|
|
432
|
+
var bottomVisibleMargin = scrollOffset.y + collectionViewHeight;
|
|
433
|
+
|
|
434
|
+
var cellWidth = collectionViewWidth - this.insets.left - this.insets.right;
|
|
435
|
+
var cellHeight = collectionViewHeight - this.insets.top - this.insets.bottom;
|
|
436
|
+
|
|
437
|
+
var attributes = [];
|
|
438
|
+
|
|
439
|
+
var currentOffset = 0;
|
|
440
|
+
|
|
441
|
+
// Find the current topmost cell. This will be the first cell whose bottom edge is within the visible area
|
|
442
|
+
var topmostIndexPath;
|
|
443
|
+
var numberOfSections = this.collectionView.numberOfSections();
|
|
444
|
+
for (var i = 0; i < numberOfSections; i++) {
|
|
445
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(i);
|
|
446
|
+
|
|
447
|
+
for (var j = 0; j < numberOfObjects; j++) {
|
|
448
|
+
currentOffset += collectionViewHeight;
|
|
449
|
+
|
|
450
|
+
if (currentOffset >= topVisibleMargin && currentOffset <= bottomVisibleMargin) {
|
|
451
|
+
topmostIndexPath = this.collectionView.indexPathForObjectAtRow(j, {inSectionAtIndex: i});
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// If the index path was found, stop looking
|
|
457
|
+
if (topmostIndexPath) break;
|
|
458
|
+
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
var spread = this._spread;
|
|
462
|
+
|
|
463
|
+
// The displacement percentage represents how far away the topmost cell is from the scroll offset.
|
|
464
|
+
var displacementPercentage = (collectionViewHeight - currentOffset + topVisibleMargin) / collectionViewHeight;
|
|
465
|
+
|
|
466
|
+
var displacementPixels = (this._spread * displacementPercentage) | 0;
|
|
467
|
+
|
|
468
|
+
var scalePerCell = (1 - this._minimumScale) / (this._numberOfBackgroundCells + 1);
|
|
469
|
+
var opacityPerCell = 1 / (this._numberOfBackgroundCells + 1);
|
|
470
|
+
var blurPerCell = this._maximumBlur / (this._numberOfBackgroundCells + 1);
|
|
471
|
+
|
|
472
|
+
if (indexPath.isEqualToIndexPath(topmostIndexPath, {usingComparator: this.collectionView.identityComparator})) {
|
|
473
|
+
|
|
474
|
+
var currentCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(indexPath);
|
|
475
|
+
currentCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
476
|
+
// The topmost cell's position is adjusted so it appears in the center of the view
|
|
477
|
+
y: topVisibleMargin + this.insets.top - displacementPixels,
|
|
478
|
+
width: cellWidth,
|
|
479
|
+
height: cellHeight
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
currentCellAttributes.style.zIndex = this._numberOfBackgroundCells + 2;
|
|
483
|
+
currentCellAttributes.style.scaleX = 1 - scalePerCell * displacementPercentage;
|
|
484
|
+
currentCellAttributes.style.scaleY = 1 - scalePerCell * displacementPercentage;
|
|
485
|
+
currentCellAttributes.style.opacity = 1 - opacityPerCell * displacementPercentage;
|
|
486
|
+
if (this._blursBackgroundCells) currentCellAttributes.style.blur = (displacementPercentage * blurPerCell) + 'px';
|
|
487
|
+
|
|
488
|
+
return currentCellAttributes;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Create the attributes for the next cell
|
|
492
|
+
var nextIndexPath = this.nextIndexPathWithIndexPath(topmostIndexPath);
|
|
493
|
+
if (nextIndexPath && indexPath.isEqualToIndexPath(nextIndexPath, {usingComparator: this.collectionView.identityComparator})) {
|
|
494
|
+
var nextCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(nextIndexPath);
|
|
495
|
+
nextCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
496
|
+
y: currentOffset + this.insets.top,
|
|
497
|
+
width: cellWidth,
|
|
498
|
+
height: cellHeight
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
nextCellAttributes.style.zIndex = this._numberOfBackgroundCells + 3;
|
|
502
|
+
|
|
503
|
+
return nextCellAttributes;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (indexPath.section > nextIndexPath.section || (indexPath.section == nextIndexPath.section && indexPath.row > nextIndexPath.row)) {
|
|
507
|
+
var y = 0;
|
|
508
|
+
for (var i = 0; i < indexPath.section; i++) {
|
|
509
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(i);
|
|
510
|
+
|
|
511
|
+
y += collectionViewHeight * numberOfObjects;
|
|
512
|
+
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
y += collectionViewHeight * indexPath.row;
|
|
516
|
+
|
|
517
|
+
var attributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(indexPath);
|
|
518
|
+
attributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
519
|
+
y: y,
|
|
520
|
+
width: cellWidth,
|
|
521
|
+
height: cellHeight
|
|
522
|
+
});
|
|
523
|
+
attributes.isHidden = YES;
|
|
524
|
+
attributes.opacity = 0;
|
|
525
|
+
return attributes;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Create the attributes for the previous cells
|
|
529
|
+
for (var i = 0; i < this._numberOfBackgroundCells; i++) {
|
|
530
|
+
var previousIndexPath = this.previousIndexPathWithIndexPath(topmostIndexPath);
|
|
531
|
+
|
|
532
|
+
if (!previousIndexPath) break;
|
|
533
|
+
|
|
534
|
+
if (!indexPath.isEqualToIndexPath(previousIndexPath, {usingComparator: this.collectionView.identityComparator})) {
|
|
535
|
+
|
|
536
|
+
topmostIndexPath = previousIndexPath;
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
var previousCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(previousIndexPath);
|
|
541
|
+
previousCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
542
|
+
y: topVisibleMargin + this.insets.top - displacementPixels - (i + 1) * this._spread,
|
|
543
|
+
width: cellWidth,
|
|
544
|
+
height: cellHeight
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
previousCellAttributes.style.zIndex = this._numberOfBackgroundCells + 1 - i;
|
|
548
|
+
previousCellAttributes.style.scaleX = 1 - scalePerCell * displacementPercentage - scalePerCell * (i + 1);
|
|
549
|
+
previousCellAttributes.style.scaleY = 1 - scalePerCell * displacementPercentage - scalePerCell * (i + 1);
|
|
550
|
+
previousCellAttributes.style.opacity = 1 - opacityPerCell * displacementPercentage - opacityPerCell * (i + 1);
|
|
551
|
+
if (this._blursBackgroundCells) previousCellAttributes.style.blur = ((displacementPercentage + i + 1) * blurPerCell) + 'px';
|
|
552
|
+
|
|
553
|
+
return previousCellAttributes;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
var previousCellAttributes = BMCollectionViewLayoutAttributesMakeForCellAtIndexPath(indexPath);
|
|
557
|
+
previousCellAttributes.frame = BMRectMakeWithX(this.insets.left, {
|
|
558
|
+
y: topVisibleMargin + this.insets.top - (this._numberOfBackgroundCells + 1) * this._spread,
|
|
559
|
+
width: cellWidth,
|
|
560
|
+
height: cellHeight
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
previousCellAttributes.style.zIndex = 0;
|
|
564
|
+
previousCellAttributes.style.scaleX = this._minimumScale;
|
|
565
|
+
previousCellAttributes.style.scaleY = this._minimumScale;
|
|
566
|
+
previousCellAttributes.style.opacity = 0;
|
|
567
|
+
if (this._blursBackgroundCells) previousCellAttributes.style.blur = (this._maximumBlur) + 'px';
|
|
568
|
+
|
|
569
|
+
return previousCellAttributes;
|
|
570
|
+
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
// @override - BMCollectionViewLayout
|
|
574
|
+
rectWithScrollingPositionOfCellAtIndexPath: function (indexPath) {
|
|
575
|
+
var collectionViewHeight = this.collectionView.frame.size.height;
|
|
576
|
+
|
|
577
|
+
var y = 0;
|
|
578
|
+
for (var i = 0; i < indexPath.section; i++) {
|
|
579
|
+
var numberOfObjects = this.collectionView.numberOfObjectsInSectionAtIndex(i);
|
|
580
|
+
|
|
581
|
+
y += collectionViewHeight * numberOfObjects;
|
|
582
|
+
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
y += collectionViewHeight * indexPath.row;
|
|
586
|
+
|
|
587
|
+
return BMRectMakeWithX(0, {y: y, width: this.collectionView.frame.size.width, height: this.collectionView.frame.size.height});
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
// @override - BMCollectionViewLayout
|
|
591
|
+
snapsScrollPosition() {
|
|
592
|
+
return YES;
|
|
593
|
+
},
|
|
594
|
+
|
|
595
|
+
// @override - BMCollectionViewLayout
|
|
596
|
+
snappingScrollOffsetForScrollOffset(offset, args) {
|
|
597
|
+
var offset = offset.copy();
|
|
598
|
+
|
|
599
|
+
var additionalOffset = (args.withVerticalDirection == BMScrollingDirectionVertical.Bottom ? this.collectionView.frame.size.height : 0);
|
|
600
|
+
|
|
601
|
+
offset.y = ((offset.y / this.collectionView.frame.size.height) | 0) * this.collectionView.frame.size.height + additionalOffset;
|
|
602
|
+
|
|
603
|
+
offset.y = Math.max(0, Math.min(this.collectionView.size.height - this.collectionView.frame.size.height, offset.y));
|
|
604
|
+
|
|
605
|
+
return offset;
|
|
606
|
+
},
|
|
607
|
+
|
|
608
|
+
// @override - BMCollectionViewLayout
|
|
609
|
+
copy() {
|
|
610
|
+
var layout = new BMCollectionViewStackLayout();
|
|
611
|
+
|
|
612
|
+
layout._showsSingleCellFullScreen = this._showsSingleCellFullScreen;
|
|
613
|
+
layout._showsSingleCell = this._showsSingleCell;
|
|
614
|
+
layout._insets = this._insets.copy();
|
|
615
|
+
layout._spread = this._spread;
|
|
616
|
+
layout._numberOfBackgroundCells = this._numberOfBackgroundCells;
|
|
617
|
+
layout._minimumScale = this._minimumScale;
|
|
618
|
+
layout._blursBackgroundCells = this._blursBackgroundCells;
|
|
619
|
+
layout._maximumBlur = this._maximumBlur;
|
|
620
|
+
|
|
621
|
+
return layout;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Constructs and returns a new stack layout.
|
|
628
|
+
* @returns <BMCollectionViewStackLayout> A stack layout.
|
|
629
|
+
*/
|
|
630
|
+
BMCollectionViewStackLayout.stackLayout = function () {
|
|
631
|
+
return new BMCollectionViewStackLayout();
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// @endtype
|