1// Copyright (C) 2022 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {assertTrue} from '../base/logging'; 16 17export type DropDirection = 'left'|'right'; 18 19export interface Interval { 20 from: number; 21 to: number; 22} 23 24/* 25 * When a drag'n'drop is performed in a linear sequence, the resulting reordered 26 * array will consist of several contiguous subarrays of the original glued 27 * together. 28 * 29 * This function implements the computation of these intervals. 30 * 31 * The drag'n'drop operation performed is as follows: in the sequence with given 32 * length, the element with index `dragFrom` is dropped on the `direction` to 33 * the element `dragTo`. 34 */ 35export function computeIntervals( 36 length: number, dragFrom: number, dragTo: number, direction: DropDirection): 37 Interval[] { 38 assertTrue(dragFrom !== dragTo); 39 40 if (dragTo < dragFrom) { 41 const prefixLen = direction == 'left' ? dragTo : dragTo + 1; 42 return [ 43 // First goes unchanged prefix. 44 {from: 0, to: prefixLen}, 45 // Then goes dragged element. 46 {from: dragFrom, to: dragFrom + 1}, 47 // Then goes suffix up to dragged element (which has already been moved). 48 {from: prefixLen, to: dragFrom}, 49 // Then the rest of an array. 50 {from: dragFrom + 1, to: length}, 51 ]; 52 } 53 54 // Other case: dragTo > dragFrom 55 const prefixLen = direction == 'left' ? dragTo : dragTo + 1; 56 return [ 57 {from: 0, to: dragFrom}, 58 {from: dragFrom + 1, to: prefixLen}, 59 {from: dragFrom, to: dragFrom + 1}, 60 {from: prefixLen, to: length}, 61 ]; 62} 63 64export function performReordering<T>(intervals: Interval[], arr: T[]): T[] { 65 const result: T[] = []; 66 67 for (const interval of intervals) { 68 result.push(...arr.slice(interval.from, interval.to)); 69 } 70 71 return result; 72} 73