bm-core-ui 2.11.9-beta.2 → 2.12.0-beta.12
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/README.md +1 -1
- package/build/@types/index.d.ts +2268 -71
- package/build/BMCollectionView/BMCollectionView.js +1070 -235
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +11 -4
- package/build/BMCollectionView/BMCollectionViewLayout.js +19 -0
- package/build/BMCoreUI.css +213 -44
- package/build/BMView/BMDragSession.js +1243 -0
- package/build/BMView/BMDragSessionActions.js +121 -0
- package/build/BMView/BMDragSessionPreview.js +1650 -0
- package/build/BMView/BMLayoutConstraint_v2.5.js +14 -59
- package/build/BMView/BMMenu.js +50 -20
- package/build/BMView/BMView_v2.5.js +34 -3
- package/build/BMWindow/BMPopover/BMPopover.js +35 -20
- package/build/BMWindow/BMToolWindow.js +29 -1
- package/build/BMWindow/BMWindow.js +128 -65
- 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 +4 -0
- package/lib/@types/BMCoreUI.min.d.ts +2268 -71
- package/lib/BMCoreUI.min.js +1 -1
- package/package.json +3 -3
|
@@ -5,8 +5,8 @@ import {BMInset} from '../Core/BMInset'
|
|
|
5
5
|
import {BMPointMake} from '../Core/BMPoint'
|
|
6
6
|
import {BMSizeMake} from '../Core/BMSize'
|
|
7
7
|
import {BMRect, BMRectMake, BMRectMakeWithNodeFrame, BMRectMakeWithOrigin, BMRectByInterpolatingRect} from '../Core/BMRect'
|
|
8
|
-
import {BMIndexPathNone} from '../Core/BMIndexPath'
|
|
9
|
-
import {BMAnimateWithBlock, BMAnimationContextBeginStatic, BMAnimationContextGetCurrent, BMAnimationContextAddCompletionHandler, BMAnimationApply, __BMVelocityAnimate, BMHook} from '../Core/BMAnimationContext'
|
|
8
|
+
import {BMIndexPathMakeWithRow, BMIndexPathNone} from '../Core/BMIndexPath'
|
|
9
|
+
import {BMAnimateWithBlock, BMAnimationContextBeginStatic, BMAnimationContextGetCurrent, BMAnimationContextAddCompletionHandler, BMAnimationApply, __BMVelocityAnimate, BMHook, BMAnimationBeginWithDuration} from '../Core/BMAnimationContext'
|
|
10
10
|
import {BMView, BMViewLayoutQueue} from '../BMView/BMView_v2.5'
|
|
11
11
|
import {BMCollectionViewLayoutAttributesMakeForCellAtIndexPath, BMCollectionViewLayoutAttributesType, BMCollectionViewLayoutAttributesStyleDefaults, _BMCollectionViewTransitionLayoutAttributesMakeWithSourceAttributes} from './BMCollectionViewLayoutAttributes'
|
|
12
12
|
import {BMJQueryShim, BMCollectionViewCell, BMCollectionViewCellReuseState} from './BMCollectionViewCell'
|
|
@@ -16,6 +16,9 @@ import {IScroll} from '../iScroll/iscroll-probe'
|
|
|
16
16
|
import { BMLayoutAttribute } from '../BMView/BMLayoutConstraint_v2.5'
|
|
17
17
|
import { BMMenuSourceNodeCSSClass } from '../BMView/BMMenu'
|
|
18
18
|
import { BMKeyboardShortcut, BMKeyboardShortcutModifier } from '../BMWindow/BMKeyboardShortcut'
|
|
19
|
+
import { BMDragSession, BMDragSessionAction, BMDragTransferKind, BMDropSessionAction } from '../BMView/BMDragSession'
|
|
20
|
+
import { BMDragPreview } from '../BMView/BMDragSessionPreview'
|
|
21
|
+
import { BMDragSessionActionKind, BMDropSessionActionKind } from '../BMView/BMDragSessionActions'
|
|
19
22
|
|
|
20
23
|
// When set to YES, this will cause collection view to use static animation contexts when setting up animations
|
|
21
24
|
const BM_COLLECTION_VIEW_USE_STATIC_CONTEXT = YES;
|
|
@@ -78,6 +81,45 @@ export var BMCollectionViewAcceptPolicy = Object.freeze({ // <enum>
|
|
|
78
81
|
|
|
79
82
|
// @endtype
|
|
80
83
|
|
|
84
|
+
// @type BMCollectionViewAcceptRegion
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Constants which describe the region by which a drag and drop gesture can be accepted as it
|
|
88
|
+
* enters the collection view's frame.
|
|
89
|
+
*/
|
|
90
|
+
export const BMCollectionViewAcceptRegion = Object.freeze({ // <enum>
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Indicates that the drop session will have the same drop action regardless of where
|
|
94
|
+
* in the collection view's frame it is.
|
|
95
|
+
*/
|
|
96
|
+
Anywhere: 'Accept', // <enum>
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Indicates that the drop session's drop action changes based on the cell in which the
|
|
100
|
+
* drop occurs. Drops outside of any cell's frame are rejected. The delegate object is
|
|
101
|
+
* expected to implement the {@link BMCollectionViewDelegate.collectionViewDropSessionDidEnterCell} method
|
|
102
|
+
* provide the appropriate drop action for each cell.
|
|
103
|
+
*/
|
|
104
|
+
Cell: 'Cell', // <enum>
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Indicates the drop session's drop action depends on the specific position in which the drop occurs.
|
|
108
|
+
* The delegate object is expected to implement the {@link BMCollectionViewDelegate.collectionViewDropSessionDidUpdate}
|
|
109
|
+
* method to provide the appropriate action as the drop session's position updates.
|
|
110
|
+
*/
|
|
111
|
+
Position: 'Position', // <enum>
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Indicates that the collection view cannot process the session's items and no further updates will
|
|
115
|
+
* be provided regarding this drop session.
|
|
116
|
+
*/
|
|
117
|
+
Nowhere: 'Reject', // <enum>
|
|
118
|
+
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// @endtype
|
|
122
|
+
|
|
81
123
|
// @type BMCollectionView Global Symbols
|
|
82
124
|
|
|
83
125
|
// Set to YES during a drag & drop operation
|
|
@@ -128,6 +170,24 @@ var _BMCollectionViewSnappingScrollThreshold = 200; // <Number>
|
|
|
128
170
|
*/
|
|
129
171
|
var _BMCollectionViewIdentityComparator = function (o1, o2) { return o1 == o2; }; // <Boolean ^ (AnyObject, AnyObject)>
|
|
130
172
|
|
|
173
|
+
/**
|
|
174
|
+
* The number of pixels determining how close to an edge the drag session position must be
|
|
175
|
+
* for a collection view to start scrolling.
|
|
176
|
+
*/
|
|
177
|
+
const _BMCollectionViewDragScrollDistance = 32;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* How much to multiply the distance to the edge to obtain the final scrolling speed during
|
|
181
|
+
* a drag and drop gesture.
|
|
182
|
+
*/
|
|
183
|
+
const _BMCollectionViewDragScrollMultiplier = 20;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The number of milliseconds to wait for a data source to insert items asynchronously after a drop
|
|
187
|
+
* before playing the generic drop animation for the drop previews.
|
|
188
|
+
*/
|
|
189
|
+
const _BMCollectionViewAsynchronousDropDelay = 200;
|
|
190
|
+
|
|
131
191
|
// @endtype
|
|
132
192
|
|
|
133
193
|
// @type BMCollectionViewScrollingDirection
|
|
@@ -157,7 +217,7 @@ export var BMCollectionViewScrollingDirection = Object.freeze({ // <enum>
|
|
|
157
217
|
// @type BMCollectionViewScrollingGravityHorizontal
|
|
158
218
|
|
|
159
219
|
/**
|
|
160
|
-
* Controls the final horizontal scrolling position of a
|
|
220
|
+
* Controls the final horizontal scrolling position of a programmatic scroll.
|
|
161
221
|
*/
|
|
162
222
|
export var BMCollectionViewScrollingGravityHorizontal = Object.freeze({ // <enum>
|
|
163
223
|
/**
|
|
@@ -181,7 +241,7 @@ export var BMCollectionViewScrollingGravityHorizontal = Object.freeze({ // <enum
|
|
|
181
241
|
// @type BMCollectionViewScrollingGravityVertical
|
|
182
242
|
|
|
183
243
|
/**
|
|
184
|
-
* Controls the final vertical scrolling position of a
|
|
244
|
+
* Controls the final vertical scrolling position of a programmatic scroll.
|
|
185
245
|
*/
|
|
186
246
|
export var BMCollectionViewScrollingGravityVertical = Object.freeze({ // <enum>
|
|
187
247
|
/**
|
|
@@ -202,7 +262,7 @@ export var BMCollectionViewScrollingGravityVertical = Object.freeze({ // <enum>
|
|
|
202
262
|
|
|
203
263
|
// @endtype
|
|
204
264
|
|
|
205
|
-
// @type BMCollectionView<T = any> extends BMView
|
|
265
|
+
// @type BMCollectionView<T = any> extends BMView implements BMDragDelegate, BMDropDelegate
|
|
206
266
|
|
|
207
267
|
// Contains all active collection view instances
|
|
208
268
|
var _BMCollectionViews = new Map;
|
|
@@ -239,7 +299,6 @@ export function BMCollectionView() { // <constructor>
|
|
|
239
299
|
BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? Object.create(BMView.prototype) : {}, {
|
|
240
300
|
constructor: BMCollectionView,
|
|
241
301
|
|
|
242
|
-
// MARK: BMView overrides
|
|
243
302
|
//#region BMView overrides
|
|
244
303
|
|
|
245
304
|
// @override - BMView
|
|
@@ -809,6 +868,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
809
868
|
var customScrollRequired = args && args.customScroll;
|
|
810
869
|
|
|
811
870
|
_BMCollectionViews.set(this, true);
|
|
871
|
+
BMDragSession._dropTargets.set(this, this);
|
|
812
872
|
|
|
813
873
|
this._container = BMJQueryShim.shimWithDOMNode(node);
|
|
814
874
|
this.layout = new BMCollectionViewFlowLayout();
|
|
@@ -1158,9 +1218,10 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
1158
1218
|
for (var i = 0; i < retainedCellsLength; i++) {
|
|
1159
1219
|
// The retained cells array resizes itself when cells are removed
|
|
1160
1220
|
this.retainedCells[0]._unmanage();
|
|
1161
|
-
}
|
|
1221
|
+
}
|
|
1162
1222
|
|
|
1163
1223
|
this.retainedCells = [];
|
|
1224
|
+
*/
|
|
1164
1225
|
|
|
1165
1226
|
// Reload the layout
|
|
1166
1227
|
this._reloadLayout();
|
|
@@ -1537,7 +1598,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
1537
1598
|
// Compute the new bounds
|
|
1538
1599
|
var containerNode = this._container[0];
|
|
1539
1600
|
|
|
1540
|
-
// When snapping, retain the previous
|
|
1601
|
+
// When snapping, retain the previous scroll position so that the scroll direction can be computed
|
|
1541
1602
|
var snapsScrollPosition = (!this._isPerformingAnimatedScrolling) && this._layout.snapsScrollPosition;
|
|
1542
1603
|
var previousBoundsOffset;
|
|
1543
1604
|
previousBoundsOffset = this._bounds.origin.copy();
|
|
@@ -2071,6 +2132,30 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2071
2132
|
* @param indexPaths <[BMIndexPath<T>]> The index paths of the cell whose size should be measured.
|
|
2072
2133
|
*/
|
|
2073
2134
|
measureSizesOfCellsAtIndexPaths(indexPaths) {
|
|
2135
|
+
// Skip index paths that have already been measured
|
|
2136
|
+
indexPaths = indexPaths.filter(indexPath => {
|
|
2137
|
+
// Return the cached size if it is available.
|
|
2138
|
+
let identifier;
|
|
2139
|
+
if (this._dataSet.identifierForIndexPath) {
|
|
2140
|
+
identifier = this._dataSet.identifierForIndexPath(indexPath);
|
|
2141
|
+
|
|
2142
|
+
if (this._measures[identifier]) {
|
|
2143
|
+
return NO;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
else {
|
|
2147
|
+
let length = this._measuredIndexPaths.length;
|
|
2148
|
+
for (let i = 0; i < length; i++) {
|
|
2149
|
+
let measure = this._measuredIndexPaths[i];
|
|
2150
|
+
if (measure.indexPath.isEqualToIndexPath(indexPath, {usingComparator: this.identityComparator})) {
|
|
2151
|
+
return NO;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
return YES;
|
|
2157
|
+
});
|
|
2158
|
+
|
|
2074
2159
|
const queue = BMViewLayoutQueue.layoutQueue();
|
|
2075
2160
|
const iterators = indexPaths.map(p => this._measuredSizeOfCellAtIndexPathGenerator(p, {layoutQueue: queue, dequeue: NO}));
|
|
2076
2161
|
|
|
@@ -2094,23 +2179,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2094
2179
|
if (result.done) return result.value;
|
|
2095
2180
|
}
|
|
2096
2181
|
|
|
2097
|
-
// Return the cached size if it is available.
|
|
2098
|
-
let identifier;
|
|
2099
|
-
if (this._dataSet.identifierForIndexPath) {
|
|
2100
|
-
identifier = this._dataSet.identifierForIndexPath(indexPath);
|
|
2101
|
-
|
|
2102
|
-
if (this._measures[identifier]) return this._measures[identifier];
|
|
2103
|
-
}
|
|
2104
|
-
else {
|
|
2105
|
-
let length = this._measuredIndexPaths.length;
|
|
2106
|
-
for (let i = 0; i < length; i++) {
|
|
2107
|
-
let measure = this._measuredIndexPaths[i];
|
|
2108
|
-
if (measure.indexPath.isEqualToIndexPath(indexPath, {usingComparator: this.identityComparator})) {
|
|
2109
|
-
return this._measuredIndexPaths[i].size;
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
2182
|
if (BM_COLLECTION_VIEW_DEBUG_MEASURE) {
|
|
2115
2183
|
if (!this.__debug__measuring) {
|
|
2116
2184
|
this.__debug__measuring = YES;
|
|
@@ -2603,8 +2671,8 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2603
2671
|
event.target.classList.contains('BMCollectionViewCellEventHandler') || event.target.parentNode.classList.contains('BMCollectionViewCellEventHandler') ||
|
|
2604
2672
|
event.target.classList.contains('widget-foldingpanel-header') ||
|
|
2605
2673
|
event.target.hasAttribute('contenteditable') ||
|
|
2606
|
-
// This a specific Thingworx workaround
|
|
2607
|
-
|
|
2674
|
+
// This a specific Thingworx workaround
|
|
2675
|
+
event.target.closest('.widget-dhxdropdown')) {
|
|
2608
2676
|
return;
|
|
2609
2677
|
}
|
|
2610
2678
|
|
|
@@ -2682,7 +2750,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2682
2750
|
|
|
2683
2751
|
cellEventCanDoubleClick = NO;
|
|
2684
2752
|
if (self.delegate && self.delegate.collectionViewCanDoubleClickCell) {
|
|
2685
|
-
cellEventCanDoubleClick = self.delegate.collectionViewCanDoubleClickCell(self, cell);
|
|
2753
|
+
cellEventCanDoubleClick = self.delegate.collectionViewCanDoubleClickCell(self, cell, {withEvent: event});
|
|
2686
2754
|
}
|
|
2687
2755
|
|
|
2688
2756
|
if (cellEventCanDoubleClick) cellEventDoubleClickTimeout = window.setTimeout(function () {
|
|
@@ -2909,6 +2977,8 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2909
2977
|
return cell;
|
|
2910
2978
|
|
|
2911
2979
|
},
|
|
2980
|
+
|
|
2981
|
+
// #region Drag and drop
|
|
2912
2982
|
|
|
2913
2983
|
isDragging: NO,
|
|
2914
2984
|
|
|
@@ -2954,6 +3024,8 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2954
3024
|
* @param toIndexPath <BMIndexPath<T>> The suggested index path at which to add the items.
|
|
2955
3025
|
* @param withDropShadows <Map<AnyObject, DOMNode>> A map containing the link between drop shadows and the items.
|
|
2956
3026
|
* }
|
|
3027
|
+
* @return <Promise<void>> A promise that resolves when the associated data update
|
|
3028
|
+
* has completed.
|
|
2957
3029
|
*/
|
|
2958
3030
|
_insertItems: async function (items, args) {
|
|
2959
3031
|
this._droppedShadows = args.withDropShadows;
|
|
@@ -2965,6 +3037,615 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2965
3037
|
});
|
|
2966
3038
|
},
|
|
2967
3039
|
|
|
3040
|
+
/**
|
|
3041
|
+
* An array containing the cells whose index paths are part of the current drag session, or
|
|
3042
|
+
* `undefined` while there is no drag session in progress for this collection view.
|
|
3043
|
+
*/
|
|
3044
|
+
_draggingCells: undefined, // <[BMCollectionViewCell], nullable>
|
|
3045
|
+
|
|
3046
|
+
/**
|
|
3047
|
+
* A map that keeps track of the association between drag items in a drag session and the cells
|
|
3048
|
+
* whose items they represent.
|
|
3049
|
+
*/
|
|
3050
|
+
_cellItemMap: undefined, // <Map<BMDragItem, BMCollectionViewCell>>
|
|
3051
|
+
|
|
3052
|
+
/**
|
|
3053
|
+
* Begins a drag gesture from the specified event. The drag event will move the cell from which
|
|
3054
|
+
* the event originates, or all selected cells if that cell is selected.
|
|
3055
|
+
* @param event <Event> The event triggering this action.
|
|
3056
|
+
* {
|
|
3057
|
+
* @param forCell <BMCollectionViewCell> The cell from which this event originates.
|
|
3058
|
+
* @param touchIdentifier <AnyObject> If this event is a `TouchEvent`, this represents the identifier
|
|
3059
|
+
* of the touch point that will control this drag & drop operation.
|
|
3060
|
+
* }
|
|
3061
|
+
*/
|
|
3062
|
+
beginDragWithEvent(event, args) {
|
|
3063
|
+
const cell = args.forCell;
|
|
3064
|
+
|
|
3065
|
+
let cells;
|
|
3066
|
+
|
|
3067
|
+
if (this.isCellAtIndexPathSelected(cell.indexPath)) {
|
|
3068
|
+
cells = [cell];
|
|
3069
|
+
// Sort the index paths in ascending order
|
|
3070
|
+
this._selectedIndexPaths.sort((i1, i2) => i2.section == i1.section ? i1.row - i2.row : i1.section - i2.section).forEach(indexPath => {
|
|
3071
|
+
let retainedCell = this.retainCellForIndexPath(indexPath);
|
|
3072
|
+
|
|
3073
|
+
if (retainedCell != cell) {
|
|
3074
|
+
cells.push(retainedCell);
|
|
3075
|
+
}
|
|
3076
|
+
retainedCell.isDragging = YES;
|
|
3077
|
+
|
|
3078
|
+
retainedCell.node.classList.add('BMCollectionViewCellDragging');
|
|
3079
|
+
});
|
|
3080
|
+
}
|
|
3081
|
+
else {
|
|
3082
|
+
cells = [cell];
|
|
3083
|
+
cell.isDragging = YES;
|
|
3084
|
+
cell.retain();
|
|
3085
|
+
|
|
3086
|
+
cell.node.classList.add('BMCollectionViewCellDragging');
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
this._draggingCells = cells;
|
|
3090
|
+
this._cellItemMap = new Map();
|
|
3091
|
+
|
|
3092
|
+
BMDragSession._beginDragWithEvent(event, {dragDelegate: this, view: this, touchIdentifier: args.touchIdentifier});
|
|
3093
|
+
},
|
|
3094
|
+
|
|
3095
|
+
/**
|
|
3096
|
+
* Creates and returns a fallback drag item for the specified index path if the data source
|
|
3097
|
+
* object cannot provide a customized drag item.
|
|
3098
|
+
* @param indexPath <BMIndexPath> The index path for which to return a drag item.
|
|
3099
|
+
* @return <BMDragItem> A drag item;
|
|
3100
|
+
*/
|
|
3101
|
+
_defaultDragItemForIndexPath(indexPath) {
|
|
3102
|
+
const object = this.dataSet.copyOfItem?.(indexPath.object) ?? JSON.parse(JSON.stringify(indexPath.object));
|
|
3103
|
+
|
|
3104
|
+
return {
|
|
3105
|
+
canConformToType(type) {
|
|
3106
|
+
return type == 'default' || type == 'object';
|
|
3107
|
+
},
|
|
3108
|
+
|
|
3109
|
+
itemOfType(type) {
|
|
3110
|
+
if (type != 'default' && type != 'object') {
|
|
3111
|
+
throw new Error(`Cannot provide an item representation of type "${type}"`);
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
return object;
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
},
|
|
3118
|
+
|
|
3119
|
+
dragSessionInitialItems(session) {
|
|
3120
|
+
this._draggingIndexPaths = [];
|
|
3121
|
+
|
|
3122
|
+
const items = this._draggingCells.map(cell => {
|
|
3123
|
+
const item = this.dataSet.dragItemForIndexPath?.(cell.indexPath, {session}) ?? this._defaultDragItemForIndexPath(cell.indexPath);
|
|
3124
|
+
this._cellItemMap.set(item, cell);
|
|
3125
|
+
this._draggingIndexPaths.push(cell.indexPath);
|
|
3126
|
+
return item;
|
|
3127
|
+
});
|
|
3128
|
+
|
|
3129
|
+
this._draggingIndexPaths.sort((i1, i2) => i1.section == i2.section ? i1.row - i2.row : i1.section - i2.section);
|
|
3130
|
+
|
|
3131
|
+
return items;
|
|
3132
|
+
},
|
|
3133
|
+
|
|
3134
|
+
dragSessionPreviewForItem(session, item) {
|
|
3135
|
+
const cell = this._cellItemMap.get(item);
|
|
3136
|
+
|
|
3137
|
+
cell.node.classList.remove('BMCollectionViewCellDragging');
|
|
3138
|
+
const preview = BMDragPreview.dragPreviewWithCopyOfSourceNode(cell.node, {forItem: item});
|
|
3139
|
+
cell.node.classList.add('BMCollectionViewCellDragging');
|
|
3140
|
+
|
|
3141
|
+
return preview;
|
|
3142
|
+
},
|
|
3143
|
+
|
|
3144
|
+
/**
|
|
3145
|
+
* The current drag action to use based on the current drag position.
|
|
3146
|
+
*/
|
|
3147
|
+
_dragAction: undefined, // <BMDragSessionAction, nullable>
|
|
3148
|
+
|
|
3149
|
+
/**
|
|
3150
|
+
* Set to `YES` while a drag session started by this collection view is in its frame.
|
|
3151
|
+
*/
|
|
3152
|
+
_dragSessionInFrame: NO, // <Boolean>
|
|
3153
|
+
|
|
3154
|
+
/**
|
|
3155
|
+
* The amount by which to scroll on the Y axis during the current drag session.
|
|
3156
|
+
*/
|
|
3157
|
+
_dragScrollDirectionY: 0, // <Number>
|
|
3158
|
+
|
|
3159
|
+
/**
|
|
3160
|
+
* The amount by which to scroll on the X axis during the current drag session.
|
|
3161
|
+
*/
|
|
3162
|
+
_dragScrollDirectionX: 0, // <Number>
|
|
3163
|
+
|
|
3164
|
+
/**
|
|
3165
|
+
* Whenever the pointer moves to the edges of this collection view during a drag session,
|
|
3166
|
+
* this method periodically scrolls the collection view's contents appropriately.
|
|
3167
|
+
*/
|
|
3168
|
+
_dragScroll() {
|
|
3169
|
+
// This callback runs continuously during the drag & drop operation - it is removed upon the operation finishing
|
|
3170
|
+
this._scrollFrameIdentifier = window.requestAnimationFrame(() => this._dragScroll());
|
|
3171
|
+
|
|
3172
|
+
// Don't perform the scroll during data updates
|
|
3173
|
+
if (this.isUpdatingData) {
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
if (this._dragScrollDirectionX || this._dragScrollDirectionY) {
|
|
3178
|
+
const offset = this.scrollOffset;
|
|
3179
|
+
offset.x = offset.x + this._dragScrollDirectionX;
|
|
3180
|
+
offset.y = offset.y + this._dragScrollDirectionY;
|
|
3181
|
+
|
|
3182
|
+
offset.x = Math.max(0, Math.min(offset.x, this.size.width - this.frame.size.width));
|
|
3183
|
+
offset.y = Math.max(0, Math.min(offset.y, this.size.height - this.frame.size.height));
|
|
3184
|
+
|
|
3185
|
+
this.scrollOffset = offset;
|
|
3186
|
+
}
|
|
3187
|
+
},
|
|
3188
|
+
|
|
3189
|
+
/**
|
|
3190
|
+
* The identifier of the animation frame callback used to scroll this collection during a drag session while the
|
|
3191
|
+
* mouse pointer
|
|
3192
|
+
*/
|
|
3193
|
+
_scrollFrameIdentifier: undefined, // <Number, nullable>
|
|
3194
|
+
|
|
3195
|
+
dragSessionDidEnter(session) {
|
|
3196
|
+
this._dragSessionInFrame = YES;
|
|
3197
|
+
this._dragAction = BMDragSessionAction.actionWithKind(BMDragSessionActionKind.Ignore);
|
|
3198
|
+
this._scrollFrameIdentifier = window.requestAnimationFrame(() => this._dragScroll());
|
|
3199
|
+
},
|
|
3200
|
+
|
|
3201
|
+
dragSessionDidUpdate(session) {
|
|
3202
|
+
if (this._dragSessionInFrame) {
|
|
3203
|
+
if (this.delegate?.collectionViewCanReorderItemsAtIndexPaths?.(this, this._draggingIndexPaths, {session}) ?? YES) {
|
|
3204
|
+
// If item movement is supported, determine the new index path to which the items should move
|
|
3205
|
+
// Instruct the data set to move the item, if the new index path does not match the index path of any dragging item
|
|
3206
|
+
const localPoint = this.positionOfDragSession(session);
|
|
3207
|
+
const targetIndexPath = this.indexPathAtPoint(localPoint);
|
|
3208
|
+
|
|
3209
|
+
let canMoveItem = YES;
|
|
3210
|
+
if (!targetIndexPath) {
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// If the target index path is an index path of an item that's part of the session, don't perform the reorder
|
|
3215
|
+
this._draggingIndexPaths.forEach(indexPath => {
|
|
3216
|
+
if (targetIndexPath.row == indexPath.row && targetIndexPath.section == indexPath.section) {
|
|
3217
|
+
canMoveItem = NO;
|
|
3218
|
+
}
|
|
3219
|
+
});
|
|
3220
|
+
|
|
3221
|
+
if (canMoveItem) {
|
|
3222
|
+
if (this.dataSet.moveItemsFromIndexPaths && this._draggingIndexPaths.length > 1) {
|
|
3223
|
+
// Instruct the data set to move the items in bulk if possible
|
|
3224
|
+
const newIndexPaths = this.dataSet.moveItemsFromIndexPaths(this._draggingIndexPaths, {toIndexPath: targetIndexPath});
|
|
3225
|
+
this._draggingIndexPaths = newIndexPaths.sort((i1, i2) => i1.section == i2.section ? i1.row - i2.row : i1.section - i2.section);
|
|
3226
|
+
}
|
|
3227
|
+
else {
|
|
3228
|
+
// Otherwise move them one by one
|
|
3229
|
+
this._draggingIndexPaths.forEach((indexPath, index) => {
|
|
3230
|
+
let destinationIndexPath = targetIndexPath.copy();
|
|
3231
|
+
destinationIndexPath.object = indexPath.object;
|
|
3232
|
+
destinationIndexPath.row += index;
|
|
3233
|
+
if (this.dataSet.moveItemFromIndexPath(indexPath, {toIndexPath: destinationIndexPath})) {
|
|
3234
|
+
this._draggingIndexPaths[index] = destinationIndexPath;
|
|
3235
|
+
}
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
// Determine the scrolling direction
|
|
3242
|
+
const viewportFrame = BMRectMakeWithNodeFrame(this.node);
|
|
3243
|
+
const slope = _BMCollectionViewDragScrollDistance;
|
|
3244
|
+
const multi = _BMCollectionViewDragScrollMultiplier;
|
|
3245
|
+
if (session.position.x - viewportFrame.origin.x < slope) {
|
|
3246
|
+
this._dragScrollDirectionX =
|
|
3247
|
+
(session.position.x - viewportFrame.origin.x - slope) / slope * multi;
|
|
3248
|
+
}
|
|
3249
|
+
else if (viewportFrame.right - session.position.x < slope) {
|
|
3250
|
+
this._dragScrollDirectionX = (slope - viewportFrame.right + session.position.x) / slope * multi;
|
|
3251
|
+
}
|
|
3252
|
+
else {
|
|
3253
|
+
this._dragScrollDirectionX = 0;
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3256
|
+
if (session.position.y - viewportFrame.origin.y < slope) {
|
|
3257
|
+
this._dragScrollDirectionY = (session.position.y - viewportFrame.origin.y - slope) / slope * multi;
|
|
3258
|
+
}
|
|
3259
|
+
else if (viewportFrame.bottom - session.position.y < slope) {
|
|
3260
|
+
this._dragScrollDirectionY = (slope - viewportFrame.bottom + session.position.y) / slope * multi;
|
|
3261
|
+
}
|
|
3262
|
+
else {
|
|
3263
|
+
this._dragScrollDirectionY = 0;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
return this._dragAction;
|
|
3268
|
+
},
|
|
3269
|
+
|
|
3270
|
+
dragSessionDidExit(session) {
|
|
3271
|
+
this._dragSessionInFrame = NO;
|
|
3272
|
+
if (this.delegate?.collectionViewCanRemoveItemsAtIndexPaths?.(this, this._draggingIndexPaths, {session})) {
|
|
3273
|
+
const message = this.delegate?.collectionDeleteMessageForIndexPaths?.(this, this._draggingIndexPaths, {session}) ?? 'Remove';
|
|
3274
|
+
this._dragAction = BMDragSessionAction.actionWithKind(BMDragSessionActionKind.Delete, {message});
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
if (this._scrollFrameIdentifier) {
|
|
3278
|
+
this._dragScrollDirectionX = 0;
|
|
3279
|
+
this._dragScrollDirectionY = 0;
|
|
3280
|
+
window.cancelAnimationFrame(this._scrollFrameIdentifier);
|
|
3281
|
+
this._scrollFrameIdentifier = undefined;
|
|
3282
|
+
}
|
|
3283
|
+
},
|
|
3284
|
+
|
|
3285
|
+
dragSessionWillFinish(session) {
|
|
3286
|
+
this.delegate?.collectionViewWillFinishInteractiveMovementForCell?.(this, this._draggingCells[0], {atIndexPath: this._draggingCells[0].indexPath, session});
|
|
3287
|
+
},
|
|
3288
|
+
|
|
3289
|
+
dragSessionPerformMoveForItems(session, items) {
|
|
3290
|
+
const indexPaths = items.map(i => this._cellItemMap.get(i).indexPath).sort((i1, i2) => {
|
|
3291
|
+
return i1.section == i2.section ? i1.row - i2.row : i1.section - i2.section;
|
|
3292
|
+
});
|
|
3293
|
+
|
|
3294
|
+
this.dataSet.removeItemsAtIndexPaths(indexPaths, {session});
|
|
3295
|
+
},
|
|
3296
|
+
|
|
3297
|
+
dragSessionPerformDelete(session) {
|
|
3298
|
+
this.dataSet.removeItemsAtIndexPaths(this._draggingIndexPaths, {session});
|
|
3299
|
+
},
|
|
3300
|
+
|
|
3301
|
+
dragSessionTransferKind(session) {
|
|
3302
|
+
const acceptPolicy = this.delegate?.collectionViewTransferPolicyForItemsAtIndexPaths?.(this, this._draggingIndexPaths, {session});
|
|
3303
|
+
switch (acceptPolicy) {
|
|
3304
|
+
case BMCollectionViewTransferPolicy.Move:
|
|
3305
|
+
return BMDragTransferKind.Move;
|
|
3306
|
+
case BMCollectionViewTransferPolicy.Copy:
|
|
3307
|
+
default:
|
|
3308
|
+
return BMDragTransferKind.Copy;
|
|
3309
|
+
}
|
|
3310
|
+
},
|
|
3311
|
+
|
|
3312
|
+
dragSessionDidFinish(session) {
|
|
3313
|
+
// Remove the dragging class from the cell
|
|
3314
|
+
this._draggingCells.forEach(cell => {
|
|
3315
|
+
cell.node.classList.remove('BMCollectionViewCellDragging');
|
|
3316
|
+
cell.isDragging = NO;
|
|
3317
|
+
|
|
3318
|
+
// Release the cell
|
|
3319
|
+
cell.release();
|
|
3320
|
+
});
|
|
3321
|
+
|
|
3322
|
+
this._draggingCells = undefined;
|
|
3323
|
+
this._cellItemMap = undefined;
|
|
3324
|
+
this._draggingIndexPaths = undefined;
|
|
3325
|
+
|
|
3326
|
+
this.delegate?.collectionViewDidFinishInteractiveMovementForCell?.(this, this._draggingCells[0], {atIndexPath: this._draggingCells[0].indexPath, session});
|
|
3327
|
+
},
|
|
3328
|
+
|
|
3329
|
+
dragSessionRequiresCustomDropAnimationForItems(session, items) {
|
|
3330
|
+
// Collection view only needs to customize the drop animation for partial transfers
|
|
3331
|
+
// where the transfer kind is move
|
|
3332
|
+
if (session.transferKind == BMDragTransferKind.Move && session.action._action == BMDropSessionActionKind.AcceptPartially) {
|
|
3333
|
+
return YES;
|
|
3334
|
+
}
|
|
3335
|
+
return NO;
|
|
3336
|
+
},
|
|
3337
|
+
|
|
3338
|
+
dragSessionAnimateDropWithPreviews(session, previews) {
|
|
3339
|
+
// If this collection view was already waiting for the data set to insert some data from a drop,
|
|
3340
|
+
// play the generic drop animation for those previews
|
|
3341
|
+
if (this._dropPreviews) {
|
|
3342
|
+
for (const preview of this._dropPreviews) {
|
|
3343
|
+
preview.performDrop();
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
|
|
3347
|
+
this._dropPreviews = previews.slice();
|
|
3348
|
+
const dropPreviews = this._dropPreviews;
|
|
3349
|
+
|
|
3350
|
+
// After this method returns, the drag session will instruct collection view to perform the move for the
|
|
3351
|
+
// affected items, which should trigger a synchronous data update to use and clear the drag previews
|
|
3352
|
+
queueMicrotask(() => {
|
|
3353
|
+
if (this._dropPreviews == dropPreviews) {
|
|
3354
|
+
this._dropPreviews = undefined;
|
|
3355
|
+
}
|
|
3356
|
+
});
|
|
3357
|
+
},
|
|
3358
|
+
|
|
3359
|
+
/**
|
|
3360
|
+
* The kind of region being tracked during a drop session. `undefined` if a drop session is
|
|
3361
|
+
* not in progress.
|
|
3362
|
+
*/
|
|
3363
|
+
_dropSessionRegionKind: undefined, // <BMCollectionViewAcceptRegion, nullable>
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* The current drop action to use based on the current drop session position.
|
|
3367
|
+
*/
|
|
3368
|
+
_dropAction: undefined, // <BMDropSessionAction, nullable>
|
|
3369
|
+
|
|
3370
|
+
/**
|
|
3371
|
+
* The index path associated with the current drop session, if any.
|
|
3372
|
+
*/
|
|
3373
|
+
_dropIndexPath: undefined, // <BMIndexPath, nullable>
|
|
3374
|
+
|
|
3375
|
+
dropSessionCanBegin(session) {
|
|
3376
|
+
this._lastDropIndexPath = undefined;
|
|
3377
|
+
this._dropIndexPath = undefined;
|
|
3378
|
+
this._dropAction = undefined;
|
|
3379
|
+
|
|
3380
|
+
const items = session.items.map(i => i.itemOfType('default'));
|
|
3381
|
+
const canBegin = this.delegate?.collectionViewCanAcceptItems?.(this, items, {session}) ?? NO;
|
|
3382
|
+
|
|
3383
|
+
// The drop session can begin if the response is not `NO` or `.Nowhere`.
|
|
3384
|
+
if (canBegin != NO && canBegin != BMCollectionViewAcceptRegion.Nowhere) {
|
|
3385
|
+
if (canBegin == YES || canBegin == BMCollectionViewAcceptRegion.Anywhere) {
|
|
3386
|
+
// If the drop session can be accepted anywhere, request the drop action from the delegate
|
|
3387
|
+
this._dropAction = this.delegate?.collectionViewDropActionForDropSession?.(this, session);
|
|
3388
|
+
this._dropAction ??= BMDropSessionAction.actionWithKind(BMDropSessionActionKind.Accept);
|
|
3389
|
+
this._dropSessionRegionKind = BMCollectionViewAcceptRegion.Anywhere;
|
|
3390
|
+
}
|
|
3391
|
+
else {
|
|
3392
|
+
this._dropSessionRegionKind = canBegin;
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
return YES;
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
return NO;
|
|
3399
|
+
},
|
|
3400
|
+
|
|
3401
|
+
dropSessionDidEnter(session) {
|
|
3402
|
+
this._dragScrollDirectionX = 0;
|
|
3403
|
+
this._dragScrollDirectionY = 0;
|
|
3404
|
+
this._scrollFrameIdentifier = window.requestAnimationFrame(() => this._dragScroll());
|
|
3405
|
+
},
|
|
3406
|
+
|
|
3407
|
+
dropSessionDidExit(session) {
|
|
3408
|
+
if (this._scrollFrameIdentifier) {
|
|
3409
|
+
this._dragScrollDirectionX = 0;
|
|
3410
|
+
this._dragScrollDirectionY = 0;
|
|
3411
|
+
window.cancelAnimationFrame(this._scrollFrameIdentifier);
|
|
3412
|
+
this._scrollFrameIdentifier = undefined;
|
|
3413
|
+
}
|
|
3414
|
+
},
|
|
3415
|
+
|
|
3416
|
+
/**
|
|
3417
|
+
* Returns the position of the specified drag or drop session relative to the collection view's bounds.
|
|
3418
|
+
* @param session <BMDragSession or BMDropSession> The drag or drop session.
|
|
3419
|
+
* @return <BMPoint> The coordinates relative to the bounds.
|
|
3420
|
+
*/
|
|
3421
|
+
positionOfDragSession(session) {
|
|
3422
|
+
const point = session.position;
|
|
3423
|
+
|
|
3424
|
+
// Determine the index path over which this session currently is
|
|
3425
|
+
const viewportFrame = BMRectMakeWithNodeFrame(this.node);
|
|
3426
|
+
|
|
3427
|
+
// Discover the coordinates of the point that are relative to the collection view's bounds
|
|
3428
|
+
let localPoint = BMPointMake(
|
|
3429
|
+
point.x - viewportFrame.origin.x,
|
|
3430
|
+
point.y - viewportFrame.origin.y,
|
|
3431
|
+
);
|
|
3432
|
+
localPoint.x += this.scrollOffset.x;
|
|
3433
|
+
localPoint.y += this.scrollOffset.y;
|
|
3434
|
+
|
|
3435
|
+
return localPoint;
|
|
3436
|
+
},
|
|
3437
|
+
|
|
3438
|
+
/**
|
|
3439
|
+
* Determines the index path at the specified point whose coordinates are relative to the bounds.
|
|
3440
|
+
* @param point <BMPoint> The point.
|
|
3441
|
+
* @return <BMIndexPath, nullable> The index path, if any cell's frame intersects the point,
|
|
3442
|
+
* or `undefined` otherwise.
|
|
3443
|
+
*/
|
|
3444
|
+
indexPathAtPoint(point) {
|
|
3445
|
+
// Create a rect around this point with a size of 64 by 64 pixels.
|
|
3446
|
+
const rect = BMRectMake(0, 0, 64, 64);
|
|
3447
|
+
rect.center = point;
|
|
3448
|
+
|
|
3449
|
+
// Request the attributes within the given rect
|
|
3450
|
+
const attributes = this.layout.attributesForElementsInRect(rect);
|
|
3451
|
+
|
|
3452
|
+
// Find the index path to which the cell should move
|
|
3453
|
+
let targetIndexPath;
|
|
3454
|
+
attributes.forEach(attribute => {
|
|
3455
|
+
if (attribute.itemType != BMCollectionViewLayoutAttributesType.Cell) {
|
|
3456
|
+
return;
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
if (attribute.frame.containsPoint(point)) {
|
|
3460
|
+
targetIndexPath = attribute.indexPath.copy();
|
|
3461
|
+
}
|
|
3462
|
+
});
|
|
3463
|
+
|
|
3464
|
+
return targetIndexPath;
|
|
3465
|
+
},
|
|
3466
|
+
|
|
3467
|
+
/**
|
|
3468
|
+
* The most recent index path the current drop session has been over.
|
|
3469
|
+
*/
|
|
3470
|
+
_lastDropIndexPath: undefined, // <BMIndexPath>
|
|
3471
|
+
|
|
3472
|
+
dropSessionDidUpdate(session) {
|
|
3473
|
+
const localPoint = this.positionOfDragSession(session);
|
|
3474
|
+
const targetIndexPath = this.indexPathAtPoint(localPoint);
|
|
3475
|
+
|
|
3476
|
+
if (targetIndexPath) {
|
|
3477
|
+
this._lastDropIndexPath = targetIndexPath;
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
if (this._dropSessionRegionKind == BMCollectionViewAcceptRegion.Anywhere) {
|
|
3481
|
+
return this._dropAction;
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
// Determine the scrolling direction
|
|
3485
|
+
const viewportFrame = BMRectMakeWithNodeFrame(this.node);
|
|
3486
|
+
const slope = _BMCollectionViewDragScrollDistance;
|
|
3487
|
+
const multi = _BMCollectionViewDragScrollMultiplier;
|
|
3488
|
+
if (session.position.x - viewportFrame.origin.x < slope) {
|
|
3489
|
+
this._dragScrollDirectionX =
|
|
3490
|
+
(session.position.x - viewportFrame.origin.x - slope) / slope * multi;
|
|
3491
|
+
}
|
|
3492
|
+
else if (viewportFrame.right - session.position.x < slope) {
|
|
3493
|
+
this._dragScrollDirectionX = (slope - viewportFrame.right + session.position.x) / slope * multi;
|
|
3494
|
+
}
|
|
3495
|
+
else {
|
|
3496
|
+
this._dragScrollDirectionX = 0;
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
if (session.position.y - viewportFrame.origin.y < slope) {
|
|
3500
|
+
this._dragScrollDirectionY = (session.position.y - viewportFrame.origin.y - slope) / slope * multi;
|
|
3501
|
+
}
|
|
3502
|
+
else if (viewportFrame.bottom - session.position.y < slope) {
|
|
3503
|
+
this._dragScrollDirectionY = (slope - viewportFrame.bottom + session.position.y) / slope * multi;
|
|
3504
|
+
}
|
|
3505
|
+
else {
|
|
3506
|
+
this._dragScrollDirectionY = 0;
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3509
|
+
// If the index path changes, notify the delegate using the appropriate methods
|
|
3510
|
+
if (!targetIndexPath) {
|
|
3511
|
+
if (this._dropIndexPath) {
|
|
3512
|
+
this._dropIndexPath = undefined;
|
|
3513
|
+
this.delegate?.collectionViewDropSessionDidExitIndexPath?.(this, session, {indexPath: this._dropIndexPath});
|
|
3514
|
+
|
|
3515
|
+
if (this._dropSessionRegionKind == BMCollectionViewAcceptRegion.Cell) {
|
|
3516
|
+
return BMDropSessionAction.actionWithKind(BMDropSessionActionKind.Ignore);
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
else {
|
|
3521
|
+
let isNewIndexPath = NO;
|
|
3522
|
+
if (!this._dropIndexPath) {
|
|
3523
|
+
isNewIndexPath = YES;
|
|
3524
|
+
}
|
|
3525
|
+
else {
|
|
3526
|
+
if (!this._dropIndexPath.isEqualToIndexPath(targetIndexPath, {usingComparator: this.identityComparator})) {
|
|
3527
|
+
isNewIndexPath = YES;
|
|
3528
|
+
this.delegate?.collectionViewDropSessionDidExitIndexPath?.(this, session, {indexPath: this._dropIndexPath});
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
this._dropIndexPath = targetIndexPath;
|
|
3533
|
+
|
|
3534
|
+
if (isNewIndexPath) {
|
|
3535
|
+
const action = this.delegate?.collectionViewDropSessionDidEnterIndexPath?.(this, session, {indexPath: this._dropIndexPath});
|
|
3536
|
+
|
|
3537
|
+
if (this._dropSessionRegionKind == BMCollectionViewAcceptRegion.Cell) {
|
|
3538
|
+
return action;
|
|
3539
|
+
}
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
|
|
3543
|
+
if (this._dropSessionRegionKind == BMCollectionViewAcceptRegion.Position) {
|
|
3544
|
+
const action = this.delegate?.collectionViewDropSessionDidUpdate?.(this, session, {position: localPoint});
|
|
3545
|
+
return action;
|
|
3546
|
+
}
|
|
3547
|
+
},
|
|
3548
|
+
|
|
3549
|
+
dropSessionPreviewForItem(session, item) {
|
|
3550
|
+
const node = this.delegate?.collectionViewPreviewForDropSession?.(this, session, {item});
|
|
3551
|
+
if (node) {
|
|
3552
|
+
return BMDragPreview.dragPreviewWithPreviewNode(node, {forItem: item});
|
|
3553
|
+
}
|
|
3554
|
+
},
|
|
3555
|
+
|
|
3556
|
+
dropSessionWillFinish(session) {
|
|
3557
|
+
this.delegate?.collectionViewDropSessionWillFinish?.(this, session);
|
|
3558
|
+
},
|
|
3559
|
+
|
|
3560
|
+
dropSessionRequiresCustomDropAnimationForItems(session, items) {
|
|
3561
|
+
return YES;
|
|
3562
|
+
},
|
|
3563
|
+
|
|
3564
|
+
dropSessionTransferKind(session) {
|
|
3565
|
+
const acceptPolicy = this.delegate?.collectionViewAcceptPolicyForItems?.(this, session.items.map(i => i.itemOfType('default')), {session});
|
|
3566
|
+
switch (acceptPolicy) {
|
|
3567
|
+
case BMCollectionViewAcceptPolicy.Move:
|
|
3568
|
+
return BMDragTransferKind.Move;
|
|
3569
|
+
case BMCollectionViewAcceptPolicy.Copy:
|
|
3570
|
+
default:
|
|
3571
|
+
return BMDragTransferKind.Copy;
|
|
3572
|
+
}
|
|
3573
|
+
},
|
|
3574
|
+
|
|
3575
|
+
/**
|
|
3576
|
+
* The drop previews that must be animated at the end of a successful drop session. Only set while performing
|
|
3577
|
+
* the data update associated with accepting items via a drop session.
|
|
3578
|
+
*/
|
|
3579
|
+
_dropPreviews: undefined, // <[BMDropPreview], nullable>
|
|
3580
|
+
|
|
3581
|
+
dropSessionPerformDrop(session) {
|
|
3582
|
+
// If this collection view was already waiting for the data set to insert some data from a drop,
|
|
3583
|
+
// play the generic drop animation for those previews
|
|
3584
|
+
if (this._dropPreviews) {
|
|
3585
|
+
BMAnimateWithBlock(() => {
|
|
3586
|
+
for (const preview of this._dropPreviews) {
|
|
3587
|
+
preview.performDrop();
|
|
3588
|
+
}
|
|
3589
|
+
}, {duration: 300, easing: 'easeInQuad'});
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3592
|
+
// If there are no items to accept, don't perform any other changes
|
|
3593
|
+
if (!session.dropItems.length) {
|
|
3594
|
+
BMAnimateWithBlock(() => {
|
|
3595
|
+
for (const preview of session.dropPreviews) {
|
|
3596
|
+
preview.performDrop();
|
|
3597
|
+
}
|
|
3598
|
+
}, {duration: 300, easing: 'easeInQuad'});
|
|
3599
|
+
return;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
let toIndexPath = this._lastDropIndexPath;
|
|
3603
|
+
if (!toIndexPath) {
|
|
3604
|
+
const sectionCount = this.numberOfSections();
|
|
3605
|
+
const row = this.numberOfObjectsInSectionAtIndex(sectionCount - 1) - 1;
|
|
3606
|
+
const section = sectionCount - 1;
|
|
3607
|
+
toIndexPath = this.indexPathForObjectAtRow(row, {inSectionAtIndex: section}) ?? BMIndexPathMakeWithRow(row, {section});
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
// Instruct the data set to insert the items to the appropriate index path
|
|
3611
|
+
this._dropPreviews = session.dropPreviews.slice();
|
|
3612
|
+
|
|
3613
|
+
const items = session.dropItems.map(i => i.itemOfType('default'));
|
|
3614
|
+
const result = this.dataSet.insertItems(items, {toIndexPath, session});
|
|
3615
|
+
|
|
3616
|
+
if (result) {
|
|
3617
|
+
// If the data set performs the change asynchronously, give it 200ms to trigger the data update, otherwise
|
|
3618
|
+
// play the generic drop animation for the previews
|
|
3619
|
+
const dropPreviews = this._dropPreviews;
|
|
3620
|
+
let resolved = NO;
|
|
3621
|
+
result.then(() => {
|
|
3622
|
+
resolved = YES;
|
|
3623
|
+
|
|
3624
|
+
if (this._dropPreviews == dropPreviews) {
|
|
3625
|
+
this._dropPreviews = undefined;
|
|
3626
|
+
}
|
|
3627
|
+
});
|
|
3628
|
+
|
|
3629
|
+
setTimeout(() => {
|
|
3630
|
+
if (!resolved) {
|
|
3631
|
+
if (this._dropPreviews == dropPreviews) {
|
|
3632
|
+
this._dropPreviews = undefined;
|
|
3633
|
+
}
|
|
3634
|
+
|
|
3635
|
+
BMAnimateWithBlock(() => {
|
|
3636
|
+
for (const preview of dropPreviews) {
|
|
3637
|
+
preview.performDrop();
|
|
3638
|
+
}
|
|
3639
|
+
}, {duration: 300, easing: 'easeInQuad'});
|
|
3640
|
+
|
|
3641
|
+
}
|
|
3642
|
+
}, _BMCollectionViewAsynchronousDropDelay);
|
|
3643
|
+
}
|
|
3644
|
+
else {
|
|
3645
|
+
this._dropPreviews = undefined;
|
|
3646
|
+
}
|
|
3647
|
+
},
|
|
3648
|
+
|
|
2968
3649
|
/**
|
|
2969
3650
|
* Begins a drag gesture from the given event. The drag event will move the cell from which
|
|
2970
3651
|
* the event originates.
|
|
@@ -2975,7 +3656,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2975
3656
|
* of the touch point that will control this drag & drop operation.
|
|
2976
3657
|
* }
|
|
2977
3658
|
*/
|
|
2978
|
-
|
|
3659
|
+
_beginDragWithEvent(event, args) {
|
|
2979
3660
|
if (this.isDragging) return;
|
|
2980
3661
|
// TODO Consider splitting up this giant method
|
|
2981
3662
|
|
|
@@ -3018,7 +3699,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3018
3699
|
}
|
|
3019
3700
|
else {
|
|
3020
3701
|
cells = [cell];
|
|
3021
|
-
cell.
|
|
3702
|
+
cell.isDragging = YES;
|
|
3022
3703
|
cell.retain();
|
|
3023
3704
|
|
|
3024
3705
|
cell.node.classList.add('BMCollectionViewCellDragging');
|
|
@@ -3082,18 +3763,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3082
3763
|
|
|
3083
3764
|
draggingShadows.push(otherDraggingShadow);
|
|
3084
3765
|
let index = draggingShadows.length;
|
|
3085
|
-
|
|
3086
|
-
// __BMVelocityAnimate(otherDraggingShadow, {
|
|
3087
|
-
// rotateZ: ((index) * 60 / cells.length) + 'deg',
|
|
3088
|
-
// left: [draggingShadowTargetPoint.x + 'px', sourceRect.origin.x + 'px'],
|
|
3089
|
-
// top: [draggingShadowTargetPoint.y + 'py', sourceRect.origin.x + 'px']
|
|
3090
|
-
// }, {
|
|
3091
|
-
// easing: 'easeInOutQuad',
|
|
3092
|
-
// duration: 300,
|
|
3093
|
-
// complete() {
|
|
3094
|
-
// areDraggingShadowsAnimating = NO;
|
|
3095
|
-
// }
|
|
3096
|
-
// });
|
|
3766
|
+
|
|
3097
3767
|
(window.Velocity || $.Velocity).animate(otherDraggingShadow, {tween: 1}, {
|
|
3098
3768
|
easing: 'easeInOutQuad',
|
|
3099
3769
|
duration: 300,
|
|
@@ -3123,15 +3793,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3123
3793
|
draggingShadowsToAdd.forEach(shadow => document.body.appendChild(shadow));
|
|
3124
3794
|
document.body.appendChild(draggingIndicator);
|
|
3125
3795
|
|
|
3126
|
-
// (window.Velocity || $.Velocity).animate(draggingIndicator, {
|
|
3127
|
-
// opacity: [1, 0],
|
|
3128
|
-
// scaleX: [1, 0],
|
|
3129
|
-
// scaleY: [1, 0]
|
|
3130
|
-
// }, {
|
|
3131
|
-
// duration: 300,
|
|
3132
|
-
// easing: 'easeOutQuad'
|
|
3133
|
-
// });
|
|
3134
|
-
|
|
3135
3796
|
__BMVelocityAnimate(draggingIndicator, {
|
|
3136
3797
|
opacity: [1, 0],
|
|
3137
3798
|
scaleX: [1, 0],
|
|
@@ -3342,10 +4003,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3342
4003
|
}
|
|
3343
4004
|
|
|
3344
4005
|
// Temporarily suspend these updates while a data update is in progress
|
|
3345
|
-
if (this.isUpdatingData)
|
|
4006
|
+
if (this.isUpdatingData) {
|
|
4007
|
+
event.preventDefault();
|
|
4008
|
+
event.stopPropagation();
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
3346
4011
|
|
|
3347
4012
|
|
|
3348
|
-
// 3.
|
|
4013
|
+
// 3. Enable scrolling while close to the collection view's edges.
|
|
3349
4014
|
if (clientX - collectionViewViewportFrame.origin.x < 32) {
|
|
3350
4015
|
scrollDirectionX = (clientX - collectionViewViewportFrame.origin.x - 32) / 32 * 20;
|
|
3351
4016
|
}
|
|
@@ -3773,7 +4438,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3773
4438
|
// Remove the dragging class from the cell
|
|
3774
4439
|
cells.forEach(cell => {
|
|
3775
4440
|
cell.node.classList.remove('BMCollectionViewCellDragging');
|
|
3776
|
-
cell.
|
|
4441
|
+
cell.isDragging = NO;
|
|
3777
4442
|
|
|
3778
4443
|
// Release the cell
|
|
3779
4444
|
cell.release();
|
|
@@ -4381,7 +5046,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4381
5046
|
* Highlights the index path to the specified direction of the currently highlighted index path.
|
|
4382
5047
|
* @param arrow <String> The key code of the keyboard arrow that was pressed.
|
|
4383
5048
|
* {
|
|
4384
|
-
* @param withEvent <KeyboardEvent> The event that
|
|
5049
|
+
* @param withEvent <KeyboardEvent> The event that triggered this action.
|
|
4385
5050
|
* }
|
|
4386
5051
|
*/
|
|
4387
5052
|
keyboardArrowPressed(arrow, args) {
|
|
@@ -4872,8 +5537,66 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4872
5537
|
// regardless of where the new or old positions of cells might be
|
|
4873
5538
|
let size = layout.contentSize();
|
|
4874
5539
|
this._size = BMSizeMake(Math.max(this._size.width, size.width), Math.max(this._size.height, size.height));
|
|
5540
|
+
|
|
5541
|
+
/**
|
|
5542
|
+
* Cleans up the changes performed by the current transition.
|
|
5543
|
+
*/
|
|
5544
|
+
function cleanupTransition() {
|
|
5545
|
+
if (self.iScroll) self.iScroll.refresh();
|
|
5546
|
+
|
|
5547
|
+
// Unmanage all outgoing supplementary views
|
|
5548
|
+
for (var i = 0; i < outgoingSupplementaryViewAttributes.length; i++) {
|
|
5549
|
+
var attribute = outgoingSupplementaryViewAttributes[i];
|
|
5550
|
+
var cell = self.supplementaryViewWithIdentifier(attribute.identifier, {atIndexPath: attribute.indexPath});
|
|
5551
|
+
|
|
5552
|
+
if (cell && cell.isManaged) {
|
|
5553
|
+
cell._unmanage();
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
|
|
5557
|
+
self._applyOverflows();
|
|
5558
|
+
|
|
5559
|
+
// Restore collection and invoke the data completion callbacks unless another animation is in progress
|
|
5560
|
+
if (self._dataUpdatePromise == dataUpdatePromise) {
|
|
5561
|
+
self._collectionEnabled = YES;
|
|
5562
|
+
self.isUpdatingData = NO;
|
|
5563
|
+
|
|
5564
|
+
self._executeDataCompletionCallbacks();
|
|
5565
|
+
}
|
|
5566
|
+
|
|
5567
|
+
// If the delegate animation options contains a complete handler, invoke it here
|
|
5568
|
+
if (delegateOptions.complete) delegateOptions.complete();
|
|
5569
|
+
|
|
5570
|
+
// Run the completion handler if it was specified
|
|
5571
|
+
if (options && options.completionHandler) options.completionHandler();
|
|
5572
|
+
|
|
5573
|
+
resolveLayoutUpdate();
|
|
5574
|
+
}
|
|
4875
5575
|
|
|
4876
5576
|
animationOptions.complete = function () {
|
|
5577
|
+
// If the transition was stopped, don't continue with the remaining changes
|
|
5578
|
+
if (self._layout != transitionLayout) {
|
|
5579
|
+
self._size = size.copy();
|
|
5580
|
+
|
|
5581
|
+
if (self.iScroll) {
|
|
5582
|
+
// Apply the new scroll offset internally to iScroll, if it changed
|
|
5583
|
+
if (oldBounds.origin.x != newBounds.origin.x || oldBounds.origin.y != newBounds.origin.y) {
|
|
5584
|
+
var targetOffset = newBounds.origin.copy();
|
|
5585
|
+
|
|
5586
|
+
targetOffset.x += self._offscreenBufferSize;
|
|
5587
|
+
targetOffset.y += self._offscreenBufferSize;
|
|
5588
|
+
|
|
5589
|
+
self.iScroll._translate(-targetOffset.x, -targetOffset.y);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
|
|
5593
|
+
animationCells.forEach(cell => cell.release());
|
|
5594
|
+
retainedCells.forEach(cell => cell.release());
|
|
5595
|
+
|
|
5596
|
+
cleanupTransition();
|
|
5597
|
+
return;
|
|
5598
|
+
}
|
|
5599
|
+
|
|
4877
5600
|
// Request the layout page
|
|
4878
5601
|
var attributes = transitionLayout.attributesForElementsInRect();
|
|
4879
5602
|
|
|
@@ -4908,35 +5631,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4908
5631
|
self._layout = layout;
|
|
4909
5632
|
self._transitionLayout = undefined;
|
|
4910
5633
|
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
// Unmanage all outgoing supplementary views
|
|
4914
|
-
for (var i = 0; i < outgoingSupplementaryViewAttributes.length; i++) {
|
|
4915
|
-
var attribute = outgoingSupplementaryViewAttributes[i];
|
|
4916
|
-
var cell = self.supplementaryViewWithIdentifier(attribute.identifier, {atIndexPath: attribute.indexPath});
|
|
4917
|
-
|
|
4918
|
-
if (cell && cell.isManaged) {
|
|
4919
|
-
cell._unmanage();
|
|
4920
|
-
}
|
|
4921
|
-
}
|
|
4922
|
-
|
|
4923
|
-
self._applyOverflows();
|
|
4924
|
-
|
|
4925
|
-
// Restore collection invoke the data completion callbacks unless another animation is in progress
|
|
4926
|
-
if (self._dataUpdatePromise == dataUpdatePromise) {
|
|
4927
|
-
self._collectionEnabled = YES;
|
|
4928
|
-
self.isUpdatingData = NO;
|
|
4929
|
-
|
|
4930
|
-
self._executeDataCompletionCallbacks();
|
|
4931
|
-
}
|
|
4932
|
-
|
|
4933
|
-
// If the delegate animation options contains a complete handler, invoke it here
|
|
4934
|
-
if (delegateOptions.complete) delegateOptions.complete();
|
|
4935
|
-
|
|
4936
|
-
// Run the completion handler if it was specified
|
|
4937
|
-
if (options && options.completionHandler) options.completionHandler();
|
|
4938
|
-
|
|
4939
|
-
resolveLayoutUpdate();
|
|
5634
|
+
cleanupTransition();
|
|
4940
5635
|
};
|
|
4941
5636
|
|
|
4942
5637
|
animationOptions.queue = NO;
|
|
@@ -5034,9 +5729,16 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5034
5729
|
|
|
5035
5730
|
},
|
|
5036
5731
|
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5732
|
+
/**
|
|
5733
|
+
* If a layout transition is currently in progress it is stopped, allowing data updates to
|
|
5734
|
+
* start without affecting the retained cells.
|
|
5735
|
+
*/
|
|
5736
|
+
_stopLayoutTransition() {
|
|
5737
|
+
if (this._transitionLayout && this._layout == this._transitionLayout) {
|
|
5738
|
+
this._layout._stopTransition();
|
|
5739
|
+
this._layout = this._layout.targetLayout;
|
|
5740
|
+
}
|
|
5741
|
+
},
|
|
5040
5742
|
|
|
5041
5743
|
/************************************* DATA SET UPDATE ************************************/
|
|
5042
5744
|
|
|
@@ -5133,6 +5835,49 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5133
5835
|
get dataUpdated() { // <Promise<void>, nullable>
|
|
5134
5836
|
return this._dataUpdatePromise;
|
|
5135
5837
|
},
|
|
5838
|
+
|
|
5839
|
+
/**
|
|
5840
|
+
* Finds and returns the drop preview associated with the specified layout attributes, if any exists.
|
|
5841
|
+
* @param attributes <BMCollectionViewLayoutAttributes> Tha attributes for which to find the drop preview.
|
|
5842
|
+
* {
|
|
5843
|
+
* @param previewMap <Map<BMIndexPath<T>, BMDropPreview>, nullable>
|
|
5844
|
+
* An optional mapping between index paths and drop items
|
|
5845
|
+
* used to find the drop preview for the item representation
|
|
5846
|
+
* that the data set actually inserted. The default item
|
|
5847
|
+
* representation will be used if this is not provided.
|
|
5848
|
+
* }
|
|
5849
|
+
* @returns <BMDropPreview, nullable> The drop preview if it was found, `undefined` otherwise.
|
|
5850
|
+
*/
|
|
5851
|
+
_dropPreviewForLayoutAttributes: function (attributes, {previewMap}) {
|
|
5852
|
+
if (!this._dropPreviews) {
|
|
5853
|
+
return;
|
|
5854
|
+
}
|
|
5855
|
+
|
|
5856
|
+
let dropPreview;
|
|
5857
|
+
|
|
5858
|
+
if (this._cellItemMap) {
|
|
5859
|
+
for (const [item, cell] of this._cellItemMap.entries()) {
|
|
5860
|
+
if (cell.indexPath.isLooselyEqualToIndexPath(attributes.indexPath, {usingComparator: this.identityComparator})) {
|
|
5861
|
+
return this._dropPreviews.find(p => p.item == item);
|
|
5862
|
+
}
|
|
5863
|
+
}
|
|
5864
|
+
}
|
|
5865
|
+
else if (previewMap) {
|
|
5866
|
+
for (const [indexPath, preview] of previewMap.entries()) {
|
|
5867
|
+
if (indexPath.isEqualToIndexPath(attributes.indexPath, {usingComparator: this.identityComparator})) {
|
|
5868
|
+
dropPreview = preview;
|
|
5869
|
+
break;
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5873
|
+
else {
|
|
5874
|
+
// If the data set did not provide the new index paths, assume that the default representation
|
|
5875
|
+
// was used and instead look for the object
|
|
5876
|
+
dropPreview = this._dropPreviews.find(p => p.item.itemOfType('default') == attributes.indexPath.object);
|
|
5877
|
+
}
|
|
5878
|
+
|
|
5879
|
+
return dropPreview;
|
|
5880
|
+
},
|
|
5136
5881
|
|
|
5137
5882
|
/**
|
|
5138
5883
|
* Should be invoked when the entire data set is updated in bulk.
|
|
@@ -5163,6 +5908,9 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5163
5908
|
let resolveUpdateData;
|
|
5164
5909
|
const dataUpdatePromise = new Promise(function (resolve, reject) {resolveUpdateData = resolve});
|
|
5165
5910
|
this._dataUpdatePromise = dataUpdatePromise;
|
|
5911
|
+
|
|
5912
|
+
// Stop any in progress layout updates
|
|
5913
|
+
this._stopLayoutTransition();
|
|
5166
5914
|
|
|
5167
5915
|
// Update the selection index paths
|
|
5168
5916
|
this._updateSelectionIndexPaths();
|
|
@@ -5272,8 +6020,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5272
6020
|
// Disable scrolling and interaction during update
|
|
5273
6021
|
this._container[0].style.pointerEvents = 'none';
|
|
5274
6022
|
var containerScrollOffset = this.scrollOffset;
|
|
5275
|
-
|
|
5276
|
-
if (this.
|
|
6023
|
+
|
|
6024
|
+
if (!this.iScroll) {
|
|
6025
|
+
this._container[0].scrollTo(containerScrollOffset.x, containerScrollOffset.y);
|
|
6026
|
+
}
|
|
6027
|
+
|
|
6028
|
+
if (this.scrollView) {
|
|
6029
|
+
this.scrollView.scrollingEnabled = NO;
|
|
6030
|
+
}
|
|
5277
6031
|
|
|
5278
6032
|
// Get the new content
|
|
5279
6033
|
var attributes = this.layout.attributesForElementsInRect(this._bounds);
|
|
@@ -5284,6 +6038,12 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5284
6038
|
var deletedCells = [];
|
|
5285
6039
|
var insertedCells = [];
|
|
5286
6040
|
var movingCells = [];
|
|
6041
|
+
|
|
6042
|
+
// Contains cells that are temporarily hidden due to a drop animation
|
|
6043
|
+
const sessionDropCells = [];
|
|
6044
|
+
|
|
6045
|
+
// Contains moving cells that have associated drop previews
|
|
6046
|
+
const dropMovingCells = [];
|
|
5287
6047
|
|
|
5288
6048
|
var supplementaryViewsToInsert = this.layout.supplementaryViewsToInsert();
|
|
5289
6049
|
var supplementaryViewsToDelete = this.layout.supplementaryViewsToDelete();
|
|
@@ -5297,6 +6057,20 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5297
6057
|
var visibleRect = new BMRect(BMPointMake(this._bounds.origin.x + this._offscreenBufferSize, this._bounds.origin.y + this._offscreenBufferSize), this._frame.size.copy());
|
|
5298
6058
|
var currentVisibleRect = new BMRect(BMPointMake(oldBounds.origin.x + this._offscreenBufferSize, oldBounds.origin.y + this._offscreenBufferSize), this._frame.size.copy());
|
|
5299
6059
|
|
|
6060
|
+
// If this update occurs because of a drag & drop operation, try to obtain the associated index paths from the data set
|
|
6061
|
+
let dropPreviewMap;
|
|
6062
|
+
if (this._dropPreviews && this.dataSet.indexPathForDragItem) {
|
|
6063
|
+
dropPreviewMap = new Map();
|
|
6064
|
+
|
|
6065
|
+
for (const preview of this._dropPreviews) {
|
|
6066
|
+
const indexPath = this.dataSet.indexPathForDragItem(preview.item);
|
|
6067
|
+
|
|
6068
|
+
if (indexPath) {
|
|
6069
|
+
dropPreviewMap.set(indexPath, preview);
|
|
6070
|
+
}
|
|
6071
|
+
}
|
|
6072
|
+
}
|
|
6073
|
+
|
|
5300
6074
|
// Compare the current content to the new content and data set
|
|
5301
6075
|
for (var i = 0; i < oldCells.length; i++) {
|
|
5302
6076
|
var cell = oldCells[i];
|
|
@@ -5314,13 +6088,17 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5314
6088
|
var attribute = attributes[j];
|
|
5315
6089
|
|
|
5316
6090
|
// Skip cells with different item types
|
|
5317
|
-
if (cell.itemType !== attribute.itemType)
|
|
6091
|
+
if (cell.itemType !== attribute.itemType) {
|
|
6092
|
+
continue;
|
|
6093
|
+
}
|
|
5318
6094
|
|
|
5319
6095
|
// Two cells refer to the same object if they are the same type and their index paths are loosely equal
|
|
5320
6096
|
if (cell.indexPath.isLooselyEqualToIndexPath(attribute.indexPath, {usingComparator: this.identityComparator})) {
|
|
5321
6097
|
|
|
5322
6098
|
// For supplementary views, it is also required that they have the same type identifier
|
|
5323
|
-
if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView && cell.reuseIdentifier !== attribute.identifier)
|
|
6099
|
+
if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView && cell.reuseIdentifier !== attribute.identifier) {
|
|
6100
|
+
continue;
|
|
6101
|
+
}
|
|
5324
6102
|
|
|
5325
6103
|
// If they are equal, mark the cell as moving and continue
|
|
5326
6104
|
cell.targetAttributes = attribute;
|
|
@@ -5330,17 +6108,35 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5330
6108
|
|
|
5331
6109
|
// Instruct the data set to update this cell's content
|
|
5332
6110
|
if (cell.itemType === BMCollectionViewLayoutAttributesType.Cell) {
|
|
5333
|
-
|
|
6111
|
+
|
|
6112
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6113
|
+
// at the appropriate position
|
|
6114
|
+
if (this._dropPreviews) {
|
|
6115
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6116
|
+
|
|
6117
|
+
if (dropPreview) {
|
|
6118
|
+
cell._dropPreview = dropPreview;
|
|
6119
|
+
dropMovingCells.push(cell);
|
|
6120
|
+
}
|
|
6121
|
+
}
|
|
6122
|
+
|
|
6123
|
+
if (this.dataSet.updateCell) {
|
|
6124
|
+
this.dataSet.updateCell(cell, {atIndexPath: attribute.indexPath});
|
|
6125
|
+
}
|
|
5334
6126
|
}
|
|
5335
6127
|
else if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView) {
|
|
5336
|
-
if (this.dataSet.updateSupplementaryView)
|
|
6128
|
+
if (this.dataSet.updateSupplementaryView) {
|
|
6129
|
+
this.dataSet.updateSupplementaryView(cell, {withIdentifier: cell.reuseIdentifier, atIndexPath: attribute.indexPath});
|
|
6130
|
+
}
|
|
5337
6131
|
}
|
|
5338
6132
|
|
|
5339
6133
|
break;
|
|
5340
6134
|
}
|
|
5341
6135
|
}
|
|
5342
6136
|
|
|
5343
|
-
if (foundCell)
|
|
6137
|
+
if (foundCell) {
|
|
6138
|
+
continue;
|
|
6139
|
+
}
|
|
5344
6140
|
|
|
5345
6141
|
// If the cell wasn't found in the new layout, check to see if its object still exists in the data set
|
|
5346
6142
|
if (cell.itemType === BMCollectionViewLayoutAttributesType.Cell) {
|
|
@@ -5351,9 +6147,22 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5351
6147
|
var attribute = this.layout.attributesForCellAtIndexPath(indexPath);
|
|
5352
6148
|
cell.targetAttributes = attribute;
|
|
5353
6149
|
movingCells.push(cell);
|
|
6150
|
+
|
|
6151
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6152
|
+
// at the appropriate position
|
|
6153
|
+
if (this._dropPreviews) {
|
|
6154
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6155
|
+
|
|
6156
|
+
if (dropPreview) {
|
|
6157
|
+
cell._dropPreview = dropPreview;
|
|
6158
|
+
dropMovingCells.push(cell);
|
|
6159
|
+
}
|
|
6160
|
+
}
|
|
5354
6161
|
|
|
5355
6162
|
// Instruct the data set to update this cell's content
|
|
5356
|
-
if (this.dataSet.updateCell)
|
|
6163
|
+
if (this.dataSet.updateCell) {
|
|
6164
|
+
this.dataSet.updateCell(cell, {atIndexPath: attribute.indexPath});
|
|
6165
|
+
}
|
|
5357
6166
|
}
|
|
5358
6167
|
else {
|
|
5359
6168
|
// Otherwise the cell was removed from the data set
|
|
@@ -5381,7 +6190,9 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5381
6190
|
movingCells.push(cell);
|
|
5382
6191
|
|
|
5383
6192
|
// Instruct the data set to update this supplementary view's content
|
|
5384
|
-
if (this.dataSet.updateSupplementaryView)
|
|
6193
|
+
if (this.dataSet.updateSupplementaryView) {
|
|
6194
|
+
this.dataSet.updateSupplementaryView(cell, {withIdentifier: cell.reuseIdentifier, atIndexPath: attribute.indexPath});
|
|
6195
|
+
}
|
|
5385
6196
|
}
|
|
5386
6197
|
else {
|
|
5387
6198
|
// Otherwise find its final attributes
|
|
@@ -5396,12 +6207,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5396
6207
|
|
|
5397
6208
|
// Construct the cells for the new attributes
|
|
5398
6209
|
var newCells = [];
|
|
5399
|
-
|
|
5400
|
-
// If this update occurs because of a drag & drop operation, the collection view's viewport frame will be needed
|
|
5401
|
-
var viewportFrame;
|
|
5402
|
-
if (this._droppedShadows) {
|
|
5403
|
-
viewportFrame = BMRectMakeWithNodeFrame(this._container[0]);
|
|
5404
|
-
}
|
|
5405
6210
|
|
|
5406
6211
|
// Compare the remaining new content to the old data set
|
|
5407
6212
|
for (var i = 0; i < attributes.length; i++) {
|
|
@@ -5424,53 +6229,55 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5424
6229
|
var oldAttribute = this.layout.initialAttributesForMovingCellFromIndexPath(oldIndexPath, {toIndexPath: attribute.indexPath, withTargetAttributes: attribute});
|
|
5425
6230
|
attribute.initialAttributes = oldAttribute;
|
|
5426
6231
|
//oldAttribute.indexPath = attribute.indexPath;
|
|
6232
|
+
|
|
6233
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6234
|
+
// at the appropriate position
|
|
6235
|
+
if (this._dropPreviews) {
|
|
6236
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6237
|
+
|
|
6238
|
+
if (dropPreview) {
|
|
6239
|
+
cell._dropPreview = dropPreview;
|
|
6240
|
+
dropMovingCells.push(cell);
|
|
6241
|
+
}
|
|
6242
|
+
}
|
|
5427
6243
|
}
|
|
5428
6244
|
else {
|
|
5429
6245
|
// Otherwise this is a new element
|
|
5430
6246
|
|
|
5431
|
-
// Check if there is a drop
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
frame.origin.y += cellTransform.origin.y;
|
|
5461
|
-
|
|
5462
|
-
initialAttributes.frame = frame;
|
|
5463
|
-
initialAttributes.style.rotateZ = droppedShadow.rotation + 'deg';
|
|
5464
|
-
initialAttributes.style.scaleX = cellTransform.size.width;
|
|
5465
|
-
initialAttributes.style.scaleY = cellTransform.size.height;
|
|
5466
|
-
initialAttributes.style.opacity = 0;
|
|
6247
|
+
// Check if there is a drop preview associated with this element and transition from that preview
|
|
6248
|
+
if (this._dropPreviews) {
|
|
6249
|
+
// Find if a newly inserted index path matches this cell's index path
|
|
6250
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(attribute, {previewMap: dropPreviewMap});
|
|
6251
|
+
|
|
6252
|
+
let initialAttributes = attribute;
|
|
6253
|
+
|
|
6254
|
+
// If a preferred scroll offset is provided by the layout, displace the cell initially so that it
|
|
6255
|
+
// starts out at the position it will be in at the end of the scroll animation, relative to the viewport
|
|
6256
|
+
const displacement = BMPointMake(
|
|
6257
|
+
preferredScrollOffset.x - scrollOffset.x,
|
|
6258
|
+
preferredScrollOffset.y - scrollOffset.y
|
|
6259
|
+
);
|
|
6260
|
+
|
|
6261
|
+
if (displacement.x || displacement.y) {
|
|
6262
|
+
initialAttributes = attribute.copy();
|
|
6263
|
+
initialAttributes.frame = initialAttributes.frame.copy();
|
|
6264
|
+
initialAttributes.frame.offset(displacement.x, displacement.y);
|
|
6265
|
+
}
|
|
6266
|
+
|
|
6267
|
+
if (dropPreview) {
|
|
6268
|
+
newCell._dropPreview = dropPreview;
|
|
6269
|
+
attribute.initialAttributes = initialAttributes;
|
|
6270
|
+
insertedCells.push(newCell);
|
|
6271
|
+
}
|
|
6272
|
+
else {
|
|
6273
|
+
const initialAttributes = this.layout.initialAttributesForAppearingCellAtIndexPath(attribute.indexPath, {withTargetAttributes: attribute});
|
|
6274
|
+
attribute.initialAttributes = initialAttributes;
|
|
6275
|
+
}
|
|
5467
6276
|
}
|
|
5468
6277
|
else {
|
|
5469
6278
|
var initialAttributes = this.layout.initialAttributesForAppearingCellAtIndexPath(attribute.indexPath, {withTargetAttributes: attribute});
|
|
6279
|
+
attribute.initialAttributes = initialAttributes;
|
|
5470
6280
|
}
|
|
5471
|
-
|
|
5472
|
-
attribute.initialAttributes = initialAttributes;
|
|
5473
|
-
//initialAttributes.indexPath = attribute.indexPath;
|
|
5474
6281
|
}
|
|
5475
6282
|
|
|
5476
6283
|
newCell.attributes = attribute.initialAttributes;
|
|
@@ -5596,7 +6403,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5596
6403
|
animationCells[i].release();
|
|
5597
6404
|
|
|
5598
6405
|
// Additionally, unmanage hidden cells
|
|
5599
|
-
if (animationCells[i].attributes.isHidden)
|
|
6406
|
+
if (animationCells[i].attributes.isHidden) {
|
|
6407
|
+
animationCells[i]._unmanage();
|
|
6408
|
+
}
|
|
6409
|
+
}
|
|
6410
|
+
|
|
6411
|
+
// Remove the hiding class from inserted cells
|
|
6412
|
+
for (const cell of sessionDropCells) {
|
|
6413
|
+
cell.node.classList.remove('BMCollectionViewCellInserting');
|
|
5600
6414
|
}
|
|
5601
6415
|
|
|
5602
6416
|
// Destroy the deleted cells
|
|
@@ -5629,56 +6443,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5629
6443
|
|
|
5630
6444
|
};
|
|
5631
6445
|
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
// Apply the new scroll offset, if it changed
|
|
5635
|
-
/*if (oldBounds.origin.x != self._bounds.origin.x || oldBounds.origin.y != self._bounds.origin.y) {
|
|
5636
|
-
|
|
5637
|
-
if (self.scrollView) {
|
|
5638
|
-
var currentOffset = self.scrollView.offset.copy();
|
|
5639
|
-
var targetOffset = self._bounds.origin.copy();
|
|
5640
|
-
|
|
5641
|
-
targetOffset.x += self._offscreenBufferSize;
|
|
5642
|
-
targetOffset.y += self._offscreenBufferSize;
|
|
5643
|
-
|
|
5644
|
-
animationOptions.progress = function (elements, fraction) {
|
|
5645
|
-
var offsetX = currentOffset.x + fraction * (targetOffset.x - currentOffset.x);
|
|
5646
|
-
var offsetY = currentOffset.y + fraction * (targetOffset.y - currentOffset.y);
|
|
5647
|
-
|
|
5648
|
-
self.scrollView.offset = BMPointMake(offsetX, offsetY);
|
|
5649
|
-
}
|
|
5650
|
-
}
|
|
5651
|
-
else if (self.iScroll) {
|
|
5652
|
-
var currentOffset = scrollOffset;
|
|
5653
|
-
var targetOffset = self._bounds.origin.copy();
|
|
5654
|
-
|
|
5655
|
-
targetOffset.x += self._offscreenBufferSize;
|
|
5656
|
-
targetOffset.y += self._offscreenBufferSize;
|
|
5657
|
-
|
|
5658
|
-
animationOptions.progress = function (elements, fraction) {
|
|
5659
|
-
var offsetX = currentOffset.x + fraction * (targetOffset.x - currentOffset.x);
|
|
5660
|
-
var offsetY = currentOffset.y + fraction * (targetOffset.y - currentOffset.y);
|
|
5661
|
-
|
|
5662
|
-
self.iScroll._translate(-offsetX, -offsetY);
|
|
5663
|
-
}
|
|
5664
|
-
}
|
|
5665
|
-
else {
|
|
5666
|
-
var currentOffset = scrollOffset;
|
|
5667
|
-
var targetOffset = self._bounds.origin.copy();
|
|
5668
|
-
|
|
5669
|
-
targetOffset.x += self._offscreenBufferSize;
|
|
5670
|
-
targetOffset.y += self._offscreenBufferSize;
|
|
5671
|
-
|
|
5672
|
-
animationOptions.progress = function (elements, fraction) {
|
|
5673
|
-
var offsetX = currentOffset.x + fraction * (targetOffset.x - currentOffset.x);
|
|
5674
|
-
var offsetY = currentOffset.y + fraction * (targetOffset.y - currentOffset.y);
|
|
5675
|
-
|
|
5676
|
-
self._container[0].scrollTo(offsetX, offsetY);
|
|
5677
|
-
}
|
|
5678
|
-
}
|
|
5679
|
-
|
|
5680
|
-
}*/
|
|
5681
|
-
|
|
5682
6446
|
// All cells involved in the animation will be retained for the duration of the animation
|
|
5683
6447
|
// And then released at the end
|
|
5684
6448
|
var animationCells = [];
|
|
@@ -5696,26 +6460,65 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5696
6460
|
}
|
|
5697
6461
|
|
|
5698
6462
|
// Apply the drop shadow animations if needed
|
|
5699
|
-
if (self.
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
controller.registerBuiltInProperty('scaleY', {withValue: shadow.transform.size.height});
|
|
5708
|
-
controller.registerBuiltInProperty('rotateZ', {withValue: '0deg'});
|
|
5709
|
-
controller.registerBuiltInProperty('opacity', {withValue: 0});
|
|
6463
|
+
if (self._dropPreviews) {
|
|
6464
|
+
for (const cell of insertedCells) {
|
|
6465
|
+
cell._dropPreview.performDropToNode(cell.node);
|
|
6466
|
+
|
|
6467
|
+
const index = self._dropPreviews.indexOf(cell._dropPreview);
|
|
6468
|
+
|
|
6469
|
+
if (index != -1) {
|
|
6470
|
+
self._dropPreviews.splice(index, 1);
|
|
5710
6471
|
}
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
6472
|
+
}
|
|
6473
|
+
|
|
6474
|
+
if (dropMovingCells.length) {
|
|
6475
|
+
// For the items that move, move them instantly to their final positions start the drop
|
|
6476
|
+
// animations, then move them back for the regular animation to play for them
|
|
6477
|
+
BMAnimationContextBeginStatic();
|
|
6478
|
+
const initialAttributeMap = new Map();
|
|
6479
|
+
for (const cell of dropMovingCells) {
|
|
6480
|
+
// Instantly move each cell to its final attributes
|
|
6481
|
+
initialAttributeMap.set(cell, cell.attributes);
|
|
6482
|
+
cell.attributes = cell.targetAttributes;
|
|
5717
6483
|
}
|
|
5718
|
-
|
|
6484
|
+
BMAnimationApply();
|
|
6485
|
+
|
|
6486
|
+
// Play all drop animations
|
|
6487
|
+
for (const cell of dropMovingCells) {
|
|
6488
|
+
cell._dropPreview.performDropToNode(cell.node);
|
|
6489
|
+
const index = self._dropPreviews.indexOf(cell._dropPreview);
|
|
6490
|
+
|
|
6491
|
+
if (index != -1) {
|
|
6492
|
+
self._dropPreviews.splice(index, 1);
|
|
6493
|
+
}
|
|
6494
|
+
}
|
|
6495
|
+
|
|
6496
|
+
// Revert each cell to its staging attributes
|
|
6497
|
+
BMAnimationContextBeginStatic();
|
|
6498
|
+
for (const [cell, attributes] of initialAttributeMap) {
|
|
6499
|
+
cell.attributes = attributes;
|
|
6500
|
+
}
|
|
6501
|
+
BMAnimationApply();
|
|
6502
|
+
}
|
|
6503
|
+
|
|
6504
|
+
// For remaining drop previews, play an animation to the target cell if available
|
|
6505
|
+
if (self._cellItemMap) {
|
|
6506
|
+
for (let i = 0; i < self._dropPreviews.length; i++) {
|
|
6507
|
+
const item = self._dropPreviews[i];
|
|
6508
|
+
const cell = self._cellItemMap.get(item);
|
|
6509
|
+
|
|
6510
|
+
if (cell) {
|
|
6511
|
+
self._dropPreviews.performDropToNode(cell.node);
|
|
6512
|
+
self._dropPreviews.splice(i, 1);
|
|
6513
|
+
i--;
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
}
|
|
6517
|
+
|
|
6518
|
+
// Play a generic animation for all remaining drop previews without associated cells
|
|
6519
|
+
for (const preview of self._dropPreviews) {
|
|
6520
|
+
preview.performDrop();
|
|
6521
|
+
}
|
|
5719
6522
|
}
|
|
5720
6523
|
|
|
5721
6524
|
// Apply the new scroll offset, if it changed
|
|
@@ -5766,7 +6569,15 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5766
6569
|
var cell = newCells[i];
|
|
5767
6570
|
if (!cell.animatable) continue;
|
|
5768
6571
|
|
|
5769
|
-
cell.
|
|
6572
|
+
if (cell._dropPreview) {
|
|
6573
|
+
cell._dropPreview = undefined;
|
|
6574
|
+
cell.node.classList.add('BMCollectionViewCellInserting');
|
|
6575
|
+
sessionDropCells.push(cell);
|
|
6576
|
+
}
|
|
6577
|
+
else {
|
|
6578
|
+
cell.attributes = cell.targetAttributes;
|
|
6579
|
+
}
|
|
6580
|
+
|
|
5770
6581
|
cell.animatable = NO;
|
|
5771
6582
|
|
|
5772
6583
|
animationCells.push(cell.retain());
|
|
@@ -5803,6 +6614,11 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5803
6614
|
if (BMAnimationContextGetCurrent()) {
|
|
5804
6615
|
animationBlock();
|
|
5805
6616
|
BMAnimationContextAddCompletionHandler(animationOptions.complete);
|
|
6617
|
+
|
|
6618
|
+
// Clear out all target attributes on all cell after the animation starts
|
|
6619
|
+
for (const cell of this.allCells) {
|
|
6620
|
+
cell.targetAttributes = undefined;
|
|
6621
|
+
}
|
|
5806
6622
|
}
|
|
5807
6623
|
else {
|
|
5808
6624
|
BMAnimateWithBlock(animationBlock, animationOptions);
|
|
@@ -5812,7 +6628,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5812
6628
|
this.oldBounds = undefined;
|
|
5813
6629
|
|
|
5814
6630
|
// If no cells should be changed, immediately run the completion handler
|
|
5815
|
-
if (newCells.length == 0 && oldCells.length == 0) {
|
|
6631
|
+
if (newCells.length == 0 && oldCells.length == 0 && !this._dropPreviews) {
|
|
5816
6632
|
animationOptions.complete();
|
|
5817
6633
|
}
|
|
5818
6634
|
|
|
@@ -5997,9 +6813,19 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5997
6813
|
// Scroll to the offset point
|
|
5998
6814
|
if (options.animated) {
|
|
5999
6815
|
var self = this;
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6816
|
+
const currentContext = BMAnimationContextGetCurrent();
|
|
6817
|
+
if (!currentContext) {
|
|
6818
|
+
BMAnimationBeginWithDuration(300);
|
|
6819
|
+
}
|
|
6820
|
+
|
|
6821
|
+
self.scrollOffset = offset;
|
|
6822
|
+
|
|
6823
|
+
if (!currentContext) {
|
|
6824
|
+
return BMAnimationApply();
|
|
6825
|
+
}
|
|
6826
|
+
else {
|
|
6827
|
+
return new Promise(resolve => BMAnimationContextAddCompletionHandler(resolve));
|
|
6828
|
+
}
|
|
6003
6829
|
}
|
|
6004
6830
|
else {
|
|
6005
6831
|
// Scrolling is performed differently based on whether iScroll is used or not
|
|
@@ -6282,6 +7108,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
6282
7108
|
var self = this;
|
|
6283
7109
|
|
|
6284
7110
|
_BMCollectionViews.delete(this);
|
|
7111
|
+
BMDragSession._dropTargets.delete(this);
|
|
6285
7112
|
|
|
6286
7113
|
// Unbind the scroll event listener
|
|
6287
7114
|
if (this.initialized && !this.iScroll) {
|
|
@@ -6419,8 +7246,8 @@ class BMCollectionViewDataSourceAdapter {
|
|
|
6419
7246
|
return this._dataSet.moveItemsFromIndexPaths(indexPaths, args);
|
|
6420
7247
|
}
|
|
6421
7248
|
|
|
6422
|
-
collectionViewRemoveItemsAtIndexPaths(collectionView, indexPaths) {
|
|
6423
|
-
return this._dataSet.removeItemsAtIndexPaths(indexPaths);
|
|
7249
|
+
collectionViewRemoveItemsAtIndexPaths(collectionView, indexPaths, args) {
|
|
7250
|
+
return this._dataSet.removeItemsAtIndexPaths(indexPaths, args);
|
|
6424
7251
|
}
|
|
6425
7252
|
|
|
6426
7253
|
collectionViewInsertItems(collectionView, items, args) {
|
|
@@ -6436,6 +7263,18 @@ class BMCollectionViewDataSourceAdapter {
|
|
|
6436
7263
|
};
|
|
6437
7264
|
}
|
|
6438
7265
|
|
|
7266
|
+
if (dataSet.dragItemForIndexPath) {
|
|
7267
|
+
adapter.collectionViewDragItemForIndexPath = function (collectionView, indexPath, args) {
|
|
7268
|
+
return dataSet.dragItemForIndexPath(indexPath, args);
|
|
7269
|
+
};
|
|
7270
|
+
}
|
|
7271
|
+
|
|
7272
|
+
if (dataSet.indexPathForDragItem) {
|
|
7273
|
+
adapter.collectionViewIndexPathForDragItem = function (collectionView, item, args) {
|
|
7274
|
+
return dataSet.indexPathForDragItem(item, args);
|
|
7275
|
+
};
|
|
7276
|
+
}
|
|
7277
|
+
|
|
6439
7278
|
return adapter;
|
|
6440
7279
|
}
|
|
6441
7280
|
}
|
|
@@ -6472,30 +7311,14 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6472
7311
|
return this._dataSource.collectionViewIndexPathForObject(this._collectionView, object);
|
|
6473
7312
|
}
|
|
6474
7313
|
|
|
6475
|
-
contentsForCellWithReuseIdentifier(identifier) {
|
|
6476
|
-
throw new Error(`contentsForCellWithReuseIdentifier is unsupported when using data source objects`);
|
|
6477
|
-
}
|
|
6478
|
-
|
|
6479
7314
|
cellForItemAtIndexPath(indexPath) {
|
|
6480
7315
|
return this._dataSource.collectionViewCellForItemAtIndexPath(this._collectionView, indexPath);
|
|
6481
7316
|
}
|
|
6482
7317
|
|
|
6483
|
-
contentsForSupplementaryViewWithIdentifier(identifier) {
|
|
6484
|
-
throw new Error(`contentsForSupplementaryViewWithIdentifier is unsupported when using data source objects`);
|
|
6485
|
-
}
|
|
6486
|
-
|
|
6487
7318
|
cellForSupplementaryViewWithIdentifier(identifier, args) {
|
|
6488
7319
|
return this._dataSource.collectionViewCellForSupplementaryViewWithIdentifier(this._collectionView, identifier, args);
|
|
6489
7320
|
}
|
|
6490
7321
|
|
|
6491
|
-
updateCell(cell, {atIndexPath: indexPath}) {
|
|
6492
|
-
throw new Error(`updateCell is unsupported when using data source objects`);
|
|
6493
|
-
}
|
|
6494
|
-
|
|
6495
|
-
updateSupplementaryView(view, {withIdentifier: identifier, atIndexPath: indexPath}) {
|
|
6496
|
-
throw new Error(`updateSupplementaryView is unsupported when using data source objects`);
|
|
6497
|
-
}
|
|
6498
|
-
|
|
6499
7322
|
useOldData(use) {
|
|
6500
7323
|
return this._dataSource.collectionViewUseOldData(this._collectionView, use);
|
|
6501
7324
|
}
|
|
@@ -6512,8 +7335,8 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6512
7335
|
return this._dataSource.collectionViewMoveItemsFromIndexPaths(this._collectionView, indexPaths, args);
|
|
6513
7336
|
}
|
|
6514
7337
|
|
|
6515
|
-
removeItemsAtIndexPaths(indexPaths) {
|
|
6516
|
-
return this._dataSource.collectionViewRemoveItemsAtIndexPaths(this._collectionView, indexPaths);
|
|
7338
|
+
removeItemsAtIndexPaths(indexPaths, args) {
|
|
7339
|
+
return this._dataSource.collectionViewRemoveItemsAtIndexPaths(this._collectionView, indexPaths, args);
|
|
6517
7340
|
}
|
|
6518
7341
|
|
|
6519
7342
|
insertItems(items, args) {
|
|
@@ -6529,6 +7352,18 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6529
7352
|
};
|
|
6530
7353
|
}
|
|
6531
7354
|
|
|
7355
|
+
if (dataSource.collectionViewDragItemForIndexPath) {
|
|
7356
|
+
adapter.dragItemForIndexPath = function (indexPath, args) {
|
|
7357
|
+
return dataSource.collectionViewDragItemForIndexPath(adapter._collectionView, indexPath, args);
|
|
7358
|
+
};
|
|
7359
|
+
}
|
|
7360
|
+
|
|
7361
|
+
if (dataSource.collectionViewIndexPathForDragItem) {
|
|
7362
|
+
adapter.indexPathForDragItem = function (item, args) {
|
|
7363
|
+
return dataSource.collectionViewIndexPathForDragItem(adapter._collectionView, item, args);
|
|
7364
|
+
};
|
|
7365
|
+
}
|
|
7366
|
+
|
|
6532
7367
|
return adapter;
|
|
6533
7368
|
}
|
|
6534
7369
|
}
|