diff --git a/README.md b/README.md
index 507b3a14..6805f47c 100644
--- a/README.md
+++ b/README.md
@@ -96,8 +96,11 @@ docker logs make_sense
| Load next image | Editor | ⌥ + Right | Ctrl + Right |
| Zoom in | Editor | ⌥ + + | Ctrl + + |
| Zoom out | Editor | ⌥ + - | Ctrl + - |
+| Toggle Drag Mode | Editor | h | h |
| Move image | Editor | Up / Down / Left / Right | Up / Down / Left / Right |
| Select Label | Editor | ⌥ + 0-9 | Ctrl + 0-9 |
+| Copy all labels | Editor | ⌥ + c | Ctrl + c |
+| Paste all labels | Editor | ⌥ + p | Ctrl + p |
| Exit popup | Popup | Escape | Escape |
**Table 1.** Supported keyboard shortcuts
diff --git a/src/logic/context/EditorContext.ts b/src/logic/context/EditorContext.ts
index 14ee56ae..9b39ab38 100644
--- a/src/logic/context/EditorContext.ts
+++ b/src/logic/context/EditorContext.ts
@@ -167,6 +167,24 @@ export class EditorContext extends BaseContext {
ImageActions.setActiveLabelOnActiveImage(9);
EditorActions.fullRender();
}
+ },
+ {
+ keyCombo: ["h"],
+ action: (event: KeyboardEvent) =>{
+ document.getElementById("imageDragOnClick").click();
+ }
+ },
+ {
+ keyCombo: PlatformUtil.isMac(window.navigator.userAgent) ? ["Alt", "v"] : ["Control", "v"],
+ action: (event: KeyboardEvent)=>{
+ EditorModel.supportRenderingEngine.pasteHandler();
+ }
+ },
+ {
+ keyCombo: PlatformUtil.isMac(window.navigator.userAgent) ? ["Alt", "v"] : ["Control", "c"],
+ action: (event: KeyboardEvent)=>{
+ EditorModel.supportRenderingEngine.copyHandler();
+ }
}
];
}
\ No newline at end of file
diff --git a/src/logic/render/BaseRenderEngine.ts b/src/logic/render/BaseRenderEngine.ts
index 1f07b9ae..f41e0048 100644
--- a/src/logic/render/BaseRenderEngine.ts
+++ b/src/logic/render/BaseRenderEngine.ts
@@ -4,12 +4,16 @@ import {EventType} from '../../data/enums/EventType';
import {LabelType} from '../../data/enums/LabelType';
import {GeneralSelector} from '../../store/selectors/GeneralSelector';
import {RenderEngineSettings} from '../../settings/RenderEngineSettings';
-import {LabelName} from '../../store/labels/types';
+import {ImageData, LabelName} from '../../store/labels/types';
import {LabelsSelector} from '../../store/selectors/LabelsSelector';
+import { EditorModel } from '../../staticModels/EditorModel';
+import { PolygonRenderEngine } from './PolygonRenderEngine';
+import { LineRenderEngine } from './LineRenderEngine';
export abstract class BaseRenderEngine {
protected readonly canvas: HTMLCanvasElement;
public labelType: LabelType;
+ protected imageDataCache: ImageData;
protected constructor(canvas: HTMLCanvasElement) {
this.canvas = canvas;
@@ -36,6 +40,20 @@ export abstract class BaseRenderEngine {
protected abstract mouseDownHandler(data: EditorData): void;
protected abstract mouseMoveHandler(data: EditorData): void;
protected abstract mouseUpHandler(data: EditorData): void;
+ public abstract pasteHandler(): void;
+
+ public copyHandler(){
+ switch (EditorModel.supportRenderingEngine.labelType) {
+ case LabelType.POLYGON:
+ (EditorModel.supportRenderingEngine as PolygonRenderEngine).cancelLabelCreation();
+ break;
+ case LabelType.LINE:
+ (EditorModel.supportRenderingEngine as LineRenderEngine).cancelLabelCreation();
+ break;
+ }
+ const imageData = LabelsSelector.getActiveImageData();
+ this.imageDataCache = {...imageData};
+ }
abstract render(data: EditorData): void;
diff --git a/src/logic/render/LineRenderEngine.ts b/src/logic/render/LineRenderEngine.ts
index e9d09534..b393403e 100644
--- a/src/logic/render/LineRenderEngine.ts
+++ b/src/logic/render/LineRenderEngine.ts
@@ -84,6 +84,21 @@ export class LineRenderEngine extends BaseRenderEngine {
}
}
}
+
+ public pasteHandler(): void {
+ this.cancelLabelCreation();
+ if(this.imageDataCache && this.imageDataCache.labelLines){
+ const imageData: ImageData = LabelsSelector.getActiveImageData();
+ this.imageDataCache.labelLines.forEach((lineLabel) => {
+ imageData.labelLines.push(lineLabel);
+ store.dispatch(updateImageDataById(imageData.id, imageData));
+ store.dispatch(updateFirstLabelCreatedFlag(true));
+ store.dispatch(updateActiveLabelId(lineLabel.id));
+ this.lineCreationStartPoint = null
+ });
+ EditorActions.setViewPortActionsDisabledStatus(false);
+ }
+ }
// =================================================================================================================
// RENDERING
diff --git a/src/logic/render/PointRenderEngine.ts b/src/logic/render/PointRenderEngine.ts
index 727f0739..41583ffa 100644
--- a/src/logic/render/PointRenderEngine.ts
+++ b/src/logic/render/PointRenderEngine.ts
@@ -7,6 +7,7 @@ import {ImageData, LabelPoint} from '../../store/labels/types';
import { v4 as uuidv4 } from 'uuid';
import {
updateActiveLabelId,
+ updateActiveLabelNameId,
updateFirstLabelCreatedFlag,
updateHighlightedLabelId,
updateImageDataById
@@ -103,6 +104,15 @@ export class PointRenderEngine extends BaseRenderEngine {
}
}
}
+
+ public pasteHandler(): void {
+ if(this.imageDataCache && this.imageDataCache.labelPoints){
+ this.imageDataCache.labelPoints.forEach((pointLabel) => {
+ store.dispatch(updateActiveLabelNameId(pointLabel.labelId));
+ this.addPointLabel(pointLabel.point);
+ });
+ }
+ }
// =================================================================================================================
// RENDERING
diff --git a/src/logic/render/PolygonRenderEngine.ts b/src/logic/render/PolygonRenderEngine.ts
index b9091f9e..d9bf134c 100644
--- a/src/logic/render/PolygonRenderEngine.ts
+++ b/src/logic/render/PolygonRenderEngine.ts
@@ -13,6 +13,7 @@ import {ImageData, LabelPolygon} from '../../store/labels/types';
import {LabelsSelector} from '../../store/selectors/LabelsSelector';
import {
updateActiveLabelId,
+ updateActiveLabelNameId,
updateFirstLabelCreatedFlag,
updateHighlightedLabelId,
updateImageDataById
@@ -28,7 +29,7 @@ import {Settings} from '../../settings/Settings';
import {LabelUtil} from '../../utils/LabelUtil';
export class PolygonRenderEngine extends BaseRenderEngine {
-
+
// =================================================================================================================
// STATE
// =================================================================================================================
@@ -144,6 +145,15 @@ export class PolygonRenderEngine extends BaseRenderEngine {
}
}
}
+
+ public pasteHandler(): void {
+ if(this.imageDataCache && this.imageDataCache.labelPolygons){
+ this.imageDataCache.labelPolygons.forEach((polyLabel) => {
+ store.dispatch(updateActiveLabelNameId(polyLabel.labelId));
+ this.addPolygonLabel(polyLabel.vertices);
+ });
+ }
+ }
// =================================================================================================================
// RENDERING
diff --git a/src/logic/render/PrimaryEditorRenderEngine.ts b/src/logic/render/PrimaryEditorRenderEngine.ts
index a7685543..ad245b83 100644
--- a/src/logic/render/PrimaryEditorRenderEngine.ts
+++ b/src/logic/render/PrimaryEditorRenderEngine.ts
@@ -24,6 +24,7 @@ export class PrimaryEditorRenderEngine extends BaseRenderEngine {
public mouseMoveHandler(data: EditorData): void {}
public mouseDownHandler(data: EditorData): void {}
public mouseUpHandler(data: EditorData): void {}
+ public pasteHandler(): void {}
// =================================================================================================================
// RENDERING
diff --git a/src/logic/render/RectRenderEngine.ts b/src/logic/render/RectRenderEngine.ts
index 0a6b8e21..76b221fa 100644
--- a/src/logic/render/RectRenderEngine.ts
+++ b/src/logic/render/RectRenderEngine.ts
@@ -1,32 +1,32 @@
-import {IPoint} from '../../interfaces/IPoint';
-import {IRect} from '../../interfaces/IRect';
-import {RectUtil} from '../../utils/RectUtil';
-import {DrawUtil} from '../../utils/DrawUtil';
-import {store} from '../..';
-import {ImageData, LabelRect} from '../../store/labels/types';
+import { IPoint } from '../../interfaces/IPoint';
+import { IRect } from '../../interfaces/IRect';
+import { RectUtil } from '../../utils/RectUtil';
+import { DrawUtil } from '../../utils/DrawUtil';
+import { store } from '../..';
+import { ImageData, LabelRect } from '../../store/labels/types';
import {
updateActiveLabelId,
+ updateActiveLabelNameId,
updateFirstLabelCreatedFlag,
updateHighlightedLabelId,
updateImageDataById
} from '../../store/labels/actionCreators';
-import {PointUtil} from '../../utils/PointUtil';
-import {RectAnchor} from '../../data/RectAnchor';
-import {RenderEngineSettings} from '../../settings/RenderEngineSettings';
-import {updateCustomCursorStyle} from '../../store/general/actionCreators';
-import {CustomCursorStyle} from '../../data/enums/CustomCursorStyle';
-import {LabelsSelector} from '../../store/selectors/LabelsSelector';
-import {EditorData} from '../../data/EditorData';
-import {BaseRenderEngine} from './BaseRenderEngine';
-import {RenderEngineUtil} from '../../utils/RenderEngineUtil';
-import {LabelType} from '../../data/enums/LabelType';
-import {EditorActions} from '../actions/EditorActions';
-import {GeneralSelector} from '../../store/selectors/GeneralSelector';
-import {LabelStatus} from '../../data/enums/LabelStatus';
-import {LabelUtil} from '../../utils/LabelUtil';
+import { PointUtil } from '../../utils/PointUtil';
+import { RectAnchor } from '../../data/RectAnchor';
+import { RenderEngineSettings } from '../../settings/RenderEngineSettings';
+import { updateCustomCursorStyle } from '../../store/general/actionCreators';
+import { CustomCursorStyle } from '../../data/enums/CustomCursorStyle';
+import { LabelsSelector } from '../../store/selectors/LabelsSelector';
+import { EditorData } from '../../data/EditorData';
+import { BaseRenderEngine } from './BaseRenderEngine';
+import { RenderEngineUtil } from '../../utils/RenderEngineUtil';
+import { LabelType } from '../../data/enums/LabelType';
+import { EditorActions } from '../actions/EditorActions';
+import { GeneralSelector } from '../../store/selectors/GeneralSelector';
+import { LabelStatus } from '../../data/enums/LabelStatus';
+import { LabelUtil } from '../../utils/LabelUtil';
export class RectRenderEngine extends BaseRenderEngine {
-
// =================================================================================================================
// STATE
// =================================================================================================================
@@ -49,19 +49,30 @@ export class RectRenderEngine extends BaseRenderEngine {
if (isMouseOverCanvas) {
const rectUnderMouse: LabelRect = this.getRectUnderMouse(data);
if (!!rectUnderMouse) {
- const rect: IRect = this.calculateRectRelativeToActiveImage(rectUnderMouse.rect, data);
- const anchorUnderMouse: RectAnchor = this.getAnchorUnderMouseByRect(rect, data.mousePositionOnViewPortContent, data.viewPortContentImageRect);
- if (!!anchorUnderMouse && rectUnderMouse.status === LabelStatus.ACCEPTED) {
+ const rect: IRect = this.calculateRectRelativeToActiveImage(
+ rectUnderMouse.rect,
+ data
+ );
+ const anchorUnderMouse: RectAnchor = this.getAnchorUnderMouseByRect(
+ rect,
+ data.mousePositionOnViewPortContent,
+ data.viewPortContentImageRect
+ );
+ if (
+ !!anchorUnderMouse &&
+ rectUnderMouse.status === LabelStatus.ACCEPTED
+ ) {
store.dispatch(updateActiveLabelId(rectUnderMouse.id));
this.startRectResize(anchorUnderMouse);
} else {
- if (!!LabelsSelector.getHighlightedLabelId())
- store.dispatch(updateActiveLabelId(LabelsSelector.getHighlightedLabelId()));
- else
- this.startRectCreation(data.mousePositionOnViewPortContent);
+ if (!!LabelsSelector.getHighlightedLabelId()) {
+ console.log(LabelsSelector.getHighlightedLabelId());
+ store.dispatch(
+ updateActiveLabelId(LabelsSelector.getHighlightedLabelId())
+ );
+ } else this.startRectCreation(data.mousePositionOnViewPortContent);
}
} else if (isMouseOverImage) {
-
this.startRectCreation(data.mousePositionOnViewPortContent);
}
}
@@ -69,63 +80,113 @@ export class RectRenderEngine extends BaseRenderEngine {
public mouseUpHandler = (data: EditorData) => {
if (!!data.viewPortContentImageRect) {
- const mousePositionSnapped: IPoint = RectUtil.snapPointToRect(data.mousePositionOnViewPortContent, data.viewPortContentImageRect);
+ const mousePositionSnapped: IPoint = RectUtil.snapPointToRect(
+ data.mousePositionOnViewPortContent,
+ data.viewPortContentImageRect
+ );
const activeLabelRect: LabelRect = LabelsSelector.getActiveRectLabel();
- if (!!this.startCreateRectPoint && !PointUtil.equals(this.startCreateRectPoint, mousePositionSnapped)) {
-
- const minX: number = Math.min(this.startCreateRectPoint.x, mousePositionSnapped.x);
- const minY: number = Math.min(this.startCreateRectPoint.y, mousePositionSnapped.y);
- const maxX: number = Math.max(this.startCreateRectPoint.x, mousePositionSnapped.x);
- const maxY: number = Math.max(this.startCreateRectPoint.y, mousePositionSnapped.y);
-
- const rect = {x: minX, y: minY, width: maxX - minX, height: maxY - minY};
- this.addRectLabel(RenderEngineUtil.transferRectFromImageToViewPortContent(rect, data));
+ if (
+ !!this.startCreateRectPoint &&
+ !PointUtil.equals(this.startCreateRectPoint, mousePositionSnapped)
+ ) {
+ const minX: number = Math.min(
+ this.startCreateRectPoint.x,
+ mousePositionSnapped.x
+ );
+ const minY: number = Math.min(
+ this.startCreateRectPoint.y,
+ mousePositionSnapped.y
+ );
+ const maxX: number = Math.max(
+ this.startCreateRectPoint.x,
+ mousePositionSnapped.x
+ );
+ const maxY: number = Math.max(
+ this.startCreateRectPoint.y,
+ mousePositionSnapped.y
+ );
+
+ const rect = {
+ x: minX,
+ y: minY,
+ width: maxX - minX,
+ height: maxY - minY
+ };
+ this.addRectLabel(
+ RenderEngineUtil.transferRectFromImageToViewPortContent(rect, data)
+ );
}
if (!!this.startResizeRectAnchor && !!activeLabelRect) {
- const rect: IRect = this.calculateRectRelativeToActiveImage(activeLabelRect.rect, data);
- const startAnchorPosition: IPoint = PointUtil.add(this.startResizeRectAnchor.position,
- data.viewPortContentImageRect);
- const delta: IPoint = PointUtil.subtract(mousePositionSnapped, startAnchorPosition);
- const resizeRect: IRect = RectUtil.resizeRect(rect, this.startResizeRectAnchor.type, delta);
+ const rect: IRect = this.calculateRectRelativeToActiveImage(
+ activeLabelRect.rect,
+ data
+ );
+ const startAnchorPosition: IPoint = PointUtil.add(
+ this.startResizeRectAnchor.position,
+ data.viewPortContentImageRect
+ );
+ const delta: IPoint = PointUtil.subtract(
+ mousePositionSnapped,
+ startAnchorPosition
+ );
+ const resizeRect: IRect = RectUtil.resizeRect(
+ rect,
+ this.startResizeRectAnchor.type,
+ delta
+ );
const scale: number = RenderEngineUtil.calculateImageScale(data);
const scaledRect: IRect = RectUtil.scaleRect(resizeRect, scale);
const imageData = LabelsSelector.getActiveImageData();
- imageData.labelRects = imageData.labelRects.map((labelRect: LabelRect) => {
- if (labelRect.id === activeLabelRect.id) {
- return {
- ...labelRect,
- rect: scaledRect
- };
+ imageData.labelRects = imageData.labelRects.map(
+ (labelRect: LabelRect) => {
+ if (labelRect.id === activeLabelRect.id) {
+ return {
+ ...labelRect,
+ rect: scaledRect
+ };
+ }
+ return labelRect;
}
- return labelRect;
- });
+ );
store.dispatch(updateImageDataById(imageData.id, imageData));
}
}
- this.endRectTransformation()
+ this.endRectTransformation();
};
public mouseMoveHandler = (data: EditorData) => {
- if (!!data.viewPortContentImageRect && !!data.mousePositionOnViewPortContent) {
+ if (
+ !!data.viewPortContentImageRect &&
+ !!data.mousePositionOnViewPortContent
+ ) {
const isOverImage: boolean = RenderEngineUtil.isMouseOverImage(data);
if (isOverImage && !this.startResizeRectAnchor) {
const labelRect: LabelRect = this.getRectUnderMouse(data);
if (!!labelRect && !this.isInProgress()) {
if (LabelsSelector.getHighlightedLabelId() !== labelRect.id) {
- store.dispatch(updateHighlightedLabelId(labelRect.id))
+ store.dispatch(updateHighlightedLabelId(labelRect.id));
}
} else {
if (LabelsSelector.getHighlightedLabelId() !== null) {
- store.dispatch(updateHighlightedLabelId(null))
+ store.dispatch(updateHighlightedLabelId(null));
}
}
}
}
};
+ public pasteHandler(): void {
+ if (this.imageDataCache && this.imageDataCache.labelRects) {
+ this.imageDataCache.labelRects.forEach((rectLabel) => {
+ store.dispatch(updateActiveLabelNameId(rectLabel.labelId));
+ this.addRectLabel(rectLabel.rect);
+ });
+ }
+ }
+
// =================================================================================================================
// RENDERING
// =================================================================================================================
@@ -135,82 +196,163 @@ export class RectRenderEngine extends BaseRenderEngine {
const imageData: ImageData = LabelsSelector.getActiveImageData();
if (imageData) {
imageData.labelRects.forEach((labelRect: LabelRect) => {
- if (labelRect.status === LabelStatus.ACCEPTED && labelRect.id === activeLabelId) {
- this.drawActiveRect(labelRect, data)
+ if (
+ labelRect.status === LabelStatus.ACCEPTED &&
+ labelRect.id === activeLabelId
+ ) {
+ this.drawActiveRect(labelRect, data);
} else {
this.drawInactiveRect(labelRect, data);
}
});
- this.drawCurrentlyCreatedRect(data.mousePositionOnViewPortContent, data.viewPortContentImageRect);
+ this.drawCurrentlyCreatedRect(
+ data.mousePositionOnViewPortContent,
+ data.viewPortContentImageRect
+ );
this.updateCursorStyle(data);
}
}
private drawCurrentlyCreatedRect(mousePosition: IPoint, imageRect: IRect) {
if (!!this.startCreateRectPoint) {
- const mousePositionSnapped: IPoint = RectUtil.snapPointToRect(mousePosition, imageRect);
+ const mousePositionSnapped: IPoint = RectUtil.snapPointToRect(
+ mousePosition,
+ imageRect
+ );
const activeRect: IRect = {
x: this.startCreateRectPoint.x,
y: this.startCreateRectPoint.y,
width: mousePositionSnapped.x - this.startCreateRectPoint.x,
height: mousePositionSnapped.y - this.startCreateRectPoint.y
};
- const activeRectBetweenPixels = RenderEngineUtil.setRectBetweenPixels(activeRect);
- const lineColor: string = BaseRenderEngine.resolveLabelLineColor(null, true)
- DrawUtil.drawRect(this.canvas, activeRectBetweenPixels, lineColor, RenderEngineSettings.LINE_THICKNESS);
+ const activeRectBetweenPixels =
+ RenderEngineUtil.setRectBetweenPixels(activeRect);
+ const lineColor: string = BaseRenderEngine.resolveLabelLineColor(
+ null,
+ true
+ );
+ DrawUtil.drawRect(
+ this.canvas,
+ activeRectBetweenPixels,
+ lineColor,
+ RenderEngineSettings.LINE_THICKNESS
+ );
}
}
private drawInactiveRect(labelRect: LabelRect, data: EditorData) {
- const rectOnImage: IRect = RenderEngineUtil.transferRectFromViewPortContentToImage(labelRect.rect, data)
- const highlightedLabelId: string = LabelsSelector.getHighlightedLabelId()
- const displayAsActive: boolean = labelRect.status === LabelStatus.ACCEPTED && labelRect.id === highlightedLabelId;
- const lineColor: string = BaseRenderEngine.resolveLabelLineColor(labelRect.labelId, displayAsActive)
- const anchorColor: string = BaseRenderEngine.resolveLabelAnchorColor(displayAsActive);
+ const rectOnImage: IRect =
+ RenderEngineUtil.transferRectFromViewPortContentToImage(
+ labelRect.rect,
+ data
+ );
+ const highlightedLabelId: string = LabelsSelector.getHighlightedLabelId();
+ const displayAsActive: boolean =
+ labelRect.status === LabelStatus.ACCEPTED &&
+ labelRect.id === highlightedLabelId;
+ const lineColor: string = BaseRenderEngine.resolveLabelLineColor(
+ labelRect.labelId,
+ displayAsActive
+ );
+ const anchorColor: string =
+ BaseRenderEngine.resolveLabelAnchorColor(displayAsActive);
this.renderRect(rectOnImage, displayAsActive, lineColor, anchorColor);
}
private drawActiveRect(labelRect: LabelRect, data: EditorData) {
- let rect: IRect = this.calculateRectRelativeToActiveImage(labelRect.rect, data);
+ let rect: IRect = this.calculateRectRelativeToActiveImage(
+ labelRect.rect,
+ data
+ );
if (!!this.startResizeRectAnchor) {
- const startAnchorPosition: IPoint = PointUtil.add(this.startResizeRectAnchor.position, data.viewPortContentImageRect);
- const endAnchorPositionSnapped: IPoint = RectUtil.snapPointToRect(data.mousePositionOnViewPortContent, data.viewPortContentImageRect);
- const delta = PointUtil.subtract(endAnchorPositionSnapped, startAnchorPosition);
+ const startAnchorPosition: IPoint = PointUtil.add(
+ this.startResizeRectAnchor.position,
+ data.viewPortContentImageRect
+ );
+ const endAnchorPositionSnapped: IPoint = RectUtil.snapPointToRect(
+ data.mousePositionOnViewPortContent,
+ data.viewPortContentImageRect
+ );
+ const delta = PointUtil.subtract(
+ endAnchorPositionSnapped,
+ startAnchorPosition
+ );
rect = RectUtil.resizeRect(rect, this.startResizeRectAnchor.type, delta);
}
- const rectOnImage: IRect = RectUtil.translate(rect, data.viewPortContentImageRect);
- const lineColor: string = BaseRenderEngine.resolveLabelLineColor(labelRect.labelId, true)
+ const rectOnImage: IRect = RectUtil.translate(
+ rect,
+ data.viewPortContentImageRect
+ );
+ const lineColor: string = BaseRenderEngine.resolveLabelLineColor(
+ labelRect.labelId,
+ true
+ );
const anchorColor: string = BaseRenderEngine.resolveLabelAnchorColor(true);
this.renderRect(rectOnImage, true, lineColor, anchorColor);
}
- private renderRect(rectOnImage: IRect, isActive: boolean, lineColor: string, anchorColor: string) {
- const rectBetweenPixels = RenderEngineUtil.setRectBetweenPixels(rectOnImage);
- DrawUtil.drawRectWithFill(this.canvas, rectBetweenPixels, DrawUtil.hexToRGB(lineColor, 0.2));
- DrawUtil.drawRect(this.canvas, rectBetweenPixels, lineColor, RenderEngineSettings.LINE_THICKNESS);
+ private renderRect(
+ rectOnImage: IRect,
+ isActive: boolean,
+ lineColor: string,
+ anchorColor: string
+ ) {
+ const rectBetweenPixels =
+ RenderEngineUtil.setRectBetweenPixels(rectOnImage);
+ DrawUtil.drawRectWithFill(
+ this.canvas,
+ rectBetweenPixels,
+ DrawUtil.hexToRGB(lineColor, 0.2)
+ );
+ DrawUtil.drawRect(
+ this.canvas,
+ rectBetweenPixels,
+ lineColor,
+ RenderEngineSettings.LINE_THICKNESS
+ );
if (isActive) {
- const handleCenters: IPoint[] = RectUtil.mapRectToAnchors(rectOnImage).map((rectAnchor: RectAnchor) => rectAnchor.position);
+ const handleCenters: IPoint[] = RectUtil.mapRectToAnchors(
+ rectOnImage
+ ).map((rectAnchor: RectAnchor) => rectAnchor.position);
handleCenters.forEach((center: IPoint) => {
- const handleRect: IRect = RectUtil.getRectWithCenterAndSize(center, RenderEngineSettings.anchorSize);
- const handleRectBetweenPixels: IRect = RenderEngineUtil.setRectBetweenPixels(handleRect);
- DrawUtil.drawRectWithFill(this.canvas, handleRectBetweenPixels, anchorColor);
- })
+ const handleRect: IRect = RectUtil.getRectWithCenterAndSize(
+ center,
+ RenderEngineSettings.anchorSize
+ );
+ const handleRectBetweenPixels: IRect =
+ RenderEngineUtil.setRectBetweenPixels(handleRect);
+ DrawUtil.drawRectWithFill(
+ this.canvas,
+ handleRectBetweenPixels,
+ anchorColor
+ );
+ });
}
}
private updateCursorStyle(data: EditorData) {
- if (!!this.canvas && !!data.mousePositionOnViewPortContent && !GeneralSelector.getImageDragModeStatus()) {
+ if (
+ !!this.canvas &&
+ !!data.mousePositionOnViewPortContent &&
+ !GeneralSelector.getImageDragModeStatus()
+ ) {
const rectUnderMouse: LabelRect = this.getRectUnderMouse(data);
const rectAnchorUnderMouse: RectAnchor = this.getAnchorUnderMouse(data);
- if ((!!rectAnchorUnderMouse && rectUnderMouse && rectUnderMouse.status === LabelStatus.ACCEPTED) || !!this.startResizeRectAnchor) {
+ if (
+ (!!rectAnchorUnderMouse &&
+ rectUnderMouse &&
+ rectUnderMouse.status === LabelStatus.ACCEPTED) ||
+ !!this.startResizeRectAnchor
+ ) {
store.dispatch(updateCustomCursorStyle(CustomCursorStyle.MOVE));
return;
- }
- else if (RenderEngineUtil.isMouseOverCanvas(data)) {
- if (!RenderEngineUtil.isMouseOverImage(data) && !!this.startCreateRectPoint)
+ } else if (RenderEngineUtil.isMouseOverCanvas(data)) {
+ if (
+ !RenderEngineUtil.isMouseOverImage(data) &&
+ !!this.startCreateRectPoint
+ )
store.dispatch(updateCustomCursorStyle(CustomCursorStyle.MOVE));
- else
- RenderEngineUtil.wrapDefaultCursorStyleInCancel(data);
+ else RenderEngineUtil.wrapDefaultCursorStyleInCancel(data);
this.canvas.style.cursor = 'none';
} else {
this.canvas.style.cursor = 'default';
@@ -226,9 +368,12 @@ export class RectRenderEngine extends BaseRenderEngine {
return !!this.startCreateRectPoint || !!this.startResizeRectAnchor;
}
- private calculateRectRelativeToActiveImage(rect: IRect, data: EditorData):IRect {
+ private calculateRectRelativeToActiveImage(
+ rect: IRect,
+ data: EditorData
+ ): IRect {
const scale: number = RenderEngineUtil.calculateImageScale(data);
- return RectUtil.scaleRect(rect, 1/scale);
+ return RectUtil.scaleRect(rect, 1 / scale);
}
private addRectLabel = (rect: IRect) => {
@@ -243,11 +388,15 @@ export class RectRenderEngine extends BaseRenderEngine {
private getRectUnderMouse(data: EditorData): LabelRect {
const activeRectLabel: LabelRect = LabelsSelector.getActiveRectLabel();
- if (!!activeRectLabel && this.isMouseOverRectEdges(activeRectLabel.rect, data)) {
+ if (
+ !!activeRectLabel &&
+ this.isMouseOverRectEdges(activeRectLabel.rect, data)
+ ) {
return activeRectLabel;
}
- const labelRects: LabelRect[] = LabelsSelector.getActiveImageData().labelRects;
+ const labelRects: LabelRect[] =
+ LabelsSelector.getActiveImageData().labelRects;
for (let i = 0; i < labelRects.length; i++) {
if (this.isMouseOverRectEdges(labelRects[i].rect, data)) {
return labelRects[i];
@@ -258,7 +407,9 @@ export class RectRenderEngine extends BaseRenderEngine {
private isMouseOverRectEdges(rect: IRect, data: EditorData): boolean {
const rectOnImage: IRect = RectUtil.translate(
- this.calculateRectRelativeToActiveImage(rect, data), data.viewPortContentImageRect);
+ this.calculateRectRelativeToActiveImage(rect, data),
+ data.viewPortContentImageRect
+ );
const outerRectDelta: IPoint = {
x: RenderEngineSettings.anchorHoverSize.width / 2,
@@ -267,20 +418,35 @@ export class RectRenderEngine extends BaseRenderEngine {
const outerRect: IRect = RectUtil.expand(rectOnImage, outerRectDelta);
const innerRectDelta: IPoint = {
- x: - RenderEngineSettings.anchorHoverSize.width / 2,
- y: - RenderEngineSettings.anchorHoverSize.height / 2
+ x: -RenderEngineSettings.anchorHoverSize.width / 2,
+ y: -RenderEngineSettings.anchorHoverSize.height / 2
};
const innerRect: IRect = RectUtil.expand(rectOnImage, innerRectDelta);
- return (RectUtil.isPointInside(outerRect, data.mousePositionOnViewPortContent) &&
- !RectUtil.isPointInside(innerRect, data.mousePositionOnViewPortContent));
+ return (
+ RectUtil.isPointInside(outerRect, data.mousePositionOnViewPortContent) &&
+ !RectUtil.isPointInside(innerRect, data.mousePositionOnViewPortContent)
+ );
}
- private getAnchorUnderMouseByRect(rect: IRect, mousePosition: IPoint, imageRect: IRect): RectAnchor {
+ private getAnchorUnderMouseByRect(
+ rect: IRect,
+ mousePosition: IPoint,
+ imageRect: IRect
+ ): RectAnchor {
const rectAnchors: RectAnchor[] = RectUtil.mapRectToAnchors(rect);
for (let i = 0; i < rectAnchors.length; i++) {
- const anchorRect: IRect = RectUtil.translate(RectUtil.getRectWithCenterAndSize(rectAnchors[i].position, RenderEngineSettings.anchorHoverSize), imageRect);
- if (!!mousePosition && RectUtil.isPointInside(anchorRect, mousePosition)) {
+ const anchorRect: IRect = RectUtil.translate(
+ RectUtil.getRectWithCenterAndSize(
+ rectAnchors[i].position,
+ RenderEngineSettings.anchorHoverSize
+ ),
+ imageRect
+ );
+ if (
+ !!mousePosition &&
+ RectUtil.isPointInside(anchorRect, mousePosition)
+ ) {
return rectAnchors[i];
}
}
@@ -288,10 +454,18 @@ export class RectRenderEngine extends BaseRenderEngine {
}
private getAnchorUnderMouse(data: EditorData): RectAnchor {
- const labelRects: LabelRect[] = LabelsSelector.getActiveImageData().labelRects;
+ const labelRects: LabelRect[] =
+ LabelsSelector.getActiveImageData().labelRects;
for (let i = 0; i < labelRects.length; i++) {
- const rect: IRect = this.calculateRectRelativeToActiveImage(labelRects[i].rect, data);
- const rectAnchor = this.getAnchorUnderMouseByRect(rect, data.mousePositionOnViewPortContent, data.viewPortContentImageRect);
+ const rect: IRect = this.calculateRectRelativeToActiveImage(
+ labelRects[i].rect,
+ data
+ );
+ const rectAnchor = this.getAnchorUnderMouseByRect(
+ rect,
+ data.mousePositionOnViewPortContent,
+ data.viewPortContentImageRect
+ );
if (!!rectAnchor) return rectAnchor;
}
return null;
diff --git a/src/views/Common/ImageButton/ImageButton.tsx b/src/views/Common/ImageButton/ImageButton.tsx
index 4015dc2f..385a75e0 100644
--- a/src/views/Common/ImageButton/ImageButton.tsx
+++ b/src/views/Common/ImageButton/ImageButton.tsx
@@ -18,7 +18,7 @@ export interface ImageButtonProps extends React.HTMLProps {
}
export const ImageButton = React.forwardRef((props: ImageButtonProps, ref: LegacyRef) => {
- const {buttonSize, padding, image, imageAlt, href, onClick, style, isActive, isDisabled, externalClassName} = props;
+ const {buttonSize, padding, image, imageAlt, href, onClick, id, style, isActive, isDisabled, externalClassName} = props;
const imagePadding:number = !!padding ? padding : 10;
const onClickHandler = (event: React.MouseEvent) => {
@@ -54,6 +54,7 @@ export const ImageButton = React.forwardRef((props: ImageButtonProps, ref: Legac
style={buttonStyle}
onClick={onClickHandler}
ref={ref}
+ id={id}
>
{!!href &&
any
+ onClick?:() => any,
+ id?:string
): React.ReactElement => {
return
@@ -160,7 +162,8 @@ const EditorTopNavigationBar: React.FC = (
'image-drag-mode',
imageDragMode,
undefined,
- imageDragOnClick
+ imageDragOnClick,
+ 'imageDragOnClick'
)
}
{
diff --git a/src/views/EditorView/EditorView.tsx b/src/views/EditorView/EditorView.tsx
index c016720b..cb10a7d9 100644
--- a/src/views/EditorView/EditorView.tsx
+++ b/src/views/EditorView/EditorView.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import './EditorView.scss';
import EditorContainer from './EditorContainer/EditorContainer';
import {PopupWindowType} from '../../data/enums/PopupWindowType';
@@ -13,6 +13,12 @@ interface IProps {
const EditorView: React.FC = ({activePopupType}) => {
+ // Disable middle mouse scroll
+ useEffect(() => {
+ document.body.onmousedown = e => { return e.button === 1 ? false : true; };
+ }, []
+ );
+
const getClassName = () => {
return classNames(
'EditorView',