Skip to content

Commit 7dee4a5

Browse files
authored
Added usage of resize observer if available. (#516)
1 parent e518b86 commit 7dee4a5

File tree

8 files changed

+85
-45
lines changed

8 files changed

+85
-45
lines changed

package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"devDependencies": {
4444
"@rollup/plugin-commonjs": "^17.0.0",
4545
"@types/jasmine": "^3.6.2",
46+
"@types/resize-observer-browser": "^0.1.5",
4647
"concurrently": "^5.3.0",
4748
"cors": "^2.8.5",
4849
"fs-extra": "^9.0.1",

src.csharp/AlphaTab.Windows/WinForms/ControlContainer.cs

-12
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,6 @@ public ControlContainer(Control control)
1212
{
1313
Control = control;
1414

15-
Scroll = new DelegatedEventEmitter(
16-
value =>
17-
{
18-
if (Control is ScrollableControl scroll)
19-
{
20-
scroll.Scroll += (sender, args) => value();
21-
}
22-
},
23-
value => { }
24-
);
25-
2615
Resize = new DelegatedEventEmitter(
2716
value => { Control.Resize += (sender, args) => value(); },
2817
value => { }
@@ -127,7 +116,6 @@ public void Clear()
127116
Control.Controls.Clear();
128117
}
129118

130-
public IEventEmitter Scroll { get; set; }
131119
public IEventEmitter Resize { get; set; }
132120
public IEventEmitterOfT<IMouseEventArgs> MouseDown { get; set; }
133121
public IEventEmitterOfT<IMouseEventArgs> MouseMove { get; set; }

src.csharp/AlphaTab.Windows/Wpf/FrameworkElementContainer.cs

-12
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,6 @@ public FrameworkElementContainer(FrameworkElement control)
1414
{
1515
Control = control;
1616

17-
Scroll = new DelegatedEventEmitter(
18-
value =>
19-
{
20-
if (Control is ScrollViewer scroll)
21-
{
22-
scroll.ScrollChanged += (sender, args) => value();
23-
}
24-
},
25-
value => { }
26-
);
27-
2817
Resize = new DelegatedEventEmitter(
2918
value => { Control.SizeChanged += (sender, args) => value(); },
3019
value => { }
@@ -153,7 +142,6 @@ public void Clear()
153142
}
154143
}
155144

156-
public IEventEmitter Scroll { get; set; }
157145
public IEventEmitter Resize { get; set; }
158146
public IEventEmitterOfT<IMouseEventArgs> MouseDown { get; set; }
159147
public IEventEmitterOfT<IMouseEventArgs> MouseMove { get; set; }

src/Environment.ts

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { FontLoadingChecker } from '@src/util/FontLoadingChecker';
5353
import { Logger } from '@src/Logger';
5454
import { LeftHandTapEffectInfo } from './rendering/effects/LeftHandTapEffectInfo';
5555
import { CapellaImporter } from './importer/CapellaImporter';
56+
import { ResizeObserverPolyfill } from './platform/javascript/ResizeObserverPolyfill';
5657

5758
export class LayoutEngineFactory {
5859
public readonly vertical: boolean;
@@ -450,6 +451,11 @@ export class Environment {
450451
Environment.registerJQueryPlugin();
451452
if (!Environment.isRunningInWorker) {
452453
Environment.HighDpiFactor = window.devicePixelRatio;
454+
// ResizeObserver API does not yet exist so long on Safari (only start 2020 with iOS Safari 13.7 and Desktop 13.1)
455+
// so we better add a polyfill for it
456+
if(!('ResizeObserver' in globalThis)) {
457+
(globalThis as any).ResizeObserver = ResizeObserverPolyfill;
458+
}
453459
} else {
454460
AlphaTabWebWorker.init();
455461
AlphaSynthWebWorker.init();

src/platform/IContainer.ts

-5
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,6 @@ export interface IContainer {
6363
*/
6464
clear(): void;
6565

66-
/**
67-
* This event occurs when a scroll on the control happened.
68-
*/
69-
scroll: IEventEmitter;
70-
7166
/**
7267
* This event occurs when the control was resized.
7368
*/

src/platform/javascript/HtmlElementContainer.ts

+31-16
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@ import { IEventEmitter, IEventEmitterOfT } from '@src/EventEmitter';
22
import { IContainer } from '@src/platform/IContainer';
33
import { IMouseEventArgs } from '@src/platform/IMouseEventArgs';
44
import { BrowserMouseEventArgs } from '@src/platform/javascript/BrowserMouseEventArgs';
5+
import { Lazy } from '@src/util/Lazy';
56

67
/**
78
* @target web
89
*/
910
export class HtmlElementContainer implements IContainer {
11+
private static resizeObserver: Lazy<ResizeObserver> = new Lazy<ResizeObserver>(() => new ResizeObserver((entries) => {
12+
for (const e of entries) {
13+
let evt = new CustomEvent('resize', {
14+
detail: e
15+
});
16+
e.target.dispatchEvent(evt);
17+
}
18+
}));
19+
20+
private _resizeListeners: number = 0;
21+
1022
public get top(): number {
1123
return parseFloat(this.element.style.top);
1224
}
@@ -113,21 +125,29 @@ export class HtmlElementContainer implements IContainer {
113125
}
114126
};
115127

116-
this.scroll = {
117-
on: (value: any) => {
118-
window.addEventListener('scroll', value, true);
119-
},
120-
off: (value: any) => {
121-
window.removeEventListener('scroll', value, true);
122-
}
123-
};
124-
125128
this.resize = {
126129
on: (value: any) => {
127-
window.addEventListener('resize', value, true);
130+
if (this._resizeListeners === 0) {
131+
HtmlElementContainer.resizeObserver.value.observe(this.element);
132+
}
133+
this.element.addEventListener(
134+
'resize',
135+
value,
136+
true
137+
);
138+
this._resizeListeners++;
128139
},
129140
off: (value: any) => {
130-
window.removeEventListener('resize', value, true);
141+
this.element.removeEventListener(
142+
'resize',
143+
value,
144+
true
145+
);
146+
this._resizeListeners--;
147+
if (this._resizeListeners <= 0) {
148+
this._resizeListeners = 0;
149+
HtmlElementContainer.resizeObserver.value.unobserve(this.element);
150+
}
131151
}
132152
};
133153
}
@@ -142,11 +162,6 @@ export class HtmlElementContainer implements IContainer {
142162
this.element.style.left = x + 'px';
143163
}
144164

145-
/**
146-
* This event occurs when a scroll on the control happened.
147-
*/
148-
public scroll: IEventEmitter;
149-
150165
/**
151166
* This event occurs when the control was resized.
152167
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* A very basic polyfill of the ResizeObserver which triggers
3+
* a the callback on window resize for all registered targets.
4+
* @target web
5+
*/
6+
export class ResizeObserverPolyfill {
7+
private _callback: ResizeObserverCallback;
8+
private _targets = new Set<Element>();
9+
10+
public constructor(callback: ResizeObserverCallback) {
11+
this._callback = callback;
12+
window.addEventListener('resize', this.onWindowResize.bind(this), false);
13+
}
14+
15+
public observe(target: Element) {
16+
this._targets.add(target);
17+
}
18+
19+
public unobserve(target: Element) {
20+
this._targets.delete(target);
21+
}
22+
23+
public disconnect() {
24+
this._targets.clear();
25+
}
26+
27+
28+
private onWindowResize() {
29+
const entries: ResizeObserverEntry[] = [];
30+
for (const t of this._targets) {
31+
entries.push({
32+
target: t,
33+
// not used by alphaTab
34+
contentRect: undefined!,
35+
borderBoxSize: undefined!,
36+
contentBoxSize: []
37+
});
38+
}
39+
this._callback(entries, this);
40+
}
41+
}

0 commit comments

Comments
 (0)