diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DocumentDecorations.tsx | 46 | ||||
-rw-r--r-- | src/views/freeformcanvas/CollectionFreeFormView.tsx | 22 | ||||
-rw-r--r-- | src/views/nodes/DocumentView.tsx | 61 |
3 files changed, 65 insertions, 64 deletions
diff --git a/src/DocumentDecorations.tsx b/src/DocumentDecorations.tsx index 28d6dc377..8145ba732 100644 --- a/src/DocumentDecorations.tsx +++ b/src/DocumentDecorations.tsx @@ -4,10 +4,15 @@ import {DocumentView} from "./views/nodes/DocumentView"; import {SelectionManager} from "./util/SelectionManager"; import {observer} from "mobx-react"; import './DocumentDecorations.scss' +import {CollectionFreeFormView} from "./views/freeformcanvas/CollectionFreeFormView"; @observer export class DocumentDecorations extends React.Component { static Instance: DocumentDecorations + private _resizer = "" + private _isPointerDown = false; + @observable private _opacity = 1; + constructor(props: Readonly<{}>) { super(props) @@ -15,31 +20,17 @@ export class DocumentDecorations extends React.Component { } @computed - get x(): number { - return SelectionManager.SelectedDocuments().reduce((left, element) => Math.min(element.TransformToScreenPoint(0, 0).ScreenX, left), Number.MAX_VALUE); - } - - @computed - get y(): number { - return SelectionManager.SelectedDocuments().reduce((top, element) => Math.min(element.TransformToScreenPoint(0, 0).ScreenY, top), Number.MAX_VALUE); - } - - @computed - get height(): number { - return (SelectionManager.SelectedDocuments().reduce((bottom, element) => Math.max(element.TransformToScreenPoint(0, element.height).ScreenY, bottom), - Number.MIN_VALUE)) - this.y; - } - - @computed - get width(): number { - return SelectionManager.SelectedDocuments().reduce((right, element) => Math.max(element.TransformToScreenPoint(element.width, 0).ScreenX, right), - Number.MIN_VALUE) - this.x; + get Bounds(): {x: number, y: number, b: number, r: number} { + return SelectionManager.SelectedDocuments().reduce((bounds, element) => { + var spt = element.TransformToScreenPoint(0, 0); + var bpt = element.TransformToScreenPoint(element.width, element.height); + return { + x: Math.min(spt.ScreenX, bounds.x), y: Math.min(spt.ScreenY, bounds.y), + r: Math.max(bpt.ScreenX, bounds.r), b: Math.max(bpt.ScreenY, bounds.b) + } + }, {x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE}); } - private _resizer = "" - private _isPointerDown = false; - @observable private _opacity = 1; - @computed get opacity(): number { return this._opacity @@ -134,12 +125,13 @@ export class DocumentDecorations extends React.Component { } render() { + var bounds = this.Bounds; return ( <div id="documentDecorations-container" style={{ - width: `${this.width + 40}px`, - height: `${this.height + 40}px`, - left: this.x - 20, - top: this.y - 20, + width: (bounds.r - bounds.x + 40) + "px", + height: (bounds.b - bounds.y + 40) + "px", + left: bounds.x - 20, + top: bounds.y - 20, opacity: this.opacity }}> <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx index 2233ffcaf..00b912294 100644 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -31,6 +31,8 @@ export class CollectionFreeFormView extends React.Component<IProps> { super(props); } + public static BORDER_WIDTH = 2; + @computed public get active(): boolean { var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView)); @@ -101,17 +103,11 @@ export class CollectionFreeFormView extends React.Component<IProps> { if (!e.cancelBubble) { e.preventDefault(); e.stopPropagation(); - const doc = this.props.Document; - let me = this; - let currScale: number = this.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); - if (me.props.ContainingDocumentView!.props.ContainingDocumentView != undefined) { - let pme = me.props.ContainingDocumentView!.props.ContainingDocumentView!.props.Document; - currScale = pme.GetFieldValue(KeyStore.Scale, NumberField, Number(0)); - } - let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - doc.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField); - doc.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField); + let currScale: number = this.props.ContainingDocumentView!.ScalingToScreenSpace; + let x = this.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + let y = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + this.props.Document.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX) / currScale, NumberField); + this.props.Document.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY) / currScale, NumberField); this._lastX = e.pageX; this._lastY = e.pageY; } @@ -198,11 +194,11 @@ export class CollectionFreeFormView extends React.Component<IProps> { return ( <div className="border" style={{ borderStyle: "solid", - borderWidth: "2px", + borderWidth: `${CollectionFreeFormView.BORDER_WIDTH}px`, }}> <div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} style={{ width: "100%", - height: "calc(100% - 4px)", + height: `calc(100% - 2*${CollectionFreeFormView.BORDER_WIDTH}px)`, overflow: "hidden" }} onDrop={this.onDrop} onDragOver={this.onDragOver} ref={this._containerRef}> <div className="collectionfreeformview" style={{transform: `translate(${panx}px, ${pany}px) scale(${currScale}, ${currScale})`, transformOrigin: `left, top`}} ref={this._canvasRef}> diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index 1387f44b1..19feefa70 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -129,21 +129,33 @@ export class DocumentView extends React.Component<IProps> { return SelectionManager.IsSelected(this) || this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView!.active; } - hackToAccountForCollectionFreeFormBorderWidth: number = 2; // this is the border width of the collection + + // + // returns the cumulative scaling between the document and the screen + // + @computed + public get ScalingToScreenSpace(): number { + let containingDocView = this.props.ContainingDocumentView; + if (containingDocView != undefined) { + let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + return containingDocView.ScalingToScreenSpace * ss; + } + return 1; + } + // - // Converts an input coordinate in application's screen space - // into a coordinate in the space of this document. - // NOTE: this is intended for use on DocumentViews that are CollectionFreeFormViews + // Converts a coordinate in the screen space of the app into a local document coordinate. // public TransformToLocalPoint(screenX: number, screenY: number) { - let ContainerX = screenX - this.hackToAccountForCollectionFreeFormBorderWidth; - let ContainerY = screenY - this.hackToAccountForCollectionFreeFormBorderWidth; + let ContainerX = screenX; + let ContainerY = screenY - CollectionFreeFormView.BORDER_WIDTH; + // if this collection view is nested within another collection view, then // first transform the screen point into the parent collection's coordinate space. if (this.props.ContainingDocumentView != undefined) { let {LocalX, LocalY} = this.props.ContainingDocumentView!.TransformToLocalPoint(screenX, screenY); - ContainerX = LocalX; - ContainerY = LocalY; + ContainerX = LocalX - CollectionFreeFormView.BORDER_WIDTH; + ContainerY = LocalY - CollectionFreeFormView.BORDER_WIDTH; } let W = this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); @@ -152,38 +164,39 @@ export class DocumentView extends React.Component<IProps> { let Ss = this.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); let Panxx = this.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); let Panyy = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - let LocalX = W / 2 - (Xx + Panxx) / Ss + (ContainerX - W / 2) / Ss; - let LocalY = -(Yy + Panyy) / Ss + ContainerY / Ss; + let LocalX = (ContainerX - (Xx + Panxx) - W / 2) / Ss + W / 2; + let LocalY = (ContainerY - (Yy + Panyy)) / Ss; return {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY}; } + // - // Converts the coordinate space of a document to a screen space coordinate. + // Converts a point in the coordinate space of a document to a screen space coordinate. // public TransformToScreenPoint(localX: number, localY: number, Ss: number = 1, Panxx: number = 0, Panyy: number = 0): {ScreenX: number, ScreenY: number} { let W = this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); + let H = CollectionFreeFormView.BORDER_WIDTH; let Xx = this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); let Yy = this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); - - let parentX = (localX + (Xx + Panxx) / Ss - W / 2) * Ss + W / 2; - let parentY = (localY + (Yy + Panyy) / Ss) * Ss; + let parentX = (localX - W / 2) * Ss + (Xx + Panxx) + W / 2; + let parentY = (localY - H) * Ss + (Yy + Panyy) + H; // if this collection view is nested within another collection view, then - // first transform the screen point into the parent collection's coordinate space. - if (this.props.ContainingDocumentView != undefined) { - let ss = this.props.ContainingDocumentView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); - let panxx = this.props.ContainingDocumentView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - let panyy = this.props.ContainingDocumentView.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - let {ScreenX, ScreenY} = this.props.ContainingDocumentView.TransformToScreenPoint(parentX, parentY, ss, panxx, panyy); - return {ScreenX: ScreenX + this.hackToAccountForCollectionFreeFormBorderWidth, ScreenY: ScreenY + this.hackToAccountForCollectionFreeFormBorderWidth}; - } else { - return {ScreenX: parentX, ScreenY: parentY}; + // first transform the local point into the parent collection's coordinate space. + let containingDocView = this.props.ContainingDocumentView; + if (containingDocView != undefined) { + let ss = containingDocView.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + let panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + CollectionFreeFormView.BORDER_WIDTH * ss; + let panyy = containingDocView.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)) + CollectionFreeFormView.BORDER_WIDTH * ss; + let {ScreenX, ScreenY} = containingDocView.TransformToScreenPoint(parentX, parentY, ss, panxx, panyy); + parentX = ScreenX; + parentY = ScreenY; } + return {ScreenX: parentX, ScreenY: parentY}; } onPointerDown = (e: React.PointerEvent): void => { - let me = this; this._downX = e.clientX; this._downY = e.clientY; this._contextMenuCanOpen = e.button == 2; |