egui_dnd/utils.rs
1/// Move an item in a slice according to the drag and drop logic.
2///
3/// Rotates the section of the slice between `source_idx` and `target_idx` such that the item
4/// previously at `source_idx` ends up at `target_idx - 1` if `target_idx > source_idx`, and
5/// at `target_idx` otherwise. This matches the expected behavior when grabbing the item in
6/// the UI and moving it to another position.
7///
8/// # Example
9///
10/// ```rust
11/// use egui_dnd::utils::shift_vec;
12///
13/// let mut v = vec![1, 2, 3, 4];
14/// shift_vec(1, 1, &mut v);
15/// assert_eq!(v, [1, 2, 3, 4]);
16/// shift_vec(0, 2, &mut v);
17/// assert_eq!(v, [2, 1, 3, 4]);
18/// shift_vec(2, 0, &mut v);
19/// assert_eq!(v, [3, 2, 1, 4]);
20/// ```
21///
22/// # Panics
23/// Panics if `source_idx >= len()` or `target_idx > len()`
24/// ```rust,should_panic
25/// use egui_dnd::utils::shift_vec;
26///
27/// let mut v = vec![1];
28/// shift_vec(0, 2, &mut v);
29/// ```
30pub fn shift_vec<T>(source_idx: usize, target_idx: usize, vec: &mut [T]) {
31 if let Some(slice) = vec.get_mut(source_idx..target_idx) {
32 slice.rotate_left(1.min(slice.len()));
33 } else if let Some(slice) = vec.get_mut(target_idx..=source_idx) {
34 slice.rotate_right(1.min(slice.len()));
35 } else {
36 panic!(
37 "Failed to move item from index {} to index {}. Slice has {} elements",
38 source_idx,
39 target_idx,
40 vec.len()
41 );
42 }
43}