Disabled ability to edit positions in attribute anntation mode

main
Boris Sekachev 5 years ago
parent 3bd06603c5
commit a53bd6c44d

@ -14,6 +14,7 @@ import {
GroupData,
Mode,
InteractionData,
Configuration,
} from './canvasModel';
export interface CanvasController {
@ -27,6 +28,7 @@ export interface CanvasController {
readonly splitData: SplitData;
readonly groupData: GroupData;
readonly selected: any;
readonly configuration: Configuration;
mode: Mode;
geometry: Geometry;
@ -151,6 +153,10 @@ export class CanvasControllerImpl implements CanvasController {
return this.model.selected;
}
public get configuration(): Configuration {
return this.model.configuration;
}
public set mode(value: Mode) {
this.model.mode = value;
}

@ -56,6 +56,7 @@ export interface Configuration {
displayAllText?: boolean;
undefinedAttrValue?: string;
showProjections?: boolean;
forceDisableEditing?: boolean;
}
export interface DrawData {
@ -288,15 +289,15 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
const mutiplier = Math.sin((angle * Math.PI) / 180) + Math.cos((angle * Math.PI) / 180);
if ((angle / 90) % 2) {
// 90, 270, ..
this.data.top +=
mutiplier * ((x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1)) * this.data.scale;
this.data.left -=
mutiplier * ((y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1)) * this.data.scale;
const topMultiplier = (x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1);
const leftMultiplier = (y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1);
this.data.top += mutiplier * topMultiplier * this.data.scale;
this.data.left -= mutiplier * leftMultiplier * this.data.scale;
} else {
this.data.left +=
mutiplier * ((x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1)) * this.data.scale;
this.data.top +=
mutiplier * ((y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1)) * this.data.scale;
const leftMultiplier = (x - this.data.imageSize.width / 2) * (oldScale / this.data.scale - 1);
const topMultiplier = (y - this.data.imageSize.height / 2) * (oldScale / this.data.scale - 1);
this.data.left += mutiplier * leftMultiplier * this.data.scale;
this.data.top += mutiplier * topMultiplier * this.data.scale;
}
this.notify(UpdateReasons.IMAGE_ZOOMED);
@ -599,13 +600,16 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
this.data.configuration.undefinedAttrValue = configuration.undefinedAttrValue;
}
if (typeof configuration.forceDisableEditing !== 'undefined') {
this.data.configuration.forceDisableEditing = configuration.forceDisableEditing;
}
this.notify(UpdateReasons.CONFIG_UPDATED);
}
public isAbleToChangeFrame(): boolean {
const isUnable =
[Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT].includes(this.data.mode) ||
(this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number');
const isUnable = [Mode.DRAG, Mode.EDIT, Mode.RESIZE, Mode.INTERACT].includes(this.data.mode)
|| (this.data.mode === Mode.DRAW && typeof this.data.drawData.redraw === 'number');
return !isUnable;
}

@ -94,6 +94,11 @@ export class CanvasViewImpl implements CanvasView, Listener {
return this.serviceFlags.drawHidden[clientID] || false;
}
private stateIsLocked(state: any): boolean {
const { configuration } = this.controller;
return state.lock || configuration.forceDisableEditing;
}
private setupServiceHidden(clientID: number, value: boolean): void {
this.serviceFlags.drawHidden[clientID] = value;
const shape = this.svgShapes[clientID];
@ -455,8 +460,8 @@ export class CanvasViewImpl implements CanvasView, Listener {
// Transform all text
for (const key in this.svgShapes) {
if (
Object.prototype.hasOwnProperty.call(this.svgShapes, key) &&
Object.prototype.hasOwnProperty.call(this.svgTexts, key)
Object.prototype.hasOwnProperty.call(this.svgShapes, key)
&& Object.prototype.hasOwnProperty.call(this.svgTexts, key)
) {
this.updateTextPosition(this.svgTexts[key], this.svgShapes[key]);
}
@ -874,9 +879,9 @@ export class CanvasViewImpl implements CanvasView, Listener {
this.content.addEventListener('mousedown', (event): void => {
if ([0, 1].includes(event.button)) {
if (
[Mode.IDLE, Mode.DRAG_CANVAS, Mode.MERGE, Mode.SPLIT].includes(this.mode) ||
event.button === 1 ||
event.altKey
[Mode.IDLE, Mode.DRAG_CANVAS, Mode.MERGE, Mode.SPLIT].includes(this.mode)
|| event.button === 1
|| event.altKey
) {
self.controller.enableDrag(event.clientX, event.clientY);
}
@ -1325,8 +1330,8 @@ export class CanvasViewImpl implements CanvasView, Listener {
}
if (
state.points.length !== drawnState.points.length ||
state.points.some((p: number, id: number): boolean => p !== drawnState.points[id])
state.points.length !== drawnState.points.length
|| state.points.some((p: number, id: number): boolean => p !== drawnState.points[id])
) {
const translatedPoints: number[] = translate(state.points);
@ -1542,7 +1547,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
if (state && state.shapeType === 'points') {
this.svgShapes[clientID]
.remember('_selectHandler')
.nested.style('pointer-events', state.lock ? 'none' : '');
.nested.style('pointer-events', this.stateIsLocked(state) ? 'none' : '');
}
if (!state || state.hidden || state.outside) {
@ -1550,8 +1555,14 @@ export class CanvasViewImpl implements CanvasView, Listener {
}
const shape = this.svgShapes[clientID];
let text = this.svgTexts[clientID];
if (!text) {
text = this.addText(state);
this.svgTexts[state.clientID] = text;
}
this.updateTextPosition(text, shape);
if (state.lock) {
if (this.stateIsLocked(state)) {
return;
}
@ -1567,12 +1578,6 @@ export class CanvasViewImpl implements CanvasView, Listener {
(shape as any).attr('projections', true);
}
let text = this.svgTexts[clientID];
if (!text) {
text = this.addText(state);
this.svgTexts[state.clientID] = text;
}
const hideText = (): void => {
if (text) {
text.addClass('cvat_canvas_hidden');
@ -1601,12 +1606,14 @@ export class CanvasViewImpl implements CanvasView, Listener {
const p2 = e.detail.p;
const delta = 1;
const { offset } = this.controller.geometry;
if (Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) >= delta) {
const dx2 = (p1.x - p2.x) ** 2;
const dy2 = (p1.y - p2.y) ** 2;
if (Math.sqrt(dx2 + dy2) >= delta) {
const points = pointsToNumberArray(
shape.attr('points') ||
`${shape.attr('x')},${shape.attr('y')} ` +
`${shape.attr('x') + shape.attr('width')},` +
`${shape.attr('y') + shape.attr('height')}`,
shape.attr('points')
|| `${shape.attr('x')},${shape.attr('y')} `
+ `${shape.attr('x') + shape.attr('width')},`
+ `${shape.attr('y') + shape.attr('height')}`,
).map((x: number): number => x - offset);
this.drawnStates[state.clientID].points = points;
@ -1677,10 +1684,10 @@ export class CanvasViewImpl implements CanvasView, Listener {
const { offset } = this.controller.geometry;
const points = pointsToNumberArray(
shape.attr('points') ||
`${shape.attr('x')},${shape.attr('y')} ` +
`${shape.attr('x') + shape.attr('width')},` +
`${shape.attr('y') + shape.attr('height')}`,
shape.attr('points')
|| `${shape.attr('x')},${shape.attr('y')} `
+ `${shape.attr('x') + shape.attr('width')},`
+ `${shape.attr('y') + shape.attr('height')}`,
).map((x: number): number => x - offset);
this.drawnStates[state.clientID].points = points;
@ -1697,7 +1704,6 @@ export class CanvasViewImpl implements CanvasView, Listener {
}
});
this.updateTextPosition(text, shape);
this.canvas.dispatchEvent(
new CustomEvent('canvas.activated', {
bubbles: false,
@ -1757,8 +1763,8 @@ export class CanvasViewImpl implements CanvasView, Listener {
// Find the best place for a text
let [clientX, clientY]: number[] = [box.x + box.width, box.y];
if (
clientX + ((text.node as any) as SVGTextElement).getBBox().width + consts.TEXT_MARGIN >
this.canvas.offsetWidth
clientX + ((text.node as any) as SVGTextElement).getBBox().width + consts.TEXT_MARGIN
> this.canvas.offsetWidth
) {
[clientX, clientY] = [box.x, box.y];
}
@ -1778,7 +1784,9 @@ export class CanvasViewImpl implements CanvasView, Listener {
private addText(state: any): SVG.Text {
const { undefinedAttrValue } = this.configuration;
const { label, clientID, attributes, source } = state;
const {
label, clientID, attributes, source,
} = state;
const attrNames = label.attributes.reduce((acc: any, val: any): void => {
acc[val.id] = val.name;
return acc;

@ -93,7 +93,9 @@ interface Props {
export default class CanvasWrapperComponent extends React.PureComponent<Props> {
public componentDidMount(): void {
const { automaticBordering, showObjectsTextAlways, canvasInstance } = this.props;
const {
automaticBordering, showObjectsTextAlways, canvasInstance, workspace,
} = this.props;
// It's awful approach from the point of view React
// But we do not have another way because cvat-canvas returns regular DOM element
@ -104,6 +106,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
autoborders: automaticBordering,
undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE,
displayAllText: showObjectsTextAlways,
forceDisableEditing: workspace === Workspace.ATTRIBUTE_ANNOTATION,
});
this.initialSetup();
@ -247,6 +250,18 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
canvasInstance.rotate(frameAngle);
}
if (prevProps.workspace !== workspace) {
if (workspace === Workspace.ATTRIBUTE_ANNOTATION) {
canvasInstance.configure({
forceDisableEditing: true,
});
} else if (prevProps.workspace === Workspace.ATTRIBUTE_ANNOTATION) {
canvasInstance.configure({
forceDisableEditing: false,
});
}
}
const loadingAnimation = window.document.getElementById('cvat_canvas_loading_animation');
if (loadingAnimation && frameFetching !== prevProps.frameFetching) {
if (frameFetching) {

Loading…
Cancel
Save