UNPKG

8.71 kBPlain TextView Raw
1import {ColumnUtils} from "./columnUtils";
2import {Column} from "../entities/column";
3import {OriginalColumnGroupChild} from "../entities/originalColumnGroupChild";
4import {GroupInstanceIdCreator} from "./groupInstanceIdCreator";
5import {ColumnGroupChild} from "../entities/columnGroupChild";
6import {ColumnGroup} from "../entities/columnGroup";
7import {OriginalColumnGroup} from "../entities/originalColumnGroup";
8import {Bean, Context} from "../context/context";
9import {Utils as _} from "../utils";
10import {Autowired} from "../context/context";
11
12// takes in a list of columns, as specified by the column definitions, and returns column groups
13@Bean('displayedGroupCreator')
14export class DisplayedGroupCreator {
15
16 @Autowired('columnUtils') private columnUtils: ColumnUtils;
17 @Autowired('context') private context: Context;
18
19 public createDisplayedGroups(
20 // all displayed columns sorted - this is the columns the grid should show
21 sortedVisibleColumns: Column[],
22 // the tree of columns, as provided by the users, used to know what groups columns roll up into
23 balancedColumnTree: OriginalColumnGroupChild[],
24 // create's unique id's for the group
25 groupInstanceIdCreator: GroupInstanceIdCreator,
26 // we try to reuse old groups if we can, to allow gui to do animation
27 oldDisplayedGroups?: ColumnGroupChild[]): ColumnGroupChild[] {
28
29 let result: ColumnGroupChild[] = [];
30
31 let previousRealPath: ColumnGroup[];
32 let previousOriginalPath: OriginalColumnGroup[];
33
34 let oldColumnsMapped = this.mapOldGroupsById(oldDisplayedGroups);
35
36 // go through each column, then do a bottom up comparison to the previous column, and start
37 // to share groups if they converge at any point.
38 sortedVisibleColumns.forEach( (currentColumn: Column)=> {
39
40 let currentOriginalPath = this.getOriginalPathForColumn(balancedColumnTree, currentColumn);
41 let currentRealPath: ColumnGroup[] = [];
42 let firstColumn = !previousOriginalPath;
43
44 for (let i = 0; i<currentOriginalPath.length; i++) {
45 if (firstColumn || currentOriginalPath[i]!==previousOriginalPath[i]) {
46 // new group needed
47 let newGroup = this.createColumnGroup(currentOriginalPath[i], groupInstanceIdCreator, oldColumnsMapped);
48 currentRealPath[i] = newGroup;
49 // if top level, add to result, otherwise add to parent
50 if (i==0) {
51 result.push(newGroup);
52 } else {
53 currentRealPath[i-1].addChild(newGroup);
54 }
55 } else {
56 // reuse old group
57 currentRealPath[i] = previousRealPath[i];
58 }
59 }
60
61 let noColumnGroups = currentRealPath.length===0;
62 if (noColumnGroups) {
63 // if we are not grouping, then the result of the above is an empty
64 // path (no groups), and we just add the column to the root list.
65 result.push(currentColumn);
66 } else {
67 let leafGroup = currentRealPath[currentRealPath.length-1];
68 leafGroup.addChild(currentColumn);
69 }
70
71 previousRealPath = currentRealPath;
72 previousOriginalPath = currentOriginalPath;
73 });
74
75 this.setupParentsIntoColumns(result, null);
76
77 return result;
78 }
79
80 private createColumnGroup(originalGroup: OriginalColumnGroup,
81 groupInstanceIdCreator: GroupInstanceIdCreator,
82 oldColumnsMapped: {[key: string]: ColumnGroup}): ColumnGroup {
83
84 let groupId = originalGroup.getGroupId();
85 let instanceId = groupInstanceIdCreator.getInstanceIdForKey(groupId);
86 let uniqueId = ColumnGroup.createUniqueId(groupId, instanceId);
87
88 let columnGroup = oldColumnsMapped[uniqueId];
89
90 // if the user is setting new colDefs, it is possible that the id's overlap, and we
91 // would have a false match from above. so we double check we are talking about the
92 // same original column group.
93 if (columnGroup && columnGroup.getOriginalColumnGroup()!==originalGroup) {
94 columnGroup = null;
95 }
96
97 if (_.exists(columnGroup)) {
98 // clean out the old column group here, as we will be adding children into it again
99 columnGroup.reset();
100 } else {
101 columnGroup = new ColumnGroup(originalGroup, groupId, instanceId);
102 this.context.wireBean(columnGroup);
103 }
104
105 return columnGroup;
106 }
107
108 // returns back a 2d map of ColumnGroup as follows: groupId -> instanceId -> ColumnGroup
109 private mapOldGroupsById(displayedGroups: ColumnGroupChild[]): {[uniqueId: string]: ColumnGroup} {
110 let result: {[uniqueId: string]: ColumnGroup} = {};
111
112 let recursive = (columnsOrGroups: ColumnGroupChild[])=> {
113 columnsOrGroups.forEach( columnOrGroup => {
114 if (columnOrGroup instanceof ColumnGroup) {
115 let columnGroup = <ColumnGroup> columnOrGroup;
116 result[columnOrGroup.getUniqueId()] = columnGroup;
117 recursive(columnGroup.getChildren());
118 }
119 });
120 };
121
122 if (displayedGroups) {
123 recursive(displayedGroups);
124 }
125
126 return result;
127 }
128
129 private setupParentsIntoColumns(columnsOrGroups: ColumnGroupChild[], parent: ColumnGroup): void {
130 columnsOrGroups.forEach( columnsOrGroup => {
131 columnsOrGroup.setParent(parent);
132 if (columnsOrGroup instanceof ColumnGroup) {
133 let columnGroup = <ColumnGroup> columnsOrGroup;
134 this.setupParentsIntoColumns(columnGroup.getChildren(), columnGroup);
135 }
136 });
137 }
138
139 // private createFakePath(balancedColumnTree: OriginalColumnGroupChild[], column: Column): OriginalColumnGroup[] {
140 // let fakePath: OriginalColumnGroup[] = [];
141 // let currentChildren = balancedColumnTree;
142 // // this while loop does search on the balanced tree, so our result is the right length
143 // let index = 0;
144 // while (currentChildren && currentChildren[0] && currentChildren[0] instanceof OriginalColumnGroup) {
145 // // putting in a deterministic fake id, in case the API in the future needs to reference the col
146 // let fakeGroup = new OriginalColumnGroup(null, 'FAKE_PATH_' + index, true);
147 // this.context.wireBean(fakeGroup);
148 //
149 // // fakePath.setChildren(children);
150 //
151 // fakePath.push(fakeGroup);
152 // currentChildren = (<OriginalColumnGroup>currentChildren[0]).getChildren();
153 // index++;
154 // }
155 //
156 // fakePath.forEach( (fakePathGroup: OriginalColumnGroup, i: number) => {
157 // let lastItemInList = i === fakePath.length-1;
158 // let child = lastItemInList ? column : fakePath[i+1];
159 // fakePathGroup.setChildren([child]);
160 // });
161 //
162 // return fakePath;
163 // }
164
165 private getOriginalPathForColumn(balancedColumnTree: OriginalColumnGroupChild[], column: Column): OriginalColumnGroup[] {
166
167 let result: OriginalColumnGroup[] = [];
168 let found = false;
169
170 recursePath(balancedColumnTree, 0);
171
172 // it's possible we didn't find a path. this happens if the column is generated
173 // by the grid (auto-group), in that the definition didn't come from the client. in this case,
174 // we create a fake original path.
175 if (found) {
176 return result;
177 } else {
178 console.log('could not get path');
179 return null;
180 // return this.createFakePath(balancedColumnTree, column);
181 }
182
183 function recursePath(balancedColumnTree: OriginalColumnGroupChild[], dept: number): void {
184
185 for (let i = 0; i<balancedColumnTree.length; i++) {
186 if (found) {
187 // quit the search, so 'result' is kept with the found result
188 return;
189 }
190 let node = balancedColumnTree[i];
191 if (node instanceof OriginalColumnGroup) {
192 let nextNode = <OriginalColumnGroup> node;
193 recursePath(nextNode.getChildren(), dept+1);
194 result[dept] = node;
195 } else {
196 if (node === column) {
197 found = true;
198 }
199 }
200 }
201 }
202 }
203}
\No newline at end of file