From 11134bc5ce01d0a025d311a4f83e67ff6e63ce1c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 9 Feb 2019 19:13:24 -0500 Subject: Moved client code to client folder --- src/client/util/DragManager.ts | 131 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/client/util/DragManager.ts (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts new file mode 100644 index 000000000..f4dcce7c8 --- /dev/null +++ b/src/client/util/DragManager.ts @@ -0,0 +1,131 @@ + +export namespace DragManager { + export function Root() { + const root = document.getElementById("root"); + if (!root) { + throw new Error("No root element found"); + } + return root; + } + + let dragDiv: HTMLDivElement; + + export enum DragButtons { + Left = 1, Right = 2, Both = Left | Right + } + + interface DragOptions { + handlers: DragHandlers; + + hideSource: boolean | (() => boolean); + } + + export interface DragDropDisposer { + (): void; + } + + export class DragCompleteEvent { + } + + export interface DragHandlers { + dragComplete: (e: DragCompleteEvent) => void; + } + + export interface DropOptions { + handlers: DropHandlers; + } + + export class DropEvent { + constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { } + } + + export interface DropHandlers { + drop: (e: Event, de: DropEvent) => void; + } + + export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer { + if ("canDrop" in element.dataset) { + throw new Error("Element is already droppable, can't make it droppable again"); + } + element.dataset["canDrop"] = "true"; + const handler = (e: Event) => { + const ce = e as CustomEvent; + options.handlers.drop(e, ce.detail); + }; + element.addEventListener("dashOnDrop", handler); + return () => { + element.removeEventListener("dashOnDrop", handler); + delete element.dataset["canDrop"] + }; + } + + + let _lastPointerX: number = 0; + let _lastPointerY: number = 0; + export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options: DragOptions) { + if (!dragDiv) { + dragDiv = document.createElement("div"); + DragManager.Root().appendChild(dragDiv); + } + const w = ele.offsetWidth, h = ele.offsetHeight; + const rect = ele.getBoundingClientRect(); + const scaleX = rect.width / w, scaleY = rect.height / h; + let x = rect.left, y = rect.top; + // const offsetX = e.x - rect.left, offsetY = e.y - rect.top; + let dragElement = ele.cloneNode(true) as HTMLElement; + dragElement.style.opacity = "0.7"; + dragElement.style.position = "absolute"; + dragElement.style.transformOrigin = "0 0"; + dragElement.style.zIndex = "1000"; + dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; + dragDiv.appendChild(dragElement); + _lastPointerX = dragData["xOffset"] + rect.left; + _lastPointerY = dragData["yOffset"] + rect.top; + + let hideSource = false; + if (typeof options.hideSource === "boolean") { + hideSource = options.hideSource; + } else { + hideSource = options.hideSource(); + } + const wasHidden = ele.hidden; + if (hideSource) { + ele.hidden = true; + } + + const moveHandler = (e: PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + x += e.clientX - _lastPointerX; _lastPointerX = e.clientX; + y += e.clientY - _lastPointerY; _lastPointerY = e.clientY; + dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; + }; + const upHandler = (e: PointerEvent) => { + document.removeEventListener("pointermove", moveHandler, true); + document.removeEventListener("pointerup", upHandler); + FinishDrag(dragElement, e, options, dragData); + if (hideSource && !wasHidden) { + ele.hidden = false; + } + }; + document.addEventListener("pointermove", moveHandler, true); + document.addEventListener("pointerup", upHandler); + } + + function FinishDrag(dragEle: HTMLElement, e: PointerEvent, options: DragOptions, dragData: { [index: string]: any }) { + dragDiv.removeChild(dragEle); + const target = document.elementFromPoint(e.x, e.y); + if (!target) { + return; + } + target.dispatchEvent(new CustomEvent("dashOnDrop", { + bubbles: true, + detail: { + x: e.x, + y: e.y, + data: dragData + } + })); + options.handlers.dragComplete({}); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c93c3e1970c6ecc91b60f1782e82b1bfdc7fef30 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 13 Feb 2019 04:50:56 -0500 Subject: A lot of stuff working, a lot of other stuff not working --- .vscode/launch.json | 6 +- src/client/util/DragManager.ts | 2 + src/client/util/SelectionManager.ts | 12 +- src/client/util/Transform.ts | 70 ++++---- src/client/views/DocumentDecorations.tsx | 39 ++++- src/client/views/Main.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 10 +- .../views/collections/CollectionFreeFormView.tsx | 55 +++--- .../views/collections/CollectionSchemaView.tsx | 4 +- .../views/collections/CollectionViewBase.tsx | 10 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 138 +--------------- src/client/views/nodes/DocumentView.tsx | 184 +++++++++++++++++++-- src/client/views/nodes/FieldView.tsx | 6 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 4 +- 15 files changed, 303 insertions(+), 240 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/.vscode/launch.json b/.vscode/launch.json index 9a0a9afb4..546ede805 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,11 @@ "sourceMaps": true, "breakOnLoad": true, "url": "http://localhost:1050", - "webRoot": "${workspaceFolder}" + "webRoot": "${workspaceFolder}", + "skipFiles": [ + "${workspaceRoot}/node_modules/**/*.js", + "${workspaceRoot}/node_modules/**/*.ts", + ] }, { "type": "node", diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index f4dcce7c8..93b927f8b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -78,6 +78,8 @@ export namespace DragManager { dragElement.style.transformOrigin = "0 0"; dragElement.style.zIndex = "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; + dragElement.style.width = `${rect.width}px`; + dragElement.style.height = `${rect.height}px`; dragDiv.appendChild(dragElement); _lastPointerX = dragData["xOffset"] + rect.left; _lastPointerY = dragData["yOffset"] + rect.top; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0759ae110..1a711ae64 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,13 +1,13 @@ -import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; import { observable, action } from "mobx"; +import { DocumentView } from "../views/nodes/DocumentView"; export namespace SelectionManager { class Manager { @observable - SelectedDocuments: Array = []; + SelectedDocuments: Array = []; @action - SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void { + SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { // if doc is not in SelectedDocuments, add it if (!ctrlPressed) { manager.SelectedDocuments = []; @@ -21,11 +21,11 @@ export namespace SelectionManager { const manager = new Manager; - export function SelectDoc(doc: CollectionFreeFormDocumentView, ctrlPressed: boolean): void { + export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { manager.SelectDoc(doc, ctrlPressed) } - export function IsSelected(doc: CollectionFreeFormDocumentView): boolean { + export function IsSelected(doc: DocumentView): boolean { return manager.SelectedDocuments.indexOf(doc) !== -1; } @@ -33,7 +33,7 @@ export namespace SelectionManager { manager.SelectedDocuments = [] } - export function SelectedDocuments(): Array { + export function SelectedDocuments(): Array { return manager.SelectedDocuments; } } \ No newline at end of file diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts index 3edc8d569..8ae3f837f 100644 --- a/src/client/util/Transform.ts +++ b/src/client/util/Transform.ts @@ -23,29 +23,13 @@ export class Transform { return this; } - translated = (x: number, y: number): Transform => { - return this.copy().translate(x, y); - } - - preTranslate = (x: number, y: number): Transform => { - this._translateX += x * this._scale; - this._translateY += y * this._scale; - return this; - } - - preTranslated = (x: number, y: number): Transform => { - return this.copy().preTranslate(x, y); - } - scale = (scale: number): Transform => { this._scale *= scale; + this._translateX *= scale; + this._translateY *= scale; return this; } - scaled = (scale: number): Transform => { - return this.copy().scale(scale); - } - scaleAbout = (scale: number, x: number, y: number): Transform => { this._translateX += x * this._scale - x * this._scale * scale; this._translateY += y * this._scale - y * this._scale * scale; @@ -53,21 +37,6 @@ export class Transform { return this; } - scaledAbout = (scale: number, x: number, y: number): Transform => { - return this.copy().scaleAbout(scale, x, y); - } - - preScale = (scale: number): Transform => { - this._scale *= scale; - this._translateX *= scale; - this._translateY *= scale; - return this; - } - - preScaled = (scale: number): Transform => { - return this.copy().preScale(scale); - } - transform = (transform: Transform): Transform => { this._translateX += transform._translateX * this._scale; this._translateY += transform._translateY * this._scale; @@ -75,8 +44,15 @@ export class Transform { return this; } - transformed = (transform: Transform): Transform => { - return this.copy().transform(transform); + preTranslate = (x: number, y: number): Transform => { + this._translateX += this._scale * x; + this._translateY += this._scale * y; + return this; + } + + preScale = (scale: number): Transform => { + this._scale *= scale; + return this; } preTransform = (transform: Transform): Transform => { @@ -86,6 +62,30 @@ export class Transform { return this; } + translated = (x: number, y: number): Transform => { + return this.copy().translate(x, y); + } + + preTranslated = (x: number, y: number): Transform => { + return this.copy().preTranslate(x, y); + } + + scaled = (scale: number): Transform => { + return this.copy().scale(scale); + } + + scaledAbout = (scale: number, x: number, y: number): Transform => { + return this.copy().scaleAbout(scale, x, y); + } + + preScaled = (scale: number): Transform => { + return this.copy().preScale(scale); + } + + transformed = (transform: Transform): Transform => { + return this.copy().transform(transform); + } + preTransformed = (transform: Transform): Transform => { return this.copy().preTransform(transform); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 85b44307f..5abe3f5b2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -4,6 +4,8 @@ import { SelectionManager } from "../util/SelectionManager"; import { observer } from "mobx-react"; import './DocumentDecorations.scss' import { CollectionFreeFormView } from "./collections/CollectionFreeFormView"; +import { KeyStore } from "../../fields/Key"; +import { NumberField } from "../../fields/NumberField"; @observer export class DocumentDecorations extends React.Component { @@ -25,9 +27,12 @@ export class DocumentDecorations extends React.Component { !(element.props.ContainingCollectionView instanceof CollectionFreeFormView)) { return bounds; } - let transform = element.getTransform().inverse(); + let transform = element.props.GetTransform().inverse(); var [sptX, sptY] = transform.transformPoint(0, 0); - var [bptX, bptY] = transform.transformDirection(element.width, element.height); + // var [bptX, bptY] = transform.transformDirection(element.width, element.height); + let doc = element.props.Document; + let [bptX, bptY] = [doc.GetNumber(KeyStore.Width, 0), doc.GetNumber(KeyStore.Height, 0)]; + [bptX, bptY] = transform.transformPoint(bptX, bptY); return { x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) @@ -106,16 +111,32 @@ export class DocumentDecorations extends React.Component { SelectionManager.SelectedDocuments().forEach(element => { const rect = element.screenRect; + // if (rect.width !== 0) { + // let scale = element.width / rect.width; + // let actualdW = Math.max(element.width + (dW * scale), 20); + // let actualdH = Math.max(element.height + (dH * scale), 20); + // element.x += dX * (actualdW - element.width); + // element.y += dY * (actualdH - element.height); + // if (Math.abs(dW) > Math.abs(dH)) + // element.width = actualdW; + // else + // element.height = actualdH; + // } if (rect.width !== 0) { - let scale = element.width / rect.width; - let actualdW = Math.max(element.width + (dW * scale), 20); - let actualdH = Math.max(element.height + (dH * scale), 20); - element.x += dX * (actualdW - element.width); - element.y += dY * (actualdH - element.height); + let doc = element.props.Document; + let width = doc.GetOrCreate(KeyStore.Width, NumberField); + let height = doc.GetOrCreate(KeyStore.Height, NumberField); + let x = doc.GetOrCreate(KeyStore.X, NumberField); + let y = doc.GetOrCreate(KeyStore.X, NumberField); + let scale = width.Data / rect.width; + let actualdW = Math.max(width.Data + (dW * scale), 20); + let actualdH = Math.max(height.Data + (dH * scale), 20); + x.Data += dX * (actualdW - width.Data); + y.Data += dY * (actualdH - height.Data); if (Math.abs(dW) > Math.abs(dH)) - element.width = actualdW; + width.Data = actualdW; else - element.height = actualdH; + height.Data = actualdH; } }) } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6ca0000b8..c7ad3e249 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -84,6 +84,7 @@ ReactDOM.render(( Transform.Identity} Scaling={1} + isTopMost={true} ContainingCollectionView={undefined} DocumentView={undefined} /> diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d3e90d11c..c870a9cf0 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -16,6 +16,7 @@ import "./CollectionDockingView.scss"; import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; import React = require("react"); import { changeDependenciesStateTo0 } from "mobx/lib/internal"; +import { Utils } from "../../../Utils"; @observer export class CollectionDockingView extends CollectionViewBase { @@ -100,6 +101,7 @@ export class CollectionDockingView extends CollectionViewBase { return ( Transform.Identity} + isTopMost={true} Scaling={1} ContainingCollectionView={this} DocumentView={undefined} />); } @@ -307,12 +309,16 @@ class RenderClass { this.render(); } render() { - var nativeWidth = this._document.GetNumber(KeyStore.NativeWidth, 0); + let nativeWidth = this._document.GetNumber(KeyStore.NativeWidth, 0); let scaling = nativeWidth > 0 ? this._htmlElement!.clientWidth / nativeWidth : 1; ReactDOM.render(( Transform.Identity} + GetTransform={() => { + let { scale, translateX, translateY } = Utils.GetScreenTransform(this._htmlElement); + return this._collectionDockingView.props.GetTransform().scale(scale).translate(-translateX, -translateY) + }} + isTopMost={true} Scaling={scaling} ContainingCollectionView={this._collectionDockingView} DocumentView={undefined} /> ), diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 975eaaae8..7947b1c51 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -14,6 +14,7 @@ import { NumberField } from "../../../fields/NumberField"; import { Documents } from "../../documents/Documents"; import { FieldWaiting } from "../../../fields/Field"; import { Transform } from "../../util/Transform"; +import { DocumentView } from "../nodes/DocumentView"; @observer export class CollectionFreeFormView extends CollectionViewBase { @@ -45,23 +46,21 @@ export class CollectionFreeFormView extends CollectionViewBase { @action drop = (e: Event, de: DragManager.DropEvent) => { - const doc = de.data["document"]; + const doc: DocumentView = de.data["document"]; var me = this; - if (doc instanceof CollectionFreeFormDocumentView) { - if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) { - doc.props.ContainingCollectionView.removeDocument(doc.props.Document); - this.addDocument(doc.props.Document); - } - const xOffset = de.data["xOffset"] as number || 0; - const yOffset = de.data["yOffset"] as number || 0; - const { translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!); - const currScale = this.resizeScaling * this.zoomScaling * this.props.ContainingDocumentView!.ScalingToScreenSpace; - const screenX = de.x - xOffset; - const screenY = de.y - yOffset; - doc.x = (screenX - translateX) / currScale; - doc.y = (screenY - translateY) / currScale; - this.bringToFront(doc); + if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) { + doc.props.ContainingCollectionView.removeDocument(doc.props.Document); + this.addDocument(doc.props.Document); } + const xOffset = de.data["xOffset"] as number || 0; + const yOffset = de.data["yOffset"] as number || 0; + const transform = doc.props.GetTransform(); + const screenX = de.x - xOffset; + const screenY = de.y - yOffset; + const [x, y] = transform.transformPoint(screenX, screenY); + doc.props.Document.SetNumber(KeyStore.X, x); + doc.props.Document.SetNumber(KeyStore.Y, y); + this.bringToFront(doc); e.stopPropagation(); } @@ -94,8 +93,8 @@ export class CollectionFreeFormView extends CollectionViewBase { document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); if (Math.abs(this._downX - e.clientX) < 3 && Math.abs(this._downY - e.clientY) < 3) { - if (!SelectionManager.IsSelected(this.props.ContainingDocumentView as CollectionFreeFormDocumentView)) { - SelectionManager.SelectDoc(this.props.ContainingDocumentView as CollectionFreeFormDocumentView, false); + if (!this.props.isSelected()) { + this.props.select(false); } } } @@ -105,11 +104,11 @@ export class CollectionFreeFormView extends CollectionViewBase { if (!e.cancelBubble && this.active) { e.preventDefault(); e.stopPropagation(); - let currScale: number = this.props.ContainingDocumentView!.ScalingToScreenSpace; let x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0); let y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0); + let [dx, dy] = this.props.GetTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); - this.SetPan(x + (e.pageX - this._lastX) / currScale, y + (e.pageY - this._lastY) / currScale); + this.SetPan(x + dx, y + dy); } this._lastX = e.pageX; this._lastY = e.pageY; @@ -124,15 +123,14 @@ export class CollectionFreeFormView extends CollectionViewBase { // if (modes[e.deltaMode] == 'pixels') coefficient = 50; // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height?? let transform = this.getTransform(); - let localTransform = this.getLocalTransform(); - let deltaScale = (1 - (e.deltaY / coefficient)) * transform.Scale; - let newDeltaScale = this.isAnnotationOverlay ? Math.max(1, deltaScale) : deltaScale; + let deltaScale = (1 - (e.deltaY / coefficient)); let [x, y] = transform.transformPoint(e.clientX, e.clientY); - localTransform.scaleAbout(newDeltaScale, x, y); + let localTransform = this.getLocalTransform(); + localTransform.scaleAbout(deltaScale, x, y); - this.props.DocumentForCollection.SetNumber(KeyStore.Scale, newDeltaScale); + this.props.DocumentForCollection.SetNumber(KeyStore.Scale, localTransform.Scale); this.SetPan(localTransform.TranslateX, localTransform.TranslateY); } @@ -182,7 +180,7 @@ export class CollectionFreeFormView extends CollectionViewBase { } @action - bringToFront(doc: CollectionFreeFormDocumentView) { + bringToFront(doc: DocumentView) { const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props; const value: Document[] = Document.GetList(fieldKey, []); @@ -213,12 +211,12 @@ export class CollectionFreeFormView extends CollectionViewBase { getTransform = (): Transform => { const [x, y] = this.translate; - return this.props.GetTransform().scaled(this.scale).translate(x, y); + return this.props.GetTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform().inverse()) } getLocalTransform = (): Transform => { const [x, y] = this.translate; - return new Transform(x, y, this.scale); + return Transform.Identity.scale(this.scale).translate(x, y); } render() { @@ -249,8 +247,9 @@ export class CollectionFreeFormView extends CollectionViewBase { AddDocument={this.addDocument} RemoveDocument={this.removeDocument} GetTransform={this.getTransform} + isTopMost={false} Scaling={1} - ContainingCollectionView={this} DocumentView={undefined} />); + ContainingCollectionView={this} DocumentView={this.props.ContainingDocumentView} />); })} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f1e882e20..adae8560e 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -27,7 +27,8 @@ export class CollectionSchemaView extends CollectionViewBase { let props: FieldViewProps = { doc: rowProps.value[0], fieldKey: rowProps.value[1], - DocumentViewForField: undefined, + isSelected: () => false, + isTopMost: false } let contents = ( @@ -110,6 +111,7 @@ export class CollectionSchemaView extends CollectionViewBase { AddDocument={this.addDocument} RemoveDocument={this.removeDocument} GetTransform={() => Transform.Identity}//TODO This should probably be an actual transform Scaling={1} + isTopMost={false} DocumentView={undefined} ContainingCollectionView={this} /> ) } else { diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index cf5bc70c4..2c950c8ae 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -18,6 +18,9 @@ export interface CollectionViewProps { DocumentForCollection: Document; ContainingDocumentView: Opt; GetTransform: () => Transform; + isSelected: () => boolean; + isTopMost: boolean; + select: (ctrlPressed: boolean) => void; BackgroundView: Opt; Scaling: number; } @@ -29,16 +32,15 @@ export class CollectionViewBase extends React.Component { public static LayoutString(collectionType: string, fieldKey: string = "DataKey") { return `<${collectionType} Scaling={Scaling} DocumentForCollection={Document} - GetTransform={GetTransform} CollectionFieldKey={${fieldKey}} + GetTransform={GetTransform} CollectionFieldKey={${fieldKey}} isSelected={isSelected} select={select} + isTopMost={isTopMost} ContainingDocumentView={DocumentView} BackgroundView={BackgroundView} />`; } @computed public get active(): boolean { var isSelected = (this.props.ContainingDocumentView instanceof CollectionFreeFormDocumentView && 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 || - this.props.ContainingDocumentView.props.ContainingCollectionView instanceof CollectionDockingView); + var topMost = this.props.isTopMost; return isSelected || childSelected || topMost; } @action diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 9cd42a069..54bc7327b 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -14,11 +14,8 @@ import { Transform } from "../../util/Transform"; @observer -export class CollectionFreeFormDocumentView extends DocumentView { - private _contextMenuCanOpen = false; - private _downX: number = 0; - private _downY: number = 0; - // private _mainCont = React.createRef(); +export class CollectionFreeFormDocumentView extends React.Component { + private _mainCont = React.createRef(); constructor(props: DocumentViewProps) { super(props); @@ -95,130 +92,6 @@ export class CollectionFreeFormDocumentView extends DocumentView { this.props.Document.SetData(KeyStore.ZIndex, h, NumberField) } - @action - dragComplete = (e: DragManager.DragCompleteEvent) => { - } - - @computed - get active(): boolean { - return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || - this.props.ContainingCollectionView.active; - } - - @computed - get topMost(): boolean { - return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView; - } - - onPointerDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - var me = this; - if (e.shiftKey && e.buttons === 1) { - CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document); - e.stopPropagation(); - return; - } - this._contextMenuCanOpen = e.button == 2; - if (this.active && !e.isDefaultPrevented()) { - e.stopPropagation(); - if (e.buttons === 2) { - e.preventDefault(); - } - document.removeEventListener("pointermove", this.onPointerMove) - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp) - document.addEventListener("pointerup", this.onPointerUp); - } - } - - onPointerMove = (e: PointerEvent): void => { - if (e.cancelBubble) { - this._contextMenuCanOpen = false; - return; - } - if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - this._contextMenuCanOpen = false; - if (this._mainCont.current != null && !this.topMost) { - this._contextMenuCanOpen = false; - const rect = this.screenRect; - let dragData: { [id: string]: any } = {}; - dragData["document"] = this; - dragData["xOffset"] = e.x - rect.left; - dragData["yOffset"] = e.y - rect.top; - DragManager.StartDrag(this._mainCont.current, dragData, { - handlers: { - dragComplete: this.dragComplete, - }, - hideSource: true - }) - } - } - e.stopPropagation(); - e.preventDefault(); - } - - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onPointerMove) - document.removeEventListener("pointerup", this.onPointerUp) - e.stopPropagation(); - if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { - SelectionManager.SelectDoc(this, e.ctrlKey); - } - } - - openRight = (e: React.MouseEvent): void => { - CollectionDockingView.AddRightSplit(this.props.Document); - } - - deleteClicked = (e: React.MouseEvent): void => { - if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) { - this.props.ContainingCollectionView.removeDocument(this.props.Document) - } - } - @action - fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.OpenFullScreen(this.props.Document); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - @action - closeFullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.CloseFullScreen(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - - @action - onContextMenu = (e: React.MouseEvent): void => { - if (!SelectionManager.IsSelected(this)) { - return; - } - e.preventDefault() - - if (!this._contextMenuCanOpen) { - return; - } - - if (this.topMost) { - ContextMenu.Instance.clearItems() - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - else { - // DocumentViews should stop propogation of this event - e.stopPropagation(); - - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight }) - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - SelectionManager.SelectDoc(this, e.ctrlKey); - } - } getTransform = (): Transform => { return this.props.GetTransform().translated(this.x, this.y); @@ -234,11 +107,10 @@ export class CollectionFreeFormDocumentView extends DocumentView { height: freestyling ? this.height : "100%", position: freestyling ? "absolute" : "relative", zIndex: freestyling ? this.zIndex : 0, - }} - onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown}> + backgroundColor: "transparent" + }} > - + ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d7ecc6d9d..cb080c08e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -16,6 +16,9 @@ import { ImageBox } from "../nodes/ImageBox"; import "./NodeView.scss"; import React = require("react"); import { Transform } from "../../util/Transform"; +import { SelectionManager } from "../../util/SelectionManager"; +import { DragManager } from "../../util/DragManager"; +import { ContextMenu } from "../ContextMenu"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? export interface DocumentViewProps { @@ -26,24 +29,34 @@ export interface DocumentViewProps { AddDocument?: (doc: Document) => void; RemoveDocument?: (doc: Document) => boolean; GetTransform: () => Transform; + isTopMost: boolean; Scaling: number; } @observer export class DocumentView extends React.Component { - protected _mainCont = React.createRef(); + private _mainCont = React.createRef(); get MainContent() { return this._mainCont; } + get screenRect(): ClientRect | DOMRect { + if (this._mainCont.current) { + return this._mainCont.current.getBoundingClientRect(); + } + return new DOMRect(); + } @computed get layout(): string { return this.props.Document.GetData(KeyStore.Layout, TextField, String("

Error loading layout data

")); } @computed - get backgroundLayout(): string { - return this.props.Document.GetData(KeyStore.BackgroundLayout, TextField, String("

Error loading layout data

")); + get backgroundLayout(): string | undefined { + let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField); + if (field && field !== "") { + return field.Data; + } } @computed @@ -56,6 +69,134 @@ export class DocumentView extends React.Component { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array()); } + @computed + get active(): boolean { + return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || + this.props.ContainingCollectionView.active; + } + + private _contextMenuCanOpen = false; + private _downX: number = 0; + private _downY: number = 0; + onPointerDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + var me = this; + if (e.shiftKey && e.buttons === 1) { + CollectionDockingView.StartOtherDrag(this._mainCont.current!, this.props.Document); + e.stopPropagation(); + return; + } + this._contextMenuCanOpen = e.button == 2; + if (this.active && !e.isDefaultPrevented()) { + e.stopPropagation(); + if (e.buttons === 2) { + e.preventDefault(); + } + document.removeEventListener("pointermove", this.onPointerMove) + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp) + document.addEventListener("pointerup", this.onPointerUp); + } + } + + @action + dragComplete = (e: DragManager.DragCompleteEvent) => { + } + + @computed + get topMost(): boolean { + return this.props.ContainingCollectionView == undefined || this.props.ContainingCollectionView instanceof CollectionDockingView; + } + + onPointerMove = (e: PointerEvent): void => { + if (e.cancelBubble) { + this._contextMenuCanOpen = false; + return; + } + if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { + this._contextMenuCanOpen = false; + if (this._mainCont.current != null && !this.topMost) { + this._contextMenuCanOpen = false; + const [left, top] = this.props.GetTransform().inverse().transformPoint(0, 0); + let dragData: { [id: string]: any } = {}; + dragData["document"] = this; + dragData["xOffset"] = e.x - left; + dragData["yOffset"] = e.y - top; + DragManager.StartDrag(this._mainCont.current, dragData, { + handlers: { + dragComplete: this.dragComplete, + }, + hideSource: true + }) + } + } + e.stopPropagation(); + e.preventDefault(); + } + + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove) + document.removeEventListener("pointerup", this.onPointerUp) + e.stopPropagation(); + if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { + SelectionManager.SelectDoc(this, e.ctrlKey); + } + } + + openRight = (e: React.MouseEvent): void => { + CollectionDockingView.AddRightSplit(this.props.Document); + } + + deleteClicked = (e: React.MouseEvent): void => { + if (this.props.RemoveDocument) { + this.props.RemoveDocument(this.props.Document); + } + } + @action + fullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.OpenFullScreen(this.props.Document); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + @action + closeFullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.CloseFullScreen(); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + + @action + onContextMenu = (e: React.MouseEvent): void => { + if (!SelectionManager.IsSelected(this)) { + return; + } + e.preventDefault() + + if (!this._contextMenuCanOpen) { + return; + } + + if (this.topMost) { + ContextMenu.Instance.clearItems() + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + } + else { + // DocumentViews should stop propogation of this event + e.stopPropagation(); + + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.addItem({ description: "Open Right", event: this.openRight }) + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + SelectionManager.SelectDoc(this, e.ctrlKey); + } + } + // // returns the cumulative scaling between the document and the screen // @@ -69,9 +210,19 @@ export class DocumentView extends React.Component { return 1; } + isSelected = () => { + return SelectionManager.IsSelected(this); + } + + select = (ctrlPressed: boolean) => { + SelectionManager.SelectDoc(this, ctrlPressed) + } + render() { let bindings = { ...this.props } as any; + bindings.isSelected = this.isSelected; + bindings.select = this.select; for (const key of this.layoutKeys) { bindings[key.Name + "Key"] = key; // this maps string values of the form Key to an actual key Kestore.keyname e.g, "DataKey" => KeyStore.Data } @@ -82,26 +233,29 @@ export class DocumentView extends React.Component { let field = this.props.Document.Get(key); bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field; } - if (bindings.DocumentView === undefined) { - bindings.DocumentView = this; // set the DocumentView to this if it hasn't already been set by a sub-class during its render method. + let annotated = null; + let backgroundLayout = this.backgroundLayout; + if (backgroundLayout) { + annotated = { console.log(test) }} + />; } - var annotated = { console.log(test) }} - />; - bindings["BackgroundView"] = this.backgroundLayout ? annotated : null; + bindings.BackgroundView = annotated; var width = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); var strwidth = width > 0 ? width.toString() + "px" : "100%"; var height = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); var strheight = height > 0 ? height.toString() + "px" : "100%"; return ( -
+
+ isSelected: () => boolean; + isTopMost: boolean; } @observer export class FieldView extends React.Component { - public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} />`; } + public static LayoutString(fieldType: string) { return `<${fieldType} doc={Document} DocumentViewForField={DocumentView} fieldKey={DataKey} isSelected={isSelected} isTopMost={isTopMost} />`; } @computed get field(): FieldValue { const { doc, fieldKey } = this.props; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f6bd0c0f8..2e3d396c1 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -110,7 +110,7 @@ export class FormattedTextBox extends React.Component { } onPointerDown = (e: React.PointerEvent): void => { let me = this; - if (e.buttons === 1 && me.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(me.props.DocumentViewForField)) { + if (e.buttons === 1 && this.props.isSelected()) { e.stopPropagation(); } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 2fa70734d..e1fa26e2f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -41,7 +41,7 @@ export class ImageBox extends React.Component { onPointerDown = (e: React.PointerEvent): void => { if (Date.now() - this._lastTap < 300) { - if (e.buttons === 1 && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { + if (e.buttons === 1 && this.props.isSelected()) { e.stopPropagation(); this._downX = e.clientX; this._downY = e.clientY; @@ -63,7 +63,7 @@ export class ImageBox extends React.Component { lightbox = (path: string) => { const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; - if (this._isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { + if (this._isOpen && this.props.isSelected()) { return ( Date: Wed, 13 Feb 2019 23:04:20 -0500 Subject: fixed drag feedback --- src/client/util/DragManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 93b927f8b..f1b0445ca 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -78,8 +78,8 @@ export namespace DragManager { dragElement.style.transformOrigin = "0 0"; dragElement.style.zIndex = "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; - dragElement.style.width = `${rect.width}px`; - dragElement.style.height = `${rect.height}px`; + dragElement.style.width = `${rect.width / scaleX}px`; + dragElement.style.height = `${rect.height / scaleY}px`; dragDiv.appendChild(dragElement); _lastPointerX = dragData["xOffset"] + rect.left; _lastPointerY = dragData["yOffset"] + rect.top; -- cgit v1.2.3-70-g09d2 From bc7a13cb54d3f60b4e9ad301d17db2941eb84912 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 17 Feb 2019 07:50:37 -0500 Subject: Trying to fix drop with transforms --- src/client/util/DragManager.ts | 10 ++++++---- src/client/views/collections/CollectionDockingView.tsx | 12 ++++++++---- src/client/views/collections/CollectionFreeFormView.tsx | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index f1b0445ca..337ec855a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -80,9 +80,11 @@ export namespace DragManager { dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; dragElement.style.width = `${rect.width / scaleX}px`; dragElement.style.height = `${rect.height / scaleY}px`; + // It seems like the above code should be able to just be this: + // dragElement.style.transform = `translate(${x}px, ${y}px)`; + // dragElement.style.width = `${rect.width}px`; + // dragElement.style.height = `${rect.height}px`; dragDiv.appendChild(dragElement); - _lastPointerX = dragData["xOffset"] + rect.left; - _lastPointerY = dragData["yOffset"] + rect.top; let hideSource = false; if (typeof options.hideSource === "boolean") { @@ -98,8 +100,8 @@ export namespace DragManager { const moveHandler = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); - x += e.clientX - _lastPointerX; _lastPointerX = e.clientX; - y += e.clientY - _lastPointerY; _lastPointerY = e.clientY; + x += e.movementX; + y += e.movementY; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; }; const upHandler = (e: PointerEvent) => { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 39716170b..adfcb96ee 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -15,6 +15,7 @@ import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from import React = require("react"); import * as ReactDOM from 'react-dom'; import Measure from "react-measure"; +import { Utils } from "../../../Utils"; @observer export class CollectionDockingView extends CollectionViewBase { @@ -239,14 +240,14 @@ export class CollectionDockingView extends CollectionViewBase { var containingDiv = "component_" + me.nextId(); container.getElement().html("
"); setTimeout(function () { - let divContainer = document.getElementById(containingDiv); + let divContainer = document.getElementById(containingDiv) as HTMLDivElement; if (divContainer) { let props: DockingProps = { ContainingDiv: containingDiv, Document: state.doc, Container: container, CollectionDockingView: me, - HtmlElement: divContainer + HtmlElement: divContainer, } ReactDOM.render((), divContainer); if (CollectionDockingView.myLayout._maxstack) { @@ -293,7 +294,7 @@ interface DockingProps { Document: Document, Container: any, HtmlElement: HTMLElement, - CollectionDockingView: CollectionDockingView + CollectionDockingView: CollectionDockingView, } @observer export class RenderClass extends React.Component { @@ -307,8 +308,11 @@ export class RenderClass extends React.Component { Transform.Identity} Scaling={this._parentScaling} + GetTransform={() => { + let { scale, translateX, translateY } = Utils.GetScreenTransform(this.props.HtmlElement); + return this.props.CollectionDockingView.props.GetTransform().scale(scale).translate(translateX, translateY) + }} isTopMost={true} ContainingCollectionView={this.props.CollectionDockingView} DocumentView={undefined} /> diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index b5e954e83..49864ca6c 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -54,6 +54,7 @@ export class CollectionFreeFormView extends CollectionViewBase { } const xOffset = de.data["xOffset"] as number || 0; const yOffset = de.data["yOffset"] as number || 0; + //this should be able to use translate and scale methods on an Identity transform, no? const transform = new Transform(0, 0, 1 / me.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1)).transform( new Transform(-me.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0), -me.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0), 1) ).transform(me.props.GetTransform()); -- cgit v1.2.3-70-g09d2 From 3e02f7c7efe0b07ab1e34165e6d8d369f69110b0 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 20 Feb 2019 10:55:30 -0500 Subject: fixed dragdrop issue. improved selection in schema views, but not fixed fully. --- src/client/util/DragManager.ts | 6 +- src/client/views/DocumentDecorations.tsx | 19 ++-- .../views/collections/CollectionSchemaView.tsx | 110 ++++++++++----------- 3 files changed, 62 insertions(+), 73 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 337ec855a..6d5fe12a7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,3 +1,4 @@ +import { DocumentDecorations } from "../views/DocumentDecorations"; export namespace DragManager { export function Root() { @@ -59,10 +60,8 @@ export namespace DragManager { }; } - - let _lastPointerX: number = 0; - let _lastPointerY: number = 0; export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options: DragOptions) { + DocumentDecorations.Instance.Hidden = true; if (!dragDiv) { dragDiv = document.createElement("div"); DragManager.Root().appendChild(dragDiv); @@ -131,5 +130,6 @@ export namespace DragManager { } })); options.handlers.dragComplete({}); + DocumentDecorations.Instance.Hidden = false; } } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 770433e27..dccab1dc5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,9 +1,8 @@ -import { observable, computed } from "mobx"; +import { observable, computed, action } from "mobx"; import React = require("react"); import { SelectionManager } from "../util/SelectionManager"; import { observer } from "mobx-react"; import './DocumentDecorations.scss' -import { CollectionFreeFormView } from "./collections/CollectionFreeFormView"; import { KeyStore } from '../../fields/KeyStore' import { NumberField } from "../../fields/NumberField"; @@ -12,7 +11,7 @@ export class DocumentDecorations extends React.Component { static Instance: DocumentDecorations private _resizer = "" private _isPointerDown = false; - @observable private _opacity = 1; + @observable private _hidden = false; constructor(props: Readonly<{}>) { super(props) @@ -39,14 +38,10 @@ export class DocumentDecorations extends React.Component { }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); } - @computed - get opacity(): number { - return this._opacity - } - set opacity(o: number) { - this._opacity = Math.min(Math.max(0, o), 1) - } + @computed + public get Hidden() { return this._hidden; } + public set Hidden(value: boolean) { this._hidden = value; } onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -147,13 +142,15 @@ export class DocumentDecorations extends React.Component { render() { var bounds = this.Bounds; + if (this.Hidden) { + return (null); + } return (
e.preventDefault()}>
e.preventDefault()}>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 597a97222..fa37e0e76 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -2,7 +2,6 @@ import React = require("react") import { action, observable } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; -import SplitPane from "react-split-pane"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; @@ -15,7 +14,6 @@ import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase"; -import { relative } from "path"; @observer export class CollectionSchemaView extends CollectionViewBase { @@ -67,6 +65,7 @@ export class CollectionSchemaView extends CollectionViewBase { ) } + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { @@ -75,8 +74,7 @@ export class CollectionSchemaView extends CollectionViewBase { return { onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that.selectedIndex = rowInfo.index; - const doc: Document = rowInfo.original; - console.log("Row clicked: ", doc.Title) + this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize if (handleOriginal) { handleOriginal() @@ -118,70 +116,64 @@ export class CollectionSchemaView extends CollectionViewBase { } } + innerScreenToLocal(tx: number, ty: number) { + return () => this.props.ScreenToLocalTransform().transform(new Transform(-tx - 5 - COLLECTION_BORDER_WIDTH, -ty - COLLECTION_BORDER_WIDTH, 1)) + } - @observable - private _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView + @observable _parentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ParentScaling prop of the DocumentView + @observable _dividerX = 0; + @observable _dividerY = 0; render() { - const { Document: Document, fieldKey: fieldKey } = this.props; - const children = Document.GetList(fieldKey, []); - const columns = Document.GetList(KeyStore.ColumnsKey, - [KeyStore.Title, KeyStore.Data, KeyStore.Author]) - let content =
+ const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author]) + const children = this.props.Document.GetList(this.props.fieldKey, []); + const selected = children.length > this.selectedIndex ? children[this.selectedIndex] : undefined; let me = this; - if (this.selectedIndex != -1) { - content = ( + let content = this.selectedIndex == -1 || !selected ? (null) : ( + this._parentScaling = r.entry.width / selected.GetNumber(KeyStore.NativeWidth, r.entry.width))}> + {({ measureRef }) => +
+ +
+ } +
+ ) + return ( +
{ - var doc = children[this.selectedIndex]; - var n = doc.GetNumber(KeyStore.NativeWidth, 0); - if (n > 0 && r.entry.width > 0) { - this._parentScaling = r.entry.width / n; - } + this._dividerX = r.entry.width; })}> {({ measureRef }) => -
- Transform.Identity}//TODO This should probably be an actual transform - Scaling={this._parentScaling} - isTopMost={false} - ContainingCollectionView={me} /> +
+ { + return ( + { + Header: col.Name, + accessor: (doc: Document) => [doc, col], + id: col.Id + }) + })} + column={{ + ...ReactTableDefaults.column, + Cell: this.renderCell + }} + getTrProps={this.getTrProps} + />
} - ) - } - let nativeWidth = Document.GetNumber(KeyStore.NativeWidth, 0); - return ( -
-
- { - return ( - { - Header: col.Name, - accessor: (doc: Document) => [doc, col], - id: col.Id - }) - })} - column={{ - ...ReactTableDefaults.column, - Cell: this.renderCell - }} - getTrProps={this.getTrProps} - /> -
-
- -
-
- this._parentScaling = nativeWidth > 0 ? r.entry.width / nativeWidth : 1)}> - {({ measureRef }) =>
{content}
} -
+
+
+ {content}
) -- cgit v1.2.3-70-g09d2 From 9b23c5123abf42c3751938d831556cdb94ad3951 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 22 Feb 2019 13:42:25 -0500 Subject: moved common code into CollectionViewBase. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 1 + .../views/collections/CollectionDockingView.tsx | 3 +- .../views/collections/CollectionFreeFormView.tsx | 59 ++-------------- .../views/collections/CollectionSchemaView.tsx | 13 ++-- src/client/views/collections/CollectionView.tsx | 20 +----- .../views/collections/CollectionViewBase.tsx | 82 ++++++++++++++++++++++ 7 files changed, 102 insertions(+), 78 deletions(-) create mode 100644 src/client/views/collections/CollectionViewBase.tsx (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bfa6cb7a9..156a09316 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -13,7 +13,7 @@ import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormV import { FieldId } from "../../fields/Field"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; -interface DocumentOptions { +export interface DocumentOptions { x?: number; y?: number; width?: number; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6d5fe12a7..eb4b3aeaa 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -44,6 +44,7 @@ export namespace DragManager { drop: (e: Event, de: DropEvent) => void; } + export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error("Element is already droppable, can't make it droppable again"); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 752007439..857af023d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -14,8 +14,9 @@ import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; -import { CollectionViewProps, COLLECTION_BORDER_WIDTH, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import React = require("react"); +import { SubCollectionViewProps } from "./CollectionViewBase"; @observer export class CollectionDockingView extends React.Component { diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index b78b1a3b6..b8312aff7 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -4,20 +4,18 @@ import { action, computed, trace } from "mobx"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DragManager } from "../../util/DragManager"; import "./CollectionFreeFormView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { KeyStore } from "../../../fields/KeyStore"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; -import { NumberField } from "../../../fields/NumberField"; -import { Documents } from "../../documents/Documents"; import { FieldWaiting } from "../../../fields/Field"; import { Transform } from "../../util/Transform"; import { DocumentView } from "../nodes/DocumentView"; import { undoBatch } from "../../util/UndoManager"; -import { jSXElement } from "babel-types"; +import { CollectionViewBase, SubCollectionViewProps } from "./CollectionViewBase"; @observer -export class CollectionFreeFormView extends React.Component { +export class CollectionFreeFormView extends CollectionViewBase { private _canvasRef = React.createRef(); private _lastX: number = 0; private _lastY: number = 0; @@ -45,13 +43,8 @@ export class CollectionFreeFormView extends React.Component { + super.drop(e, de); const doc: DocumentView = de.data["document"]; - if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { - if (doc.props.RemoveDocument) { - doc.props.RemoveDocument(doc.props.Document); - } - this.props.addDocument(doc.props.Document); - } const xOffset = de.data["xOffset"] as number || 0; const yOffset = de.data["yOffset"] as number || 0; //this should be able to use translate and scale methods on an Identity transform, no? @@ -62,21 +55,6 @@ export class CollectionFreeFormView extends React.Component { - if (this.dropDisposer) { - this.dropDisposer(); - } - if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { - handlers: { - drop: this.drop - } - }); - } } @action @@ -148,36 +126,11 @@ export class CollectionFreeFormView extends React.Component { - e.stopPropagation() - e.preventDefault() - let fReader = new FileReader() - let file = e.dataTransfer.items[0].getAsFile(); - let that = this; const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0); let x = e.pageX - panx let y = e.pageY - pany - - fReader.addEventListener("load", action("drop", () => { - if (fReader.result) { - let url = "" + fReader.result; - let doc = Documents.ImageDocument(url, { - x: x, y: y - }) - let docs = that.props.Document.GetT(KeyStore.Data, ListField); - if (docs != FieldWaiting) { - if (!docs) { - docs = new ListField(); - that.props.Document.Set(KeyStore.Data, docs) - } - docs.Data.push(doc); - } - } - }), false) - - if (file) { - fReader.readAsDataURL(file) - } + super.onDrop(e, { x: x, y: y }); } onDragOver = (): void => { @@ -249,7 +202,7 @@ export class CollectionFreeFormView extends React.Component e.preventDefault()} - onDrop={this.onDrop} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }} ref={this.createDropTarget}> diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f25e721c0..df732308a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -5,7 +5,7 @@ import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; -import { Field } from "../../../fields/Field"; +import { Field, FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { CompileScript, ToField } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; @@ -13,10 +13,11 @@ import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; -import { COLLECTION_BORDER_WIDTH, CollectionViewProps, SubCollectionViewProps } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { CollectionViewBase } from "./CollectionViewBase"; @observer -export class CollectionSchemaView extends React.Component { +export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); private DIVIDER_WIDTH = 5; @@ -117,6 +118,7 @@ export class CollectionSchemaView extends React.Component { return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._parentScaling); } @@ -181,7 +183,10 @@ export class CollectionSchemaView extends React.Component
-
+
this.onDrop(e, {})} + ref={this.createDropTarget} + style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> {content}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 651d85879..ff1803ec3 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,36 +1,18 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Key } from "../../../fields/Key"; import { ListField } from "../../../fields/ListField"; import { SelectionManager } from "../../util/SelectionManager"; import { ContextMenu } from "../ContextMenu"; import React = require("react"); -import { Transform } from "../../util/Transform"; import { KeyStore } from "../../../fields/KeyStore"; import { NumberField } from "../../../fields/NumberField"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; -import { Opt } from "../../../fields/Field"; +import { CollectionViewProps } from "./CollectionViewBase"; -export interface CollectionViewProps { - fieldKey: Key; - Document: Document; - ScreenToLocalTransform: () => Transform; - isSelected: () => boolean; - isTopMost: boolean; - select: (ctrlPressed: boolean) => void; - BackgroundView?: () => JSX.Element; -} - -export interface SubCollectionViewProps extends CollectionViewProps { - active: () => boolean; - addDocument: (doc: Document) => void; - removeDocument: (doc: Document) => boolean; - CollectionView: Opt; -} export enum CollectionViewType { Invalid, diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx new file mode 100644 index 000000000..06de56383 --- /dev/null +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -0,0 +1,82 @@ +import { action, computed } from "mobx"; +import { Document } from "../../../fields/Document"; +import { ListField } from "../../../fields/ListField"; +import React = require("react"); +import { KeyStore } from "../../../fields/KeyStore"; +import { Opt, FieldWaiting } from "../../../fields/Field"; +import { undoBatch } from "../../util/UndoManager"; +import { DragManager } from "../../util/DragManager"; +import { DocumentView } from "../nodes/DocumentView"; +import { Documents, DocumentOptions } from "../../documents/Documents"; +import { Key } from "../../../fields/Key"; +import { Transform } from "../../util/Transform"; + + +export interface CollectionViewProps { + fieldKey: Key; + Document: Document; + ScreenToLocalTransform: () => Transform; + isSelected: () => boolean; + isTopMost: boolean; + select: (ctrlPressed: boolean) => void; + BackgroundView?: () => JSX.Element; +} +export interface SubCollectionViewProps extends CollectionViewProps { + active: () => boolean; + addDocument: (doc: Document) => void; + removeDocument: (doc: Document) => boolean; + CollectionView: any; +} + +export class CollectionViewBase extends React.Component { + private dropDisposer?: DragManager.DragDropDisposer; + protected createDropTarget = (ele: HTMLDivElement) => { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } + } + + @undoBatch + @action + protected drop(e: Event, de: DragManager.DropEvent) { + const doc: DocumentView = de.data["document"]; + if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { + if (doc.props.RemoveDocument) { + doc.props.RemoveDocument(doc.props.Document); + } + this.props.addDocument(doc.props.Document); + } + e.stopPropagation(); + } + + @action + protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + e.stopPropagation() + e.preventDefault() + let fReader = new FileReader() + let file = e.dataTransfer.items[0].getAsFile(); + let that = this; + + fReader.addEventListener("load", action("drop", () => { + if (fReader.result) { + let url = "" + fReader.result; + let doc = Documents.ImageDocument(url, options) + let docs = that.props.Document.GetT(KeyStore.Data, ListField); + if (docs != FieldWaiting) { + if (!docs) { + docs = new ListField(); + that.props.Document.Set(KeyStore.Data, docs) + } + docs.Data.push(doc); + } + } + }), false) + + if (file) { + fReader.readAsDataURL(file) + } + } +} -- cgit v1.2.3-70-g09d2 From 39215d8999413a5e27d222c6650fc9e84c7a9ae9 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 25 Feb 2019 16:08:36 -0500 Subject: added drag/drop out of schema view --- src/client/util/DragManager.ts | 20 ++-- .../views/collections/CollectionFreeFormView.tsx | 23 ++--- .../views/collections/CollectionSchemaView.tsx | 114 ++++++++++++++++----- src/client/views/collections/CollectionView.tsx | 8 +- .../views/collections/CollectionViewBase.tsx | 14 ++- src/client/views/nodes/DocumentView.tsx | 2 +- 6 files changed, 127 insertions(+), 54 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index eb4b3aeaa..fd026992b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -61,7 +61,7 @@ export namespace DragManager { }; } - export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options: DragOptions) { + export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions) { DocumentDecorations.Instance.Hidden = true; if (!dragDiv) { dragDiv = document.createElement("div"); @@ -87,10 +87,12 @@ export namespace DragManager { dragDiv.appendChild(dragElement); let hideSource = false; - if (typeof options.hideSource === "boolean") { - hideSource = options.hideSource; - } else { - hideSource = options.hideSource(); + if (options) { + if (typeof options.hideSource === "boolean") { + hideSource = options.hideSource; + } else { + hideSource = options.hideSource(); + } } const wasHidden = ele.hidden; if (hideSource) { @@ -107,7 +109,7 @@ export namespace DragManager { const upHandler = (e: PointerEvent) => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); - FinishDrag(dragElement, e, options, dragData); + FinishDrag(dragElement, e, dragData, options); if (hideSource && !wasHidden) { ele.hidden = false; } @@ -116,7 +118,7 @@ export namespace DragManager { document.addEventListener("pointerup", upHandler); } - function FinishDrag(dragEle: HTMLElement, e: PointerEvent, options: DragOptions, dragData: { [index: string]: any }) { + function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) { dragDiv.removeChild(dragEle); const target = document.elementFromPoint(e.x, e.y); if (!target) { @@ -130,7 +132,9 @@ export namespace DragManager { data: dragData } })); - options.handlers.dragComplete({}); + if (options) { + options.handlers.dragComplete({}); + } DocumentDecorations.Instance.Hidden = false; } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 90eb8a44e..b54d9e0cf 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -44,16 +44,13 @@ export class CollectionFreeFormView extends CollectionViewBase { @action drop = (e: Event, de: DragManager.DropEvent) => { super.drop(e, de); - const doc: DocumentView = de.data["document"]; - const xOffset = de.data["xOffset"] as number || 0; - const yOffset = de.data["yOffset"] as number || 0; - //this should be able to use translate and scale methods on an Identity transform, no? - const transform = this.getTransform(); - const screenX = de.x - xOffset; - const screenY = de.y - yOffset; - const [x, y] = transform.transformPoint(screenX, screenY); - doc.props.Document.SetNumber(KeyStore.X, x); - doc.props.Document.SetNumber(KeyStore.Y, y); + const docView: DocumentView = de.data["documentView"]; + let doc: Document = docView ? docView.props.Document : de.data["document"]; + let screenX = de.x - (de.data["xOffset"] as number || 0); + let screenY = de.y - (de.data["yOffset"] as number || 0); + const [x, y] = this.getTransform().transformPoint(screenX, screenY); + doc.SetNumber(KeyStore.X, x); + doc.SetNumber(KeyStore.Y, y); this.bringToFront(doc); } @@ -148,15 +145,15 @@ export class CollectionFreeFormView extends CollectionViewBase { } @action - bringToFront(doc: DocumentView) { + bringToFront(doc: Document) { const { fieldKey: fieldKey, Document: Document } = this.props; const value: Document[] = Document.GetList(fieldKey, []).slice(); value.sort((doc1, doc2) => { - if (doc1 === doc.props.Document) { + if (doc1 === doc) { return 1; } - if (doc2 === doc.props.Document) { + if (doc2 === doc) { return -1; } return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index dc952ef82..d5b82cbb6 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -15,6 +15,8 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; +import { DragManager } from "../../util/DragManager"; +import { CollectionDockingView } from "./CollectionDockingView"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 @@ -30,6 +32,9 @@ export class CollectionSchemaView extends CollectionViewBase { @observable _selectedIndex = 0; @observable _splitPercentage: number = 50; + + + renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { doc: rowProps.value[0], @@ -42,31 +47,55 @@ export class CollectionSchemaView extends CollectionViewBase { let contents = ( ) + let reference = React.createRef(); + let onRowMove = action((e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + DragManager.StartDrag(reference.current!, { document: props.doc }); + }); + let onRowUp = action((e: PointerEvent): void => { + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + }); + let onRowDown = (e: React.PointerEvent) => { + if (e.shiftKey) { + CollectionDockingView.Instance.StartOtherDrag(reference.current!, props.doc); + e.stopPropagation(); + } else { + document.addEventListener("pointermove", onRowMove); + document.addEventListener('pointerup', onRowUp); + } + } return ( - { - let field = props.doc.Get(props.fieldKey); - if (field && field instanceof Field) { - return field.ToScriptString(); - } - return field || ""; - }} SetValue={(value: string) => { - let script = CompileScript(value); - if (!script.compiled) { - return false; - } - let field = script(); - if (field instanceof Field) { - props.doc.Set(props.fieldKey, field); - return true; - } else { - let dataField = ToField(field); - if (dataField) { - props.doc.Set(props.fieldKey, dataField); - return true; - } - } - return false; - }}> +
+ { + let field = props.doc.Get(props.fieldKey); + if (field && field instanceof Field) { + return field.ToScriptString(); + } + return field || ""; + }} SetValue={(value: string) => { + let script = CompileScript(value); + if (!script.compiled) { + return false; + } + let field = script(); + if (field instanceof Field) { + props.doc.Set(props.fieldKey, field); + return true; + } else { + let dataField = ToField(field); + if (dataField) { + props.doc.Set(props.fieldKey, dataField); + return true; + } + } + return false; + }}>
) } @@ -91,21 +120,49 @@ export class CollectionSchemaView extends CollectionViewBase { }; } + _startSplitPercent = 0; @action onDividerMove = (e: PointerEvent): void => { let nativeWidth = this._mainCont.current!.getBoundingClientRect(); this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100); } + @action onDividerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onDividerMove); document.removeEventListener('pointerup', this.onDividerUp); + if (this._startSplitPercent == this._splitPercentage) { + this._splitPercentage = this._splitPercentage == 1 ? 66 : 100; + } } onDividerDown = (e: React.PointerEvent) => { + this._startSplitPercent = this._splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onDividerMove); document.addEventListener('pointerup', this.onDividerUp); } + @action + onExpanderMove = (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + } + @action + onExpanderUp = (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + document.removeEventListener("pointermove", this.onExpanderMove); + document.removeEventListener('pointerup', this.onExpanderUp); + if (this._startSplitPercent == this._splitPercentage) { + this._splitPercentage = this._splitPercentage == 100 ? 66 : 100; + } + } + onExpanderDown = (e: React.PointerEvent) => { + this._startSplitPercent = this._splitPercentage; + e.stopPropagation(); + e.preventDefault(); + document.addEventListener("pointermove", this.onExpanderMove); + document.addEventListener('pointerup', this.onExpanderUp); + } onPointerDown = (e: React.PointerEvent) => { // if (e.button === 2 && this.active) { @@ -113,8 +170,10 @@ export class CollectionSchemaView extends CollectionViewBase { // e.preventDefault(); // } else { - if (e.buttons === 1 && this.props.active()) { - e.stopPropagation(); + if (e.buttons === 1) { + if (this.props.isSelected()) { + e.stopPropagation(); + } } } } @@ -155,6 +214,8 @@ export class CollectionSchemaView extends CollectionViewBase { } ) + let handle = !this.props.active() ? (null) : ( +
); return (
{ @@ -190,6 +251,7 @@ export class CollectionSchemaView extends CollectionViewBase { style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> {content}
+ {handle}
) } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6d30cf365..83886f933 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -53,7 +53,13 @@ export class CollectionView extends React.Component { removeDocument = (doc: Document): boolean => { //TODO This won't create the field if it doesn't already exist const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array()) - let index = value.indexOf(doc); + let index = -1; + for (let i = 0; i < value.length; i++) { + if (value[i].Id == doc.Id) { + index = i; + break; + } + } if (index !== -1) { value.splice(index, 1) diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index e53485183..217536e2b 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -44,12 +44,16 @@ export class CollectionViewBase extends React.Component @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent) { - const doc: DocumentView = de.data["document"]; - if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this.props.CollectionView) { - if (doc.props.RemoveDocument) { - doc.props.RemoveDocument(doc.props.Document); + const docView: DocumentView = de.data["documentView"]; + const doc: Document = de.data["document"]; + if (docView && docView.props.ContainingCollectionView && docView.props.ContainingCollectionView !== this.props.CollectionView) { + if (docView.props.RemoveDocument) { + docView.props.RemoveDocument(docView.props.Document); } - this.props.addDocument(doc.props.Document); + this.props.addDocument(docView.props.Document); + } else if (doc) { + this.props.removeDocument(doc); + this.props.addDocument(doc); } e.stopPropagation(); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 212697442..6fe78daee 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -124,7 +124,7 @@ export class DocumentView extends React.Component { this._contextMenuCanOpen = false; const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); let dragData: { [id: string]: any } = {}; - dragData["document"] = this; + dragData["documentView"] = this; dragData["xOffset"] = e.x - left; dragData["yOffset"] = e.y - top; DragManager.StartDrag(this._mainCont.current, dragData, { -- cgit v1.2.3-70-g09d2 From bb418216efa9cc2e191b970e4cbe5080f4fd2b87 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 25 Feb 2019 17:00:31 -0500 Subject: drag and drop of main buttons. --- src/client/util/DragManager.ts | 2 + src/client/views/Main.tsx | 116 +++++++++------------ .../views/collections/CollectionDockingView.tsx | 8 +- .../views/collections/CollectionSchemaView.scss | 1 + 4 files changed, 58 insertions(+), 69 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index fd026992b..aab23f91c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -75,6 +75,8 @@ export namespace DragManager { let dragElement = ele.cloneNode(true) as HTMLElement; dragElement.style.opacity = "0.7"; dragElement.style.position = "absolute"; + dragElement.style.bottom = ""; + dragElement.style.left = ""; dragElement.style.transformOrigin = "0 0"; dragElement.style.zIndex = "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 661a2ac20..61ad66c72 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -17,6 +17,7 @@ import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { FieldWaiting } from '../../fields/Field'; import { UndoManager } from '../util/UndoManager'; +import { DragManager } from '../util/DragManager'; configure({ @@ -77,31 +78,47 @@ Documents.initProtos(() => { }, 0); } - let addImageNode = action(() => { - mainfreeform.GetList(KeyStore.Data, []).push(Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { - x: 0, y: 300, width: 200, height: 200, title: "added note" - })); - }) - let addTextNode = action(() => { - mainfreeform.GetList(KeyStore.Data, []).push(Documents.TextDocument({ - x: 0, y: 300, width: 200, height: 200, title: "added note" - })); - }) - let addColNode = action(() => { - mainfreeform.GetList(KeyStore.Data, []).push(Documents.FreeformDocument([], { - x: 0, y: 300, width: 200, height: 200, title: "added note" - })); - }) - let addSchemaNode = action(() => { - mainfreeform.GetList(KeyStore.Data, []).push(Documents.SchemaDocument([Documents.TextDocument()], { - x: 0, y: 300, width: 200, height: 200, title: "added note" - })); - }) + let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {})) + let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) + let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a feeform collection" })); + let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" })); + let addImageNode = action(() => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { + width: 200, height: 200, title: "an image of a cat" + })); - let clearDatabase = action(() => { - Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}); - }) + let addClick = (creator: any) => action(() => { + var img = creator(); + img.SetNumber(KeyStore.X, 0); + img.SetNumber(KeyStore.Y, 0); + mainfreeform.GetList(KeyStore.Data, []).push(img); + }); + let imgRef = React.createRef(); + let textRef = React.createRef(); + let schemaRef = React.createRef(); + let colRef = React.createRef(); + let curMoveListener: any = null + let onRowMove = (creator: any, dragRef: any) => action((e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", curMoveListener); + document.removeEventListener('pointerup', onRowUp); + DragManager.StartDrag(dragRef.current!, { document: creator() }); + }); + let onRowUp = action((e: PointerEvent): void => { + document.removeEventListener("pointermove", curMoveListener); + document.removeEventListener('pointerup', onRowUp); + }); + let onRowDown = (creator: any, dragRef: any) => (e: React.PointerEvent) => { + if (e.shiftKey) { + CollectionDockingView.Instance.StartOtherDrag(dragRef.current!, creator()); + e.stopPropagation(); + } else { + document.addEventListener("pointermove", curMoveListener = onRowMove(creator, dragRef)); + document.addEventListener('pointerup', onRowUp); + } + } ReactDOM.render((
{ ContainingCollectionView={undefined} /> - - - - - - - +
+
+
+
+
+
+
+
+ + +
), document.getElementById('root')); }) diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index a0f457ef2..8926f4aca 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -36,8 +36,8 @@ export class CollectionDockingView extends React.Component(); private _fullScreen: any = null; @@ -48,7 +48,7 @@ export class CollectionDockingView extends React.Component Date: Tue, 26 Feb 2019 12:32:52 -0500 Subject: extended CollectionTreeView to support drag and drop. updated CollectionSchemaView's drag drop --- src/client/util/DragManager.ts | 33 ++++++ .../views/collections/CollectionSchemaView.scss | 27 +++++ .../views/collections/CollectionSchemaView.tsx | 111 ++++++++------------- .../views/collections/CollectionTreeView.scss | 6 ++ .../views/collections/CollectionTreeView.tsx | 78 ++++++--------- src/client/views/nodes/DocumentView.tsx | 30 +++--- src/client/views/nodes/FieldView.tsx | 11 +- 7 files changed, 160 insertions(+), 136 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index aab23f91c..8adadee0f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,4 +1,37 @@ import { DocumentDecorations } from "../views/DocumentDecorations"; +import { CollectionDockingView } from "../views/collections/CollectionDockingView"; +import { Document } from "../../fields/Document" +import { action } from "mobx"; + +export function setupDrag(_reference: React.RefObject, _dragDocument: Document) { + let onRowMove = action((e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + DragManager.StartDrag(_reference.current!, { document: _dragDocument }); + }); + let onRowUp = action((e: PointerEvent): void => { + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener('pointerup', onRowUp); + }); + let onItemDown = (e: React.PointerEvent) => { + // if (this.props.isSelected() || this.props.isTopMost) { + if (e.button == 0) { + e.stopPropagation(); + e.preventDefault(); + if (e.shiftKey) { + CollectionDockingView.Instance.StartOtherDrag(_reference.current!, _dragDocument); + } else { + document.addEventListener("pointermove", onRowMove); + document.addEventListener('pointerup', onRowUp); + } + } + //} + } + return onItemDown; +} export namespace DragManager { export function Root() { diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index f86094a98..995d60f74 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -1,4 +1,5 @@ + .collectionSchemaView-container { border-style: solid; box-sizing: border-box; @@ -14,6 +15,32 @@ border-radius: 2px; background-color: rgba(0,0,0,.5); } + .collectionSchemaView-previewRegion { + position: relative; + background: black; + float: left; + height: 100%; + } + .collectionSchemaView-previewHandle { + position: absolute; + height: 37px; + width: 20px; + z-index: 20; + right: 0; + top: 0; + background: Black ; + } + .collectionSchemaView-dividerDragger{ + position: relative; + background: black; + float: left; + height: 100%; + } + .collectionSchemaView-tableContainer { + position: relative; + float: left; + height: 100%; + } .ReactTable { position: absolute; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 79c688f6b..106a5c4f5 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -15,11 +15,11 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; -import { DragManager } from "../../util/DragManager"; -import { CollectionDockingView } from "./CollectionDockingView"; +import { setupDrag } from "../../util/DragManager"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 + @observer export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); @@ -32,9 +32,6 @@ export class CollectionSchemaView extends CollectionViewBase { @observable _selectedIndex = 0; @observable _splitPercentage: number = 50; - - - renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { doc: rowProps.value[0], @@ -48,31 +45,9 @@ export class CollectionSchemaView extends CollectionViewBase { ) let reference = React.createRef(); - let onRowMove = action((e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener('pointerup', onRowUp); - DragManager.StartDrag(reference.current!, { document: props.doc }); - }); - let onRowUp = action((e: PointerEvent): void => { - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener('pointerup', onRowUp); - }); - let onRowDown = (e: React.PointerEvent) => { - if (this.props.isSelected() || this.props.isTopMost) { - if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag(reference.current!, props.doc); - e.stopPropagation(); - } else { - document.addEventListener("pointermove", onRowMove); - document.addEventListener('pointerup', onRowUp); - } - } - } + let onItemDown = setupDrag(reference, props.doc); return ( -
+
{ let field = props.doc.Get(props.fieldKey); @@ -80,7 +55,8 @@ export class CollectionSchemaView extends CollectionViewBase { return field.ToScriptString(); } return field || ""; - }} SetValue={(value: string) => { + }} + SetValue={(value: string) => { let script = CompileScript(value); if (!script.compiled) { return false; @@ -97,7 +73,9 @@ export class CollectionSchemaView extends CollectionViewBase { } } return false; - }}>
+ }}> + +
) } @@ -216,44 +194,43 @@ export class CollectionSchemaView extends CollectionViewBase { } ) - let handle = !this.props.active() ? (null) : ( -
); + let previewHandle = !this.props.active() ? (null) : ( +
); return ( -
- { - this._dividerX = r.entry.width; - this._panelHeight = r.entry.height; - })}> - {({ measureRef }) => -
- ({ - Header: col.Name, - accessor: (doc: Document) => [doc, col], - id: col.Id - }))} - column={{ - ...ReactTableDefaults.column, - Cell: this.renderCell, - - }} - getTrProps={this.getTrProps} - /> -
- } -
-
-
this.onDrop(e, {})} - ref={this.createDropTarget} - style={{ position: "relative", float: "left", width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)`, height: "100%" }}> - {content} +
+
this.onDrop(e, {})} ref={this.createDropTarget}> + { + this._dividerX = r.entry.width; + this._panelHeight = r.entry.height; + })}> + {({ measureRef }) => +
+ ({ + Header: col.Name, + accessor: (doc: Document) => [doc, col], + id: col.Id + }))} + column={{ + ...ReactTableDefaults.column, + Cell: this.renderCell, + + }} + getTrProps={this.getTrProps} + /> +
+ } +
+
+
+ {content} +
+ {previewHandle}
- {handle}
) } diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 675fc6c53..c488e2894 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -25,4 +25,10 @@ li:before { .uncollapsed:before { content: '\25bc'; margin-right: 0.5em; +} + +.collectionTreeView-dropTarget { + border-style: solid; + box-sizing: border-box; + height:100%; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 52e853bf7..64f4c0970 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -7,6 +7,9 @@ import React = require("react") import { TextField } from "../../../fields/TextField"; import { observable, action } from "mobx"; import "./CollectionTreeView.scss"; +import { setupDrag } from "../../util/DragManager"; +import { FieldWaiting } from "../../../fields/Field"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; export interface TreeViewProps { document: Document; @@ -23,60 +26,39 @@ class TreeView extends React.Component { /** * Renders a single child document. If this child is a collection, it will call renderTreeView again. Otherwise, it will just append a list element. - * @param document The document to render. + * @param childDocument The document to render. */ - renderChild(document: Document) { - var children = document.GetT>(KeyStore.Data, ListField); - let title = document.GetT(KeyStore.Title, TextField); + renderChild(childDocument: Document) { + let reference = React.createRef(); - // if the title hasn't loaded, immediately return the div - if (!title || title === "") { - return
; - } - - // otherwise, check if it's a collection. - else if (children && children !== "") { - // if it's not collapsed, then render the full TreeView. - if (!this.collapsed) { - return ( -
  • this.collapsed = true)} > - {title.Data} -
      - -
    -
  • - ); - } else { - return
  • this.collapsed = false)}>{title.Data}
  • - } - } + var children = childDocument.GetT>(KeyStore.Data, ListField); + let title = childDocument.GetT(KeyStore.Title, TextField); + let onItemDown = setupDrag(reference, childDocument); - // finally, if it's a normal document, then render it as such. - else { - return
  • {title.Data}
  • ; + if (title && title != FieldWaiting) { + let subView = !children || this.collapsed || children === FieldWaiting ? (null) : +
      + +
    ; + return
    +
  • this.collapsed = !this.collapsed)} > + {title.Data} + {subView} +
  • +
    } + return (null); } render() { var children = this.props.document.GetT>(KeyStore.Data, ListField); - - if (children && children !== "") { - return (
    - {children.Data.map(value => this.renderChild(value))} -
    ) - // let results: JSX.Element[] = []; - - // // append a list item for each child in the collection - // children.Data.forEach((value) => { - // results.push(this.renderChild(value)); - // }) - - // return results; - } else { - return
    ; - } + return !children || children === FieldWaiting ? (null) : + (children.Data.map(value => +
    + {this.renderChild(value)} +
    ) + ) } } @@ -87,11 +69,11 @@ export class CollectionTreeView extends CollectionViewBase { render() { let titleStr = ""; let title = this.props.Document.GetT(KeyStore.Title, TextField); - if (title && title !== "") { + if (title && title !== FieldWaiting) { titleStr = title.Data; } return ( -
    +
    this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >

    {titleStr}

      { return; } - if (this.topMost) { - ContextMenu.Instance.clearItems() - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } - else { + ContextMenu.Instance.clearItems() + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) + ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) + ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) + ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) + //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + if (!this.topMost) { // DocumentViews should stop propagation of this event e.stopPropagation(); - - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) - ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) - ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) - ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) - ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - SelectionManager.SelectDoc(this, e.ctrlKey); } + + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + SelectionManager.SelectDoc(this, e.ctrlKey); } @computed get mainContent() { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 1a9d325db..b71309bf5 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -52,11 +52,14 @@ export class FieldView extends React.Component { } else if (field instanceof NumberField) { return

      {field.Data}

      - } else if (field instanceof HtmlField) { + } + else if (field instanceof HtmlField) { return - } else if (field != FieldWaiting) { - return

      {field.GetValue}

      - } else + } + else if (field != FieldWaiting) { + return

      {JSON.stringify(field.GetValue())}

      + } + else return

      {"Waiting for server..."}

      } -- cgit v1.2.3-70-g09d2 From bd54526065428de2e931d7254776352199f6e55a Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 26 Feb 2019 16:56:04 -0500 Subject: fixed shift-dragging!! --- src/client/util/DragManager.ts | 8 ++-- src/client/views/Main.tsx | 33 +++-------------- .../views/collections/CollectionDockingView.tsx | 43 ++++------------------ .../views/collections/CollectionSchemaView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- 6 files changed, 21 insertions(+), 71 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 8adadee0f..0d76d2640 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -3,14 +3,14 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { Document } from "../../fields/Document" import { action } from "mobx"; -export function setupDrag(_reference: React.RefObject, _dragDocument: Document) { +export function setupDrag(_reference: React.RefObject, docFunc: () => Document) { let onRowMove = action((e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - DragManager.StartDrag(_reference.current!, { document: _dragDocument }); + DragManager.StartDrag(_reference.current!, { document: docFunc() }); }); let onRowUp = action((e: PointerEvent): void => { document.removeEventListener("pointermove", onRowMove); @@ -20,10 +20,10 @@ export function setupDrag(_reference: React.RefObject, _dragDocu // if (this.props.isSelected() || this.props.isTopMost) { if (e.button == 0) { e.stopPropagation(); - e.preventDefault(); if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag(_reference.current!, _dragDocument); + CollectionDockingView.Instance.StartOtherDrag(docFunc(), e); } else { + e.preventDefault(); document.addEventListener("pointermove", onRowMove); document.addEventListener('pointerup', onRowUp); } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 17dda899d..7ef4b6132 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -15,9 +15,8 @@ import { ServerUtils } from '../../server/ServerUtil'; import { MessageStore, DocumentTransfer } from '../../server/Message'; import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; -import { FieldWaiting } from '../../fields/Field'; import { UndoManager } from '../util/UndoManager'; -import { DragManager } from '../util/DragManager'; +import { setupDrag } from '../util/DragManager'; configure({ @@ -30,7 +29,6 @@ window.addEventListener("dragover", function (e) { e.preventDefault(); }, false) document.addEventListener("pointerdown", action(function (e: PointerEvent) { - console.log(ContextMenu); if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) { ContextMenu.Instance.clearItems() } @@ -98,28 +96,7 @@ Documents.initProtos(() => { let textRef = React.createRef(); let schemaRef = React.createRef(); let colRef = React.createRef(); - let curMoveListener: any = null - let onRowMove = (creator: any, dragRef: any) => action((e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - document.removeEventListener("pointermove", curMoveListener); - document.removeEventListener('pointerup', onRowUp); - DragManager.StartDrag(dragRef.current!, { document: creator() }); - }); - let onRowUp = action((e: PointerEvent): void => { - document.removeEventListener("pointermove", curMoveListener); - document.removeEventListener('pointerup', onRowUp); - }); - let onRowDown = (creator: any, dragRef: any) => (e: React.PointerEvent) => { - if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag(dragRef.current!, creator()); - e.stopPropagation(); - } else { - document.addEventListener("pointermove", curMoveListener = onRowMove(creator, dragRef)); - document.addEventListener('pointerup', onRowUp); - } - } ReactDOM.render((
      {
      -
      +
      -
      +
    -
    +
    -
    +
    diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 5fb632469..3d7e46a01 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -10,7 +10,6 @@ import { FieldId, Opt, Field } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { Utils } from "../../../Utils"; import { Server } from "../../Server"; -import { DragManager } from "../../util/DragManager"; import { undoBatch } from "../../util/UndoManager"; import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; @@ -34,10 +33,6 @@ export class CollectionDockingView extends React.Component(); private _fullScreen: any = null; @@ -47,28 +42,8 @@ export class CollectionDockingView extends React.Component { }, button: e.button }) } @action @@ -98,7 +73,7 @@ export class CollectionDockingView extends React.Component { - if (this._dragDiv) { - this._dragDiv.removeChild(this._dragElement); - this._dragParent!.removeChild(this._dragFakeElement!); - this._dragParent!.appendChild(this._dragElement!); - DragManager.Root().removeChild(this._dragDiv); - this._dragDiv = null; - } tab.closeElement.off('click') //unbind the current click handler .click(function () { tab.contentItem.remove(); diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 106a5c4f5..03110a9c7 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -45,9 +45,9 @@ export class CollectionSchemaView extends CollectionViewBase { ) let reference = React.createRef(); - let onItemDown = setupDrag(reference, props.doc); + let onItemDown = setupDrag(reference, () => props.doc); return ( -
    +
    { let field = props.doc.Get(props.fieldKey); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 64f4c0970..55c804337 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -33,7 +33,7 @@ class TreeView extends React.Component { var children = childDocument.GetT>(KeyStore.Data, ListField); let title = childDocument.GetT(KeyStore.Title, TextField); - let onItemDown = setupDrag(reference, childDocument); + let onItemDown = setupDrag(reference, () => childDocument); if (title && title != FieldWaiting) { let subView = !children || this.collapsed || children === FieldWaiting ? (null) : diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c579b7142..feecde921 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -96,7 +96,7 @@ export class DocumentView extends React.Component { this._downX = e.clientX; this._downY = e.clientY; if (e.shiftKey && e.buttons === 1) { - CollectionDockingView.Instance.StartOtherDrag(this._mainCont.current!, this.props.Document); + CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e); e.stopPropagation(); } else { this._contextMenuCanOpen = true; -- cgit v1.2.3-70-g09d2 From 04ee2ad6e7ca887c3cfc7277c4b382f936c0fa6d Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 26 Feb 2019 17:32:07 -0500 Subject: can switch into drag-as-dockingframe using shift after drag starts. changed scrollbars globally . --- src/client/util/DragManager.ts | 18 ++++++++++++++---- src/client/views/Main.scss | 11 ++++++++++- .../views/collections/CollectionFreeFormView.scss | 10 ---------- src/client/views/collections/CollectionSchemaView.scss | 9 --------- 4 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0d76d2640..6b4b8ca57 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -2,6 +2,7 @@ import { DocumentDecorations } from "../views/DocumentDecorations"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { Document } from "../../fields/Document" import { action } from "mobx"; +import { DocumentView } from "../views/nodes/DocumentView"; export function setupDrag(_reference: React.RefObject, docFunc: () => Document) { let onRowMove = action((e: PointerEvent): void => { @@ -23,7 +24,6 @@ export function setupDrag(_reference: React.RefObject, docFunc: if (e.shiftKey) { CollectionDockingView.Instance.StartOtherDrag(docFunc(), e); } else { - e.preventDefault(); document.addEventListener("pointermove", onRowMove); document.addEventListener('pointerup', onRowUp); } @@ -139,22 +139,32 @@ export namespace DragManager { e.preventDefault(); x += e.movementX; y += e.movementY; + if (e.shiftKey) { + abortDrag(); + const docView: DocumentView = dragData["documentView"]; + const doc: Document = docView ? docView.props.Document : dragData["document"]; + CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }); + } dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; }; - const upHandler = (e: PointerEvent) => { + + const abortDrag = () => { document.removeEventListener("pointermove", moveHandler, true); document.removeEventListener("pointerup", upHandler); - FinishDrag(dragElement, e, dragData, options); + dragDiv.removeChild(dragElement); if (hideSource && !wasHidden) { ele.hidden = false; } + } + const upHandler = (e: PointerEvent) => { + abortDrag(); + FinishDrag(dragElement, e, dragData, options); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) { - dragDiv.removeChild(dragEle); const target = document.elementFromPoint(e.x, e.y); if (!target) { return; diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index e73f62904..6540af5b2 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -28,4 +28,13 @@ h1 { p { margin: 0px; padding: 0px; -} \ No newline at end of file +} +::-webkit-scrollbar { + -webkit-appearance: none; + height:5px; + width:5px; +} +::-webkit-scrollbar-thumb { + border-radius: 2px; + background-color: rgba(0,0,0,.5); +} diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index 737f28318..e86295c26 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -1,15 +1,5 @@ .collectionfreeformview-container { - ::-webkit-scrollbar { - -webkit-appearance: none; - height:5px; - width:5px; - } - ::-webkit-scrollbar-thumb { - border-radius: 2px; - background-color: rgba(0,0,0,.5); - } - .collectionfreeformview > .jsx-parser{ position:absolute; height: 100%; diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 995d60f74..d40e6d314 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -6,15 +6,6 @@ position: absolute; width: 100%; height: 100%; - ::-webkit-scrollbar { - -webkit-appearance: none; - height:5px; - width:5px; - } - ::-webkit-scrollbar-thumb { - border-radius: 2px; - background-color: rgba(0,0,0,.5); - } .collectionSchemaView-previewRegion { position: relative; background: black; -- cgit v1.2.3-70-g09d2 From faccb013ad0265d1507e0b5c59cabb42aedbb88c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 26 Feb 2019 23:54:07 -0500 Subject: fixed some drag problems. cleaned up Documents.ts --- src/client/documents/Documents.ts | 229 ++++++++++++-------------------- src/client/util/DragManager.ts | 8 +- src/client/views/nodes/DocumentView.tsx | 2 + 3 files changed, 95 insertions(+), 144 deletions(-) (limited to 'src/client/util/DragManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e5154737e..8b733507b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -11,6 +11,8 @@ import { WebField } from "../../fields/WebField"; import { WebBox } from "../views/nodes/WebBox"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { HtmlField } from "../../fields/HtmlField"; +import { Key } from "../../fields/Key" +import { Field } from "../../fields/Field"; export interface DocumentOptions { x?: number; @@ -20,87 +22,110 @@ export interface DocumentOptions { nativeWidth?: number; nativeHeight?: number; title?: string; + panx?: number; + pany?: number; + scale?: number; + layout?: string; + layoutKeys?: Key[]; + viewType?: number; } export namespace Documents { + let textProto: Document; + let imageProto: Document; + let webProto: Document; + let collProto: Document; + const textProtoId = "textProto"; + const imageProtoId = "imageProto"; + const webProtoId = "webProto"; + const collProtoId = "collectionProto"; + export function initProtos(callback: () => void) { - Server.GetFields([collectionProtoId, textProtoId, imageProtoId], (fields) => { - collectionProto = fields[collectionProtoId] as Document; + Server.GetFields([collProtoId, textProtoId, imageProtoId], (fields) => { + collProto = fields[collProtoId] as Document; imageProto = fields[imageProtoId] as Document; textProto = fields[textProtoId] as Document; + webProto = fields[webProtoId] as Document; callback() }); } - - function setupOptions(doc: Document, options: DocumentOptions): void { - if (options.x !== undefined) { - doc.SetData(KeyStore.X, options.x, NumberField); - } - if (options.y !== undefined) { - doc.SetData(KeyStore.Y, options.y, NumberField); - } - if (options.width !== undefined) { - doc.SetData(KeyStore.Width, options.width, NumberField); - } - if (options.height !== undefined) { - doc.SetData(KeyStore.Height, options.height, NumberField); - } - if (options.nativeWidth !== undefined) { - doc.SetData(KeyStore.NativeWidth, options.nativeWidth, NumberField); - } - if (options.nativeHeight !== undefined) { - doc.SetData(KeyStore.NativeHeight, options.nativeHeight, NumberField); - } - if (options.title !== undefined) { - doc.SetData(KeyStore.Title, options.title, TextField); - } - doc.SetData(KeyStore.Scale, 1, NumberField); - doc.SetData(KeyStore.PanX, 0, NumberField); - doc.SetData(KeyStore.PanY, 0, NumberField); + function assignOptions(doc: Document, options: DocumentOptions): Document { + if (options.x !== undefined) { doc.SetNumber(KeyStore.X, options.x); } + if (options.y !== undefined) { doc.SetNumber(KeyStore.Y, options.y); } + if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); } + if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); } + if (options.nativeWidth !== undefined) { doc.SetNumber(KeyStore.NativeWidth, options.nativeWidth); } + if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); } + if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); } + if (options.panx !== undefined) { doc.SetNumber(KeyStore.PanX, options.panx); } + if (options.pany !== undefined) { doc.SetNumber(KeyStore.PanY, options.pany); } + if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); } + if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); } + if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } + if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } + return doc; } - - let textProto: Document; - const textProtoId = "textProto"; - function GetTextPrototype(): Document { - if (!textProto) { - textProto = new Document(textProtoId); - textProto.Set(KeyStore.X, new NumberField(0)); - textProto.Set(KeyStore.Y, new NumberField(0)); - textProto.Set(KeyStore.Width, new NumberField(300)); - textProto.Set(KeyStore.Height, new NumberField(150)); - textProto.Set(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString())); - textProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return textProto; + function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document { + return assignOptions(new Document(protoId), { ...options, title: title, layout: layout }); } - - export function TextDocument(options: DocumentOptions = {}): Document { - let doc = GetTextPrototype().MakeDelegate(); - setupOptions(doc, options); - // doc.Set(KeyStore.Data, new RichTextField()); - return doc; + function SetInstanceOptions(doc: Document, options: DocumentOptions, value: T, ctor: { new(): U }, id?: string) { + var deleg = doc.MakeDelegate(id); + deleg.SetData(KeyStore.Data, value, ctor); + return assignOptions(deleg, options); } - let imageProto: Document; - const imageProtoId = "imageProto"; function GetImagePrototype(): Document { if (!imageProto) { - imageProto = new Document(imageProtoId); - imageProto.Set(KeyStore.Title, new TextField("IMAGE PROTO")); - imageProto.Set(KeyStore.X, new NumberField(0)); - imageProto.Set(KeyStore.Y, new NumberField(0)); - imageProto.Set(KeyStore.NativeWidth, new NumberField(300)); - imageProto.Set(KeyStore.Width, new NumberField(300)); - imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey"))); - imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) - imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString())); - // imageProto.Set(KeyStore.Layout, new TextField('
    ')); - imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); - return imageProto; + imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"), + { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString()); } return imageProto; + } + function GetTextPrototype(): Document { + return textProto ? textProto : + textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), + { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }); + } + function GetWebPrototype(): Document { + return webProto ? webProto : + webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(), + { x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] }); + } + function GetCollectionPrototype(): Document { + return collProto ? collProto : + collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"), + { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] }); + } + export function ImageDocument(url: string, options: DocumentOptions = {}) { + let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] }, + new URL(url), ImageField); + doc.SetText(KeyStore.Caption, "my caption..."); + doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption()); + doc.SetText(KeyStore.OverlayLayout, FixedCaption()); + return doc; + } + export function TextDocument(options: DocumentOptions = {}) { + return SetInstanceOptions(GetTextPrototype(), options, "", TextField); + } + export function WebDocument(url: string, options: DocumentOptions = {}) { + return SetInstanceOptions(GetWebPrototype(), options, new URL(url), WebField); + } + export function HtmlDocument(html: string, options: DocumentOptions = {}) { + return SetInstanceOptions(GetWebPrototype(), options, html, HtmlField); + } + export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, documents, ListField, id) } + export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, documents, ListField, id) + } + export function DockDocument(config: string, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, config, TextField, id) + } + + // example of custom display string for an image that shows a caption. function EmbeddedCaption() { @@ -118,84 +143,4 @@ export namespace Documents { + FormattedTextBox.LayoutString("CaptionKey") + `
    ` }; - - export function ImageDocument(url: string, options: DocumentOptions = {}): Document { - let doc = GetImagePrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new ImageField(new URL(url))); - doc.Set(KeyStore.Caption, new TextField("my caption...")); - doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption())); - doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption())); - doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption])); - console.log("" + doc.GetNumber(KeyStore.Height, 311)); - return doc; - } - - let webProto: Document; - const webProtoId = "webProto"; - function GetWebPrototype(): Document { - if (!webProto) { - webProto = new Document(webProtoId); - webProto.Set(KeyStore.Title, new TextField("WEB PROTO")); - webProto.Set(KeyStore.X, new NumberField(0)); - webProto.Set(KeyStore.Y, new NumberField(0)); - webProto.Set(KeyStore.Width, new NumberField(300)); - webProto.Set(KeyStore.Height, new NumberField(300)); - //webProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey"))); - webProto.Set(KeyStore.Layout, new TextField(WebBox.LayoutString())); - webProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); - } - return webProto; - } - - export function WebDocument(url: string, options: DocumentOptions = {}): Document { - let doc = GetWebPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new WebField(new URL(url))); - return doc; - } - export function HtmlDocument(html: string, options: DocumentOptions = {}): Document { - let doc = GetWebPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new HtmlField(html)); - return doc; - } - - let collectionProto: Document; - const collectionProtoId = "collectionProto"; - function GetCollectionPrototype(): Document { - if (!collectionProto) { - collectionProto = new Document(collectionProtoId); - collectionProto.Set(KeyStore.Scale, new NumberField(1)); - collectionProto.Set(KeyStore.PanX, new NumberField(0)); - collectionProto.Set(KeyStore.PanY, new NumberField(0)); - collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey"))); - collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return collectionProto; - } - - export function CollectionDocument(data: Array | string, viewType: CollectionViewType, options: DocumentOptions = {}, id?: string): Document { - let doc = GetCollectionPrototype().MakeDelegate(id); - setupOptions(doc, options); - if (typeof data === "string") { - doc.SetText(KeyStore.Data, data); - } else { - doc.SetData(KeyStore.Data, data, ListField); - } - doc.SetNumber(KeyStore.ViewType, viewType); - return doc; - } - - export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { - return CollectionDocument(documents, CollectionViewType.Freeform, options, id) - } - - export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { - return CollectionDocument(documents, CollectionViewType.Schema, options, id) - } - - export function DockDocument(config: string, options: DocumentOptions, id?: string) { - return CollectionDocument(config, CollectionViewType.Docking, options, id) - } } \ No newline at end of file diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6b4b8ca57..60910a40b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -133,7 +133,6 @@ export namespace DragManager { if (hideSource) { ele.hidden = true; } - const moveHandler = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -158,14 +157,19 @@ export namespace DragManager { } const upHandler = (e: PointerEvent) => { abortDrag(); - FinishDrag(dragElement, e, dragData, options); + FinishDrag(ele, e, dragData, options); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) { + let parent = dragEle.parentElement; + if (parent) + parent.removeChild(dragEle); const target = document.elementFromPoint(e.x, e.y); + if (parent) + parent.appendChild(dragEle); if (!target) { return; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8e5a0d17e..c929f9d54 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -119,6 +119,8 @@ export class DocumentView extends React.Component { return; } if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { + document.removeEventListener("pointermove", this.onPointerMove) + document.removeEventListener("pointerup", this.onPointerUp) this._contextMenuCanOpen = false; if (this._mainCont.current != null && !this.topMost) { this._contextMenuCanOpen = false; -- cgit v1.2.3-70-g09d2