Skip to content

Commit

Permalink
Add APIs to clean-up components and to remove event handlers
Browse files Browse the repository at this point in the history
When being destroyed, make sure that all children are removed as well as
all event handlers are removed to avoid unexpected handler calls.

Fixes #98
Fixes #120

Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
  • Loading branch information
bhufmann committed May 3, 2021
1 parent 3246589 commit 4b97ae9
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 66 deletions.
15 changes: 13 additions & 2 deletions timeline-chart/src/layer/time-graph-axis-cursors.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { TimeGraphAxisCursor } from "../components/time-graph-axis-cursor";
import { TimelineChart } from "../time-graph-model";
import { TimeGraphLayer } from "./time-graph-layer";

export class TimeGraphAxisCursors extends TimeGraphLayer {
protected firstCursor?: TimeGraphAxisCursor;
protected secondCursor?: TimeGraphAxisCursor;
protected color: number = 0x0000ff;
private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };

constructor(id: string, style?: { color?: number }) {
super(id);
Expand All @@ -15,8 +17,9 @@ export class TimeGraphAxisCursors extends TimeGraphLayer {
}

afterAddToContainer() {
this.unitController.onViewRangeChanged(() => this.update());
this.unitController.onSelectionRangeChange(() => this.update());
this._updateHandler = (): void => this.update();
this.unitController.onViewRangeChanged(this._updateHandler);
this.unitController.onSelectionRangeChange(this._updateHandler);
this.update();
}

Expand Down Expand Up @@ -60,4 +63,12 @@ export class TimeGraphAxisCursors extends TimeGraphLayer {
delete this.secondCursor;
}
}

destroy(): void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._updateHandler);
this.unitController.removeSelectionRangeChangedHandler(this._updateHandler);
}
super.destroy();
}
}
44 changes: 35 additions & 9 deletions timeline-chart/src/layer/time-graph-axis.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { TimeGraphAxisScale } from "../components/time-graph-axis-scale";
import { TimeGraphLayer } from "./time-graph-layer";
import * as _ from "lodash";
import { TimelineChart } from "../time-graph-model";

