UNPKG

12.3 kBPlain TextView Raw
1import {GridOptionsWrapper} from '../gridOptionsWrapper';
2import {Logger, LoggerFactory} from '../logger';
3import {ColumnUtils} from '../columnController/columnUtils';
4import {AbstractColDef, ColDef, ColGroupDef} from "../entities/colDef";
5import {ColumnKeyCreator} from "./columnKeyCreator";
6import {OriginalColumnGroupChild} from "../entities/originalColumnGroupChild";
7import {OriginalColumnGroup} from "../entities/originalColumnGroup";
8import {Column} from "../entities/column";
9import {Autowired, Bean, Context, Qualifier} from "../context/context";
10import {Utils as _} from "../utils";
11import { DefaultColumnTypes } from "../entities/defaultColumnTypes";
12
13// takes in a list of columns, as specified by the column definitions, and returns column groups
14@Bean('balancedColumnTreeBuilder')
15export class BalancedColumnTreeBuilder {
16
17 @Autowired('gridOptionsWrapper') private gridOptionsWrapper: GridOptionsWrapper;
18 @Autowired('columnUtils') private columnUtils: ColumnUtils;
19 @Autowired('context') private context: Context;
20
21 private logger: Logger;
22
23 private setBeans(@Qualifier('loggerFactory') loggerFactory: LoggerFactory) {
24 this.logger = loggerFactory.create('BalancedColumnTreeBuilder');
25 }
26
27 public createForAutoGroups(autoGroupCols: Column[], gridBalancedTree: OriginalColumnGroupChild[]): OriginalColumnGroupChild[] {
28
29 let autoColBalancedTree: OriginalColumnGroupChild[] = [];
30 autoGroupCols.forEach( col => {
31 let fakeTreeItem = this.createAutoGroupTreeItem(gridBalancedTree, col);
32 autoColBalancedTree.push(fakeTreeItem);
33 });
34
35 return autoColBalancedTree;
36 }
37
38 private createAutoGroupTreeItem(balancedColumnTree: OriginalColumnGroupChild[], column: Column): OriginalColumnGroupChild {
39
40 let dept = this.findDept(balancedColumnTree);
41
42 // at the end, this will be the top of the tree item.
43 let nextChild: OriginalColumnGroupChild = column;
44
45 for (let i = dept - 1; i>=0; i--) {
46 let autoGroup = new OriginalColumnGroup(
47 null,
48 `FAKE_PATH_${column.getId()}}_${i}`,
49 true,
50 i);
51 this.context.wireBean(autoGroup);
52 autoGroup.setChildren([nextChild]);
53 nextChild = autoGroup;
54 }
55
56 // at this point, the nextChild is the top most item in the tree
57 return nextChild;
58 }
59
60 private findDept(balancedColumnTree: OriginalColumnGroupChild[]): number {
61 let dept = 0;
62 let pointer = balancedColumnTree;
63 while (pointer && pointer[0] && pointer[0] instanceof OriginalColumnGroup) {
64 dept++;
65 pointer = (<OriginalColumnGroup>pointer[0]).getChildren();
66 }
67 return dept;
68 }
69
70 public createBalancedColumnGroups(abstractColDefs: (ColDef|ColGroupDef)[], primaryColumns: boolean): any {
71 // column key creator dishes out unique column id's in a deterministic way,
72 // so if we have two grids (that cold be master/slave) with same column definitions,
73 // then this ensures the two grids use identical id's.
74 let columnKeyCreator = new ColumnKeyCreator();
75
76 // create am unbalanced tree that maps the provided definitions
77 let unbalancedTree = this.recursivelyCreateColumns(abstractColDefs, 0, columnKeyCreator, primaryColumns);
78 let treeDept = this.findMaxDept(unbalancedTree, 0);
79 this.logger.log('Number of levels for grouped columns is ' + treeDept);
80 let balancedTree = this.balanceColumnTree(unbalancedTree, 0, treeDept, columnKeyCreator);
81
82 this.columnUtils.depthFirstOriginalTreeSearch(balancedTree, (child: OriginalColumnGroupChild)=> {
83 if (child instanceof OriginalColumnGroup) {
84 (<OriginalColumnGroup>child).setupExpandable();
85 }
86 });
87
88 return {
89 balancedTree: balancedTree,
90 treeDept: treeDept
91 };
92 }
93
94 private balanceColumnTree(unbalancedTree: OriginalColumnGroupChild[], currentDept: number,
95 columnDept: number, columnKeyCreator: ColumnKeyCreator): OriginalColumnGroupChild[] {
96
97 let result: OriginalColumnGroupChild[] = [];
98
99 // go through each child, for groups, recurse a level deeper,
100 // for columns we need to pad
101 unbalancedTree.forEach( (child: OriginalColumnGroupChild)=> {
102 if (child instanceof OriginalColumnGroup) {
103 let originalGroup = <OriginalColumnGroup> child;
104 let newChildren = this.balanceColumnTree(
105 originalGroup.getChildren(), currentDept + 1, columnDept, columnKeyCreator);
106 originalGroup.setChildren(newChildren);
107 result.push(originalGroup);
108 } else {
109 let newChild = child;
110 for (let i = columnDept-1; i>=currentDept; i--) {
111 let newColId = columnKeyCreator.getUniqueKey(null, null);
112 let colGroupDefMerged = this.createMergedColGroupDef(null);
113 let paddedGroup = new OriginalColumnGroup(colGroupDefMerged, newColId, true, currentDept);
114 this.context.wireBean(paddedGroup);
115 paddedGroup.setChildren([newChild]);
116 newChild = paddedGroup;
117 }
118 result.push(newChild);
119 }
120 });
121
122 return result;
123 }
124
125 private findMaxDept(treeChildren: OriginalColumnGroupChild[], dept: number): number {
126 let maxDeptThisLevel = dept;
127 for (let i = 0; i<treeChildren.length; i++) {
128 let abstractColumn = treeChildren[i];
129 if (abstractColumn instanceof OriginalColumnGroup) {
130 let originalGroup = <OriginalColumnGroup> abstractColumn;
131 let newDept = this.findMaxDept(originalGroup.getChildren(), dept+1);
132 if (maxDeptThisLevel<newDept) {
133 maxDeptThisLevel = newDept;
134 }
135 }
136 }
137 return maxDeptThisLevel;
138 }
139
140 private recursivelyCreateColumns(abstractColDefs: (ColDef|ColGroupDef)[], level: number,
141 columnKeyCreator: ColumnKeyCreator, primaryColumns: boolean): OriginalColumnGroupChild[] {
142
143 let result: OriginalColumnGroupChild[] = [];
144
145 if (!abstractColDefs) {
146 return result;
147 }
148
149 abstractColDefs.forEach( (abstractColDef: ColDef|ColGroupDef)=> {
150 let newGroupOrColumn: OriginalColumnGroupChild;
151 if (this.isColumnGroup(abstractColDef)) {
152 newGroupOrColumn = this.createColumnGroup(columnKeyCreator, primaryColumns, <ColGroupDef> abstractColDef, level);
153 } else {
154 newGroupOrColumn = this.createColumn(columnKeyCreator, primaryColumns, <ColDef> abstractColDef);
155 }
156 result.push(newGroupOrColumn);
157 });
158
159 return result;
160 }
161
162 private createColumnGroup(columnKeyCreator: ColumnKeyCreator, primaryColumns: boolean, colGroupDef: ColGroupDef, level: number): OriginalColumnGroup {
163 let colGroupDefMerged = this.createMergedColGroupDef(colGroupDef);
164
165 let groupId = columnKeyCreator.getUniqueKey(colGroupDefMerged.groupId, null);
166 let originalGroup = new OriginalColumnGroup(colGroupDefMerged, groupId, false, level);
167 this.context.wireBean(originalGroup);
168 let children = this.recursivelyCreateColumns(colGroupDefMerged.children, level + 1, columnKeyCreator, primaryColumns);
169
170 originalGroup.setChildren(children);
171
172 return originalGroup;
173 }
174
175 private createMergedColGroupDef(colGroupDef: ColGroupDef): ColGroupDef {
176 let colGroupDefMerged: ColGroupDef = <ColGroupDef> {};
177 _.assign(colGroupDefMerged, this.gridOptionsWrapper.getDefaultColGroupDef());
178 _.assign(colGroupDefMerged, colGroupDef);
179 this.checkForDeprecatedItems(colGroupDefMerged);
180 return colGroupDefMerged;
181 }
182
183 private createColumn(columnKeyCreator: ColumnKeyCreator, primaryColumns: boolean, colDef: ColDef): Column {
184 let colDefMerged = this.mergeColDefs(colDef);
185 this.checkForDeprecatedItems(colDefMerged);
186 let colId = columnKeyCreator.getUniqueKey(colDefMerged.colId, colDefMerged.field);
187 let column = new Column(colDefMerged, colId, primaryColumns);
188 this.context.wireBean(column);
189 return column;
190 }
191
192 public mergeColDefs(colDef: ColDef) {
193 // start with empty merged definition
194 let colDefMerged: ColDef = <ColDef> {};
195
196 // merge properties from default column definitions
197 _.assign(colDefMerged, this.gridOptionsWrapper.getDefaultColDef());
198
199 // merge properties from column type properties
200 if (colDef.type) {
201 this.assignColumnTypes(colDef, colDefMerged);
202 }
203
204 // merge properties from column definitions
205 _.assign(colDefMerged, colDef);
206
207 return colDefMerged;
208 }
209
210 private assignColumnTypes(colDef: ColDef, colDefMerged: ColDef) {
211 let typeKeys: string[];
212
213 if (colDef.type instanceof Array) {
214 let invalidArray = colDef.type.some(a => typeof a !== 'string');
215 if (invalidArray) {
216 console.warn("ag-grid: if colDef.type is supplied an array it should be of type 'string[]'");
217 } else {
218 typeKeys = colDef.type;
219 }
220 } else if (typeof colDef.type === 'string') {
221 typeKeys = colDef.type.split(',');
222 } else {
223 console.warn("ag-grid: colDef.type should be of type 'string' | 'string[]'");
224 return;
225 }
226
227 // merge user defined with default column types
228 let allColumnTypes = _.assign({}, this.gridOptionsWrapper.getColumnTypes(), DefaultColumnTypes);
229
230 typeKeys.forEach((t) => {
231 let typeColDef = allColumnTypes[t.trim()];
232 if (typeColDef) {
233 _.assign(colDefMerged, typeColDef);
234 } else {
235 console.warn("ag-grid: colDef.type '" + t + "' does not correspond to defined gridOptions.columnTypes");
236 }
237 });
238 }
239
240 private checkForDeprecatedItems(colDef: AbstractColDef) {
241 if (colDef) {
242 let colDefNoType = <any> colDef; // take out the type, so we can access attributes not defined in the type
243 if (colDefNoType.group !== undefined) {
244 console.warn('ag-grid: colDef.group is invalid, please check documentation on how to do grouping as it changed in version 3');
245 }
246 if (colDefNoType.headerGroup !== undefined) {
247 console.warn('ag-grid: colDef.headerGroup is invalid, please check documentation on how to do grouping as it changed in version 3');
248 }
249 if (colDefNoType.headerGroupShow !== undefined) {
250 console.warn('ag-grid: colDef.headerGroupShow is invalid, should be columnGroupShow, please check documentation on how to do grouping as it changed in version 3');
251 }
252
253 if (colDefNoType.suppressRowGroup !== undefined) {
254 console.warn('ag-grid: colDef.suppressRowGroup is deprecated, please use colDef.type instead');
255 }
256 if (colDefNoType.suppressAggregation !== undefined) {
257 console.warn('ag-grid: colDef.suppressAggregation is deprecated, please use colDef.type instead');
258 }
259
260 if (colDefNoType.suppressRowGroup || colDefNoType.suppressAggregation) {
261 console.warn('ag-grid: colDef.suppressAggregation and colDef.suppressRowGroup are deprecated, use allowRowGroup, allowPivot and allowValue instead');
262 }
263
264 if (colDefNoType.displayName) {
265 console.warn("ag-grid: Found displayName " + colDefNoType.displayName + ", please use headerName instead, displayName is deprecated.");
266 colDefNoType.headerName = colDefNoType.displayName;
267 }
268 }
269 }
270
271 // if object has children, we assume it's a group
272 private isColumnGroup(abstractColDef: ColDef|ColGroupDef): boolean {
273 return (<ColGroupDef>abstractColDef).children !== undefined;
274 }
275
276}
\No newline at end of file