Skip to content

Commit

Permalink
Snap to mouse on time-graph-navigator click
Browse files Browse the repository at this point in the history
Adds background PIXI rectangless to the time-graph-navigator +
vertical-navigator components.  This rect listens for clicks then
centers the handler on the mouse and resumes 'dragging' for navigating.

Fixes: eclipse-cdt-cloud#97

Signed-off-by: Will Yang <william.yang@ericsson.com>
  • Loading branch information
William Yang authored and williamsyang-work committed Feb 26, 2022
1 parent ae1adb0 commit dad5e6b
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 16 deletions.
73 changes: 67 additions & 6 deletions timeline-chart/src/layer/time-graph-navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import { BIMath } from "../bigint-utils";
export class TimeGraphNavigator extends TimeGraphLayer {

protected navigatorHandle: TimeGraphNavigatorHandle;
protected navigatorBackground: TimeGraphNavigatorBackground;
protected selectionRange?: TimeGraphRectangle;
private _updateHandler: { (): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; (viewRange: TimelineChart.TimeGraphRange): void; (selectionRange: TimelineChart.TimeGraphRange): void; };

afterAddToContainer() {
this._updateHandler = (): void => this.update();
this.unitController.onViewRangeChanged(this._updateHandler);
this.navigatorBackground = new TimeGraphNavigatorBackground(this.unitController, this.stateController);
this.addChild(this.navigatorBackground);
this.navigatorHandle = new TimeGraphNavigatorHandle(this.unitController, this.stateController);
this.addChild(this.navigatorHandle);
this.unitController.onSelectionRangeChange(this._updateHandler);
Expand Down Expand Up @@ -66,11 +69,19 @@ export class TimeGraphNavigatorHandle extends TimeGraphComponent<null> {

constructor(protected unitController: TimeGraphUnitController, protected stateController: TimeGraphStateController) {
super('navigator_handle');
this.addEvent('mousedown', event => {
const moveStart: TimeGraphInteractionHandler = event => {
this.mouseStartX = event.data.global.x;
this.oldViewStart = this.unitController.viewRange.start;
this.mouseIsDown = true;
this.stateController.snapped = false
}
const moveEnd = () => {
this.mouseIsDown = false
}
this.addEvent('mouseover', event => {
if(this.stateController.snapped) moveStart(event)
}, this._displayObject);
this.addEvent('mousedown', moveStart, this._displayObject);
this.addEvent('mousemove', event => {
if (this.mouseIsDown) {
const delta = event.data.global.x - this.mouseStartX;
Expand All @@ -83,11 +94,9 @@ export class TimeGraphNavigatorHandle extends TimeGraphComponent<null> {
}
}
}, this._displayObject);
const moveEnd: TimeGraphInteractionHandler = event => {
this.mouseIsDown = false;
}
this.addEvent('mouseup', moveEnd, this._displayObject);
this.addEvent('mouseupoutside', moveEnd, this._displayObject);
this.addEvent('mouseup', moveEnd, this._displayObject)
this.addEvent('mouseupoutside', moveEnd, this._displayObject)
document.addEventListener('snap-x-end', moveEnd)
}

render(): void {
Expand All @@ -104,4 +113,56 @@ export class TimeGraphNavigatorHandle extends TimeGraphComponent<null> {
color: 0x777769
})
}
}

export class TimeGraphNavigatorBackground extends TimeGraphComponent<null> {

protected snapEvent: CustomEvent;
protected snapEventString: string;

constructor(protected unitController: TimeGraphUnitController, protected stateController: TimeGraphStateController) {
super("navigator_background")
this.addEvent("mousedown", event => {
let x = event.data.getLocalPosition(this._displayObject).x;
let middle = BIMath.round((x / this.stateController.canvasDisplayWidth) * this._displayObject.width);
// We have horizontal offset at point of click, now we need coord for start of handler.
let hVL = this.unitController.viewRangeLength / BigInt(2);
let start0 = middle - hVL;
let max = this.unitController.absoluteRange - this.unitController.viewRangeLength;
let min = BigInt(0);
// Clamp it.
const start = BIMath.clamp(start0, min, max)
this.unitController.viewRange = {
start,
end: start + this.unitController.viewRangeLength,
}
// Set snapped state
this.toggleSnappedState(true);
}, this._displayObject);
// Custom event let's handler know 'mouseup' triggers.
this.snapEvent = new CustomEvent(this.snapEventString = 'snap-x-end')
const endSnap= () => {
this.toggleSnappedState(false);
document.dispatchEvent(this.snapEvent)
}
this.addEvent('mouseup', endSnap, this._displayObject)
this.addEvent('mouseupoutside', endSnap, this._displayObject)
}

protected toggleSnappedState = (bool: boolean) => {
this.stateController.snapped = bool;
}

render(): void {
this.rect({
height: 20,
position: {
x: 0,
y: 0
},
width: Number(this.unitController.viewRangeLength),
color: 0xe100ff,
opacity: 0,
})
}
}
80 changes: 70 additions & 10 deletions timeline-chart/src/layer/time-graph-vertical-scrollbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { TimeGraphRowController } from "../time-graph-row-controller";
export class TimeGraphVerticalScrollbar extends TimeGraphChartLayer {

protected navigatorHandle: TimeGraphVerticalScrollbarHandle;
protected navigatorBackground: TimeGraphVerticalScrollbarBackground;
protected selectionRange?: TimeGraphRectangle;

protected factor: number;
Expand All @@ -18,11 +19,14 @@ export class TimeGraphVerticalScrollbar extends TimeGraphChartLayer {
protected afterAddToContainer() {
this.updateFactor();
this.navigatorHandle = new TimeGraphVerticalScrollbarHandle(this.rowController, this.stateController, this.factor);
this.navigatorBackground = new TimeGraphVerticalScrollbarBackground(this.rowController, this.stateController, this.factor);
this.addChild(this.navigatorBackground);
this.addChild(this.navigatorHandle);
this.rowController.onVerticalOffsetChangedHandler(() => this.update());
this.rowController.onTotalHeightChangedHandler(() => {
this.updateFactor();
this.navigatorHandle.updateFactor(this.factor);
this.navigatorBackground.updateFactor(this.factor);
this.update()
});
}
Expand All @@ -38,6 +42,8 @@ export class TimeGraphVerticalScrollbar extends TimeGraphChartLayer {
update() {
this.navigatorHandle.clear();
this.navigatorHandle.render();
this.navigatorBackground.clear();
this.navigatorBackground.render();
}
}

Expand All @@ -52,23 +58,29 @@ export class TimeGraphVerticalScrollbarHandle extends TimeGraphComponent<null> {

constructor(protected rowController: TimeGraphRowController, protected stateController: TimeGraphStateController, protected factor: number) {
super('vscroll_handle');
this.addEvent('mousedown', event => {
this.mouseStartY = event.data.global.y;
this.oldVerticalOffset = this.rowController.verticalOffset
this.mouseIsDown = true;
}, this._displayObject);
const moveStart: TimeGraphInteractionHandler = event => {
this.mouseStartY = event.data.global.y;
this.oldVerticalOffset = this.rowController.verticalOffset
this.mouseIsDown = true;
this.stateController.snapped = false;
};
const moveEnd = () => {
this.mouseIsDown = false
}
this.addEvent('mouseover', (event) => {
if(this.stateController.snapped) moveStart(event)
}, this._displayObject)
this.addEvent('mousedown', moveStart, this._displayObject);
this.addEvent('mousemove', event => {
if (this.mouseIsDown) {
const delta = (event.data.global.y - this.mouseStartY) / this.factor;
const verticalOffset = this.oldVerticalOffset + delta;
this.rowController.verticalOffset = Math.max(0, Math.min(this.rowController.totalHeight - this.stateController.canvasDisplayHeight, verticalOffset));
}
}, this._displayObject);
const moveEnd: TimeGraphInteractionHandler = event => {
this.mouseIsDown = false;
}
this.addEvent('mouseup', moveEnd, this._displayObject);
this.addEvent('mouseupoutside', moveEnd, this._displayObject);
this.addEvent('mouseup', moveEnd, this._displayObject)
this.addEvent('mouseupoutside', moveEnd, this._displayObject)
document.addEventListener('snap-y-end', moveEnd)
}

updateFactor(factor: number) {
Expand All @@ -85,4 +97,52 @@ export class TimeGraphVerticalScrollbarHandle extends TimeGraphComponent<null> {
color: 0x777769
})
}
}

export class TimeGraphVerticalScrollbarBackground extends TimeGraphComponent<null> {

protected snapEvent: CustomEvent;
protected snapEventString: string;

constructor(protected rowController: TimeGraphRowController, protected stateController: TimeGraphStateController, protected factor: number) {
super("vscroll_background")
this.addEvent("mousedown", event => {
let yPosition = event.data.getLocalPosition(this._displayObject).y;
let vOffset = (yPosition/this.stateController.canvasDisplayHeight) * this.rowController.totalHeight
// We have vertical offset at point of click, but need to make it the center of scrollbar.
let scrollBarHeight = (this.rowController.totalHeight * this.factor)
vOffset = vOffset - (scrollBarHeight / 2)
// Clamp it
let vOffsetClamped = Math.max(0, Math.min(this.rowController.totalHeight - this.stateController.canvasDisplayHeight, vOffset))
this.rowController.verticalOffset = vOffsetClamped;
// Set snapped state
this.toggleSnappedState(true);
}, this._displayObject);
// Emit custom event to let vertical handler know when 'mousedown' is released.
this.snapEvent = new CustomEvent(this.snapEventString = 'snap-y-end')
const endSnap = () => {
this.toggleSnappedState(false)
document.dispatchEvent(this.snapEvent)
}
this.addEvent('mouseup', endSnap, this._displayObject)
this.addEvent('mouseupoutside', endSnap, this._displayObject)
}

updateFactor(factor: number) {
this.factor = factor;
}

protected toggleSnappedState = (bool: boolean) => {
this.stateController.snapped = bool;
}

render(): void {
this.rect({
height: this.stateController.canvasDisplayHeight,
position: { x: 0, y: 0 },
width: 10,
color: 0xe100ff,
opacity: 0,
})
}
}
4 changes: 4 additions & 0 deletions timeline-chart/src/time-graph-state-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export class TimeGraphStateController {
x: number;
y: number;
};

snapped: boolean;

protected ratio: number;

Expand Down Expand Up @@ -32,6 +34,7 @@ export class TimeGraphStateController {
this.zoomChangedHandlers = [];
this.positionChangedHandlers = [];
this.canvasDisplayWidthChangedHandlers = [];
this.snapped = false;
}

protected handleZoomChange() {
Expand Down Expand Up @@ -102,4 +105,5 @@ export class TimeGraphStateController {
this._positionOffset = value;
this.handlePositionChange();
}

}

0 comments on commit dad5e6b

Please sign in to comment.