aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts9
-rw-r--r--src/util/DragManager.ts17
-rw-r--r--src/views/freeformcanvas/CollectionFreeFormView.tsx107
-rw-r--r--src/views/nodes/DocumentView.tsx40
4 files changed, 110 insertions, 63 deletions
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<IProps> {
+ private _ref = React.createRef<HTMLDivElement>();
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<IProps> {
}
@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<IProps> {
}
- 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<IProps> {
}
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<IProps> {
// DocumentDecorations.Instance.forceUpdate()
return (
<div className="border" style={{
- borderStyle: "solid",
- borderWidth: "2px"
- }}>
+ borderStyle: "solid",
+ borderWidth: "2px"
+ }}>
<div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} style={{
width: "100%",
height: "calc(100% - 4px)",
overflow: "hidden"
- }} onDrop={this.onDrop} onDragOver={this.onDragOver}>
- <div className="collectionfreeformview" style={{ transform: `translate(${panx}px, ${pany}px) scale(${currScale}, ${currScale})` , transformOrigin: `left, top`}}>
-
+ }} onDrop={this.onDrop} onDragOver={this.onDragOver} ref={this._ref}>
+ <div className="collectionfreeformview" style={{ transform: `translate(${panx}px, ${pany}px) scale(${currScale}, ${currScale})`, transformOrigin: `left, top` }}>
+
<div className="node-container">
{value.map(doc => {
- return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentView={this.props.ContainingDocumentView}/>);
+ return (<DocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} ContainingDocumentView={this.props.ContainingDocumentView} />);
})}
</div>
</div>
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<IProps> {
}
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<IProps> {
}
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<IProps> {
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<IProps> {
onContextMenu={this.onContextMenu}
onPointerDown={this.onPointerDown}
onClick={this.onClick}>
- <DocumentContents {...this.props} />
+ <DocumentContents {...this.props} ContainingDocumentView={this} />
</div>
);
}