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 commandsmain
parent
dff57eb24b
commit
fb17dca505
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue