From 5879fec78509e36717b27ca5f85ed0af8400a6d8 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:18:12 +0300 Subject: [PATCH 1/8] Refactoring: tools blocker state outside of canvas --- cvat-canvas/src/typescript/canvasModel.ts | 1 - .../src/typescript/interactionHandler.ts | 52 +++++-------------- cvat-core/src/core-types.ts | 1 - cvat-core/src/ml-model.ts | 10 ---- .../controls-side-bar/opencv-control.tsx | 38 ++++++++++---- .../controls-side-bar/tools-control.tsx | 35 +++++++++++-- .../opencv-wrapper/intelligent-scissors.ts | 6 +-- .../utils/opencv-wrapper/opencv-wrapper.ts | 6 +-- 8 files changed, 75 insertions(+), 74 deletions(-) diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index 165ca626ea5e..88d3a270118a 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -136,7 +136,6 @@ export interface InteractionData { shapeType: string; points: number[]; }; - onChangeToolsBlockerState?: (event: string) => void; } export interface InteractionResult { diff --git a/cvat-canvas/src/typescript/interactionHandler.ts b/cvat-canvas/src/typescript/interactionHandler.ts index 747c3c545370..aaa5a29624e0 100644 --- a/cvat-canvas/src/typescript/interactionHandler.ts +++ b/cvat-canvas/src/typescript/interactionHandler.ts @@ -36,7 +36,6 @@ export class InteractionHandlerImpl implements InteractionHandler { private thresholdRectSize: number; private intermediateShape: PropType; private drawnIntermediateShape: SVG.Shape; - private thresholdWasModified: boolean; private controlPointsSize: number; private selectedShapeOpacity: number; private cancelled: boolean; @@ -64,7 +63,7 @@ export class InteractionHandlerImpl implements InteractionHandler { ); } - private shouldRaiseEvent(ctrlKey: boolean): boolean { + private shouldRaiseEvent(): boolean { const { interactionData, interactionShapes, shapesWereUpdated } = this; const { minPosVertices, minNegVertices, enabled } = interactionData; @@ -76,7 +75,7 @@ export class InteractionHandlerImpl implements InteractionHandler { ); if (interactionData.shapeType === 'rectangle') { - return enabled && !ctrlKey && !!interactionShapes.length; + return enabled && !!interactionShapes.length; } const minPosVerticesDefined = Number.isInteger(minPosVertices); @@ -84,7 +83,7 @@ export class InteractionHandlerImpl implements InteractionHandler { const minPosVerticesAchieved = !minPosVerticesDefined || minPosVertices <= positiveShapes.length; const minNegVerticesAchieved = !minNegVerticesDefined || minNegVertices <= negativeShapes.length; const minimumVerticesAchieved = minPosVerticesAchieved && minNegVerticesAchieved; - return enabled && !ctrlKey && minimumVerticesAchieved && shapesWereUpdated; + return enabled && positiveShapes.length && minimumVerticesAchieved && shapesWereUpdated; } private addThreshold(): void { @@ -125,7 +124,7 @@ export class InteractionHandlerImpl implements InteractionHandler { this.interactionShapes.push(this.currentInteractionShape); this.shapesWereUpdated = true; - if (this.shouldRaiseEvent(e.ctrlKey)) { + if (this.shouldRaiseEvent()) { this.onInteraction(this.prepareResult(), true, false); } @@ -154,7 +153,7 @@ export class InteractionHandlerImpl implements InteractionHandler { if (this.interactionData.startWithBox && this.interactionShapes.length === 1) { this.interactionShapes[0].style({ visibility: '' }); } - const shouldRaiseEvent = this.shouldRaiseEvent(_e.ctrlKey); + const shouldRaiseEvent = this.shouldRaiseEvent(); if (shouldRaiseEvent) { this.onInteraction(this.prepareResult(), true, false); } @@ -193,7 +192,7 @@ export class InteractionHandlerImpl implements InteractionHandler { this.currentInteractionShape = this.canvas.rect(); this.canvas.on('mousedown.interaction', eventListener); this.currentInteractionShape - .on('drawstop', (e): void => { + .on('drawstop', (): void => { if (this.cancelled) { return; } @@ -204,7 +203,7 @@ export class InteractionHandlerImpl implements InteractionHandler { if (shouldFinish) { this.interact({ enabled: false }); - } else if (this.shouldRaiseEvent(e.ctrlKey)) { + } else if (this.shouldRaiseEvent()) { this.onInteraction(this.prepareResult(), true, false); } @@ -391,7 +390,7 @@ export class InteractionHandlerImpl implements InteractionHandler { } private visualComponentsChanged(interactionData: InteractionData): boolean { - const allowedKeys = ['enabled', 'crosshair', 'enableThreshold', 'onChangeToolsBlockerState']; + const allowedKeys = ['enabled', 'crosshair', 'enableThreshold']; if (Object.keys(interactionData).every((key: string): boolean => allowedKeys.includes(key))) { if (this.interactionData.enableThreshold !== undefined && interactionData.enableThreshold !== undefined && this.interactionData.enableThreshold !== interactionData.enableThreshold) { @@ -405,27 +404,6 @@ export class InteractionHandlerImpl implements InteractionHandler { 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( onInteraction: ( shapes: InteractionResult[] | null, @@ -488,11 +466,11 @@ export class InteractionHandlerImpl implements InteractionHandler { }); this.canvas.on('wheel.interaction', (e: WheelEvent): void => { - if (e.ctrlKey) { + if (e.altKey || e.ctrlKey) { + e.stopPropagation(); + e.preventDefault(); if (this.threshold) { - this.thresholdWasModified = true; const { x, y } = this.cursorPosition; - e.preventDefault(); if (e.deltaY > 0) { this.thresholdRectSize *= 6 / 5; } else { @@ -503,9 +481,6 @@ export class InteractionHandlerImpl implements InteractionHandler { } } }); - - window.document.addEventListener('keyup', this.onKeyUp); - window.document.addEventListener('keydown', this.onKeyDown); } public transform(geometry: Geometry): void { @@ -565,7 +540,7 @@ export class InteractionHandlerImpl implements InteractionHandler { (this.currentInteractionShape as any).draw('stop'); } - this.onInteraction(this.prepareResult(), this.shouldRaiseEvent(false), true); + this.onInteraction(this.prepareResult(), this.shouldRaiseEvent(), true); this.release(); this.interactionData = interactionData; } @@ -599,7 +574,6 @@ export class InteractionHandlerImpl implements InteractionHandler { } public destroy(): void { - window.document.removeEventListener('keyup', this.onKeyUp); - window.document.removeEventListener('keydown', this.onKeyDown); + // nothing to release } } diff --git a/cvat-core/src/core-types.ts b/cvat-core/src/core-types.ts index fee5bb4caa81..4b5a130f4d39 100644 --- a/cvat-core/src/core-types.ts +++ b/cvat-core/src/core-types.ts @@ -16,7 +16,6 @@ export interface ModelParams { minNegVertices?: number; startWithBox?: boolean; startWithBoxOptional?: boolean; - onChangeToolsBlockerState?: (event: string) => void; }; } diff --git a/cvat-core/src/ml-model.ts b/cvat-core/src/ml-model.ts index 3767bb71334b..ac128f5396fd 100644 --- a/cvat-core/src/ml-model.ts +++ b/cvat-core/src/ml-model.ts @@ -13,7 +13,6 @@ import { export default class MLModel { private serialized: SerializedModel; - private changeToolsBlockerStateCallback?: (event: string) => void; constructor(serialized: SerializedModel) { this.serialized = { ...serialized }; @@ -61,10 +60,6 @@ export default class MLModel { }, }; - if (this.changeToolsBlockerStateCallback) { - result.canvas.onChangeToolsBlockerState = this.changeToolsBlockerStateCallback; - } - return result; } @@ -103,11 +98,6 @@ export default class MLModel { return this.serialized?.return_type; } - // Used to set a callback when the tool is blocked in UI - public set onChangeToolsBlockerState(onChangeToolsBlockerState: (event: string) => void) { - this.changeToolsBlockerStateCallback = onChangeToolsBlockerState; - } - public async preview(): Promise { const result = await PluginRegistry.apiWrapper.call(this, MLModel.prototype.preview); return result; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx index c2ceab8f24d6..95057cd0c638 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx @@ -138,12 +138,14 @@ const mapDispatchToProps = { class OpenCVControlComponent extends React.PureComponent { private activeTool: IntelligentScissors | null; private latestPoints: number[]; + private latestPostponedEvent: Event | null; public constructor(props: Props & DispatchToProps) { super(props); const { labels, defaultApproxPolyAccuracy } = props; this.activeTool = null; this.latestPoints = []; + this.latestPostponedEvent = null; this.state = { libraryInitialized: openCVWrapper.isInitialized, @@ -161,6 +163,8 @@ class OpenCVControlComponent extends React.PureComponent shape.trackerModel.delete()); @@ -368,21 +374,36 @@ class OpenCVControlComponent extends React.PureComponent { + private onChangeToolsBlockerState = (): void => { const { - isActivated, toolsBlockerState, onSwitchToolsBlockerState, canvasInstance, + toolsBlockerState, canvasInstance, + isActivated, onSwitchToolsBlockerState, } = this.props; - if (isActivated && event === 'keyup') { - onSwitchToolsBlockerState({ algorithmsLocked: !toolsBlockerState.algorithmsLocked }); + + if (isActivated) { + const isLocked = !toolsBlockerState.algorithmsLocked; + onSwitchToolsBlockerState({ algorithmsLocked: isLocked }); + + if (isLocked) { + this.latestPostponedEvent = null; + } else if (this.latestPostponedEvent) { + this.onInteraction(this.latestPostponedEvent); + } + canvasInstance.interact({ enabled: true, - crosshair: toolsBlockerState.algorithmsLocked, - enableThreshold: toolsBlockerState.algorithmsLocked, - onChangeToolsBlockerState: this.onChangeToolsBlockerState, + crosshair: !isLocked, + enableThreshold: !isLocked, }); } }; + private onKeyUp = (e: KeyboardEvent): void => { + if (e.key === 'Control') { + this.onChangeToolsBlockerState(); + } + }; + private applyTracking = (imageData: ImageData, shape: TrackedShape, objectState: any): Promise => new Promise((resolve, reject) => { setTimeout(() => { @@ -580,8 +601,7 @@ class OpenCVControlComponent extends React.PureComponent { this.setState({ mode: 'interaction' }); - this.activeTool = openCVWrapper.segmentation - .intelligentScissorsFactory(this.onChangeToolsBlockerState); + this.activeTool = openCVWrapper.segmentation.intelligentScissorsFactory(); canvasInstance.cancel(); const interactorParameters = this.activeTool.params.canvas; diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx index 30ba6cf8b448..90398ca2f053 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx @@ -219,6 +219,7 @@ export class ToolsControlComponent extends React.PureComponent { points: [number, number][]; bounds?: [number, number, number, number]; }; + latestPostponedEvent: Event | null; lastestApproximatedPoints: number[][]; latestRequest: null | { interactor: MLModel; @@ -251,6 +252,7 @@ export class ToolsControlComponent extends React.PureComponent { this.interaction = { id: null, isAborted: false, + latestPostponedEvent: null, latestResponse: { rle: [], points: [], @@ -270,6 +272,9 @@ export class ToolsControlComponent extends React.PureComponent { this.setState({ portals: this.collectTrackerPortals(), }); + + window.document.addEventListener('keydown', this.onKeyDown); + window.document.addEventListener('keyup', this.onKeyUp); canvasInstance.html().addEventListener('canvas.interacted', this.interactionListener); canvasInstance.html().addEventListener('canvas.canceled', this.cancelListener); } @@ -298,6 +303,7 @@ export class ToolsControlComponent extends React.PureComponent { this.interaction = { id: null, isAborted: false, + latestPostponedEvent: null, latestResponse: { rle: [], points: [] }, lastestApproximatedPoints: [], latestRequest: null, @@ -322,7 +328,6 @@ export class ToolsControlComponent extends React.PureComponent { shapeType: ShapeType.POLYGON, points: this.interaction.lastestApproximatedPoints.flat(), }, - onChangeToolsBlockerState: this.onChangeToolsBlockerState, }); }); } @@ -334,6 +339,8 @@ export class ToolsControlComponent extends React.PureComponent { public componentWillUnmount(): void { const { canvasInstance } = this.props; onRemoveAnnotations(null); + window.document.removeEventListener('keydown', this.onKeyDown); + window.document.removeEventListener('keyup', this.onKeyUp); canvasInstance.html().removeEventListener('canvas.interacted', this.interactionListener); canvasInstance.html().removeEventListener('canvas.canceled', this.cancelListener); } @@ -436,7 +443,6 @@ export class ToolsControlComponent extends React.PureComponent { points: convertMasksToPolygons ? this.interaction.lastestApproximatedPoints.flat() : this.interaction.latestResponse.rle, }, - onChangeToolsBlockerState: this.onChangeToolsBlockerState, }); } @@ -545,9 +551,15 @@ export class ToolsControlComponent extends React.PureComponent { }; private interactionListener = async (e: Event): Promise => { + const { toolsBlockerState } = this.props; const { mode } = this.state; if (mode === 'interaction') { + if (toolsBlockerState.algorithmsLocked) { + this.interaction.latestPostponedEvent = e; + return; + } + await this.onInteraction(e); } @@ -582,9 +594,25 @@ export class ToolsControlComponent extends React.PureComponent { private onChangeToolsBlockerState = (event: string): void => { const { isActivated, onSwitchToolsBlockerState } = this.props; if (isActivated && event === 'keydown') { + this.interaction.latestPostponedEvent = null; onSwitchToolsBlockerState({ algorithmsLocked: true }); } else if (isActivated && event === 'keyup') { onSwitchToolsBlockerState({ algorithmsLocked: false }); + if (this.interaction.latestPostponedEvent) { + this.onInteraction(this.interaction.latestPostponedEvent); + } + } + }; + + private onKeyUp = (e: KeyboardEvent): void => { + if (e.key === 'Control') { + this.onChangeToolsBlockerState('keyup'); + } + }; + + private onKeyDown = (e: KeyboardEvent): void => { + if (!e.repeat && e.key === 'Control') { + this.onChangeToolsBlockerState('keydown'); } }; @@ -1141,10 +1169,7 @@ export class ToolsControlComponent extends React.PureComponent { onClick={() => { if (activeInteractor && activeLabelID && labels.length) { this.setState({ mode: 'interaction' }); - canvasInstance.cancel(); - activeInteractor.onChangeToolsBlockerState = this.onChangeToolsBlockerState; - const interactorParameters = { ...omit(activeInteractor.params.canvas, 'startWithBoxOptional'), // replace 'optional' with true or false depending on user specified setting diff --git a/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts b/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts index a73f8b389116..2f89c353d1e5 100644 --- a/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts +++ b/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts @@ -14,7 +14,6 @@ export interface IntelligentScissorsParams { enableSliding: boolean; allowRemoveOnlyLast: boolean; minPosVertices: number; - onChangeToolsBlockerState: (event:string)=>void; }; } @@ -38,7 +37,6 @@ function applyOffset(points: Point[], offsetX: number, offsetY: number): Point[] export default class IntelligentScissorsImplementation implements IntelligentScissors { public kind = 'opencv_intelligent_scissors'; private cv: any; - private onChangeToolsBlockerState: (event:string)=>void; private scissors: { tool: any; state: { @@ -55,9 +53,8 @@ export default class IntelligentScissorsImplementation implements IntelligentSci }; }; - public constructor(cv: any, onChangeToolsBlockerState:(event:string)=>void) { + public constructor(cv: any) { this.cv = cv; - this.onChangeToolsBlockerState = onChangeToolsBlockerState; this.reset(); } @@ -180,7 +177,6 @@ export default class IntelligentScissorsImplementation implements IntelligentSci enableSliding: true, allowRemoveOnlyLast: true, minPosVertices: 1, - onChangeToolsBlockerState: this.onChangeToolsBlockerState, }, }; } diff --git a/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts b/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts index 4e2f3ea57f48..0daf0670957a 100644 --- a/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts +++ b/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts @@ -14,7 +14,7 @@ import { OpenCVTracker } from './opencv-interfaces'; const core = getCore(); export interface Segmentation { - intelligentScissorsFactory: (onChangeToolsBlockerState:(event:string)=>void) => IntelligentScissors; + intelligentScissorsFactory: () => IntelligentScissors; } export interface MatSpace { @@ -291,9 +291,7 @@ export class OpenCVWrapper { public get segmentation(): Segmentation { this.checkInitialization(); return { - intelligentScissorsFactory: - (onChangeToolsBlockerState: - (event:string)=>void) => new IntelligentScissorsImplementation(this.cv, onChangeToolsBlockerState), + intelligentScissorsFactory: () => new IntelligentScissorsImplementation(this.cv), }; } From dcee69f10a98e8dbdf1f734909f6465ec77ea9b4 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:22:17 +0300 Subject: [PATCH 2/8] v2.20.8 --- cvat-canvas/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index 3db518447347..5dc500eb6eed 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.20.7", + "version": "2.20.8", "type": "module", "description": "Part of Computer Vision Annotation Tool which presents its canvas library", "main": "src/canvas.ts", From 6b103f69856bf9fa606be08d1c5376bf510c3024 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:22:23 +0300 Subject: [PATCH 3/8] v15.1.1 --- cvat-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-core/package.json b/cvat-core/package.json index 030b2cb0e497..a93411284bc1 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "15.1.0", + "version": "15.1.1", "type": "module", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "src/api.ts", From 08abccdf842690c757f156cdfa119c7c9fa9088f Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:22:34 +0300 Subject: [PATCH 4/8] v1.64.5 --- cvat-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-ui/package.json b/cvat-ui/package.json index af9c203ca985..ffbc6f08b7fd 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.64.4", + "version": "1.64.5", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From 3dddffa5132303b743e580bdc0a9a944bf09ae8e Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:24:04 +0300 Subject: [PATCH 5/8] Updated license headers --- cvat-canvas/src/typescript/interactionHandler.ts | 2 +- cvat-core/src/core-types.ts | 2 +- cvat-core/src/ml-model.ts | 2 +- cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts | 1 + cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cvat-canvas/src/typescript/interactionHandler.ts b/cvat-canvas/src/typescript/interactionHandler.ts index aaa5a29624e0..8c1dbf58ac9f 100644 --- a/cvat-canvas/src/typescript/interactionHandler.ts +++ b/cvat-canvas/src/typescript/interactionHandler.ts @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2023 CVAT.ai Corporation +// Copyright (C) 2023-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT diff --git a/cvat-core/src/core-types.ts b/cvat-core/src/core-types.ts index 4b5a130f4d39..e44a354cb5bd 100644 --- a/cvat-core/src/core-types.ts +++ b/cvat-core/src/core-types.ts @@ -1,4 +1,4 @@ -// Copyright (C) 2023 CVAT.ai Corporation +// Copyright (C) 2023-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT diff --git a/cvat-core/src/ml-model.ts b/cvat-core/src/ml-model.ts index ac128f5396fd..787277cf5593 100644 --- a/cvat-core/src/ml-model.ts +++ b/cvat-core/src/ml-model.ts @@ -1,5 +1,5 @@ // Copyright (C) 2019-2022 Intel Corporation -// Copyright (C) 2022-2023 CVAT.ai Corporation +// Copyright (C) 2022-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT diff --git a/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts b/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts index 2f89c353d1e5..cf05ddb72cb3 100644 --- a/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts +++ b/cvat-ui/src/utils/opencv-wrapper/intelligent-scissors.ts @@ -1,4 +1,5 @@ // Copyright (C) 2021-2022 Intel Corporation +// Copyright (C) 2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT diff --git a/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts b/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts index 0daf0670957a..b2d045c32483 100644 --- a/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts +++ b/cvat-ui/src/utils/opencv-wrapper/opencv-wrapper.ts @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2023 CVAT.ai Corporation +// Copyright (C) 2023-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT From 8aaabe3ddd04e4f5621920d8602ab15fd65623c4 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:29:09 +0300 Subject: [PATCH 6/8] Minor issue --- cvat-canvas/src/typescript/interactionHandler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cvat-canvas/src/typescript/interactionHandler.ts b/cvat-canvas/src/typescript/interactionHandler.ts index 8c1dbf58ac9f..9e9508ee9552 100644 --- a/cvat-canvas/src/typescript/interactionHandler.ts +++ b/cvat-canvas/src/typescript/interactionHandler.ts @@ -74,6 +74,7 @@ export class InteractionHandlerImpl implements InteractionHandler { (shape: SVG.Shape): boolean => (shape as any).attr('stroke') !== 'green', ); + const somethingWasDrawn = interactionShapes.some((shape) => shape.type === 'rect') || positiveShapes.length; if (interactionData.shapeType === 'rectangle') { return enabled && !!interactionShapes.length; } @@ -83,7 +84,7 @@ export class InteractionHandlerImpl implements InteractionHandler { const minPosVerticesAchieved = !minPosVerticesDefined || minPosVertices <= positiveShapes.length; const minNegVerticesAchieved = !minNegVerticesDefined || minNegVertices <= negativeShapes.length; const minimumVerticesAchieved = minPosVerticesAchieved && minNegVerticesAchieved; - return enabled && positiveShapes.length && minimumVerticesAchieved && shapesWereUpdated; + return enabled && somethingWasDrawn && minimumVerticesAchieved && shapesWereUpdated; } private addThreshold(): void { From a20b4d61b00a5b1709459b9d0f786a5b4c003883 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 14:32:40 +0300 Subject: [PATCH 7/8] Minor refactoring --- .../controls-side-bar/tools-control.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx index 90398ca2f053..7e7c0eb41d65 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx @@ -593,13 +593,17 @@ export class ToolsControlComponent extends React.PureComponent { private onChangeToolsBlockerState = (event: string): void => { const { isActivated, onSwitchToolsBlockerState } = this.props; - if (isActivated && event === 'keydown') { - this.interaction.latestPostponedEvent = null; - onSwitchToolsBlockerState({ algorithmsLocked: true }); - } else if (isActivated && event === 'keyup') { - onSwitchToolsBlockerState({ algorithmsLocked: false }); - if (this.interaction.latestPostponedEvent) { - this.onInteraction(this.interaction.latestPostponedEvent); + const { mode } = this.state; + + if (isActivated && mode === 'interaction') { + if (event === 'keydown') { + this.interaction.latestPostponedEvent = null; + onSwitchToolsBlockerState({ algorithmsLocked: true }); + } else if (event === 'keyup') { + onSwitchToolsBlockerState({ algorithmsLocked: false }); + if (this.interaction.latestPostponedEvent) { + this.onInteraction(this.interaction.latestPostponedEvent); + } } } }; From ea93bf234aa67ab1959d6b992df25e3cf12c0915 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 12 Aug 2024 15:53:47 +0300 Subject: [PATCH 8/8] Removed extra code --- cvat-canvas/src/typescript/interactionHandler.ts | 2 +- .../controls-side-bar/opencv-control.tsx | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/cvat-canvas/src/typescript/interactionHandler.ts b/cvat-canvas/src/typescript/interactionHandler.ts index 9e9508ee9552..90e8f57d6d35 100644 --- a/cvat-canvas/src/typescript/interactionHandler.ts +++ b/cvat-canvas/src/typescript/interactionHandler.ts @@ -467,7 +467,7 @@ export class InteractionHandlerImpl implements InteractionHandler { }); this.canvas.on('wheel.interaction', (e: WheelEvent): void => { - if (e.altKey || e.ctrlKey) { + if (e.altKey) { e.stopPropagation(); e.preventDefault(); if (this.threshold) { diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx index 95057cd0c638..df3b2400f1bb 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/opencv-control.tsx @@ -138,14 +138,12 @@ const mapDispatchToProps = { class OpenCVControlComponent extends React.PureComponent { private activeTool: IntelligentScissors | null; private latestPoints: number[]; - private latestPostponedEvent: Event | null; public constructor(props: Props & DispatchToProps) { super(props); const { labels, defaultApproxPolyAccuracy } = props; this.activeTool = null; this.latestPoints = []; - this.latestPostponedEvent = null; this.state = { libraryInitialized: openCVWrapper.isInitialized, @@ -383,13 +381,6 @@ class OpenCVControlComponent extends React.PureComponent