diff options
author | bobzel <zzzman@gmail.com> | 2021-08-24 14:28:13 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2021-08-24 14:28:13 -0400 |
commit | 5867ca16f8a8beaf7daf754ee5c42a5cc249346f (patch) | |
tree | d59c42afdbc9f0aa0abc8b8e79772df5c639f4ab /src | |
parent | a38501569769c00dc1c25fb57d09ca88f3951c3d (diff) |
fixed undo for dragging docs. made separate layers for transparent and other annotations on pdfs/webs so that transparency will work better.
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 10 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 12 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 48 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 18 | ||||
-rw-r--r-- | src/fields/Doc.ts | 5 |
5 files changed, 60 insertions, 33 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index f251f776c..f90296121 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -115,6 +115,16 @@ export namespace Utils { return { r: r, g: g, b: b, a: a }; } + export function IsTransparentFilter() { + // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one + return ["backgroundColor:isTransparent(__value__):check"]; + } + export function IsOpaqueFilter() { + // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one + return ["backgroundColor:isTransparent(__value__):x"]; + } + + export function toRGBAstr(col: { r: number, g: number, b: number, a?: number }) { return "rgba(" + col.r + "," + col.g + "," + col.b + (col.a !== undefined ? "," + col.a : "") + ")"; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 5e16de617..f7ef9ae6f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -425,10 +425,10 @@ export namespace DragManager { AbortDrag = () => { options?.dragComplete?.(new DragCompleteEvent(true, dragData)); - endDrag(); + cleanupDrag(); }; - const endDrag = action(() => { + const cleanupDrag = action(() => { hideDragShowOriginalElements(false); document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); @@ -518,15 +518,14 @@ export namespace DragManager { `translate(${(xs[i] += moveVec.x) + (options?.offsetX || 0)}px, ${(ys[i] += moveVec.y) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) ); }; - const upHandler = async (e: PointerEvent) => { - dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options); - endDrag(); + const upHandler = (e: PointerEvent) => { + dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options, cleanupDrag); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } - async function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions) { + async function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions, endDrag?: () => void) { const dropArgs = { bubbles: true, detail: { @@ -543,5 +542,6 @@ export namespace DragManager { await finishDrag?.(complete); target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", dropArgs)); options?.dragComplete?.(complete); + endDrag?.(); } }
\ No newline at end of file diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 0c32a30db..94697464a 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -512,6 +512,29 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined; const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const scale = previewScale * (this.props.scaling?.() || 1); + const renderAnnotations = (docFilters: () => string[]) => + <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + renderDepth={this.props.renderDepth + 1} + isAnnotationOverlay={true} + fieldKey={this.annotationKey} + CollectionView={undefined} + setPreviewCursor={this.setPreviewCursor} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} + ScreenToLocalTransform={this.scrollXf} + scaling={returnOne} + dropAction={"alias"} + docFilters={docFilters} + select={emptyFunction} + isContentActive={returnFalse} + ContentScaling={returnOne} + bringToFront={emptyFunction} + whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} + removeDocument={this.removeDocument} + moveDocument={this.moveDocument} + addDocument={this.sidebarAddDocument} + childPointerEvents={true} + pointerEvents={this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />; return ( <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.isContentActive() ? "all" : this.isContentActive() || SnappingManager.GetIsDragging() ? undefined : "none" }} > <div className={`webBox-container`} style={{ pointerEvents }} onContextMenu={this.specificContextMenu}> @@ -529,27 +552,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps > <div className={"webBox-innerContent"} style={{ height: NumCast(this.scrollHeight, 50), pointerEvents }}> {this.content} - <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} - renderDepth={this.props.renderDepth + 1} - isAnnotationOverlay={true} - fieldKey={this.annotationKey} - CollectionView={undefined} - setPreviewCursor={this.setPreviewCursor} - PanelWidth={this.panelWidth} - PanelHeight={this.panelHeight} - ScreenToLocalTransform={this.scrollXf} - scaling={returnOne} - dropAction={"alias"} - select={emptyFunction} - isContentActive={returnFalse} - ContentScaling={returnOne} - bringToFront={emptyFunction} - whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} - removeDocument={this.removeDocument} - moveDocument={this.moveDocument} - addDocument={this.sidebarAddDocument} - childPointerEvents={true} - pointerEvents={this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} /> + <div style={{ mixBlendMode: "multiply" }}> + {renderAnnotations(Utils.IsTransparentFilter)} + </div> + {renderAnnotations(Utils.IsOpaqueFilter)} {this.annotationLayer} </div> </div> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 41a60bedf..2c00b005d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -507,12 +507,7 @@ export class PDFViewer extends React.Component<IViewerProps> { panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); @computed get overlayLayer() { - return <div className={`pdfViewerDash-overlay${CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} - style={{ - pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, - mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, - transform: `scale(${this._zoomed})` - }}> + const renderAnnotations = (docFilters: () => string[]) => <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} isAnnotationOverlay={true} isContentActive={returnFalse} @@ -524,10 +519,21 @@ export class PDFViewer extends React.Component<IViewerProps> { select={emptyFunction} ContentScaling={this.contentZoom} bringToFront={emptyFunction} + docFilters={doFilters} CollectionView={undefined} ScreenToLocalTransform={this.overlayTransform} renderDepth={this.props.renderDepth + 1} childPointerEvents={true} /> + return <div className={`pdfViewerDash-overlay${CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} + style={{ + pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, + mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, + transform: `scale(${this._zoomed})` + }}> + <div style={{ mixBlendMode: "multiply" }}> + {renderAnnotations(Utils.IsTransparentFilter)} + </div> + {renderAnnotations(Utils.IsOpaqueFilter)} </div>; } @computed get pdfViewerDiv() { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index e4087cf43..f6efefdf9 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -25,6 +25,7 @@ import { deleteProperty, GetEffectiveAcl, getField, getter, inheritParentAcls, m import JSZip = require("jszip"); import { CurrentUserUtils } from "../client/util/CurrentUserUtils"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import Color = require("color"); export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -1087,6 +1088,10 @@ export namespace Doc { } export function matchFieldValue(doc: Doc, key: string, value: any): boolean { + if (value === "isTransparent(__value__)") { + const isTransparent = (color: string) => color !== "" && (Color(color).alpha() !== 1); + return isTransparent(StrCast(doc[key])); + } const fieldVal = doc[key]; if (Cast(fieldVal, listSpec("string"), []).length) { const vals = Cast(fieldVal, listSpec("string"), []); |