1 | import {Component} from "../../widgets/component";
|
2 | import {Autowired, Context, PostConstruct} from "../../context/context";
|
3 | import {Column} from "../../entities/column";
|
4 | import {Utils as _} from "../../utils";
|
5 | import {
|
6 | DragAndDropService, DragItem, DragSource, DragSourceType,
|
7 | DropTarget
|
8 | } from "../../dragAndDrop/dragAndDropService";
|
9 | import {IHeaderComp, IHeaderParams} from "./headerComp";
|
10 | import {ColumnApi} from "../../columnController/columnApi";
|
11 | import {ColumnController} from "../../columnController/columnController";
|
12 | import {HorizontalResizeService} from "../horizontalResizeService";
|
13 | import {GridOptionsWrapper} from "../../gridOptionsWrapper";
|
14 | import {CssClassApplier} from "../cssClassApplier";
|
15 | import {SetLeftFeature} from "../../rendering/features/setLeftFeature";
|
16 | import {IMenuFactory} from "../../interfaces/iMenuFactory";
|
17 | import {GridApi} from "../../gridApi";
|
18 | import {SortController} from "../../sortController";
|
19 | import {EventService} from "../../eventService";
|
20 | import {ComponentRecipes} from "../../components/framework/componentRecipes";
|
21 | import {AgCheckbox} from "../../widgets/agCheckbox";
|
22 | import {RefSelector} from "../../widgets/componentAnnotations";
|
23 | import {SelectAllFeature} from "./selectAllFeature";
|
24 | import {Events} from "../../events";
|
25 | import {ColumnHoverService} from "../../rendering/columnHoverService";
|
26 | import {Beans} from "../../rendering/beans";
|
27 | import {HoverFeature} from "../hoverFeature";
|
28 | import {TouchListener} from "../../widgets/touchListener";
|
29 |
|
30 | export class HeaderWrapperComp extends Component {
|
31 |
|
32 | private static TEMPLATE =
|
33 | '<div class="ag-header-cell" role="presentation" >' +
|
34 | '<div ref="eResize" class="ag-header-cell-resize" role="presentation"></div>' +
|
35 | '<ag-checkbox ref="cbSelectAll" class="ag-header-select-all" role="presentation"></ag-checkbox>' +
|
36 |
|
37 | '</div>';
|
38 |
|
39 | @Autowired('gridOptionsWrapper') private gridOptionsWrapper: GridOptionsWrapper;
|
40 | @Autowired('dragAndDropService') private dragAndDropService: DragAndDropService;
|
41 | @Autowired('columnController') private columnController: ColumnController;
|
42 | @Autowired('horizontalResizeService') private horizontalResizeService: HorizontalResizeService;
|
43 | @Autowired('context') private context: Context;
|
44 | @Autowired('menuFactory') private menuFactory: IMenuFactory;
|
45 | @Autowired('gridApi') private gridApi: GridApi;
|
46 | @Autowired('columnApi') private columnApi: ColumnApi;
|
47 | @Autowired('sortController') private sortController: SortController;
|
48 | @Autowired('eventService') private eventService: EventService;
|
49 | @Autowired('componentRecipes') private componentRecipes: ComponentRecipes;
|
50 | @Autowired('columnHoverService') private columnHoverService: ColumnHoverService;
|
51 | @Autowired('beans') private beans: Beans;
|
52 |
|
53 | @RefSelector('eResize') private eResize: HTMLElement;
|
54 | @RefSelector('cbSelectAll') private cbSelectAll: AgCheckbox;
|
55 |
|
56 | private column: Column;
|
57 | private dragSourceDropTarget: DropTarget;
|
58 | private pinned: string;
|
59 |
|
60 | private resizeStartWidth: number;
|
61 | private resizeWithShiftKey: boolean;
|
62 |
|
63 | constructor(column: Column, dragSourceDropTarget: DropTarget, pinned: string) {
|
64 | super(HeaderWrapperComp.TEMPLATE);
|
65 | this.column = column;
|
66 | this.dragSourceDropTarget = dragSourceDropTarget;
|
67 | this.pinned = pinned;
|
68 | }
|
69 |
|
70 | public getColumn(): Column {
|
71 | return this.column;
|
72 | }
|
73 |
|
74 | @PostConstruct
|
75 | public init(): void {
|
76 | this.instantiate(this.context);
|
77 |
|
78 | let displayName = this.columnController.getDisplayNameForColumn(this.column, 'header', true);
|
79 | let enableSorting = this.gridOptionsWrapper.isEnableSorting() && !this.column.getColDef().suppressSorting;
|
80 | let enableMenu = this.menuFactory.isMenuEnabled(this.column) && !this.column.getColDef().suppressMenu;
|
81 |
|
82 | this.appendHeaderComp(displayName, enableSorting, enableMenu);
|
83 |
|
84 | this.setupWidth();
|
85 | this.setupMovingCss();
|
86 | this.setupTooltip();
|
87 | this.setupResize();
|
88 | this.setupMenuClass();
|
89 | this.setupSortableClass(enableSorting);
|
90 | this.addColumnHoverListener();
|
91 |
|
92 | this.addFeature(this.context, new HoverFeature([this.column], this.getGui()));
|
93 |
|
94 | this.addDestroyableEventListener(this.column, Column.EVENT_FILTER_ACTIVE_CHANGED, this.onFilterChanged.bind(this));
|
95 | this.onFilterChanged();
|
96 |
|
97 | this.addFeature(this.context, new SelectAllFeature(this.cbSelectAll, this.column));
|
98 |
|
99 | let setLeftFeature = new SetLeftFeature(this.column, this.getGui(), this.beans);
|
100 | setLeftFeature.init();
|
101 | this.addDestroyFunc(setLeftFeature.destroy.bind(setLeftFeature));
|
102 |
|
103 | this.addAttributes();
|
104 | CssClassApplier.addHeaderClassesFromColDef(this.column.getColDef(), this.getGui(), this.gridOptionsWrapper, this.column, null);
|
105 | }
|
106 |
|
107 | private addColumnHoverListener(): void {
|
108 | this.addDestroyableEventListener(this.eventService, Events.EVENT_COLUMN_HOVER_CHANGED, this.onColumnHover.bind(this));
|
109 | this.onColumnHover();
|
110 | }
|
111 |
|
112 | private onColumnHover(): void {
|
113 | let isHovered = this.columnHoverService.isHovered(this.column);
|
114 | _.addOrRemoveCssClass(this.getGui(), 'ag-column-hover', isHovered)
|
115 | }
|
116 |
|
117 | private setupSortableClass(enableSorting:boolean):void{
|
118 | if (enableSorting) {
|
119 | let element = this.getGui();
|
120 | _.addCssClass(element, 'ag-header-cell-sortable');
|
121 | }
|
122 | }
|
123 |
|
124 | private onFilterChanged(): void {
|
125 | let filterPresent = this.column.isFilterActive();
|
126 | _.addOrRemoveCssClass(this.getGui(), 'ag-header-cell-filtered', filterPresent);
|
127 | }
|
128 |
|
129 | private appendHeaderComp(displayName: string, enableSorting: boolean, enableMenu: boolean): void {
|
130 | let params = <IHeaderParams> {
|
131 | column: this.column,
|
132 | displayName: displayName,
|
133 | enableSorting: enableSorting,
|
134 | enableMenu: enableMenu,
|
135 | showColumnMenu: (source:HTMLElement) => {
|
136 | this.gridApi.showColumnMenuAfterButtonClick(this.column, source)
|
137 | },
|
138 | progressSort: (multiSort?:boolean) => {
|
139 | this.sortController.progressSort(this.column, !!multiSort, "uiColumnSorted");
|
140 | },
|
141 | setSort: (sort: string, multiSort?: boolean) => {
|
142 | this.sortController.setSortForColumn(this.column, sort, !!multiSort, "uiColumnSorted");
|
143 | },
|
144 | api: this.gridApi,
|
145 | columnApi: this.columnApi,
|
146 | context: this.gridOptionsWrapper.getContext()
|
147 | };
|
148 |
|
149 | let callback = this.afterHeaderCompCreated.bind(this, displayName);
|
150 |
|
151 | this.componentRecipes.newHeaderComponent(params).then(callback);
|
152 | }
|
153 |
|
154 | private afterHeaderCompCreated(displayName: string, headerComp: IHeaderComp): void {
|
155 | this.appendChild(headerComp);
|
156 | this.setupMove(headerComp.getGui(), displayName);
|
157 |
|
158 | if (headerComp.destroy) {
|
159 | this.addDestroyFunc(headerComp.destroy.bind(headerComp));
|
160 | }
|
161 | }
|
162 |
|
163 | private onColumnMovingChanged(): void {
|
164 |
|
165 |
|
166 |
|
167 | if (this.column.isMoving()) {
|
168 | _.addCssClass(this.getGui(), 'ag-header-cell-moving');
|
169 | } else {
|
170 | _.removeCssClass(this.getGui(), 'ag-header-cell-moving');
|
171 | }
|
172 | }
|
173 |
|
174 | private setupMove(eHeaderCellLabel: HTMLElement, displayName: string): void {
|
175 | let suppressMove = this.gridOptionsWrapper.isSuppressMovableColumns()
|
176 | || this.column.getColDef().suppressMovable
|
177 | || this.column.isLockPosition();
|
178 |
|
179 | if (suppressMove) { return; }
|
180 |
|
181 | if (eHeaderCellLabel) {
|
182 | let dragSource: DragSource = {
|
183 | type: DragSourceType.HeaderCell,
|
184 | eElement: eHeaderCellLabel,
|
185 | dragItemCallback: () => this.createDragItem(),
|
186 | dragItemName: displayName,
|
187 | dragSourceDropTarget: this.dragSourceDropTarget,
|
188 | dragStarted: () => this.column.setMoving(true, "uiColumnMoved"),
|
189 | dragStopped: () => this.column.setMoving(false, "uiColumnMoved")
|
190 | };
|
191 | this.dragAndDropService.addDragSource(dragSource, true);
|
192 | this.addDestroyFunc( ()=> this.dragAndDropService.removeDragSource(dragSource) );
|
193 | }
|
194 | }
|
195 |
|
196 | private createDragItem(): DragItem {
|
197 | let visibleState: { [key: string]: boolean } = {};
|
198 | visibleState[this.column.getId()] = this.column.isVisible();
|
199 |
|
200 | return {
|
201 | columns: [this.column],
|
202 | visibleState: visibleState
|
203 | };
|
204 | }
|
205 |
|
206 | private setupResize(): void {
|
207 | let colDef = this.column.getColDef();
|
208 |
|
209 |
|
210 | if (!this.eResize) {
|
211 | return;
|
212 | }
|
213 |
|
214 | if (!this.column.isResizable()) {
|
215 | _.removeFromParent(this.eResize);
|
216 | return;
|
217 | }
|
218 |
|
219 | let finishedWithResizeFunc = this.horizontalResizeService.addResizeBar({
|
220 | eResizeBar: this.eResize,
|
221 | onResizeStart: this.onResizeStart.bind(this),
|
222 | onResizing: this.onResizing.bind(this, false),
|
223 | onResizeEnd: this.onResizing.bind(this, true)
|
224 | });
|
225 |
|
226 | this.addDestroyFunc(finishedWithResizeFunc);
|
227 |
|
228 | let weWantAutoSize = !this.gridOptionsWrapper.isSuppressAutoSize() && !colDef.suppressAutoSize;
|
229 | if (weWantAutoSize) {
|
230 | this.addDestroyableEventListener(this.eResize, 'dblclick', () => {
|
231 | this.columnController.autoSizeColumn(this.column, "uiColumnResized");
|
232 | });
|
233 | let touchListener: TouchListener = new TouchListener(this.eResize);
|
234 | this.addDestroyableEventListener(touchListener, TouchListener.EVENT_DOUBLE_TAP, ()=> {
|
235 | this.columnController.autoSizeColumn(this.column, "uiColumnResized");
|
236 | });
|
237 | this.addDestroyFunc(touchListener.destroy.bind(touchListener));
|
238 | }
|
239 | }
|
240 |
|
241 | public onResizing(finished: boolean, resizeAmount: number): void {
|
242 | let resizeAmountNormalised = this.normaliseResizeAmount(resizeAmount);
|
243 | let newWidth = this.resizeStartWidth + resizeAmountNormalised;
|
244 | this.columnController.setColumnWidth(this.column, newWidth, this.resizeWithShiftKey, finished, "uiColumnDragged");
|
245 | }
|
246 |
|
247 | public onResizeStart(shiftKey: boolean): void {
|
248 | this.resizeStartWidth = this.column.getActualWidth();
|
249 | this.resizeWithShiftKey = shiftKey;
|
250 | }
|
251 |
|
252 | private setupTooltip(): void {
|
253 | let colDef = this.column.getColDef();
|
254 |
|
255 |
|
256 | if (colDef.headerTooltip) {
|
257 | this.getGui().title = colDef.headerTooltip;
|
258 | }
|
259 | }
|
260 |
|
261 | private setupMovingCss(): void {
|
262 | this.addDestroyableEventListener(this.column, Column.EVENT_MOVING_CHANGED, this.onColumnMovingChanged.bind(this));
|
263 | this.onColumnMovingChanged();
|
264 | }
|
265 |
|
266 | private addAttributes(): void {
|
267 | this.getGui().setAttribute("col-id", this.column.getColId());
|
268 | }
|
269 |
|
270 | private setupWidth(): void {
|
271 | this.addDestroyableEventListener(this.column, Column.EVENT_WIDTH_CHANGED, this.onColumnWidthChanged.bind(this));
|
272 | this.onColumnWidthChanged();
|
273 | }
|
274 |
|
275 | private setupMenuClass(): void {
|
276 | this.addDestroyableEventListener(this.column, Column.EVENT_MENU_VISIBLE_CHANGED, this.onMenuVisible.bind(this));
|
277 | this.onColumnWidthChanged();
|
278 | }
|
279 |
|
280 | private onMenuVisible(): void {
|
281 | this.addOrRemoveCssClass('ag-column-menu-visible', this.column.isMenuVisible());
|
282 | }
|
283 |
|
284 | private onColumnWidthChanged(): void {
|
285 | this.getGui().style.width = this.column.getActualWidth() + 'px';
|
286 | }
|
287 |
|
288 |
|
289 |
|
290 | private normaliseResizeAmount(dragChange: number): number {
|
291 | let result = dragChange;
|
292 | if (this.gridOptionsWrapper.isEnableRtl()) {
|
293 |
|
294 | if (this.pinned !== Column.PINNED_LEFT) {
|
295 | result *= -1;
|
296 | }
|
297 | } else {
|
298 |
|
299 | if (this.pinned === Column.PINNED_RIGHT) {
|
300 | result *= -1;
|
301 | }
|
302 | }
|
303 | return result;
|
304 | }
|
305 |
|
306 | }
|