React UI: batch of fixes (#1227)

* Fix: keyframes navigation

* Fix: handled removing of the latest keyframe

* Fix: activating a shape when another shape is being changed

* Fix: up points in the side bar on points click

* Fix: editable shape isn't transformed when change zoom

* Updated message
main
Boris Sekachev 6 years ago committed by GitHub
parent b3f7f5b8bc
commit 6a59e7cff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -3,6 +3,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { import {
Mode,
DrawData, DrawData,
MergeData, MergeData,
SplitData, SplitData,
@ -51,6 +52,7 @@ interface Canvas {
dragCanvas(enable: boolean): void; dragCanvas(enable: boolean): void;
zoomCanvas(enable: boolean): void; zoomCanvas(enable: boolean): void;
mode(): void;
cancel(): void; cancel(): void;
} }
@ -132,6 +134,10 @@ class CanvasImpl implements Canvas {
this.model.select(objectState); this.model.select(objectState);
} }
public mode(): Mode {
return this.model.mode;
}
public cancel(): void { public cancel(): void {
this.model.cancel(); this.model.cancel();
} }
@ -141,4 +147,5 @@ export {
CanvasImpl as Canvas, CanvasImpl as Canvas,
CanvasVersion, CanvasVersion,
RectDrawingMethod, RectDrawingMethod,
Mode as CanvasMode,
}; };

