Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added simple extra popover to keep other controls out of display #2880

Merged
merged 5 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cvat-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cvat-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"@types/react-router-dom": "^5.1.7",
"@types/react-share": "^3.0.3",
"@types/redux-logger": "^3.0.8",
"@types/resize-observer-browser": "^0.1.5",
"antd": "^4.12.2",
"copy-to-clipboard": "^3.3.1",
"cvat-canvas": "file:../cvat-canvas",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

/// <reference types="resize-observer-browser" />

import { SmallDashOutlined } from '@ant-design/icons';
import Popover from 'antd/lib/popover';
import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';

const extraControlsContentClassName = 'cvat-extra-controls-control-content';

let onUpdateChildren: Function | null = null;
export function ExtraControlsControl(): JSX.Element {
const [hasChildren, setHasChildren] = useState(false);
const [initialized, setInitialized] = useState(false);

useEffect(() => {
if (!initialized) {
setInitialized(true);
}

window.document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
}, []);

onUpdateChildren = () => {
setHasChildren(window.document.getElementsByClassName(extraControlsContentClassName)[0].children.length > 0);
};

return (
<Popover
defaultVisible
trigger={initialized ? 'hover' : 'click'}
placement='right'
overlayStyle={{ display: initialized ? '' : 'none' }}
content={<div className={extraControlsContentClassName} />}
>
<SmallDashOutlined
style={{ visibility: hasChildren ? 'visible' : 'hidden' }}
className='cvat-extra-controls-control'
/>
</Popover>
);
}

export default function ControlVisibilityObserver<P = {}>(
ControlComponent: React.FunctionComponent<P>,
): React.FunctionComponent<P> {
let visibilityHeightThreshold = 0; // minimum value of height when element can be pushed to main panel

return (props: P): JSX.Element | null => {
const ref = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(true);

useEffect(() => {
if (ref && ref.current) {
const wrapper = ref.current;
const parentElement = ref.current.parentElement as HTMLElement;

const reservedHeight = 45; // for itself
const observer = new ResizeObserver(() => {
const availableHeight = parentElement.offsetHeight;
setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold);
});

if (ref && ref.current) {
const availableHeight = parentElement.offsetHeight;
visibilityHeightThreshold = wrapper.offsetTop + wrapper.offsetHeight;
observer.observe(ref.current.parentElement as HTMLElement);
setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold);
}

return () => {
observer.disconnect();
};
}

return () => {};
}, []);

useEffect(() => {
if (onUpdateChildren) {
onUpdateChildren();
}
}, [visible]);

if (!visible) {
const extraControlsContent = window.document.getElementsByClassName(extraControlsContentClassName)[0];
if (extraControlsContent) {
return ReactDOM.createPortal(<ControlComponent {...props} />, extraControlsContent);
}

return null;
}

