Interaction handler keyboard handlers fix (#3881)

* initinal implementaion

* additional action, README and version changes

* update changelog

* remove excess reducer

* comment fixes

* changelog update

* canvas3d destroy call upd
main
Kirill Lakhov 4 years ago committed by GitHub
parent cddc76a31a
commit 14262fa951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- TDB - TDB
### Fixed ### Fixed
- TDB - Fixed Interaction handler keyboard handlers (<https://github.com/openvinotoolkit/cvat/pull/3881>)
### Security ### Security
- TDB - TDB

@ -137,6 +137,7 @@ Canvas itself handles:
cancel(): void; cancel(): void;
configure(configuration: Configuration): void; configure(configuration: Configuration): void;
isAbleToChangeFrame(): boolean; isAbleToChangeFrame(): boolean;
destroy(): void;
readonly geometry: Geometry; readonly geometry: Geometry;
} }
@ -189,6 +190,7 @@ Standard JS events are used.
- canvas.resizeshape => {id: number} - canvas.resizeshape => {id: number}
- canvas.contextmenu => { mouseEvent: MouseEvent, objectState: ObjectState, pointID: number } - canvas.contextmenu => { mouseEvent: MouseEvent, objectState: ObjectState, pointID: number }
- canvas.error => { exception: Error } - canvas.error => { exception: Error }
- canvas.destroy
``` ```
### WEB ### WEB
@ -239,6 +241,7 @@ canvas.draw({
| bitmap() | + | + | + | + | + | + | + | + | + | + | + | | bitmap() | + | + | + | + | + | + | + | + | + | + | + |
| setZLayer() | + | + | + | + | + | + | + | + | + | + | + | | setZLayer() | + | + | + | + | + | + | + | + | + | + | + |
| setupReviewROIs() | + | + | + | + | + | + | + | + | + | + | + | | setupReviewROIs() | + | + | + | + | + | + | + | + | + | + | + |
| destroy() | + | + | + | + | + | + | + | + | + | + | + |
<!--lint enable maximum-line-length--> <!--lint enable maximum-line-length-->

@ -1,12 +1,12 @@
{ {
"name": "cvat-canvas", "name": "cvat-canvas",
"version": "2.8.0", "version": "2.9.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cvat-canvas", "name": "cvat-canvas",
"version": "2.8.0", "version": "2.9.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"svg.draggable.js": "2.2.2", "svg.draggable.js": "2.2.2",

@ -1,6 +1,6 @@
{ {
"name": "cvat-canvas", "name": "cvat-canvas",
"version": "2.8.0", "version": "2.9.0",
"description": "Part of Computer Vision Annotation Tool which presents its canvas library", "description": "Part of Computer Vision Annotation Tool which presents its canvas library",
"main": "src/canvas.ts", "main": "src/canvas.ts",
"scripts": { "scripts": {

@ -53,6 +53,7 @@ interface Canvas {
cancel(): void; cancel(): void;
configure(configuration: Configuration): void; configure(configuration: Configuration): void;
isAbleToChangeFrame(): boolean; isAbleToChangeFrame(): boolean;
destroy(): void;
readonly geometry: Geometry; readonly geometry: Geometry;
} }
@ -163,6 +164,10 @@ class CanvasImpl implements Canvas {
public get geometry(): Geometry { public get geometry(): Geometry {
return this.model.geometry; return this.model.geometry;
} }
public destroy(): void {
this.model.destroy();
}
} }
export type InteractionData = _InteractionData; export type InteractionData = _InteractionData;

@ -146,6 +146,7 @@ export enum UpdateReasons {
ZOOM_CANVAS = 'zoom_canvas', ZOOM_CANVAS = 'zoom_canvas',
CONFIG_UPDATED = 'config_updated', CONFIG_UPDATED = 'config_updated',
DATA_FAILED = 'data_failed', DATA_FAILED = 'data_failed',
DESTROY = 'destroy',
} }
export enum Mode { export enum Mode {
@ -210,6 +211,7 @@ export interface CanvasModel {
isAbleToChangeFrame(): boolean; isAbleToChangeFrame(): boolean;
configure(configuration: Configuration): void; configure(configuration: Configuration): void;
cancel(): void; cancel(): void;
destroy(): void;
} }
export class CanvasModelImpl extends MasterImpl implements CanvasModel { export class CanvasModelImpl extends MasterImpl implements CanvasModel {
@ -685,6 +687,10 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
this.notify(UpdateReasons.CANCEL); this.notify(UpdateReasons.CANCEL);
} }
public destroy(): void {
this.notify(UpdateReasons.DESTROY);
}
public get configuration(): Configuration { public get configuration(): Configuration {
return { ...this.data.configuration }; return { ...this.data.configuration };
} }

@ -1358,6 +1358,16 @@ export class CanvasViewImpl implements CanvasView, Listener {
}, },
}); });
this.canvas.dispatchEvent(event); this.canvas.dispatchEvent(event);
} else if (reason === UpdateReasons.DESTROY) {
this.canvas.dispatchEvent(
new CustomEvent('canvas.destroy', {
bubbles: false,
cancelable: true,
}),
);
// We can't call namespaced svgjs event
// see - https://svgjs.dev/docs/2.7/events/
this.adoptedContent.fire('destroy');
} }
if (model.imageBitmap && [UpdateReasons.IMAGE_CHANGED, UpdateReasons.OBJECTS_UPDATED].includes(reason)) { if (model.imageBitmap && [UpdateReasons.IMAGE_CHANGED, UpdateReasons.OBJECTS_UPDATED].includes(reason)) {

@ -375,6 +375,27 @@ export class InteractionHandlerImpl implements InteractionHandler {
return false; return false;
} }
private onKeyUp = (e: KeyboardEvent): void => {
if (this.interactionData.enabled && e.keyCode === 17) {
if (this.interactionData.onChangeToolsBlockerState && !this.thresholdWasModified) {
this.interactionData.onChangeToolsBlockerState('keyup');
}
if (this.shouldRaiseEvent(false)) {
// 17 is ctrl
this.onInteraction(this.prepareResult(), true, false);
}
}
};
private onKeyDown = (e: KeyboardEvent): void => {
if (!e.repeat && this.interactionData.enabled && e.keyCode === 17) {
if (this.interactionData.onChangeToolsBlockerState && !this.thresholdWasModified) {
this.interactionData.onChangeToolsBlockerState('keydown');
}
this.thresholdWasModified = false;
}
};
public constructor( public constructor(
onInteraction: ( onInteraction: (
shapes: InteractionResult[] | null, shapes: InteractionResult[] | null,
@ -452,25 +473,12 @@ export class InteractionHandlerImpl implements InteractionHandler {
} }
}); });
window.addEventListener('keyup', (e: KeyboardEvent): void => { window.addEventListener('keyup', this.onKeyUp);
if (this.interactionData.enabled && e.keyCode === 17) { window.addEventListener('keydown', this.onKeyDown);
if (this.interactionData.onChangeToolsBlockerState && !this.thresholdWasModified) {
this.interactionData.onChangeToolsBlockerState('keyup');
}
if (this.shouldRaiseEvent(false)) {
// 17 is ctrl
this.onInteraction(this.prepareResult(), true, false);
}
}
});
window.addEventListener('keydown', (e: KeyboardEvent): void => { this.canvas.on('destroy.canvas', ():void => {
if (!e.repeat && this.interactionData.enabled && e.keyCode === 17) { window.removeEventListener('keyup', this.onKeyUp);
if (this.interactionData.onChangeToolsBlockerState && !this.thresholdWasModified) { window.removeEventListener('keydown', this.onKeyDown);
this.interactionData.onChangeToolsBlockerState('keydown');
}
this.thresholdWasModified = false;
}
}); });
} }

