UNPKG

4.58 kBPlain TextView Raw
1import {BeanStub} from "../context/beanStub";
2import {Autowired, Bean, PostConstruct} from "../context/context";
3import {EventService} from "../eventService";
4import {Events} from "../eventKeys";
5import {GridPanel} from "../gridPanel/gridPanel";
6import {_} from "../utils";
7
8/**
9 * This class solves the 'max height' problem, where the user might want to show more data than
10 * the max div height actually allows.
11 */
12
13@Bean('heightScaler')
14export class HeightScaler extends BeanStub {
15
16 @Autowired('eventService') private eventService: EventService;
17
18 private gridPanel: GridPanel;
19
20 private maxDivHeight: number;
21
22 // if false, then scaling is not active, logic in this class is not used,
23 // the pixel height of the row container matches what is actually needed,
24 // no scaling applied.
25 private scaling: boolean;
26
27 private modelHeight: number; // how many pixels the model needs
28 private uiContainerHeight: number; // how many pixels we actually have
29 private pixelsToShave: number; // the number of pixels we need to shave
30
31 // the number of pixels we add to each rowTop - depends on the scroll position
32 private offset: number;
33
34 // the scrollY position
35 private scrollY = 0;
36 // how tall the body is
37 private uiBodyHeight = 0;
38
39 // the max scroll position
40 private maxScrollY: number;
41
42 // we need this for the maths, as it impacts the grid height
43 private scrollBarWidth: number;
44
45 @PostConstruct
46 private postConstruct(): void {
47 this.addDestroyableEventListener(this.eventService, Events.EVENT_BODY_HEIGHT_CHANGED, this.update.bind(this));
48 this.scrollBarWidth = _.getScrollbarWidth();
49 this.maxDivHeight = _.getMaxDivHeight();
50 }
51
52 public registerGridComp(gridPanel: GridPanel): void {
53 this.gridPanel = gridPanel;
54 }
55
56 public isScaling(): boolean {
57 return this.scaling;
58 }
59
60 public getOffset(): number {
61 return this.offset;
62 }
63
64 public update(): void {
65 if (!this.scaling) { return; }
66
67 let newScrollY = this.gridPanel.getVScrollPosition().top;
68 let newBodyHeight = this.getUiBodyHeight();
69
70 let atLeastOneChanged = newScrollY!==this.scrollY || newBodyHeight!==this.uiBodyHeight;
71 if (atLeastOneChanged) {
72 this.scrollY = newScrollY;
73 this.uiBodyHeight = newBodyHeight;
74 this.calculateOffset();
75 }
76 }
77
78 private calculateOffset(): void {
79 this.uiContainerHeight = this.maxDivHeight;
80 this.pixelsToShave = this.modelHeight - this.uiContainerHeight;
81
82 this.maxScrollY = this.uiContainerHeight - this.uiBodyHeight;
83 let scrollPercent = this.scrollY / this.maxScrollY;
84
85 this.setOffset(scrollPercent * this.pixelsToShave);
86 }
87
88 private clearOffset(): void {
89 this.uiContainerHeight = this.modelHeight;
90 this.pixelsToShave = 0;
91
92 this.setOffset(0);
93 }
94
95 private setOffset(newOffset: number): void {
96 // because we are talking pixels, no point in confusing things with half numbers
97 let newOffsetFloor = typeof newOffset === 'number' ? Math.floor(newOffset) : null;
98 if (this.offset!==newOffsetFloor) {
99 this.offset = newOffsetFloor;
100 this.eventService.dispatchEvent({type: Events.EVENT_HEIGHT_SCALE_CHANGED});
101 }
102 }
103
104 public setModelHeight(modelHeight: number): void {
105 this.modelHeight = modelHeight;
106 this.scaling = this.maxDivHeight > 0 && modelHeight > this.maxDivHeight;
107 if (this.scaling) {
108 this.calculateOffset();
109 } else {
110 this.clearOffset();
111 }
112 }
113
114 public getUiContainerHeight(): number {
115 return this.uiContainerHeight;
116 }
117
118 public getRealPixelPosition(modelPixel: number): number {
119 let uiPixel = modelPixel - this.offset;
120 return uiPixel;
121 }
122
123 private getUiBodyHeight(): number {
124 let pos = this.gridPanel.getVScrollPosition();
125 let bodyHeight = pos.bottom - pos.top;
126 if (this.gridPanel.isHorizontalScrollShowing()) {
127 bodyHeight -= this.scrollBarWidth;
128 }
129 return bodyHeight;
130 }
131
132 public getScrollPositionForPixel(rowTop: number): number {
133 if (this.pixelsToShave<=0) {
134 return rowTop;
135 } else {
136 let modelMaxScroll = this.modelHeight - this.getUiBodyHeight();
137 let scrollPercent = rowTop / modelMaxScroll;
138 let scrollPixel = this.maxScrollY * scrollPercent;
139 return scrollPixel;
140 }
141 }
142}
\No newline at end of file