export class TimeGraphAxis extends TimeGraphLayer {

protected scaleComponent: TimeGraphAxisScale;
protected controlKeyDown: boolean;
private _updateHandler: { (): void; (selectionRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };
private _mouseWheelHandler: _.DebouncedFunc<(ev: WheelEvent) => boolean>;
private _keyUpHandler: { (event: KeyboardEvent): void; (this: Document, ev: KeyboardEvent): any; };
private _keyDownHandler: { (event: KeyboardEvent): void; (this: Document, ev: KeyboardEvent): any; };

constructor(id: string, protected style?: { color?: number, lineColor?: number }) {
super(id);
Expand All @@ -32,13 +37,15 @@ export class TimeGraphAxis extends TimeGraphLayer {

protected afterAddToContainer() {
this.controlKeyDown = false
document.addEventListener('keydown', (event: KeyboardEvent) => {
this._keyDownHandler = (event: KeyboardEvent) => {
this.controlKeyDown = event.ctrlKey;
});
document.addEventListener('keyup', (event: KeyboardEvent) => {
};
document.addEventListener('keydown', this._keyDownHandler);
this._keyUpHandler = (event: KeyboardEvent) => {
this.controlKeyDown = event.ctrlKey;
});
const mw = _.throttle((ev: WheelEvent) => {
};
document.addEventListener('keyup', this._keyUpHandler);
this._mouseWheelHandler = _.throttle((ev: WheelEvent) => {
if (this.controlKeyDown) {
// ZOOM AROUND MOUSE POINTER
const zoomPosition = (ev.offsetX / this.stateController.zoomFactor);
Expand Down Expand Up @@ -71,8 +78,8 @@ export class TimeGraphAxis extends TimeGraphLayer {
ev.preventDefault();
return false;
});
this.onCanvasEvent('mousewheel', mw);
this.onCanvasEvent('wheel', mw);
this.onCanvasEvent('mousewheel', this._mouseWheelHandler);
this.onCanvasEvent('wheel', this._mouseWheelHandler);
this.scaleComponent = new TimeGraphAxisScale(
this.id + '_scale',
this.getOptions(),
Expand All @@ -81,11 +88,30 @@ export class TimeGraphAxis extends TimeGraphLayer {
);
this.addChild(this.scaleComponent);

this.unitController.onSelectionRangeChange(() => this.update());
this.unitController.onViewRangeChanged(() => this.update());
this._updateHandler = (): void => this.update();
this.unitController.onSelectionRangeChange(this._updateHandler);
this.unitController.onViewRangeChanged(this._updateHandler);
}

update() {
this.scaleComponent.update(this.getOptions());
}

destroy() : void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._updateHandler);
this.unitController.removeSelectionRangeChangedHandler(this._updateHandler);
}
if (this._mouseWheelHandler) {
this.removeOnCanvasEvent('mousewheel', this._mouseWheelHandler);
this.removeOnCanvasEvent('wheel', this._mouseWheelHandler);
}
if (this._keyDownHandler) {
document.removeEventListener('keydown', this._keyDownHandler);
}
if (this._keyUpHandler) {
document.removeEventListener('keyup', this._keyUpHandler);
}
super.destroy();
}
}
12 changes: 10 additions & 2 deletions timeline-chart/src/layer/time-graph-chart-arrows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { TimeGraphChartLayer } from "./time-graph-chart-layer";
export class TimeGraphChartArrows extends TimeGraphChartLayer {

protected arrows: Map<TimelineChart.TimeGraphArrow, TimeGraphArrowComponent>;
private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; };

protected afterAddToContainer() {
this.unitController.onViewRangeChanged(() => this.update());
this._updateHandler = (): void => this.update();
this.unitController.onViewRangeChanged(this._updateHandler);

this.rowController.onVerticalOffsetChangedHandler(verticalOffset => {
this.layer.position.y = -verticalOffset;
Expand Down Expand Up @@ -40,7 +42,7 @@ export class TimeGraphChartArrows extends TimeGraphChartLayer {
throw ('Add this TimeGraphChartArrows to a container before adding arrows.');
}
if (this.arrows) {
this.arrows.forEach(rowEl => rowEl.destroy());
this.removeChildren();
}
this.arrows = new Map();
arrows.forEach(arrow => {
Expand All @@ -64,4 +66,10 @@ export class TimeGraphChartArrows extends TimeGraphChartLayer {
}
}

destroy() : void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._updateHandler);
}
super.destroy();
}
}
69 changes: 53 additions & 16 deletions timeline-chart/src/layer/time-graph-chart-cursors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
protected secondCursor?: TimeGraphCursor;
protected color: number = 0x0000ff;

private _stageMouseDownHandler: Function;
private _stageMouseMoveHandler: Function;
private _stageMouseUpHandler: Function;

private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };
private _mouseDownHandler: { (event: MouseEvent): void; (event: Event): void; };
private _keyDownHandler: (event: KeyboardEvent) => void;
private _keyUpHandler: (event: KeyboardEvent) => void;

constructor(id: string, protected chartLayer: TimeGraphChart, protected rowController: TimeGraphRowController, style?: { color?: number }) {
super(id, rowController);
if (style && style.color) {
Expand All @@ -27,7 +36,9 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
this.shiftKeyDown = false
this.stage.interactive = true;

const keyDownHandler = (event: KeyboardEvent) => {
this._updateHandler = (): void => this.update();

this._keyDownHandler = (event: KeyboardEvent) => {
if (event.key === 'Shift' && this.mouseButtons === 0 && !event.ctrlKey && !event.altKey) {
this.stage.cursor = 'crosshair';
} else if (this.stage.cursor === 'crosshair' && !this.mouseSelecting &&
Expand All @@ -47,17 +58,17 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
}
};

const keyUpHandler = (event: KeyboardEvent) => {
this._keyUpHandler = (event: KeyboardEvent) => {
this.shiftKeyDown = event.shiftKey;
if (this.stage.cursor === 'crosshair' && !this.mouseSelecting && event.key === 'Shift' ) {
this.stage.cursor = 'default';
}
};

this.onCanvasEvent('keydown', keyDownHandler);
this.onCanvasEvent('keyup', keyUpHandler);
this.onCanvasEvent('keydown', this._keyDownHandler);
this.onCanvasEvent('keyup', this._keyUpHandler);

this.stage.on('mousedown', (event: PIXI.InteractionEvent) => {
this._stageMouseDownHandler = (event: PIXI.InteractionEvent) => {
this.mouseButtons = event.data.buttons;
// if only left button is pressed with or without Shift key
if (event.data.button !== 0 || event.data.buttons !== 1 ||
Expand All @@ -82,8 +93,9 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
end: xpos
}
}
});
this.stage.on('mousemove', (event: PIXI.InteractionEvent) => {
};
this.stage.on('mousedown', this._stageMouseDownHandler);
this._stageMouseMoveHandler = (event: PIXI.InteractionEvent) => {
this.mouseButtons = event.data.buttons;
if (this.mouseSelecting && this.unitController.selectionRange) {
if ((this.mouseButtons & 1) === 0) {
Expand All @@ -103,8 +115,10 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
end: xEndPos
}
}
});
const mouseUpHandler = (event: PIXI.InteractionEvent) => {
}
this.stage.on('mousemove', this._stageMouseMoveHandler);

this._stageMouseUpHandler = (event: PIXI.InteractionEvent) => {
this.mouseButtons = event.data.buttons;
if (this.mouseSelecting && event.data.button === 0) {
this.mouseSelecting = false;
Expand All @@ -114,10 +128,10 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
}
}
};
this.stage.on('mouseup', mouseUpHandler);
this.stage.on('mouseupoutside', mouseUpHandler);
this.stage.on('mouseup', this._stageMouseUpHandler);
this.stage.on('mouseupoutside', this._stageMouseUpHandler);
// right mouse button is not detected on stage
this.onCanvasEvent('mousedown', (e: MouseEvent) => {
this._mouseDownHandler = (e: MouseEvent) => {
this.mouseButtons = e.buttons;
// if right button is pressed
if (e.button === 2) {
Expand All @@ -130,10 +144,10 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
}
document.addEventListener('mouseup', mouseUpListener);
}
});

this.unitController.onViewRangeChanged(() => this.update());
this.unitController.onSelectionRangeChange(() => this.update());
};
this.onCanvasEvent('mousedown', this._mouseDownHandler);
this.unitController.onViewRangeChanged(this._updateHandler);
this.unitController.onSelectionRangeChange(this._updateHandler);
this.update();
}

Expand Down Expand Up @@ -287,4 +301,27 @@ export class TimeGraphChartCursors extends TimeGraphChartLayer {
delete this.secondCursor;
}
}

destroy() : void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._updateHandler);
this.unitController.removeSelectionRangeChangedHandler(this._updateHandler);
}
if (this._mouseDownHandler) {
this.removeOnCanvasEvent('mousedown', this._mouseDownHandler);
}
if (this._keyDownHandler) {
this.removeOnCanvasEvent('keydown', this._keyDownHandler);
}
if (this._keyUpHandler) {
this.removeOnCanvasEvent('mousedown', this._keyUpHandler);
}
if (this.stage) {
this.stage.off('mousedown', this._stageMouseDownHandler);
this.stage.off('mousemove', this._stageMouseMoveHandler);
this.stage.off('mouseup', this._stageMouseUpHandler);
this.stage.off('mouseupoutside', this._stageMouseUpHandler);
}
super.destroy();
}
}
13 changes: 12 additions & 1 deletion timeline-chart/src/layer/time-graph-chart-grid.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { TimeGraphLayer } from "./time-graph-layer";
import { TimeGraphGrid } from "../components/time-graph-grid";
import { TimelineChart } from "../time-graph-model";

