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.

525 lines
14 KiB
TypeScript

// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import copy from 'copy-to-clipboard';
import { connect } from 'react-redux';
import {
ActiveControl,
CombinedState,
ColorBy,
} from 'reducers/interfaces';
import {
collapseObjectItems,
changeLabelColorAsync,
createAnnotationsAsync,
updateAnnotationsAsync,
changeFrameAsync,
removeObjectAsync,
changeGroupColorAsync,
copyShape as copyShapeAction,
activateObject as activateObjectAction,
propagateObject as propagateObjectAction,
pasteShapeAsync,
} from 'actions/annotation-actions';
import ObjectStateItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/object-item';
interface OwnProps {
clientID: number;
}
interface StateToProps {
objectState: any;
collapsed: boolean;
labels: any[];
attributes: any[];
jobInstance: any;
frameNumber: number;
activated: boolean;
colorBy: ColorBy;
ready: boolean;
colors: string[];
activeControl: ActiveControl;
minZLayer: number;
maxZLayer: number;
}
interface DispatchToProps {
changeFrame(frame: number): void;
updateState(objectState: any): void;
createAnnotations(sessionInstance: any, frameNumber: number, state: any): void;
collapseOrExpand(objectStates: any[], collapsed: boolean): void;
activateObject: (activatedStateID: number | null) => void;
removeObject: (sessionInstance: any, objectState: any) => void;
copyShape: (objectState: any) => void;
propagateObject: (objectState: any) => void;
changeLabelColor(sessionInstance: any, frameNumber: number, label: any, color: string): void;
changeGroupColor(group: number, color: string): void;
}
function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const {
annotation: {
annotations: {
states,
collapsed: statesCollapsed,
activatedStateID,
zLayer: {
min: minZLayer,
max: maxZLayer,
},
},
job: {
attributes: jobAttributes,
instance: jobInstance,
labels,
},
player: {
frame: {
number: frameNumber,
},
},
canvas: {
ready,
activeControl,
},
colors,
},
settings: {
shapes: {
colorBy,
},
},
} = state;
const index = states
.map((_state: any): number => _state.clientID)
.indexOf(own.clientID);
const collapsedState = typeof (statesCollapsed[own.clientID]) === 'undefined'
? true : statesCollapsed[own.clientID];
return {
objectState: states[index],
collapsed: collapsedState,
attributes: jobAttributes[states[index].label.id],
labels,
ready,
activeControl,
colorBy,
colors,
jobInstance,
frameNumber,
activated: activatedStateID === own.clientID,
minZLayer,
maxZLayer,
};
}
function mapDispatchToProps(dispatch: any): DispatchToProps {
return {
changeFrame(frame: number): void {
dispatch(changeFrameAsync(frame));
},
updateState(state: any): void {
dispatch(updateAnnotationsAsync([state]));
},
createAnnotations(sessionInstance: any, frameNumber: number, state: any): void {
dispatch(createAnnotationsAsync(sessionInstance, frameNumber, state));
},
collapseOrExpand(objectStates: any[], collapsed: boolean): void {
dispatch(collapseObjectItems(objectStates, collapsed));
},
activateObject(activatedStateID: number | null): void {
dispatch(activateObjectAction(activatedStateID, null));
},
removeObject(sessionInstance: any, objectState: any): void {
dispatch(removeObjectAsync(sessionInstance, objectState, true));
},
copyShape(objectState: any): void {
dispatch(copyShapeAction(objectState));
dispatch(pasteShapeAsync());
},
propagateObject(objectState: any): void {
dispatch(propagateObjectAction(objectState));
},
changeLabelColor(
sessionInstance: any,
frameNumber: number,
label: any,
color: string,
): void {
dispatch(changeLabelColorAsync(sessionInstance, frameNumber, label, color));
},
changeGroupColor(group: number, color: string): void {
dispatch(changeGroupColorAsync(group, color));
},
};
}
type Props = StateToProps & DispatchToProps;
class ObjectItemContainer extends React.PureComponent<Props> {
private navigateFirstKeyframe = (): void => {
const {
objectState,
changeFrame,
frameNumber,
} = this.props;
const { first } = objectState.keyframes;
if (first !== frameNumber) {
changeFrame(first);
}
};
private navigatePrevKeyframe = (): void => {
const {
objectState,
changeFrame,
frameNumber,
} = this.props;
const { prev } = objectState.keyframes;
if (prev !== null && prev !== frameNumber) {
changeFrame(prev);
}
};
private navigateNextKeyframe = (): void => {
const {
objectState,
changeFrame,
frameNumber,
} = this.props;
const { next } = objectState.keyframes;
if (next !== null && next !== frameNumber) {
changeFrame(next);
}
};
private navigateLastKeyframe = (): void => {
const {
objectState,
changeFrame,
frameNumber,
} = this.props;
const { last } = objectState.keyframes;
if (last !== frameNumber) {
changeFrame(last);
}
};
private copy = (): void => {
const {
objectState,
copyShape,
} = this.props;
copyShape(objectState);
};
private propagate = (): void => {
const {
objectState,
propagateObject,
} = this.props;
propagateObject(objectState);
};
private remove = (): void => {
const {
objectState,
removeObject,
jobInstance,
} = this.props;
removeObject(jobInstance, objectState);
};
private createURL = (): void => {
const {
objectState,
frameNumber,
} = this.props;
const {
origin,
pathname,
} = window.location;
const search = `frame=${frameNumber}&object=${objectState.serverID}`;
const url = `${origin}${pathname}?${search}`;
copy(url);
};
private toBackground = (): void => {
const {
objectState,
minZLayer,
} = this.props;
objectState.zOrder = minZLayer - 1;
this.commit();
};
private toForeground = (): void => {
const {
objectState,
maxZLayer,
} = this.props;
objectState.zOrder = maxZLayer + 1;
this.commit();
};
private activate = (): void => {
const {
activateObject,
objectState,
ready,
activeControl,
} = this.props;
if (ready && activeControl === ActiveControl.CURSOR) {
activateObject(objectState.clientID);
}
};
private lock = (): void => {
const { objectState } = this.props;
objectState.lock = true;
this.commit();
};
private unlock = (): void => {
const { objectState } = this.props;
objectState.lock = false;
this.commit();
};
private pin = (): void => {
const { objectState } = this.props;
objectState.pinned = true;
this.commit();
};
private unpin = (): void => {
const { objectState } = this.props;
objectState.pinned = false;
this.commit();
};
private show = (): void => {
const { objectState } = this.props;
objectState.hidden = false;
this.commit();
};
private hide = (): void => {
const { objectState } = this.props;
objectState.hidden = true;
this.commit();
};
private setOccluded = (): void => {
const { objectState } = this.props;
objectState.occluded = true;
this.commit();
};
private unsetOccluded = (): void => {
const { objectState } = this.props;
objectState.occluded = false;
this.commit();
};
private setOutside = (): void => {
const { objectState } = this.props;
objectState.outside = true;
this.commit();
};
private unsetOutside = (): void => {
const { objectState } = this.props;
objectState.outside = false;
this.commit();
};
private setKeyframe = (): void => {
const { objectState } = this.props;
objectState.keyframe = true;
this.commit();
};
private unsetKeyframe = (): void => {
const { objectState } = this.props;
objectState.keyframe = false;
this.commit();
};
private collapse = (): void => {
const {
collapseOrExpand,
objectState,
collapsed,
} = this.props;
collapseOrExpand([objectState], !collapsed);
};
private changeColor = (color: string): void => {
const {
jobInstance,
objectState,
colorBy,
changeLabelColor,
changeGroupColor,
frameNumber,
} = this.props;
if (colorBy === ColorBy.INSTANCE) {
objectState.color = color;
this.commit();
} else if (colorBy === ColorBy.GROUP) {
changeGroupColor(objectState.group.id, color);
} else if (colorBy === ColorBy.LABEL) {
changeLabelColor(jobInstance, frameNumber, objectState.label, color);
}
};
private changeLabel = (labelID: string): void => {
const {
objectState,
labels,
} = this.props;
const [label] = labels.filter((_label: any): boolean => _label.id === +labelID);
objectState.label = label;
this.commit();
};
private changeAttribute = (id: number, value: string): void => {
const { objectState } = this.props;
const attr: Record<number, string> = {};
attr[id] = value;
objectState.attributes = attr;
this.commit();
};
private commit(): void {
const {
objectState,
updateState,
} = this.props;
updateState(objectState);
}
public render(): JSX.Element {
const {
objectState,
collapsed,
labels,
attributes,
frameNumber,
activated,
colorBy,
colors,
} = this.props;
const {
first,
prev,
next,
last,
} = objectState.keyframes || {
first: null, // shapes don't have keyframes, so we use null
prev: null,
next: null,
last: null,
};
let stateColor = '';
if (colorBy === ColorBy.INSTANCE) {
stateColor = objectState.color;
} else if (colorBy === ColorBy.GROUP) {
stateColor = objectState.group.color;
} else if (colorBy === ColorBy.LABEL) {
stateColor = objectState.label.color;
}
return (
<ObjectStateItemComponent
activated={activated}
objectType={objectState.objectType}
shapeType={objectState.shapeType}
clientID={objectState.clientID}
serverID={objectState.serverID}
occluded={objectState.occluded}
outside={objectState.outside}
locked={objectState.lock}
pinned={objectState.pinned}
hidden={objectState.hidden}
keyframe={objectState.keyframe}
attrValues={{ ...objectState.attributes }}
labelID={objectState.label.id}
color={stateColor}
colors={colors}
attributes={attributes}
labels={labels}
collapsed={collapsed}
navigateFirstKeyframe={
first >= frameNumber || first === null
? null : this.navigateFirstKeyframe
}
navigatePrevKeyframe={
prev === frameNumber || prev === null
? null : this.navigatePrevKeyframe
}
navigateNextKeyframe={
next === frameNumber || next === null
? null : this.navigateNextKeyframe
}
navigateLastKeyframe={
last <= frameNumber || last === null
? null : this.navigateLastKeyframe
}
activate={this.activate}
remove={this.remove}
copy={this.copy}
propagate={this.propagate}
createURL={this.createURL}
toBackground={this.toBackground}
toForeground={this.toForeground}
setOccluded={this.setOccluded}
unsetOccluded={this.unsetOccluded}
setOutside={this.setOutside}
unsetOutside={this.unsetOutside}
setKeyframe={this.setKeyframe}
unsetKeyframe={this.unsetKeyframe}
lock={this.lock}
unlock={this.unlock}
pin={this.pin}
unpin={this.unpin}
hide={this.hide}
show={this.show}
changeColor={this.changeColor}
changeLabel={this.changeLabel}
changeAttribute={this.changeAttribute}
collapse={this.collapse}
/>
);
}
}
export default connect<StateToProps, DispatchToProps, OwnProps, CombinedState>(
mapStateToProps,
mapDispatchToProps,
)(ObjectItemContainer);