-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathReorderItems.ts
138 lines (109 loc) · 4.48 KB
/
ReorderItems.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/** @module adaptation */
import { Reorder } from "./Reorder";
import { MenuManager } from "../../elements/MenuManager";
import { DataManager } from "../../data/DataManager";
import { Item } from "../../elements/Item";
import { TargetPolicy } from "../policies/TargetPolicy";
export class ReorderItems extends Reorder {
// ============================================================ PROPERTIES ===
/** HTML class of item elements which have been reordered. */
static readonly REORDERED_ELEMENT_CLASS: string = "sam-reordered-item";
readonly name: string = "Reorder items";
// =========================================================== CONSTRUCTOR ===
/**
* Create a new instance of ReorderItem.
*/
constructor () {
super();
}
// =============================================================== METHODS ===
// ===========================================================================
// Utility
// ===========================================================================
protected getReorderedElementClass (): string {
return "sam-reordered-item";
}
protected getReorderedElementType (): string {
return Item.ELEMENT_TYPE;
}
// ===========================================================================
// Apply style
// ===========================================================================
/**
* Use the given policy to score and sort the items of all the menus to adapt,
* and filter out any item which:
* - cannot be reordered;
* - has a null (0) score.
*
* @param menuManager The menu manager containing the menus with items to reorder.
* @param policy The policy to use to score the items.
* @param dataManager The data manager containing data for the policy.
* @return A sorted and filtered list of items.
*/
private getFilteredSortedItems (menuManager: MenuManager, policy: TargetPolicy, dataManager?: DataManager): Item[] {
return policy
.getSortedItemsWithScores(menuManager, dataManager)
.filter((itemWithScore) => {
if (! itemWithScore.item.canBeReordered) {
return false;
}
return itemWithScore.score > 0;
})
.map((itemWithScore) => {
return itemWithScore.item;
});
}
/**
* Return the maximum number of items which can be reordered in a menu.
*
* @param nbItems The total number of items in the menu.
* @return The maximum number of items to reorder in the menu.
*/
private getMaxNbItemsToReorder (nbItems: number): number {
return Math.floor(Math.sqrt(nbItems));
}
/**
* Return the maximum number of items which can be reordered in a group.
*
* @param nbItemsInGroup The total number of items in the group.
* @return The maximum number of items to reorder in the group.
*/
private getMaxNbItemsToReorderInGroup (nbItemsInGroup: number): number {
return Math.floor(Math.sqrt(nbItemsInGroup));
}
/**
* Reorder all the given elements, in the given order,
* assuming they all belong to the same group.
*
* @param sameGroupItems A sorted list of items located in the same group.
*/
private applyInGroup (sameGroupItems: Item[]) {
// Splice the same group items to only reorder the top ones
let totalNbGroupItems = sameGroupItems[0].parent.items.length;
let nbTopSameGroupItemsToKeep = this.getMaxNbItemsToReorderInGroup(totalNbGroupItems);
let topSameGroupItems = sameGroupItems.splice(0, nbTopSameGroupItemsToKeep);
this.reorderAllElements(topSameGroupItems);
}
/**
* Split all the given items by their group, and reorder them group by group
* (using [[applyInGroup]]).
*
* @param items A sorted list of items to reorder.
*/
private splitAndApplyByGroup (items: Item[]) {
let topItemsSplitByGroup = Item.splitAllByGroup(items);
for (let sameGroupItems of topItemsSplitByGroup) {
this.applyInGroup(sameGroupItems);
}
}
apply (menuManager: MenuManager, policy: TargetPolicy, dataManager?: DataManager) {
let items = this.getFilteredSortedItems(menuManager, policy, dataManager);
// Save some children in their original order to be able to cancel the reordering
this.saveParentNodeChildrenInOriginalOrder(items);
// Splice the items to only reorder the top ones
let totalNbItems = menuManager.getNbItems();
let nbTopItemsToKeep = this.getMaxNbItemsToReorder(totalNbItems);
let topItems = items.slice(0, nbTopItemsToKeep);
this.splitAndApplyByGroup(topItems);
}
}