@ -469,21 +469,21 @@ export class CanvasViewImpl implements CanvasView, Listener {
'stroke-width': consts.POINTS_STROKE_WIDTH / self.geometry.scale, 'stroke-width': consts.POINTS_STROKE_WIDTH / self.geometry.scale,
}); });
circle.node.addEventListener('mouseenter', (): void => { circle.on('mouseenter', (): void => {
circle.attr({ circle.attr({
'stroke-width': consts.POINTS_SELECTED_STROKE_WIDTH / self.geometry.scale, 'stroke-width': consts.POINTS_SELECTED_STROKE_WIDTH / self.geometry.scale,
}); });
circle.node.addEventListener('dblclick', dblClickHandler); circle.on('dblclick', dblClickHandler);
circle.addClass('cvat_canvas_selected_point'); circle.addClass('cvat_canvas_selected_point');
}); });
circle.node.addEventListener('mouseleave', (): void => { circle.on('mouseleave', (): void => {
circle.attr({ circle.attr({
'stroke-width': consts.POINTS_STROKE_WIDTH / self.geometry.scale, 'stroke-width': consts.POINTS_STROKE_WIDTH / self.geometry.scale,
}); });
circle.node.removeEventListener('dblclick', dblClickHandler); circle.off('dblclick', dblClickHandler);
circle.removeClass('cvat_canvas_selected_point'); circle.removeClass('cvat_canvas_selected_point');
}); });
@ -1330,13 +1330,18 @@ export class CanvasViewImpl implements CanvasView, Listener {
private setupPoints(basicPolyline: SVG.PolyLine, state: any): any { private setupPoints(basicPolyline: SVG.PolyLine, state: any): any {
this.selectize(true, basicPolyline); this.selectize(true, basicPolyline);
const group = basicPolyline.remember('_selectHandler').nested const group: SVG.G = basicPolyline.remember('_selectHandler').nested
.addClass('cvat_canvas_shape').attr({ .addClass('cvat_canvas_shape').attr({
clientID: state.clientID, clientID: state.clientID,
id: `cvat_canvas_shape_${state.clientID}`, id: `cvat_canvas_shape_${state.clientID}`,
'data-z-order': state.zOrder, 'data-z-order': state.zOrder,
}); });
group.on('click.canvas', (event: MouseEvent): void => {
// Need to redispatch the event on another element
basicPolyline.fire(new MouseEvent('click', event));
});
group.bbox = basicPolyline.bbox.bind(basicPolyline); group.bbox = basicPolyline.bbox.bind(basicPolyline);
group.clone = basicPolyline.clone.bind(basicPolyline); group.clone = basicPolyline.clone.bind(basicPolyline);

@ -84,7 +84,7 @@ export class EditHandlerImpl implements EditHandler {
}).draw(dummyEvent, { snapToGrid: 0.1 }); }).draw(dummyEvent, { snapToGrid: 0.1 });
if (this.editData.state.shapeType === 'points') { if (this.editData.state.shapeType === 'points') {
this.editLine.style('stroke-width', 0); this.editLine.attr('stroke-width', 0);
(this.editLine as any).draw('undo'); (this.editLine as any).draw('undo');
} }
@ -168,7 +168,7 @@ export class EditHandlerImpl implements EditHandler {
for (const points of [firstPart, secondPart]) { for (const points of [firstPart, secondPart]) {
this.clones.push(this.canvas.polygon(points.join(' ')) this.clones.push(this.canvas.polygon(points.join(' '))
.attr('fill', this.editedShape.attr('fill')) .attr('fill', this.editedShape.attr('fill'))
.style('fill-opacity', '0.5') .attr('fill-opacity', '0.5')
.addClass('cvat_canvas_shape')); .addClass('cvat_canvas_shape'));
} }
@ -340,10 +340,16 @@ export class EditHandlerImpl implements EditHandler {
public transform(geometry: Geometry): void { public transform(geometry: Geometry): void {
this.geometry = geometry; this.geometry = geometry;
if (this.editedShape) {
this.editedShape.attr({
'stroke-width': consts.BASE_STROKE_WIDTH / geometry.scale,
});
}
if (this.editLine) { if (this.editLine) {
(this.editLine as any).draw('transform'); (this.editLine as any).draw('transform');
if (this.editData.state.shapeType !== 'points') { if (this.editData.state.shapeType !== 'points') {
this.editLine.style({ this.editLine.attr({
'stroke-width': consts.BASE_STROKE_WIDTH / geometry.scale, 'stroke-width': consts.BASE_STROKE_WIDTH / geometry.scale,
}); });
} }
@ -351,7 +357,7 @@ export class EditHandlerImpl implements EditHandler {
const paintHandler = this.editLine.remember('_paintHandler'); const paintHandler = this.editLine.remember('_paintHandler');
for (const point of (paintHandler as any).set.members) { for (const point of (paintHandler as any).set.members) {
point.style( point.attr(
'stroke-width', 'stroke-width',
`${consts.POINTS_STROKE_WIDTH / geometry.scale}`, `${consts.POINTS_STROKE_WIDTH / geometry.scale}`,
); );

@ -339,6 +339,11 @@
if (updated.keyframe) { if (updated.keyframe) {
checkObjectType('keyframe', data.keyframe, 'boolean', null); checkObjectType('keyframe', data.keyframe, 'boolean', null);
if (!this.shapes || (Object.keys(this.shapes).length === 1 && !data.keyframe)) {
throw new ArgumentError(
'Can not remove the latest keyframe of an object. Consider removing the object instead',
);
}
} }
return fittedPoints; return fittedPoints;
@ -964,7 +969,8 @@
const current = this.get(frame); const current = this.get(frame);
const wasKeyframe = frame in this.shapes; const wasKeyframe = frame in this.shapes;
if ((keyframe && wasKeyframe) || (!keyframe && !wasKeyframe)) { if ((keyframe && wasKeyframe)
|| (!keyframe && !wasKeyframe)) {
return; return;
} }
@ -1088,7 +1094,7 @@
throw new DataError( throw new DataError(
'No one left position or right position was found. ' 'No one left position or right position was found. '
+ `Interpolation impossible. Client ID: ${this.id}`, + `Interpolation impossible. Client ID: ${this.clientID}`,
); );
} }
} }

@ -39,7 +39,7 @@
color: null, color: null,
hidden: null, hidden: null,
pinned: null, pinned: null,
keyframes: null, keyframes: serialized.keyframes,
group: serialized.group, group: serialized.group,
updated: serialized.updated, updated: serialized.updated,

@ -4,12 +4,14 @@
import { import {
Canvas, Canvas,
CanvasMode,
CanvasVersion, CanvasVersion,
RectDrawingMethod, RectDrawingMethod,
} from '../../cvat-canvas/src/typescript/canvas'; } from '../../cvat-canvas/src/typescript/canvas';
export { export {
Canvas, Canvas,
CanvasMode,
CanvasVersion, CanvasVersion,
RectDrawingMethod, RectDrawingMethod,
}; };

@ -4,7 +4,7 @@
import { AnyAction } from 'redux'; import { AnyAction } from 'redux';
import { Canvas } from 'cvat-canvas'; import { Canvas, CanvasMode } from 'cvat-canvas';
import { AnnotationActionTypes } from 'actions/annotation-actions'; import { AnnotationActionTypes } from 'actions/annotation-actions';
import { AuthActionTypes } from 'actions/auth-actions'; import { AuthActionTypes } from 'actions/auth-actions';
import { import {
@ -609,9 +609,17 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
}; };
} }
case AnnotationActionTypes.ACTIVATE_OBJECT: { case AnnotationActionTypes.ACTIVATE_OBJECT: {
const { activatedStateID } = action.payload;
const { const {
activatedStateID, canvas: {
} = action.payload; activeControl,
instance,
},
} = state;
if (activeControl !== ActiveControl.CURSOR || instance.mode() !== CanvasMode.IDLE) {
return state;
}
return { return {
...state, ...state,

Loading…
Cancel
Save