From 22a2462a6854f31f6f546d56258aec2042073d4b Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 19 Jan 2021 11:31:02 -0500 Subject: more cleanup of marquee annotator. added marquee annotator to images --- src/client/views/nodes/ImageBox.scss | 10 +++++ src/client/views/nodes/ImageBox.tsx | 43 ++++++++++++++++++--- src/client/views/nodes/WebBox.tsx | 72 ++++++++++-------------------------- 3 files changed, 68 insertions(+), 57 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss index c1b95b308..41055e2db 100644 --- a/src/client/views/nodes/ImageBox.scss +++ b/src/client/views/nodes/ImageBox.scss @@ -5,6 +5,16 @@ position: relative; transform-origin: top left; + + .imageBox-annotationLayer { + position: absolute; + transform-origin: left top; + top: 0; + width: 100%; + pointer-events: none; + mix-blend-mode: multiply; // bcz: makes text fuzzy! + } + .imageBox-fader { pointer-events: inherit; } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index b0e7f4ce5..e202749aa 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -27,6 +27,10 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); import { StyleProp } from '../StyleProvider'; +import { PDFMenu } from '../pdf/PDFMenu'; +import { Dictionary } from 'typescript-collections'; +import { MarqueeAnnotator } from '../MarqueeAnnotator'; +import { Annotation } from '../pdf/Annotation'; const path = require('path'); const { Howl } = require('howler'); @@ -63,7 +67,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; - private _pathDisposer?: IReactionDisposer; + private _disposers: { [name: string]: IReactionDisposer } = {}; @observable private _audioState = 0; @observable static _showControls: boolean; @observable uploadIcon = uploadIcons.idle; @@ -74,7 +78,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), + this._disposers.selection = reaction(() => this.props.isSelected(), + selected => { + if (!selected) { + this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + this._savedAnnotations.clear(); + PDFMenu.Instance.fadeOut(true); + } + }, + { fireImmediately: true }); + this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), action(({ nativeSize, width }) => { if (!this.layoutDoc._height) { this.layoutDoc._height = width * nativeSize.nativeHeight / nativeSize.nativeWidth; @@ -84,7 +97,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent disposer?.()); } @undoBatch @@ -356,7 +369,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent + return
this.props.ScreenToLocalTransform().translate(0, -this.ycenter); contentFunc = () => [this.content]; + private _mainCont: React.RefObject = React.createRef(); + private _annotationLayer: React.RefObject = React.createRef(); + @observable _marqueeing: number[] | undefined; + @observable _savedAnnotations: Dictionary = new Dictionary(); + @computed get annotationLayer() { + return
; + } + @action + marqueeDown = (e: React.PointerEvent) => { + if (!e.altKey && e.button === 0 && this.active(true)) this._marqueeing = [e.clientX, e.clientY]; + } + @action + finishMarquee = () => { + this._marqueeing = undefined; + this.props.select(true); + } + render() { TraceMobx(); const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); const borderRadius = borderRad?.includes("px") ? `${Number(borderRad.split("px")[0]) / (this.props.scaling?.() || 1)}px` : borderRad; - return (
{this.contentFunc} + {this.annotationLayer} + {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : + }
); } } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index f9e71bc92..ca3d4448d 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -14,7 +14,7 @@ import { listSpec, makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { WebField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; -import { addStyleSheet, clearStyleSheetRules, emptyFunction, OmitKeys, returnOne, smoothScroll, Utils } from "../../../Utils"; +import { emptyFunction, OmitKeys, returnOne, smoothScroll, Utils } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; @@ -38,26 +38,21 @@ const WebDocument = makeInterface(documentSchema); @observer export class WebBox extends ViewBoxAnnotatableComponent(WebDocument) { private _annotationLayer: React.RefObject = React.createRef(); - static _annotationStyle: any = addStyleSheet(); public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); } private _mainCont: React.RefObject = React.createRef(); - private _downX: number = 0; - private _downY: number = 0; - @observable private _marqueeing: boolean = false; + private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void); + private _disposers: { [name: string]: IReactionDisposer } = {}; + private _longPressSecondsHack?: NodeJS.Timeout; + private _outerRef = React.createRef(); + private _iframeIndicatorRef = React.createRef(); + private _iframeDragRef = React.createRef(); + @observable private _marqueeing: number[] | undefined; @observable private _url: string = "hello"; @observable private _pressX: number = 0; @observable private _pressY: number = 0; @observable private _iframe: HTMLIFrameElement | null = null; @observable private _savedAnnotations: Dictionary = new Dictionary(); - private _selectionReactionDisposer?: IReactionDisposer; - private _scrollReactionDisposer?: IReactionDisposer; - private _scrollTopReactionDisposer?: IReactionDisposer; - private _moveReactionDisposer?: IReactionDisposer; - private _longPressSecondsHack?: NodeJS.Timeout; - private _outerRef = React.createRef(); - private _iframeIndicatorRef = React.createRef(); - private _iframeDragRef = React.createRef(); - private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void); + get scrollHeight() { return this.webpage?.scrollHeight || 1000; } get _collapsed() { return StrCast(this.layoutDoc._chromeStatus) !== "enabled"; } set _collapsed(value) { this.layoutDoc._chromeStatus = !value ? "enabled" : "disabled"; } @@ -91,8 +86,8 @@ export class WebBox extends ViewBoxAnnotatableComponent ({ scrollY: this.layoutDoc._scrollY, scrollX: this.layoutDoc._scrollX }), + this._disposers.scrollReaction?.(); + this._disposers.scrollReaction = reaction(() => ({ scrollY: this.layoutDoc._scrollY, scrollX: this.layoutDoc._scrollX }), ({ scrollY, scrollX }) => { const delay = this._outerRef.current ? 0 : 250; // wait for mainCont and try again to scroll const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/); @@ -110,7 +105,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this.layoutDoc._scrollTop, + this._disposers.scrollTop = reaction(() => this.layoutDoc._scrollTop, scrollTop => { const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/); const duration = durationStr ? Number(durationStr[1]) : 1000; @@ -158,14 +153,14 @@ export class WebBox extends ViewBoxAnnotatableComponent this._url = urlField?.url.toString() || ""); - this._moveReactionDisposer = reaction(() => this.layoutDoc.x || this.layoutDoc.y, + this._disposers.scrollMove = reaction(() => this.layoutDoc.x || this.layoutDoc.y, () => this.updateScroll(this.layoutDoc._scrollLeft, this.layoutDoc._scrollTop)); - this._selectionReactionDisposer = reaction(() => this.props.isSelected(), + this._disposers.selection = reaction(() => this.props.isSelected(), selected => { if (!selected) { this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.keys().forEach(k => this._savedAnnotations.setValue(k, [])); + this._savedAnnotations.clear(); PDFMenu.Instance.fadeOut(true); } }, @@ -194,10 +189,7 @@ export class WebBox extends ViewBoxAnnotatableComponent disposer?.()); document.removeEventListener("pointerup", this.onLongPressUp); document.removeEventListener("pointermove", this.onLongPressMove); this._iframe?.removeEventListener('wheel', this.iframeWheel); @@ -471,39 +463,15 @@ export class WebBox extends ViewBoxAnnotatableComponent { - this._downX = e.clientX; - this._downY = e.clientY; if (!e.altKey && e.button === 0 && this.active(true)) { - // clear out old marquees and initialize menu for new selection - PDFMenu.Instance.Status = "pdf"; - PDFMenu.Instance.fadeOut(true); - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.keys().forEach(k => this._savedAnnotations.setValue(k, [])); - if ((e.target as any)?.parentElement.className === "textLayer") { - // start selecting text if mouse down on textLayer spans - } - else this._marqueeing = true; - document.addEventListener("pointermove", this.onSelectMove); - document.addEventListener("pointerup", this.onSelectEnd); + this._marqueeing = [e.clientX, e.clientY]; } } @action - onSelectMove = (e: PointerEvent): void => { - if (e.target && (e.target as any).parentElement === this._mainCont.current) e.stopPropagation(); - } - - @action - finishMarquee = () => { this._marqueeing = false; } - - @action - onSelectEnd = (e: PointerEvent): void => { - clearStyleSheetRules(WebBox._annotationStyle); + finishMarquee = () => { + this._marqueeing = undefined; this.props.select(true); - this._savedAnnotations.clear(); - - document.removeEventListener("pointermove", this.onSelectMove); - document.removeEventListener("pointerup", this.onSelectEnd); } scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop)); @@ -562,7 +530,7 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.annotationLayer} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : - } + }
{this.props.isSelected() ? this.editToggleBtn() : null}
); -- cgit v1.2.3-70-g09d2