Migration to mousetrap, redesigned visualization settings (#2872)

* Initial version of shortcut fixes using mousetrap

* Redesigned visualization settings

* Updated cypress tests

* Minor fix in AAM

* Aborted extra changes

* 1.1.0

* Updated version & changelog

* Aborted extra changes

* Fixed headers

* Using keycodes in cypress

* Fixed a couple of commands
main
Boris Sekachev 5 years ago committed by GitHub
parent dff57eb24b
commit fb17dca505
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- All methods for interative segmentation accept negative points as well - All methods for interative segmentation accept negative points as well
- Persistent queue added to logstash (<https://github.com/openvinotoolkit/cvat/pull/2744>) - Persistent queue added to logstash (<https://github.com/openvinotoolkit/cvat/pull/2744>)
- Improved maintanance of popups visibility (<https://github.com/openvinotoolkit/cvat/pull/2809>) - Improved maintanance of popups visibility (<https://github.com/openvinotoolkit/cvat/pull/2809>)
- Image visualizations settings on canvas for faster access (<https://github.com/openvinotoolkit/cvat/pull/2872>)
### Deprecated ### Deprecated
@ -56,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Polygon editing using trailing point (<https://github.com/openvinotoolkit/cvat/pull/2808>) - Polygon editing using trailing point (<https://github.com/openvinotoolkit/cvat/pull/2808>)
- Updated the path to python for DL models inside automatic annotation documentation (<https://github.com/openvinotoolkit/cvat/pull/2847>) - Updated the path to python for DL models inside automatic annotation documentation (<https://github.com/openvinotoolkit/cvat/pull/2847>)
- Fixed of receiving function variable (<https://github.com/openvinotoolkit/cvat/pull/2860>) - Fixed of receiving function variable (<https://github.com/openvinotoolkit/cvat/pull/2860>)
- Shortcuts with CAPSLOCK enabled and with non-US languages activated (<https://github.com/openvinotoolkit/cvat/pull/2872>)
### Security ### Security

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.14.3", "version": "1.15.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -1227,6 +1227,12 @@
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
"dev": true "dev": true
}, },
"@types/mousetrap": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.5.tgz",
"integrity": "sha512-OwVhKFim9Y/MprzCe4I6a59p31pMy8+LrtP6qS7J0kaOxYmW6VVJPBw5NYm+g7nSbgPUz22FvqU1F1hC5YGTfg==",
"dev": true
},
"@types/node": { "@types/node": {
"version": "14.14.2", "version": "14.14.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz",
@ -12873,7 +12879,7 @@
"cvat-canvas3d": { "cvat-canvas3d": {
"version": "file:../cvat-canvas3d", "version": "file:../cvat-canvas3d",
"requires": { "requires": {
"camera-controls": "1.25.3", "camera-controls": "^1.25.3",
"three": "^0.125.0" "three": "^0.125.0"
}, },
"dependencies": { "dependencies": {
@ -25965,6 +25971,11 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
}, },
"mousetrap": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA=="
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -28852,14 +28863,6 @@
"scheduler": "^0.19.1" "scheduler": "^0.19.1"
} }
}, },
"react-hotkeys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-hotkeys/-/react-hotkeys-2.0.0.tgz",
"integrity": "sha512-3n3OU8vLX/pfcJrR3xJ1zlww6KS1kEJt0Whxc4FiGV+MJrQ1mYSYI3qS/11d2MJDFm8IhOXMTFQirfu6AVOF6Q==",
"requires": {
"prop-types": "^15.6.1"
}
},
"react-is": { "react-is": {
"version": "16.11.0", "version": "16.11.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.14.3", "version": "1.15.0",
"description": "CVAT single-page application", "description": "CVAT single-page application",
"main": "src/index.tsx", "main": "src/index.tsx",
"scripts": { "scripts": {
@ -20,6 +20,7 @@
"@babel/preset-env": "^7.6.0", "@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.6.0", "@babel/preset-typescript": "^7.6.0",
"@types/mousetrap": "^1.6.5",
"@typescript-eslint/eslint-plugin": "^4.5.0", "@typescript-eslint/eslint-plugin": "^4.5.0",
"@typescript-eslint/parser": "^4.5.0", "@typescript-eslint/parser": "^4.5.0",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
@ -60,20 +61,20 @@
"@types/redux-logger": "^3.0.8", "@types/redux-logger": "^3.0.8",
"antd": "^4.12.2", "antd": "^4.12.2",
"copy-to-clipboard": "^3.3.1", "copy-to-clipboard": "^3.3.1",
"cvat-canvas3d": "file:../cvat-canvas3d",
"cvat-canvas": "file:../cvat-canvas", "cvat-canvas": "file:../cvat-canvas",
"cvat-canvas3d": "file:../cvat-canvas3d",
"cvat-core": "file:../cvat-core", "cvat-core": "file:../cvat-core",
"dotenv-webpack": "^1.8.0", "dotenv-webpack": "^1.8.0",
"error-stack-parser": "^2.0.6", "error-stack-parser": "^2.0.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.29.1", "moment": "^2.29.1",
"mousetrap": "^1.6.5",
"platform": "^1.3.6", "platform": "^1.3.6",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^16.14.0", "react": "^16.14.0",
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-cookie": "^4.0.3", "react-cookie": "^4.0.3",
"react-dom": "^16.14.0", "react-dom": "^16.14.0",
"react-hotkeys": "^2.0.0",
"react-redux": "^7.2.2", "react-redux": "^7.2.2",
"react-router": "^5.1.0", "react-router": "^5.1.0",
"react-router-dom": "^5.1.0", "react-router-dom": "^5.1.0",

@ -1,9 +1,9 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Layout, { SiderProps } from 'antd/lib/layout'; import Layout, { SiderProps } from 'antd/lib/layout';
import { SelectValue } from 'antd/lib/select'; import { SelectValue } from 'antd/lib/select';
@ -35,7 +35,7 @@ interface StateToProps {
states: any[]; states: any[];
labels: any[]; labels: any[];
jobInstance: any; jobInstance: any;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas; canvasInstance: Canvas;
canvasIsReady: boolean; canvasIsReady: boolean;
@ -295,7 +295,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
> >
{sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />} {sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />}
</span> </span>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<Row> <Row>
<Col span={24}> <Col span={24}>
<AnnotationsFiltersInput /> <AnnotationsFiltersInput />

@ -1,9 +1,9 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { GlobalHotKeys, KeyMap } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox'; import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Select, { SelectValue } from 'antd/lib/select'; import Select, { SelectValue } from 'antd/lib/select';
@ -150,7 +150,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
keyMap[key] = { keyMap[key] = {
name: `Set value "${value}"`, name: `Set value "${value}"`,
description: `Change current value for the attribute to "${value}"`, description: `Change current value for the attribute to "${value}"`,
sequence: `${index}`, sequences: [`${index}`],
action: 'keydown', action: 'keydown',
}; };
@ -165,7 +165,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
return ( return (
<div className='attribute-annotation-sidebar-attr-list-wrapper'> <div className='attribute-annotation-sidebar-attr-list-wrapper'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<div> <div>
<Text strong>0:</Text> <Text strong>0:</Text>
<Text>{` ${sortedValues[0]}`}</Text> <Text>{` ${sortedValues[0]}`}</Text>
@ -190,7 +190,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
keyMap[key] = { keyMap[key] = {
name: `Set value "${value}"`, name: `Set value "${value}"`,
description: `Change current value for the attribute to "${value}"`, description: `Change current value for the attribute to "${value}"`,
sequence: `${index}`, sequences: [`${index}`],
action: 'keydown', action: 'keydown',
}; };
@ -205,7 +205,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
return ( return (
<div className='attribute-annotation-sidebar-attr-list-wrapper'> <div className='attribute-annotation-sidebar-attr-list-wrapper'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={keyMap} handlers={handlers} />
{filteredValues.map( {filteredValues.map(
(value: string, index: number): JSX.Element => ( (value: string, index: number): JSX.Element => (
<div key={value}> <div key={value}>

@ -3,10 +3,11 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout'; import Layout from 'antd/lib/layout';
import Slider from 'antd/lib/slider'; import Slider from 'antd/lib/slider';
import { PlusCircleOutlined } from '@ant-design/icons'; import Dropdown from 'antd/lib/dropdown';
import { PlusCircleOutlined, UpOutlined } from '@ant-design/icons';
import { import {
ColorBy, GridColor, ObjectType, ContextMenuType, Workspace, ShapeType, ColorBy, GridColor, ObjectType, ContextMenuType, Workspace, ShapeType,
@ -16,6 +17,7 @@ import { Canvas } from 'cvat-canvas-wrapper';
import getCore from 'cvat-core-wrapper'; import getCore from 'cvat-core-wrapper';
import consts from 'consts'; import consts from 'consts';
import CVATTooltip from 'components/common/cvat-tooltip'; import CVATTooltip from 'components/common/cvat-tooltip';
import ImageSetupsContent from './image-setups-content';
const cvat = getCore(); const cvat = getCore();
@ -59,7 +61,7 @@ interface Props {
showAllInterpolationTracks: boolean; showAllInterpolationTracks: boolean;
workspace: Workspace; workspace: Workspace;
automaticBordering: boolean; automaticBordering: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
canvasBackgroundColor: string; canvasBackgroundColor: string;
switchableAutomaticBordering: boolean; switchableAutomaticBordering: boolean;
onSetupCanvas: () => void; onSetupCanvas: () => void;
@ -762,21 +764,9 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
minZLayer, minZLayer,
onSwitchZLayer, onSwitchZLayer,
onAddZLayer, onAddZLayer,
brightnessLevel,
contrastLevel,
saturationLevel,
keyMap, keyMap,
grid,
gridColor,
gridOpacity,
switchableAutomaticBordering, switchableAutomaticBordering,
automaticBordering, automaticBordering,
onChangeBrightnessLevel,
onChangeSaturationLevel,
onChangeContrastLevel,
onChangeGridColor,
onChangeGridOpacity,
onSwitchGrid,
onSwitchAutomaticBordering, onSwitchAutomaticBordering,
} = this.props; } = this.props;
@ -787,91 +777,10 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
}; };
const subKeyMap = { const subKeyMap = {
INCREASE_BRIGHTNESS: keyMap.INCREASE_BRIGHTNESS,
DECREASE_BRIGHTNESS: keyMap.DECREASE_BRIGHTNESS,
INCREASE_CONTRAST: keyMap.INCREASE_CONTRAST,
DECREASE_CONTRAST: keyMap.DECREASE_CONTRAST,
INCREASE_SATURATION: keyMap.INCREASE_SATURATION,
DECREASE_SATURATION: keyMap.DECREASE_SATURATION,
INCREASE_GRID_OPACITY: keyMap.INCREASE_GRID_OPACITY,
DECREASE_GRID_OPACITY: keyMap.DECREASE_GRID_OPACITY,
CHANGE_GRID_COLOR: keyMap.CHANGE_GRID_COLOR,
SWITCH_AUTOMATIC_BORDERING: keyMap.SWITCH_AUTOMATIC_BORDERING, SWITCH_AUTOMATIC_BORDERING: keyMap.SWITCH_AUTOMATIC_BORDERING,
}; };
const step = 10;
const handlers = { const handlers = {
INCREASE_BRIGHTNESS: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const maxLevel = 200;
if (brightnessLevel < maxLevel) {
onChangeBrightnessLevel(Math.min(brightnessLevel + step, maxLevel));
}
},
DECREASE_BRIGHTNESS: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const minLevel = 50;
if (brightnessLevel > minLevel) {
onChangeBrightnessLevel(Math.max(brightnessLevel - step, minLevel));
}
},
INCREASE_CONTRAST: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const maxLevel = 200;
if (contrastLevel < maxLevel) {
onChangeContrastLevel(Math.min(contrastLevel + step, maxLevel));
}
},
DECREASE_CONTRAST: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const minLevel = 50;
if (contrastLevel > minLevel) {
onChangeContrastLevel(Math.max(contrastLevel - step, minLevel));
}
},
INCREASE_SATURATION: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const maxLevel = 300;
if (saturationLevel < maxLevel) {
onChangeSaturationLevel(Math.min(saturationLevel + step, maxLevel));
}
},
DECREASE_SATURATION: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const minLevel = 0;
if (saturationLevel > minLevel) {
onChangeSaturationLevel(Math.max(saturationLevel - step, minLevel));
}
},
INCREASE_GRID_OPACITY: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const maxLevel = 100;
if (!grid) {
onSwitchGrid(true);
}
if (gridOpacity < maxLevel) {
onChangeGridOpacity(Math.min(gridOpacity + step, maxLevel));
}
},
DECREASE_GRID_OPACITY: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const minLevel = 0;
if (gridOpacity - step <= minLevel) {
onSwitchGrid(false);
}
if (gridOpacity > minLevel) {
onChangeGridOpacity(Math.max(gridOpacity - step, minLevel));
}
},
CHANGE_GRID_COLOR: (event: KeyboardEvent | undefined) => {
preventDefault(event);
const colors = [GridColor.Black, GridColor.Blue, GridColor.Green, GridColor.Red, GridColor.White];
const indexOf = colors.indexOf(gridColor) + 1;
const color = colors[indexOf >= colors.length ? 0 : indexOf];
onChangeGridColor(color);
},
SWITCH_AUTOMATIC_BORDERING: (event: KeyboardEvent | undefined) => { SWITCH_AUTOMATIC_BORDERING: (event: KeyboardEvent | undefined) => {
if (switchableAutomaticBordering) { if (switchableAutomaticBordering) {
preventDefault(event); preventDefault(event);
@ -882,7 +791,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
return ( return (
<Layout.Content style={{ position: 'relative' }}> <Layout.Content style={{ position: 'relative' }}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
{/* {/*
This element doesn't have any props This element doesn't have any props
So, React isn't going to rerender it So, React isn't going to rerender it
@ -896,6 +805,11 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
height: '100%', height: '100%',
}} }}
/> />
<Dropdown trigger='click' placement='topCenter' overlay={<ImageSetupsContent />}>
<UpOutlined className='cvat-canvas-image-setups-trigger' />
</Dropdown>
<div className='cvat-canvas-z-axis-wrapper'> <div className='cvat-canvas-z-axis-wrapper'>
<Slider <Slider
disabled={minZLayer === maxZLayer} disabled={minZLayer === maxZLayer}

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React, { ReactElement, useEffect, useRef } from 'react'; import React, { ReactElement, useEffect, useRef } from 'react';
import { GlobalHotKeys } from 'react-hotkeys';
import Layout from 'antd/lib/layout/layout'; import Layout from 'antd/lib/layout/layout';
import { import {
ArrowUpOutlined, ArrowRightOutlined, ArrowLeftOutlined, ArrowDownOutlined, ArrowUpOutlined, ArrowRightOutlined, ArrowLeftOutlined, ArrowDownOutlined,
@ -155,8 +154,6 @@ const CanvasWrapperComponent = (props: Props): ReactElement => {
return ( return (
<Layout.Content className='cvat-canvas3d-fullsize'> <Layout.Content className='cvat-canvas3d-fullsize'>
<GlobalHotKeys />
<ContextImage <ContextImage
frame={frameData} frame={frameData}
contextImageHide={contextImageHide} contextImageHide={contextImageHide}

@ -0,0 +1,189 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Row, Col } from 'antd/lib/grid';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Text from 'antd/lib/typography/Text';
import InputNumber from 'antd/lib/input-number';
import Select from 'antd/lib/select';
import Slider from 'antd/lib/slider';
import Button from 'antd/lib/button';
import {
switchGrid,
changeGridColor,
changeGridOpacity,
changeBrightnessLevel,
changeContrastLevel,
changeSaturationLevel,
changeGridSize,
} from 'actions/settings-actions';
import { clamp } from 'utils/math';
import { GridColor, CombinedState, PlayerSettingsState } from 'reducers/interfaces';
const minGridSize = 5;
const maxGridSize = 1000;
export default function ImageSetupsContent(): JSX.Element {
const dispatch = useDispatch();
const {
brightnessLevel,
contrastLevel,
saturationLevel,
gridOpacity,
gridColor,
gridSize,
grid: gridEnabled,
} = useSelector((state: CombinedState): PlayerSettingsState => state.settings.player);
return (
<div className='cvat-canvas-image-setups-content'>
<Text>Image grid</Text>
<hr />
<Row justify='space-between' align='middle' gutter={8}>
<Col span={1} />
<Col span={6}>
<Text className='cvat-text-color'> Size </Text>
</Col>
<Col span={8}>
<Text className='cvat-text-color'> Color </Text>
</Col>
<Col span={8}>
<Text className='cvat-text-color'> Opacity </Text>
</Col>
</Row>
<Row justify='space-between' align='middle' gutter={8}>
<Col span={1}>
<Checkbox
className='cvat-text-color cvat-image-setups-grid'
checked={gridEnabled}
onChange={(event: CheckboxChangeEvent): void => {
dispatch(switchGrid(event.target.checked));
}}
/>
</Col>
<Col span={6} className='cvat-image-setups-grid-size'>
<InputNumber
className='cvat-image-setups-grid-size-input'
min={minGridSize}
max={maxGridSize}
value={gridSize}
disabled={!gridEnabled}
onChange={(value: number | undefined | null | string): void => {
if (typeof value !== 'undefined' && value !== null) {
const converted = Math.floor(clamp(+value, minGridSize, maxGridSize));
dispatch(changeGridSize(converted));
}
}}
/>
</Col>
<Col span={8} className='cvat-image-setups-grid-color'>
<Select
className='cvat-image-setups-grid-color-input'
value={gridColor}
disabled={!gridEnabled}
onChange={(color: GridColor): void => {
dispatch(changeGridColor(color));
}}
>
<Select.Option key='white' value={GridColor.White}>
White
</Select.Option>
<Select.Option key='black' value={GridColor.Black}>
Black
</Select.Option>
<Select.Option key='red' value={GridColor.Red}>
Red
</Select.Option>
<Select.Option key='green' value={GridColor.Green}>
Green
</Select.Option>
<Select.Option key='blue' value={GridColor.Blue}>
Blue
</Select.Option>
</Select>
</Col>
<Col span={8} className='cvat-image-setups-grid-opacity'>
<Slider
className='cvat-image-setups-grid-opacity-input'
min={0}
max={100}
value={gridOpacity}
disabled={!gridEnabled}
onChange={(value: number | [number, number]): void => {
dispatch(changeGridOpacity(value as number));
}}
/>
</Col>
</Row>
<Text>Color settings</Text>
<hr />
<Row justify='space-around'>
<Col span={24}>
<Row className='cvat-image-setups-brightness'>
<Col span={6}>
<Text className='cvat-text-color'> Brightness </Text>
</Col>
<Col span={12}>
<Slider
min={50}
max={200}
value={brightnessLevel}
onChange={(value: number | [number, number]): void => {
dispatch(changeBrightnessLevel(value as number));
}}
/>
</Col>
</Row>
<Row className='cvat-image-setups-contrast'>
<Col span={6}>
<Text className='cvat-text-color'> Contrast </Text>
</Col>
<Col span={12}>
<Slider
min={50}
max={200}
value={contrastLevel}
onChange={(value: number | [number, number]): void => {
dispatch(changeContrastLevel(value as number));
}}
/>
</Col>
</Row>
<Row className='cvat-image-setups-saturation'>
<Col span={6}>
<Text className='cvat-text-color'> Saturation </Text>
</Col>
<Col span={12}>
<Slider
min={0}
max={300}
value={saturationLevel}
onChange={(value: number | [number, number]): void => {
dispatch(changeSaturationLevel(value as number));
}}
/>
</Col>
</Row>
<Row className='cvat-image-setups-reset-color-settings' justify='space-around'>
<Col>
<Button
onClick={() => {
const defaultValue = 100;
dispatch(changeBrightnessLevel(defaultValue));
dispatch(changeContrastLevel(defaultValue));
dispatch(changeSaturationLevel(defaultValue));
}}
>
Reset color settings
</Button>
</Col>
</Row>
</Col>
</Row>
</div>
);
}

@ -1,9 +1,9 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout'; import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces'; import { ActiveControl, Rotation } from 'reducers/interfaces';
@ -19,7 +19,7 @@ import IssueControl from './issue-control';
interface Props { interface Props {
canvasInstance: Canvas; canvasInstance: Canvas;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
rotateFrame(rotation: Rotation): void; rotateFrame(rotation: Rotation): void;
@ -64,7 +64,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return ( return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}> <Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<CursorControl <CursorControl
cursorShortkey={normalizedKeyMap.CANCEL} cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance} canvasInstance={canvasInstance}

@ -1,9 +1,9 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout'; import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces'; import { ActiveControl, Rotation } from 'reducers/interfaces';
@ -29,7 +29,7 @@ import SplitControl from './split-control';
interface Props { interface Props {
canvasInstance: Canvas; canvasInstance: Canvas;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
mergeObjects(enabled: boolean): void; mergeObjects(enabled: boolean): void;
@ -169,7 +169,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return ( return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}> <Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<CursorControl <CursorControl
cursorShortkey={normalizedKeyMap.CANCEL} cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance} canvasInstance={canvasInstance}

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { GlobalHotKeys } from 'react-hotkeys';
import Layout from 'antd/lib/layout'; import Layout from 'antd/lib/layout';
import { ActiveControl } from 'reducers/interfaces'; import { ActiveControl } from 'reducers/interfaces';
@ -31,8 +30,6 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return ( return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}> <Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys />
<MoveControl canvasInstance={canvasInstance} activeControl={activeControl} /> <MoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
<CursorControl <CursorControl

@ -238,6 +238,77 @@
} }
} }
.cvat-canvas-image-setups-trigger {
position: absolute;
background: $background-color-2;
bottom: 0;
left: 50%;
opacity: 0.5;
border-radius: 6px 6px 0 0;
border: 1px solid $border-color-3;
z-index: 100;
padding: 4px 12px;
&:hover {
opacity: 1;
}
&:active {
opacity: 0.75;
}
}
.cvat-canvas-image-setups-content {
background: $background-color-2;
padding: 8px;
border-radius: 6px;
opacity: 0.9;
}
.cvat-image-setups-grid {
margin-bottom: 25px;
> div:first-child {
margin-bottom: 10px;
}
}
.cvat-image-setups-grid-size,
.cvat-image-setups-grid-color,
.cvat-image-setups-opacity {
margin-bottom: 25px;
}
.cvat-image-setups-grid-size,
.cvat-image-setups-grid-color,
.cvat-image-setups-grid-opacity {
display: flex;
justify-items: start;
}
.cvat-image-setups-grid-size-input {
height: fit-content;
}
.cvat-image-setups-grid-color {
> .ant-select {
width: 150px;
}
}
.cvat-image-setups-grid-opacity {
> .ant-slider {
width: 150px;
}
}
.cvat-image-setups-reset-color-settings,
.cvat-image-setups-brightness,
.cvat-image-setups-contrast,
.cvat-image-setups-saturation {
width: 100%;
}
.cvat-canvas-z-axis-wrapper { .cvat-canvas-z-axis-wrapper {
position: absolute; position: absolute;
background: $background-color-2; background: $background-color-2;

@ -1,10 +1,10 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { GlobalHotKeys, KeyMap } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import Select from 'antd/lib/select'; import Select from 'antd/lib/select';
@ -60,7 +60,7 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
keyMap[key] = { keyMap[key] = {
name: `Setup ${label.name} tag`, name: `Setup ${label.name} tag`,
description: `Setup tag with "${label.name}" label`, description: `Setup tag with "${label.name}" label`,
sequence: `${id}`, sequences: [`${id}`],
action: 'keydown', action: 'keydown',
}; };
@ -81,7 +81,7 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
return ( return (
<div className='cvat-tag-annotation-label-selects'> <div className='cvat-tag-annotation-label-selects'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} />
<Row> <Row>
<Col> <Col>
<Text strong>Shortcuts for labels:</Text> <Text strong>Shortcuts for labels:</Text>

@ -1,10 +1,10 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { Action } from 'redux'; import { Action } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
@ -35,7 +35,7 @@ interface StateToProps {
jobInstance: any; jobInstance: any;
canvasInstance: Canvas; canvasInstance: Canvas;
frameNumber: number; frameNumber: number;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
} }
@ -198,7 +198,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
return ( return (
<> <>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<Layout.Sider {...siderProps}> <Layout.Sider {...siderProps}>
{/* eslint-disable-next-line */} {/* eslint-disable-next-line */}
<span <span

@ -27,7 +27,7 @@ import LoginPageContainer from 'containers/login-page/login-page';
import RegisterPageContainer from 'containers/register-page/register-page'; import RegisterPageContainer from 'containers/register-page/register-page';
import getCore from 'cvat-core-wrapper'; import getCore from 'cvat-core-wrapper';
import React from 'react'; import React from 'react';
import { configure, ExtendedKeyMapOptions, GlobalHotKeys } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { Redirect, Route, Switch } from 'react-router'; import { Redirect, Route, Switch } from 'react-router';
import { RouteComponentProps, withRouter } from 'react-router-dom'; import { RouteComponentProps, withRouter } from 'react-router-dom';
import { NotificationsState } from 'reducers/interfaces'; import { NotificationsState } from 'reducers/interfaces';
@ -47,7 +47,7 @@ interface CVATAppProps {
switchShortcutsDialog: () => void; switchShortcutsDialog: () => void;
switchSettingsDialog: () => void; switchSettingsDialog: () => void;
loadAuthActions: () => void; loadAuthActions: () => void;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
userInitialized: boolean; userInitialized: boolean;
userFetching: boolean; userFetching: boolean;
pluginsInitialized: boolean; pluginsInitialized: boolean;
@ -71,7 +71,7 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
public componentDidMount(): void { public componentDidMount(): void {
const core = getCore(); const core = getCore();
const { verifyAuthorized, history, location } = this.props; const { verifyAuthorized, history, location } = this.props;
configure({ ignoreRepeatedEventsWhenKeyHeldDown: false }); // configure({ ignoreRepeatedEventsWhenKeyHeldDown: false });
// Logger configuration // Logger configuration
const userActivityCallback: (() => void)[] = []; const userActivityCallback: (() => void)[] = [];
@ -256,12 +256,12 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
}; };
const handlers = { const handlers = {
SWITCH_SHORTCUTS: (event: KeyboardEvent | undefined) => { SWITCH_SHORTCUTS: (event: KeyboardEvent) => {
if (event) event.preventDefault(); if (event) event.preventDefault();
switchShortcutsDialog(); switchShortcutsDialog();
}, },
SWITCH_SETTINGS: (event: KeyboardEvent | undefined) => { SWITCH_SETTINGS: (event: KeyboardEvent) => {
if (event) event.preventDefault(); if (event) event.preventDefault();
switchSettingsDialog(); switchSettingsDialog();

@ -7,7 +7,6 @@ import React from 'react';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox'; import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import Slider from 'antd/lib/slider';
import Select from 'antd/lib/select'; import Select from 'antd/lib/select';
import Popover from 'antd/lib/popover'; import Popover from 'antd/lib/popover';
import InputNumber from 'antd/lib/input-number'; import InputNumber from 'antd/lib/input-number';
@ -17,7 +16,7 @@ import { CompactPicker } from 'react-color';
import { clamp } from 'utils/math'; import { clamp } from 'utils/math';
import { BackJumpIcon, ForwardJumpIcon } from 'icons'; import { BackJumpIcon, ForwardJumpIcon } from 'icons';
import { FrameSpeed, GridColor } from 'reducers/interfaces'; import { FrameSpeed } from 'reducers/interfaces';
import consts from 'consts'; import consts from 'consts';
interface Props { interface Props {
@ -25,25 +24,11 @@ interface Props {
frameSpeed: FrameSpeed; frameSpeed: FrameSpeed;
resetZoom: boolean; resetZoom: boolean;
rotateAll: boolean; rotateAll: boolean;
grid: boolean;
gridSize: number;
gridColor: GridColor;
gridOpacity: number;
brightnessLevel: number;
contrastLevel: number;
saturationLevel: number;
canvasBackgroundColor: string; canvasBackgroundColor: string;
onChangeFrameStep(step: number): void; onChangeFrameStep(step: number): void;
onChangeFrameSpeed(speed: FrameSpeed): void; onChangeFrameSpeed(speed: FrameSpeed): void;
onSwitchResetZoom(enabled: boolean): void; onSwitchResetZoom(enabled: boolean): void;
onSwitchRotateAll(rotateAll: boolean): void; onSwitchRotateAll(rotateAll: boolean): void;
onSwitchGrid(grid: boolean): void;
onChangeGridSize(gridSize: number): void;
onChangeGridColor(gridColor: GridColor): void;
onChangeGridOpacity(gridOpacity: number): void;
onChangeBrightnessLevel(level: number): void;
onChangeContrastLevel(level: number): void;
onChangeSaturationLevel(level: number): void;
onChangeCanvasBackgroundColor(color: string): void; onChangeCanvasBackgroundColor(color: string): void;
} }
@ -53,32 +38,16 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
frameSpeed, frameSpeed,
resetZoom, resetZoom,
rotateAll, rotateAll,
grid,
gridSize,
gridColor,
gridOpacity,
brightnessLevel,
contrastLevel,
saturationLevel,
canvasBackgroundColor, canvasBackgroundColor,
onChangeFrameStep, onChangeFrameStep,
onChangeFrameSpeed, onChangeFrameSpeed,
onSwitchResetZoom, onSwitchResetZoom,
onSwitchRotateAll, onSwitchRotateAll,
onSwitchGrid,
onChangeGridSize,
onChangeGridColor,
onChangeGridOpacity,
onChangeBrightnessLevel,
onChangeContrastLevel,
onChangeSaturationLevel,
onChangeCanvasBackgroundColor, onChangeCanvasBackgroundColor,
} = props; } = props;
const minFrameStep = 2; const minFrameStep = 2;
const maxFrameStep = 1000; const maxFrameStep = 1000;
const minGridSize = 5;
const maxGridSize = 1000;
return ( return (
<div className='cvat-player-settings'> <div className='cvat-player-settings'>
@ -89,8 +58,8 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
min={minFrameStep} min={minFrameStep}
max={maxFrameStep} max={maxFrameStep}
value={frameStep} value={frameStep}
onChange={(value: number | undefined | string): void => { onChange={(value: number | undefined | string | null): void => {
if (typeof value !== 'undefined') { if (typeof value !== 'undefined' && value !== null) {
onChangeFrameStep(Math.floor(clamp(+value, minFrameStep, maxFrameStep))); onChangeFrameStep(Math.floor(clamp(+value, minFrameStep, maxFrameStep)));
} }
}} }}
@ -169,77 +138,6 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Popover> </Popover>
</Col> </Col>
</Row> </Row>
<Row>
<Col>
<Checkbox
className='cvat-text-color cvat-player-settings-grid'
checked={grid}
onChange={(event: CheckboxChangeEvent): void => {
onSwitchGrid(event.target.checked);
}}
>
Show grid
</Checkbox>
</Col>
</Row>
<Row justify='space-between'>
<Col span={8} className='cvat-player-settings-grid-size'>
<Text className='cvat-text-color'> Grid size </Text>
<InputNumber
className='cvat-player-settings-grid-size-input'
min={minGridSize}
max={maxGridSize}
value={gridSize}
disabled={!grid}
onChange={(value: number | undefined | string): void => {
if (typeof value !== 'undefined') {
onChangeGridSize(Math.floor(clamp(+value, minGridSize, maxGridSize)));
}
}}
/>
</Col>
<Col span={8} className='cvat-player-settings-grid-color'>
<Text className='cvat-text-color'> Grid color </Text>
<Select
className='cvat-player-settings-grid-color-input'
value={gridColor}
disabled={!grid}
onChange={(color: GridColor): void => {
onChangeGridColor(color);
}}
>
<Select.Option key='white' value={GridColor.White}>
White
</Select.Option>
<Select.Option key='black' value={GridColor.Black}>
Black
</Select.Option>
<Select.Option key='red' value={GridColor.Red}>
Red
</Select.Option>
<Select.Option key='green' value={GridColor.Green}>
Green
</Select.Option>
<Select.Option key='blue' value={GridColor.Blue}>
Blue
</Select.Option>
</Select>
</Col>
<Col span={8} className='cvat-player-settings-grid-opacity'>
<Text className='cvat-text-color'> Grid opacity </Text>
<Slider
className='cvat-player-settings-grid-opacity-input'
min={0}
max={100}
value={gridOpacity}
disabled={!grid}
onChange={(value: number | [number, number]): void => {
onChangeGridOpacity(value as number);
}}
/>
<Text className='cvat-text-color'>{`${gridOpacity} %`}</Text>
</Col>
</Row>
<Row justify='start'> <Row justify='start'>
<Col span={7}> <Col span={7}>
<Row className='cvat-player-settings-reset-zoom'> <Row className='cvat-player-settings-reset-zoom'>
@ -278,68 +176,6 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Row> </Row>
</Col> </Col>
</Row> </Row>
<Row>
<Col span={12}>
<Row className='cvat-player-settings-brightness'>
<Col span={24} className='cvat-text-color'>
Brightness
</Col>
<Col span={24}>
<Slider
min={50}
max={200}
value={brightnessLevel}
onChange={(value: number | [number, number]): void => {
onChangeBrightnessLevel(value as number);
}}
/>
</Col>
</Row>
<Row className='cvat-player-settings-contrast'>
<Col span={24} className='cvat-text-color'>
Contrast
</Col>
<Col span={24}>
<Slider
min={50}
max={200}
value={contrastLevel}
onChange={(value: number | [number, number]): void => {
onChangeContrastLevel(value as number);
}}
/>
</Col>
</Row>
<Row className='cvat-player-settings-saturation'>
<Col span={24} className='cvat-text-color'>
Saturation
</Col>
<Col span={24}>
<Slider
min={0}
max={300}
value={saturationLevel}
onChange={(value: number | [number, number]): void => {
onChangeSaturationLevel(value as number);
}}
/>
</Col>
</Row>
<Row className='cvat-player-reset-color-settings'>
<Col>
<Button
onClick={() => {
onChangeBrightnessLevel(100);
onChangeContrastLevel(100);
onChangeSaturationLevel(100);
}}
>
Reset color settings
</Button>
</Col>
</Row>
</Col>
</Row>
</div> </div>
); );
} }

@ -23,7 +23,6 @@
padding: 24px; padding: 24px;
} }
.cvat-player-settings-grid,
.cvat-workspace-settings-auto-save, .cvat-workspace-settings-auto-save,
.cvat-workspace-settings-autoborders, .cvat-workspace-settings-autoborders,
.cvat-workspace-settings-show-text-always, .cvat-workspace-settings-show-text-always,
@ -35,9 +34,6 @@
} }
} }
.cvat-player-settings-grid-size,
.cvat-player-settings-grid-color,
.cvat-player-settings-grid-opacity,
.cvat-player-settings-step, .cvat-player-settings-step,
.cvat-player-settings-speed, .cvat-player-settings-speed,
.cvat-player-settings-reset-zoom, .cvat-player-settings-reset-zoom,
@ -48,29 +44,6 @@
margin-bottom: 25px; margin-bottom: 25px;
} }
.cvat-player-settings-grid-size,
.cvat-player-settings-grid-color,
.cvat-player-settings-grid-opacity {
display: grid;
justify-items: start;
}
.cvat-player-settings-grid-size-input {
height: fit-content;
}
.cvat-player-settings-grid-color {
> .ant-select {
width: 150px;
}
}
.cvat-player-settings-grid-opacity {
> .ant-slider {
width: 150px;
}
}
.cvat-player-settings-step, .cvat-player-settings-step,
.cvat-player-settings-speed { .cvat-player-settings-speed {
> div { > div {
@ -88,13 +61,6 @@
width: 90px; width: 90px;
} }
.cvat-player-reset-color-settings,
.cvat-player-settings-brightness,
.cvat-player-settings-contrast,
.cvat-player-settings-saturation {
width: 40%;
}
.cvat-player-reset-color-settings { .cvat-player-reset-color-settings {
> .ant-col { > .ant-col {
text-align: center; text-align: center;

@ -1,17 +1,19 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { GlobalHotKeys } from 'react-hotkeys'; import GlobalHotKeys from 'utils/mousetrap-react';
import { useSelector } from 'react-redux';
import { CombinedState } from 'reducers/interfaces';
import './styles.scss'; import './styles.scss';
const LayoutGrid = (): React.ReactPortal => { const LayoutGrid = (): React.ReactPortal => {
const [showGrid, setShowGrid] = useState(false); const [showGrid, setShowGrid] = useState(false);
const keyMap = useSelector((state: CombinedState) => state.shortcuts.keyMap);
const keyMap = { const subKeyMap = {
TOGGLE_LAYOUT_GRID: 'ctrl+alt+enter', TOGGLE_LAYOUT_GRID: keyMap.TOGGLE_LAYOUT_GRID,
}; };
const toggleLayoutGrid = useCallback((): void => { const toggleLayoutGrid = useCallback((): void => {
@ -23,9 +25,11 @@ const LayoutGrid = (): React.ReactPortal => {
}; };
const portalContent: JSX.Element = ( const portalContent: JSX.Element = (
<GlobalHotKeys keyMap={keyMap} handlers={handlers}> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers}>
{showGrid && <div className='grid sm' />} <>
{showGrid && <div className='grid lg' />} {showGrid && <div className='grid sm' />}
{showGrid && <div className='grid lg' />}
</>
</GlobalHotKeys> </GlobalHotKeys>
); );

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -6,7 +6,7 @@ import { shortcutsActions } from 'actions/shortcuts-actions';
import Modal from 'antd/lib/modal'; import Modal from 'antd/lib/modal';
import Table from 'antd/lib/table'; import Table from 'antd/lib/table';
import React from 'react'; import React from 'react';
import { getApplicationKeyMap } from 'react-hotkeys'; import { getApplicationKeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { CombinedState } from 'reducers/interfaces'; import { CombinedState } from 'reducers/interfaces';
@ -80,8 +80,8 @@ function ShorcutsDialog(props: StateToProps & DispatchToProps): JSX.Element | nu
key: id, key: id,
name: keyMap[key].name || key, name: keyMap[key].name || key,
description: keyMap[key].description || '', description: keyMap[key].description || '',
shortcut: keyMap[key].sequences.map((value) => value.sequence), shortcut: keyMap[key].sequences,
action: keyMap[key].sequences.map((value) => value.action || 'keydown'), action: [keyMap[key].action],
})); }));
return ( return (

@ -1,8 +1,8 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys'; import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import CanvasWrapperComponent from 'components/annotation-page/canvas/canvas-wrapper'; import CanvasWrapperComponent from 'components/annotation-page/canvas/canvas-wrapper';
@ -90,7 +90,7 @@ interface StateToProps {
curZLayer: number; curZLayer: number;
automaticBordering: boolean; automaticBordering: boolean;
switchableAutomaticBordering: boolean; switchableAutomaticBordering: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
canvasBackgroundColor: string; canvasBackgroundColor: string;
} }

@ -1,8 +1,8 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys'; import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas } from 'cvat-canvas-wrapper';
@ -24,7 +24,7 @@ interface StateToProps {
canvasInstance: Canvas; canvasInstance: Canvas;
rotateAll: boolean; rotateAll: boolean;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
} }

@ -1,8 +1,8 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys'; import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas } from 'cvat-canvas-wrapper';
@ -23,7 +23,7 @@ interface StateToProps {
canvasInstance: Canvas; canvasInstance: Canvas;
rotateAll: boolean; rotateAll: boolean;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
} }

@ -1,10 +1,10 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import ObjectsListComponent from 'components/annotation-page/standard-workspace/objects-side-bar/objects-list'; import ObjectsListComponent from 'components/annotation-page/standard-workspace/objects-side-bar/objects-list';
import { import {
@ -41,7 +41,7 @@ interface StateToProps {
minZLayer: number; minZLayer: number;
maxZLayer: number; maxZLayer: number;
annotationsFiltersHistory: string[]; annotationsFiltersHistory: string[];
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas; canvasInstance: Canvas;
} }
@ -442,7 +442,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
return ( return (
<> <>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<ObjectsListComponent <ObjectsListComponent
listHeight={listHeight} listHeight={listHeight}
statesHidden={statesHidden} statesHidden={statesHidden}

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys'; import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas } from 'cvat-canvas-wrapper';
@ -13,7 +13,7 @@ import { ActiveControl, CombinedState } from 'reducers/interfaces';
interface StateToProps { interface StateToProps {
canvasInstance: Canvas; canvasInstance: Canvas;
activeControl: ActiveControl; activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
contextImageHide: boolean; contextImageHide: boolean;
loaded: boolean; loaded: boolean;

@ -7,7 +7,7 @@ import copy from 'copy-to-clipboard';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import { RouteComponentProps } from 'react-router-dom'; import { RouteComponentProps } from 'react-router-dom';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys'; import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Input from 'antd/lib/input'; import Input from 'antd/lib/input';
import { import {
@ -45,7 +45,7 @@ interface StateToProps {
autoSave: boolean; autoSave: boolean;
autoSaveInterval: number; autoSaveInterval: number;
workspace: Workspace; workspace: Workspace;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas; canvasInstance: Canvas;
forceExit: boolean; forceExit: boolean;
@ -584,7 +584,7 @@ class AnnotationTopBarContainer extends React.PureComponent<Props, State> {
return ( return (
<> <>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<AnnotationTopBarComponent <AnnotationTopBarComponent
showStatistics={this.showStatistics} showStatistics={this.showStatistics}
onSwitchPlay={this.onSwitchPlay} onSwitchPlay={this.onSwitchPlay}

@ -1,41 +1,24 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PlayerSettingsComponent from 'components/header/settings-modal/player-settings'; import PlayerSettingsComponent from 'components/header/settings-modal/player-settings';
import { import {
changeFrameStep, changeFrameStep,
changeFrameSpeed, changeFrameSpeed,
switchResetZoom, switchResetZoom,
switchRotateAll, switchRotateAll,
switchGrid,
changeGridSize,
changeGridColor,
changeGridOpacity,
changeBrightnessLevel,
changeContrastLevel,
changeSaturationLevel,
changeCanvasBackgroundColor, changeCanvasBackgroundColor,
} from 'actions/settings-actions'; } from 'actions/settings-actions';
import { CombinedState, FrameSpeed } from 'reducers/interfaces';
import { CombinedState, FrameSpeed, GridColor } from 'reducers/interfaces';
interface StateToProps { interface StateToProps {
frameStep: number; frameStep: number;
frameSpeed: FrameSpeed; frameSpeed: FrameSpeed;
resetZoom: boolean; resetZoom: boolean;
rotateAll: boolean; rotateAll: boolean;
grid: boolean;
gridSize: number;
gridColor: GridColor;
gridOpacity: number;
brightnessLevel: number;
contrastLevel: number;
saturationLevel: number;
canvasBackgroundColor: string; canvasBackgroundColor: string;
} }
@ -44,13 +27,6 @@ interface DispatchToProps {
onChangeFrameSpeed(speed: FrameSpeed): void; onChangeFrameSpeed(speed: FrameSpeed): void;
onSwitchResetZoom(enabled: boolean): void; onSwitchResetZoom(enabled: boolean): void;
onSwitchRotateAll(rotateAll: boolean): void; onSwitchRotateAll(rotateAll: boolean): void;
onSwitchGrid(grid: boolean): void;
onChangeGridSize(gridSize: number): void;
onChangeGridColor(gridColor: GridColor): void;
onChangeGridOpacity(gridOpacity: number): void;
onChangeBrightnessLevel(level: number): void;
onChangeContrastLevel(level: number): void;
onChangeSaturationLevel(level: number): void;
onChangeCanvasBackgroundColor(color: string): void; onChangeCanvasBackgroundColor(color: string): void;
} }
@ -76,35 +52,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
onSwitchRotateAll(rotateAll: boolean): void { onSwitchRotateAll(rotateAll: boolean): void {
dispatch(switchRotateAll(rotateAll)); dispatch(switchRotateAll(rotateAll));
}, },
onSwitchGrid(grid: boolean): void {
dispatch(switchGrid(grid));
},
onChangeGridSize(gridSize: number): void {
dispatch(changeGridSize(gridSize));
},
onChangeGridColor(gridColor: GridColor): void {
dispatch(changeGridColor(gridColor));
},
onChangeGridOpacity(gridOpacity: number): void {
dispatch(changeGridOpacity(gridOpacity));
},
onChangeBrightnessLevel(level: number): void {
dispatch(changeBrightnessLevel(level));
},
onChangeContrastLevel(level: number): void {
dispatch(changeContrastLevel(level));
},
onChangeSaturationLevel(level: number): void {
dispatch(changeSaturationLevel(level));
},
onChangeCanvasBackgroundColor(color: string): void { onChangeCanvasBackgroundColor(color: string): void {
dispatch(changeCanvasBackgroundColor(color)); dispatch(changeCanvasBackgroundColor(color));
}, },
}; };
} }
function PlayerSettingsContainer(props: StateToProps & DispatchToProps): JSX.Element { export default connect(mapStateToProps, mapDispatchToProps)(PlayerSettingsComponent);
return <PlayerSettingsComponent {...props} />;
}
export default connect(mapStateToProps, mapDispatchToProps)(PlayerSettingsContainer);

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -16,7 +16,7 @@ import logger, { LogType } from 'cvat-logger';
import createCVATStore, { getCVATStore } from 'cvat-store'; import createCVATStore, { getCVATStore } from 'cvat-store';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { ExtendedKeyMapOptions } from 'react-hotkeys'; import { KeyMap } from 'utils/mousetrap-react';
import { connect, Provider } from 'react-redux'; import { connect, Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import createRootReducer from 'reducers/root-reducer'; import createRootReducer from 'reducers/root-reducer';
@ -45,7 +45,7 @@ interface StateToProps {
allowResetPassword: boolean; allowResetPassword: boolean;
notifications: NotificationsState; notifications: NotificationsState;
user: any; user: any;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
isModelPluginActive: boolean; isModelPluginActive: boolean;
} }

@ -2,11 +2,11 @@
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { Canvas, RectDrawingMethod } from 'cvat-canvas-wrapper';
import { IntelligentScissors } from 'utils/opencv-wrapper/intelligent-scissors';
import { MutableRefObject } from 'react'; import { MutableRefObject } from 'react';
import { Canvas, RectDrawingMethod } from 'cvat-canvas-wrapper';
import { Canvas3d } from 'cvat-canvas3d/src/typescript/canvas3d'; import { Canvas3d } from 'cvat-canvas3d/src/typescript/canvas3d';
import { IntelligentScissors } from 'utils/opencv-wrapper/intelligent-scissors';
import { KeyMap } from 'utils/mousetrap-react';
export type StringObject = { export type StringObject = {
[index: string]: string; [index: string]: string;
@ -539,7 +539,7 @@ export interface SettingsState {
export interface ShortcutsState { export interface ShortcutsState {
visibleShortcutsHelp: boolean; visibleShortcutsHelp: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>; keyMap: KeyMap;
normalizedKeyMap: Record<string, string>; normalizedKeyMap: Record<string, string>;
} }

@ -1,15 +1,14 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { BoundariesActions, BoundariesActionTypes } from 'actions/boundaries-actions'; import { BoundariesActions, BoundariesActionTypes } from 'actions/boundaries-actions';
import { AuthActions, AuthActionTypes } from 'actions/auth-actions'; import { AuthActions, AuthActionTypes } from 'actions/auth-actions';
import { ShortcutsActions, ShortcutsActionsTypes } from 'actions/shortcuts-actions'; import { ShortcutsActions, ShortcutsActionsTypes } from 'actions/shortcuts-actions';
import { KeyMap, KeyMapItem } from 'utils/mousetrap-react';
import { ShortcutsState } from './interfaces'; import { ShortcutsState } from './interfaces';
function formatShortcuts(shortcuts: ExtendedKeyMapOptions): string { function formatShortcuts(shortcuts: KeyMapItem): string {
const list: string[] = shortcuts.sequences as string[]; const list: string[] = shortcuts.sequences as string[];
return `[${list return `[${list
.map((shortcut: string): string => { .map((shortcut: string): string => {
@ -39,7 +38,7 @@ const defaultKeyMap = ({
SWITCH_ALL_LOCK: { SWITCH_ALL_LOCK: {
name: 'Lock/unlock all objects', name: 'Lock/unlock all objects',
description: 'Change locked state for all objects in the side bar', description: 'Change locked state for all objects in the side bar',
sequences: ['t+l'], sequences: ['t l'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_LOCK: { SWITCH_LOCK: {
@ -51,7 +50,7 @@ const defaultKeyMap = ({
SWITCH_ALL_HIDDEN: { SWITCH_ALL_HIDDEN: {
name: 'Hide/show all objects', name: 'Hide/show all objects',
description: 'Change hidden state for objects in the side bar', description: 'Change hidden state for objects in the side bar',
sequences: ['t+h'], sequences: ['t h'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_HIDDEN: { SWITCH_HIDDEN: {
@ -124,80 +123,25 @@ const defaultKeyMap = ({
NEXT_ATTRIBUTE: { NEXT_ATTRIBUTE: {
name: 'Next attribute', name: 'Next attribute',
description: 'Go to the next attribute', description: 'Go to the next attribute',
sequences: ['ArrowDown'], sequences: ['down'],
action: 'keydown', action: 'keydown',
}, },
PREVIOUS_ATTRIBUTE: { PREVIOUS_ATTRIBUTE: {
name: 'Previous attribute', name: 'Previous attribute',
description: 'Go to the previous attribute', description: 'Go to the previous attribute',
sequences: ['ArrowUp'], sequences: ['up'],
action: 'keydown', action: 'keydown',
}, },
NEXT_OBJECT: { NEXT_OBJECT: {
name: 'Next object', name: 'Next object',
description: 'Go to the next object', description: 'Go to the next object',
sequences: ['Tab'], sequences: ['tab'],
action: 'keydown', action: 'keydown',
}, },
PREVIOUS_OBJECT: { PREVIOUS_OBJECT: {
name: 'Previous object', name: 'Previous object',
description: 'Go to the previous object', description: 'Go to the previous object',
sequences: ['Shift+Tab'], sequences: ['shift+tab'],
action: 'keydown',
},
INCREASE_BRIGHTNESS: {
name: 'Brightness+',
description: 'Increase brightness level for the image',
sequences: ['shift+b+='],
action: 'keypress',
},
DECREASE_BRIGHTNESS: {
name: 'Brightness-',
description: 'Decrease brightness level for the image',
sequences: ['shift+b+-'],
action: 'keydown',
},
INCREASE_CONTRAST: {
name: 'Contrast+',
description: 'Increase contrast level for the image',
sequences: ['shift+c+='],
action: 'keydown',
},
DECREASE_CONTRAST: {
name: 'Contrast-',
description: 'Decrease contrast level for the image',
sequences: ['shift+c+-'],
action: 'keydown',
},
INCREASE_SATURATION: {
name: 'Saturation+',
description: 'Increase saturation level for the image',
sequences: ['shift+s+='],
action: 'keydown',
},
DECREASE_SATURATION: {
name: 'Saturation-',
description: 'Increase contrast level for the image',
sequences: ['shift+s+-'],
action: 'keydown',
},
INCREASE_GRID_OPACITY: {
name: 'Grid opacity+',
description: 'Make the grid more visible',
sequences: ['shift+g+='],
action: 'keydown',
},
DECREASE_GRID_OPACITY: {
name: 'Grid opacity-',
description: 'Make the grid less visible',
sequences: ['shift+g+-'],
action: 'keydown',
},
CHANGE_GRID_COLOR: {
name: 'Grid color',
description: 'Set another color for the image grid',
sequences: ['shift+g+enter'],
action: 'keydown', action: 'keydown',
}, },
@ -326,22 +270,28 @@ const defaultKeyMap = ({
FOCUS_INPUT_FRAME: { FOCUS_INPUT_FRAME: {
name: 'Focus input frame', name: 'Focus input frame',
description: 'Focus on the element to change the current frame', description: 'Focus on the element to change the current frame',
sequences: ['`', '~'], sequences: ['~'],
action: 'keydown', action: 'keydown',
}, },
SWITCH_AUTOMATIC_BORDERING: { SWITCH_AUTOMATIC_BORDERING: {
name: 'Switch automatic bordering', name: 'Switch automatic bordering',
description: 'Switch automatic bordering for polygons and polylines during drawing/editing', description: 'Switch automatic bordering for polygons and polylines during drawing/editing',
sequences: ['Control'], sequences: ['ctrl'],
action: 'keydown', action: 'keydown',
}, },
CHANGE_OBJECT_COLOR: { CHANGE_OBJECT_COLOR: {
name: 'Change color', name: 'Change color',
description: 'Set the next color for an activated shape', description: 'Set the next color for an activated shape',
sequences: ['Enter'], sequences: ['enter'],
action: 'keydown',
},
TOGGLE_LAYOUT_GRID: {
name: 'Toggle layout grid',
description: 'Is used in development',
sequences: ['ctrl+alt+enter'],
action: 'keydown', action: 'keydown',
}, },
} as any) as Record<string, ExtendedKeyMapOptions>; } as any) as KeyMap;
const defaultState: ShortcutsState = { const defaultState: ShortcutsState = {
visibleShortcutsHelp: false, visibleShortcutsHelp: false,

@ -0,0 +1,57 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React, { useEffect } from 'react';
import Mousetrap from 'mousetrap';
export interface KeyMapItem {
name: string;
description: string;
sequences: string[];
action: 'keydown' | 'keyup' | 'keypress';
}
export interface KeyMap {
[index: string]: KeyMapItem;
}
export interface Handlers {
[index: string]: (event: KeyboardEvent) => void;
}
interface Props {
children?: JSX.Element;
keyMap: KeyMap;
handlers: Handlers;
}
const applicationKeyMap: KeyMap = {};
export default function GlobalHotKeys(props: Props): JSX.Element {
const { children, keyMap, handlers } = props;
useEffect(() => {
for (const key of Object.keys(keyMap)) {
const { sequences, action } = keyMap[key];
const handler = handlers[key];
Mousetrap.bind(sequences, handler, action);
applicationKeyMap[key] = keyMap[key];
}
return () => {
for (const key of Object.keys(keyMap)) {
const { sequences, action } = keyMap[key];
Mousetrap.unbind(sequences, action);
delete applicationKeyMap[key];
}
};
});
return children || <></>;
}
export function getApplicationKeyMap(): KeyMap {
return {
...applicationKeyMap,
};
}

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -22,22 +22,20 @@ context('Canvas grid feature', () => {
before(() => { before(() => {
cy.openTaskJob(taskName); cy.openTaskJob(taskName);
cy.get('.cvat-canvas-image-setups-trigger').click();
}); });
describe(`Testing case "${caseId}"`, () => { describe(`Testing case "${caseId}"`, () => {
it('Go to settings.', () => {
cy.openSettings();
});
it('Set "Show grid" to true.', () => { it('Set "Show grid" to true.', () => {
cy.get('.cvat-player-settings-grid').click(); cy.get('.cvat-image-setups-grid').click();
}); });
it('Set "Grid size" to 50.', () => { it('Set "Grid size" to 50.', () => {
cy.get('.cvat-player-settings-grid-size-input').within(() => { cy.get('.cvat-image-setups-grid-size-input').within(() => {
cy.get('[role="spinbutton"]').clear().type(settingsGridSize); cy.get('[role="spinbutton"]').clear().type(settingsGridSize);
}); });
}); });
it('Set "Grid color" to black.', () => { it('Set "Grid color" to black.', () => {
cy.get('.cvat-player-settings-grid-color-input').click(); cy.get('.cvat-image-setups-grid-color-input').click();
cy.get('.ant-select-dropdown') cy.get('.ant-select-dropdown')
.not('.ant-select-dropdown-hidden') .not('.ant-select-dropdown-hidden')
.within(() => { .within(() => {
@ -45,7 +43,7 @@ context('Canvas grid feature', () => {
}); });
}); });
it('Set "Grid opacity" to 80%.', () => { it('Set "Grid opacity" to 80%.', () => {
cy.get('.cvat-player-settings-grid-opacity-input').within(() => { cy.get('.cvat-image-setups-grid-opacity-input').within(() => {
cy.get('[role="slider"]').type(generateString(20)); // Moving the slider to the left up to 80. cy.get('[role="slider"]').type(generateString(20)); // Moving the slider to the left up to 80.
cy.get('[role="slider"]').should('have.attr', 'aria-valuenow', gridOpacity); cy.get('[role="slider"]').should('have.attr', 'aria-valuenow', gridOpacity);
}); });

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -12,41 +12,45 @@ context('Canvas brightness/contrast/saturation feature', () => {
const defaultValueInSidebar = 100; const defaultValueInSidebar = 100;
const expectedResultInSetting = defaultValueInSidebar + countActionMoveSlider; const expectedResultInSetting = defaultValueInSidebar + countActionMoveSlider;
const classNameSliders = [ const classNameSliders = [
'.cvat-player-settings-brightness', '.cvat-image-setups-brightness',
'.cvat-player-settings-contrast', '.cvat-image-setups-contrast',
'.cvat-player-settings-saturation', '.cvat-image-setups-saturation',
]; ];
function generateStringCountAction(countAction) { function generateStringCountAction(countAction) {
let stringAction = ''; let stringAction = '';
for (let i = 0; i < countAction; i++) { for (let i = 0; i < countAction; i++) {
stringAction += '{rightarrow}'; stringAction += '{rightarrow}';
}; }
return stringAction; return stringAction;
}; }
function checkStateValuesInBackground(expectedValue) { function checkStateValuesInBackground(expectedValue) {
cy.get('#cvat_canvas_background') cy.get('#cvat_canvas_background')
.should('have.attr', 'style') .should('have.attr', 'style')
.and('contain', `filter: brightness(${expectedValue}) contrast(${expectedValue}) saturate(${expectedValue})`); .and(
}; 'contain',
`filter: brightness(${expectedValue}) contrast(${expectedValue}) saturate(${expectedValue})`,
);
}
before(() => { before(() => {
cy.openTaskJob(taskName); cy.openTaskJob(taskName);
cy.get('.cvat-canvas-image-setups-trigger').click();
}); });
describe(`Testing case "${caseId}"`, () => { describe(`Testing case "${caseId}"`, () => {
it('Check apply of settings', () => { it('Check apply of settings', () => {
let stringAction = generateStringCountAction(countActionMoveSlider); let stringAction = generateStringCountAction(countActionMoveSlider);
cy.openSettings(); cy.get('.cvat-canvas-image-setups-content').within(() => {
cy.get('.cvat-settings-modal').within(() => {
cy.contains('Player').click();
cy.wrap(classNameSliders).each(($el) => { cy.wrap(classNameSliders).each(($el) => {
cy.wrap($el).get($el).within(() => { cy.wrap($el)
cy.get('[role=slider]') .get($el)
.type(stringAction) .within(() => {
.should('have.attr', 'aria-valuenow', expectedResultInSetting); cy.get('[role=slider]')
}); .type(stringAction)
.should('have.attr', 'aria-valuenow', expectedResultInSetting);
});
}); });
}); });
const expectedResultInBackground = (defaultValueInSidebar + countActionMoveSlider) / 100; const expectedResultInBackground = (defaultValueInSidebar + countActionMoveSlider) / 100;
@ -54,7 +58,7 @@ context('Canvas brightness/contrast/saturation feature', () => {
}); });
it('Check reset of settings', () => { it('Check reset of settings', () => {
cy.get('.cvat-player-reset-color-settings').click(); cy.get('.cvat-image-setups-reset-color-settings').find('button').click();
const expectedResultInBackground = defaultValueInSidebar / 100; const expectedResultInBackground = defaultValueInSidebar / 100;
checkStateValuesInBackground(expectedResultInBackground); checkStateValuesInBackground(expectedResultInBackground);
}); });

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -24,11 +24,12 @@ context('Check hide functionality (H)', () => {
describe(`Testing issue "${issueId}"`, () => { describe(`Testing issue "${issueId}"`, () => {
it('Object is hidden', () => { it('Object is hidden', () => {
const keyCodeH = 72;
cy.createRectangle(createRectangleShape2Points); cy.createRectangle(createRectangleShape2Points);
cy.get('#cvat_canvas_shape_1') cy.get('#cvat_canvas_shape_1')
.trigger('mousemove') .trigger('mousemove')
.trigger('mouseover') .trigger('mouseover')
.trigger('keydown', { key: 'h' }) .trigger('keydown', { keyCode: keyCodeH })
.should('be.hidden'); .should('be.hidden');
}); });
}); });

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -22,11 +22,12 @@ context('Check if the UI not to crash after remove a tag', () => {
cy.changeWorkspace('Standard'); cy.changeWorkspace('Standard');
}); });
it('Remove the tag', () => { it('Remove the tag', () => {
const keyCodeDel = 46;
cy.get('#cvat-objects-sidebar-state-item-1') cy.get('#cvat-objects-sidebar-state-item-1')
.should('contain', '1') .should('contain', '1')
.and('contain', 'TAG') .and('contain', 'TAG')
.trigger('mouseover') .trigger('mouseover')
.trigger('keydown', { key: 'Delete' }); .trigger('keydown', { keyCode: keyCodeDel });
}); });
it('Page with the error is missing', () => { it('Page with the error is missing', () => {
cy.contains('Oops, something went wrong').should('not.exist'); cy.contains('Oops, something went wrong').should('not.exist');

@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation // Copyright (C) 2020-2021 Intel Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -43,10 +43,11 @@ context("The points of the previous polygon mustn't appear while polygon's inter
cy.get('#cvat-objects-sidebar-state-item-1').should('contain', '1').and('contain', 'POLYGON TRACK'); cy.get('#cvat-objects-sidebar-state-item-1').should('contain', '1').and('contain', 'POLYGON TRACK');
}); });
it('Redraw the polygon', () => { it('Redraw the polygon', () => {
const keyCodeN = 78;
cy.get('#cvat_canvas_shape_1') cy.get('#cvat_canvas_shape_1')
.trigger('mousemove', { force: true }) .trigger('mousemove', { force: true })
.trigger('keydown', { key: 'n', shiftKey: true }) .trigger('keydown', { keyCode: keyCodeN, shiftKey: true })
.trigger('keyup', { force: true }, { key: 'n', shiftKey: true }); .trigger('keyup', { force: true }, { keyCode: keyCodeN, shiftKey: true });
cy.createPolygon(reDrawPolygonTrack); cy.createPolygon(reDrawPolygonTrack);
}); });
it('Activate auto bordering mode', () => { it('Activate auto bordering mode', () => {

@ -216,7 +216,10 @@ Cypress.Commands.add('createPoint', (createPointParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y); cy.get('.cvat-canvas-container').click(element.x, element.y);
}); });
if (createPointParams.complete) { if (createPointParams.complete) {
cy.get('.cvat-canvas-container').trigger('keydown', { key: 'n' }).trigger('keyup', { key: 'n' }); const keyCodeN = 78;
cy.get('.cvat-canvas-container')
.trigger('keydown', { keyCode: keyCodeN })
.trigger('keyup', { keyCode: keyCodeN });
} }
cy.checkObjectParameters(createPointParams, 'POINTS'); cy.checkObjectParameters(createPointParams, 'POINTS');
}); });
@ -228,14 +231,15 @@ Cypress.Commands.add('changeAppearance', (colorBy) => {
}); });
Cypress.Commands.add('shapeGrouping', (firstX, firstY, lastX, lastY) => { Cypress.Commands.add('shapeGrouping', (firstX, firstY, lastX, lastY) => {
const keyCodeG = 71;
cy.get('.cvat-canvas-container') cy.get('.cvat-canvas-container')
.trigger('keydown', { key: 'g' }) .trigger('keydown', { keyCode: keyCodeG })
.trigger('keyup', { key: 'g' }) .trigger('keyup', { keyCode: keyCodeG })
.trigger('mousedown', firstX, firstY, { which: 1 }) .trigger('mousedown', firstX, firstY, { which: 1 })
.trigger('mousemove', lastX, lastY) .trigger('mousemove', lastX, lastY)
.trigger('mouseup', lastX, lastY) .trigger('mouseup', lastX, lastY)
.trigger('keydown', { key: 'g' }) .trigger('keydown', { keyCode: keyCodeG })
.trigger('keyup', { key: 'g' }); .trigger('keyup', { keyCode: keyCodeG });
}); });
Cypress.Commands.add('createPolygon', (createPolygonParams) => { Cypress.Commands.add('createPolygon', (createPolygonParams) => {
@ -257,7 +261,10 @@ Cypress.Commands.add('createPolygon', (createPolygonParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y); cy.get('.cvat-canvas-container').click(element.x, element.y);
}); });
if (createPolygonParams.complete) { if (createPolygonParams.complete) {
cy.get('.cvat-canvas-container').trigger('keydown', { key: 'n' }).trigger('keyup', { key: 'n' }); const keyCodeN = 78;
cy.get('.cvat-canvas-container')
.trigger('keydown', { keyCode: keyCodeN })
.trigger('keyup', { keyCode: keyCodeN });
} }
cy.checkObjectParameters(createPolygonParams, 'POLYGON'); cy.checkObjectParameters(createPolygonParams, 'POLYGON');
}); });
@ -383,7 +390,10 @@ Cypress.Commands.add('createPolyline', (createPolylineParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y); cy.get('.cvat-canvas-container').click(element.x, element.y);
}); });
if (createPolylineParams.complete) { if (createPolylineParams.complete) {
cy.get('.cvat-canvas-container').trigger('keydown', { key: 'n' }).trigger('keyup', { key: 'n' }); const keyCodeN = 78;
cy.get('.cvat-canvas-container')
.trigger('keydown', { keyCode: keyCodeN })
.trigger('keyup', { keyCode: keyCodeN });
} }
cy.checkObjectParameters(createPolylineParams, 'POLYLINE'); cy.checkObjectParameters(createPolylineParams, 'POLYLINE');
}); });

Loading…
Cancel
Save