import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import { Doc, Opt } from '../../../fields/Doc'; import { documentSchema } from '../../../fields/documentSchemas'; import { createSchema, makeInterface } from '../../../fields/Schema'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { emptyFunction, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import "./ComparisonBox.scss"; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import React = require("react"); import { DocumentType } from '../../documents/DocumentTypes'; export const comparisonSchema = createSchema({}); type ComparisonDocument = makeInterface<[typeof comparisonSchema, typeof documentSchema]>; const ComparisonDocument = makeInterface(comparisonSchema, documentSchema); @observer export class ComparisonBox extends ViewBoxAnnotatableComponent(ComparisonDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ComparisonBox, fieldKey); } protected _multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined; private _disposers: (DragManager.DragDropDisposer | undefined)[] = [undefined, undefined]; @observable _animating = ""; protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => { this._disposers[disposerId]?.(); if (ele) { // create disposers identified by disposerId to remove drag & drop listeners this._disposers[disposerId] = DragManager.MakeDropTarget(ele, (e, dropEvent) => this.dropHandler(e, dropEvent, fieldKey), this.layoutDoc); } } @undoBatch private dropHandler = (event: Event, dropEvent: DragManager.DropEvent, fieldKey: string) => { if (dropEvent.complete.docDragData) { event.stopPropagation(); // prevent parent Doc from registering new position so that it snaps back into place const droppedDocs = dropEvent.complete.docDragData?.droppedDocuments; if (droppedDocs?.length) { this.dataDoc[fieldKey] = droppedDocs[0]; } } } private registerSliding = (e: React.PointerEvent, targetWidth: number) => { e.button !== 2 && setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, action(() => { // on click, animate slider movement to the targetWidth this._animating = "all 200ms"; this.layoutDoc._clipWidth = targetWidth * 100 / this.props.PanelWidth(); setTimeout(action(() => this._animating = ""), 200); }), false); } @action private onPointerMove = ({ movementX }: PointerEvent) => { const width = movementX * this.props.ScreenToLocalTransform().Scale + NumCast(this.layoutDoc._clipWidth) / 100 * this.props.PanelWidth(); if (width && width > 5 && width < this.props.PanelWidth()) { this.layoutDoc._clipWidth = width * 100 / this.props.PanelWidth(); } return false; } @undoBatch clearDoc = (e: React.MouseEvent, fieldKey: string) => { e.stopPropagation; // prevent click event action (slider movement) in registerSliding delete this.dataDoc[fieldKey]; } docStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (property === StyleProp.PointerEvents) return "none"; return this.props.styleProvider?.(doc, props, property); } render() { const clipWidth = NumCast(this.layoutDoc._clipWidth) + "%"; const clearButton = (which: string) => { return
e.stopPropagation()} // prevent triggering slider movement in registerSliding onClick={e => this.clearDoc(e, `compareBox-${which}`)}>
; }; const displayDoc = (which: string) => { var whichDoc = Cast(this.dataDoc[which], Doc, null); if (whichDoc?.type === DocumentType.MARKER) whichDoc = Cast(whichDoc.annotationOn, Doc, null); return whichDoc ? <> {clearButton(which)} : // placeholder image if doc is missing
; }; const displayBox = (which: string, index: number, cover: number) => { return
this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)} > {displayDoc(which)}
; }; return (
{displayBox(this.fieldKey === "data" ? "compareBox-after" : `${this.fieldKey}2`, 1, this.props.PanelWidth() - 3)}
{displayBox(this.fieldKey === "data" ? "compareBox-before" : `${this.fieldKey}1`, 0, 0)}
(this.props.PanelWidth() - 5) / this.props.PanelWidth() ? "w-resize" : undefined }} onPointerDown={e => this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ >
); } }