bm-core-ui 2.11.9-beta.2 → 2.12.0-beta.10
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 +2237 -71
- package/build/BMCollectionView/BMCollectionView.js +1057 -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 +1185 -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 +47 -19
- 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 +2237 -71
- package/lib/BMCoreUI.min.js +1 -1
- package/package.json +2 -2
|
@@ -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,605 @@ 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
|
+
for (const preview of this._dropPreviews) {
|
|
3586
|
+
preview.performDrop();
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
// If there are no items to accept, don't perform any other changes
|
|
3591
|
+
if (!session.dropItems.length) {
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
let toIndexPath = this._lastDropIndexPath;
|
|
3596
|
+
if (!toIndexPath) {
|
|
3597
|
+
const sectionCount = this.numberOfSections();
|
|
3598
|
+
const row = this.numberOfObjectsInSectionAtIndex(sectionCount - 1) - 1;
|
|
3599
|
+
const section = sectionCount - 1;
|
|
3600
|
+
toIndexPath = this.indexPathForObjectAtRow(row, {inSectionAtIndex: section}) ?? BMIndexPathMakeWithRow(row, {section});
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
// Instruct the data set to insert the items to the appropriate index path
|
|
3604
|
+
this._dropPreviews = session.dropPreviews.slice();
|
|
3605
|
+
|
|
3606
|
+
const items = session.dropItems.map(i => i.itemOfType('default'));
|
|
3607
|
+
const result = this.dataSet.insertItems(items, {toIndexPath, session});
|
|
3608
|
+
|
|
3609
|
+
if (result) {
|
|
3610
|
+
// If the data set performs the change asynchronously, give it 200ms to trigger the data update, otherwise
|
|
3611
|
+
// play the generic drop animation for the previews
|
|
3612
|
+
const dropPreviews = this._dropPreviews;
|
|
3613
|
+
let resolved = NO;
|
|
3614
|
+
result.then(() => {
|
|
3615
|
+
resolved = YES;
|
|
3616
|
+
|
|
3617
|
+
if (this._dropPreviews == dropPreviews) {
|
|
3618
|
+
this._dropPreviews = undefined;
|
|
3619
|
+
}
|
|
3620
|
+
});
|
|
3621
|
+
|
|
3622
|
+
setTimeout(() => {
|
|
3623
|
+
if (!resolved) {
|
|
3624
|
+
if (this._dropPreviews == dropPreviews) {
|
|
3625
|
+
this._dropPreviews = undefined;
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
for (const preview of dropPreviews) {
|
|
3629
|
+
preview.performDrop();
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
}, _BMCollectionViewAsynchronousDropDelay);
|
|
3633
|
+
}
|
|
3634
|
+
else {
|
|
3635
|
+
this._dropPreviews = undefined;
|
|
3636
|
+
}
|
|
3637
|
+
},
|
|
3638
|
+
|
|
2968
3639
|
/**
|
|
2969
3640
|
* Begins a drag gesture from the given event. The drag event will move the cell from which
|
|
2970
3641
|
* the event originates.
|
|
@@ -2975,7 +3646,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
2975
3646
|
* of the touch point that will control this drag & drop operation.
|
|
2976
3647
|
* }
|
|
2977
3648
|
*/
|
|
2978
|
-
|
|
3649
|
+
_beginDragWithEvent(event, args) {
|
|
2979
3650
|
if (this.isDragging) return;
|
|
2980
3651
|
// TODO Consider splitting up this giant method
|
|
2981
3652
|
|
|
@@ -3018,7 +3689,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3018
3689
|
}
|
|
3019
3690
|
else {
|
|
3020
3691
|
cells = [cell];
|
|
3021
|
-
cell.
|
|
3692
|
+
cell.isDragging = YES;
|
|
3022
3693
|
cell.retain();
|
|
3023
3694
|
|
|
3024
3695
|
cell.node.classList.add('BMCollectionViewCellDragging');
|
|
@@ -3082,18 +3753,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3082
3753
|
|
|
3083
3754
|
draggingShadows.push(otherDraggingShadow);
|
|
3084
3755
|
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
|
-
// });
|
|
3756
|
+
|
|
3097
3757
|
(window.Velocity || $.Velocity).animate(otherDraggingShadow, {tween: 1}, {
|
|
3098
3758
|
easing: 'easeInOutQuad',
|
|
3099
3759
|
duration: 300,
|
|
@@ -3123,15 +3783,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3123
3783
|
draggingShadowsToAdd.forEach(shadow => document.body.appendChild(shadow));
|
|
3124
3784
|
document.body.appendChild(draggingIndicator);
|
|
3125
3785
|
|
|
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
3786
|
__BMVelocityAnimate(draggingIndicator, {
|
|
3136
3787
|
opacity: [1, 0],
|
|
3137
3788
|
scaleX: [1, 0],
|
|
@@ -3342,10 +3993,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3342
3993
|
}
|
|
3343
3994
|
|
|
3344
3995
|
// Temporarily suspend these updates while a data update is in progress
|
|
3345
|
-
if (this.isUpdatingData)
|
|
3996
|
+
if (this.isUpdatingData) {
|
|
3997
|
+
event.preventDefault();
|
|
3998
|
+
event.stopPropagation();
|
|
3999
|
+
return;
|
|
4000
|
+
}
|
|
3346
4001
|
|
|
3347
4002
|
|
|
3348
|
-
// 3.
|
|
4003
|
+
// 3. Enable scrolling while close to the collection view's edges.
|
|
3349
4004
|
if (clientX - collectionViewViewportFrame.origin.x < 32) {
|
|
3350
4005
|
scrollDirectionX = (clientX - collectionViewViewportFrame.origin.x - 32) / 32 * 20;
|
|
3351
4006
|
}
|
|
@@ -3773,7 +4428,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
3773
4428
|
// Remove the dragging class from the cell
|
|
3774
4429
|
cells.forEach(cell => {
|
|
3775
4430
|
cell.node.classList.remove('BMCollectionViewCellDragging');
|
|
3776
|
-
cell.
|
|
4431
|
+
cell.isDragging = NO;
|
|
3777
4432
|
|
|
3778
4433
|
// Release the cell
|
|
3779
4434
|
cell.release();
|
|
@@ -4381,7 +5036,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4381
5036
|
* Highlights the index path to the specified direction of the currently highlighted index path.
|
|
4382
5037
|
* @param arrow <String> The key code of the keyboard arrow that was pressed.
|
|
4383
5038
|
* {
|
|
4384
|
-
* @param withEvent <KeyboardEvent> The event that
|
|
5039
|
+
* @param withEvent <KeyboardEvent> The event that triggered this action.
|
|
4385
5040
|
* }
|
|
4386
5041
|
*/
|
|
4387
5042
|
keyboardArrowPressed(arrow, args) {
|
|
@@ -4872,8 +5527,66 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4872
5527
|
// regardless of where the new or old positions of cells might be
|
|
4873
5528
|
let size = layout.contentSize();
|
|
4874
5529
|
this._size = BMSizeMake(Math.max(this._size.width, size.width), Math.max(this._size.height, size.height));
|
|
5530
|
+
|
|
5531
|
+
/**
|
|
5532
|
+
* Cleans up the changes performed by the current transition.
|
|
5533
|
+
*/
|
|
5534
|
+
function cleanupTransition() {
|
|
5535
|
+
if (self.iScroll) self.iScroll.refresh();
|
|
5536
|
+
|
|
5537
|
+
// Unmanage all outgoing supplementary views
|
|
5538
|
+
for (var i = 0; i < outgoingSupplementaryViewAttributes.length; i++) {
|
|
5539
|
+
var attribute = outgoingSupplementaryViewAttributes[i];
|
|
5540
|
+
var cell = self.supplementaryViewWithIdentifier(attribute.identifier, {atIndexPath: attribute.indexPath});
|
|
5541
|
+
|
|
5542
|
+
if (cell && cell.isManaged) {
|
|
5543
|
+
cell._unmanage();
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
|
|
5547
|
+
self._applyOverflows();
|
|
5548
|
+
|
|
5549
|
+
// Restore collection and invoke the data completion callbacks unless another animation is in progress
|
|
5550
|
+
if (self._dataUpdatePromise == dataUpdatePromise) {
|
|
5551
|
+
self._collectionEnabled = YES;
|
|
5552
|
+
self.isUpdatingData = NO;
|
|
5553
|
+
|
|
5554
|
+
self._executeDataCompletionCallbacks();
|
|
5555
|
+
}
|
|
5556
|
+
|
|
5557
|
+
// If the delegate animation options contains a complete handler, invoke it here
|
|
5558
|
+
if (delegateOptions.complete) delegateOptions.complete();
|
|
5559
|
+
|
|
5560
|
+
// Run the completion handler if it was specified
|
|
5561
|
+
if (options && options.completionHandler) options.completionHandler();
|
|
5562
|
+
|
|
5563
|
+
resolveLayoutUpdate();
|
|
5564
|
+
}
|
|
4875
5565
|
|
|
4876
5566
|
animationOptions.complete = function () {
|
|
5567
|
+
// If the transition was stopped, don't continue with the remaining changes
|
|
5568
|
+
if (self._layout != transitionLayout) {
|
|
5569
|
+
self._size = size.copy();
|
|
5570
|
+
|
|
5571
|
+
if (self.iScroll) {
|
|
5572
|
+
// Apply the new scroll offset internally to iScroll, if it changed
|
|
5573
|
+
if (oldBounds.origin.x != newBounds.origin.x || oldBounds.origin.y != newBounds.origin.y) {
|
|
5574
|
+
var targetOffset = newBounds.origin.copy();
|
|
5575
|
+
|
|
5576
|
+
targetOffset.x += self._offscreenBufferSize;
|
|
5577
|
+
targetOffset.y += self._offscreenBufferSize;
|
|
5578
|
+
|
|
5579
|
+
self.iScroll._translate(-targetOffset.x, -targetOffset.y);
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
|
|
5583
|
+
animationCells.forEach(cell => cell.release());
|
|
5584
|
+
retainedCells.forEach(cell => cell.release());
|
|
5585
|
+
|
|
5586
|
+
cleanupTransition();
|
|
5587
|
+
return;
|
|
5588
|
+
}
|
|
5589
|
+
|
|
4877
5590
|
// Request the layout page
|
|
4878
5591
|
var attributes = transitionLayout.attributesForElementsInRect();
|
|
4879
5592
|
|
|
@@ -4908,35 +5621,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
4908
5621
|
self._layout = layout;
|
|
4909
5622
|
self._transitionLayout = undefined;
|
|
4910
5623
|
|
|
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();
|
|
5624
|
+
cleanupTransition();
|
|
4940
5625
|
};
|
|
4941
5626
|
|
|
4942
5627
|
animationOptions.queue = NO;
|
|
@@ -5034,9 +5719,16 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5034
5719
|
|
|
5035
5720
|
},
|
|
5036
5721
|
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5722
|
+
/**
|
|
5723
|
+
* If a layout transition is currently in progress it is stopped, allowing data updates to
|
|
5724
|
+
* start without affecting the retained cells.
|
|
5725
|
+
*/
|
|
5726
|
+
_stopLayoutTransition() {
|
|
5727
|
+
if (this._transitionLayout && this._layout == this._transitionLayout) {
|
|
5728
|
+
this._layout._stopTransition();
|
|
5729
|
+
this._layout = this._layout.targetLayout;
|
|
5730
|
+
}
|
|
5731
|
+
},
|
|
5040
5732
|
|
|
5041
5733
|
/************************************* DATA SET UPDATE ************************************/
|
|
5042
5734
|
|
|
@@ -5133,6 +5825,49 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5133
5825
|
get dataUpdated() { // <Promise<void>, nullable>
|
|
5134
5826
|
return this._dataUpdatePromise;
|
|
5135
5827
|
},
|
|
5828
|
+
|
|
5829
|
+
/**
|
|
5830
|
+
* Finds and returns the drop preview associated with the specified layout attributes, if any exists.
|
|
5831
|
+
* @param attributes <BMCollectionViewLayoutAttributes> Tha attributes for which to find the drop preview.
|
|
5832
|
+
* {
|
|
5833
|
+
* @param previewMap <Map<BMIndexPath<T>, BMDropPreview>, nullable>
|
|
5834
|
+
* An optional mapping between index paths and drop items
|
|
5835
|
+
* used to find the drop preview for the item representation
|
|
5836
|
+
* that the data set actually inserted. The default item
|
|
5837
|
+
* representation will be used if this is not provided.
|
|
5838
|
+
* }
|
|
5839
|
+
* @returns <BMDropPreview, nullable> The drop preview if it was found, `undefined` otherwise.
|
|
5840
|
+
*/
|
|
5841
|
+
_dropPreviewForLayoutAttributes: function (attributes, {previewMap}) {
|
|
5842
|
+
if (!this._dropPreviews) {
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
|
|
5846
|
+
let dropPreview;
|
|
5847
|
+
|
|
5848
|
+
if (this._cellItemMap) {
|
|
5849
|
+
for (const [item, cell] of this._cellItemMap.entries()) {
|
|
5850
|
+
if (cell.indexPath.isLooselyEqualToIndexPath(attributes.indexPath, {usingComparator: this.identityComparator})) {
|
|
5851
|
+
return this._dropPreviews.find(p => p.item == item);
|
|
5852
|
+
}
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
else if (previewMap) {
|
|
5856
|
+
for (const [indexPath, preview] of previewMap.entries()) {
|
|
5857
|
+
if (indexPath.isEqualToIndexPath(attributes.indexPath, {usingComparator: this.identityComparator})) {
|
|
5858
|
+
dropPreview = preview;
|
|
5859
|
+
break;
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
}
|
|
5863
|
+
else {
|
|
5864
|
+
// If the data set did not provide the new index paths, assume that the default representation
|
|
5865
|
+
// was used and instead look for the object
|
|
5866
|
+
dropPreview = this._dropPreviews.find(p => p.item.itemOfType('default') == attributes.indexPath.object);
|
|
5867
|
+
}
|
|
5868
|
+
|
|
5869
|
+
return dropPreview;
|
|
5870
|
+
},
|
|
5136
5871
|
|
|
5137
5872
|
/**
|
|
5138
5873
|
* Should be invoked when the entire data set is updated in bulk.
|
|
@@ -5163,6 +5898,9 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5163
5898
|
let resolveUpdateData;
|
|
5164
5899
|
const dataUpdatePromise = new Promise(function (resolve, reject) {resolveUpdateData = resolve});
|
|
5165
5900
|
this._dataUpdatePromise = dataUpdatePromise;
|
|
5901
|
+
|
|
5902
|
+
// Stop any in progress layout updates
|
|
5903
|
+
this._stopLayoutTransition();
|
|
5166
5904
|
|
|
5167
5905
|
// Update the selection index paths
|
|
5168
5906
|
this._updateSelectionIndexPaths();
|
|
@@ -5272,8 +6010,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5272
6010
|
// Disable scrolling and interaction during update
|
|
5273
6011
|
this._container[0].style.pointerEvents = 'none';
|
|
5274
6012
|
var containerScrollOffset = this.scrollOffset;
|
|
5275
|
-
|
|
5276
|
-
if (this.
|
|
6013
|
+
|
|
6014
|
+
if (!this.iScroll) {
|
|
6015
|
+
this._container[0].scrollTo(containerScrollOffset.x, containerScrollOffset.y);
|
|
6016
|
+
}
|
|
6017
|
+
|
|
6018
|
+
if (this.scrollView) {
|
|
6019
|
+
this.scrollView.scrollingEnabled = NO;
|
|
6020
|
+
}
|
|
5277
6021
|
|
|
5278
6022
|
// Get the new content
|
|
5279
6023
|
var attributes = this.layout.attributesForElementsInRect(this._bounds);
|
|
@@ -5284,6 +6028,12 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5284
6028
|
var deletedCells = [];
|
|
5285
6029
|
var insertedCells = [];
|
|
5286
6030
|
var movingCells = [];
|
|
6031
|
+
|
|
6032
|
+
// Contains cells that are temporarily hidden due to a drop animation
|
|
6033
|
+
const sessionDropCells = [];
|
|
6034
|
+
|
|
6035
|
+
// Contains moving cells that have associated drop previews
|
|
6036
|
+
const dropMovingCells = [];
|
|
5287
6037
|
|
|
5288
6038
|
var supplementaryViewsToInsert = this.layout.supplementaryViewsToInsert();
|
|
5289
6039
|
var supplementaryViewsToDelete = this.layout.supplementaryViewsToDelete();
|
|
@@ -5297,6 +6047,20 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5297
6047
|
var visibleRect = new BMRect(BMPointMake(this._bounds.origin.x + this._offscreenBufferSize, this._bounds.origin.y + this._offscreenBufferSize), this._frame.size.copy());
|
|
5298
6048
|
var currentVisibleRect = new BMRect(BMPointMake(oldBounds.origin.x + this._offscreenBufferSize, oldBounds.origin.y + this._offscreenBufferSize), this._frame.size.copy());
|
|
5299
6049
|
|
|
6050
|
+
// If this update occurs because of a drag & drop operation, try to obtain the associated index paths from the data set
|
|
6051
|
+
let dropPreviewMap;
|
|
6052
|
+
if (this._dropPreviews && this.dataSet.indexPathForDragItem) {
|
|
6053
|
+
dropPreviewMap = new Map();
|
|
6054
|
+
|
|
6055
|
+
for (const preview of this._dropPreviews) {
|
|
6056
|
+
const indexPath = this.dataSet.indexPathForDragItem(preview.item);
|
|
6057
|
+
|
|
6058
|
+
if (indexPath) {
|
|
6059
|
+
dropPreviewMap.set(indexPath, preview);
|
|
6060
|
+
}
|
|
6061
|
+
}
|
|
6062
|
+
}
|
|
6063
|
+
|
|
5300
6064
|
// Compare the current content to the new content and data set
|
|
5301
6065
|
for (var i = 0; i < oldCells.length; i++) {
|
|
5302
6066
|
var cell = oldCells[i];
|
|
@@ -5314,13 +6078,17 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5314
6078
|
var attribute = attributes[j];
|
|
5315
6079
|
|
|
5316
6080
|
// Skip cells with different item types
|
|
5317
|
-
if (cell.itemType !== attribute.itemType)
|
|
6081
|
+
if (cell.itemType !== attribute.itemType) {
|
|
6082
|
+
continue;
|
|
6083
|
+
}
|
|
5318
6084
|
|
|
5319
6085
|
// Two cells refer to the same object if they are the same type and their index paths are loosely equal
|
|
5320
6086
|
if (cell.indexPath.isLooselyEqualToIndexPath(attribute.indexPath, {usingComparator: this.identityComparator})) {
|
|
5321
6087
|
|
|
5322
6088
|
// For supplementary views, it is also required that they have the same type identifier
|
|
5323
|
-
if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView && cell.reuseIdentifier !== attribute.identifier)
|
|
6089
|
+
if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView && cell.reuseIdentifier !== attribute.identifier) {
|
|
6090
|
+
continue;
|
|
6091
|
+
}
|
|
5324
6092
|
|
|
5325
6093
|
// If they are equal, mark the cell as moving and continue
|
|
5326
6094
|
cell.targetAttributes = attribute;
|
|
@@ -5330,17 +6098,35 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5330
6098
|
|
|
5331
6099
|
// Instruct the data set to update this cell's content
|
|
5332
6100
|
if (cell.itemType === BMCollectionViewLayoutAttributesType.Cell) {
|
|
5333
|
-
|
|
6101
|
+
|
|
6102
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6103
|
+
// at the appropriate position
|
|
6104
|
+
if (this._dropPreviews) {
|
|
6105
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6106
|
+
|
|
6107
|
+
if (dropPreview) {
|
|
6108
|
+
cell._dropPreview = dropPreview;
|
|
6109
|
+
dropMovingCells.push(cell);
|
|
6110
|
+
}
|
|
6111
|
+
}
|
|
6112
|
+
|
|
6113
|
+
if (this.dataSet.updateCell) {
|
|
6114
|
+
this.dataSet.updateCell(cell, {atIndexPath: attribute.indexPath});
|
|
6115
|
+
}
|
|
5334
6116
|
}
|
|
5335
6117
|
else if (cell.itemType === BMCollectionViewLayoutAttributesType.SupplementaryView) {
|
|
5336
|
-
if (this.dataSet.updateSupplementaryView)
|
|
6118
|
+
if (this.dataSet.updateSupplementaryView) {
|
|
6119
|
+
this.dataSet.updateSupplementaryView(cell, {withIdentifier: cell.reuseIdentifier, atIndexPath: attribute.indexPath});
|
|
6120
|
+
}
|
|
5337
6121
|
}
|
|
5338
6122
|
|
|
5339
6123
|
break;
|
|
5340
6124
|
}
|
|
5341
6125
|
}
|
|
5342
6126
|
|
|
5343
|
-
if (foundCell)
|
|
6127
|
+
if (foundCell) {
|
|
6128
|
+
continue;
|
|
6129
|
+
}
|
|
5344
6130
|
|
|
5345
6131
|
// If the cell wasn't found in the new layout, check to see if its object still exists in the data set
|
|
5346
6132
|
if (cell.itemType === BMCollectionViewLayoutAttributesType.Cell) {
|
|
@@ -5351,9 +6137,22 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5351
6137
|
var attribute = this.layout.attributesForCellAtIndexPath(indexPath);
|
|
5352
6138
|
cell.targetAttributes = attribute;
|
|
5353
6139
|
movingCells.push(cell);
|
|
6140
|
+
|
|
6141
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6142
|
+
// at the appropriate position
|
|
6143
|
+
if (this._dropPreviews) {
|
|
6144
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6145
|
+
|
|
6146
|
+
if (dropPreview) {
|
|
6147
|
+
cell._dropPreview = dropPreview;
|
|
6148
|
+
dropMovingCells.push(cell);
|
|
6149
|
+
}
|
|
6150
|
+
}
|
|
5354
6151
|
|
|
5355
6152
|
// Instruct the data set to update this cell's content
|
|
5356
|
-
if (this.dataSet.updateCell)
|
|
6153
|
+
if (this.dataSet.updateCell) {
|
|
6154
|
+
this.dataSet.updateCell(cell, {atIndexPath: attribute.indexPath});
|
|
6155
|
+
}
|
|
5357
6156
|
}
|
|
5358
6157
|
else {
|
|
5359
6158
|
// Otherwise the cell was removed from the data set
|
|
@@ -5381,7 +6180,9 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5381
6180
|
movingCells.push(cell);
|
|
5382
6181
|
|
|
5383
6182
|
// Instruct the data set to update this supplementary view's content
|
|
5384
|
-
if (this.dataSet.updateSupplementaryView)
|
|
6183
|
+
if (this.dataSet.updateSupplementaryView) {
|
|
6184
|
+
this.dataSet.updateSupplementaryView(cell, {withIdentifier: cell.reuseIdentifier, atIndexPath: attribute.indexPath});
|
|
6185
|
+
}
|
|
5385
6186
|
}
|
|
5386
6187
|
else {
|
|
5387
6188
|
// Otherwise find its final attributes
|
|
@@ -5396,12 +6197,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5396
6197
|
|
|
5397
6198
|
// Construct the cells for the new attributes
|
|
5398
6199
|
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
6200
|
|
|
5406
6201
|
// Compare the remaining new content to the old data set
|
|
5407
6202
|
for (var i = 0; i < attributes.length; i++) {
|
|
@@ -5424,53 +6219,55 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5424
6219
|
var oldAttribute = this.layout.initialAttributesForMovingCellFromIndexPath(oldIndexPath, {toIndexPath: attribute.indexPath, withTargetAttributes: attribute});
|
|
5425
6220
|
attribute.initialAttributes = oldAttribute;
|
|
5426
6221
|
//oldAttribute.indexPath = attribute.indexPath;
|
|
6222
|
+
|
|
6223
|
+
// If a drop preview exists for this cell, store it so that the drop is performed
|
|
6224
|
+
// at the appropriate position
|
|
6225
|
+
if (this._dropPreviews) {
|
|
6226
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(cell.targetAttributes, {previewMap: dropPreviewMap});
|
|
6227
|
+
|
|
6228
|
+
if (dropPreview) {
|
|
6229
|
+
cell._dropPreview = dropPreview;
|
|
6230
|
+
dropMovingCells.push(cell);
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
5427
6233
|
}
|
|
5428
6234
|
else {
|
|
5429
6235
|
// Otherwise this is a new element
|
|
5430
6236
|
|
|
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;
|
|
6237
|
+
// Check if there is a drop preview associated with this element and transition from that preview
|
|
6238
|
+
if (this._dropPreviews) {
|
|
6239
|
+
// Find if a newly inserted index path matches this cell's index path
|
|
6240
|
+
const dropPreview = this._dropPreviewForLayoutAttributes(attribute, {previewMap: dropPreviewMap});
|
|
6241
|
+
|
|
6242
|
+
let initialAttributes = attribute;
|
|
6243
|
+
|
|
6244
|
+
// If a preferred scroll offset is provided by the layout, displace the cell initially so that it
|
|
6245
|
+
// starts out at the position it will be in at the end of the scroll animation, relative to the viewport
|
|
6246
|
+
const displacement = BMPointMake(
|
|
6247
|
+
preferredScrollOffset.x - scrollOffset.x,
|
|
6248
|
+
preferredScrollOffset.y - scrollOffset.y
|
|
6249
|
+
);
|
|
6250
|
+
|
|
6251
|
+
if (displacement.x || displacement.y) {
|
|
6252
|
+
initialAttributes = attribute.copy();
|
|
6253
|
+
initialAttributes.frame = initialAttributes.frame.copy();
|
|
6254
|
+
initialAttributes.frame.offset(displacement.x, displacement.y);
|
|
6255
|
+
}
|
|
6256
|
+
|
|
6257
|
+
if (dropPreview) {
|
|
6258
|
+
newCell._dropPreview = dropPreview;
|
|
6259
|
+
attribute.initialAttributes = initialAttributes;
|
|
6260
|
+
insertedCells.push(newCell);
|
|
6261
|
+
}
|
|
6262
|
+
else {
|
|
6263
|
+
const initialAttributes = this.layout.initialAttributesForAppearingCellAtIndexPath(attribute.indexPath, {withTargetAttributes: attribute});
|
|
6264
|
+
attribute.initialAttributes = initialAttributes;
|
|
6265
|
+
}
|
|
5467
6266
|
}
|
|
5468
6267
|
else {
|
|
5469
6268
|
var initialAttributes = this.layout.initialAttributesForAppearingCellAtIndexPath(attribute.indexPath, {withTargetAttributes: attribute});
|
|
6269
|
+
attribute.initialAttributes = initialAttributes;
|
|
5470
6270
|
}
|
|
5471
|
-
|
|
5472
|
-
attribute.initialAttributes = initialAttributes;
|
|
5473
|
-
//initialAttributes.indexPath = attribute.indexPath;
|
|
5474
6271
|
}
|
|
5475
6272
|
|
|
5476
6273
|
newCell.attributes = attribute.initialAttributes;
|
|
@@ -5596,7 +6393,14 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5596
6393
|
animationCells[i].release();
|
|
5597
6394
|
|
|
5598
6395
|
// Additionally, unmanage hidden cells
|
|
5599
|
-
if (animationCells[i].attributes.isHidden)
|
|
6396
|
+
if (animationCells[i].attributes.isHidden) {
|
|
6397
|
+
animationCells[i]._unmanage();
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
|
|
6401
|
+
// Remove the hiding class from inserted cells
|
|
6402
|
+
for (const cell of sessionDropCells) {
|
|
6403
|
+
cell.node.classList.remove('BMCollectionViewCellInserting');
|
|
5600
6404
|
}
|
|
5601
6405
|
|
|
5602
6406
|
// Destroy the deleted cells
|
|
@@ -5629,56 +6433,6 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5629
6433
|
|
|
5630
6434
|
};
|
|
5631
6435
|
|
|
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
6436
|
// All cells involved in the animation will be retained for the duration of the animation
|
|
5683
6437
|
// And then released at the end
|
|
5684
6438
|
var animationCells = [];
|
|
@@ -5696,26 +6450,65 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5696
6450
|
}
|
|
5697
6451
|
|
|
5698
6452
|
// 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});
|
|
6453
|
+
if (self._dropPreviews) {
|
|
6454
|
+
for (const cell of insertedCells) {
|
|
6455
|
+
cell._dropPreview.performDropToNode(cell.node);
|
|
6456
|
+
|
|
6457
|
+
const index = self._dropPreviews.indexOf(cell._dropPreview);
|
|
6458
|
+
|
|
6459
|
+
if (index != -1) {
|
|
6460
|
+
self._dropPreviews.splice(index, 1);
|
|
5710
6461
|
}
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
6462
|
+
}
|
|
6463
|
+
|
|
6464
|
+
if (dropMovingCells.length) {
|
|
6465
|
+
// For the items that move, move them instantly to their final positions start the drop
|
|
6466
|
+
// animations, then move them back for the regular animation to play for them
|
|
6467
|
+
BMAnimationContextBeginStatic();
|
|
6468
|
+
const initialAttributeMap = new Map();
|
|
6469
|
+
for (const cell of dropMovingCells) {
|
|
6470
|
+
// Instantly move each cell to its final attributes
|
|
6471
|
+
initialAttributeMap.set(cell, cell.attributes);
|
|
6472
|
+
cell.attributes = cell.targetAttributes;
|
|
5717
6473
|
}
|
|
5718
|
-
|
|
6474
|
+
BMAnimationApply();
|
|
6475
|
+
|
|
6476
|
+
// Play all drop animations
|
|
6477
|
+
for (const cell of dropMovingCells) {
|
|
6478
|
+
cell._dropPreview.performDropToNode(cell.node);
|
|
6479
|
+
const index = self._dropPreviews.indexOf(cell._dropPreview);
|
|
6480
|
+
|
|
6481
|
+
if (index != -1) {
|
|
6482
|
+
self._dropPreviews.splice(index, 1);
|
|
6483
|
+
}
|
|
6484
|
+
}
|
|
6485
|
+
|
|
6486
|
+
// Revert each cell to its staging attributes
|
|
6487
|
+
BMAnimationContextBeginStatic();
|
|
6488
|
+
for (const [cell, attributes] of initialAttributeMap) {
|
|
6489
|
+
cell.attributes = attributes;
|
|
6490
|
+
}
|
|
6491
|
+
BMAnimationApply();
|
|
6492
|
+
}
|
|
6493
|
+
|
|
6494
|
+
// For remaining drop previews, play an animation to the target cell if available
|
|
6495
|
+
if (self._cellItemMap) {
|
|
6496
|
+
for (let i = 0; i < self._dropPreviews.length; i++) {
|
|
6497
|
+
const item = self._dropPreviews[i];
|
|
6498
|
+
const cell = self._cellItemMap.get(item);
|
|
6499
|
+
|
|
6500
|
+
if (cell) {
|
|
6501
|
+
self._dropPreviews.performDropToNode(cell.node);
|
|
6502
|
+
self._dropPreviews.splice(i, 1);
|
|
6503
|
+
i--;
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
|
|
6508
|
+
// Play a generic animation for all remaining drop previews without associated cells
|
|
6509
|
+
for (const preview of self._dropPreviews) {
|
|
6510
|
+
preview.performDrop();
|
|
6511
|
+
}
|
|
5719
6512
|
}
|
|
5720
6513
|
|
|
5721
6514
|
// Apply the new scroll offset, if it changed
|
|
@@ -5766,7 +6559,15 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5766
6559
|
var cell = newCells[i];
|
|
5767
6560
|
if (!cell.animatable) continue;
|
|
5768
6561
|
|
|
5769
|
-
cell.
|
|
6562
|
+
if (cell._dropPreview) {
|
|
6563
|
+
cell._dropPreview = undefined;
|
|
6564
|
+
cell.node.classList.add('BMCollectionViewCellInserting');
|
|
6565
|
+
sessionDropCells.push(cell);
|
|
6566
|
+
}
|
|
6567
|
+
else {
|
|
6568
|
+
cell.attributes = cell.targetAttributes;
|
|
6569
|
+
}
|
|
6570
|
+
|
|
5770
6571
|
cell.animatable = NO;
|
|
5771
6572
|
|
|
5772
6573
|
animationCells.push(cell.retain());
|
|
@@ -5803,6 +6604,11 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5803
6604
|
if (BMAnimationContextGetCurrent()) {
|
|
5804
6605
|
animationBlock();
|
|
5805
6606
|
BMAnimationContextAddCompletionHandler(animationOptions.complete);
|
|
6607
|
+
|
|
6608
|
+
// Clear out all target attributes on all cell after the animation starts
|
|
6609
|
+
for (const cell of this.allCells) {
|
|
6610
|
+
cell.targetAttributes = undefined;
|
|
6611
|
+
}
|
|
5806
6612
|
}
|
|
5807
6613
|
else {
|
|
5808
6614
|
BMAnimateWithBlock(animationBlock, animationOptions);
|
|
@@ -5812,7 +6618,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5812
6618
|
this.oldBounds = undefined;
|
|
5813
6619
|
|
|
5814
6620
|
// If no cells should be changed, immediately run the completion handler
|
|
5815
|
-
if (newCells.length == 0 && oldCells.length == 0) {
|
|
6621
|
+
if (newCells.length == 0 && oldCells.length == 0 && !this._dropPreviews) {
|
|
5816
6622
|
animationOptions.complete();
|
|
5817
6623
|
}
|
|
5818
6624
|
|
|
@@ -5997,9 +6803,16 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
5997
6803
|
// Scroll to the offset point
|
|
5998
6804
|
if (options.animated) {
|
|
5999
6805
|
var self = this;
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6806
|
+
const currentContext = BMAnimationContextGetCurrent();
|
|
6807
|
+
if (!currentContext) {
|
|
6808
|
+
BMAnimationBeginWithDuration(300);
|
|
6809
|
+
}
|
|
6810
|
+
|
|
6811
|
+
self.scrollOffset = offset;
|
|
6812
|
+
|
|
6813
|
+
if (!currentContext) {
|
|
6814
|
+
BMAnimationApply();
|
|
6815
|
+
}
|
|
6003
6816
|
}
|
|
6004
6817
|
else {
|
|
6005
6818
|
// Scrolling is performed differently based on whether iScroll is used or not
|
|
@@ -6282,6 +7095,7 @@ BMCollectionView.prototype = BMExtend(BM_COLLECTION_VIEW_USE_BMVIEW_SUBCLASS ? O
|
|
|
6282
7095
|
var self = this;
|
|
6283
7096
|
|
|
6284
7097
|
_BMCollectionViews.delete(this);
|
|
7098
|
+
BMDragSession._dropTargets.delete(this);
|
|
6285
7099
|
|
|
6286
7100
|
// Unbind the scroll event listener
|
|
6287
7101
|
if (this.initialized && !this.iScroll) {
|
|
@@ -6419,8 +7233,8 @@ class BMCollectionViewDataSourceAdapter {
|
|
|
6419
7233
|
return this._dataSet.moveItemsFromIndexPaths(indexPaths, args);
|
|
6420
7234
|
}
|
|
6421
7235
|
|
|
6422
|
-
collectionViewRemoveItemsAtIndexPaths(collectionView, indexPaths) {
|
|
6423
|
-
return this._dataSet.removeItemsAtIndexPaths(indexPaths);
|
|
7236
|
+
collectionViewRemoveItemsAtIndexPaths(collectionView, indexPaths, args) {
|
|
7237
|
+
return this._dataSet.removeItemsAtIndexPaths(indexPaths, args);
|
|
6424
7238
|
}
|
|
6425
7239
|
|
|
6426
7240
|
collectionViewInsertItems(collectionView, items, args) {
|
|
@@ -6436,6 +7250,18 @@ class BMCollectionViewDataSourceAdapter {
|
|
|
6436
7250
|
};
|
|
6437
7251
|
}
|
|
6438
7252
|
|
|
7253
|
+
if (dataSet.dragItemForIndexPath) {
|
|
7254
|
+
adapter.collectionViewDragItemForIndexPath = function (collectionView, indexPath, args) {
|
|
7255
|
+
return dataSet.dragItemForIndexPath(indexPath, args);
|
|
7256
|
+
};
|
|
7257
|
+
}
|
|
7258
|
+
|
|
7259
|
+
if (dataSet.indexPathForDragItem) {
|
|
7260
|
+
adapter.collectionViewIndexPathForDragItem = function (collectionView, item, args) {
|
|
7261
|
+
return dataSet.indexPathForDragItem(item, args);
|
|
7262
|
+
};
|
|
7263
|
+
}
|
|
7264
|
+
|
|
6439
7265
|
return adapter;
|
|
6440
7266
|
}
|
|
6441
7267
|
}
|
|
@@ -6472,30 +7298,14 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6472
7298
|
return this._dataSource.collectionViewIndexPathForObject(this._collectionView, object);
|
|
6473
7299
|
}
|
|
6474
7300
|
|
|
6475
|
-
contentsForCellWithReuseIdentifier(identifier) {
|
|
6476
|
-
throw new Error(`contentsForCellWithReuseIdentifier is unsupported when using data source objects`);
|
|
6477
|
-
}
|
|
6478
|
-
|
|
6479
7301
|
cellForItemAtIndexPath(indexPath) {
|
|
6480
7302
|
return this._dataSource.collectionViewCellForItemAtIndexPath(this._collectionView, indexPath);
|
|
6481
7303
|
}
|
|
6482
7304
|
|
|
6483
|
-
contentsForSupplementaryViewWithIdentifier(identifier) {
|
|
6484
|
-
throw new Error(`contentsForSupplementaryViewWithIdentifier is unsupported when using data source objects`);
|
|
6485
|
-
}
|
|
6486
|
-
|
|
6487
7305
|
cellForSupplementaryViewWithIdentifier(identifier, args) {
|
|
6488
7306
|
return this._dataSource.collectionViewCellForSupplementaryViewWithIdentifier(this._collectionView, identifier, args);
|
|
6489
7307
|
}
|
|
6490
7308
|
|
|
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
7309
|
useOldData(use) {
|
|
6500
7310
|
return this._dataSource.collectionViewUseOldData(this._collectionView, use);
|
|
6501
7311
|
}
|
|
@@ -6512,8 +7322,8 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6512
7322
|
return this._dataSource.collectionViewMoveItemsFromIndexPaths(this._collectionView, indexPaths, args);
|
|
6513
7323
|
}
|
|
6514
7324
|
|
|
6515
|
-
removeItemsAtIndexPaths(indexPaths) {
|
|
6516
|
-
return this._dataSource.collectionViewRemoveItemsAtIndexPaths(this._collectionView, indexPaths);
|
|
7325
|
+
removeItemsAtIndexPaths(indexPaths, args) {
|
|
7326
|
+
return this._dataSource.collectionViewRemoveItemsAtIndexPaths(this._collectionView, indexPaths, args);
|
|
6517
7327
|
}
|
|
6518
7328
|
|
|
6519
7329
|
insertItems(items, args) {
|
|
@@ -6529,6 +7339,18 @@ class BMCollectionViewDataSetAdapter {
|
|
|
6529
7339
|
};
|
|
6530
7340
|
}
|
|
6531
7341
|
|
|
7342
|
+
if (dataSource.collectionViewDragItemForIndexPath) {
|
|
7343
|
+
adapter.dragItemForIndexPath = function (indexPath, args) {
|
|
7344
|
+
return dataSource.collectionViewDragItemForIndexPath(adapter._collectionView, indexPath, args);
|
|
7345
|
+
};
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
if (dataSource.collectionViewIndexPathForDragItem) {
|
|
7349
|
+
adapter.indexPathForDragItem = function (item, args) {
|
|
7350
|
+
return dataSource.collectionViewIndexPathForDragItem(adapter._collectionView, item, args);
|
|
7351
|
+
};
|
|
7352
|
+
}
|
|
7353
|
+
|
|
6532
7354
|
return adapter;
|
|
6533
7355
|
}
|
|
6534
7356
|
}
|