// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import {
Row,
Col,
Icon,
Select,
Radio,
Input,
Collapse,
Checkbox,
InputNumber,
Dropdown,
Menu,
Button,
Modal,
Popover,
} from 'antd';
import Text from 'antd/lib/typography/Text';
import { RadioChangeEvent } from 'antd/lib/radio';
import { CheckboxChangeEvent } from 'antd/lib/checkbox';
import ColorChanger from 'components/annotation-page/standard-workspace/objects-side-bar/color-changer';
import {
ObjectOutsideIcon,
FirstIcon,
LastIcon,
PreviousIcon,
NextIcon,
BackgroundIcon,
ForegroundIcon,
} from 'icons';
import {
ObjectType, ShapeType,
} from 'reducers/interfaces';
function ItemMenu(
serverID: number | undefined,
locked: boolean,
objectType: ObjectType,
copy: (() => void),
remove: (() => void),
propagate: (() => void),
createURL: (() => void),
toBackground: (() => void),
toForeground: (() => void),
): JSX.Element {
return (
);
}
interface ItemTopComponentProps {
clientID: number;
serverID: number | undefined;
labelID: number;
labels: any[];
objectType: ObjectType;
type: string;
locked: boolean;
changeLabel(labelID: string): void;
copy(): void;
remove(): void;
propagate(): void;
createURL(): void;
toBackground(): void;
toForeground(): void;
}
function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
const {
clientID,
serverID,
labelID,
labels,
objectType,
type,
locked,
changeLabel,
copy,
remove,
propagate,
createURL,
toBackground,
toForeground,
} = props;
return (
{clientID}
{type}
);
}
const ItemTop = React.memo(ItemTopComponent);
interface ItemButtonsComponentProps {
objectType: ObjectType;
shapeType: ShapeType;
occluded: boolean;
outside: boolean | undefined;
locked: boolean;
pinned: boolean;
hidden: boolean;
keyframe: boolean | undefined;
navigateFirstKeyframe: null | (() => void);
navigatePrevKeyframe: null | (() => void);
navigateNextKeyframe: null | (() => void);
navigateLastKeyframe: null | (() => void);
setOccluded(): void;
unsetOccluded(): void;
setOutside(): void;
unsetOutside(): void;
setKeyframe(): void;
unsetKeyframe(): void;
lock(): void;
unlock(): void;
pin(): void;
unpin(): void;
hide(): void;
show(): void;
}
function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
const {
objectType,
shapeType,
occluded,
outside,
locked,
pinned,
hidden,
keyframe,
navigateFirstKeyframe,
navigatePrevKeyframe,
navigateNextKeyframe,
navigateLastKeyframe,
setOccluded,
unsetOccluded,
setOutside,
unsetOutside,
setKeyframe,
unsetKeyframe,
lock,
unlock,
pin,
unpin,
hide,
show,
} = props;
if (objectType === ObjectType.TRACK) {
return (
{ navigateFirstKeyframe
?
: }
{ navigatePrevKeyframe
?
: }
{ navigateNextKeyframe
?
: }
{ navigateLastKeyframe
?
: }
{ outside
?
: }
{ locked
?
: }
{ occluded
?
: }
{ hidden
?
: }
{ keyframe
?
: }
{
shapeType !== ShapeType.POINTS && (
{ pinned
?
: }
)
}
);
}
if (objectType === ObjectType.TAG) {
return (
{ locked
?
: }
);
}
return (
{ locked
?
: }
{ occluded
?
: }
{ hidden
?
: }
{
shapeType !== ShapeType.POINTS && (
{ pinned
?
: }
)
}
);
}
const ItemButtons = React.memo(ItemButtonsComponent);
interface ItemAttributeComponentProps {
attrInputType: string;
attrValues: string[];
attrValue: string;
attrName: string;
attrID: number;
changeAttribute(attrID: number, value: string): void;
}
function attrIsTheSame(
prevProps: ItemAttributeComponentProps,
nextProps: ItemAttributeComponentProps,
): boolean {
return nextProps.attrID === prevProps.attrID
&& nextProps.attrValue === prevProps.attrValue
&& nextProps.attrName === prevProps.attrName
&& nextProps.attrInputType === prevProps.attrInputType
&& nextProps.attrValues
.map((value: string, id: number): boolean => prevProps.attrValues[id] === value)
.every((value: boolean): boolean => value);
}
function ItemAttributeComponent(props: ItemAttributeComponentProps): JSX.Element {
const {
attrInputType,
attrValues,
attrValue,
attrName,
attrID,
changeAttribute,
} = props;
if (attrInputType === 'checkbox') {
return (
{
const value = event.target.checked ? 'true' : 'false';
changeAttribute(attrID, value);
}}
>
{attrName}
);
}
if (attrInputType === 'radio') {
return (
);
}
if (attrInputType === 'select') {
return (
<>
{attrName}
>
);
}
if (attrInputType === 'number') {
const [min, max, step] = attrValues;
return (
<>
{attrName}
{
if (typeof (value) !== 'undefined') {
changeAttribute(attrID, `${value}`);
}
}}
value={+attrValue}
className='cvat-object-item-number-attribute'
min={+min}
max={+max}
step={+step}
/>
>
);
}
return (
<>
{attrName}
): void => {
changeAttribute(attrID, event.target.value);
}}
value={attrValue}
className='cvat-object-item-text-attribute'
/>
>
);
}
const ItemAttribute = React.memo(ItemAttributeComponent, attrIsTheSame);
interface ItemAttributesComponentProps {
collapsed: boolean;
attributes: any[];
values: Record;
changeAttribute(attrID: number, value: string): void;
collapse(): void;
}
function attrValuesAreEqual(next: Record, prev: Record): boolean {
const prevKeys = Object.keys(prev);
const nextKeys = Object.keys(next);
return nextKeys.length === prevKeys.length
&& nextKeys.map((key: string): boolean => prev[+key] === next[+key])
.every((value: boolean) => value);
}
function attrAreTheSame(
prevProps: ItemAttributesComponentProps,
nextProps: ItemAttributesComponentProps,
): boolean {
return nextProps.collapsed === prevProps.collapsed
&& nextProps.attributes === prevProps.attributes
&& attrValuesAreEqual(nextProps.values, prevProps.values);
}
function ItemAttributesComponent(props: ItemAttributesComponentProps): JSX.Element {
const {
collapsed,
attributes,
values,
changeAttribute,
collapse,
} = props;
const sorted = [...attributes]
.sort((a: any, b: any): number => a.inputType.localeCompare(b.inputType));
return (
Details}
key='details'
>
{ sorted.map((attribute: any): JSX.Element => (
))}
);
}
const ItemAttributes = React.memo(ItemAttributesComponent, attrAreTheSame);
interface Props {
activated: boolean;
objectType: ObjectType;
shapeType: ShapeType;
clientID: number;
serverID: number | undefined;
labelID: number;
occluded: boolean;
outside: boolean | undefined;
locked: boolean;
pinned: boolean;
hidden: boolean;
keyframe: boolean | undefined;
attrValues: Record;
color: string;
colors: string[];
labels: any[];
attributes: any[];
collapsed: boolean;
navigateFirstKeyframe: null | (() => void);
navigatePrevKeyframe: null | (() => void);
navigateNextKeyframe: null | (() => void);
navigateLastKeyframe: null | (() => void);
activate(): void;
copy(): void;
propagate(): void;
createURL(): void;
toBackground(): void;
toForeground(): void;
remove(): void;
setOccluded(): void;
unsetOccluded(): void;
setOutside(): void;
unsetOutside(): void;
setKeyframe(): void;
unsetKeyframe(): void;
lock(): void;
unlock(): void;
pin(): void;
unpin(): void;
hide(): void;
show(): void;
changeLabel(labelID: string): void;
changeAttribute(attrID: number, value: string): void;
changeColor(color: string): void;
collapse(): void;
}
function objectItemsAreEqual(prevProps: Props, nextProps: Props): boolean {
return nextProps.activated === prevProps.activated
&& nextProps.locked === prevProps.locked
&& nextProps.pinned === prevProps.pinned
&& nextProps.occluded === prevProps.occluded
&& nextProps.outside === prevProps.outside
&& nextProps.hidden === prevProps.hidden
&& nextProps.keyframe === prevProps.keyframe
&& nextProps.labelID === prevProps.labelID
&& nextProps.color === prevProps.color
&& nextProps.clientID === prevProps.clientID
&& nextProps.serverID === prevProps.serverID
&& nextProps.objectType === prevProps.objectType
&& nextProps.shapeType === prevProps.shapeType
&& nextProps.collapsed === prevProps.collapsed
&& nextProps.labels === prevProps.labels
&& nextProps.attributes === prevProps.attributes
&& nextProps.navigateFirstKeyframe === prevProps.navigateFirstKeyframe
&& nextProps.navigatePrevKeyframe === prevProps.navigatePrevKeyframe
&& nextProps.navigateNextKeyframe === prevProps.navigateNextKeyframe
&& nextProps.navigateLastKeyframe === prevProps.navigateLastKeyframe
&& attrValuesAreEqual(nextProps.attrValues, prevProps.attrValues);
}
function ObjectItemComponent(props: Props): JSX.Element {
const {
activated,
objectType,
shapeType,
clientID,
serverID,
occluded,
outside,
locked,
pinned,
hidden,
keyframe,
attrValues,
labelID,
color,
colors,
attributes,
labels,
collapsed,
navigateFirstKeyframe,
navigatePrevKeyframe,
navigateNextKeyframe,
navigateLastKeyframe,
activate,
copy,
propagate,
createURL,
toBackground,
toForeground,
remove,
setOccluded,
unsetOccluded,
setOutside,
unsetOutside,
setKeyframe,
unsetKeyframe,
lock,
unlock,
pin,
unpin,
hide,
show,
changeLabel,
changeAttribute,
changeColor,
collapse,
} = props;
const type = objectType === ObjectType.TAG ? ObjectType.TAG.toUpperCase()
: `${shapeType.toUpperCase()} ${objectType.toUpperCase()}`;
const className = !activated ? 'cvat-objects-sidebar-state-item'
: 'cvat-objects-sidebar-state-item cvat-objects-sidebar-state-active-item';
return (
);
}
export default React.memo(ObjectItemComponent, objectItemsAreEqual);