aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-01-28 15:38:32 -0500
committerbob <bcz@cs.brown.edu>2019-01-28 15:38:32 -0500
commit738d9fae678aa151d0ebb29ec4dbe62b18cd50f3 (patch)
tree186659164b298f8a340abaaa3ff3fe7fbe9de894
parent5e1171dd68c227ad6e3a618dd77d0dcd97b2003c (diff)
finished with transformations
-rw-r--r--src/DocumentDecorations.tsx46
-rw-r--r--src/views/freeformcanvas/CollectionFreeFormView.tsx22
-rw-r--r--src/views/nodes/DocumentView.tsx61
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;