You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.9 KiB
TypeScript

// Copyright (C) 2020-2022 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import Button from 'antd/lib/button';
import { DeleteOutlined, EnvironmentOutlined } from '@ant-design/icons';
import { connect } from 'react-redux';
import { CombinedState, ContextMenuType } from 'reducers/interfaces';
import { updateAnnotationsAsync, updateCanvasContextMenu } from 'actions/annotation-actions';
import CVATTooltip from 'components/common/cvat-tooltip';
interface StateToProps {
activatedState: any | null;
selectedPoint: number | null;
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: selectedPoint,
},
},
},
} = state;
return {
activatedState:
activatedStateID === null ?
null :
states.filter((_state) => _state.clientID === activatedStateID)[0] || null,
selectedPoint,
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;
function CanvasPointContextMenu(props: Props): React.ReactPortal | null {
const {
onCloseContextMenu, onUpdateAnnotations, activatedState, visible, type, top, left,
} = props;
const [contextMenuFor, setContextMenuFor] = useState(activatedState);
if (activatedState !== contextMenuFor) {
setContextMenuFor(activatedState);
if (visible && type === ContextMenuType.CANVAS_SHAPE_POINT) {
onCloseContextMenu();
}
}
const onPointDelete = (): void => {
const { selectedPoint } = props;
if (contextMenuFor && selectedPoint !== null) {
contextMenuFor.points = contextMenuFor.points
.slice(0, selectedPoint * 2)
.concat(contextMenuFor.points.slice(selectedPoint * 2 + 2));
onUpdateAnnotations([contextMenuFor]);
onCloseContextMenu();
}
};
const onSetStartPoint = (): void => {
const { selectedPoint } = props;
if (contextMenuFor && selectedPoint !== null && contextMenuFor.shapeType === 'polygon') {
contextMenuFor.points = contextMenuFor.points
.slice(selectedPoint * 2)
.concat(contextMenuFor.points.slice(0, selectedPoint * 2));
onUpdateAnnotations([contextMenuFor]);
onCloseContextMenu();
}
};
return visible && contextMenuFor && type === ContextMenuType.CANVAS_SHAPE_POINT ?
ReactDOM.createPortal(
<div className='cvat-canvas-point-context-menu' style={{ top, left }}>
<CVATTooltip title='Delete point [Alt + dblclick]'>
<Button type='link' icon={<DeleteOutlined />} onClick={onPointDelete}>
Delete point
</Button>
</CVATTooltip>
{contextMenuFor && contextMenuFor.shapeType === 'polygon' && (
<Button type='link' icon={<EnvironmentOutlined />} onClick={onSetStartPoint}>
Set start point
</Button>
)}
</div>,
window.document.body,
) :
null;
}
export default connect(mapStateToProps, mapDispatchToProps)(CanvasPointContextMenu);