Skip to content

Commit

Permalink
refactored code, fixed issues
Browse files Browse the repository at this point in the history
  • Loading branch information
klakhov committed Oct 18, 2024
1 parent 0684a9a commit c6aecf3
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 102 deletions.
63 changes: 48 additions & 15 deletions cvat-canvas/src/typescript/drawHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as SVG from 'svg.js';
import 'svg.draw.js';
import './svg.patch';
import { CIRCLE_STROKE } from './svg.patch';

import { AutoborderHandler } from './autoborderHandler';
import {
Expand Down Expand Up @@ -104,6 +104,7 @@ export class DrawHandlerImpl implements DrawHandler {
private controlPointsSize: number;
private selectedShapeOpacity: number;
private outlinedBorders: string;
private isHidden: boolean;

// 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
Expand Down Expand Up @@ -579,7 +580,10 @@ export class DrawHandlerImpl implements DrawHandler {

this.drawInstance.on('drawstart', sizeDecrement);
this.drawInstance.on('drawpoint', sizeDecrement);
this.drawInstance.on('drawupdate', (): void => this.transform(this.geometry));
this.drawInstance.on('drawupdate', (): void => {
this.transform(this.geometry);
this.updateInnerCircles(!this.isHidden);
});
this.drawInstance.on('undopoint', (): number => size++);

// Add ability to cancel the latest drawn point
Expand Down Expand Up @@ -1276,6 +1280,7 @@ export class DrawHandlerImpl implements DrawHandler {
this.selectedShapeOpacity = configuration.selectedShapeOpacity;
this.outlinedBorders = configuration.outlinedBorders || 'black';
this.autobordersEnabled = false;
this.isHidden = false;
this.startTimestamp = Date.now();
this.onDrawDoneDefault = onDrawDone;
this.canvas = canvas;
Expand All @@ -1301,11 +1306,17 @@ export class DrawHandlerImpl implements DrawHandler {
});
}

public configurate(configuration: Configuration): void {
this.controlPointsSize = configuration.controlPointsSize;
this.selectedShapeOpacity = configuration.selectedShapeOpacity;
this.outlinedBorders = configuration.outlinedBorders || 'black';
private updateInnerCircles(shown: boolean) {

Check warning on line 1309 in cvat-canvas/src/typescript/drawHandler.ts

View workflow job for this annotation

GitHub Actions / Linter

Missing return type on function
const paintHandler = this.drawInstance.remember('_paintHandler');
if (paintHandler) {
for (const point of (paintHandler as any).set.members) {
point.attr('stroke', shown ? CIRCLE_STROKE : 'none');
point.fill({ opacity: shown ? 1 : 0 });
}
}
}

private updateDrawInstance(opacity: number) {

Check warning on line 1319 in cvat-canvas/src/typescript/drawHandler.ts

View workflow job for this annotation

GitHub Actions / Linter

Missing return type on function
const isFillableRect = this.drawData &&
this.drawData.shapeType === 'rectangle' &&
(this.drawData.rectDrawingMethod === RectDrawingMethod.CLASSIC || this.drawData.initialState);
Expand All @@ -1315,23 +1326,45 @@ export class DrawHandlerImpl implements DrawHandler {
const isFilalblePolygon = this.drawData && this.drawData.shapeType === 'polygon';

if (this.drawInstance && (isFillableRect || isFillableCuboid || isFilalblePolygon)) {
this.drawInstance.fill({ opacity: configuration.selectedShapeOpacity });
this.drawInstance.fill({ opacity });
}

if (this.drawInstance && this.drawInstance.attr('stroke')) {
this.drawInstance.attr('stroke', this.outlinedBorders);
this.drawInstance.attr('stroke', opacity ? this.outlinedBorders : 'none');
}

if (this.drawInstance && (isFilalblePolygon)) {
this.updateInnerCircles(!this.isHidden);
}

if (this.pointsGroup && this.pointsGroup.attr('stroke')) {
this.pointsGroup.attr('stroke', this.outlinedBorders);
this.pointsGroup.attr('stroke', opacity ? this.outlinedBorders : 'none');
}
}

this.autobordersEnabled = configuration.autoborders;
if (this.drawInstance && !this.drawData.initialState) {
if (this.autobordersEnabled) {
this.autoborderHandler.autoborder(true, this.drawInstance, this.drawData.redraw);
} else {
this.autoborderHandler.autoborder(false);
private updateHidden(value: boolean) {

Check warning on line 1345 in cvat-canvas/src/typescript/drawHandler.ts

View workflow job for this annotation

GitHub Actions / Linter

Missing return type on function
this.isHidden = value;
if (value) {
this.updateDrawInstance(0);
}
}

public configurate(configuration: Configuration): void {
this.controlPointsSize = configuration.controlPointsSize;
this.selectedShapeOpacity = configuration.selectedShapeOpacity;
this.outlinedBorders = configuration.outlinedBorders || 'black';

if (this.isHidden !== configuration.hideEditedObject) {
this.updateHidden(configuration.hideEditedObject);
} else if (!this.isHidden) {
this.updateDrawInstance(configuration.selectedShapeOpacity);
this.autobordersEnabled = configuration.autoborders;
if (this.drawInstance && !this.drawData.initialState) {
if (this.autobordersEnabled) {
this.autoborderHandler.autoborder(true, this.drawInstance, this.drawData.redraw);
} else {
this.autoborderHandler.autoborder(false);
}
}
}
}
Expand Down
18 changes: 12 additions & 6 deletions cvat-canvas/src/typescript/masksHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fabric } from 'fabric';
import debounce from 'lodash/debounce';

import {
DrawData, MasksEditData, Geometry, Configuration, BrushTool, ColorBy,
DrawData, MasksEditData, Geometry, Configuration, BrushTool, ColorBy, Position,
} from './canvasModel';
import consts from './consts';
import { DrawHandler } from './drawHandler';
Expand Down Expand Up @@ -61,7 +61,7 @@ export class MasksHandlerImpl implements MasksHandler {
private editData: MasksEditData | null;

private colorBy: ColorBy;
private latestMousePos: { x: number; y: number; };
private latestMousePos: Position;
private startTimestamp: number;
private geometry: Geometry;
private drawingOpacity: number;
Expand Down Expand Up @@ -228,11 +228,16 @@ export class MasksHandlerImpl implements MasksHandler {

private updateHidden(value: boolean) {

Check warning on line 229 in cvat-canvas/src/typescript/masksHandler.ts

View workflow job for this annotation

GitHub Actions / Linter

Missing return type on function
this.isHidden = value;
// Need to update style of upper canvas explicilty because update of default cursor is not applied immideately
// https://github.com/fabricjs/fabric.js/issues/1456
if (value) {
this.canvas.getElement().parentElement.style.display = 'none';
this.canvas.getElement().parentElement.style.opacity = '0';
(this.canvas.getElement().parentElement.querySelector('.upper-canvas') as HTMLElement).style.cursor = 'inherit';
this.canvas.defaultCursor = 'inherit';
} else {
this.canvas.getElement().parentElement.style.display = this.isDrawing || this.isEditing ? 'block' : '';
// TODO: change brush tool position to avoid flickering
this.canvas.getElement().parentElement.style.opacity = '';
(this.canvas.getElement().parentElement.querySelector('.upper-canvas') as HTMLElement).style.cursor = 'none';
this.canvas.defaultCursor = 'none';
}
}

Expand Down Expand Up @@ -363,6 +368,7 @@ export class MasksHandlerImpl implements MasksHandler {
this.editData = null;
this.drawingOpacity = 0.5;
this.brushMarker = null;
this.isHidden = false;
this.colorBy = ColorBy.LABEL;
this.onDrawDone = onDrawDone;
this.onDrawRepeat = onDrawRepeat;
Expand Down Expand Up @@ -465,7 +471,7 @@ export class MasksHandlerImpl implements MasksHandler {
this.canvas.renderAll();
}

if (isMouseDown && !isBrushSizeChanging && ['brush', 'eraser'].includes(tool?.type)) {
if (isMouseDown && !this.isHidden && !isBrushSizeChanging && ['brush', 'eraser'].includes(tool?.type)) {
const color = fabric.Color.fromHex(tool.color);
color.setAlpha(tool.type === 'eraser' ? 1 : 0.5);

Expand Down
1 change: 1 addition & 0 deletions cvat-canvas/src/typescript/svg.patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ SVG.Element.prototype.draw.extend(
}),
);

export const CIRCLE_STROKE = '#000';
// Fix method drawCircles
function drawCircles(): void {
const array = this.el.array().valueOf();
Expand Down
117 changes: 80 additions & 37 deletions cvat-ui/src/actions/annotation-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,43 +245,6 @@ export function highlightConflict(conflict: QualityConflict | null): AnyAction {
};
}

export function updateEditedState(shapeType: ShapeType | null, editedState: ObjectState | null): AnyAction {
return {
type: AnnotationActionTypes.UPDATE_EDITED_STATE,
payload: {
shapeType,
editedState,
},
};
}

export function resetEditedState(): AnyAction {
return {
type: AnnotationActionTypes.RESET_EDITED_STATE,
payload: {},
};
}

// TODO: change to regular func, we dont need async
export function hideEditedState(hide: boolean): ThunkAction {
return async (dispatch: ThunkDispatch, getState): Promise<void> => {
const state = getState();
const { instance: canvas } = state.annotation.canvas;
if (canvas) {
(canvas as Canvas).configure({
hideEditedObject: hide,
});
}

dispatch({
type: AnnotationActionTypes.HIDE_EDITED_STATE,
payload: {
hide,
},
});
};
}

function wrapAnnotationsInGTJob(states: ObjectState[]): ObjectState[] {
return states.map((state: ObjectState) => new Proxy(state, {
get(_state, prop) {
Expand Down Expand Up @@ -1648,3 +1611,83 @@ export function restoreFrameAsync(frame: number): ThunkAction {
}
};
}

export function updateEditedStateAsync(
shapeType: ShapeType | null,
editedStateInstance: ObjectState | null,
): ThunkAction {
return async (dispatch: ThunkDispatch, getState): Promise<void> => {
if (editedStateInstance) {
const state = getState();
const { instance: canvas } = state.annotation.canvas;
if (canvas) {
(canvas as Canvas).configure({
hideEditedObject: editedStateInstance.hidden,
});
}

dispatch({
type: AnnotationActionTypes.HIDE_EDITED_STATE,
payload: {
hide: editedStateInstance.hidden,
},
});
}
dispatch({
type: AnnotationActionTypes.UPDATE_EDITED_STATE,
payload: {
shapeType,
editedStateInstance,
},
});
};
}

export function resetEditedStateAsync(): ThunkAction {
return async (dispatch: ThunkDispatch, getState): Promise<void> => {
const state = getState();
const { instance: canvas } = state.annotation.canvas;
if (canvas) {
(canvas as Canvas).configure({
hideEditedObject: false,
});
}

dispatch({
type: AnnotationActionTypes.RESET_EDITED_STATE,
payload: {},
});
};
}

export function resetEditedState(): AnyAction {
return {
type: AnnotationActionTypes.RESET_EDITED_STATE,
payload: {},
};
}

export function changeHideEditedStateAsync(hide: boolean): ThunkAction {
return async (dispatch: ThunkDispatch, getState): Promise<void> => {
const state = getState();
const { instance: canvas } = state.annotation.canvas;
if (canvas) {
(canvas as Canvas).configure({
hideEditedObject: hide,
});

dispatch({
type: AnnotationActionTypes.HIDE_EDITED_STATE,
payload: {
hide,
},
});

const { editedStateInstance } = state.annotation.annotations.editedState;
if (editedStateInstance) {
editedStateInstance.hidden = hide;
await dispatch(updateAnnotationsAsync([editedStateInstance]));
}
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import CVATTooltip from 'components/common/cvat-tooltip';
import { CombinedState, ObjectType, ShapeType } from 'reducers';
import LabelSelector from 'components/label-selector/label-selector';
import { hideEditedState, rememberObject, updateCanvasBrushTools } from 'actions/annotation-actions';
import { changeHideEditedStateAsync, rememberObject, updateCanvasBrushTools } from 'actions/annotation-actions';
import { ShortcutScope } from 'utils/enums';
import GlobalHotKeys from 'utils/mousetrap-react';
import { subKeyMap } from 'utils/component-subkeymap';
Expand Down Expand Up @@ -75,7 +75,7 @@ function BrushTools(): React.ReactPortal | null {
const config = useSelector((state: CombinedState) => state.annotation.canvas.brushTools);
const canvasInstance = useSelector((state: CombinedState) => state.annotation.canvas.instance);
const labels = useSelector((state: CombinedState) => state.annotation.job.labels);
const editedState = useSelector((state: CombinedState) => state.annotation.annotations.edited);
const editedState = useSelector((state: CombinedState) => state.annotation.annotations.editedState);
const { keyMap, normalizedKeyMap } = useSelector((state: CombinedState) => state.shortcuts);
const { visible } = config;

Expand Down Expand Up @@ -105,7 +105,7 @@ function BrushTools(): React.ReactPortal | null {
}, [setCurrentTool, blockedTools['polygon-minus']]);

const hideMask = useCallback((hide: boolean) => {
dispatch(hideEditedState(hide));
dispatch(changeHideEditedStateAsync(hide));
}, [dispatch]);

const handlers: Record<keyof typeof componentShortcuts, (event?: KeyboardEvent) => void> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ import {
fetchAnnotationsAsync,
getDataFailed,
canvasErrorOccurred,
updateEditedState,
resetEditedState,
updateEditedStateAsync,
resetEditedStateAsync,
} from 'actions/annotation-actions';
import {
switchGrid,
Expand Down Expand Up @@ -352,10 +352,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
dispatch(reviewActions.startIssue(position));
},
onUpdateEditedObject(objectType: ShapeType | null, editedState: ObjectState | null): void {
dispatch(updateEditedState(objectType, editedState));
dispatch(updateEditedStateAsync(objectType, editedState));
},
onResetEditedObject(): void {
dispatch(resetEditedState());
dispatch(resetEditedStateAsync());
},
};
}
Expand Down
Loading

0 comments on commit c6aecf3

Please sign in to comment.