From 5dc52f94a2e3b92a0c4f68783f9dea33a67188f0 Mon Sep 17 00:00:00 2001 From: Boris Sekachev <40690378+bsekachev@users.noreply.github.com> Date: Fri, 28 Feb 2020 19:56:38 +0300 Subject: [PATCH] React UI: Batch of fixes (#1211) * Disabled tracks for polyshapes in UI * RectDrawingMethod enum pushed to cvat-canvas, fixed some code issues * Optional arguments * Draw a text for locked shapes, some fixes with not keyframe shapes * Fixed zooming & batch grouping * Reset zoom for tasks with images * Fixed putting shapes out of canvas * Fixed grid opacity, little refactoring of componentDidUpdate in canvas-wrapper component * Fixed corner cases for drawing * Fixed putting shapes out of canvas * Improved drawing * Removed extra event handler --- cvat-canvas/README.md | 8 +- cvat-canvas/src/typescript/canvas.ts | 2 + cvat-canvas/src/typescript/canvasModel.ts | 8 +- cvat-canvas/src/typescript/canvasView.ts | 39 ++++--- cvat-canvas/src/typescript/consts.ts | 2 +- cvat-canvas/src/typescript/drawHandler.ts | 109 +++++++----------- cvat-ui/src/actions/annotation-actions.ts | 3 +- .../standard-workspace/canvas-wrapper.tsx | 42 ++----- .../controls-side-bar/draw-shape-popover.tsx | 16 +-- .../controls-side-bar/draw-shape-popover.tsx | 22 ++-- cvat-ui/src/cvat-canvas.ts | 2 + cvat-ui/src/reducers/interfaces.ts | 7 +- cvat-ui/src/reducers/settings-reducer.ts | 14 ++- 13 files changed, 127 insertions(+), 147 deletions(-) diff --git a/cvat-canvas/README.md b/cvat-canvas/README.md index 38806d24..fe216817 100644 --- a/cvat-canvas/README.md +++ b/cvat-canvas/README.md @@ -37,10 +37,15 @@ Canvas itself handles: CLOCKWISE90, } + enum RectDrawingMethod { + CLASSIC = 'By 2 points', + EXTREME_POINTS = 'By 4 points' + } + interface DrawData { enabled: boolean; shapeType?: string; - rectDrawingMethod?: string; + rectDrawingMethod?: RectDrawingMethod; numberOfPoints?: number; initialState?: any; crosshair?: boolean; @@ -147,6 +152,7 @@ Standard JS events are used. enabled: true, shapeType: 'rectangle', crosshair: true, + rectDrawingMethod: window.Canvas.RectDrawingMethod.CLASSIC, }); ``` diff --git a/cvat-canvas/src/typescript/canvas.ts b/cvat-canvas/src/typescript/canvas.ts index 4ddb2deb..66af0ce8 100644 --- a/cvat-canvas/src/typescript/canvas.ts +++ b/cvat-canvas/src/typescript/canvas.ts @@ -10,6 +10,7 @@ import { GroupData, CanvasModel, CanvasModelImpl, + RectDrawingMethod, } from './canvasModel'; import { @@ -141,4 +142,5 @@ export { CanvasImpl as Canvas, Rotation, CanvasVersion, + RectDrawingMethod, }; diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index 28a0a48f..1fc273a6 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -4,7 +4,6 @@ import { MasterImpl } from './master'; - export interface Size { width: number; height: number; @@ -36,10 +35,15 @@ export interface ActiveElement { attributeID: number | null; } +export enum RectDrawingMethod { + CLASSIC = 'By 2 points', + EXTREME_POINTS = 'By 4 points' +} + export interface DrawData { enabled: boolean; shapeType?: string; - rectDrawingMethod?: string; + rectDrawingMethod?: RectDrawingMethod; numberOfPoints?: number; initialState?: any; crosshair?: boolean; diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 808b8a17..4ce4c536 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -106,11 +106,10 @@ export class CanvasViewImpl implements CanvasView, Listener { this.geometry, ); } else { + this.mode = Mode.IDLE; this.controller.draw({ enabled: false, }); - - this.mode = Mode.IDLE; } } @@ -551,7 +550,8 @@ export class CanvasViewImpl implements CanvasView, Listener { this.grid.setAttribute('version', '2'); this.gridPath.setAttribute('d', 'M 1000 0 L 0 0 0 1000'); this.gridPath.setAttribute('fill', 'none'); - this.gridPath.setAttribute('stroke-width', '1.5'); + this.gridPath.setAttribute('stroke-width', `${consts.BASE_GRID_WIDTH}`); + this.gridPath.setAttribute('opacity', 'inherit'); this.gridPattern.setAttribute('id', 'cvat_canvas_grid_pattern'); this.gridPattern.setAttribute('width', '100'); this.gridPattern.setAttribute('height', '100'); @@ -626,7 +626,9 @@ export class CanvasViewImpl implements CanvasView, Listener { this.content.addEventListener('mousedown', (event): void => { if ([1, 2].includes(event.which)) { - self.controller.enableDrag(event.clientX, event.clientY); + if (![Mode.ZOOM_CANVAS, Mode.GROUP].includes(this.mode) || event.which === 2) { + self.controller.enableDrag(event.clientX, event.clientY); + } event.preventDefault(); } }); @@ -760,13 +762,16 @@ export class CanvasViewImpl implements CanvasView, Listener { } } else if (reason === UpdateReasons.DRAW) { const data: DrawData = this.controller.drawData; - if (data.enabled) { + if (data.enabled && this.mode === Mode.IDLE) { this.canvas.style.cursor = 'crosshair'; this.mode = Mode.DRAW; + this.drawHandler.draw(data, this.geometry); } else { this.canvas.style.cursor = ''; + if (this.mode !== Mode.IDLE) { + this.drawHandler.draw(data, this.geometry); + } } - this.drawHandler.draw(data, this.geometry); } else if (reason === UpdateReasons.MERGE) { const data: MergeData = this.controller.mergeData; if (data.enabled) { @@ -1060,24 +1065,18 @@ export class CanvasViewImpl implements CanvasView, Listener { const [state] = this.controller.objects .filter((_state: any): boolean => _state.clientID === clientID); - if (!state) { - return; - } - - if (state.shapeType === 'points') { + if (state && state.shapeType === 'points') { this.svgShapes[clientID].remember('_selectHandler').nested .style('pointer-events', state.lock ? 'none' : ''); } - if (state.hidden || state.lock) { + if (!state || state.hidden || state.outside) { return; } this.activeElement = { ...activeElement }; const shape = this.svgShapes[clientID]; - shape.addClass('cvat_canvas_shape_activated'); let text = this.svgTexts[clientID]; - // Draw text if it's hidden by default if (!text) { text = this.addText(state); this.svgTexts[state.clientID] = text; @@ -1087,7 +1086,11 @@ export class CanvasViewImpl implements CanvasView, Listener { ); } - const self = this; + if (state.lock) { + return; + } + + shape.addClass('cvat_canvas_shape_activated'); if (state.shapeType === 'points') { this.content.append(this.svgShapes[clientID] .remember('_selectHandler').nested.node); @@ -1103,7 +1106,7 @@ export class CanvasViewImpl implements CanvasView, Listener { }).on('dragend', (e: CustomEvent): void => { if (text) { text.removeClass('cvat_canvas_hidden'); - self.updateTextPosition( + this.updateTextPosition( text, shape, ); @@ -1122,6 +1125,7 @@ export class CanvasViewImpl implements CanvasView, Listener { + `${shape.attr('y') + shape.attr('height')}`, ).map((x: number): number => x - offset); + this.drawnStates[state.clientID].points = points; this.onEditDone(state, points); } }); @@ -1153,7 +1157,7 @@ export class CanvasViewImpl implements CanvasView, Listener { if (text) { text.removeClass('cvat_canvas_hidden'); - self.updateTextPosition( + this.updateTextPosition( text, shape, ); @@ -1170,6 +1174,7 @@ export class CanvasViewImpl implements CanvasView, Listener { + `${shape.attr('y') + shape.attr('height')}`, ).map((x: number): number => x - offset); + this.drawnStates[state.clientID].points = points; this.onEditDone(state, points); } }); diff --git a/cvat-canvas/src/typescript/consts.ts b/cvat-canvas/src/typescript/consts.ts index 6b1ab234..1c36351d 100644 --- a/cvat-canvas/src/typescript/consts.ts +++ b/cvat-canvas/src/typescript/consts.ts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT const BASE_STROKE_WIDTH = 1.75; -const BASE_GRID_WIDTH = 1; +const BASE_GRID_WIDTH = 2; const BASE_POINT_SIZE = 5; const TEXT_MARGIN = 10; const AREA_THRESHOLD = 9; diff --git a/cvat-canvas/src/typescript/drawHandler.ts b/cvat-canvas/src/typescript/drawHandler.ts index 2a17b0a4..2413368f 100644 --- a/cvat-canvas/src/typescript/drawHandler.ts +++ b/cvat-canvas/src/typescript/drawHandler.ts @@ -10,6 +10,7 @@ import './svg.patch'; import { DrawData, Geometry, + RectDrawingMethod, } from './canvasModel'; import { @@ -43,6 +44,7 @@ export class DrawHandlerImpl implements DrawHandler { // we should use any instead of SVG.Shape because svg plugins cannot change declared interface // so, methods like draw() just undefined for SVG.Shape, but nevertheless they exist private drawInstance: any; + private initialized: boolean; private pointsGroup: SVG.G | null; private shapeSizeElement: ShapeSizeElement; @@ -113,6 +115,12 @@ export class DrawHandlerImpl implements DrawHandler { } private release(): void { + if (!this.initialized) { + // prevents recursive calls + return; + } + + this.initialized = false; this.canvas.off('mousedown.draw'); this.canvas.off('mouseup.draw'); this.canvas.off('mousemove.draw'); @@ -123,18 +131,21 @@ export class DrawHandlerImpl implements DrawHandler { this.pointsGroup = null; } - if (this.drawInstance) { - // Draw plugin isn't activated when draw from initialState - // So, we don't need to use any draw events - if (!this.drawData.initialState) { - this.drawInstance.off('drawdone'); - this.drawInstance.off('drawstop'); - this.drawInstance.draw('stop'); + // Draw plugin in some cases isn't activated + // For example when draw from initialState + // Or when no drawn points, but we call cancel() drawing + // We check if it is activated with remember function + if (this.drawInstance.remember('_paintHandler')) { + if (this.drawData.shapeType !== 'rectangle') { + // Check for unsaved drawn shapes + this.drawInstance.draw('done'); } - - this.drawInstance.remove(); - this.drawInstance = null; + // Clear drawing + this.drawInstance.draw('stop'); } + this.drawInstance.off(); + this.drawInstance.remove(); + this.drawInstance = null; if (this.shapeSizeElement) { this.shapeSizeElement.rm(); @@ -152,45 +163,19 @@ export class DrawHandlerImpl implements DrawHandler { } } - private closeDrawing(): void { - if (this.drawInstance) { - // Draw plugin isn't activated when draw from initialState - // So, we don't need to use any draw events - if (!this.drawData.initialState) { - const { drawInstance } = this; - this.drawInstance = null; - if (this.drawData.shapeType === 'rectangle' - && this.drawData.rectDrawingMethod !== 'by_four_points') { - drawInstance.draw('cancel'); - } else { - drawInstance.draw('done'); - } - this.drawInstance = drawInstance; - this.release(); - } else { - this.release(); - this.onDrawDone(null); - } - - // here is a cycle - // onDrawDone => controller => model => view => closeDrawing - // one call of closeDrawing is unuseful, but it's okey - } - } - private drawBox(): void { this.drawInstance = this.canvas.rect(); this.drawInstance.on('drawstop', (e: Event): void => { const bbox = (e.target as SVGRectElement).getBBox(); const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox); + const { shapeType } = this.drawData; + this.cancel(); if ((xbr - xtl) * (ybr - ytl) >= consts.AREA_THRESHOLD) { this.onDrawDone({ - shapeType: this.drawData.shapeType, + shapeType, points: [xtl, ytl, xbr, ybr], }); - } else { - this.onDrawDone(null); } }).on('drawupdate', (): void => { this.shapeSizeElement.update(this.drawInstance); @@ -206,10 +191,10 @@ export class DrawHandlerImpl implements DrawHandler { .addClass('cvat_canvas_shape_drawing').attr({ 'stroke-width': 0, opacity: 0, - }).on('drawstart', () => { + }).on('drawstart', (): void => { // init numberOfPoints as one on drawstart numberOfPoints = 1; - }).on('drawpoint', (e: CustomEvent) => { + }).on('drawpoint', (e: CustomEvent): void => { // increase numberOfPoints by one on drawpoint numberOfPoints += 1; @@ -217,23 +202,20 @@ export class DrawHandlerImpl implements DrawHandler { if (numberOfPoints === 4) { const bbox = (e.target as SVGPolylineElement).getBBox(); const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox); + const { shapeType } = this.drawData; + this.cancel(); if ((xbr - xtl) * (ybr - ytl) >= consts.AREA_THRESHOLD) { this.onDrawDone({ - shapeType: this.drawData.shapeType, + shapeType, points: [xtl, ytl, xbr, ybr], }); - } else { - this.onDrawDone(null); } } - }).on('undopoint', () => { + }).on('undopoint', (): void => { if (numberOfPoints > 0) { numberOfPoints -= 1; } - }).off('drawdone').on('drawdone', () => { - // close drawing mode without drawing rect - this.onDrawDone(null); }); this.drawPolyshape(); @@ -308,34 +290,31 @@ export class DrawHandlerImpl implements DrawHandler { this.drawInstance.on('drawdone', (e: CustomEvent): void => { const targetPoints = pointsToArray((e.target as SVGElement).getAttribute('points')); - const { - points, - box, - } = this.getFinalPolyshapeCoordinates(targetPoints); + const { points, box } = this.getFinalPolyshapeCoordinates(targetPoints); + const { shapeType } = this.drawData; + this.cancel(); - if (this.drawData.shapeType === 'polygon' + if (shapeType === 'polygon' && ((box.xbr - box.xtl) * (box.ybr - box.ytl) >= consts.AREA_THRESHOLD) && points.length >= 3 * 2) { this.onDrawDone({ - shapeType: this.drawData.shapeType, + shapeType, points, }); - } else if (this.drawData.shapeType === 'polyline' + } else if (shapeType === 'polyline' && ((box.xbr - box.xtl) >= consts.SIZE_THRESHOLD || (box.ybr - box.ytl) >= consts.SIZE_THRESHOLD) && points.length >= 2 * 2) { this.onDrawDone({ - shapeType: this.drawData.shapeType, + shapeType, points, }); - } else if (this.drawData.shapeType === 'points' + } else if (shapeType === 'points' && (e.target as any).getAttribute('points') !== '0,0') { this.onDrawDone({ - shapeType: this.drawData.shapeType, + shapeType, points, }); - } else { - this.onDrawDone(null); } }); } @@ -578,7 +557,7 @@ export class DrawHandlerImpl implements DrawHandler { this.setupPasteEvents(); } else { if (this.drawData.shapeType === 'rectangle') { - if (this.drawData.rectDrawingMethod === 'by_four_points') { + if (this.drawData.rectDrawingMethod === RectDrawingMethod.EXTREME_POINTS) { // draw box by extreme clicking this.drawBoxBy4Points(); } else { @@ -596,6 +575,8 @@ export class DrawHandlerImpl implements DrawHandler { } this.setupDrawEvents(); } + + this.initialized = true; } public constructor( @@ -606,6 +587,7 @@ export class DrawHandlerImpl implements DrawHandler { this.onDrawDone = onDrawDone; this.canvas = canvas; this.text = text; + this.initialized = false; this.drawData = null; this.geometry = null; this.crosshair = null; @@ -686,7 +668,7 @@ export class DrawHandlerImpl implements DrawHandler { this.initDrawing(); this.startDraw(); } else { - this.closeDrawing(); + this.cancel(); this.drawData = drawData; } } @@ -694,8 +676,5 @@ export class DrawHandlerImpl implements DrawHandler { public cancel(): void { this.release(); this.onDrawDone(null); - // here is a cycle - // onDrawDone => controller => model => view => closeDrawing - // one call of closeDrawing is unuseful, but it's okey } } diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index 759d92be..62c95586 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -20,6 +20,7 @@ import { } from 'reducers/interfaces'; import getCore from 'cvat-core'; +import { RectDrawingMethod } from 'cvat-canvas'; import { getCVATStore } from 'cvat-store'; const cvat = getCore(); @@ -807,7 +808,7 @@ export function drawShape( labelID: number, objectType: ObjectType, points?: number, - rectDrawingMethod?: string, + rectDrawingMethod?: RectDrawingMethod, ): AnyAction { let activeControl = ActiveControl.DRAW_RECTANGLE; if (shapeType === ShapeType.POLYGON) { diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx index fbcb5077..d95b901a 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-wrapper.tsx @@ -100,10 +100,6 @@ export default class CanvasWrapperComponent extends React.PureComponent { colorBy, selectedOpacity, blackBorders, - grid, - gridSize, - gridColor, - gridOpacity, frameData, annotations, canvasInstance, @@ -122,34 +118,12 @@ export default class CanvasWrapperComponent extends React.PureComponent { } } - if (prevProps.grid !== grid) { - const gridElement = window.document.getElementById('cvat_canvas_grid'); - if (gridElement) { - gridElement.style.display = grid ? 'block' : 'none'; - } - } - - if (prevProps.gridSize !== gridSize) { - canvasInstance.grid(gridSize, gridSize); - } - - if (prevProps.gridColor !== gridColor) { - const gridPattern = window.document.getElementById('cvat_canvas_grid_pattern'); - if (gridPattern) { - gridPattern.style.stroke = gridColor.toLowerCase(); - } - } - - if (prevProps.gridOpacity !== gridOpacity) { - const gridPattern = window.document.getElementById('cvat_canvas_grid_pattern'); - if (gridPattern) { - gridPattern.style.opacity = `${gridOpacity / 100}`; - } - } - if (prevProps.activatedStateID !== null && prevProps.activatedStateID !== activatedStateID) { canvasInstance.activate(null); + } + + if (activatedStateID) { const el = window.document.getElementById(`cvat_canvas_shape_${prevProps.activatedStateID}`); if (el) { (el as any).instance.fill({ opacity: opacity / 100 }); @@ -160,17 +134,17 @@ export default class CanvasWrapperComponent extends React.PureComponent { this.updateCanvas(); } - if (prevProps.opacity !== opacity || prevProps.blackBorders !== blackBorders - || prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy) { - this.updateShapesView(); - } - if (prevProps.frame !== frameData.number && resetZoom) { canvasInstance.html().addEventListener('canvas.setup', () => { canvasInstance.fit(); }, { once: true }); } + if (prevProps.opacity !== opacity || prevProps.blackBorders !== blackBorders + || prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy) { + this.updateShapesView(); + } + if (prevProps.curZLayer !== curZLayer) { canvasInstance.setZLayer(curZLayer); } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx index 769b5d14..9ee0f8a9 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx @@ -16,16 +16,14 @@ import { import { RadioChangeEvent } from 'antd/lib/radio'; import Text from 'antd/lib/typography/Text'; -import { - ShapeType, - RectDrawingMethod, -} from 'reducers/interfaces'; +import { RectDrawingMethod } from 'cvat-canvas'; +import { ShapeType } from 'reducers/interfaces'; interface Props { shapeType: ShapeType; - rectDrawingMethod: RectDrawingMethod; labels: any[]; minimumPoints: number; + rectDrawingMethod?: RectDrawingMethod; numberOfPoints?: number; selectedLabeID: number; onChangeLabel(value: string): void; @@ -42,6 +40,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element { minimumPoints, selectedLabeID, numberOfPoints, + rectDrawingMethod, onDrawTrack, onDrawShape, onChangeLabel, @@ -92,17 +91,17 @@ function DrawShapePopoverComponent(props: Props): JSX.Element { By 2 Points By 4 Points @@ -139,6 +138,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element { diff --git a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx index edea8b3e..8d418e68 100644 --- a/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx +++ b/cvat-ui/src/containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover.tsx @@ -10,13 +10,12 @@ import { CombinedState, ShapeType, ObjectType, - RectDrawingMethod, } from 'reducers/interfaces'; import { drawShape, } from 'actions/annotation-actions'; -import { Canvas } from 'cvat-canvas'; +import { Canvas, RectDrawingMethod } from 'cvat-canvas'; import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; interface OwnProps { @@ -29,7 +28,7 @@ interface DispatchToProps { labelID: number, objectType: ObjectType, points?: number, - rectDrawingMethod?: string, + rectDrawingMethod?: RectDrawingMethod, ): void; } @@ -46,7 +45,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { labelID: number, objectType: ObjectType, points?: number, - rectDrawingMethod?: string, + rectDrawingMethod?: RectDrawingMethod, ): void { dispatch(drawShape(shapeType, labelID, objectType, points, rectDrawingMethod)); }, @@ -75,7 +74,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps { type Props = StateToProps & DispatchToProps; interface State { - rectDrawingMethod?: string; + rectDrawingMethod?: RectDrawingMethod; numberOfPoints?: number; selectedLabelID: number; } @@ -85,13 +84,15 @@ class DrawShapePopoverContainer extends React.PureComponent { constructor(props: Props) { super(props); + const { shapeType } = props; const defaultLabelID = props.labels[0].id; - const defaultRectDrawingMethod = RectDrawingMethod.BY_TWO_POINTS; + const defaultRectDrawingMethod = RectDrawingMethod.CLASSIC; this.state = { selectedLabelID: defaultLabelID, + rectDrawingMethod: shapeType === ShapeType.RECTANGLE + ? defaultRectDrawingMethod : undefined, }; - const { shapeType } = props; if (shapeType === ShapeType.POLYGON) { this.minimumPoints = 3; } @@ -101,9 +102,6 @@ class DrawShapePopoverContainer extends React.PureComponent { if (shapeType === ShapeType.POINTS) { this.minimumPoints = 1; } - if (shapeType === ShapeType.RECTANGLE) { - this.state.rectDrawingMethod = defaultRectDrawingMethod; - } } private onDraw(objectType: ObjectType): void { @@ -129,7 +127,7 @@ class DrawShapePopoverContainer extends React.PureComponent { }); onDrawStart(shapeType, selectedLabelID, - objectType, numberOfPoints); + objectType, numberOfPoints, rectDrawingMethod); } private onChangeRectDrawingMethod = (event: RadioChangeEvent): void => { @@ -166,6 +164,7 @@ class DrawShapePopoverContainer extends React.PureComponent { public render(): JSX.Element { const { + rectDrawingMethod, selectedLabelID, numberOfPoints, } = this.state; @@ -182,6 +181,7 @@ class DrawShapePopoverContainer extends React.PureComponent { minimumPoints={this.minimumPoints} selectedLabeID={selectedLabelID} numberOfPoints={numberOfPoints} + rectDrawingMethod={rectDrawingMethod} onChangeLabel={this.onChangeLabel} onChangePoints={this.onChangePoints} onChangeRectDrawingMethod={this.onChangeRectDrawingMethod} diff --git a/cvat-ui/src/cvat-canvas.ts b/cvat-ui/src/cvat-canvas.ts index 399174d3..8ca0cd28 100644 --- a/cvat-ui/src/cvat-canvas.ts +++ b/cvat-ui/src/cvat-canvas.ts @@ -6,10 +6,12 @@ import { Canvas, Rotation, CanvasVersion, + RectDrawingMethod, } from '../../cvat-canvas/src/typescript/canvas'; export { Canvas, Rotation, CanvasVersion, + RectDrawingMethod, }; diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index dae5a267..caf814b5 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -import { Canvas } from 'cvat-canvas'; +import { Canvas, RectDrawingMethod } from 'cvat-canvas'; export type StringObject = { [index: string]: string; @@ -251,11 +251,6 @@ export enum ActiveControl { EDIT = 'edit', } -export enum RectDrawingMethod { - BY_TWO_POINTS = 'by_two_points', - BY_FOUR_POINTS = 'by_four_points' -} - export enum ShapeType { RECTANGLE = 'rectangle', POLYGON = 'polygon', diff --git a/cvat-ui/src/reducers/settings-reducer.ts b/cvat-ui/src/reducers/settings-reducer.ts index 90aacf75..c9f82e81 100644 --- a/cvat-ui/src/reducers/settings-reducer.ts +++ b/cvat-ui/src/reducers/settings-reducer.ts @@ -4,6 +4,7 @@ import { AnyAction } from 'redux'; import { SettingsActionTypes } from 'actions/settings-actions'; +import { AnnotationActionTypes } from 'actions/annotation-actions'; import { SettingsState, @@ -33,7 +34,7 @@ const defaultState: SettingsState = { grid: false, gridSize: 100, gridColor: GridColor.White, - gridOpacity: 0, + gridOpacity: 100, brightnessLevel: 100, contrastLevel: 100, saturationLevel: 100, @@ -213,6 +214,17 @@ export default (state = defaultState, action: AnyAction): SettingsState => { }, }; } + case AnnotationActionTypes.GET_JOB_SUCCESS: { + const { job } = action.payload; + + return { + ...state, + player: { + ...state.player, + resetZoom: job && job.task.mode === 'annotation', + }, + }; + } default: { return state; }