未验证 提交 fb17dca5 编写于 作者: B Boris Sekachev 提交者: GitHub

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
上级 dff57eb2
......@@ -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
- Persistent queue added to logstash (<https://github.com/openvinotoolkit/cvat/pull/2744>)
- 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
......@@ -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>)
- 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>)
- Shortcuts with CAPSLOCK enabled and with non-US languages activated (<https://github.com/openvinotoolkit/cvat/pull/2872>)
### Security
......
{
"name": "cvat-ui",
"version": "1.14.3",
"version": "1.15.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -1227,6 +1227,12 @@
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
"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": {
"version": "14.14.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz",
......@@ -12873,7 +12879,7 @@
"cvat-canvas3d": {
"version": "file:../cvat-canvas3d",
"requires": {
"camera-controls": "1.25.3",
"camera-controls": "^1.25.3",
"three": "^0.125.0"
},
"dependencies": {
......@@ -25965,6 +25971,11 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"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": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
......@@ -28852,14 +28863,6 @@
"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": {
"version": "16.11.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz",
{
"name": "cvat-ui",
"version": "1.14.3",
"version": "1.15.0",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
......@@ -20,6 +20,7 @@
"@babel/preset-env": "^7.6.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.6.0",
"@types/mousetrap": "^1.6.5",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"@typescript-eslint/parser": "^4.5.0",
"babel-loader": "^8.0.6",
......@@ -60,20 +61,20 @@
"@types/redux-logger": "^3.0.8",
"antd": "^4.12.2",
"copy-to-clipboard": "^3.3.1",
"cvat-canvas3d": "file:../cvat-canvas3d",
"cvat-canvas": "file:../cvat-canvas",
"cvat-canvas3d": "file:../cvat-canvas3d",
"cvat-core": "file:../cvat-core",
"dotenv-webpack": "^1.8.0",
"error-stack-parser": "^2.0.6",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"mousetrap": "^1.6.5",
"platform": "^1.3.6",
"prop-types": "^15.7.2",
"react": "^16.14.0",
"react-color": "^2.19.3",
"react-cookie": "^4.0.3",
"react-dom": "^16.14.0",
"react-hotkeys": "^2.0.0",
"react-redux": "^7.2.2",
"react-router": "^5.1.0",
"react-router-dom": "^5.1.0",
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
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 Layout, { SiderProps } from 'antd/lib/layout';
import { SelectValue } from 'antd/lib/select';
......@@ -35,7 +35,7 @@ interface StateToProps {
states: any[];
labels: any[];
jobInstance: any;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas;
canvasIsReady: boolean;
......@@ -295,7 +295,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
>
{sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />}
</span>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<Row>
<Col span={24}>
<AnnotationsFiltersInput />
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
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 Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Select, { SelectValue } from 'antd/lib/select';
......@@ -150,7 +150,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
keyMap[key] = {
name: `Set value "${value}"`,
description: `Change current value for the attribute to "${value}"`,
sequence: `${index}`,
sequences: [`${index}`],
action: 'keydown',
};
......@@ -165,7 +165,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
return (
<div className='attribute-annotation-sidebar-attr-list-wrapper'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<div>
<Text strong>0:</Text>
<Text>{` ${sortedValues[0]}`}</Text>
......@@ -190,7 +190,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
keyMap[key] = {
name: `Set value "${value}"`,
description: `Change current value for the attribute to "${value}"`,
sequence: `${index}`,
sequences: [`${index}`],
action: 'keydown',
};
......@@ -205,7 +205,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
return (
<div className='attribute-annotation-sidebar-attr-list-wrapper'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
{filteredValues.map(
(value: string, index: number): JSX.Element => (
<div key={value}>
......
......@@ -3,10 +3,11 @@
// SPDX-License-Identifier: MIT
import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout';
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 {
ColorBy, GridColor, ObjectType, ContextMenuType, Workspace, ShapeType,
......@@ -16,6 +17,7 @@ import { Canvas } from 'cvat-canvas-wrapper';
import getCore from 'cvat-core-wrapper';
import consts from 'consts';
import CVATTooltip from 'components/common/cvat-tooltip';
import ImageSetupsContent from './image-setups-content';
const cvat = getCore();
......@@ -59,7 +61,7 @@ interface Props {
showAllInterpolationTracks: boolean;
workspace: Workspace;
automaticBordering: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
canvasBackgroundColor: string;
switchableAutomaticBordering: boolean;
onSetupCanvas: () => void;
......@@ -762,21 +764,9 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
minZLayer,
onSwitchZLayer,
onAddZLayer,
brightnessLevel,
contrastLevel,
saturationLevel,
keyMap,
grid,
gridColor,
gridOpacity,
switchableAutomaticBordering,
automaticBordering,
onChangeBrightnessLevel,
onChangeSaturationLevel,
onChangeContrastLevel,
onChangeGridColor,
onChangeGridOpacity,
onSwitchGrid,
onSwitchAutomaticBordering,
} = this.props;
......@@ -787,91 +777,10 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
};
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,
};
const step = 10;
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) => {
if (switchableAutomaticBordering) {
preventDefault(event);
......@@ -882,7 +791,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
return (
<Layout.Content style={{ position: 'relative' }}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
{/*
This element doesn't have any props
So, React isn't going to rerender it
......@@ -896,6 +805,11 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
height: '100%',
}}
/>
<Dropdown trigger='click' placement='topCenter' overlay={<ImageSetupsContent />}>
<UpOutlined className='cvat-canvas-image-setups-trigger' />
</Dropdown>
<div className='cvat-canvas-z-axis-wrapper'>
<Slider
disabled={minZLayer === maxZLayer}
......
......@@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT
import React, { ReactElement, useEffect, useRef } from 'react';
import { GlobalHotKeys } from 'react-hotkeys';
import Layout from 'antd/lib/layout/layout';
import {
ArrowUpOutlined, ArrowRightOutlined, ArrowLeftOutlined, ArrowDownOutlined,
......@@ -155,8 +154,6 @@ const CanvasWrapperComponent = (props: Props): ReactElement => {
return (
<Layout.Content className='cvat-canvas3d-fullsize'>
<GlobalHotKeys />
<ContextImage
frame={frameData}
contextImageHide={contextImageHide}
......
// 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>
);
}
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces';
......@@ -19,7 +19,7 @@ import IssueControl from './issue-control';
interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
rotateFrame(rotation: Rotation): void;
......@@ -64,7 +64,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<CursorControl
cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces';
......@@ -29,7 +29,7 @@ import SplitControl from './split-control';
interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
mergeObjects(enabled: boolean): void;
......@@ -169,7 +169,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<CursorControl
cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance}
......
......@@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT
import React from 'react';
import { GlobalHotKeys } from 'react-hotkeys';
import Layout from 'antd/lib/layout';
import { ActiveControl } from 'reducers/interfaces';
......@@ -31,8 +30,6 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
return (
<Layout.Sider className='cvat-canvas-controls-sidebar' theme='light' width={44}>
<GlobalHotKeys />
<MoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
<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 {
position: absolute;
background: $background-color-2;
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React, { useState, useEffect } from 'react';
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 Text from 'antd/lib/typography/Text';
import Select from 'antd/lib/select';
......@@ -60,7 +60,7 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
keyMap[key] = {
name: `Setup ${label.name} tag`,
description: `Setup tag with "${label.name}" label`,
sequence: `${id}`,
sequences: [`${id}`],
action: 'keydown',
};
......@@ -81,7 +81,7 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
return (
<div className='cvat-tag-annotation-label-selects'>
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={keyMap as KeyMap} handlers={handlers} />
<Row>
<Col>
<Text strong>Shortcuts for labels:</Text>
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { GlobalHotKeys, ExtendedKeyMapOptions } from 'react-hotkeys';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { Action } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { Row, Col } from 'antd/lib/grid';
......@@ -35,7 +35,7 @@ interface StateToProps {
jobInstance: any;
canvasInstance: Canvas;
frameNumber: number;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
}
......@@ -198,7 +198,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
return (
<>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<Layout.Sider {...siderProps}>
{/* eslint-disable-next-line */}
<span
......
......@@ -27,7 +27,7 @@ import LoginPageContainer from 'containers/login-page/login-page';
import RegisterPageContainer from 'containers/register-page/register-page';
import getCore from 'cvat-core-wrapper';
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 { RouteComponentProps, withRouter } from 'react-router-dom';
import { NotificationsState } from 'reducers/interfaces';
......@@ -47,7 +47,7 @@ interface CVATAppProps {
switchShortcutsDialog: () => void;
switchSettingsDialog: () => void;
loadAuthActions: () => void;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
userInitialized: boolean;
userFetching: boolean;
pluginsInitialized: boolean;
......@@ -71,7 +71,7 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
public componentDidMount(): void {
const core = getCore();
const { verifyAuthorized, history, location } = this.props;
configure({ ignoreRepeatedEventsWhenKeyHeldDown: false });
// configure({ ignoreRepeatedEventsWhenKeyHeldDown: false });
// Logger configuration
const userActivityCallback: (() => void)[] = [];
......@@ -256,12 +256,12 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
};
const handlers = {
SWITCH_SHORTCUTS: (event: KeyboardEvent | undefined) => {
SWITCH_SHORTCUTS: (event: KeyboardEvent) => {
if (event) event.preventDefault();
switchShortcutsDialog();
},
SWITCH_SETTINGS: (event: KeyboardEvent | undefined) => {
SWITCH_SETTINGS: (event: KeyboardEvent) => {
if (event) event.preventDefault();
switchSettingsDialog();
......
......@@ -7,7 +7,6 @@ import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Button from 'antd/lib/button';
import Slider from 'antd/lib/slider';
import Select from 'antd/lib/select';
import Popover from 'antd/lib/popover';
import InputNumber from 'antd/lib/input-number';
......@@ -17,7 +16,7 @@ import { CompactPicker } from 'react-color';
import { clamp } from 'utils/math';
import { BackJumpIcon, ForwardJumpIcon } from 'icons';
import { FrameSpeed, GridColor } from 'reducers/interfaces';
import { FrameSpeed } from 'reducers/interfaces';
import consts from 'consts';
interface Props {
......@@ -25,25 +24,11 @@ interface Props {
frameSpeed: FrameSpeed;
resetZoom: boolean;
rotateAll: boolean;
grid: boolean;
gridSize: number;
gridColor: GridColor;
gridOpacity: number;
brightnessLevel: number;
contrastLevel: number;
saturationLevel: number;
canvasBackgroundColor: string;
onChangeFrameStep(step: number): void;
onChangeFrameSpeed(speed: FrameSpeed): void;
onSwitchResetZoom(enabled: 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;
}
......@@ -53,32 +38,16 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
frameSpeed,
resetZoom,
rotateAll,
grid,
gridSize,
gridColor,
gridOpacity,
brightnessLevel,
contrastLevel,
saturationLevel,
canvasBackgroundColor,
onChangeFrameStep,
onChangeFrameSpeed,
onSwitchResetZoom,
onSwitchRotateAll,
onSwitchGrid,
onChangeGridSize,
onChangeGridColor,
onChangeGridOpacity,
onChangeBrightnessLevel,
onChangeContrastLevel,
onChangeSaturationLevel,
onChangeCanvasBackgroundColor,
} = props;
const minFrameStep = 2;
const maxFrameStep = 1000;
const minGridSize = 5;
const maxGridSize = 1000;
return (
<div className='cvat-player-settings'>
......@@ -89,8 +58,8 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
min={minFrameStep}
max={maxFrameStep}
value={frameStep}
onChange={(value: number | undefined | string): void => {
if (typeof value !== 'undefined') {
onChange={(value: number | undefined | string | null): void => {
if (typeof value !== 'undefined' && value !== null) {
onChangeFrameStep(Math.floor(clamp(+value, minFrameStep, maxFrameStep)));
}
}}
......@@ -169,77 +138,6 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Popover>
</Col>
</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'>
<Col span={7}>
<Row className='cvat-player-settings-reset-zoom'>
......@@ -278,68 +176,6 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Row>
</Col>
</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>
);
}
......@@ -23,7 +23,6 @@
padding: 24px;
}
.cvat-player-settings-grid,
.cvat-workspace-settings-auto-save,
.cvat-workspace-settings-autoborders,
.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-speed,
.cvat-player-settings-reset-zoom,
......@@ -48,29 +44,6 @@
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-speed {
> div {
......@@ -88,13 +61,6 @@
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 {
> .ant-col {
text-align: center;
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React, { useCallback, useState } from 'react';
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';
const LayoutGrid = (): React.ReactPortal => {
const [showGrid, setShowGrid] = useState(false);
const keyMap = {
TOGGLE_LAYOUT_GRID: 'ctrl+alt+enter',
const keyMap = useSelector((state: CombinedState) => state.shortcuts.keyMap);
const subKeyMap = {
TOGGLE_LAYOUT_GRID: keyMap.TOGGLE_LAYOUT_GRID,
};
const toggleLayoutGrid = useCallback((): void => {
......@@ -23,9 +25,11 @@ const LayoutGrid = (): React.ReactPortal => {
};
const portalContent: JSX.Element = (
<GlobalHotKeys keyMap={keyMap} handlers={handlers}>
{showGrid && <div className='grid sm' />}
{showGrid && <div className='grid lg' />}
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers}>
<>
{showGrid && <div className='grid sm' />}
{showGrid && <div className='grid lg' />}
</>
</GlobalHotKeys>
);
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -6,7 +6,7 @@ import { shortcutsActions } from 'actions/shortcuts-actions';
import Modal from 'antd/lib/modal';
import Table from 'antd/lib/table';
import React from 'react';
import { getApplicationKeyMap } from 'react-hotkeys';
import { getApplicationKeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux';
import { CombinedState } from 'reducers/interfaces';
......@@ -80,8 +80,8 @@ function ShorcutsDialog(props: StateToProps & DispatchToProps): JSX.Element | nu
key: id,
name: keyMap[key].name || key,
description: keyMap[key].description || '',
shortcut: keyMap[key].sequences.map((value) => value.sequence),
action: keyMap[key].sequences.map((value) => value.action || 'keydown'),
shortcut: keyMap[key].sequences,
action: [keyMap[key].action],
}));
return (
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux';
import CanvasWrapperComponent from 'components/annotation-page/canvas/canvas-wrapper';
......@@ -90,7 +90,7 @@ interface StateToProps {
curZLayer: number;
automaticBordering: boolean;
switchableAutomaticBordering: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
canvasBackgroundColor: string;
}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper';
......@@ -24,7 +24,7 @@ interface StateToProps {
canvasInstance: Canvas;
rotateAll: boolean;
activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper';
......@@ -23,7 +23,7 @@ interface StateToProps {
canvasInstance: Canvas;
rotateAll: boolean;
activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
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 {
......@@ -41,7 +41,7 @@ interface StateToProps {
minZLayer: number;
maxZLayer: number;
annotationsFiltersHistory: string[];
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas;
}
......@@ -442,7 +442,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
return (
<>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<ObjectsListComponent
listHeight={listHeight}
statesHidden={statesHidden}
......
......@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { KeyMap } from 'utils/mousetrap-react';
import { connect } from 'react-redux';
import { Canvas } from 'cvat-canvas-wrapper';
......@@ -13,7 +13,7 @@ import { ActiveControl, CombinedState } from 'reducers/interfaces';
interface StateToProps {
canvasInstance: Canvas;
activeControl: ActiveControl;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
contextImageHide: boolean;
loaded: boolean;
......
......@@ -7,7 +7,7 @@ import copy from 'copy-to-clipboard';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
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 {
......@@ -45,7 +45,7 @@ interface StateToProps {
autoSave: boolean;
autoSaveInterval: number;
workspace: Workspace;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
canvasInstance: Canvas;
forceExit: boolean;
......@@ -584,7 +584,7 @@ class AnnotationTopBarContainer extends React.PureComponent<Props, State> {
return (
<>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} />
<AnnotationTopBarComponent
showStatistics={this.showStatistics}
onSwitchPlay={this.onSwitchPlay}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { connect } from 'react-redux';
import PlayerSettingsComponent from 'components/header/settings-modal/player-settings';
import {
changeFrameStep,
changeFrameSpeed,
switchResetZoom,
switchRotateAll,
switchGrid,
changeGridSize,
changeGridColor,
changeGridOpacity,
changeBrightnessLevel,
changeContrastLevel,
changeSaturationLevel,
changeCanvasBackgroundColor,
} from 'actions/settings-actions';
import { CombinedState, FrameSpeed, GridColor } from 'reducers/interfaces';
import { CombinedState, FrameSpeed } from 'reducers/interfaces';
interface StateToProps {
frameStep: number;
frameSpeed: FrameSpeed;
resetZoom: boolean;
rotateAll: boolean;
grid: boolean;
gridSize: number;
gridColor: GridColor;
gridOpacity: number;
brightnessLevel: number;
contrastLevel: number;
saturationLevel: number;
canvasBackgroundColor: string;
}
......@@ -44,13 +27,6 @@ interface DispatchToProps {
onChangeFrameSpeed(speed: FrameSpeed): void;
onSwitchResetZoom(enabled: 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;
}
......@@ -76,35 +52,10 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
onSwitchRotateAll(rotateAll: boolean): void {
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 {
dispatch(changeCanvasBackgroundColor(color));
},
};
}
function PlayerSettingsContainer(props: StateToProps & DispatchToProps): JSX.Element {
return <PlayerSettingsComponent {...props} />;
}
export default connect(mapStateToProps, mapDispatchToProps)(PlayerSettingsContainer);
export default connect(mapStateToProps, mapDispatchToProps)(PlayerSettingsComponent);
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -16,7 +16,7 @@ import logger, { LogType } from 'cvat-logger';
import createCVATStore, { getCVATStore } from 'cvat-store';
import React from 'react';
import ReactDOM from 'react-dom';
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { KeyMap } from 'utils/mousetrap-react';
import { connect, Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import createRootReducer from 'reducers/root-reducer';
......@@ -45,7 +45,7 @@ interface StateToProps {
allowResetPassword: boolean;
notifications: NotificationsState;
user: any;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
isModelPluginActive: boolean;
}
......
......@@ -2,11 +2,11 @@
//
// 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 { Canvas, RectDrawingMethod } from 'cvat-canvas-wrapper';
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 = {
[index: string]: string;
......@@ -539,7 +539,7 @@ export interface SettingsState {
export interface ShortcutsState {
visibleShortcutsHelp: boolean;
keyMap: Record<string, ExtendedKeyMapOptions>;
keyMap: KeyMap;
normalizedKeyMap: Record<string, string>;
}
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
import { ExtendedKeyMapOptions } from 'react-hotkeys';
import { BoundariesActions, BoundariesActionTypes } from 'actions/boundaries-actions';
import { AuthActions, AuthActionTypes } from 'actions/auth-actions';
import { ShortcutsActions, ShortcutsActionsTypes } from 'actions/shortcuts-actions';
import { KeyMap, KeyMapItem } from 'utils/mousetrap-react';
import { ShortcutsState } from './interfaces';
function formatShortcuts(shortcuts: ExtendedKeyMapOptions): string {
function formatShortcuts(shortcuts: KeyMapItem): string {
const list: string[] = shortcuts.sequences as string[];
return `[${list
.map((shortcut: string): string => {
......@@ -39,7 +38,7 @@ const defaultKeyMap = ({
SWITCH_ALL_LOCK: {
name: 'Lock/unlock all objects',
description: 'Change locked state for all objects in the side bar',
sequences: ['t+l'],
sequences: ['t l'],
action: 'keydown',
},
SWITCH_LOCK: {
......@@ -51,7 +50,7 @@ const defaultKeyMap = ({
SWITCH_ALL_HIDDEN: {
name: 'Hide/show all objects',
description: 'Change hidden state for objects in the side bar',
sequences: ['t+h'],
sequences: ['t h'],
action: 'keydown',
},
SWITCH_HIDDEN: {
......@@ -124,80 +123,25 @@ const defaultKeyMap = ({
NEXT_ATTRIBUTE: {
name: 'Next attribute',
description: 'Go to the next attribute',
sequences: ['ArrowDown'],
sequences: ['down'],
action: 'keydown',
},
PREVIOUS_ATTRIBUTE: {
name: 'Previous attribute',
description: 'Go to the previous attribute',
sequences: ['ArrowUp'],
sequences: ['up'],
action: 'keydown',
},
NEXT_OBJECT: {
name: 'Next object',
description: 'Go to the next object',
sequences: ['Tab'],
sequences: ['tab'],
action: 'keydown',
},
PREVIOUS_OBJECT: {
name: 'Previous object',
description: 'Go to the previous object',
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'],
sequences: ['shift+tab'],
action: 'keydown',
},
......@@ -326,22 +270,28 @@ const defaultKeyMap = ({
FOCUS_INPUT_FRAME: {
name: 'Focus input frame',
description: 'Focus on the element to change the current frame',
sequences: ['`', '~'],
sequences: ['~'],
action: 'keydown',
},
SWITCH_AUTOMATIC_BORDERING: {
name: 'Switch automatic bordering',
description: 'Switch automatic bordering for polygons and polylines during drawing/editing',
sequences: ['Control'],
sequences: ['ctrl'],
action: 'keydown',
},
CHANGE_OBJECT_COLOR: {
name: 'Change color',
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',
},
} as any) as Record<string, ExtendedKeyMapOptions>;
} as any) as KeyMap;
const defaultState: ShortcutsState = {
visibleShortcutsHelp: false,
......
// 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,
};
}
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -22,22 +22,20 @@ context('Canvas grid feature', () => {
before(() => {
cy.openTaskJob(taskName);
cy.get('.cvat-canvas-image-setups-trigger').click();
});
describe(`Testing case "${caseId}"`, () => {
it('Go to settings.', () => {
cy.openSettings();
});
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.', () => {
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);
});
});
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')
.not('.ant-select-dropdown-hidden')
.within(() => {
......@@ -45,7 +43,7 @@ context('Canvas grid feature', () => {
});
});
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"]').should('have.attr', 'aria-valuenow', gridOpacity);
});
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -12,41 +12,45 @@ context('Canvas brightness/contrast/saturation feature', () => {
const defaultValueInSidebar = 100;
const expectedResultInSetting = defaultValueInSidebar + countActionMoveSlider;
const classNameSliders = [
'.cvat-player-settings-brightness',
'.cvat-player-settings-contrast',
'.cvat-player-settings-saturation',
'.cvat-image-setups-brightness',
'.cvat-image-setups-contrast',
'.cvat-image-setups-saturation',
];
function generateStringCountAction(countAction) {
let stringAction = '';
for (let i = 0; i < countAction; i++) {
stringAction += '{rightarrow}';
};
}
return stringAction;
};
}
function checkStateValuesInBackground(expectedValue) {
cy.get('#cvat_canvas_background')
.should('have.attr', 'style')
.and('contain', `filter: brightness(${expectedValue}) contrast(${expectedValue}) saturate(${expectedValue})`);
};
.and(
'contain',
`filter: brightness(${expectedValue}) contrast(${expectedValue}) saturate(${expectedValue})`,
);
}
before(() => {
cy.openTaskJob(taskName);
cy.get('.cvat-canvas-image-setups-trigger').click();
});
describe(`Testing case "${caseId}"`, () => {
it('Check apply of settings', () => {
let stringAction = generateStringCountAction(countActionMoveSlider);
cy.openSettings();
cy.get('.cvat-settings-modal').within(() => {
cy.contains('Player').click();
cy.get('.cvat-canvas-image-setups-content').within(() => {
cy.wrap(classNameSliders).each(($el) => {
cy.wrap($el).get($el).within(() => {
cy.get('[role=slider]')
.type(stringAction)
.should('have.attr', 'aria-valuenow', expectedResultInSetting);
});
cy.wrap($el)
.get($el)
.within(() => {
cy.get('[role=slider]')
.type(stringAction)
.should('have.attr', 'aria-valuenow', expectedResultInSetting);
});
});
});
const expectedResultInBackground = (defaultValueInSidebar + countActionMoveSlider) / 100;
......@@ -54,7 +58,7 @@ context('Canvas brightness/contrast/saturation feature', () => {
});
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;
checkStateValuesInBackground(expectedResultInBackground);
});
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -24,11 +24,12 @@ context('Check hide functionality (H)', () => {
describe(`Testing issue "${issueId}"`, () => {
it('Object is hidden', () => {
const keyCodeH = 72;
cy.createRectangle(createRectangleShape2Points);
cy.get('#cvat_canvas_shape_1')
.trigger('mousemove')
.trigger('mouseover')
.trigger('keydown', { key: 'h' })
.trigger('keydown', { keyCode: keyCodeH })
.should('be.hidden');
});
});
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
......@@ -22,11 +22,12 @@ context('Check if the UI not to crash after remove a tag', () => {
cy.changeWorkspace('Standard');
});
it('Remove the tag', () => {
const keyCodeDel = 46;
cy.get('#cvat-objects-sidebar-state-item-1')
.should('contain', '1')
.and('contain', 'TAG')
.trigger('mouseover')
.trigger('keydown', { key: 'Delete' });
.trigger('keydown', { keyCode: keyCodeDel });
});
it('Page with the error is missing', () => {
cy.contains('Oops, something went wrong').should('not.exist');
......
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// 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');
});
it('Redraw the polygon', () => {
const keyCodeN = 78;
cy.get('#cvat_canvas_shape_1')
.trigger('mousemove', { force: true })
.trigger('keydown', { key: 'n', shiftKey: true })
.trigger('keyup', { force: true }, { key: 'n', shiftKey: true });
.trigger('keydown', { keyCode: keyCodeN, shiftKey: true })
.trigger('keyup', { force: true }, { keyCode: keyCodeN, shiftKey: true });
cy.createPolygon(reDrawPolygonTrack);
});
it('Activate auto bordering mode', () => {
......
......@@ -216,7 +216,10 @@ Cypress.Commands.add('createPoint', (createPointParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
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');
});
......@@ -228,14 +231,15 @@ Cypress.Commands.add('changeAppearance', (colorBy) => {
});
Cypress.Commands.add('shapeGrouping', (firstX, firstY, lastX, lastY) => {
const keyCodeG = 71;
cy.get('.cvat-canvas-container')
.trigger('keydown', { key: 'g' })
.trigger('keyup', { key: 'g' })
.trigger('keydown', { keyCode: keyCodeG })
.trigger('keyup', { keyCode: keyCodeG })
.trigger('mousedown', firstX, firstY, { which: 1 })
.trigger('mousemove', lastX, lastY)
.trigger('mouseup', lastX, lastY)
.trigger('keydown', { key: 'g' })
.trigger('keyup', { key: 'g' });
.trigger('keydown', { keyCode: keyCodeG })
.trigger('keyup', { keyCode: keyCodeG });
});
Cypress.Commands.add('createPolygon', (createPolygonParams) => {
......@@ -257,7 +261,10 @@ Cypress.Commands.add('createPolygon', (createPolygonParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
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');
});
......@@ -383,7 +390,10 @@ Cypress.Commands.add('createPolyline', (createPolylineParams) => {
cy.get('.cvat-canvas-container').click(element.x, element.y);
});
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');
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册