@ -36,6 +36,7 @@ interface Canvas3d {
fitCanvas(): void; fitCanvas(): void;
fit(): void; fit(): void;
group(groupData: GroupData): void; group(groupData: GroupData): void;
destroy(): void;
} }
class Canvas3dImpl implements Canvas3d { class Canvas3dImpl implements Canvas3d {
@ -104,6 +105,10 @@ class Canvas3dImpl implements Canvas3d {
public fitCanvas(): void { public fitCanvas(): void {
this.model.fit(); this.model.fit();
} }
public destroy(): void {
this.model.destroy();
}
} }
export { export {

@ -126,6 +126,7 @@ export interface Canvas3dModel {
configureShapes(shapeProperties: any): void; configureShapes(shapeProperties: any): void;
fit(): void; fit(): void;
group(groupData: GroupData): void; group(groupData: GroupData): void;
destroy(): void;
} }
export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel { export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
@ -234,8 +235,8 @@ export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
} }
public isAbleToChangeFrame(): boolean { public isAbleToChangeFrame(): boolean {
const isUnable = [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT, Mode.BUSY].includes(this.data.mode) const isUnable = [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT, Mode.BUSY].includes(this.data.mode) ||
|| (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number'); (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number');
return !isUnable; return !isUnable;
} }
@ -340,4 +341,6 @@ export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
public get groupData(): GroupData { public get groupData(): GroupData {
return { ...this.data.groupData }; return { ...this.data.groupData };
} }
public destroy(): void {}
} }