export class TimeGraphChartGrid extends TimeGraphLayer {

protected gridComponent: TimeGraphGrid;
private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };;

constructor(id: string, protected rowHeight: number, protected lineColor?: number) {
super(id);
Expand All @@ -17,11 +19,20 @@ export class TimeGraphChartGrid extends TimeGraphLayer {
lineColor: this.lineColor
}, this.rowHeight, this.unitController, this.stateController);
this.addChild(this.gridComponent);
this.unitController.onViewRangeChanged(() => this.update());
this._updateHandler = (): void => this.update();
this.unitController.onViewRangeChanged(this._updateHandler);
}

update() {
this.gridComponent.update();
}

destroy() : void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._updateHandler);
this.unitController.removeSelectionRangeChangedHandler(this._updateHandler);
}
super.destroy();
}

}
20 changes: 17 additions & 3 deletions timeline-chart/src/layer/time-graph-chart-selection-range.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { TimeGraphRectangle } from "../components/time-graph-rectangle";
import { TimelineChart } from "../time-graph-model";
import { TimeGraphLayer } from "./time-graph-layer";

export class TimeGraphChartSelectionRange extends TimeGraphLayer {
protected selectionRange?: TimeGraphRectangle;
protected color: number = 0x0000ff;
private _viewRangeUpdateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; };
private _updateHandler: { (): void; (selectionRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };

constructor(id: string, style?: { color?: number }) {
super(id);
Expand All @@ -21,10 +24,13 @@ export class TimeGraphChartSelectionRange extends TimeGraphLayer {
}

protected afterAddToContainer() {
this.unitController.onViewRangeChanged(() => {
this._viewRangeUpdateHandler = () => {
this.updateScaleAndPosition();
});
this.unitController.onSelectionRangeChange(() => this.update());
};

this._updateHandler = (): void => this.update();
this.unitController.onViewRangeChanged(this._viewRangeUpdateHandler);
this.unitController.onSelectionRangeChange(this._updateHandler);
this.update();
}

Expand Down Expand Up @@ -69,4 +75,12 @@ export class TimeGraphChartSelectionRange extends TimeGraphLayer {
this.removeSelectionRange();
}
}

destroy() : void {
if (this.unitController) {
this.unitController.removeViewRangeChangedHandler(this._viewRangeUpdateHandler);
this.unitController.removeSelectionRangeChangedHandler(this._updateHandler);
}
super.destroy();
}
}
Loading

0 comments on commit 4b97ae9

Please sign in to comment.