Added point deletion context menu

main
Dmitry Kalinin 6 years ago
parent b0dbbb3faa
commit 845be3b486

@ -318,6 +318,7 @@ export function updateCanvasContextMenu(
left: number,
top: number,
type?: ContextMenuType,
pointID?: number,
): AnyAction {
return {
type: AnnotationActionTypes.UPDATE_CANVAS_CONTEXT_MENU,
@ -326,6 +327,7 @@ export function updateCanvasContextMenu(
left,
top,
type,
pointID,
},
};
}

@ -5,16 +5,21 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {
Button,
} from 'antd';
interface Props {
activatedStateID: number | null;
visible: boolean;
left: number;
top: number;
onPointDelete(): void;
}
export default function CanvasPointContextMenu(props: Props): JSX.Element | null {
const {
onPointDelete,
activatedStateID,
visible,
left,
@ -27,7 +32,9 @@ export default function CanvasPointContextMenu(props: Props): JSX.Element | null
return ReactDOM.createPortal(
<div className='cvat-canvas-point-context-menu' style={{ top, left }}>
<span>Haha</span>
<Button type='link' icon='delete' onClick={onPointDelete}>
Delete point
</Button>
</div>,
window.document.body,
);

@ -18,16 +18,10 @@ import {
GridColor,
ObjectType,
ContextMenuType,
Workspace
Workspace,
} from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas';
import getCore from 'cvat-core';
import {
ColorBy,
GridColor,
ObjectType,
Workspace,
} from 'reducers/interfaces';
const cvat = getCore();
@ -81,7 +75,8 @@ interface Props {
onSplitAnnotations(sessionInstance: any, frame: number, state: any): void;
onActivateObject(activatedStateID: number | null): void;
onSelectObjects(selectedStatesID: number[]): void;
onUpdateContextMenu(visible: boolean, left: number, top: number, type: ContextMenuType): void;
onUpdateContextMenu(visible: boolean, left: number, top: number, type: ContextMenuType,
pointID?: number): void;
onAddZLayer(): void;
onSwitchZLayer(cur: number): void;
onChangeBrightnessLevel(level: number): void;
@ -333,8 +328,17 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
};
private onCanvasContextMenu = (e: MouseEvent): void => {
const { activatedStateID, onUpdateContextMenu } = this.props;
onUpdateContextMenu(activatedStateID !== null, e.clientX, e.clientY);
const {
activatedStateID,
onUpdateContextMenu,
contextVisible,
contextType,
} = this.props;
if (!contextVisible && contextType !== ContextMenuType.CANVAS_SHAPE_POINT) {
onUpdateContextMenu(activatedStateID !== null, e.clientX, e.clientY,
ContextMenuType.CANVAS_SHAPE);
}
};
private onCanvasShapeClicked = (e: any): void => {
@ -460,6 +464,16 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
}
};
private onCanvasPointContextMenu = (e: any): void => {
const {
activatedStateID,
onUpdateContextMenu,
} = this.props;
onUpdateContextMenu(activatedStateID !== null, e.detail.mouseEvent.clientX,
e.detail.mouseEvent.clientY, ContextMenuType.CANVAS_SHAPE_POINT, e.detail.pointID);
};
private activateOnCanvas(): void {
const {
activatedStateID,
@ -599,6 +613,8 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
canvasInstance.html().addEventListener('canvas.merged', this.onCanvasObjectsMerged);
canvasInstance.html().addEventListener('canvas.groupped', this.onCanvasObjectsGroupped);
canvasInstance.html().addEventListener('canvas.splitted', this.onCanvasTrackSplitted);
canvasInstance.html().addEventListener('point.contextmenu', this.onCanvasPointContextMenu);
}
public render(): JSX.Element {

@ -14,6 +14,7 @@ import ControlsSideBarContainer from 'containers/annotation-page/standard-worksp
import ObjectSideBarContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/objects-side-bar';
import PropagateConfirmContainer from 'containers/annotation-page/standard-workspace/propagate-confirm';
import CanvasContextMenuContainer from 'containers/annotation-page/standard-workspace/canvas-context-menu';
import CanvasPointContextMenuContainer from 'containers/annotation-page/standard-workspace/canvas-point-context-menu';
export default function StandardWorkspaceComponent(): JSX.Element {
return (
@ -23,6 +24,7 @@ export default function StandardWorkspaceComponent(): JSX.Element {
<ObjectSideBarContainer />
<PropagateConfirmContainer />
<CanvasContextMenuContainer />
<CanvasPointContextMenuContainer />
</Layout>
);
}

@ -136,10 +136,12 @@
.cvat-canvas-point-context-menu {
opacity: 0.6;
position: fixed;
width: 100px;
width: 135px;
z-index: 10;
max-height: 50%;
overflow-y: auto;
background-color: #ffffff;
border-radius: 4px;
&:hover {
opacity: 1;

@ -8,7 +8,6 @@ import { connect } from 'react-redux';
import { CombinedState, ContextMenuType } from 'reducers/interfaces';
import CanvasContextMenuComponent from 'components/annotation-page/standard-workspace/canvas-context-menu';
import CanvasPointContextMenuComponent from 'components/annotation-page/standard-workspace/canvas-point-context-menu';
interface StateToProps {
activatedStateID: number | null;
@ -183,12 +182,16 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
} = this.props;
return (
<CanvasContextMenuComponent
left={left}
top={top}
visible={visible}
activatedStateID={activatedStateID}
/>
<>
{ type === ContextMenuType.CANVAS_SHAPE && (
<CanvasContextMenuComponent
left={left}
top={top}
visible={visible}
activatedStateID={activatedStateID}
/>
)}
</>
);
}
}

@ -0,0 +1,180 @@
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { connect } from 'react-redux';
import { CombinedState, ContextMenuType } from 'reducers/interfaces';
import { updateAnnotationsAsync, updateCanvasContextMenu } from 'actions/annotation-actions';
import CanvasPointContextMenuComponent from 'components/annotation-page/standard-workspace/canvas-point-context-menu';
interface StateToProps {
activatedStateID: number | null;
activetedPointID: number | null | undefined;
states: any[];
visible: boolean;
top: number;
left: number;
type: ContextMenuType;
}
function mapStateToProps(state: CombinedState): StateToProps {
const {
annotation: {
annotations: {
states,
activatedStateID,
},
canvas: {
contextMenu: {
visible,
top,
left,
type,
pointID: activetedPointID,
},
},
},
} = state;
return {
activatedStateID,
activetedPointID,
states,
visible,
left,
top,
type,
};
}
interface DispatchToProps {
onUpdateAnnotations(states: any[]): void;
onCloseContextMenu(): void;
}
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
onUpdateAnnotations(states: any[]): void {
dispatch(updateAnnotationsAsync(states));
},
onCloseContextMenu(): void {
dispatch(updateCanvasContextMenu(false, 0, 0));
},
};
}
type Props = StateToProps & DispatchToProps;
interface State {
latestLeft: number;
latestTop: number;
left: number;
top: number;
}
class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
public constructor(props: Props) {
super(props);
this.state = {
latestLeft: 0,
latestTop: 0,
left: 0,
top: 0,
};
}
static getDerivedStateFromProps(props: Props, state: State): State | null {
if (props.left === state.latestLeft
&& props.top === state.latestTop) {
return null;
}
return {
...state,
latestLeft: props.left,
latestTop: props.top,
top: props.top,
left: props.left,
};
}
public componentDidUpdate(): void {
const {
top,
left,
} = this.state;
const {
innerWidth,
innerHeight,
} = window;
const [element] = window.document.getElementsByClassName('cvat-canvas-point-context-menu');
if (element) {
const height = element.clientHeight;
const width = element.clientWidth;
if (top + height > innerHeight || left + width > innerWidth) {
this.setState({
top: top - Math.max(top + height - innerHeight, 0),
left: left - Math.max(left + width - innerWidth, 0),
});
}
}
}
private deletePoint(): void {
const {
activetedPointID,
activatedStateID,
states,
onUpdateAnnotations,
onCloseContextMenu,
} = this.props;
const [objectState] = states.filter((e) => (e.clientID === activatedStateID));
if (activetedPointID) {
objectState.points = objectState.points.slice(0, activetedPointID * 2)
.concat(objectState.points.slice(activetedPointID * 2 + 2));
onUpdateAnnotations([objectState]);
onCloseContextMenu();
}
}
public render(): JSX.Element {
const {
visible,
activatedStateID,
type,
} = this.props;
const {
top,
left,
} = this.state;
return (
<>
{type === ContextMenuType.CANVAS_SHAPE_POINT && (
<CanvasPointContextMenuComponent
left={left}
top={top}
visible={visible}
activatedStateID={activatedStateID}
onPointDelete={() => this.deletePoint()}
/>
)}
</>
);
}
}
export default connect(
mapStateToProps,
mapDispatchToProps,
)(CanvasContextMenuContainer);

@ -96,7 +96,8 @@ interface DispatchToProps {
onSplitAnnotations(sessionInstance: any, frame: number, state: any): void;
onActivateObject: (activatedStateID: number | null) => void;
onSelectObjects: (selectedStatesID: number[]) => void;
onUpdateContextMenu(visible: boolean, left: number, top: number, type: ContextMenuType): void;
onUpdateContextMenu(visible: boolean, left: number, top: number, type: ContextMenuType,
pointID?: number): void;
onAddZLayer(): void;
onSwitchZLayer(cur: number): void;
onChangeBrightnessLevel(level: number): void;
@ -257,13 +258,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
onSelectObjects(selectedStatesID: number[]): void {
dispatch(selectObjects(selectedStatesID));
},
onUpdateContextMenu(
visible: boolean,
left: number,
top: number,
type: ContextMenuType,
): void {
dispatch(updateCanvasContextMenu(visible, left, top, type));
onUpdateContextMenu(visible: boolean, left: number, top: number,
type: ContextMenuType, pointID?: number): void {
dispatch(updateCanvasContextMenu(visible, left, top, type, pointID));
},
onAddZLayer(): void {
dispatch(addZLayer());

@ -26,6 +26,7 @@ const defaultState: AnnotationState = {
left: 0,
top: 0,
type: ContextMenuType.CANVAS_SHAPE,
pointID: null,
},
instance: new Canvas(),
ready: false,
@ -934,6 +935,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
left,
top,
type,
pointID,
} = action.payload;
return {
@ -946,6 +948,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
left,
top,
type,
pointID,
},
},
};

@ -303,6 +303,7 @@ export interface AnnotationState {
top: number;
left: number;
type: ContextMenuType;
pointID: number | null | undefined;
};
instance: Canvas;
ready: boolean;

Loading…
Cancel
Save