aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DocumentDecorations.scss2
-rw-r--r--src/Main.tsx15
-rw-r--r--src/util/DragManager.ts31
-rw-r--r--src/views/collections/CollectionDockingView.scss39
-rw-r--r--src/views/collections/CollectionDockingView.tsx172
-rw-r--r--src/views/collections/CollectionFreeFormView.tsx30
-rw-r--r--src/views/nodes/DocumentView.tsx124
-rw-r--r--src/views/nodes/FieldTextBox.tsx28
8 files changed, 288 insertions, 153 deletions
diff --git a/src/DocumentDecorations.scss b/src/DocumentDecorations.scss
index 2840d782b..252b0f53f 100644
--- a/src/DocumentDecorations.scss
+++ b/src/DocumentDecorations.scss
@@ -10,7 +10,7 @@
.documentDecorations-resizer {
pointer-events: auto;
background: lightblue;
- opacity: 0.8;
+ opacity: 0.4;
}
#documentDecorations-topLeftResizer,
#documentDecorations-bottomRightResizer {
diff --git a/src/Main.tsx b/src/Main.tsx
index ab87fc316..8c91399b1 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -24,7 +24,7 @@ configure({
const mainNodeCollection = new Array<Document>();
let mainContainer = Documents.DockDocument(mainNodeCollection, {
- x: 0, y: 0, width: window.screen.width, height: window.screen.height, title: "main container"
+ x: 0, y: 0, title: "main container"
})
window.addEventListener("drop", function (e) {
@@ -47,7 +47,7 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
doc2.SetField(KS.X, new NumberField(150));
doc2.SetField(KS.Y, new NumberField(20));
let doc3 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
- x: 450, y: 500
+ x: 450, y: 500, title: "cat 1"
});
const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v
@@ -61,10 +61,10 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
x: 0, y: 400, title: "mini collection"
});
let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
- x: 650, y: 500, width: 600, height: 600, title: "cat"
+ x: 650, y: 500, width: 600, height: 600, title: "cat 2"
});
let docset2 = new Array<Document>(doc4, doc1, doc3);
- let doc6 = Documents.DockDocument(docset2, {
+ let doc6 = Documents.CollectionDocument(docset2, {
x: 350, y: 100, width: 600, height: 600, title: "docking collection"
});
let mainNodes = null;// mainContainer.GetFieldT(KeyStore.Data, ListField);
@@ -77,15 +77,14 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
// mainNodes.Data.push(doc3);
mainNodes.Data.push(doc5);
// mainNodes.Data.push(doc1);
- mainNodes.Data.push(doc2);
- //mainNodes.Data.push(doc6);
+ //mainNodes.Data.push(doc2);
+ mainNodes.Data.push(doc6);
mainContainer.SetField(KeyStore.Data, mainNodes);
}
//);
ReactDOM.render((
- <div style={{ display: "grid" }}>
- <h1>Dash Web</h1>
+ <div style={{ position: "absolute", width: "100%", height: "100%" }}>
<DocumentView Document={mainContainer} ContainingCollectionView={undefined} ContainingDocumentView={undefined} />
<DocumentDecorations />
<ContextMenu />
diff --git a/src/util/DragManager.ts b/src/util/DragManager.ts
index ca5b6c0ea..5b7609819 100644
--- a/src/util/DragManager.ts
+++ b/src/util/DragManager.ts
@@ -2,9 +2,18 @@ import { Opt } from "../fields/Field";
import { DocumentView } from "../views/nodes/DocumentView";
import { DocumentDecorations } from "../DocumentDecorations";
import { SelectionManager } from "./SelectionManager";
+import { CollectionDockingView } from "../views/collections/CollectionDockingView";
+import { Document } from "../fields/Document";
export namespace DragManager {
- export let rootId = "root";
+ 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 {
@@ -33,7 +42,7 @@ export namespace DragManager {
}
export class DropEvent {
- constructor(readonly x: number, readonly y: number, readonly data: { [ id: string ]: any }) { }
+ constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { }
}
export interface DropHandlers {
@@ -44,7 +53,7 @@ export namespace DragManager {
if ("canDrop" in element.dataset) {
throw new Error("Element is already droppable, can't make it droppable again");
}
- element.dataset[ "canDrop" ] = "true";
+ element.dataset["canDrop"] = "true";
const handler = (e: Event) => {
const ce = e as CustomEvent<DropEvent>;
options.handlers.drop(e, ce.detail);
@@ -52,21 +61,17 @@ export namespace DragManager {
element.addEventListener("dashOnDrop", handler);
return () => {
element.removeEventListener("dashOnDrop", handler);
- delete element.dataset[ "canDrop" ]
+ delete element.dataset["canDrop"]
};
}
let _lastPointerX: number = 0;
let _lastPointerY: number = 0;
- export function StartDrag(ele: HTMLElement, dragData: { [ id: string ]: any }, options: DragOptions) {
+ export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options: DragOptions) {
if (!dragDiv) {
- const root = document.getElementById(rootId);
- if (!root) {
- throw new Error("No root element found");
- }
dragDiv = document.createElement("div");
- root.appendChild(dragDiv);
+ DragManager.Root().appendChild(dragDiv);
}
const w = ele.offsetWidth, h = ele.offsetHeight;
const rect = ele.getBoundingClientRect();
@@ -79,8 +84,8 @@ export namespace DragManager {
dragElement.style.transformOrigin = "0 0";
dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
dragDiv.appendChild(dragElement);
- _lastPointerX = dragData[ "xOffset" ] + rect.left;
- _lastPointerY = dragData[ "yOffset" ] + rect.top;
+ _lastPointerX = dragData["xOffset"] + rect.left;
+ _lastPointerY = dragData["yOffset"] + rect.top;
let hideSource = false;
if (typeof options.hideSource === "boolean") {
@@ -112,7 +117,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, options: DragOptions, dragData: { [index: string]: any }) {
dragDiv.removeChild(dragEle);
const target = document.elementFromPoint(e.x, e.y);
if (!target) {
diff --git a/src/views/collections/CollectionDockingView.scss b/src/views/collections/CollectionDockingView.scss
index 43af7c538..118662d89 100644
--- a/src/views/collections/CollectionDockingView.scss
+++ b/src/views/collections/CollectionDockingView.scss
@@ -4,10 +4,23 @@
top: 0;
left: 0;
overflow: hidden;
+
+ .lm_controls>li {
+ opacity: 0.6;
+ transform: scale(1.2);
+ }
+ .lm_maximised .lm_controls .lm_maximise {
+ opacity:1;
+ transform: scale(0.8);
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKElEQVR4nGP8////fwYCgImQAgYGBgYWKM2IR81/okwajIpgvsMbVgAwgQYRVakEKQAAAABJRU5ErkJggg==) !important;
+ }
+
.flexlayout__layout {
- width: 100%;
- height: 100%;
- position: relative;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ position: absolute;
overflow:hidden;
}
@@ -79,9 +92,10 @@
.flexlayout__tab {
overflow: auto;
- position: absolute;
+ position:absolute;
box-sizing: border-box;
background-color: #222;
+ color:black;
}
.flexlayout__tab_button {
@@ -107,12 +121,10 @@
}
.flexlayout__tab_button_leading {
- float: left;
display:inline-block;
}
.flexlayout__tab_button_content {
- float: left;
display:inline-block;
}
@@ -127,7 +139,6 @@
}
.flexlayout__tab_button_trailing {
- float: left;
display:inline-block;
margin-left:5px;
margin-top:3px;
@@ -137,7 +148,7 @@
.flexlayout__tab_button:hover .flexlayout__tab_button_trailing,
.flexlayout__tab_button--selected .flexlayout__tab_button_trailing{
- //background: transparent url("../images/close_white.png") no-repeat center;
+ background: transparent url("../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
}
.flexlayout__tab_button_overflow {
@@ -150,7 +161,7 @@
font-size: 10px;
color:lightgray;
font-family: Arial, sans-serif;
- //background: transparent url("../images/more.png") no-repeat left;
+ background: transparent url("../../../node_modules/flexlayout-react/images/more.png") no-repeat left;
}
.flexlayout__tabset_header
@@ -185,12 +196,12 @@
.flexlayout__tabset-selected
{
- //background-image: linear-gradient(#111, #444);
+ background-image: linear-gradient(#111, #444);
}
.flexlayout__tabset-maximized
{
- //background-image: linear-gradient(#666, #333);
+ background-image: linear-gradient(#666, #333);
}
.flexlayout__tab_toolbar {
@@ -208,7 +219,7 @@
height:20px;
border:none;
outline-width: 0;
- //background: transparent url("../images/maximize.png") no-repeat center;
+ background: transparent url("../../../node_modules/flexlayout-react/images/maximize.png") no-repeat center;
}
.flexlayout__tab_toolbar_button-max {
@@ -216,7 +227,7 @@
height:20px;
border:none;
outline-width: 0;
- //background: transparent url("../images/restore.png") no-repeat center;
+ background: transparent url("../../../node_modules/flexlayout-react/images/restore.png") no-repeat center;
}
.flexlayout__popup_menu {
@@ -339,7 +350,7 @@
.flexlayout__border_button:hover .flexlayout__border_button_trailing,
.flexlayout__border_button--selected .flexlayout__border_button_trailing{
- //background: transparent url("../images/close_white.png") no-repeat center;
+ background: transparent url("../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
}
diff --git a/src/views/collections/CollectionDockingView.tsx b/src/views/collections/CollectionDockingView.tsx
index 3d0c39c9d..a547ea1e8 100644
--- a/src/views/collections/CollectionDockingView.tsx
+++ b/src/views/collections/CollectionDockingView.tsx
@@ -4,7 +4,7 @@ import React = require("react");
import FlexLayout from "flexlayout-react";
import { action, observable, computed } from "mobx";
import { Document } from "../../fields/Document";
-import { DocumentView, CollectionViewProps } from "../nodes/DocumentView";
+import { DocumentView, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "../nodes/DocumentView";
import { ListField } from "../../fields/ListField";
import { NumberField } from "../../fields/NumberField";
import { SSL_OP_SINGLE_DH_USE } from "constants";
@@ -15,6 +15,7 @@ import 'golden-layout/src/css/goldenlayout-base.css';
import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import * as GoldenLayout from "golden-layout";
import * as ReactDOM from 'react-dom';
+import { DragManager } from "../../util/DragManager";
@observer
export class CollectionDockingView extends React.Component<CollectionViewProps> {
@@ -45,15 +46,16 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
var docs = value.map(doc => {
return { type: 'component', componentName: 'documentViewComponent', componentState: { doc: doc } };
});
- return new GoldenLayout({ content: [ { type: 'row', content: docs } ] });
+ return new GoldenLayout({
+ settings: {
+ selectionEnabled: true
+ }, content: [ { type: 'row', content: docs } ]
+ });
}
constructor(props: CollectionViewProps) {
super(props);
}
- public static BORDER_WIDTH = 2;
- public static TAB_HEADER_HEIGHT = 20;
-
@computed
public get active(): boolean {
var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView));
@@ -65,8 +67,12 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
componentDidMount: () => void = () => {
if (this._containerRef.current && CollectionDockingView.UseGoldenLayout) {
this.goldenLayoutFactory();
+ window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
}
}
+ componentWillUnmount: () => void = () => {
+ window.removeEventListener('resize', this.onResize);
+ }
private nextId = (function () { var _next_id = 0; return function () { return _next_id++; } })();
@action
@@ -87,6 +93,15 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
ContextMenu.Instance.clearItems()
}
}
+
+ @action
+ onResize = (event: any) => {
+ var cur = this.props.ContainingDocumentView!.MainContent.current;
+
+ // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
+ CollectionDockingView.myLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
+ }
+
@action
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 2 && this.active) {
@@ -116,31 +131,94 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
}
}
+ public static myLayout: any = null;
+
+ private static _dragDiv: any = null;
+ private static _dragParent: HTMLElement | null = null;
+ private static _dragElement: HTMLDivElement;
+ private static _dragFakeElement: HTMLDivElement;
+ public static StartOtherDrag(dragElement: HTMLDivElement, dragDoc: Document) {
+ var newItemConfig = {
+ type: 'component',
+ componentName: 'documentViewComponent',
+ componentState: { doc: dragDoc }
+ };
+ this._dragElement = dragElement;
+ this._dragParent = dragElement.parentElement;
+ // bcz: we want to copy this document into the header, not move it there.
+ // However, GoldenLayout is setup to move things, so we have to do some kludgy stuff:
+
+ // - create a temporary invisible div and register that as a DragSource with GoldenLayout
+ this._dragDiv = document.createElement("div");
+ this._dragDiv.style.opacity = 0;
+ DragManager.Root().appendChild(this._dragDiv);
+ CollectionDockingView.myLayout.createDragSource(this._dragDiv, newItemConfig);
+
+ // - add our document to that div so that GoldenLayout will get the move events its listening for
+ this._dragDiv.appendChild(this._dragElement);
+
+ // - add a duplicate of our document to the original document's container
+ // (GoldenLayout will be removing our original one)
+ this._dragFakeElement = dragElement.cloneNode(true) as HTMLDivElement;
+ this._dragParent!.appendChild(this._dragFakeElement);
+
+ // all of this must be undone when the document has been dropped (see tabCreated)
+ }
+
+ _makeFullScreen: boolean = false;
+ _maximizedStack: any = null;
+ public static OpenFullScreen(dv: DocumentView) {
+ var newItemConfig = {
+ type: 'component',
+ componentName: 'documentViewComponent',
+ componentState: { doc: dv.props.Document }
+ };
+ CollectionDockingView.myLayout._makeFullScreen = true;
+ CollectionDockingView.myLayout.root.contentItems[ 0 ].addChild(newItemConfig);
+ }
+ public static CloseFullScreen() {
+ if (CollectionDockingView.myLayout._maximizedStack != null) {
+ CollectionDockingView.myLayout._maximizedStack.header.controlsContainer.find('.lm_close').click();
+ CollectionDockingView.myLayout._maximizedStack = null;
+ }
+ }
goldenLayoutFactory() {
- var myLayout = this.modelForGoldenLayout;
+ CollectionDockingView.myLayout = this.modelForGoldenLayout;
- myLayout.on('stackCreated', function (stack: any) {
- stack.header.controlsContainer.find('.lm_close') //get the close icon
- .off('click') //unbind the current click handler
+ CollectionDockingView.myLayout.on('tabCreated', function (tab: any) {
+ if (CollectionDockingView._dragDiv) {
+ CollectionDockingView._dragDiv.removeChild(CollectionDockingView._dragElement);
+ CollectionDockingView._dragParent!.removeChild(CollectionDockingView._dragFakeElement);
+ CollectionDockingView._dragParent!.appendChild(CollectionDockingView._dragElement);
+ DragManager.Root().removeChild(CollectionDockingView._dragDiv);
+ CollectionDockingView._dragDiv = null;
+ }
+ tab.setTitle(tab.contentItem.config.componentState.doc.Title);
+ tab.closeElement.off('click') //unbind the current click handler
.click(function () {
- if (confirm('really close this?')) {
- stack.remove();
- }
+ //if (confirm('really close this?')) {
+ tab.contentItem.remove();
+ //}
});
});
- myLayout.on('tabCreated', function (tab: any) {
- tab.setTitle(tab.contentItem.config.componentState.doc.Title);
- tab.closeElement.off('click') //unbind the current click handler
+ CollectionDockingView.myLayout.on('stackCreated', function (stack: any) {
+ if (CollectionDockingView.myLayout._makeFullScreen) {
+ CollectionDockingView.myLayout._maximizedStack = stack;
+ CollectionDockingView.myLayout._maxstack = stack.header.controlsContainer.find('.lm_maximise');
+ }
+ stack.header.controlsContainer.find('.lm_popout').hide();
+ stack.header.controlsContainer.find('.lm_close') //get the close icon
+ .off('click') //unbind the current click handler
.click(function () {
- if (confirm('really close this?')) {
- tab.contentItem.remove();
- }
+ //if (confirm('really close this?')) {
+ stack.remove();
+ //}
});
});
var me = this;
- myLayout.registerComponent('documentViewComponent', function (container: any, state: any) {
+ CollectionDockingView.myLayout.registerComponent('documentViewComponent', function (container: any, state: any) {
// bcz: this is crufty
// calling html() causes a div tag to be added in the DOM with id 'containingDiv'.
// Apparently, we need to wait to allow a live html div element to actually be instantiated.
@@ -152,11 +230,14 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
<DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} ContainingDocumentView={me.props.ContainingDocumentView} />
),
document.getElementById(containingDiv)
- )
+ );
+ if (CollectionDockingView.myLayout._maxstack != null) {
+ CollectionDockingView.myLayout._maxstack.click();
+ }
}, 0);
});
- myLayout.container = this._containerRef.current;
- myLayout.init();
+ CollectionDockingView.myLayout.container = this._containerRef.current;
+ CollectionDockingView.myLayout.init();
}
@@ -168,35 +249,24 @@ export class CollectionDockingView extends React.Component<CollectionViewProps>
var w = Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)) / s;
var h = Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)) / s;
- if (CollectionDockingView.UseGoldenLayout) {
- return (
- <div className="border" style={{
- borderStyle: "solid",
- borderWidth: `${CollectionDockingView.BORDER_WIDTH}px`,
- }}>
- <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
- style={{
- width: "100%",
- height: "100%"
- }} >
- </div>
- </div>
- );
- } else {
- return (
- <div className="border" style={{
- borderStyle: "solid",
- borderWidth: `${CollectionDockingView.BORDER_WIDTH}px`,
- }}>
- <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
- style={{
- width: s > 1 ? "100%" : w - 2 * CollectionDockingView.BORDER_WIDTH,
- height: s > 1 ? "100%" : h - 2 * CollectionDockingView.BORDER_WIDTH
- }} >
- <FlexLayout.Layout model={this.modelForFlexLayout} factory={this.flexLayoutFactory} />
- </div>
- </div>
- );
+ var chooseLayout = () => {
+ if (!CollectionDockingView.UseGoldenLayout)
+ return <FlexLayout.Layout model={this.modelForFlexLayout} factory={this.flexLayoutFactory} />;
}
+
+ return (
+ <div className="border" style={{
+ borderStyle: "solid",
+ borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
+ }}>
+ <div className="collectiondockingview-container" id="menuContainer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} ref={this._containerRef}
+ style={{
+ width: CollectionDockingView.UseGoldenLayout || s > 1 ? "100%" : w - 2 * COLLECTION_BORDER_WIDTH,
+ height: CollectionDockingView.UseGoldenLayout || s > 1 ? "100%" : h - 2 * COLLECTION_BORDER_WIDTH
+ }} >
+ {chooseLayout()}
+ </div>
+ </div>
+ );
}
} \ No newline at end of file
diff --git a/src/views/collections/CollectionFreeFormView.tsx b/src/views/collections/CollectionFreeFormView.tsx
index b4dd140d0..ffb39426d 100644
--- a/src/views/collections/CollectionFreeFormView.tsx
+++ b/src/views/collections/CollectionFreeFormView.tsx
@@ -3,7 +3,7 @@ import { Key, KeyStore } from "../../fields/Key";
import React = require("react");
import { action, observable, computed } from "mobx";
import { Document } from "../../fields/Document";
-import { DocumentView, CollectionViewProps } from "../nodes/DocumentView";
+import { DocumentView, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "../nodes/DocumentView";
import { ListField } from "../../fields/ListField";
import { NumberField } from "../../fields/NumberField";
import { SSL_OP_SINGLE_DH_USE } from "constants";
@@ -24,8 +24,6 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps>
super(props);
}
- public static BORDER_WIDTH = 2;
-
@computed
public get active(): boolean {
var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView));
@@ -37,17 +35,22 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps>
}
drop = (e: Event, de: DragManager.DropEvent) => {
- const doc = de.data[ "document" ];
+ const doc = de.data["document"];
if (doc instanceof DocumentView) {
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;
- let { LocalX, LocalY } = this.props.ContainingDocumentView!.TransformToLocalPoint(de.x - xOffset, de.y - yOffset);
- doc.x = LocalX;
- doc.y = LocalY;
+ const xOffset = de.data["xOffset"] as number || 0;
+ const yOffset = de.data["yOffset"] as number || 0;
+ const { scale, translateX, translateY } = Utils.GetScreenTransform(this._canvasRef.current!);
+ let sscale = this.props.ContainingDocumentView!.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1))
+ const screenX = de.x - xOffset;
+ const screenY = de.y - yOffset;
+ const docX = (screenX - translateX) / sscale / scale;
+ const docY = (screenY - translateY) / sscale / scale;
+ doc.x = docX;
+ doc.y = docY;
}
e.stopPropagation();
}
@@ -67,8 +70,6 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps>
@action
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 2 && this.active) {
- e.stopPropagation();
- e.preventDefault();
document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
@@ -123,7 +124,7 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps>
e.stopPropagation()
e.preventDefault()
let fReader = new FileReader()
- let file = e.dataTransfer.items[ 0 ].getAsFile();
+ let file = e.dataTransfer.items[0].getAsFile();
let that = this;
const panx: number = this.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0));
const pany: number = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0));
@@ -178,14 +179,15 @@ export class CollectionFreeFormView extends React.Component<CollectionViewProps>
const panx: number = Document.GetNumberField(KeyStore.PanX, 0);
const pany: number = Document.GetNumberField(KeyStore.PanY, 0);
const currScale: number = Document.GetNumberField(KeyStore.Scale, 1);
+ console.log("DocsR " + value.length);
return (
<div className="border" style={{
borderStyle: "solid",
- borderWidth: `${CollectionFreeFormView.BORDER_WIDTH}px`,
+ borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
}}>
<div className="collectionfreeformview-container" onPointerDown={this.onPointerDown} onWheel={this.onPointerWheel} onContextMenu={(e) => e.preventDefault()} style={{
width: "100%",
- height: `calc(100% - 2*${CollectionFreeFormView.BORDER_WIDTH}px)`,
+ height: `calc(100% - 2*${COLLECTION_BORDER_WIDTH}px)`,
}} 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 20dc6540b..634cd78be 100644
--- a/src/views/nodes/DocumentView.tsx
+++ b/src/views/nodes/DocumentView.tsx
@@ -1,26 +1,30 @@
+import { action, computed } from "mobx";
import { observer } from "mobx-react";
-import React = require("react");
-import { computed, observable, action } from "mobx";
-import { KeyStore, Key } from "../../fields/Key";
+import { Document } from "../../fields/Document";
+import { Opt } from "../../fields/Field";
+import { Key, KeyStore } from "../../fields/Key";
+import { ListField } from "../../fields/ListField";
import { NumberField } from "../../fields/NumberField";
import { TextField } from "../../fields/TextField";
-import { ListField } from "../../fields/ListField";
-import { FieldTextBox } from "../nodes/FieldTextBox"
-import { Document } from "../../fields/Document";
-import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"
-import { CollectionDockingView } from "../collections/CollectionDockingView"
import { CollectionSchemaView } from "../collections/CollectionSchemaView"
import "./NodeView.scss"
+import { DragManager } from "../../util/DragManager";
import { SelectionManager } from "../../util/SelectionManager";
+import { Utils } from "../../Utils";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
import { ContextMenu } from "../ContextMenu";
-import { Opt } from "../../fields/Field";
-import { DragManager } from "../../util/DragManager";
+import { FieldTextBox } from "../nodes/FieldTextBox";
+import "./NodeView.scss";
+import React = require("react");
+import { cpus } from "os";
+import { relative } from "path";
const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
interface DocumentViewProps {
Document: Document;
ContainingCollectionView: Opt<CollectionView>;
- ContainingDocumentView: Opt<DocumentView>
+ ContainingDocumentView: Opt<DocumentView>;
}
export interface CollectionViewProps {
@@ -29,14 +33,18 @@ export interface CollectionViewProps {
ContainingDocumentView: Opt<DocumentView>;
}
-// these properties are set via the render() method of the DocumentView when it creates this node.
-// However, these properties are set below in the LayoutString() static method
+//
+// these properties get assigned through the render() method of the DocumentView when it creates this node.
+// However, that only happens because the properties are "defined" in FieldTextBox's LayoutString() method
+//
export interface DocumentFieldViewProps {
fieldKey: Key;
doc: Document;
containingDocumentView: DocumentView
}
+export const COLLECTION_BORDER_WIDTH = 2;
+
interface CollectionView {
addDocument: (doc: Document) => void;
removeDocument: (doc: Document) => void;
@@ -80,10 +88,7 @@ class DocumentContents extends React.Component<DocumentViewProps> {
showWarnings={true}
onError={(test: any) => { console.log(test) }}
/>
-
-
}
-
}
@observer
@@ -103,6 +108,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return new DOMRect();
}
+ get MainContent() {
+ return this._mainCont;
+ }
+
@computed
get x(): number {
return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
@@ -170,20 +179,25 @@ export class DocumentView extends React.Component<DocumentViewProps> {
// Converts a coordinate in the screen space of the app into a local document coordinate.
//
public TransformToLocalPoint(screenX: number, screenY: number) {
- let ContainerX = screenX - CollectionFreeFormView.BORDER_WIDTH;
- 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 - CollectionFreeFormView.BORDER_WIDTH;
- ContainerY = LocalY - CollectionFreeFormView.BORDER_WIDTH;
+ let { LocalX: parentX, LocalY: parentY } = this.props.ContainingDocumentView != undefined ?
+ this.props.ContainingDocumentView!.TransformToLocalPoint(screenX, screenY) :
+ { LocalX: screenX, LocalY: screenY };
+ let ContainerX: number = parentX - COLLECTION_BORDER_WIDTH;
+ let ContainerY: number = parentY - COLLECTION_BORDER_WIDTH;
+
+ var Xx = this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
+ var Yy = this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
+ // CollectionDockingViews change the location of their children frames without using a Dash transformation.
+ // They also ignore any transformation that may have been applied to their content document.
+ // NOTE: this currently assumes CollectionDockingViews aren't nested.
+ if (this.props.ContainingCollectionView instanceof CollectionDockingView) {
+ var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this._mainCont.current!);
+ Xx = rx - COLLECTION_BORDER_WIDTH;
+ Yy = ry - COLLECTION_BORDER_WIDTH;
}
- let dockingViewChromeHack = this.props.ContainingCollectionView instanceof CollectionDockingView;
- let Xx = dockingViewChromeHack ? 0 : this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
- let Yy = dockingViewChromeHack ? CollectionDockingView.TAB_HEADER_HEIGHT : this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
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));
@@ -198,11 +212,19 @@ export class DocumentView extends React.Component<DocumentViewProps> {
//
public TransformToScreenPoint(localX: number, localY: number, Ss: number = 1, Panxx: number = 0, Panyy: number = 0): { ScreenX: number, ScreenY: number } {
- let dockingViewChromeHack = this.props.ContainingCollectionView instanceof CollectionDockingView;
- let W = CollectionFreeFormView.BORDER_WIDTH; // this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0));
- let H = CollectionFreeFormView.BORDER_WIDTH;
- let Xx = dockingViewChromeHack ? 0 : this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
- let Yy = dockingViewChromeHack ? CollectionDockingView.TAB_HEADER_HEIGHT : this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
+ var Xx = this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0));
+ var Yy = this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0));
+ // CollectionDockingViews change the location of their children frames without using a Dash transformation.
+ // They also ignore any transformation that may have been applied to their content document.
+ // NOTE: this currently assumes CollectionDockingViews aren't nested.
+ if (this.props.ContainingCollectionView instanceof CollectionDockingView) {
+ var { translateX: rx, translateY: ry } = Utils.GetScreenTransform(this._mainCont.current!);
+ Xx = rx - COLLECTION_BORDER_WIDTH;
+ Yy = ry - COLLECTION_BORDER_WIDTH;
+ }
+
+ let W = COLLECTION_BORDER_WIDTH;
+ let H = COLLECTION_BORDER_WIDTH;
let parentX = (localX - W) * Ss + (Xx + Panxx) + W;
let parentY = (localY - H) * Ss + (Yy + Panyy) + H;
@@ -211,8 +233,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
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 panxx = containingDocView.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
+ let panyy = containingDocView.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)) + COLLECTION_BORDER_WIDTH * ss;
let { ScreenX, ScreenY } = containingDocView.TransformToScreenPoint(parentX, parentY, ss, panxx, panyy);
parentX = ScreenX;
parentY = ScreenY;
@@ -223,6 +245,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
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();
@@ -237,7 +265,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
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.props.ContainingCollectionView != null) {
this._contextMenuCanOpen = false;
const rect = this.screenRect;
@@ -271,6 +304,20 @@ export class DocumentView extends React.Component<DocumentViewProps> {
this.props.ContainingCollectionView.removeDocument(this.props.Document)
}
}
+ @action
+ fullScreenClicked = (e: React.MouseEvent): void => {
+ CollectionDockingView.OpenFullScreen(this);
+ 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 => {
@@ -283,29 +330,34 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return;
}
- var topMost = this.props.ContainingCollectionView == undefined;
+ var topMost = this.props.ContainingCollectionView == undefined ||
+ this.props.ContainingCollectionView instanceof CollectionDockingView;
if (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: "Delete", event: this.deleteClicked })
- ContextMenu.Instance.displayMenu(e.pageX, e.pageY)
+ ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
SelectionManager.SelectDoc(this, e.ctrlKey);
}
}
render() {
- var freestyling = this.props.ContainingCollectionView === undefined || this.props.ContainingCollectionView instanceof CollectionFreeFormView;
+ var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView;
return (
<div className="node" ref={this._mainCont} style={{
transform: freestyling ? this.transform : "",
width: freestyling ? this.width : "100%",
height: freestyling ? this.height : "100%",
+ position: freestyling ? "absolute" : "relative",
}}
onContextMenu={this.onContextMenu}
onPointerDown={this.onPointerDown}>
diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx
index 20dfde1d2..9809f3aed 100644
--- a/src/views/nodes/FieldTextBox.tsx
+++ b/src/views/nodes/FieldTextBox.tsx
@@ -1,22 +1,18 @@
-import { Key, KeyStore } from "../../fields/Key";
-import { Document } from "../../fields/Document";
-import { observer } from "mobx-react";
-import { TextField } from "../../fields/TextField";
-import React = require("react")
-import { action, observable, reaction, IReactionDisposer } from "mobx";
-
+import { action, IReactionDisposer, reaction } from "mobx";
+import { baseKeymap } from "prosemirror-commands";
+import { history, redo, undo } from "prosemirror-history";
+import { keymap } from "prosemirror-keymap";
import { schema } from "prosemirror-schema-basic";
-import { EditorState, Transaction } from "prosemirror-state"
-import { EditorView } from "prosemirror-view"
-import { keymap } from "prosemirror-keymap"
-import { baseKeymap } from "prosemirror-commands"
-import { undo, redo, history } from "prosemirror-history"
+import { EditorState, Transaction } from "prosemirror-state";
+import { EditorView } from "prosemirror-view";
+import { Document } from "../../fields/Document";
import { Opt } from "../../fields/Field";
-
-import "./FieldTextBox.scss"
-import { DocumentFieldViewProps } from "./DocumentView";
+import { Key } from "../../fields/Key";
+import { TextField } from "../../fields/TextField";
import { SelectionManager } from "../../util/SelectionManager";
-
+import { DocumentView, DocumentFieldViewProps } from "./DocumentView";
+import "./FieldTextBox.scss";
+import React = require("react")
// FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document