return (
<div ref={ref}>
<ControlComponent {...props} />
</div>
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ import Layout from 'antd/lib/layout';
import { ActiveControl, Rotation } from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas-wrapper';

import RotateControl from './rotate-control';
import CursorControl from './cursor-control';
import MoveControl from './move-control';
import FitControl from './fit-control';
import ResizeControl from './resize-control';
import ControlVisibilityObserver, { ExtraControlsControl } from './control-visibility-observer';
import RotateControl, { Props as RotateControlProps } from './rotate-control';
import CursorControl, { Props as CursorControlProps } from './cursor-control';
import MoveControl, { Props as MoveControlProps } from './move-control';
import FitControl, { Props as FitControlProps } from './fit-control';
import ResizeControl, { Props as ResizeControlProps } from './resize-control';
import ToolsControl from './tools-control';
import OpenCVControl from './opencv-control';
import DrawRectangleControl from './draw-rectangle-control';
import DrawPolygonControl from './draw-polygon-control';
import DrawPolylineControl from './draw-polyline-control';
import DrawPointsControl from './draw-points-control';
import DrawCuboidControl from './draw-cuboid-control';
import SetupTagControl from './setup-tag-control';
import MergeControl from './merge-control';
import GroupControl from './group-control';
import SplitControl from './split-control';
import DrawRectangleControl, { Props as DrawRectangleControlProps } from './draw-rectangle-control';
import DrawPolygonControl, { Props as DrawPolygonControlProps } from './draw-polygon-control';
import DrawPolylineControl, { Props as DrawPolylineControlProps } from './draw-polyline-control';
import DrawPointsControl, { Props as DrawPointsControlProps } from './draw-points-control';
import DrawCuboidControl, { Props as DrawCuboidControlProps } from './draw-cuboid-control';
import SetupTagControl, { Props as SetupTagControlProps } from './setup-tag-control';
import MergeControl, { Props as MergeControlProps } from './merge-control';
import GroupControl, { Props as GroupControlProps } from './group-control';
import SplitControl, { Props as SplitControlProps } from './split-control';

interface Props {
canvasInstance: Canvas;
Expand All @@ -42,6 +43,25 @@ interface Props {
redrawShape(): void;
}

// We use the observer to see if these controls are in the viewport
// They automatically put to extra if not
const ObservedCursorControl = ControlVisibilityObserver<CursorControlProps>(CursorControl);
const ObservedMoveControl = ControlVisibilityObserver<MoveControlProps>(MoveControl);
const ObservedRotateControl = ControlVisibilityObserver<RotateControlProps>(RotateControl);
const ObservedFitControl = ControlVisibilityObserver<FitControlProps>(FitControl);
const ObservedResizeControl = ControlVisibilityObserver<ResizeControlProps>(ResizeControl);
const ObservedToolsControl = ControlVisibilityObserver(ToolsControl);
const ObservedOpenCVControl = ControlVisibilityObserver(OpenCVControl);
const ObservedDrawRectangleControl = ControlVisibilityObserver<DrawRectangleControlProps>(DrawRectangleControl);
const ObservedDrawPolygonControl = ControlVisibilityObserver<DrawPolygonControlProps>(DrawPolygonControl);
const ObservedDrawPolylineControl = ControlVisibilityObserver<DrawPolylineControlProps>(DrawPolylineControl);
const ObservedDrawPointsControl = ControlVisibilityObserver<DrawPointsControlProps>(DrawPointsControl);
const ObservedDrawCuboidControl = ControlVisibilityObserver<DrawCuboidControlProps>(DrawCuboidControl);
const ObservedSetupTagControl = ControlVisibilityObserver<SetupTagControlProps>(SetupTagControl);
const ObservedMergeControl = ControlVisibilityObserver<MergeControlProps>(MergeControl);
const ObservedGroupControl = ControlVisibilityObserver<GroupControlProps>(GroupControl);
const ObservedSplitControl = ControlVisibilityObserver<SplitControlProps>(SplitControl);

export default function ControlsSideBarComponent(props: Props): JSX.Element {
const {
canvasInstance,
Expand Down Expand Up @@ -170,69 +190,71 @@ 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} />
<CursorControl
<ObservedCursorControl
cursorShortkey={normalizedKeyMap.CANCEL}
canvasInstance={canvasInstance}
activeControl={activeControl}
/>
<MoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
<RotateControl
<ObservedMoveControl canvasInstance={canvasInstance} activeControl={activeControl} />
<ObservedRotateControl
anticlockwiseShortcut={normalizedKeyMap.ANTICLOCKWISE_ROTATION}
clockwiseShortcut={normalizedKeyMap.CLOCKWISE_ROTATION}
rotateFrame={rotateFrame}
/>

<hr />

<FitControl canvasInstance={canvasInstance} />
<ResizeControl canvasInstance={canvasInstance} activeControl={activeControl} />
<ObservedFitControl canvasInstance={canvasInstance} />
<ObservedResizeControl canvasInstance={canvasInstance} activeControl={activeControl} />

<hr />
<ToolsControl />
<OpenCVControl />
<DrawRectangleControl
<ObservedToolsControl />
<ObservedOpenCVControl />
<ObservedDrawRectangleControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_RECTANGLE}
/>
<DrawPolygonControl
<ObservedDrawPolygonControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_POLYGON}
/>
<DrawPolylineControl
<ObservedDrawPolylineControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_POLYLINE}
/>
<DrawPointsControl
<ObservedDrawPointsControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_POINTS}
/>
<DrawCuboidControl
<ObservedDrawCuboidControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_CUBOID}
/>
<SetupTagControl canvasInstance={canvasInstance} isDrawing={false} />
<ObservedSetupTagControl canvasInstance={canvasInstance} isDrawing={false} />

<hr />

<MergeControl
<ObservedMergeControl
switchMergeShortcut={normalizedKeyMap.SWITCH_MERGE_MODE}
canvasInstance={canvasInstance}
activeControl={activeControl}
mergeObjects={mergeObjects}
/>
<GroupControl
<ObservedGroupControl
switchGroupShortcut={normalizedKeyMap.SWITCH_GROUP_MODE}
resetGroupShortcut={normalizedKeyMap.RESET_GROUP}
canvasInstance={canvasInstance}
activeControl={activeControl}
groupObjects={groupObjects}
/>
<SplitControl
<ObservedSplitControl
canvasInstance={canvasInstance}
switchSplitShortcut={normalizedKeyMap.SWITCH_SPLIT_MODE}
activeControl={activeControl}
splitTrack={splitTrack}
/>

<ExtraControlsControl />
</Layout.Sider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas-wrapper';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
cursorShortkey: string;
activeControl: ActiveControl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { CubeIcon } from 'icons';
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
canvasInstance: Canvas;
isDrawing: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces';
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
canvasInstance: Canvas;
isDrawing: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces';
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
canvasInstance: Canvas;
isDrawing: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces';
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
canvasInstance: Canvas;
isDrawing: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ShapeType } from 'reducers/interfaces';
import DrawShapePopoverContainer from 'containers/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
canvasInstance: Canvas;
isDrawing: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { FitIcon } from 'icons';
import { Canvas } from 'cvat-canvas-wrapper';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Canvas } from 'cvat-canvas-wrapper';
import { ActiveControl } from 'reducers/interfaces';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
switchGroupShortcut: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Canvas } from 'cvat-canvas-wrapper';
import { ActiveControl } from 'reducers/interfaces';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
switchMergeShortcut: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas-wrapper';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ActiveControl } from 'reducers/interfaces';
import { Canvas } from 'cvat-canvas-wrapper';
import CVATTooltip from 'components/common/cvat-tooltip';

interface Props {
export interface Props {
canvasInstance: Canvas;
activeControl: ActiveControl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Rotation } from 'reducers/interfaces';
import CVATTooltip from 'components/common/cvat-tooltip';
import withVisibilityHandling from './handle-popover-visibility';

interface Props {
export interface Props {
clockwiseShortcut: string;
anticlockwiseShortcut: string;
rotateFrame(rotation: Rotation): void;
Expand Down
Loading