aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-03-25 23:52:33 -0400
committerbobzel <zzzman@gmail.com>2021-03-25 23:52:33 -0400
commit7878bc22a6dec8bff17f38aa3ffad897babb9e16 (patch)
tree1dbf8138ee2e4e420a0b96f247270ff7d6b75810 /src
parentbaa2152a35bac6e0a18ff916817af9bb566a549f (diff)
cleaned up dragmanager a bit and fixed issues with document shifting on drop when dragged via DocDecorations and
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts190
-rw-r--r--src/client/views/DocumentDecorations.tsx17
2 files changed, 72 insertions, 135 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 17dd85a9f..1809a77bf 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -303,7 +303,7 @@ export namespace DragManager {
near = pt.pt;
}
});
- return { thisX: near[0], thisY: near[1] };
+ return { x: near[0], y: near[1] };
}
// snap to the active snap lines - if oneAxis is set (eg, for maintaining aspect ratios), then it only snaps to the nearest horizontal/vertical line
export function snapDrag(e: PointerEvent, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number) {
@@ -320,8 +320,8 @@ export namespace DragManager {
return drag;
};
return {
- thisX: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()),
- thisY: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines())
+ x: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()),
+ y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines())
};
}
export let docsBeingDragged: Doc[] = [];
@@ -344,29 +344,22 @@ export namespace DragManager {
dragDiv.appendChild(dragLabel);
DragManager.Root().appendChild(dragDiv);
}
- dragDiv.style.width = "";
- dragDiv.style.height = "";
- dragDiv.style.overflow = "";
+ Object.assign(dragDiv.style, { width: "", height: "", overflow: "" });
dragDiv.hidden = false;
- const scaleXs: number[] = [];
- const scaleYs: number[] = [];
- const xs: number[] = [];
- const ys: number[] = [];
+ const scaleXs: number[] = [], scaleYs: number[] = [], xs: number[] = [], ys: number[] = [];
docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
const elesCont = {
- left: Number.MAX_SAFE_INTEGER,
- top: Number.MAX_SAFE_INTEGER,
- right: Number.MIN_SAFE_INTEGER,
- bottom: Number.MIN_SAFE_INTEGER
+ left: Number.MAX_SAFE_INTEGER, right: Number.MIN_SAFE_INTEGER,
+ top: Number.MAX_SAFE_INTEGER, bottom: Number.MIN_SAFE_INTEGER
};
const dragElements = eles.map(ele => {
if (!ele.parentNode) dragDiv.appendChild(ele);
const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement;
-
const rect = ele.getBoundingClientRect();
- const scaleX = rect.width / ele.offsetWidth,
- scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
+ const scaleX = rect.width / ele.offsetWidth;
+ const scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
+
elesCont.left = Math.min(rect.left, elesCont.left);
elesCont.top = Math.min(rect.top, elesCont.top);
elesCont.right = Math.max(rect.right, elesCont.right);
@@ -375,20 +368,12 @@ export namespace DragManager {
ys.push(rect.top);
scaleXs.push(scaleX);
scaleYs.push(scaleY);
- dragElement.style.opacity = "0.7";
- dragElement.style.position = "absolute";
- dragElement.style.margin = "0";
- dragElement.style.top = "0";
- dragElement.style.bottom = "";
- dragElement.style.left = "0";
- dragElement.style.color = "black";
- dragElement.style.transition = "none";
- dragElement.style.transformOrigin = "0 0";
- dragElement.style.borderRadius = getComputedStyle(ele).borderRadius;
- dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000";
- dragElement.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`;
- dragElement.style.width = `${rect.width / scaleX}px`;
- dragElement.style.height = `${rect.height / scaleY}px`;
+ Object.assign(dragElement.style, {
+ opacity: "0.7", position: "absolute", margin: "0", top: "0", bottom: "", left: "0", color: "black", transition: "none",
+ borderRadius: getComputedStyle(ele).borderRadius, zIndex: globalCssVariables.contextMenuZindex,
+ transformOrigin: "0 0", width: `${rect.width / scaleX}px`, height: `${rect.height / scaleY}px`,
+ transform: `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`,
+ });
dragLabel.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0) - 20}px)`;
if (docsBeingDragged.length) {
@@ -396,25 +381,19 @@ export namespace DragManager {
const pdfBoxSrc = ele.getElementsByTagName("canvas");
Array.from(pdfBox).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0));
}
- if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none";
- const set = dragElement.getElementsByTagName('*');
- // tslint:disable-next-line: prefer-for-of
- for (let i = 0; i < set.length; i++) {
- set[i].hasAttribute("style") && ((set[i] as any).style.pointerEvents = "none");
- }
+ [dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele =>
+ ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none"));
dragDiv.appendChild(dragElement);
if (dragElement !== ele) {
- const children = Array.from(ele.children);
- const dchildren = Array.from(dragElement.children);
- while (children.length) {
- const child = children.pop();
- const dchild = dchildren.pop();
- if (child?.children) {
- children.push(...(Array.from(child.children)));
- dchildren.push(...(Array.from(dchild!.children)));
+ const children = [Array.from(ele.children), Array.from(dragElement.children)];
+ while (children[0].length) {
+ const childs = [children[0].pop(), children[1].pop()]
+ if (childs[0]?.children) {
+ children[0].push(...Array.from(childs[0].children));
+ children[1].push(...Array.from(childs[1]!.children));
}
- if (child?.scrollTop) dchild!.scrollTop = child.scrollTop;
+ if (childs[0]?.scrollTop) childs[1]!.scrollTop = childs[0].scrollTop;
}
}
return dragElement;
@@ -428,13 +407,26 @@ export namespace DragManager {
options?.hideSource && hideDragShowOriginalElements(true);
SnappingManager.SetIsDragging(true);
- let lastX = downX;
- let lastY = downY;
+ let lastPt = { x: downX, y: downY };
const xFromLeft = downX - elesCont.left;
const yFromTop = downY - elesCont.top;
const xFromRight = elesCont.right - downX;
const yFromBottom = elesCont.bottom - downY;
let scrollAwaiter: Opt<NodeJS.Timeout>;
+
+ AbortDrag = () => {
+ options?.dragComplete?.(new DragCompleteEvent(true, dragData));
+ endDrag();
+ };
+
+ const endDrag = action(() => {
+ hideDragShowOriginalElements(false);
+ document.removeEventListener("pointermove", moveHandler, true);
+ document.removeEventListener("pointerup", upHandler);
+ SnappingManager.SetIsDragging(false);
+ SnappingManager.clearSnapLines();
+ batch.end();
+ });
const moveHandler = (e: PointerEvent) => {
e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
if (dragData instanceof DocumentDragData) {
@@ -508,93 +500,39 @@ export namespace DragManager {
scrollAwaiter = setTimeout(autoScrollHandler, 250);
}
- const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
+ const { x, y } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
+ const moveVec = { x: x - lastPt.x, y: y - lastPt.y };
+ lastPt = { x, y };
- const moveX = thisX - lastX;
- const moveY = thisY - lastY;
- lastX = thisX;
- lastY = thisY;
- dragLabel.style.transform = `translate(${xs[0] + moveX + (options?.offsetX || 0)}px, ${ys[0] + moveY + (options?.offsetY || 0) - 20}px)`;
+ dragLabel.style.transform = `translate(${xs[0] + moveVec.x + (options?.offsetX || 0)}px, ${ys[0] + moveVec.y + (options?.offsetY || 0) - 20}px)`;
dragElements.map((dragElement, i) => (dragElement.style.transform =
- `translate(${(xs[i] += moveX) + (options?.offsetX || 0)}px, ${(ys[i] += moveY) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`)
+ `translate(${(xs[i] += moveVec.x) + (options?.offsetX || 0)}px, ${(ys[i] += moveVec.y) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`)
);
};
-
- const endDrag = action(() => {
- hideDragShowOriginalElements(false);
- document.removeEventListener("pointermove", moveHandler, true);
- document.removeEventListener("pointerup", upHandler);
- SnappingManager.SetIsDragging(false);
- SnappingManager.clearSnapLines();
- batch.end();
- });
-
- AbortDrag = () => {
- options?.dragComplete?.(new DragCompleteEvent(true, dragData));
- endDrag();
- };
const upHandler = (e: PointerEvent) => {
- const complete = new DragCompleteEvent(false, dragData);
- dispatchDrag(eles, e, complete, xFromLeft, yFromTop, xFromRight, yFromBottom, options, finishDrag);
- options?.dragComplete?.(complete);
+ dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options);
endDrag();
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
- function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, complete: DragCompleteEvent,
- xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number, options?: DragOptions, finishDrag?: (e: DragCompleteEvent) => void) {
- const removed = dragEles.map(dragEle => {
- const ret = { ele: dragEle, w: dragEle.style.width, h: dragEle.style.height, o: dragEle.style.overflow };
- dragEle.style.width = "0";
- dragEle.style.height = "0";
- dragEle.style.overflow = "hidden";
- return ret;
- });
- dragDiv.hidden = true;
- dragDiv.style.width = "0";
- dragDiv.style.height = "0";
- dragDiv.style.overflow = "hidden";
- const target = document.elementFromPoint(e.x, e.y);
- removed.map(r => {
- r.ele.style.width = r.w;
- r.ele.style.height = r.h;
- r.ele.style.overflow = r.o;
- });
- const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
- if (target) {
- target.dispatchEvent(
- new CustomEvent<DropEvent>("dashPreDrop", {
- bubbles: true,
- detail: {
- x: thisX,
- y: thisY,
- complete: complete,
- shiftKey: e.shiftKey,
- altKey: e.altKey,
- metaKey: e.metaKey,
- ctrlKey: e.ctrlKey,
- embedKey: CanEmbed
- }
- })
- );
- finishDrag?.(complete);
- target.dispatchEvent(
- new CustomEvent<DropEvent>("dashOnDrop", {
- bubbles: true,
- detail: {
- x: thisX,
- y: thisY,
- complete: complete,
- shiftKey: e.shiftKey,
- altKey: e.altKey,
- metaKey: e.metaKey,
- ctrlKey: e.ctrlKey,
- embedKey: CanEmbed
- }
- })
- );
- }
+ function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions) {
+ const dropArgs = {
+ bubbles: true,
+ detail: {
+ ...pos,
+ complete,
+ shiftKey: e.shiftKey,
+ altKey: e.altKey,
+ metaKey: e.metaKey,
+ ctrlKey: e.ctrlKey,
+ embedKey: CanEmbed
+ }
+ };
+ target.dispatchEvent(new CustomEvent<DropEvent>("dashPreDrop", dropArgs));
+ finishDrag?.(complete);
+ target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", dropArgs));
+ options?.dragComplete?.(complete);
}
-}
+} \ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 50065c17a..da50ba4d8 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -94,7 +94,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), (e) => { }, action((e) => {
!this._edtingTitle && (this._accumulatedTitle = this._titleControlString.startsWith("#") ? this.selectionTitle : this._titleControlString);
this._edtingTitle = true;
- setTimeout(() => this._keyinput.current!.focus(), 0);
+ this._keyinput.current && setTimeout(this._keyinput.current!.focus);
}));
}
@@ -103,13 +103,12 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
@action
onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
const dragDocView = SelectionManager.Views()[0];
- const dragData = new DragManager.DocumentDragData(SelectionManager.Views().map(dv => dv.props.Document));
const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
- dragData.offset = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.ContentScale()).transformDirection(e.x - left, e.y - top);
+ const dragData = new DragManager.DocumentDragData(SelectionManager.Views().map(dv => dv.props.Document), dragDocView.props.dropAction);
+ dragData.offset = dragDocView.props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
dragData.moveDocument = dragDocView.props.moveDocument;
dragData.isSelectionMove = true;
dragData.canEmbed = dragTitle;
- dragData.dropAction = dragDocView.props.dropAction;
this._hidden = this.Interacting = true;
DragManager.StartDocumentDrag(SelectionManager.Views().map(dv => dv.ContentDiv!), dragData, e.x, e.y, {
dragComplete: action(e => {
@@ -228,7 +227,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
const first = SelectionManager.Views()[0];
- let thisPt = { thisX: e.clientX - this._offX, thisY: e.clientY - this._offY };
+ let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY };
var fixedAspect = Doc.NativeAspect(first.layoutDoc);
InkStrokeProperties.Instance?._lock && SelectionManager.Views().filter(dv => dv.rootDoc.type === DocumentType.INK)
.forEach(dv => fixedAspect = Doc.NativeAspect(dv.rootDoc));
@@ -250,10 +249,10 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
thisPt = DragManager.snapDrag(e, -this._offX, -this._offY, this._offX, this._offY);
}
- move[0] = thisPt.thisX - this._snapX;
- move[1] = thisPt.thisY - this._snapY;
- this._snapX = thisPt.thisX;
- this._snapY = thisPt.thisY;
+ move[0] = thisPt.x - this._snapX;
+ move[1] = thisPt.y - this._snapY;
+ this._snapX = thisPt.x;
+ this._snapY = thisPt.y;
let dragBottom = false, dragRight = false, dragBotRight = false;
let dX = 0, dY = 0, dW = 0, dH = 0;
switch (this._resizeHdlId) {