123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import {mat3} from 'gl-matrix';
- import {Rect} from './gl/utils';
- import {FlamegraphFrame} from './flamegraphFrame';
- type DrawFn = () => void;
- type ArgumentTypes<F> = F extends (...args: infer A) => any ? A : never;
- export interface FlamegraphEvents {
- ['highlight frame']: (
- frame: FlamegraphFrame | null,
- mode: 'hover' | 'selected'
- ) => void;
- ['reset zoom']: () => void;
- ['set config view']: (configView: Rect) => void;
- ['transform config view']: (transform: mat3) => void;
- ['zoom at frame']: (frame: FlamegraphFrame, strategy: 'min' | 'exact') => void;
- }
- type EventStore = {[K in keyof FlamegraphEvents]: Set<FlamegraphEvents[K]>};
- export class CanvasScheduler {
- beforeFrameCallbacks: Set<DrawFn> = new Set();
- afterFrameCallbacks: Set<DrawFn> = new Set();
- onDisposeCallbacks: Set<() => void> = new Set();
- requestAnimationFrame: number | null = null;
- events: EventStore = {
- ['reset zoom']: new Set<FlamegraphEvents['reset zoom']>(),
- ['highlight frame']: new Set<FlamegraphEvents['highlight frame']>(),
- ['set config view']: new Set<FlamegraphEvents['set config view']>(),
- ['transform config view']: new Set<FlamegraphEvents['transform config view']>(),
- ['zoom at frame']: new Set<FlamegraphEvents['zoom at frame']>(),
- };
- onDispose(cb: () => void): void {
- if (this.onDisposeCallbacks.has(cb)) {
- return;
- }
- this.onDisposeCallbacks.add(cb);
- }
- on<K extends keyof FlamegraphEvents>(eventName: K, cb: FlamegraphEvents[K]): void {
- const set = this.events[eventName] as unknown as Set<FlamegraphEvents[K]>;
- if (set.has(cb)) {
- return;
- }
- set.add(cb);
- }
- off<K extends keyof FlamegraphEvents>(eventName: K, cb: FlamegraphEvents[K]): void {
- const set = this.events[eventName] as unknown as Set<FlamegraphEvents[K]>;
- if (set.has(cb)) {
- set.delete(cb);
- }
- }
- dispatch<K extends keyof FlamegraphEvents>(
- event: K,
- ...args: ArgumentTypes<FlamegraphEvents[K]>
- ): void {
- for (const handler of this.events[event]) {
- // @ts-ignore
- handler(...args);
- }
- }
- private registerCallback(cb: DrawFn, pool: Set<DrawFn>) {
- if (pool.has(cb)) {
- return;
- }
- pool.add(cb);
- }
- private unregisterCallback(cb: DrawFn, pool: Set<DrawFn>) {
- if (pool.has(cb)) {
- pool.delete(cb);
- }
- }
- registerBeforeFrameCallback(cb: DrawFn): void {
- this.registerCallback(cb, this.beforeFrameCallbacks);
- }
- unregisterBeforeFrameCallback(cb: DrawFn): void {
- this.unregisterCallback(cb, this.beforeFrameCallbacks);
- }
- registerAfterFrameCallback(cb: DrawFn): void {
- this.registerCallback(cb, this.afterFrameCallbacks);
- }
- unregisterAfterFrameCallback(cb: DrawFn): void {
- this.unregisterCallback(cb, this.afterFrameCallbacks);
- }
- dispose(): void {
- for (const cb of this.onDisposeCallbacks) {
- this.onDisposeCallbacks.delete(cb);
- cb();
- }
- for (const type in this.events) {
- this.events[type].clear();
- }
- }
- drawSync(): void {
- for (const cb of this.beforeFrameCallbacks) {
- cb();
- }
- for (const cb of this.afterFrameCallbacks) {
- cb();
- }
- }
- draw(): void {
- if (this.requestAnimationFrame) {
- window.cancelAnimationFrame(this.requestAnimationFrame);
- }
- this.requestAnimationFrame = window.requestAnimationFrame(() => {
- for (const cb of this.beforeFrameCallbacks) {
- cb();
- }
- for (const cb of this.afterFrameCallbacks) {
- cb();
- }
- this.requestAnimationFrame = null;
- });
- }
- }
- export class CanvasPoolManager {
- schedulers: Set<CanvasScheduler> = new Set();
- registerScheduler(scheduler: CanvasScheduler): void {
- if (this.schedulers.has(scheduler)) {
- return;
- }
- this.schedulers.add(scheduler);
- }
- dispatch<K extends keyof FlamegraphEvents>(
- event: K,
- args: ArgumentTypes<FlamegraphEvents[K]>
- ): void {
- for (const scheduler of this.schedulers) {
- scheduler.dispatch(event, ...args);
- }
- }
- unregisterScheduler(scheduler: CanvasScheduler): void {
- if (this.schedulers.has(scheduler)) {
- scheduler.dispose();
- this.schedulers.delete(scheduler);
- }
- }
- drawSync(): void {
- for (const scheduler of this.schedulers) {
- scheduler.drawSync();
- }
- }
- draw(): void {
- for (const scheduler of this.schedulers) {
- scheduler.draw();
- }
- }
- }
|