From b6f8f3f6c75c330430cd593b543e682838f9865d Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 26 Jan 2019 23:33:47 -0500 Subject: Got drag drop mostly working --- src/Utils.ts | 9 ++ src/util/DragManager.ts | 17 ++-- .../freeformcanvas/CollectionFreeFormView.tsx | 107 +++++++++++++-------- src/views/nodes/DocumentView.tsx | 40 +++++--- 4 files changed, 110 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/Utils.ts b/src/Utils.ts index f352b87e3..948b6176e 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -10,4 +10,13 @@ export class Utils { public static GenerateDeterministicGuid(seed: string): string { return v5(seed, v5.URL); } + + public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } { + const rect = ele.getBoundingClientRect(); + const scale = rect.width / ele.offsetWidth; + const translateX = rect.left; + const translateY = rect.top; + + return { scale, translateX, translateY }; + } } \ No newline at end of file diff --git a/src/util/DragManager.ts b/src/util/DragManager.ts index 3111d589f..7a8362471 100644 --- a/src/util/DragManager.ts +++ b/src/util/DragManager.ts @@ -23,6 +23,8 @@ export namespace DragManager { get cancelled() { return this._cancelled }; cancel() { this._cancelled = true; }; + + constructor(readonly x:number, readonly y:number, readonly data: { [id: string]: any }) { } } export class DragCompleteEvent { @@ -39,7 +41,7 @@ export namespace DragManager { } export class DropEvent { - constructor(readonly x: number, readonly y: number) { } + constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { } } export interface DropHandlers { @@ -56,7 +58,7 @@ export namespace DragManager { document.removeEventListener("pointermove", startDragHandler); } const startDragHandler = (e: PointerEvent) => { - e.stopPropagation(); + e.stopImmediatePropagation(); e.preventDefault(); dispose(); StartDrag(element, e, options); @@ -65,7 +67,6 @@ export namespace DragManager { dispose(); }; const downHandler = (e: PointerEvent) => { - e.stopPropagation(); document.addEventListener("pointermove", startDragHandler); document.addEventListener("pointerup", upHandler); }; @@ -105,7 +106,10 @@ export namespace DragManager { if ((e.buttons & options.buttons) === 0) { return; } - let event = new DragStartEvent(); + e.stopPropagation(); + e.preventDefault(); + let dragData = {}; + let event = new DragStartEvent(e.x, e.y, dragData); options.handlers.dragStart(event); if (event.cancelled) { return; @@ -132,13 +136,13 @@ export namespace DragManager { const upHandler = (e: PointerEvent) => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); - FinishDrag(dragElement, e, options); + FinishDrag(dragElement, e, options, dragData); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } - function FinishDrag(ele: HTMLElement, e: PointerEvent, options: DragOptions) { + function FinishDrag(ele: HTMLElement, e: PointerEvent, options: DragOptions, dragData: { [index: string]: any }) { dragDiv.removeChild(ele); const target = document.elementFromPoint(e.x, e.y); if (!target) { @@ -149,6 +153,7 @@ export namespace DragManager { detail: { x: e.x, y: e.y, + data: dragData } })); } diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx index 383d71d83..53c5def52 100644 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -13,6 +13,8 @@ import { SelectionManager } from "../../util/SelectionManager"; import { Documents } from "../../documents/Documents"; import { ContextMenu } from "../ContextMenu"; import { Opt } from "../../fields/Field"; +import { DragManager } from "../../util/DragManager"; +import { Utils } from "../../Utils"; interface IProps { fieldKey: Key; @@ -22,25 +24,50 @@ interface IProps { @observer export class CollectionFreeFormView extends React.Component { + private _ref = React.createRef(); constructor(props: IProps) { super(props); } @computed - public get active():boolean { - var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView)); - var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this ); - var topMost = this.props.ContainingDocumentView != undefined && this.props.ContainingDocumentView.props.ContainingCollectionView == undefined; + public get active(): boolean { + var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView)); + var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this); + var topMost = this.props.ContainingDocumentView != undefined && this.props.ContainingDocumentView.props.ContainingCollectionView == undefined; return isSelected || childSelected || topMost; } + componentDidMount() { + if (this._ref.current) { + const ele = this._ref.current; + DragManager.MakeDropTarget(this._ref.current, { + handlers: { + drop: (e: DragManager.DropEvent) => { + const doc = e.data["document"]; + const xOffset = e.data["xOffset"] as number || 0; + const yOffset = e.data["yOffset"] as number || 0; + if (doc instanceof DocumentView) { + const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.children[0] as HTMLElement); + console.log(`${scale} ${translateX} ${translateY}`) + const screenX = e.x - xOffset; + const screenY = e.y - yOffset; + const docX = (screenX - translateX) / scale; + const docY = (screenY - translateY) / scale; + doc.x = docX; + doc.y = docY; + } + } + } + }); + } + } + _lastX: number = 0; - _lastY:number = 0; + _lastY: number = 0; @action - onPointerDown = (e: React.PointerEvent): void => - { - if (this.active && e.button === 2) { + onPointerDown = (e: React.PointerEvent): void => { + if (e.button === 2 && this.active) { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", this.onPointerMove); @@ -65,22 +92,21 @@ export class CollectionFreeFormView extends React.Component { } @action - onPointerMove = (e: PointerEvent): void => - { + onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble) { e.preventDefault(); e.stopPropagation(); const doc = this.props.Document; let me = this; - let currScale:number = this.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + let currScale: number = this.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); if (me.props.ContainingDocumentView!.props.ContainingDocumentView != undefined) { let pme = me.props.ContainingDocumentView!.props.ContainingDocumentView!.props.Document; currScale = pme.GetFieldValue(KeyStore.Scale, NumberField, Number(0)); - } + } let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - doc.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX)/currScale, NumberField); - doc.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY)/currScale, NumberField); + doc.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField); + doc.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField); this._lastX = e.pageX; this._lastY = e.pageY; @@ -89,46 +115,45 @@ export class CollectionFreeFormView extends React.Component { } - private getLocalPoint(me:DocumentView, inputX: number, inputY: number) { + private getLocalPoint(me: DocumentView, inputX: number, inputY: number) { let ContainerX = inputX; let ContainerY = inputY; if (me.props.ContainingDocumentView != undefined) { let pme = me.props.ContainingDocumentView!; - let {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy} = this.getLocalPoint(pme, ContainerX, ContainerY); + let { LocalX, LocalY } = this.getLocalPoint(pme, ContainerX, ContainerY); ContainerX = LocalX; ContainerY = LocalY; - } - - let W = me.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); - let Xx = me.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); - let Yy = me.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); - let Ss = me.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); - let Panxx = me.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - let Panyy = me.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + } + + let W = me.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); + let Xx = me.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); + let Yy = me.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); + let Ss = me.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + let Panxx = me.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + let Panyy = me.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); let LocalX = W / 2 - (Xx + Panxx) / Ss + (ContainerX - W / 2) / Ss; let LocalY = -(Yy + Panyy) / Ss + ContainerY / Ss; - return {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY}; + return { LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY }; } @action - onPointerWheel = (e: React.WheelEvent): void => - { + onPointerWheel = (e: React.WheelEvent): void => { e.stopPropagation(); - let {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY} = this.getLocalPoint(this.props.ContainingDocumentView!, e.pageX, e.pageY); + let { LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY } = this.getLocalPoint(this.props.ContainingDocumentView!, e.pageX, e.pageY); - var deltaScale = (1 - (e.deltaY / 1000)) * Ss; + var deltaScale = (1 - (e.deltaY / 1000)) * Ss; - var newContainerX = LocalX * deltaScale + W/2-W/2 * deltaScale + Panxx + Xx; - var newContainerY = LocalY * deltaScale + Panyy+ Yy; + var newContainerX = LocalX * deltaScale + W / 2 - W / 2 * deltaScale + Panxx + Xx; + var newContainerY = LocalY * deltaScale + Panyy + Yy; let dx = ContainerX - newContainerX; let dy = ContainerY - newContainerY; this.props.Document.SetField(KeyStore.Scale, new NumberField(deltaScale)); - this.props.Document.SetFieldValue(KeyStore.PanX, Panxx+dx, NumberField); - this.props.Document.SetFieldValue(KeyStore.PanY, Panyy+dy, NumberField); + this.props.Document.SetFieldValue(KeyStore.PanX, Panxx + dx, NumberField); + this.props.Document.SetFieldValue(KeyStore.PanY, Panyy + dy, NumberField); DocumentDecorations.Instance.forceUpdate() } @@ -180,7 +205,7 @@ export class CollectionFreeFormView extends React.Component { } render() { const { fieldKey, Document: Document } = this.props; - + const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []); const panx: number = Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); const pany: number = Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); @@ -188,19 +213,19 @@ export class CollectionFreeFormView extends React.Component { // DocumentDecorations.Instance.forceUpdate() return (
+ borderStyle: "solid", + borderWidth: "2px" + }}>
e.preventDefault()} style={{ width: "100%", height: "calc(100% - 4px)", overflow: "hidden" - }} onDrop={this.onDrop} onDragOver={this.onDragOver}> -
- + }} onDrop={this.onDrop} onDragOver={this.onDragOver} ref={this._ref}> +
+
{value.map(doc => { - return (); + return (); })}
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 33a126a7b..05f0928fb 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -14,6 +14,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import { DocumentDecorations } from "../../DocumentDecorations"; import { ContextMenu } from "../ContextMenu"; import { Opt } from "../../fields/Field"; +import { DragManager } from "../../util/DragManager"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? interface IProps { @@ -41,10 +42,7 @@ class DocumentContents extends React.Component { } render() { let doc = this.props.Document; - let bindings: any = { - doc: doc, - // isSelected: this.props.isSelected - }; + let bindings = {...this.props} as any; for (const key of this.layoutKeys) { bindings[key.Name + "Key"] = key; } @@ -125,15 +123,25 @@ export class DocumentView extends React.Component { } componentDidMount() { - // if(this._mainCont.current) { - // DragManager.MakeDraggable(this._mainCont.current, { - // buttons: 2, - // handlers: { - // dragComplete: () => {}, - // dragStart: () => {} - // } - // }) - // } + const that = this; + if(this._mainCont.current) { + DragManager.MakeDraggable(this._mainCont.current, { + buttons: 2, + handlers: { + dragComplete: () => {}, + dragStart: (e: DragManager.DragStartEvent) => { + if(!this.props.ContainingCollectionView) { + e.cancel(); + return; + } + const rect = this.screenRect; + e.data["document"] = this; + e.data["xOffset"] = e.x - rect.left; + e.data["yOffset"] = e.y - rect.top; + } + } + }) + } } @computed @@ -147,8 +155,8 @@ export class DocumentView extends React.Component { this._lastX = e.pageX; this._lastY = e.pageY; this._contextMenuCanOpen = e.button == 2; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); + // document.removeEventListener("pointermove", this.onPointerMove); + // document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); } @@ -238,7 +246,7 @@ export class DocumentView extends React.Component { onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}> - +
); } -- cgit v1.2.3-70-g09d2