// 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 ( { objectType !== ObjectType.TAG && ( <> )} ); } 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 (
{attrName} { changeAttribute(attrID, event.target.value); }} > { attrValues.map((value: string): JSX.Element => ( {value} )) }
); } 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);