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, 37 dragFrom: number, 38 dragTo: number, 39 direction: DropDirection, 40): Interval[] { 41 assertTrue(dragFrom !== dragTo); 42 43 if (dragTo < dragFrom) { 44 const prefixLen = direction == 'left' ? dragTo : dragTo + 1; 45 return [ 46 // First goes unchanged prefix. 47 {from: 0, to: prefixLen}, 48 // Then goes dragged element. 49 {from: dragFrom, to: dragFrom + 1}, 50 // Then goes suffix up to dragged element (which has already been moved). 51 {from: prefixLen, to: dragFrom}, 52 // Then the rest of an array. 53 {from: dragFrom + 1, to: length}, 54 ]; 55 } 56 57 // Other case: dragTo > dragFrom 58 const prefixLen = direction == 'left' ? dragTo : dragTo + 1; 59 return [ 60 {from: 0, to: dragFrom}, 61 {from: dragFrom + 1, to: prefixLen}, 62 {from: dragFrom, to: dragFrom + 1}, 63 {from: prefixLen, to: length}, 64 ]; 65} 66 67export function performReordering<T>(intervals: Interval[], arr: T[]): T[] { 68 const result: T[] = []; 69 70 for (const interval of intervals) { 71 result.push(...arr.slice(interval.from, interval.to)); 72 } 73 74 return result; 75} 76