aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx10
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx110
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx10
-rw-r--r--src/client/views/collections/CollectionMapView.tsx25
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx12
-rw-r--r--src/client/views/collections/CollectionPileView.tsx12
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx18
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaMovableTableHOC.tsx20
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx20
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx58
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx22
-rw-r--r--src/client/views/collections/CollectionStaffView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx85
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx12
-rw-r--r--src/client/views/collections/CollectionTreeView.scss1
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx192
-rw-r--r--src/client/views/collections/CollectionView.scss2
-rw-r--r--src/client/views/collections/CollectionView.tsx86
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx10
-rw-r--r--src/client/views/collections/ParentDocumentSelector.tsx10
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx14
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx20
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx11
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx247
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.scss1
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx80
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx32
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx32
-rw-r--r--src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx18
-rw-r--r--src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx4
-rw-r--r--src/client/views/collections/collectionMulticolumn/MultirowHeightLabel.tsx4
-rw-r--r--src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx18
34 files changed, 705 insertions, 507 deletions
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index a04136e51..39bb9bc23 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -2,18 +2,18 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { observable, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { documentSchema, collectionSchema } from '../../../new_fields/documentSchemas';
-import { makeInterface } from '../../../new_fields/Schema';
-import { NumCast, StrCast, ScriptCast, Cast } from '../../../new_fields/Types';
+import { documentSchema, collectionSchema } from '../../../fields/documentSchemas';
+import { makeInterface } from '../../../fields/Schema';
+import { NumCast, StrCast, ScriptCast, Cast } from '../../../fields/Types';
import { DragManager } from '../../util/DragManager';
import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
import "./CollectionCarouselView.scss";
import { CollectionSubView } from './CollectionSubView';
import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons';
-import { Doc } from '../../../new_fields/Doc';
+import { Doc } from '../../../fields/Doc';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { ContextMenu } from '../ContextMenu';
-import { ObjectField } from '../../../new_fields/ObjectField';
+import { ObjectField } from '../../../fields/ObjectField';
import { returnFalse } from '../../../Utils';
type CarouselDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 33ece13cc..745476ef7 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -7,13 +7,13 @@ import { observer } from "mobx-react";
import * as ReactDOM from 'react-dom';
import Measure from "react-measure";
import * as GoldenLayout from "../../../client/goldenLayout";
-import { DateField } from '../../../new_fields/DateField';
-import { Doc, DocListCast, Field, Opt, DataSym } from "../../../new_fields/Doc";
-import { Id } from '../../../new_fields/FieldSymbols';
-import { List } from '../../../new_fields/List';
-import { FieldId } from "../../../new_fields/RefField";
-import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { TraceMobx } from '../../../new_fields/util';
+import { DateField } from '../../../fields/DateField';
+import { Doc, DocListCast, Field, Opt, DataSym } from "../../../fields/Doc";
+import { Id } from '../../../fields/FieldSymbols';
+import { List } from '../../../fields/List';
+import { FieldId } from "../../../fields/RefField";
+import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnOne, returnTrue, Utils, returnZero } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs } from '../../documents/Documents';
@@ -30,6 +30,7 @@ import { SubCollectionViewProps } from "./CollectionSubView";
import { DockingViewButtonSelector } from './ParentDocumentSelector';
import React = require("react");
import { CollectionViewType } from './CollectionView';
+import { SnappingManager } from '../../util/SnappingManager';
library.add(faFile);
const _global = (window /* browser */ || global /* node */) as any;
@@ -68,10 +69,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
//Why is this here?
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
- DragManager.Vals.Instance.StartWindowDrag = this.StartOtherDrag;
+ DragManager.StartWindowDrag = this.StartOtherDrag;
}
- hack: boolean = false;
- undohack: any = null;
public StartOtherDrag = (e: any, dragDocs: Doc[]) => {
let config: any;
if (dragDocs.length === 1) {
@@ -191,6 +190,30 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
return retVal;
}
+ @undoBatch
+ @action
+ public static ReplaceTab(document: Doc, stack: any): Opt<Doc> {
+ if (!CollectionDockingView.Instance) return undefined;
+ const instance = CollectionDockingView.Instance;
+ const replaceTab = (doc: Doc, child: any): Opt<Doc> => {
+ for (const contentItem of child.contentItems) {
+ const { config, isStack, isRow, isColumn } = contentItem;
+ if (isRow || isColumn || isStack) {
+ const val = replaceTab(doc, contentItem);
+ if (val) return val;
+ } else if (config.component === "DocumentFrameRenderer" &&
+ config.props.documentId === doc[Id]) {
+ const alias = Doc.MakeAlias(doc);
+ config.props.documentId = alias[Id];
+ config.title = alias.title;
+ instance.stateChanged();
+ return alias;
+ }
+ }
+ return undefined;
+ };
+ return replaceTab(document, instance._goldenLayout.root);
+ }
//
// Creates a vertical split on the right side of the docking view, and then adds the Document to the right of that split
@@ -454,12 +477,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const json = JSON.stringify(this._goldenLayout.toConfig());
this.props.Document.dockingConfig = json;
this.updateDataField(json);
-
- if (this.undohack && !this.hack) {
- this.undohack.end();
- this.undohack = undefined;
- }
- this.hack = false;
}
itemDropped = () => {
@@ -500,7 +517,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const stack = tab.contentItem.parent;
// shifts the focus to this tab when another tab is dragged over it
tab.element[0].onmouseenter = (e: any) => {
- if (!this._isPointerDown || !DragManager.Vals.Instance.GetIsDragging()) return;
+ if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return;
const activeContentItem = tab.header.parent.getActiveContentItem();
if (tab.contentItem !== activeContentItem) {
tab.header.parent.setActiveContentItem(tab.contentItem);
@@ -516,15 +533,17 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
}
};
- let rendered = false;
+
tab.buttonDisposer = reaction(() => ((view: Opt<DocumentView>) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)),
(views) => {
- !rendered && ReactDOM.render(<span title="Drag as document" className="collectionDockingView-dragAsDocument" onPointerDown={onDown} >
- <DockingViewButtonSelector views={views} Stack={stack} />
- </span>,
- gearSpan);
- rendered = true;
- });
+ if (views.length) {
+ ReactDOM.render(<span title="Drag as document" className="collectionDockingView-dragAsDocument" onPointerDown={onDown} >
+ <DockingViewButtonSelector views={() => views} Stack={stack} />
+ </span>,
+ gearSpan);
+ tab.buttonDisposer?.();
+ }
+ }, { fireImmediately: true });
tab.reactComponents = [gearSpan];
tab.element.append(gearSpan);
@@ -680,16 +699,20 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
**/
@undoBatch
@action
- public static PinDoc(doc: Doc) {
- //add this new doc to props.Document
- const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
- if (curPres) {
- const pinDoc = Doc.MakeAlias(doc);
- pinDoc.presentationTargetDoc = doc;
- pinDoc.presZoomButton = true;
- Doc.AddDocToList(curPres, "data", pinDoc);
- if (!DocumentManager.Instance.getDocumentView(curPres)) {
- CollectionDockingView.AddRightSplit(curPres);
+ public static PinDoc(doc: Doc, unpin = false) {
+ if (unpin) DockedFrameRenderer.UnpinDoc(doc);
+ else {
+ //add this new doc to props.Document
+ const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
+ if (curPres) {
+ const pinDoc = Doc.MakeAlias(doc);
+ pinDoc.presentationTargetDoc = doc;
+ pinDoc.presZoomButton = true;
+ pinDoc.context = curPres;
+ Doc.AddDocToList(curPres, "data", pinDoc);
+ if (!DocumentManager.Instance.getDocumentView(curPres)) {
+ CollectionDockingView.AddRightSplit(curPres);
+ }
}
}
}
@@ -734,8 +757,10 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
}
get layoutDoc() { return this._document && Doc.Layout(this._document); }
- panelWidth = () => this.layoutDoc && this.layoutDoc.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) : this._panelWidth;
- panelHeight = () => this._panelHeight;
+ nativeAspect = () => this.nativeWidth() ? this.nativeWidth() / this.nativeHeight() : 0;
+ panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) :
+ (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth)
+ panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight;
nativeWidth = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeWidth) || this._panelWidth : 0;
nativeHeight = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeHeight) || this._panelHeight : 0;
@@ -773,7 +798,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
return Transform.Identity();
}
get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
- get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; }
+ get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}%` : undefined; }
addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => {
SelectionManager.DeselectAll();
@@ -783,6 +808,13 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
return CollectionDockingView.AddRightSplit(doc, libraryPath);
} else if (location === "close") {
return CollectionDockingView.CloseRightSplit(doc);
+ } else if (location === "replace") {
+ const alias = CollectionDockingView.ReplaceTab(doc, this._stack);
+ if (alias) {
+ runInAction(() => this._document = alias);
+ return true;
+ }
+ return false;
} else {// if (location === "inPlace") {
return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath);
}
@@ -804,8 +836,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
ContentScaling={this.contentScaling}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
+ NativeHeight={this.nativeHeight}
+ NativeWidth={this.nativeWidth}
ScreenToLocalTransform={this.ScreenToLocalTransform}
renderDepth={0}
parentActive={returnTrue}
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 344dca23a..f1002044a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -1,9 +1,9 @@
import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, HeightSym, WidthSym } from '../../../new_fields/Doc';
-import { makeInterface } from '../../../new_fields/Schema';
-import { BoolCast, NumCast, StrCast, Cast, ScriptCast } from '../../../new_fields/Types';
+import { Doc, HeightSym, WidthSym } from '../../../fields/Doc';
+import { makeInterface } from '../../../fields/Schema';
+import { BoolCast, NumCast, StrCast, Cast, ScriptCast } from '../../../fields/Types';
import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse, returnZero } from '../../../Utils';
import { DragManager } from '../../util/DragManager';
import { Transform } from '../../util/Transform';
@@ -11,8 +11,8 @@ import "./CollectionLinearView.scss";
import { CollectionViewType } from './CollectionView';
import { CollectionSubView } from './CollectionSubView';
import { DocumentView } from '../nodes/DocumentView';
-import { documentSchema } from '../../../new_fields/documentSchemas';
-import { Id } from '../../../new_fields/FieldSymbols';
+import { documentSchema } from '../../../fields/documentSchemas';
+import { Id } from '../../../fields/FieldSymbols';
type LinearDocument = makeInterface<[typeof documentSchema,]>;
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
index 971224482..d91337ce9 100644
--- a/src/client/views/collections/CollectionMapView.tsx
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -1,10 +1,10 @@
import { GoogleApiWrapper, Map as GeoMap, IMapProps, Marker } from "google-maps-react";
import { observer } from "mobx-react";
-import { Doc, Opt, DocListCast, FieldResult, Field } from "../../../new_fields/Doc";
-import { documentSchema } from "../../../new_fields/documentSchemas";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { makeInterface } from "../../../new_fields/Schema";
-import { Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types";
+import { Doc, Opt, DocListCast, FieldResult, Field } from "../../../fields/Doc";
+import { documentSchema } from "../../../fields/documentSchemas";
+import { Id } from "../../../fields/FieldSymbols";
+import { makeInterface } from "../../../fields/Schema";
+import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
import "./CollectionMapView.scss";
import { CollectionSubView } from "./CollectionSubView";
import React = require("react");
@@ -47,7 +47,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
private _cancelAddrReq = new Map<string, boolean>();
private _cancelLocReq = new Map<string, boolean>();
private _initialLookupPending = new Map<string, boolean>();
- private responders: { location: Lambda, address: Lambda }[] = [];
+ private responders: { locationDisposer: Lambda, addressDisposer: Lambda }[] = [];
/**
* Note that all the uses of runInAction below are not included
@@ -176,13 +176,16 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
}
@computed get reactiveContents() {
- this.responders.forEach(({ location, address }) => { location(); address(); });
+ this.responders.forEach(({ locationDisposer, addressDisposer }) => {
+ locationDisposer();
+ addressDisposer();
+ });
this.responders = [];
return this.childLayoutPairs.map(({ layout }) => {
const fieldKey = Doc.LayoutFieldKey(layout);
const id = layout[Id];
this.responders.push({
- location: computed(() => ({ lat: layout[`${fieldKey}-lat`], lng: layout[`${fieldKey}-lng`] }))
+ locationDisposer: computed(() => ({ lat: layout[`${fieldKey}-lat`], lng: layout[`${fieldKey}-lng`] }))
.observe(({ oldValue, newValue }) => {
if (this._cancelLocReq.get(id)) {
this._cancelLocReq.set(id, false);
@@ -190,7 +193,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
this.respondToLocationChange(layout, fieldKey, newValue, oldValue);
}
}),
- address: computed(() => Cast(layout[`${fieldKey}-address`], "string", null))
+ addressDisposer: computed(() => Cast(layout[`${fieldKey}-address`], "string", null))
.observe(({ oldValue, newValue }) => {
if (this._cancelAddrReq.get(id)) {
this._cancelAddrReq.set(id, false);
@@ -206,7 +209,8 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
render() {
const { childLayoutPairs } = this;
const { Document, fieldKey, active, google } = this.props;
- let center = this.getLocation(Document, `${fieldKey}-mapCenter`, false);
+ const mapLoc = this.getLocation(this.rootDoc, `${fieldKey}-mapCenter`, false);
+ let center = mapLoc;
if (center === undefined) {
const childLocations = childLayoutPairs.map(({ layout }) => this.getLocation(layout, Doc.LayoutFieldKey(layout), false));
center = childLocations.find(location => location) || defaultLocation;
@@ -246,6 +250,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps>
}}
>
{this.reactiveContents}
+ {mapLoc ? this.renderMarker(this.rootDoc) : undefined}
</GeoMap>
</div>
</div>;
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index c74cfbcf4..d6cb174cc 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -4,20 +4,20 @@ import { faPalette } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc } from "../../../new_fields/Doc";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
-import { ScriptField } from "../../../new_fields/ScriptField";
-import { StrCast, NumCast } from "../../../new_fields/Types";
+import { Doc } from "../../../fields/Doc";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
+import { ScriptField } from "../../../fields/ScriptField";
+import { StrCast, NumCast } from "../../../fields/Types";
import { numberRange, setupMoveUpEvents, emptyFunction } from "../../../Utils";
import { Docs } from "../../documents/Documents";
import { DragManager } from "../../util/DragManager";
import { CompileScript } from "../../util/Scripting";
-import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { undoBatch } from "../../util/UndoManager";
import { EditableView } from "../EditableView";
import { CollectionStackingView } from "./CollectionStackingView";
import "./CollectionStackingView.scss";
+import { SnappingManager } from "../../util/SnappingManager";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -132,7 +132,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
this._color = color;
}
- pointerEnteredRow = action(() => DragManager.Vals.Instance.GetIsDragging() && (this._background = "#b4b4b4"));
+ pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4"));
@action
pointerLeaveRow = () => {
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index 0a10c24b3..e3bcf2a21 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -1,8 +1,8 @@
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
-import { ScriptField } from "../../../new_fields/ScriptField";
-import { BoolCast, NumCast, StrCast } from "../../../new_fields/Types";
+import { HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { ScriptField } from "../../../fields/ScriptField";
+import { BoolCast, NumCast, StrCast } from "../../../fields/Types";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
@@ -12,7 +12,7 @@ import React = require("react");
import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../../Utils";
import { SelectionManager } from "../../util/SelectionManager";
import { UndoManager } from "../../util/UndoManager";
-import { DragManager } from "../../util/DragManager";
+import { SnappingManager } from "../../util/SnappingManager";
@observer
export class CollectionPileView extends CollectionSubView(doc => doc) {
@@ -79,7 +79,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) {
_undoBatch: UndoManager.Batch | undefined;
pointerDown = (e: React.PointerEvent) => {
let dist = 0;
- DragManager.Vals.Instance.SetIsDragging(true);
+ SnappingManager.SetIsDragging(true);
// this._lastTap should be set to 0, and this._doubleTap should be set to false in the class header
setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => {
if (this.layoutEngine() === "pass" && this.childDocs.length && this.props.isSelected(true)) {
@@ -99,7 +99,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) {
}, () => {
this._undoBatch?.end();
this._undoBatch = undefined;
- DragManager.Vals.Instance.SetIsDragging(false);
+ SnappingManager.SetIsDragging(false);
if (!this.childDocs.length) {
this.props.ContainingCollectionView?.removeDocument(this.props.Document);
}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 0e6489947..62aed67ed 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -4,8 +4,8 @@ import { observer } from "mobx-react";
import { CellInfo } from "react-table";
import "react-table/react-table.css";
import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
-import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
+import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
import { KeyCodes } from "../../util/KeyCodes";
import { SetupDrag, DragManager } from "../../util/DragManager";
import { CompileScript } from "../../util/Scripting";
@@ -16,13 +16,13 @@ import { EditableView } from "../EditableView";
import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
import { CollectionView } from "./CollectionView";
-import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types";
+import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../fields/Types";
import { Docs } from "../../documents/Documents";
-import { SelectionManager } from "../../util/SelectionManager";
import { library } from '@fortawesome/fontawesome-svg-core';
import { faExpand } from '@fortawesome/free-solid-svg-icons';
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
import { undoBatch } from "../../util/UndoManager";
+import { SnappingManager } from "../../util/SnappingManager";
library.add(faExpand);
@@ -37,8 +37,8 @@ export interface CellProps {
renderDepth: number;
addDocTab: (document: Doc, where: string) => boolean;
pinToPres: (document: Doc) => void;
- moveDocument: (document: Doc, targetCollection: Doc | undefined,
- addDocument: (document: Doc) => boolean) => boolean;
+ moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined,
+ addDocument: (document: Doc | Doc[]) => boolean) => boolean;
isFocused: boolean;
changeFocusedCellByIndex: (row: number, col: number) => void;
setIsEditing: (isEditing: boolean) => void;
@@ -185,11 +185,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
const onItemDown = (e: React.PointerEvent) => {
fieldIsDoc && SetupDrag(this._focusRef,
() => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
- this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc | undefined, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument,
+ this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument,
this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
};
const onPointerEnter = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging() && (type === "document" || type === undefined)) {
+ if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === "document" || type === undefined)) {
dragRef.current!.className = "collectionSchemaView-cellContainer doc-drag-over";
}
};
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 507ee89e4..dae0600b1 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -7,7 +7,7 @@ import { library, IconProp } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ColumnType } from "./CollectionSchemaView";
import { faFile } from "@fortawesome/free-regular-svg-icons";
-import { SchemaHeaderField, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField, PastelSchemaPalette } from "../../../fields/SchemaHeaderField";
import { undoBatch } from "../../util/UndoManager";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index f9cd9a628..6f1e8ac1f 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -2,18 +2,18 @@ import React = require("react");
import { ReactTableDefaults, TableCellRenderer, RowInfo } from "react-table";
import "./CollectionSchemaView.scss";
import { Transform } from "../../util/Transform";
-import { Doc } from "../../../new_fields/Doc";
+import { Doc } from "../../../fields/Doc";
import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager";
-import { SelectionManager } from "../../util/SelectionManager";
-import { Cast, FieldValue, StrCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, StrCast } from "../../../fields/Types";
import { ContextMenu } from "../ContextMenu";
import { action } from "mobx";
import { library } from '@fortawesome/fontawesome-svg-core';
import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { DocumentManager } from "../../util/DocumentManager";
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
import { undoBatch } from "../../util/UndoManager";
+import { SnappingManager } from "../../util/SnappingManager";
library.add(faGripVertical, faTrash);
@@ -32,7 +32,7 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
onPointerEnter = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) {
+ if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
this._header!.current!.className = "collectionSchema-col-wrapper";
document.addEventListener("pointermove", this.onDragMove, true);
}
@@ -130,8 +130,8 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
export interface MovableRowProps {
rowInfo: RowInfo;
ScreenToLocalTransform: () => Transform;
- addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
- removeDoc: (doc: Doc) => boolean;
+ addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
+ removeDoc: (doc: Doc | Doc[]) => boolean;
rowFocused: boolean;
textWrapRow: (doc: Doc) => void;
rowWrapped: boolean;
@@ -143,7 +143,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
private _rowDropDisposer?: DragManager.DragDropDisposer;
onPointerEnter = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) {
+ if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
this._header!.current!.className = "collectionSchema-row-wrapper";
document.addEventListener("pointermove", this.onDragMove, true);
}
@@ -183,7 +183,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
if (docDragData) {
e.stopPropagation();
if (docDragData.draggedDocuments[0] === rowDoc) return true;
- const addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before);
+ const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before);
const movedDocs = docDragData.draggedDocuments;
return (docDragData.dropAction || docDragData.userDropAction) ?
docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
@@ -201,7 +201,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
@undoBatch
@action
- move: DragManager.MoveFunction = (doc: Doc, targetCollection: Doc | undefined, addDoc) => {
+ move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => {
const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection);
if (targetView && targetView.props.ContainingCollectionDoc) {
return doc !== targetCollection && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index c0024293f..35f892d65 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -6,13 +6,13 @@ import { action, computed, observable, untracked } from "mobx";
import { observer } from "mobx-react";
import ReactTable, { CellInfo, Column, ComponentPropsGetterR, Resize, SortingRule } from "react-table";
import "react-table/react-table.css";
-import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { List } from "../../../new_fields/List";
-import { listSpec } from "../../../new_fields/Schema";
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
-import { ComputedField } from "../../../new_fields/ScriptField";
-import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
+import { List } from "../../../fields/List";
+import { listSpec } from "../../../fields/Schema";
+import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
+import { ComputedField } from "../../../fields/ScriptField";
+import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../fields/Types";
import { Docs, DocumentOptions } from "../../documents/Documents";
import { CompileScript, Transformer, ts } from "../../util/Scripting";
import { Transform } from "../../util/Transform";
@@ -207,9 +207,9 @@ export interface SchemaTableProps {
ContainingCollectionDoc: Opt<Doc>;
fieldKey: string;
renderDepth: number;
- deleteDocument: (document: Doc) => boolean;
- addDocument: (document: Doc) => boolean;
- moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean;
+ deleteDocument: (document: Doc | Doc[]) => boolean;
+ addDocument: (document: Doc | Doc[]) => boolean;
+ moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
ScreenToLocalTransform: () => Transform;
active: (outsideReaction: boolean) => boolean;
onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f6cdebc9b..cc6077d98 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -4,17 +4,16 @@ import { CursorProperty } from "csstype";
import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import Switch from 'rc-switch';
-import { DataSym, Doc, HeightSym, WidthSym } from "../../../new_fields/Doc";
-import { collectionSchema, documentSchema } from "../../../new_fields/documentSchemas";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { List } from "../../../new_fields/List";
-import { listSpec, makeInterface } from "../../../new_fields/Schema";
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types";
-import { TraceMobx } from "../../../new_fields/util";
-import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from "../../../Utils";
+import { DataSym, Doc, HeightSym, WidthSym } from "../../../fields/Doc";
+import { collectionSchema, documentSchema } from "../../../fields/documentSchemas";
+import { Id } from "../../../fields/FieldSymbols";
+import { List } from "../../../fields/List";
+import { listSpec, makeInterface } from "../../../fields/Schema";
+import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
+import { TraceMobx } from "../../../fields/util";
+import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, smoothScroll } from "../../../Utils";
import { DragManager, dropActionType } from "../../util/DragManager";
-import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { undoBatch } from "../../util/UndoManager";
import { ContextMenu } from "../ContextMenu";
@@ -26,7 +25,7 @@ import "./CollectionStackingView.scss";
import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
import { CollectionSubView } from "./CollectionSubView";
import { CollectionViewType } from "./CollectionView";
-import { ScriptField } from "../../../new_fields/ScriptField";
+import { SnappingManager } from "../../util/SnappingManager";
const _global = (window /* browser */ || global /* node */) as any;
type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -58,6 +57,14 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
}
@computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; }
+ constructor(props: any) {
+ super(props);
+
+ if (this.sectionHeaders === undefined) {
+ this.props.Document.sectionHeaders = new List<SchemaHeaderField>();
+ }
+ }
+
children(docs: Doc[], columns?: number) {
TraceMobx();
this._docXfs.length = 0;
@@ -66,7 +73,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
const width = () => this.getDocWidth(d);
const dref = React.createRef<HTMLDivElement>();
const dxf = () => this.getDocTransform(d, dref.current!);
- this._docXfs.push({ dxf: dxf, width: width, height: height });
+ this._docXfs.push({ dxf, width, height });
const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
const style = this.isStackingView ? { width: width(), marginTop: i ? this.gridGap : 0, height: height() } : { gridRowEnd: `span ${rowSpan}` };
return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
@@ -86,7 +93,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
setTimeout(() => this.props.Document.sectionHeaders = new List<SchemaHeaderField>(), 0);
return new Map<SchemaHeaderField, Doc[]>();
}
- const sectionHeaders: SchemaHeaderField[] = Array.from(this.sectionHeaders);
+ const sectionHeaders = Array.from(this.sectionHeaders);
const fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
let changed = false;
this.filteredChildren.map(d => {
@@ -166,6 +173,23 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
return this.props.addDocTab(doc, where);
}
+
+ focusDocument = (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => boolean) => {
+ Doc.BrushDoc(doc);
+ this.props.focus(doc);
+ Doc.linkFollowHighlight(doc);
+
+ const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]);
+ if (found) {
+ const top = found.getBoundingClientRect().top;
+ const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
+ smoothScroll(500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
+ }
+ afterFocus && setTimeout(() => {
+ if (afterFocus?.()) { }
+ }, 500);
+ }
+
getDisplayDoc(doc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
const layoutDoc = Doc.Layout(doc, this.props.ChildLayoutTemplate?.());
const height = () => this.getDocHeight(doc);
@@ -183,12 +207,13 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
NativeHeight={returnZero}
NativeWidth={returnZero}
fitToBox={false}
+ dontRegisterView={this.props.dontRegisterView}
rootSelected={this.rootSelected}
dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
onClick={this.onChildClickHandler}
onDoubleClick={this.onChildDoubleClickHandler}
ScreenToLocalTransform={dxf}
- focus={this.props.focus}
+ focus={this.focusDocument}
ContainingCollectionDoc={this.props.CollectionView?.props.Document}
ContainingCollectionView={this.props.CollectionView}
addDocument={this.props.addDocument}
@@ -312,7 +337,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
this.refList.push(ref);
const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
this.observer = new _global.ResizeObserver(action((entries: any) => {
- if (this.props.Document._autoHeight && ref && this.refList.length && !DragManager.Vals.Instance.GetIsDragging()) {
+ if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
Doc.Layout(doc)._height = Math.min(1200, Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", "")))));
}
}));
@@ -359,7 +384,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
this.refList.push(ref);
const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
this.observer = new _global.ResizeObserver(action((entries: any) => {
- if (this.props.Document._autoHeight && ref && this.refList.length && !DragManager.Vals.Instance.GetIsDragging()) {
+ if (this.props.Document._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
Doc.Layout(doc)._height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0);
}
}));
@@ -407,6 +432,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
if (!e.isPropagationStopped()) {
const subItems: ContextMenuProps[] = [];
subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" });
+ subItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" });
}
}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 1d16a5478..53435ccc9 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -4,16 +4,15 @@ import { faPalette } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast } from "../../../new_fields/Doc";
-import { RichTextField } from "../../../new_fields/RichTextField";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
-import { ScriptField } from "../../../new_fields/ScriptField";
-import { NumCast, StrCast, Cast } from "../../../new_fields/Types";
-import { ImageField } from "../../../new_fields/URLField";
-import { TraceMobx } from "../../../new_fields/util";
+import { Doc, DocListCast } from "../../../fields/Doc";
+import { RichTextField } from "../../../fields/RichTextField";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
+import { ScriptField } from "../../../fields/ScriptField";
+import { NumCast, StrCast, Cast } from "../../../fields/Types";
+import { ImageField } from "../../../fields/URLField";
+import { TraceMobx } from "../../../fields/util";
import { Docs, DocUtils } from "../../documents/Documents";
import { DragManager } from "../../util/DragManager";
-import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { undoBatch } from "../../util/UndoManager";
import { ContextMenu } from "../ContextMenu";
@@ -22,7 +21,8 @@ import { EditableView } from "../EditableView";
import { CollectionStackingView } from "./CollectionStackingView";
import { setupMoveUpEvents, emptyFunction } from "../../../Utils";
import "./CollectionStackingView.scss";
-import { listSpec } from "../../../new_fields/Schema";
+import { listSpec } from "../../../fields/Schema";
+import { SnappingManager } from "../../util/SnappingManager";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -120,7 +120,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@action
pointerEntered = () => {
- if (DragManager.Vals.Instance.GetIsDragging()) {
+ if (SnappingManager.GetIsDragging()) {
this._background = "#b4b4b4";
}
}
@@ -355,7 +355,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
<div className="collectionStackingViewFieldColumn" key={heading}
style={{
width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`,
- height: undefined, // DragManager.Vals.Instance.GetIsDragging() ? "100%" : undefined,
+ height: undefined, // DraggingManager.GetIsDragging() ? "100%" : undefined,
background: this._background
}}
ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx
index 5b9a69bf7..c5c3f96e8 100644
--- a/src/client/views/collections/CollectionStaffView.tsx
+++ b/src/client/views/collections/CollectionStaffView.tsx
@@ -1,7 +1,7 @@
import { CollectionSubView } from "./CollectionSubView";
import React = require("react");
import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx";
-import { NumCast } from "../../../new_fields/Types";
+import { NumCast } from "../../../fields/Types";
import "./CollectionStaffView.scss";
import { observer } from "mobx-react";
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b4ca29b19..c9eb08b45 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,14 +1,14 @@
import { action, computed, IReactionDisposer, reaction } from "mobx";
import { basename } from 'path';
-import CursorField from "../../../new_fields/CursorField";
-import { Doc, Opt } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { List } from "../../../new_fields/List";
-import { listSpec } from "../../../new_fields/Schema";
-import { ScriptField } from "../../../new_fields/ScriptField";
-import { Cast } from "../../../new_fields/Types";
+import CursorField from "../../../fields/CursorField";
+import { Doc, Opt } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
+import { List } from "../../../fields/List";
+import { listSpec } from "../../../fields/Schema";
+import { ScriptField } from "../../../fields/ScriptField";
+import { Cast, ScriptCast } from "../../../fields/Types";
import { GestureUtils } from "../../../pen-gestures/GestureUtils";
-import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { Upload } from "../../../server/SharedMediaTypes";
import { Utils } from "../../../Utils";
import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils";
@@ -16,7 +16,7 @@ import { DocServer } from "../../DocServer";
import { Docs, DocumentOptions } from "../../documents/Documents";
import { DocumentType } from "../../documents/DocumentTypes";
import { Networking } from "../../Network";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, dropActionType } from "../../util/DragManager";
import { ImageUtils } from "../../util/Import & Export/ImageUtils";
import { InteractionUtils } from "../../util/InteractionUtils";
import { undoBatch, UndoManager } from "../../util/UndoManager";
@@ -27,9 +27,9 @@ import { CollectionView } from "./CollectionView";
import React = require("react");
export interface CollectionViewProps extends FieldViewProps {
- addDocument: (document: Doc) => boolean;
- removeDocument: (document: Doc) => boolean;
- moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean;
+ addDocument: (document: Doc | Doc[]) => boolean;
+ removeDocument: (document: Doc | Doc[]) => boolean;
+ moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
PanelWidth: () => number;
PanelHeight: () => number;
VisibleHeight?: () => number;
@@ -95,7 +95,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
// to its children which may be templates.
// If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
@computed get dataField() {
- return this.dataDoc[this.props.fieldKey + (this.props.annotationsKey ? "-" + this.props.annotationsKey : "")];
+ return this.dataDoc[this.props.annotationsKey || this.props.fieldKey];
}
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
@@ -195,43 +195,60 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {
}
- protected onInternalPreDrop(e: Event, de: DragManager.DropEvent) {
+ protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) {
if (de.complete.docDragData) {
- if (de.complete.docDragData.draggedDocuments.some(d => this.childDocs.includes(d))) {
- de.complete.docDragData.dropAction = "move";
+ // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction.
+ // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys)
+ if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) {
+ de.complete.docDragData.dropAction = targetAction;
}
e.stopPropagation();
}
}
+ addDocument = (doc: Doc | Doc[]) => this.props.addDocument(doc);
+
@undoBatch
@action
protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
const docDragData = de.complete.docDragData;
- (this.props.Document.dropConverter instanceof ScriptField) &&
- this.props.Document.dropConverter.script.run({ dragData: docDragData }); /// bcz: check this
+ ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
if (docDragData) {
let added = false;
if (docDragData.dropAction || docDragData.userDropAction) {
- added = docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
+ added = this.addDocument(docDragData.droppedDocuments);
} else if (docDragData.moveDocument) {
- const movedDocs = docDragData.draggedDocuments;
- added = movedDocs.reduce((added: boolean, d, i) =>
- docDragData.droppedDocuments[i] !== d ? this.props.addDocument(docDragData.droppedDocuments[i]) :
- docDragData.moveDocument?.(d, this.props.Document, this.props.addDocument) || added, false);
+ const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
+ const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
+ const res = addedDocs.length ? this.addDocument(addedDocs) : true;
+ added = movedDocs.length ? docDragData.moveDocument(movedDocs, this.props.Document, this.addDocument) : res;
} else {
- added = docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
+ added = this.addDocument(docDragData.droppedDocuments);
}
e.stopPropagation();
return added;
}
else if (de.complete.annoDragData) {
e.stopPropagation();
- return this.props.addDocument(de.complete.annoDragData.dropDocument);
+ return this.addDocument(de.complete.annoDragData.dropDocument);
}
return false;
}
+ readUploadedFileAsText = (inputFile: File) => {
+ const temporaryFileReader = new FileReader();
+
+ return new Promise((resolve, reject) => {
+ temporaryFileReader.onerror = () => {
+ temporaryFileReader.abort();
+ reject(new DOMException("Problem parsing input file."));
+ };
+ temporaryFileReader.onload = () => {
+ resolve(temporaryFileReader.result);
+ };
+ temporaryFileReader.readAsText(inputFile);
+ });
+ }
@undoBatch
@action
protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: () => void) {
@@ -250,7 +267,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
e.stopPropagation();
e.preventDefault();
- const { addDocument } = this.props;
+ const { addDocument } = this;
if (!addDocument) {
alert("this.props.addDocument does not exist. Aborting drop operation.");
return;
@@ -369,7 +386,21 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
}
if (item.kind === "file") {
const file = item.getAsFile();
- file && file.type && files.push(file);
+ file?.type && files.push(file);
+
+ file?.type === "application/json" && this.readUploadedFileAsText(file).then(result => {
+ console.log(result);
+ const json = JSON.parse(result as string);
+ addDocument(Docs.Create.TreeDocument(
+ json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => {
+ const label = Docs.Create.LabelDocument({ title: c["#text"], _width: 120, _height: 20 });
+ const proto = Doc.GetProto(label);
+ proto._width = 120;
+ proto._height = 20;
+ return proto;
+ }
+ ), { _width: 150, _height: 600, title: "across", backgroundColor: "white", _singleLine: true }));
+ });
}
}
for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) {
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index a2d4774c8..15bc0bfd5 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -1,11 +1,11 @@
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc, Opt, DocCastAsync } from "../../../new_fields/Doc";
-import { List } from "../../../new_fields/List";
-import { ObjectField } from "../../../new_fields/ObjectField";
-import { RichTextField } from "../../../new_fields/RichTextField";
-import { ComputedField, ScriptField } from "../../../new_fields/ScriptField";
-import { NumCast, StrCast, BoolCast, Cast } from "../../../new_fields/Types";
+import { Doc, Opt, DocCastAsync } from "../../../fields/Doc";
+import { List } from "../../../fields/List";
+import { ObjectField } from "../../../fields/ObjectField";
+import { RichTextField } from "../../../fields/RichTextField";
+import { ComputedField, ScriptField } from "../../../fields/ScriptField";
+import { NumCast, StrCast, BoolCast, Cast } from "../../../fields/Types";
import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../Utils";
import { Scripting } from "../../util/Scripting";
import { ContextMenu } from "../ContextMenu";
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index a00bb6bfb..2aac81146 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -81,7 +81,6 @@
position: relative;
text-overflow: ellipsis;
white-space: pre-wrap;
- overflow: hidden;
min-width: 10px;
// width:100%;//width: max-content;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 288fa8794..3e99af724 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,18 +1,18 @@
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faArrowsAltH, faBell, faCamera, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faExpand, faMinus, faPlus, faTrash, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, runInAction, untracked } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc';
-import { Id } from '../../../new_fields/FieldSymbols';
-import { List } from '../../../new_fields/List';
-import { Document, listSpec } from '../../../new_fields/Schema';
-import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types';
+import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
+import { List } from '../../../fields/List';
+import { PrefetchProxy } from '../../../fields/Proxy';
+import { Document, listSpec } from '../../../fields/Schema';
+import { ComputedField, ScriptField } from '../../../fields/ScriptField';
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from "../../documents/DocumentTypes";
import { DocumentManager } from '../../util/DocumentManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
import { Scripting } from '../../util/Scripting';
import { SelectionManager } from '../../util/SelectionManager';
@@ -31,8 +31,8 @@ import { CollectionSubView } from "./CollectionSubView";
import "./CollectionTreeView.scss";
import { CollectionViewType } from './CollectionView';
import React = require("react");
-import { PrefetchProxy } from '../../../new_fields/Proxy';
-
+import { makeTemplate } from '../../util/DropConverter';
+import { TraceMobx } from '../../../fields/util';
export interface TreeViewProps {
document: Doc;
@@ -41,7 +41,7 @@ export interface TreeViewProps {
containingCollection: Doc;
prevSibling?: Doc;
renderDepth: number;
- deleteDoc: (doc: Doc) => boolean;
+ deleteDoc: (doc: Doc | Doc[]) => boolean;
moveDocument: DragManager.MoveFunction;
dropAction: dropActionType;
addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean;
@@ -49,7 +49,7 @@ export interface TreeViewProps {
panelWidth: () => number;
panelHeight: () => number;
ChromeHeight: undefined | (() => number);
- addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
+ addDocument: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
indentDocument?: () => void;
outdentDocument?: () => void;
ScreenToLocalTransform: () => Transform;
@@ -60,24 +60,12 @@ export interface TreeViewProps {
active: (outsideReaction?: boolean) => boolean;
treeViewHideHeaderFields: () => boolean;
treeViewPreventOpen: boolean;
- renderedIds: string[];
+ renderedIds: string[]; // list of document ids rendered used to avoid unending expansion of items in a cycle
onCheckedClick?: ScriptField;
onChildClick?: ScriptField;
ignoreFields?: string[];
}
-library.add(faTrashAlt);
-library.add(faAngleRight);
-library.add(faBell);
-library.add(faTrash);
-library.add(faCamera);
-library.add(faExpand);
-library.add(faCaretDown);
-library.add(faCaretRight);
-library.add(faCaretSquareDown);
-library.add(faCaretSquareRight);
-library.add(faArrowsAltH);
-library.add(faPlus, faMinus);
@observer
/**
* Renders a treeView of a collection of documents
@@ -88,66 +76,59 @@ library.add(faPlus, faMinus);
* treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
*/
class TreeView extends React.Component<TreeViewProps> {
+ static _editTitleScript: ScriptField | undefined;
private _header?: React.RefObject<HTMLDivElement> = React.createRef();
private _treedropDisposer?: DragManager.DragDropDisposer;
private _dref = React.createRef<HTMLDivElement>();
private _tref = React.createRef<HTMLDivElement>();
+ private _docRef = React.createRef<DocumentView>();
get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive
-
get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.props.document.defaultExpandedView, "fields"); }
@observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.props.document.treeViewOpen = this._overrideTreeViewOpen = c; }
- @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; }
+ @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.props.document.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; }
@computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.defaultExpandedView); }
@computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
- @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; }
+ @computed get dataDoc() { return this.props.document[DataSym]; }
@computed get fieldKey() {
const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'");
return splits.length > 1 ? splits[1].split("\'")[0] : "data";
}
childDocList(field: string) {
const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined;
- return ((this.props.dataDoc ? Cast(this.props.dataDoc[field], listSpec(Doc)) : undefined) ||
- (layout ? Cast(layout[field], listSpec(Doc)) : undefined) ||
- Cast(this.props.document[field], listSpec(Doc))) as Doc[];
+ return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
+ (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || // else if there's a layout doc, display it's fields
+ Cast(this.props.document[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field
}
@computed get childDocs() { return this.childDocList(this.fieldKey); }
@computed get childLinks() { return this.childDocList("links"); }
- @computed get templateDataDoc() {
- if (this.props.dataDoc === undefined && Doc.LayoutField(this.props.document) !== "string") {
- // if there is no dataDoc (ie, we're not rendering a template layout), but this document has a layout document (not a layout string),
- // then we render the layout document as a template and use this document as the data context for the template layout.
- return this.props.document;
- }
- return this.props.dataDoc;
- }
@computed get boundsOfCollectionDocument() {
return StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1 || !DocListCast(this.props.document[this.fieldKey]).length ? undefined :
Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey]));
}
- @undoBatch delete = () => this.props.deleteDoc(this.props.document);
- @undoBatch openRight = () => this.props.addDocTab(this.props.dropAction === "alias" ? Doc.MakeAlias(this.props.document) : this.props.document, "onRight", this.props.libraryPath);
- @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete();
- @undoBatch move = (doc: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => {
+ @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath);
+ @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc);
}
- @undoBatch @action remove = (document: Document, key: string) => {
- return Doc.RemoveDocFromList(this.dataDoc, key, document);
+ @undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
+ return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
+ flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
}
- @undoBatch @action removeDoc = (document: Document) => {
- return Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), document);
+ @undoBatch @action removeDoc = (doc: Doc | Doc[]) => {
+ return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
+ flg && Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), doc), true);
}
protected createTreeDropTarget = (ele: HTMLDivElement) => {
- this._treedropDisposer && this._treedropDisposer();
+ this._treedropDisposer?.();
ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)), this.props.document);
}
onPointerEnter = (e: React.PointerEvent): void => {
this.props.active(true) && Doc.BrushDoc(this.dataDoc);
- if (e.buttons === 1 && DragManager.Vals.Instance.GetIsDragging()) {
+ if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
this._header!.current!.className = "treeViewItem-header";
document.addEventListener("pointermove", this.onDragMove, true);
}
@@ -185,7 +166,7 @@ class TreeView extends React.Component<TreeViewProps> {
})}
OnFillDown={undoBatch((value: string) => {
Doc.SetInPlace(this.props.document, key, value, false);
- const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, templates: new List<string>([Templates.Title.Layout]) });
+ const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List<string>([Templates.Title.Layout]) });
Doc.SetInPlace(this.props.document, "editTitle", undefined, false);
Doc.SetInPlace(doc, "editTitle", true, false);
return this.props.addDocument(doc);
@@ -221,9 +202,10 @@ class TreeView extends React.Component<TreeViewProps> {
if (de.complete.docDragData) {
e.stopPropagation();
if (de.complete.docDragData.draggedDocuments[0] === this.props.document) return true;
- let addDoc = (doc: Doc) => this.props.addDocument(doc, undefined, before);
+ let addDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
if (inside) {
- addDoc = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) || addDoc(doc);
+ addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce(
+ ((flg: boolean, doc) => flg && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc)), true) || addDoc(doc);
}
const movedDocs = (de.complete.docDragData.treeViewId === this.props.treeViewId[Id] ? de.complete.docDragData.draggedDocuments : de.complete.docDragData.droppedDocuments);
const move = de.complete.docDragData.dropAction === "move" || de.complete.docDragData.dropAction;
@@ -283,8 +265,9 @@ class TreeView extends React.Component<TreeViewProps> {
let contentElement: (JSX.Element | null)[] | JSX.Element = [];
if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && (Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc))) {
- const remDoc = (doc: Doc) => this.remove(doc, key);
- const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
+ const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
+ const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce(
+ (flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true);
contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] :
DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
@@ -324,10 +307,12 @@ class TreeView extends React.Component<TreeViewProps> {
rtfHeight = () => this.rtfWidth() < Doc.Layout(this.props.document)?.[WidthSym]() ? Math.min(Doc.Layout(this.props.document)?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
@computed get renderContent() {
+ TraceMobx();
const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined;
if (expandKey !== undefined) {
- const remDoc = (doc: Doc) => this.remove(doc, expandKey);
- const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true);
+ const remDoc = (doc: Doc | Doc[]) => this.remove(doc, expandKey);
+ const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) =>
+ (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.AddDocToList(this.dataDoc, expandKey, doc, addBefore, before, false, true), true);
const docs = expandKey === "links" ? this.childLinks : this.childDocs;
const sortKey = `${this.fieldKey}-sortAscending`;
return <ul key={expandKey + "more"} onClick={(e) => {
@@ -336,7 +321,7 @@ class TreeView extends React.Component<TreeViewProps> {
}}>
{!docs ? (null) :
TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document),
- this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
+ this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
StrCast(this.props.document.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
[...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)}
@@ -352,7 +337,7 @@ class TreeView extends React.Component<TreeViewProps> {
return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.props.document[Id] + this.props.document.title}>
<ContentFittingDocumentView
Document={layoutDoc}
- DataDoc={this.templateDataDoc}
+ DataDoc={this.dataDoc}
LibraryPath={emptyPath}
renderDepth={this.props.renderDepth + 1}
rootSelected={returnTrue}
@@ -402,13 +387,16 @@ class TreeView extends React.Component<TreeViewProps> {
@computed
get renderBullet() {
const checked = this.props.document.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.props.document.treeViewChecked ? this.props.document.treeViewChecked : "unchecked") : undefined;
- return <div className="bullet" title="view inline" onClick={this.bulletClick} style={{ color: StrCast(this.props.document.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}>
+ return <div className="bullet"
+ title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
+ onClick={this.bulletClick}
+ style={{ color: StrCast(this.props.document.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}>
{<FontAwesomeIcon icon={checked === "check" ? "check" : (checked === "x" ? "times" : checked === "unchecked" ? "square" : !this.treeViewOpen ? (this.childDocs ? "caret-square-right" : "caret-right") : (this.childDocs ? "caret-square-down" : "caret-down"))} />}
</div>;
}
showContextMenu = (e: React.MouseEvent) => {
- simulateMouseClick(this._docRef.current!.ContentDiv!, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
e.stopPropagation();
}
focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true);
@@ -416,15 +404,13 @@ class TreeView extends React.Component<TreeViewProps> {
const focusScript = ScriptField.MakeFunction(`DocFocus(self)`);
return [{ script: focusScript!, label: "Focus" }];
}
- _docRef = React.createRef<DocumentView>();
/**
* Renders the EditableView title element for placement into the tree.
*/
@computed
get renderTitle() {
- const onItemDown = SetupDrag(this._tref, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId[Id], true);
- const editTitle = ScriptField.MakeFunction("setInPlace(this, 'editTitle', true)");
-
+ TraceMobx();
+ (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(self, 'editTitle', true)"));
const headerElements = (
<>
<FontAwesomeIcon icon="cog" size="sm" onClick={e => this.showContextMenu(e)}></FontAwesomeIcon>
@@ -445,13 +431,12 @@ class TreeView extends React.Component<TreeViewProps> {
<FontAwesomeIcon title="open in pane on right" icon="angle-right" size="lg" />
</div>);
return <>
- <div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`} onPointerDown={onItemDown}
+ <div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`}
style={{
- background: Doc.IsHighlighted(this.props.document) ? "orange" : Doc.IsBrushed(this.props.document) ? "#06121212" : "0",
fontWeight: this.props.document.searchMatch ? "bold" : undefined,
textDecoration: Doc.GetT(this.props.document, "title", "string", true) ? "underline" : undefined,
outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined,
- pointerEvents: this.props.active() || DragManager.Vals.Instance.GetIsDragging() ? undefined : "none"
+ pointerEvents: this.props.active() || SnappingManager.GetIsDragging() ? undefined : "none"
}} >
{Doc.GetT(this.props.document, "editTitle", "boolean", true) ?
this.editableView("title") :
@@ -459,12 +444,13 @@ class TreeView extends React.Component<TreeViewProps> {
ref={this._docRef}
Document={this.props.document}
DataDoc={undefined}
- LibraryPath={this.props.libraryPath || []}
+ treeViewId={this.props.treeViewId[Id]}
+ LibraryPath={this.props.libraryPath || emptyPath}
addDocument={undefined}
addDocTab={this.props.addDocTab}
rootSelected={returnTrue}
pinToPres={emptyFunction}
- onClick={this.props.onChildClick || editTitle}
+ onClick={this.props.onChildClick || TreeView._editTitleScript}
dropAction={this.props.dropAction}
moveDocument={this.move}
removeDocument={this.removeDoc}
@@ -476,7 +462,7 @@ class TreeView extends React.Component<TreeViewProps> {
NativeWidth={returnZero}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
- focus={emptyFunction}
+ focus={returnTrue}
parentActive={returnTrue}
whenActiveChanged={emptyFunction}
bringToFront={emptyFunction}
@@ -491,8 +477,9 @@ class TreeView extends React.Component<TreeViewProps> {
}
render() {
+ TraceMobx();
const sorting = this.props.document[`${this.fieldKey}-sortAscending`];
- setTimeout(() => runInAction(() => untracked(() => this._overrideTreeViewOpen = this.treeViewOpen)), 0);
+ //setTimeout(() => runInAction(() => untracked(() => this._overrideTreeViewOpen = this.treeViewOpen)), 0);
return <div className="treeViewItem-container" ref={this.createTreeDropTarget}>
<li className="collection-child">
<div className="treeViewItem-header" ref={this._header} onClick={e => {
@@ -500,12 +487,14 @@ class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
e.preventDefault();
}
- }} onPointerDown={e => {
- if (this.props.active(true)) {
- e.stopPropagation();
- e.preventDefault();
- }
- }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+ }}
+ onPointerDown={e => {
+ if (this.props.active(true)) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }}
+ onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
{this.renderBullet}
{this.renderTitle}
</div>
@@ -523,8 +512,8 @@ class TreeView extends React.Component<TreeViewProps> {
key: string,
parentCollectionDoc: Doc | undefined,
parentPrevSibling: Doc | undefined,
- add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
- remove: ((doc: Doc) => boolean),
+ add: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean,
+ remove: ((doc: Doc | Doc[]) => boolean),
move: DragManager.MoveFunction,
dropAction: dropActionType,
addDocTab: (doc: Doc, where: string) => boolean,
@@ -613,7 +602,7 @@ class TreeView extends React.Component<TreeViewProps> {
remove(child);
}
};
- const addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
+ const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => {
return add(doc, relativeTo ? relativeTo : docs[i], before !== undefined ? before : false);
};
const childLayout = Doc.Layout(pair.layout);
@@ -683,22 +672,26 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
@action
- remove = (document: Document): boolean => {
- const children = Cast(this.props.Document[DataSym][this.props.fieldKey], listSpec(Doc), []);
- if (children.indexOf(document) !== -1) {
- children.splice(children.indexOf(document), 1);
+ remove = (doc: Doc | Doc[]): boolean => {
+ const docs = doc instanceof Doc ? [doc] : doc;
+ const targetDataDoc = this.props.Document[DataSym];
+ const value = DocListCast(targetDataDoc[this.props.fieldKey]);
+ const result = value.filter(v => !docs.includes(v));
+ if (result.length !== value.length) {
+ targetDataDoc[this.props.fieldKey] = new List<Doc>(result);
return true;
}
return false;
}
@action
- addDoc = (doc: Document, relativeTo: Opt<Doc>, before?: boolean): boolean => {
- const doAddDoc = () =>
- Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false);
+ addDoc = (doc: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
+ const doAddDoc = (doc: Doc | Doc[]) =>
+ (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
+ flg && Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true);
if (this.props.Document.resolvedDataDoc instanceof Promise) {
- this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc());
+ this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc(doc));
} else {
- doAddDoc();
+ doAddDoc(doc);
}
return true;
}
@@ -742,9 +735,16 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
Doc.GetProto(img).doubleClickView = doubleClickView;
}
});
+ Doc.GetProto(d).type = "buxton";
Doc.GetProto(d).proto = heroView; // all devices "are" heroViews that share the same layout & defaults. Seems better than making them all be independent and copy a layout string // .layout = ImageBox.LayoutString("hero");
});
+ const iconBuxtonView = ImageDocument(fallbackImg, { title: "hero", _width: 60, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)") });
+ iconBuxtonView.isTemplateDoc = makeTemplate(iconBuxtonView, true, "icon_buxton");
+ Doc.UserDoc()["template-icon-view-buxton"] = new PrefetchProxy(iconBuxtonView);
+ const tempIcons = Doc.GetProto(Cast(Doc.UserDoc()["template-icons"], Doc, null));
+ Doc.AddDocToList(tempIcons, "data", iconBuxtonView);
+
Document.childLayoutTemplate = heroView;
Document.childClickedOpenTemplateView = new PrefetchProxy(detailView);
Document._viewType = CollectionViewType.Time;
@@ -767,16 +767,19 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
return <div id="toolbar" key="toolbar">
<button className="toolbar-button round-button" title="Empty"
onClick={undoBatch(action(() => Doc.GetProto(this.props.Document)[this.props.fieldKey] = undefined))}>
- <FontAwesomeIcon icon={faTrash} size="sm" />
+ <FontAwesomeIcon icon={"trash"} size="sm" />
</button>
</div >;
}
+ onKeyPress = (e: React.KeyboardEvent) => {
+ console.log(e);
+ }
render() {
if (!(this.props.Document instanceof Doc)) return (null);
const dropAction = StrCast(this.props.Document.childDropAction) as dropActionType;
- const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
- const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
+ const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
+ const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc);
const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs;
return !childDocs ? (null) : (
<div className="collectionTreeView-dropTarget" id="body"
@@ -786,6 +789,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
paddingRight: `${NumCast(this.props.Document._xPadding, 10)}px`,
paddingTop: `${NumCast(this.props.Document._yPadding, 20)}px`
}}
+ onKeyPress={this.onKeyPress}
onContextMenu={this.onContextMenu}
onWheel={(e: React.WheelEvent) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
onDrop={this.onTreeDrop}
@@ -800,7 +804,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)}
OnFillDown={undoBatch((value: string) => {
Doc.SetInPlace(this.dataDoc, "title", value, false);
- const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, templates: new List<string>([Templates.Title.Layout]) });
+ const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List<string>([Templates.Title.Layout]) });
EditableView.loadId = doc[Id];
Doc.SetInPlace(doc, "editTitle", true, false);
this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true);
diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss
index d43dd387a..7877fe155 100644
--- a/src/client/views/collections/CollectionView.scss
+++ b/src/client/views/collections/CollectionView.scss
@@ -70,7 +70,7 @@
height: 30px;
position: absolute;
bottom: 15px;
- left: 15px;
+ right: 15px;
border: 2px solid black;
border-radius: 50%;
padding: 3px;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c22ebbcbd..5b344813d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -7,17 +7,15 @@ import { observer } from "mobx-react";
import * as React from 'react';
import Lightbox from 'react-image-lightbox-with-rotate';
import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
-import { DateField } from '../../../new_fields/DateField';
-import { DataSym, Doc, DocListCast, Field, Opt } from '../../../new_fields/Doc';
-import { List } from '../../../new_fields/List';
-import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from '../../../new_fields/Types';
-import { ImageField } from '../../../new_fields/URLField';
-import { TraceMobx } from '../../../new_fields/util';
+import { DateField } from '../../../fields/DateField';
+import { DataSym, Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
+import { List } from '../../../fields/List';
+import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from '../../../fields/Types';
+import { ImageField } from '../../../fields/URLField';
+import { TraceMobx } from '../../../fields/util';
import { Utils, setupMoveUpEvents, returnFalse, returnZero, emptyPath, emptyFunction, returnOne } from '../../../Utils';
import { DocumentType } from '../../documents/DocumentTypes';
-import { DocumentManager } from '../../util/DocumentManager';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
-import { SelectionManager } from '../../util/SelectionManager';
import { ContextMenu } from "../ContextMenu";
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import { ScriptBox } from '../ScriptBox';
@@ -37,15 +35,14 @@ import { CollectionTimeView } from './CollectionTimeView';
import { CollectionTreeView } from "./CollectionTreeView";
import './CollectionView.scss';
import { CollectionViewBaseChrome } from './CollectionViewChromes';
-import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
-import { Id } from '../../../new_fields/FieldSymbols';
-import { listSpec } from '../../../new_fields/Schema';
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
+import { Id } from '../../../fields/FieldSymbols';
+import { listSpec } from '../../../fields/Schema';
import { Docs } from '../../documents/Documents';
-import { ScriptField, ComputedField } from '../../../new_fields/ScriptField';
+import { ScriptField, ComputedField } from '../../../fields/ScriptField';
import { InteractionUtils } from '../../util/InteractionUtils';
-import { ObjectField } from '../../../new_fields/ObjectField';
+import { ObjectField } from '../../../fields/ObjectField';
import CollectionMapView from './CollectionMapView';
-import { Transform } from 'prosemirror-transform';
import { CollectionGridView } from './collectionGrid/CollectionGridView';
import { CollectionPileView } from './CollectionPileView';
const higflyout = require("@hig/flyout");
@@ -74,15 +71,15 @@ export enum CollectionViewType {
Pile = "pileup"
}
export interface CollectionViewCustomProps {
- filterAddDocument: (doc: Doc) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
+ filterAddDocument: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
childLayoutTemplate?: () => Opt<Doc>; // specify a layout Doc template to use for children of the collection
childLayoutString?: string; // specify a layout string to use for children of the collection
}
export interface CollectionRenderProps {
- addDocument: (document: Doc) => boolean;
- removeDocument: (document: Doc) => boolean;
- moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean;
+ addDocument: (document: Doc | Doc[]) => boolean;
+ removeDocument: (document: Doc | Doc[]) => boolean;
+ moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
active: () => boolean;
whenActiveChanged: (isActive: boolean) => void;
PanelWidth: () => number;
@@ -121,35 +118,33 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive);
@action.bound
- addDocument(doc: Doc): boolean {
- if (this.props.filterAddDocument?.(doc) === false) {
- return false;
+ addDocument = (doc: Doc | Doc[]): boolean => {
+ if (doc instanceof Doc) {
+ if (this.props.filterAddDocument?.(doc) === false) {
+ return false;
+ }
}
-
+ const docs = doc instanceof Doc ? [doc] : doc;
const targetDataDoc = this.props.Document[DataSym];
const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
- !docList.includes(doc) && (targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, doc])); // DocAddToList may write to targetdataDoc's parent ... we don't want this. should really change GetProto to GetDataDoc and test for resolvedDataDoc there
- // Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc);
- targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
- doc.context = this.props.Document;
- Doc.GetProto(doc).lastOpened = new DateField;
+ const added = docs.filter(d => !docList.includes(d));
+ if (added.length) {
+ added.map(doc => doc.context = this.props.Document);
+ added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add));
+ targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, ...added]);
+ targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ }
return true;
}
@action.bound
- removeDocument(doc: Doc): boolean {
+ removeDocument = (doc: any): boolean => {
+ const docs = doc instanceof Doc ? [doc] : doc as Doc[];
const targetDataDoc = this.props.Document[DataSym];
- const docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
- docView && SelectionManager.DeselectDoc(docView);
const value = DocListCast(targetDataDoc[this.props.fieldKey]);
- let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1);
- index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
-
- doc.context = undefined;
- ContextMenu.Instance?.clearItems();
- if (index !== -1) {
- value.splice(index, 1);
- targetDataDoc[this.props.fieldKey] = new List<Doc>(value);
+ const result = value.filter(v => !docs.includes(v));
+ if (result.length !== value.length) {
+ targetDataDoc[this.props.fieldKey] = new List<Doc>(result);
return true;
}
return false;
@@ -160,7 +155,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
// otherwise, the document being moved must be able to be removed from its container before
// moving it into the target.
@action.bound
- moveDocument(doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean {
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => {
if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
return true;
}
@@ -168,10 +163,14 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
showIsTagged = () => {
- const children = DocListCast(this.props.Document[this.props.fieldKey]);
- const imageProtos = children.filter(doc => Cast(doc.data, ImageField)).map(Doc.GetProto);
- const allTagged = imageProtos.length > 0 && imageProtos.every(image => image.googlePhotosTags);
- return !allTagged ? (null) : <img id={"google-tags"} src={"/assets/google_tags.png"} />;
+ return (null);
+ // this section would display an icon in the bototm right of a collection to indicate that all
+ // photos had been processed through Google's content analysis API and Google's tags had been
+ // assigned to the documents googlePhotosTags field.
+ // const children = DocListCast(this.props.Document[this.props.fieldKey]);
+ // const imageProtos = children.filter(doc => Cast(doc.data, ImageField)).map(Doc.GetProto);
+ // const allTagged = imageProtos.length > 0 && imageProtos.every(image => image.googlePhotosTags);
+ // return !allTagged ? (null) : <img id={"google-tags"} src={"/assets/google_tags.png"} />;
}
private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
@@ -269,7 +268,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" });
!existingVm && ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
- this.setupViewTypes("Change Perspective...", (vtype => { this.props.Document._viewType = vtype; return this.props.Document; }), true);
this.setupViewTypes("Add a Perspective...", vtype => {
const newRendition = Doc.MakeAlias(this.props.Document);
newRendition._viewType = vtype;
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 62b03bbdc..5dc0b09ac 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -2,11 +2,11 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
-import { Doc, DocListCast } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { List } from "../../../new_fields/List";
-import { listSpec } from "../../../new_fields/Schema";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { Doc, DocListCast } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
+import { List } from "../../../fields/List";
+import { listSpec } from "../../../fields/Schema";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
import { Utils, emptyFunction, setupMoveUpEvents } from "../../../Utils";
import { DragManager } from "../../util/DragManager";
import { undoBatch } from "../../util/UndoManager";
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
index 10c6ead1a..649406e6c 100644
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ b/src/client/views/collections/ParentDocumentSelector.tsx
@@ -1,12 +1,12 @@
import * as React from "react";
import './ParentDocumentSelector.scss';
-import { Doc } from "../../../new_fields/Doc";
+import { Doc } from "../../../fields/Doc";
import { observer } from "mobx-react";
import { observable, action, runInAction, trace, computed, reaction, IReactionDisposer } from "mobx";
-import { Id } from "../../../new_fields/FieldSymbols";
+import { Id } from "../../../fields/FieldSymbols";
import { SearchUtil } from "../../util/SearchUtil";
import { CollectionDockingView } from "./CollectionDockingView";
-import { NumCast, StrCast } from "../../../new_fields/Types";
+import { NumCast, StrCast } from "../../../fields/Types";
import { CollectionViewType } from "./CollectionView";
import { DocumentButtonBar } from "../DocumentButtonBar";
import { DocumentManager } from "../../util/DocumentManager";
@@ -94,7 +94,7 @@ export class ParentDocSelector extends React.Component<SelectorProps> {
}
@observer
-export class DockingViewButtonSelector extends React.Component<{ views: DocumentView[], Stack: any }> {
+export class DockingViewButtonSelector extends React.Component<{ views: () => DocumentView[], Stack: any }> {
customStylesheet(styles: any) {
return {
...styles,
@@ -120,7 +120,7 @@ export class DockingViewButtonSelector extends React.Component<{ views: Document
if (getComputedStyle(this._ref.current!).width !== "100%") {
e.stopPropagation(); e.preventDefault();
}
- this.props.views[0]?.select(false);
+ this.props.views()[0]?.select(false);
}} className="buttonSelector">
<Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
<FontAwesomeIcon icon={"cog"} size={"sm"} />
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 9a864078a..3860ce2d7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -1,15 +1,15 @@
-import { Doc, Field, FieldResult, WidthSym, HeightSym } from "../../../../new_fields/Doc";
-import { NumCast, StrCast, Cast } from "../../../../new_fields/Types";
+import { Doc, Field, FieldResult, WidthSym, HeightSym } from "../../../../fields/Doc";
+import { NumCast, StrCast, Cast } from "../../../../fields/Types";
import { ScriptBox } from "../../ScriptBox";
import { CompileScript } from "../../../util/Scripting";
-import { ScriptField } from "../../../../new_fields/ScriptField";
+import { ScriptField } from "../../../../fields/ScriptField";
import { OverlayView, OverlayElementOptions } from "../../OverlayView";
import { emptyFunction, aggregateBounds } from "../../../../Utils";
import React = require("react");
-import { Id, ToString } from "../../../../new_fields/FieldSymbols";
-import { ObjectField } from "../../../../new_fields/ObjectField";
-import { RefField } from "../../../../new_fields/RefField";
-import { listSpec } from "../../../../new_fields/Schema";
+import { Id, ToString } from "../../../../fields/FieldSymbols";
+import { ObjectField } from "../../../../fields/ObjectField";
+import { RefField } from "../../../../fields/RefField";
+import { listSpec } from "../../../../fields/Schema";
export interface ViewDefBounds {
type: string;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index d67d1993e..f3fc04752 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -1,5 +1,5 @@
import { observer } from "mobx-react";
-import { Doc } from "../../../../new_fields/Doc";
+import { Doc } from "../../../../fields/Doc";
import { Utils } from '../../../../Utils';
import { DocumentView } from "../../nodes/DocumentView";
import "./CollectionFreeFormLinkView.scss";
@@ -7,8 +7,9 @@ import React = require("react");
import v5 = require("uuid/v5");
import { DocumentType } from "../../../documents/DocumentTypes";
import { observable, action, reaction, IReactionDisposer } from "mobx";
-import { StrCast } from "../../../../new_fields/Types";
-import { Id } from "../../../../new_fields/FieldSymbols";
+import { StrCast, Cast } from "../../../../fields/Types";
+import { Id } from "../../../../fields/FieldSymbols";
+import { SnappingManager } from "../../../util/SnappingManager";
export interface CollectionFreeFormLinkViewProps {
A: DocumentView;
@@ -24,6 +25,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
componentDidMount() {
this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)],
action(() => {
+ if (SnappingManager.GetIsDragging()) return;
setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render()
setTimeout(action(() => (!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line.
const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
@@ -79,11 +81,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
componentWillUnmount() {
this._anchorDisposer?.();
}
-
render() {
+ if (SnappingManager.GetIsDragging()) return null;
this.props.A.props.ScreenToLocalTransform().transform(this.props.B.props.ScreenToLocalTransform());
- const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
- const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
+ const acont = this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
+ const bcont = this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
const a = (acont.length ? acont[0] : this.props.A.ContentDiv!).getBoundingClientRect();
const b = (bcont.length ? bcont[0] : this.props.B.ContentDiv!).getBoundingClientRect();
const apt = Utils.closestPtBetweenRectangles(a.left, a.top, a.width, a.height,
@@ -105,15 +107,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const bActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
const text = StrCast(this.props.A.props.Document.linkRelationship);
return !a.width || !b.width || ((!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<>
- <text x={(pt1[0] + pt2[0]) / 2} y={(pt1[1] + pt2[1]) / 2}>
+ <text x={(Math.min(pt1[0], pt2[0]) * 2 + Math.max(pt1[0], pt2[0])) / 3} y={(pt1[1] + pt2[1]) / 2}>
{text !== "-ungrouped-" ? text : ""}
</text>
<path className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity, strokeDasharray: "2 2" }}
d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} />
- {/* <line key="linkLine" className="collectionfreeformlinkview-linkLine"
- style={{ opacity: this._opacity, strokeDasharray: "2 2" }}
- x1={`${pt1[0]}`} y1={`${pt1[1]}`}
- x2={`${pt2[0]}`} y2={`${pt2[1]}`} /> */}
</>);
}
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 0873fd1bb..ae81b4b36 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,16 +1,15 @@
import { computed } from "mobx";
import { observer } from "mobx-react";
-import { Doc } from "../../../../new_fields/Doc";
-import { Id } from "../../../../new_fields/FieldSymbols";
+import { Doc } from "../../../../fields/Doc";
+import { Id } from "../../../../fields/FieldSymbols";
import { DocumentManager } from "../../../util/DocumentManager";
import { DocumentView } from "../../nodes/DocumentView";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
import { Utils, emptyFunction } from "../../../../Utils";
-import { SelectionManager } from "../../../util/SelectionManager";
import { DocumentType } from "../../../documents/DocumentTypes";
-import { DragManager } from "../../../util/DragManager";
+import { SnappingManager } from "../../../util/SnappingManager";
@observer
export class CollectionFreeFormLinksView extends React.Component {
@@ -32,12 +31,12 @@ export class CollectionFreeFormLinksView extends React.Component {
}, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]);
return connections.filter(c =>
c.a.props.Document.type === DocumentType.LINK &&
- c.a.props.bringToFront !== emptyFunction && c.b.props.bringToFront !== emptyFunction // bcz: this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed
+ c.a.props.pinToPres !== emptyFunction && c.b.props.pinToPres !== emptyFunction // bcz: this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed
).map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
}
render() {
- return DragManager.Vals.Instance.GetIsDragging() ? (null) : <div className="collectionfreeformlinksview-container">
+ return SnappingManager.GetIsDragging() ? (null) : <div className="collectionfreeformlinksview-container">
<svg className="collectionfreeformlinksview-svgCanvas">
{this.uniqueConnections}
</svg>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 92fa2781c..548ad78a5 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -1,16 +1,16 @@
import { observer } from "mobx-react";
import * as mobxUtils from 'mobx-utils';
-import CursorField from "../../../../new_fields/CursorField";
-import { listSpec } from "../../../../new_fields/Schema";
-import { Cast } from "../../../../new_fields/Types";
-import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
+import CursorField from "../../../../fields/CursorField";
+import { listSpec } from "../../../../fields/Schema";
+import { Cast } from "../../../../fields/Types";
+import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
import { CollectionViewProps } from "../CollectionSubView";
import "./CollectionFreeFormView.scss";
import React = require("react");
import v5 = require("uuid/v5");
import { computed } from "mobx";
-import { FieldResult } from "../../../../new_fields/Doc";
-import { List } from "../../../../new_fields/List";
+import { FieldResult } from "../../../../fields/Doc";
+import { List } from "../../../../fields/List";
@observer
export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2aa9b1f5f..bf679309c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,21 +1,21 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, _allowStateChangesInsideComputed } from "mobx";
import { observer } from "mobx-react";
import { computedFn } from "mobx-utils";
-import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc";
-import { documentSchema, collectionSchema } from "../../../../new_fields/documentSchemas";
-import { Id } from "../../../../new_fields/FieldSymbols";
-import { InkData, InkField, InkTool, PointData } from "../../../../new_fields/InkField";
-import { List } from "../../../../new_fields/List";
-import { RichTextField } from "../../../../new_fields/RichTextField";
-import { createSchema, listSpec, makeInterface } from "../../../../new_fields/Schema";
-import { ScriptField } from "../../../../new_fields/ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types";
-import { TraceMobx } from "../../../../new_fields/util";
+import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../fields/Doc";
+import { documentSchema, collectionSchema } from "../../../../fields/documentSchemas";
+import { Id } from "../../../../fields/FieldSymbols";
+import { InkData, InkField, InkTool, PointData } from "../../../../fields/InkField";
+import { List } from "../../../../fields/List";
+import { RichTextField } from "../../../../fields/RichTextField";
+import { createSchema, listSpec, makeInterface } from "../../../../fields/Schema";
+import { ScriptField, ComputedField } from "../../../../fields/ScriptField";
+import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
+import { TraceMobx } from "../../../../fields/util";
import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
-import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse } from "../../../../Utils";
+import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse, numberRange } from "../../../../Utils";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { DocServer } from "../../../DocServer";
import { Docs } from "../../../documents/Documents";
@@ -45,6 +45,7 @@ import { MarqueeView } from "./MarqueeView";
import React = require("react");
import { CollectionViewType } from "../CollectionView";
import { Timeline } from "../../animationtimeline/Timeline";
+import { SnappingManager } from "../../../util/SnappingManager";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -112,8 +113,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)) :
this.Document.scale || 1)
- private centeringShiftX = () => !this.nativeWidth && !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling : 0; // shift so pan position is at center of window for non-overlay collections
- private centeringShiftY = () => !this.nativeHeight && !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling : 0;// shift so pan position is at center of window for non-overlay collections
+ private centeringShiftX = () => !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / this.contentScaling : 0; // shift so pan position is at center of window for non-overlay collections
+ private centeringShiftY = () => !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / this.contentScaling : 0;// shift so pan position is at center of window for non-overlay collections
private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform());
private getTransformOverlay = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1);
private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
@@ -122,11 +123,27 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
this.addDocument(newBox);
}
- private addDocument = (newBox: Doc) => {
- const added = this.props.addDocument(newBox);
- added && this.bringToFront(newBox);
- added && this.updateCluster(newBox);
- return added;
+ addDocument = (newBox: Doc | Doc[]) => {
+ const timecode = Cast(this.props.Document.timecode, "number", null);
+ if (timecode !== undefined) {
+ ((newBox instanceof Doc) ? [newBox] : newBox).map(doc => {
+ doc["x-indexed"] = new List<number>(numberRange(timecode + 1).map(i => NumCast(doc.x)));
+ doc["y-indexed"] = new List<number>(numberRange(timecode + 1).map(i => NumCast(doc.y)));
+ doc.timecode = ComputedField.MakeFunction("collection.timecode", {}, { collection: this.props.Document });
+ doc.x = ComputedField.MakeInterpolated("x", "timecode");
+ doc.y = ComputedField.MakeInterpolated("y", "timecode");
+ });
+ }
+
+ if (newBox instanceof Doc) {
+ const added = this.props.addDocument(newBox);
+ added && this.bringToFront(newBox);
+ added && this.updateCluster(newBox);
+ return added;
+ } else {
+ return this.props.addDocument(newBox);
+ // bcz: deal with clusters
+ }
}
private selectDocuments = (docs: Doc[]) => {
SelectionManager.DeselectAll();
@@ -152,6 +169,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const xfo = this.getTransformOverlay();
const [xp, yp] = xf.transformPoint(de.x, de.y);
const [xpo, ypo] = xfo.transformPoint(de.x, de.y);
+ const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
if (super.onInternalDrop(e, de)) {
if (de.complete.docDragData) {
if (de.complete.docDragData.droppedDocuments.length) {
@@ -161,20 +179,25 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const y = (z ? ypo : yp) - de.complete.docDragData.offset[1];
const dropX = NumCast(firstDoc.x);
const dropY = NumCast(firstDoc.y);
- de.complete.docDragData.droppedDocuments.forEach(action((d: Doc) => {
- const layoutDoc = Doc.Layout(d);
- d.x = x + NumCast(d.x) - dropX;
- d.y = y + NumCast(d.y) - dropY;
- if (!NumCast(layoutDoc._width)) {
- layoutDoc._width = 300;
- }
- if (!NumCast(layoutDoc._height)) {
- const nw = NumCast(layoutDoc._nativeWidth);
- const nh = NumCast(layoutDoc._nativeHeight);
- layoutDoc._height = nw && nh ? nh / nw * NumCast(layoutDoc._width) : 300;
+ const droppedDocs = de.complete.docDragData.droppedDocuments;
+ runInAction(() => {
+ zsorted.forEach((doc, index) => doc.zIndex = index + 1);
+ for (let i = 0; i < droppedDocs.length; i++) {
+ const d = droppedDocs[i];
+ const layoutDoc = Doc.Layout(d);
+ d.x = x + NumCast(d.x) - dropX;
+ d.y = y + NumCast(d.y) - dropY;
+ if (!NumCast(layoutDoc._width)) {
+ layoutDoc._width = 300;
+ }
+ if (!NumCast(layoutDoc._height)) {
+ const nw = NumCast(layoutDoc._nativeWidth);
+ const nh = NumCast(layoutDoc._nativeHeight);
+ layoutDoc._height = nw && nh ? nh / nw * NumCast(layoutDoc._width) : 300;
+ }
+ d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront
}
- d.isBackground === undefined && this.bringToFront(d);
- }));
+ });
(de.complete.docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(de.complete.docDragData.droppedDocuments);
}
@@ -327,6 +350,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
this._hitCluster = this.props.Document.useClusters ? this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY)) !== -1 : false;
if (e.button === 0 && (!e.shiftKey || this._hitCluster) && !e.altKey && !e.ctrlKey && this.props.active(true)) {
+
+ // if (!this.props.Document.aliasOf && !this.props.ContainingCollectionView) {
+ // this.props.addDocTab(this.props.Document, "replace");
+ // e.stopPropagation();
+ // e.preventDefault();
+ // return;
+ // }
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
document.addEventListener("pointermove", this.onPointerMove);
@@ -382,7 +412,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
case GestureUtils.Gestures.Stroke:
const points = ge.points;
const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
- const inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { title: "ink stroke", x: B.x, y: B.y, _width: B.width, _height: B.height });
+ const inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, InkingControl.Instance.selectedWidth, points, { title: "ink stroke", x: B.x, y: B.y, _width: B.width, _height: B.height });
this.addDocument(inkDoc);
e.stopPropagation();
break;
@@ -551,7 +581,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
document.removeEventListener("pointerup", this.onPointerUp);
return;
}
- this.pan(e);
+ (!MarqueeView.DragMarquee || e.altKey) && this.pan(e);
}
e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers
e.preventDefault();
@@ -697,7 +727,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@action
zoom = (pointX: number, pointY: number, deltaY: number): void => {
- let deltaScale = deltaY > 0 ? (1 / 1.1) : 1.1;
+ let deltaScale = deltaY > 0 ? (1 / 1.05) : 1.05;
if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) {
deltaScale = 1 / this.zoomScaling();
}
@@ -705,7 +735,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const [x, y] = this.getTransform().transformPoint(pointX, pointY);
const localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y);
- if (localTransform.Scale >= 0.15) {
+ if (localTransform.Scale >= 0.15 || localTransform.Scale > this.zoomScaling()) {
const safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40);
this.props.Document.scale = Math.abs(safeScale);
this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale);
@@ -720,7 +750,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
else if (this.props.active(true)) {
e.stopPropagation();
- this.zoom(e.clientX, e.clientY, e.deltaY);
+ if (!e.ctrlKey && MarqueeView.DragMarquee) this.setPan(this.panX() + e.deltaX, this.panY() + e.deltaY, "None", true);
+ else this.zoom(e.clientX, e.clientY, e.deltaY);
}
this.props.Document.targetScale = NumCast(this.props.Document.scale);
}
@@ -759,20 +790,21 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
}
- bringToFront = (doc: Doc, sendToBack?: boolean) => {
+ bringToFront = action((doc: Doc, sendToBack?: boolean) => {
if (sendToBack || doc.isBackground) {
doc.zIndex = 0;
}
else {
const docs = this.childLayoutPairs.map(pair => pair.layout);
- docs.slice().sort((doc1, doc2) => {
- if (doc1 === doc) return 1;
- if (doc2 === doc) return -1;
- return NumCast(doc1.zIndex) - NumCast(doc2.zIndex);
- }).forEach((doc, index) => doc.zIndex = index + 1);
- doc.zIndex = docs.length + 1;
+ docs.slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
+ let zlast = docs.length ? NumCast(docs[docs.length - 1].zIndex) : 1;
+ if (zlast - docs.length > 100) {
+ for (let i = 0; i < docs.length; i++) doc.zIndex = i + 1;
+ zlast = docs.length + 1;
+ }
+ doc.zIndex = zlast + 1;
}
- }
+ });
scaleAtPt(docpt: number[], scale: number) {
const screenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
@@ -872,6 +904,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
FreezeDimensions: this.props.freezeChildDimensions,
layoutKey: undefined,
setupDragLines: this.setupDragLines,
+ dontRegisterView: this.props.dontRegisterView,
rootSelected: childData ? this.rootSelected : returnFalse,
dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
onClick: this.onChildClickHandler,
@@ -894,14 +927,22 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
addDocTab = action((doc: Doc, where: string) => {
if (where === "inParent") {
- const pt = this.getTransform().transformPoint(NumCast(doc.x), NumCast(doc.y));
- doc.x = pt[0];
- doc.y = pt[1];
- this.props.addDocument(doc);
- return true;
+ if (doc instanceof Doc) {
+ const pt = this.getTransform().transformPoint(NumCast(doc.x), NumCast(doc.y));
+ doc.x = pt[0];
+ doc.y = pt[1];
+ return this.props.addDocument(doc);
+ } else {
+ (doc as any as Doc[]).forEach(doc => {
+ const pt = this.getTransform().transformPoint(NumCast(doc.x), NumCast(doc.y));
+ doc.x = pt[0];
+ doc.y = pt[1];
+ });
+ return this.props.addDocument(doc);
+ }
}
if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
- this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]);
+ this.dataDoc[this.props.fieldKey] = doc instanceof Doc ? doc : new List<Doc>(doc as any as Doc[]);
return true;
}
return this.props.addDocTab(doc, where);
@@ -915,6 +956,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const { x, y, z, color, zIndex } = params.pair.layout;
return {
x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"),
+ transition: StrCast(layoutDoc.transition),
width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number"), pair: params.pair, replica: ""
};
}
@@ -1001,8 +1043,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
get doLayoutComputation() {
const { newPool, computedElementData } = this.doInternalLayoutComputation;
- runInAction(() =>
- Array.from(newPool.entries()).map(entry => {
+ const array = Array.from(newPool.entries());
+ runInAction(() => {
+ for (const entry of array) {
const lastPos = this._cachedPool.get(entry[0]); // last computed pos
const newPos = entry[1];
if (!lastPos || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.zIndex !== lastPos.zIndex) {
@@ -1011,7 +1054,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (!lastPos || newPos.height !== lastPos.height || newPos.width !== lastPos.width) {
this._layoutSizeData.set(entry[0], { width: newPos.width, height: newPos.height });
}
- }));
+ }
+ });
this._cachedPool.clear();
Array.from(newPool.entries()).forEach(k => this._cachedPool.set(k[0], k[1]));
const elements: ViewDefResult[] = computedElementData.slice();
@@ -1036,9 +1080,14 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica)
}));
+ if (this.props.isAnnotationOverlay) {
+ this.props.Document.scale = Math.max(1, NumCast(this.props.Document.scale));
+ }
+
return elements;
}
+ @action
componentDidMount() {
super.componentDidMount?.();
this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
@@ -1057,12 +1106,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
promoteCollection = undoBatch(action(() => {
- this.childDocs.forEach(doc => {
+ const childDocs = this.childDocs.slice();
+ childDocs.forEach(doc => {
const scr = this.getTransform().inverse().transformPoint(NumCast(doc.x), NumCast(doc.y));
doc.x = scr?.[0];
doc.y = scr?.[1];
- this.props.addDocTab(doc, "inParent") && this.props.removeDocument(doc);
});
+ this.props.addDocTab(childDocs as any as Doc, "inParent");
this.props.ContainingCollectionView?.removeDocument(this.props.Document);
}));
layoutDocsInGrid = () => {
@@ -1086,22 +1136,69 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
});
}, "arrange contents");
}
+ @undoBatch
+ @action
+ toggleNativeDimensions = () => {
+ Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight());
+ }
+
+ @undoBatch
+ @action
+ snaphsotInterpolated = (): void => {
+ if (this.props.Document.timecode === undefined) {
+ this.childDocs.map(doc => {
+ this.props.Document.timecode = 0;
+ doc["x-indexed"] = new List<number>([NumCast(doc.x)]);
+ doc["y-indexed"] = new List<number>([NumCast(doc.y)]);
+ doc.timecode = ComputedField.MakeFunction("collection.timecode", {}, { collection: this.props.Document });
+ doc.x = ComputedField.MakeInterpolated("x", "timecode");
+ doc.y = ComputedField.MakeInterpolated("y", "timecode");
+ });
+ }
+ const timecode = NumCast(this.props.Document.timecode);
+ this.childDocs.map(doc => {
+ const xindexed = Cast(doc['x-indexed'], listSpec("number"), null);
+ const yindexed = Cast(doc['y-indexed'], listSpec("number"), null);
+ xindexed.length <= timecode + 1 && xindexed.push(NumCast(doc.x));
+ yindexed.length <= timecode + 1 && yindexed.push(NumCast(doc.y));
+ });
+ this.childDocs.map(doc => doc.transition = "transform 1s");
+ this.props.Document.timecode = Math.max(0, timecode + 1);
+ setTimeout(() => this.childDocs.map(doc => doc.transition = undefined), 1010);
+ }
+ @undoBatch
+ @action
+ backupInterpolated = (): void => {
+ this.childDocs.map(doc => doc.transition = "transform 1s");
+ this.props.Document.timecode = Math.max(0, NumCast(this.props.Document.timecode) - 1);
+ setTimeout(() => this.childDocs.map(doc => doc.transition = undefined), 1010);
+ }
+
private thumbIdentifier?: number;
onContextMenu = (e: React.MouseEvent) => {
- if (this.props.children && this.props.annotationsKey) return;
+ if (this.props.annotationsKey) return;
+
+ ContextMenu.Instance.addItem({
+ description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
+ this._timelineVisible = !this._timelineVisible;
+ }), icon: this._timelineVisible ? faEyeSlash : faEye
+ });
+ ContextMenu.Instance.addItem({ description: "Advance", event: this.snaphsotInterpolated, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
+ ContextMenu.Instance.addItem({ description: "Backup ", event: this.backupInterpolated, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" });
+
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
optionItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
- optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
+ optionItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" });
+ optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
optionItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" });
optionItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" });
// layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
- optionItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document._jitterRotation = (this.props.Document._jitterRotation ? 0 : 10)), icon: "paint-brush" });
optionItems.push({
description: "Import document", icon: "upload", event: ({ x, y }) => {
const input = document.createElement("input");
@@ -1129,14 +1226,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
input.click();
}
});
+ optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
-
- ContextMenu.Instance.addItem({
- description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
- this._timelineVisible = !this._timelineVisible;
- }), icon: this._timelineVisible ? faEyeSlash : faEye
- });
}
@observable _timelineVisible = false;
@@ -1147,7 +1239,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@action
setupDragLines = () => {
- const size = this.props.ScreenToLocalTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight());
+ const activeDocs = this.getActiveDocuments();
+ if (activeDocs.length > 50) {
+ DragManager.SetSnapLines([], []);
+ return;
+ }
+ const size = this.getTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight());
const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] };
const docDims = (doc: Doc) => ({ left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) });
const isDocInView = (doc: Doc, rect: { left: number, top: number, width: number, height: number }) => {
@@ -1174,7 +1271,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
DragManager.SetSnapLines(horizLines, vertLines);
}
onPointerOver = (e: React.PointerEvent) => {
- if (DragManager.Vals.Instance.GetIsDragging()) {
+ if (SnappingManager.GetIsDragging()) {
this.setupDragLines();
}
e.stopPropagation();
@@ -1215,8 +1312,16 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
return false;
});
@computed get marqueeView() {
- return <MarqueeView {...this.props} nudge={this.nudge} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} addDocument={this.addDocument}
- addLiveTextDocument={this.addLiveTextBox} getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} isAnnotationOverlay={this.isAnnotationOverlay}>
+ return <MarqueeView {...this.props}
+ nudge={this.nudge}
+ addDocTab={this.addDocTab}
+ activeDocuments={this.getActiveDocuments}
+ selectDocuments={this.selectDocuments}
+ addDocument={this.addDocument}
+ addLiveTextDocument={this.addLiveTextBox}
+ getContainerTransform={this.getContainerTransform}
+ getTransform={this.getTransform}
+ isAnnotationOverlay={this.isAnnotationOverlay}>
<CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY} shifted={!this.nativeHeight && !this.isAnnotationOverlay}
easing={this.easing} viewDefDivClick={this.props.viewDefDivClick} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
{this.children}
@@ -1233,7 +1338,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const wscale = nw ? this.props.PanelWidth() / nw : 1;
return wscale < hscale ? wscale : hscale;
}
- @computed get backgroundEvents() { return this.layoutDoc.isBackground && DragManager.Vals.Instance.GetIsDragging(); }
+ @computed get backgroundEvents() { return this.layoutDoc.isBackground && SnappingManager.GetIsDragging(); }
render() {
TraceMobx();
const clientRect = this._mainCont?.getBoundingClientRect();
@@ -1247,7 +1352,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
return <div className={"collectionfreeformview-container"}
ref={this.createDashEventsTarget}
onPointerOver={this.onPointerOver}
- onWheel={this.onPointerWheel} onClick={this.onClick} //pointerEvents: DragManager.Vals.Instance.GetIsDragging() ? "all" : undefined,
+ onWheel={this.onPointerWheel} onClick={this.onClick} //pointerEvents: DraggingManager.GetIsDragging() ? "all" : undefined,
onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu}
style={{
pointerEvents: this.backgroundEvents ? "all" : undefined,
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 1291e7dc1..a811dd15a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -7,6 +7,7 @@
height:100%;
overflow: hidden;
border-radius: inherit;
+ user-select: none;
}
.marqueeView:focus-within {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 5bac075b4..492ba6ed6 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,37 +1,34 @@
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast, DataSym, WidthSym, HeightSym, Opt } from "../../../../new_fields/Doc";
-import { InkField, InkData } from "../../../../new_fields/InkField";
-import { List } from "../../../../new_fields/List";
-import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField";
-import { Cast, NumCast, FieldValue, StrCast } from "../../../../new_fields/Types";
+import { Doc, Opt } from "../../../../fields/Doc";
+import { InkData, InkField } from "../../../../fields/InkField";
+import { List } from "../../../../fields/List";
+import { RichTextField } from "../../../../fields/RichTextField";
+import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
import { Utils } from "../../../../Utils";
-import { Docs, DocUtils, DocumentOptions } from "../../../documents/Documents";
+import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
+import { Docs, DocumentOptions, DocUtils } from "../../../documents/Documents";
import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
import { ContextMenu } from "../../ContextMenu";
+import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
import { PreviewCursor } from "../../PreviewCursor";
import { SubCollectionViewProps } from "../CollectionSubView";
+import { CollectionView } from "../CollectionView";
import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
import "./MarqueeView.scss";
import React = require("react");
-import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
-import { RichTextField } from "../../../../new_fields/RichTextField";
-import { CollectionView } from "../CollectionView";
-import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
-import { ScriptField } from "../../../../new_fields/ScriptField";
+import { InteractionUtils } from "../../../util/InteractionUtils";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
getTransform: () => Transform;
- addDocument: (doc: Doc) => boolean;
activeDocuments: () => Doc[];
selectDocuments: (docs: Doc[], ink: { Document: Doc, Ink: Map<any, any> }[]) => void;
- removeDocument: (doc: Doc) => boolean;
addLiveTextDocument: (doc: Doc) => void;
isSelected: () => boolean;
- isAnnotationOverlay?: boolean;
nudge: (x: number, y: number) => boolean;
setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void;
}
@@ -39,7 +36,7 @@ interface MarqueeViewProps {
@observer
export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps>
{
- private _mainCont = React.createRef<HTMLDivElement>();
+ @observable public static DragMarquee = false;
@observable _lastX: number = 0;
@observable _lastY: number = 0;
@observable _downX: number = 0;
@@ -108,7 +105,11 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
});
} else if (!e.ctrlKey) {
FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : "";
- const tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" });
+ const tbox = Docs.Create.TextDocument("", {
+ _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: NumCast(Doc.UserDoc().fontSize),
+ _backgroundColor: StrCast(Doc.UserDoc().backgroundColor),
+ title: "-typed text-"
+ });
const template = FormattedTextBox.DefaultLayout;
if (template instanceof Doc) {
tbox._width = NumCast(template._width);
@@ -164,12 +165,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
onPointerDown = (e: React.PointerEvent): void => {
this._downX = this._lastX = e.clientX;
this._downY = this._lastY = e.clientY;
- if (e.button === 2 || (e.button === 0 && e.altKey)) {
+ // allow marquee if right click OR alt+left click OR space bar + left click
+ if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) {
+ // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) {
this.setPreviewCursor(e.clientX, e.clientY, true);
- if (e.altKey) {
- //e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors.
- e.preventDefault();
- }
+ // (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors.
+ e.preventDefault();
+ // }
// bcz: do we need this? it kills the context menu on the main collection if !altKey
// e.stopPropagation();
}
@@ -191,14 +193,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
} else {
this.cleanupInteractions(true); // stop listening for events if another lower-level handle (e.g. another Marquee) has stopPropagated this
}
- if (e.altKey) {
+ if (e.altKey || MarqueeView.DragMarquee) {
e.preventDefault();
}
}
@action
onPointerUp = (e: PointerEvent): void => {
- if (!this.props.active(true)) this.props.selectDocuments([this.props.Document], []);
if (this._visible) {
const mselect = this.marqueeSelect();
if (!e.shiftKey) {
@@ -209,6 +210,11 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const docs = mselect.length ? mselect : [this.props.Document];
this.props.selectDocuments(docs, []);
}
+ const hideMarquee = () => {
+ this.hideMarquee();
+ MarqueeOptionsMenu.Instance.fadeOut(true);
+ document.removeEventListener("pointerdown", hideMarquee);
+ };
if (!this._commandExecuted && (Math.abs(this.Bounds.height * this.Bounds.width) > 100)) {
MarqueeOptionsMenu.Instance.createCollection = this.collection;
MarqueeOptionsMenu.Instance.delete = this.delete;
@@ -217,17 +223,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
MarqueeOptionsMenu.Instance.showMarquee = this.showMarquee;
MarqueeOptionsMenu.Instance.hideMarquee = this.hideMarquee;
MarqueeOptionsMenu.Instance.jumpTo(e.clientX, e.clientY);
+ document.addEventListener("pointerdown", hideMarquee);
+ } else {
+ this.hideMarquee();
}
this.cleanupInteractions(true, this._commandExecuted);
- const hideMarquee = () => {
- this.hideMarquee();
- MarqueeOptionsMenu.Instance.fadeOut(true);
- document.removeEventListener("pointerdown", hideMarquee);
- };
- document.addEventListener("pointerdown", hideMarquee);
-
- if (e.altKey) {
+ if (e.altKey || MarqueeView.DragMarquee) {
e.preventDefault();
}
}
@@ -300,10 +302,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
@action
delete = () => {
- this.marqueeSelect(false).map(d => this.props.removeDocument(d));
- if (this.ink) {
- // this.marqueeInkDelete(this.ink.inkData);
- }
+ this.props.removeDocument(this.marqueeSelect(false));
SelectionManager.DeselectAll();
this.cleanupInteractions(false);
MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -349,13 +348,14 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const bounds = this.Bounds;
const selected = this.marqueeSelect(false);
if (e instanceof KeyboardEvent ? e.key === "c" : true) {
- selected.map(d => {
- this.props.removeDocument(d);
+ selected.map(action(d => {
+ //this.props.removeDocument(d);
d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
d.displayTimecode = undefined; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
return d;
- });
+ }));
+ this.props.removeDocument(selected);
}
const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t" ? Docs.Create.StackingDocument : undefined);
this.props.addDocument(newCollection);
@@ -551,7 +551,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
marqueeSelect(selectBackgrounds: boolean = true) {
const selRect = this.Bounds;
const selection: Doc[] = [];
- this.props.activeDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => {
+ this.props.activeDocuments().filter(doc => !doc.isBackground && !doc.z).map(doc => {
const layoutDoc = Doc.Layout(doc);
const x = NumCast(doc.x);
const y = NumCast(doc.y);
@@ -613,7 +613,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
render() {
return <div className="marqueeView"
- style={{ overflow: StrCast(this.props.Document._overflow), }}
+ style={{ overflow: StrCast(this.props.Document._overflow), cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" }}
onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}>
{this._visible ? this.marqueeDiv : null}
{this.props.children}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 38b16e184..c0e1a0232 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -1,10 +1,10 @@
import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from "react";
-import { Doc } from '../../../../new_fields/Doc';
-import { documentSchema } from '../../../../new_fields/documentSchemas';
-import { makeInterface } from '../../../../new_fields/Schema';
-import { BoolCast, NumCast, ScriptCast, StrCast, Cast } from '../../../../new_fields/Types';
+import { Doc } from '../../../../fields/Doc';
+import { documentSchema } from '../../../../fields/documentSchemas';
+import { makeInterface } from '../../../../fields/Schema';
+import { BoolCast, NumCast, ScriptCast, StrCast, Cast } from '../../../../fields/Types';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
@@ -13,7 +13,7 @@ import { CollectionSubView } from '../CollectionSubView';
import "./collectionMulticolumnView.scss";
import ResizeBar from './MulticolumnResizer';
import WidthLabel from './MulticolumnWidthLabel';
-import { List } from '../../../../new_fields/List';
+import { List } from '../../../../fields/List';
import { returnZero, returnFalse, returnOne } from '../../../../Utils';
type MulticolumnDocument = makeInterface<[typeof documentSchema]>;
@@ -46,12 +46,12 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
*/
@computed
private get ratioDefinedDocs() {
- return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout.dimUnit, "*") === DimUnit.Ratio);
+ return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
}
/**
- * This loops through all childLayoutPairs and extracts the values for dimUnit
- * and dimMagnitude, ignoring any that are malformed. Additionally, it then
+ * This loops through all childLayoutPairs and extracts the values for _dimUnit
+ * and _dimMagnitude, ignoring any that are malformed. Additionally, it then
* normalizes the ratio values so that one * value is always 1, with the remaining
* values proportionate to that easily readable metric.
* @returns the list of the resolved width specifiers (unit and magnitude pairs)
@@ -62,8 +62,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
let starSum = 0;
const widthSpecifiers: WidthSpecifier[] = [];
this.childLayoutPairs.map(pair => {
- const unit = StrCast(pair.layout.dimUnit, "*");
- const magnitude = NumCast(pair.layout.dimMagnitude, 1);
+ const unit = StrCast(pair.layout._dimUnit, "*");
+ const magnitude = NumCast(pair.layout._dimMagnitude, 1);
if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
(unit === DimUnit.Ratio) && (starSum += magnitude);
widthSpecifiers.push({ magnitude, unit });
@@ -83,9 +83,9 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
setTimeout(() => {
const { ratioDefinedDocs } = this;
if (this.childLayoutPairs.length) {
- const minimum = Math.min(...ratioDefinedDocs.map(doc => NumCast(doc.dimMagnitude, 1)));
+ const minimum = Math.min(...ratioDefinedDocs.map(doc => NumCast(doc._dimMagnitude, 1)));
if (minimum !== 0) {
- ratioDefinedDocs.forEach(layout => layout.dimMagnitude = NumCast(layout.dimMagnitude, 1) / minimum, 1);
+ ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum, 1);
}
}
});
@@ -161,8 +161,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
if (columnUnitLength === undefined) {
return 0; // we're still waiting on promises to resolve
}
- let width = NumCast(layout.dimMagnitude, 1);
- if (StrCast(layout.dimUnit, "*") === DimUnit.Ratio) {
+ let width = NumCast(layout._dimMagnitude, 1);
+ if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
width *= columnUnitLength;
}
return width;
@@ -194,8 +194,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
if (super.onInternalDrop(e, de)) {
de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- d.dimUnit = "*";
- d.dimMagnitude = 1;
+ d._dimUnit = "*";
+ d._dimMagnitude = 1;
}));
}
return false;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index b55b67a9e..602246d07 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -1,10 +1,10 @@
import { observer } from 'mobx-react';
-import { makeInterface } from '../../../../new_fields/Schema';
-import { documentSchema } from '../../../../new_fields/documentSchemas';
+import { makeInterface } from '../../../../fields/Schema';
+import { documentSchema } from '../../../../fields/documentSchemas';
import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView';
import * as React from "react";
-import { Doc } from '../../../../new_fields/Doc';
-import { NumCast, StrCast, BoolCast, ScriptCast } from '../../../../new_fields/Types';
+import { Doc } from '../../../../fields/Doc';
+import { NumCast, StrCast, BoolCast, ScriptCast } from '../../../../fields/Types';
import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
import { Utils, returnZero, returnFalse, returnOne } from '../../../../Utils';
import "./collectionMultirowView.scss";
@@ -14,7 +14,7 @@ import HeightLabel from './MultirowHeightLabel';
import ResizeBar from './MultirowResizer';
import { undoBatch } from '../../../util/UndoManager';
import { DragManager, dropActionType } from '../../../util/DragManager';
-import { List } from '../../../../new_fields/List';
+import { List } from '../../../../fields/List';
type MultirowDocument = makeInterface<[typeof documentSchema]>;
const MultirowDocument = makeInterface(documentSchema);
@@ -46,12 +46,12 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
*/
@computed
private get ratioDefinedDocs() {
- return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout.dimUnit, "*") === DimUnit.Ratio);
+ return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
}
/**
- * This loops through all childLayoutPairs and extracts the values for dimUnit
- * and dimUnit, ignoring any that are malformed. Additionally, it then
+ * This loops through all childLayoutPairs and extracts the values for _dimUnit
+ * and _dimUnit, ignoring any that are malformed. Additionally, it then
* normalizes the ratio values so that one * value is always 1, with the remaining
* values proportionate to that easily readable metric.
* @returns the list of the resolved width specifiers (unit and magnitude pairs)
@@ -62,8 +62,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
let starSum = 0;
const heightSpecifiers: HeightSpecifier[] = [];
this.childLayoutPairs.map(pair => {
- const unit = StrCast(pair.layout.dimUnit, "*");
- const magnitude = NumCast(pair.layout.dimMagnitude, 1);
+ const unit = StrCast(pair.layout._dimUnit, "*");
+ const magnitude = NumCast(pair.layout._dimMagnitude, 1);
if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
(unit === DimUnit.Ratio) && (starSum += magnitude);
heightSpecifiers.push({ magnitude, unit });
@@ -83,9 +83,9 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
setTimeout(() => {
const { ratioDefinedDocs } = this;
if (this.childLayoutPairs.length) {
- const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout.dimMagnitude, 1)));
+ const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout._dimMagnitude, 1)));
if (minimum !== 0) {
- ratioDefinedDocs.forEach(layout => layout.dimMagnitude = NumCast(layout.dimMagnitude, 1) / minimum);
+ ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum);
}
}
});
@@ -161,8 +161,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
if (rowUnitLength === undefined) {
return 0; // we're still waiting on promises to resolve
}
- let height = NumCast(layout.dimMagnitude, 1);
- if (StrCast(layout.dimUnit, "*") === DimUnit.Ratio) {
+ let height = NumCast(layout._dimMagnitude, 1);
+ if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
height *= rowUnitLength;
}
return height;
@@ -194,8 +194,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
if (super.onInternalDrop(e, de)) {
de.complete.docDragData?.droppedDocuments.forEach(action((d: Doc) => {
- d.dimUnit = "*";
- d.dimMagnitude = 1;
+ d._dimUnit = "*";
+ d._dimMagnitude = 1;
}));
}
return false;
diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
index e1e604686..734915a93 100644
--- a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
@@ -1,8 +1,8 @@
import * as React from "react";
import { observer } from "mobx-react";
import { observable, action } from "mobx";
-import { Doc } from "../../../../new_fields/Doc";
-import { NumCast, StrCast } from "../../../../new_fields/Types";
+import { Doc } from "../../../../fields/Doc";
+import { NumCast, StrCast } from "../../../../fields/Types";
import { DimUnit } from "./CollectionMulticolumnView";
import { UndoManager } from "../../../util/UndoManager";
@@ -43,12 +43,12 @@ export default class ResizeBar extends React.Component<ResizerProps> {
const unitLength = columnUnitLength();
if (unitLength) {
if (toNarrow) {
- const scale = StrCast(toNarrow.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
- toNarrow.dimMagnitude = Math.max(0.05, NumCast(toNarrow.dimMagnitude, 1) - Math.abs(movementX) / scale);
+ const scale = StrCast(toNarrow._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
+ toNarrow._dimMagnitude = Math.max(0.05, NumCast(toNarrow._dimMagnitude, 1) - Math.abs(movementX) / scale);
}
if (toWiden) {
- const scale = StrCast(toWiden.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
- toWiden.dimMagnitude = Math.max(0.05, NumCast(toWiden.dimMagnitude, 1) + Math.abs(movementX) / scale);
+ const scale = StrCast(toWiden._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
+ toWiden._dimMagnitude = Math.max(0.05, NumCast(toWiden._dimMagnitude, 1) + Math.abs(movementX) / scale);
}
}
}
@@ -56,17 +56,17 @@ export default class ResizeBar extends React.Component<ResizerProps> {
private get isActivated() {
const { toLeft, toRight } = this.props;
if (toLeft && toRight) {
- if (StrCast(toLeft.dimUnit, "*") === DimUnit.Pixel && StrCast(toRight.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toLeft._dimUnit, "*") === DimUnit.Pixel && StrCast(toRight._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;
} else if (toLeft) {
- if (StrCast(toLeft.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toLeft._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;
} else if (toRight) {
- if (StrCast(toRight.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toRight._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;
diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx
index 5b2054428..9985a9fba 100644
--- a/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx
@@ -1,8 +1,8 @@
import * as React from "react";
import { observer } from "mobx-react";
import { computed } from "mobx";
-import { Doc } from "../../../../new_fields/Doc";
-import { NumCast, StrCast, BoolCast } from "../../../../new_fields/Types";
+import { Doc } from "../../../../fields/Doc";
+import { NumCast, StrCast, BoolCast } from "../../../../fields/Types";
import { EditableView } from "../../EditableView";
import { DimUnit } from "./CollectionMulticolumnView";
diff --git a/src/client/views/collections/collectionMulticolumn/MultirowHeightLabel.tsx b/src/client/views/collections/collectionMulticolumn/MultirowHeightLabel.tsx
index 899577fd5..aa5439fa4 100644
--- a/src/client/views/collections/collectionMulticolumn/MultirowHeightLabel.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MultirowHeightLabel.tsx
@@ -1,8 +1,8 @@
import * as React from "react";
import { observer } from "mobx-react";
import { computed } from "mobx";
-import { Doc } from "../../../../new_fields/Doc";
-import { NumCast, StrCast, BoolCast } from "../../../../new_fields/Types";
+import { Doc } from "../../../../fields/Doc";
+import { NumCast, StrCast, BoolCast } from "../../../../fields/Types";
import { EditableView } from "../../EditableView";
import { DimUnit } from "./CollectionMultirowView";
diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
index 9df8cc3e2..d0bc4d01c 100644
--- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
@@ -1,8 +1,8 @@
import * as React from "react";
import { observer } from "mobx-react";
import { observable, action } from "mobx";
-import { Doc } from "../../../../new_fields/Doc";
-import { NumCast, StrCast } from "../../../../new_fields/Types";
+import { Doc } from "../../../../fields/Doc";
+import { NumCast, StrCast } from "../../../../fields/Types";
import { DimUnit } from "./CollectionMultirowView";
import { UndoManager } from "../../../util/UndoManager";
@@ -41,12 +41,12 @@ export default class ResizeBar extends React.Component<ResizerProps> {
const unitLength = columnUnitLength();
if (unitLength) {
if (toNarrow) {
- const scale = StrCast(toNarrow.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
- toNarrow.dimMagnitude = Math.max(0.05, NumCast(toNarrow.dimMagnitude, 1) - Math.abs(movementY) / scale);
+ const scale = StrCast(toNarrow._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
+ toNarrow._dimMagnitude = Math.max(0.05, NumCast(toNarrow._dimMagnitude, 1) - Math.abs(movementY) / scale);
}
if (toWiden) {
- const scale = StrCast(toWiden.dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
- toWiden.dimMagnitude = Math.max(0.05, NumCast(toWiden.dimMagnitude, 1) + Math.abs(movementY) / scale);
+ const scale = StrCast(toWiden._dimUnit, "*") === DimUnit.Ratio ? unitLength : 1;
+ toWiden._dimMagnitude = Math.max(0.05, NumCast(toWiden._dimMagnitude, 1) + Math.abs(movementY) / scale);
}
}
}
@@ -54,17 +54,17 @@ export default class ResizeBar extends React.Component<ResizerProps> {
private get isActivated() {
const { toTop, toBottom } = this.props;
if (toTop && toBottom) {
- if (StrCast(toTop.dimUnit, "*") === DimUnit.Pixel && StrCast(toBottom.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toTop._dimUnit, "*") === DimUnit.Pixel && StrCast(toBottom._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;
} else if (toTop) {
- if (StrCast(toTop.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toTop._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;
} else if (toBottom) {
- if (StrCast(toBottom.dimUnit, "*") === DimUnit.Pixel) {
+ if (StrCast(toBottom._dimUnit, "*") === DimUnit.Pixel) {
return false;
}
return true;