@ -287,6 +287,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
(_state: any): boolean => _state.clientID === Number(intersects[0].object.name), (_state: any): boolean => _state.clientID === Number(intersects[0].object.name),
); );
if (item.length !== 0) { if (item.length !== 0) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
this.model.data.groupData.grouped = this.model.data.groupData.grouped.filter( this.model.data.groupData.grouped = this.model.data.groupData.grouped.filter(
(_state: any): boolean => _state.clientID !== Number(intersects[0].object.name), (_state: any): boolean => _state.clientID !== Number(intersects[0].object.name),
@ -543,9 +544,9 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.action.rotation.screenInit = { x: diffX, y: diffY }; this.action.rotation.screenInit = { x: diffX, y: diffY };
this.action.rotation.screenMove = { x: diffX, y: diffY }; this.action.rotation.screenMove = { x: diffX, y: diffY };
if ( if (
this.model.data.selected this.model.data.selected &&
&& !this.model.data.selected.perspective.userData.lock !this.model.data.selected.perspective.userData.lock &&
&& !this.model.data.selected.perspective.userData.hidden !this.model.data.selected.perspective.userData.hidden
) { ) {
this.action.scan = view; this.action.scan = view;
this.model.mode = Mode.EDIT; this.model.mode = Mode.EDIT;
@ -698,8 +699,8 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
cuboid.setOpacity(opacity); cuboid.setOpacity(opacity);
if ( if (
this.model.data.activeElement.clientID === clientID this.model.data.activeElement.clientID === clientID &&
&& ![Mode.DRAG_CANVAS, Mode.GROUP].includes(this.mode) ![Mode.DRAG_CANVAS, Mode.GROUP].includes(this.mode)
) { ) {
cuboid.setOpacity(selectedOpacity); cuboid.setOpacity(selectedOpacity);
if (!object.lock) { if (!object.lock) {
@ -964,12 +965,12 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
const sphereCenter = points.geometry.boundingSphere.center; const sphereCenter = points.geometry.boundingSphere.center;
const { radius } = points.geometry.boundingSphere; const { radius } = points.geometry.boundingSphere;
if (!this.views.perspective.camera) return; if (!this.views.perspective.camera) return;
const xRange = -radius / 2 < this.views.perspective.camera.position.x - sphereCenter.x const xRange = -radius / 2 < this.views.perspective.camera.position.x - sphereCenter.x &&
&& radius / 2 > this.views.perspective.camera.position.x - sphereCenter.x; radius / 2 > this.views.perspective.camera.position.x - sphereCenter.x;
const yRange = -radius / 2 < this.views.perspective.camera.position.y - sphereCenter.y const yRange = -radius / 2 < this.views.perspective.camera.position.y - sphereCenter.y &&
&& radius / 2 > this.views.perspective.camera.position.y - sphereCenter.y; radius / 2 > this.views.perspective.camera.position.y - sphereCenter.y;
const zRange = -radius / 2 < this.views.perspective.camera.position.z - sphereCenter.z const zRange = -radius / 2 < this.views.perspective.camera.position.z - sphereCenter.z &&
&& radius / 2 > this.views.perspective.camera.position.z - sphereCenter.z; radius / 2 > this.views.perspective.camera.position.z - sphereCenter.z;
let newX = 0; let newX = 0;
let newY = 0; let newY = 0;
let newZ = 0; let newZ = 0;
@ -1085,10 +1086,10 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
private positionAllViews(x: number, y: number, z: number, animation: boolean): void { private positionAllViews(x: number, y: number, z: number, animation: boolean): void {
if ( if (
this.views.perspective.controls this.views.perspective.controls &&
&& this.views.top.controls this.views.top.controls &&
&& this.views.side.controls this.views.side.controls &&
&& this.views.front.controls this.views.front.controls
) { ) {
this.views.perspective.controls.setLookAt(x - 8, y - 8, z + 3, x, y, z, animation); this.views.perspective.controls.setLookAt(x - 8, y - 8, z + 3, x, y, z, animation);
this.views.top.camera.position.set(x, y, z + 8); this.views.top.camera.position.set(x, y, z + 8);
@ -1266,8 +1267,8 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
private renderTranslateAction(view: ViewType, viewType: any): void { private renderTranslateAction(view: ViewType, viewType: any): void {
if ( if (
this.action.translation.helper.x === this.views[view].rayCaster.mouseVector.x this.action.translation.helper.x === this.views[view].rayCaster.mouseVector.x &&
&& this.action.translation.helper.y === this.views[view].rayCaster.mouseVector.y this.action.translation.helper.y === this.views[view].rayCaster.mouseVector.y
) { ) {
return; return;
} }
@ -1332,8 +1333,8 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
} }
if ( if (
this.action.resize.recentMouseVector.x === currentPosX this.action.resize.recentMouseVector.x === currentPosX &&
&& this.action.resize.recentMouseVector.y === currentPosY this.action.resize.recentMouseVector.y === currentPosY
) { ) {
return; return;
} }
@ -1736,15 +1737,15 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
y: canvas.offsetTop + canvas.offsetHeight / 2, y: canvas.offsetTop + canvas.offsetHeight / 2,
}; };
if ( if (
this.action.rotation.screenInit.x === this.action.rotation.screenMove.x this.action.rotation.screenInit.x === this.action.rotation.screenMove.x &&
&& this.action.rotation.screenInit.y === this.action.rotation.screenMove.y this.action.rotation.screenInit.y === this.action.rotation.screenMove.y
) { ) {
return; return;
} }
if ( if (
this.action.rotation.recentMouseVector.x === this.views[view].rayCaster.mouseVector.x this.action.rotation.recentMouseVector.x === this.views[view].rayCaster.mouseVector.x &&
&& this.action.rotation.recentMouseVector.y === this.views[view].rayCaster.mouseVector.y this.action.rotation.recentMouseVector.y === this.views[view].rayCaster.mouseVector.y
) { ) {
return; return;
} }

@ -1,12 +1,12 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.25.0", "version": "1.25.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.25.0", "version": "1.25.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ant-design/icons": "^4.6.3", "@ant-design/icons": "^4.6.3",

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.25.0", "version": "1.25.1",
"description": "CVAT single-page application", "description": "CVAT single-page application",
"main": "src/index.tsx", "main": "src/index.tsx",
"scripts": { "scripts": {

@ -166,6 +166,8 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
activeShapeType = ShapeType.CUBOID; activeShapeType = ShapeType.CUBOID;
} }
state.canvas.instance.destroy();
return { return {
...state, ...state,
job: { job: {

Loading…
Cancel
Save