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.tsx17
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx2
-rw-r--r--src/client/views/collections/CollectionMapView.tsx8
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx170
-rw-r--r--src/client/views/collections/CollectionPileView.scss8
-rw-r--r--src/client/views/collections/CollectionPileView.tsx127
-rw-r--r--src/client/views/collections/CollectionSchemaMovableTableHOC.tsx2
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx8
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx7
-rw-r--r--src/client/views/collections/CollectionSubView.tsx28
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx3
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx36
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/collections/CollectionViewChromes.scss11
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx164
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss9
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx125
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx20
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx31
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx31
22 files changed, 500 insertions, 322 deletions
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 9e7248db2..eda8e5684 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -11,7 +11,7 @@ import "./CollectionCarouselView.scss";
import { CollectionSubView } from './CollectionSubView';
import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons';
import { Doc } from '../../../new_fields/Doc';
-import { FormattedTextBox } from '../nodes/FormattedTextBox';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { ContextMenu } from '../ContextMenu';
import { ObjectField } from '../../../new_fields/ObjectField';
@@ -27,7 +27,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
this._dropDisposer?.();
if (ele) {
- this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+ this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
}
}
@@ -47,13 +47,22 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
<>
<div className="collectionCarouselView-image" key="image">
<ContentFittingDocumentView {...this.props}
+ renderDepth={this.props.renderDepth + 1}
Document={this.childLayoutPairs[index].layout}
DataDocument={this.childLayoutPairs[index].data}
PanelHeight={this.panelHeight}
getTransform={this.props.ScreenToLocalTransform} />
</div>
- <div className="collectionCarouselView-caption" key="caption" style={{ background: this.props.backgroundColor?.(this.props.Document) }}>
- <FormattedTextBox key={index} {...this.props} Document={this.childLayoutPairs[index].layout} DataDoc={undefined} fieldKey={"caption"}></FormattedTextBox>
+ <div className="collectionCarouselView-caption" key="caption"
+ style={{
+ background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.backgroundColor?.(this.props.Document)),
+ color: StrCast(this.layoutDoc._captionColor, StrCast(this.layoutDoc.color)),
+ borderRadius: StrCast(this.layoutDoc._captionBorderRounding),
+ }}>
+ <FormattedTextBox key={index} {...this.props}
+ xMargin={NumCast(this.layoutDoc["caption-xMargin"])}
+ yMargin={NumCast(this.layoutDoc["caption-yMargin"])}
+ Document={this.childLayoutPairs[index].layout} DataDoc={undefined} fieldKey={"caption"}></FormattedTextBox>
</div>
</>;
}
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index cb0206260..344dca23a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -64,7 +64,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
this._dropDisposer && this._dropDisposer();
if (ele) {
- this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+ this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
}
}
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
index 7b7828d7d..971224482 100644
--- a/src/client/views/collections/CollectionMapView.tsx
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -1,4 +1,4 @@
-import { GoogleApiWrapper, Map as GeoMap, MapProps, Marker } from "google-maps-react";
+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";
@@ -42,7 +42,7 @@ const query = async (data: string | google.maps.LatLngLiteral) => {
};
@observer
-class CollectionMapView extends CollectionSubView<MapSchema, Partial<MapProps> & { google: any }>(MapSchema) {
+class CollectionMapView extends CollectionSubView<MapSchema, Partial<IMapProps> & { google: any }>(MapSchema) {
private _cancelAddrReq = new Map<string, boolean>();
private _cancelLocReq = new Map<string, boolean>();
@@ -221,7 +221,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<MapProps> &
zoom={center.zoom || 10}
initialCenter={center}
center={center}
- onIdle={(_props?: MapProps, map?: google.maps.Map) => {
+ onIdle={(_props?: IMapProps, map?: google.maps.Map) => {
if (this.layoutDoc.lockedTransform) {
// reset zoom (ideally, we could probably can tell the map to disallow zooming somehow instead)
map?.setZoom(center?.zoom || 10);
@@ -233,7 +233,7 @@ class CollectionMapView extends CollectionSubView<MapSchema, Partial<MapProps> &
}))();
}
}}
- onDragend={(_props?: MapProps, map?: google.maps.Map) => {
+ onDragend={(_props?: IMapProps, map?: google.maps.Map) => {
if (this.layoutDoc.lockedTransform) {
// reset the drag (ideally, we could probably can tell the map to disallow dragging somehow instead)
map?.setCenter({ lat: center?.lat!, lng: center?.lng! });
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index b272151c1..7ad15ef41 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -2,14 +2,13 @@ import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
import { faPalette } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import Measure from "react-measure";
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 { numberRange } from "../../../Utils";
+import { numberRange, setupMoveUpEvents, emptyFunction } from "../../../Utils";
import { Docs } from "../../documents/Documents";
import { DragManager } from "../../util/DragManager";
import { CompileScript } from "../../util/Scripting";
@@ -45,39 +44,44 @@ interface CMVFieldRowProps {
export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> {
@observable private _background = "inherit";
@observable private _createAliasSelected: boolean = false;
- @observable private _collapsed: boolean = false;
- @observable private _headingsHack: number = 1;
- @observable private _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
- @observable private _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+ @observable private heading: string = "";
+ @observable private color: string = "#f1efeb";
+ @observable private collapsed: boolean = false;
+ private set _heading(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.heading = this.heading = value)); }
+ private set _color(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.color = this.color = value)); }
+ private set _collapsed(value: boolean) { runInAction(() => this.props.headingObject && (this.props.headingObject.collapsed = this.collapsed = value)); }
private _dropDisposer?: DragManager.DragDropDisposer;
private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
- private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 };
private _contRef: React.RefObject<HTMLDivElement> = React.createRef();
- private _sensitivity: number = 16;
- private _counter: number = 0;
private _ele: any;
createRowDropRef = (ele: HTMLDivElement | null) => {
- this._dropDisposer && this._dropDisposer();
+ this._dropDisposer?.();
if (ele) {
this._ele = ele;
this.props.observeHeight(ele);
this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this));
}
}
+ @action
+ componentDidMount() {
+ this.heading = this.props.headingObject?.heading || "";
+ this.color = this.props.headingObject?.color || "#f1efeb";
+ this.collapsed = this.props.headingObject?.collapsed || false;
+ }
componentWillUnmount() {
this.props.unobserveHeight(this._ele);
}
getTrueHeight = () => {
- if (this._collapsed) {
- this.props.setDocHeight(this._heading, 20);
+ if (this.collapsed) {
+ this.props.setDocHeight(this.heading, 20);
} else {
const rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; //+ 15 accounts for the group header
const transformScale = this.props.screenToLocalTransform().Scale;
const trueHeight = rawHeight * transformScale;
- this.props.setDocHeight(this._heading, trueHeight);
+ this.props.setDocHeight(this.heading, trueHeight);
}
}
@@ -89,7 +93,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
(this.props.parent.Document.dropConverter instanceof ScriptField) &&
this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData });
const key = StrCast(this.props.parent.props.Document._pivotField);
- const castedValue = this.getValue(this._heading);
+ const castedValue = this.getValue(this.heading);
de.complete.docDragData.droppedDocuments.forEach(d => d[key] = castedValue);
this.props.parent.onInternalDrop(e, de);
e.stopPropagation();
@@ -116,10 +120,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
}
}
this.props.docList.forEach(d => d[key] = castedValue);
- if (this.props.headingObject) {
- this.props.headingObject.setHeading(castedValue.toString());
- this._heading = this.props.headingObject.heading;
- }
+ this._heading = castedValue.toString();
return true;
}
return false;
@@ -128,10 +129,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
@action
changeColumnColor = (color: string) => {
this._createAliasSelected = false;
- if (this.props.headingObject) {
- this.props.headingObject.setColor(color);
- this._color = color;
- }
+ this._color = color;
}
pointerEnteredRow = action(() => SelectionManager.GetIsDragging() && (this._background = "#b4b4b4"));
@@ -140,7 +138,6 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
pointerLeaveRow = () => {
this._createAliasSelected = false;
this._background = "inherit";
- document.removeEventListener("pointermove", this.startDrag);
}
@action
@@ -164,62 +161,36 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
}));
@action
- collapseSection = () => {
+ collapseSection = (e: any) => {
this._createAliasSelected = false;
- if (this.props.headingObject) {
- this._headingsHack++;
- this.props.headingObject.setCollapsed(!this.props.headingObject.collapsed);
- this.toggleVisibility();
- }
+ this.toggleVisibility();
+ e.stopPropagation();
}
- startDrag = (e: PointerEvent) => {
- const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
- if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
- const alias = Doc.MakeAlias(this.props.parent.props.Document);
- const key = StrCast(this.props.parent.props.Document._pivotField);
- let value = this.getValue(this._heading);
- value = typeof value === "string" ? `"${value}"` : value;
- const script = `return doc.${key} === ${value}`;
- const compiled = CompileScript(script, { params: { doc: Doc.name } });
- if (compiled.compiled) {
- alias.viewSpecScript = new ScriptField(compiled);
- DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
- }
-
- e.stopPropagation();
- document.removeEventListener("pointermove", this.startDrag);
- document.removeEventListener("pointerup", this.pointerUp);
+ headerMove = (e: PointerEvent) => {
+ const alias = Doc.MakeAlias(this.props.parent.props.Document);
+ const key = StrCast(this.props.parent.props.Document._pivotField);
+ let value = this.getValue(this.heading);
+ value = typeof value === "string" ? `"${value}"` : value;
+ const script = `return doc.${key} === ${value}`;
+ const compiled = CompileScript(script, { params: { doc: Doc.name } });
+ if (compiled.compiled) {
+ alias.viewSpecScript = new ScriptField(compiled);
+ DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
}
- }
-
- pointerUp = (e: PointerEvent) => {
- e.stopPropagation();
- e.preventDefault();
-
- document.removeEventListener("pointermove", this.startDrag);
- document.removeEventListener("pointerup", this.pointerUp);
+ return true;
}
@action
headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
- e.stopPropagation();
- e.preventDefault();
-
- const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY);
- this._startDragPosition = { x: dx, y: dy };
-
- if (this._createAliasSelected) {
- document.removeEventListener("pointermove", this.startDrag);
- document.addEventListener("pointermove", this.startDrag);
- document.removeEventListener("pointerup", this.pointerUp);
- document.addEventListener("pointerup", this.pointerUp);
+ if (e.button === 0 && !e.ctrlKey) {
+ setupMoveUpEvents(this, e, this.headerMove, emptyFunction, () => (this.props.parent.props.Document._chromeStatus === "disabled") && this.collapseSection(e));
+ this._createAliasSelected = false;
}
- this._createAliasSelected = false;
}
renderColorPicker = () => {
- const selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+ const selected = this.color;
const pink = PastelSchemaPalette.get("pink2");
const purple = PastelSchemaPalette.get("purple4");
@@ -249,7 +220,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
}
toggleAlias = action(() => this._createAliasSelected = true);
- toggleVisibility = action(() => this._collapsed = !this._collapsed);
+ toggleVisibility = () => this._collapsed = !this.collapsed;
renderMenu = () => {
const selected = this._createAliasSelected;
@@ -261,27 +232,19 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
</div>);
}
- handleResize = (size: any) => {
- if (++this._counter !== 1) {
- this.getTrueHeight();
- }
- }
-
@computed get contentLayout() {
const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap))));
const style = this.props.parent;
- const collapsed = this._collapsed;
const chromeStatus = this.props.parent.props.Document._chromeStatus;
const newEditableViewProps = {
GetValue: () => "",
SetValue: this.addDocument,
contents: "+ NEW",
HeadingObject: this.props.headingObject,
- HeadingsHack: this._headingsHack,
toggle: this.toggleVisibility,
- color: this._color
+ color: this.color
};
- return collapsed ? (null) :
+ return this.collapsed ? (null) :
<div style={{ position: "relative" }}>
{(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ?
<div className="collectionStackingView-addDocumentButton"
@@ -307,18 +270,17 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
}
@computed get headingView() {
- const heading = this._heading;
+ const noChrome = this.props.parent.props.Document._chromeStatus === "disabled";
const key = StrCast(this.props.parent.props.Document._pivotField);
- const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
+ const evContents = this.heading ? this.heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
const headerEditableViewProps = {
GetValue: () => evContents,
SetValue: this.headingChanged,
contents: evContents,
oneLine: true,
HeadingObject: this.props.headingObject,
- HeadingsHack: this._headingsHack,
toggle: this.toggleVisibility,
- color: this._color
+ color: this.color
};
return this.props.parent.props.Document.miniHeaders ?
<div className="collectionStackingView-miniHeader">
@@ -329,9 +291,9 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
<div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
title={evContents === `NO ${key.toUpperCase()} VALUE` ?
`Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
- style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : "lightgrey" }}>
- <EditableView {...headerEditableViewProps} />
- {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
+ style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : "lightgrey" }}>
+ {noChrome ? evContents : <EditableView {...headerEditableViewProps} />}
+ {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
<div className="collectionStackingView-sectionColor">
<Flyout anchorPoint={anchorPoints.CENTER_RIGHT} content={this.renderColorPicker()}>
<button className="collectionStackingView-sectionColorButton">
@@ -340,10 +302,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
</ Flyout >
</div>
}
- <button className="collectionStackingView-sectionDelete" onClick={this.collapseSection}>
- <FontAwesomeIcon icon={this._collapsed ? "chevron-down" : "chevron-up"} size="lg" />
- </button>
- {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
+ {noChrome ? (null) : <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}>
+ <FontAwesomeIcon icon={this.collapsed ? "chevron-down" : "chevron-up"} size="lg" />
+ </button>}
+ {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
<div className="collectionStackingView-sectionOptions">
<Flyout anchorPoint={anchorPoints.TOP_RIGHT} content={this.renderMenu()}>
<button className="collectionStackingView-sectionOptionButton">
@@ -356,23 +318,15 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
</div>;
}
render() {
- const background = this._background; //to account for observables in Measure
- const contentlayout = this.contentLayout;
- const headingview = this.headingView;
- return <Measure offset onResize={this.handleResize}>
- {({ measureRef }) => {
- return <div ref={measureRef}>
- <div className="collectionStackingView-masonrySection"
- style={{ width: this.props.parent.NodeWidth, background }}
- ref={this.createRowDropRef}
- onPointerEnter={this.pointerEnteredRow}
- onPointerLeave={this.pointerLeaveRow}
- >
- {headingview}
- {contentlayout}
- </div >
- </div>;
- }}
- </Measure>;
+ const background = this._background;
+ return <div className="collectionStackingView-masonrySection"
+ style={{ width: this.props.parent.NodeWidth, background }}
+ ref={this.createRowDropRef}
+ onPointerEnter={this.pointerEnteredRow}
+ onPointerLeave={this.pointerLeaveRow}
+ >
+ {this.headingView}
+ {this.contentLayout}
+ </div >;
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionPileView.scss b/src/client/views/collections/CollectionPileView.scss
new file mode 100644
index 000000000..ac874b663
--- /dev/null
+++ b/src/client/views/collections/CollectionPileView.scss
@@ -0,0 +1,8 @@
+.collectionPileView {
+ display: flex;
+ flex-direction: row;
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ overflow: visible;
+}
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
new file mode 100644
index 000000000..3bbfcc4d7
--- /dev/null
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -0,0 +1,127 @@
+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 { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from "../ContextMenuItem";
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { CollectionSubView } from "./CollectionSubView";
+import "./CollectionPileView.scss";
+import React = require("react");
+import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../../Utils";
+import { SelectionManager } from "../../util/SelectionManager";
+import { UndoManager } from "../../util/UndoManager";
+
+@observer
+export class CollectionPileView extends CollectionSubView(doc => doc) {
+ _lastTap = 0;
+ _doubleTap: boolean | undefined = false;
+ _originalChrome: string = "";
+ @observable _contentsActive = true;
+ @observable _layoutEngine = "pass";
+ @observable _collapsed: boolean = false;
+ @observable _childClickedScript: Opt<ScriptField>;
+ componentDidMount() {
+ this._originalChrome = StrCast(this.layoutDoc._chromeStatus);
+ this.layoutDoc._chromeStatus = "disabled";
+ this.layoutDoc.hideFilterView = true;
+ }
+ componentWillUnmount() {
+ this.layoutDoc.hideFilterView = false;
+ this.layoutDoc._chromeStatus = this._originalChrome;
+ }
+
+ layoutEngine = () => this._layoutEngine;
+
+ @computed get contents() {
+ return <div className="collectionPileView-innards" style={{
+ width: "100%",
+ pointerEvents: this.layoutEngine() !== "pass" && (this.props.active() || this.layoutEngine() === "starburst") ? undefined : "none"
+ }} >
+ <CollectionFreeFormView {...this.props} layoutEngine={this.layoutEngine} />
+ </div>;
+ }
+
+ specificMenu = (e: React.MouseEvent) => {
+ const layoutItems: ContextMenuProps[] = [];
+ const doc = this.props.Document;
+
+ ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" });
+ }
+
+ toggleStarburst = action(() => {
+ if (this._layoutEngine === 'starburst') {
+ const defaultSize = 110;
+ this.layoutDoc.overflow = undefined;
+ this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - NumCast(this.layoutDoc._starburstPileWidth, defaultSize) / 2;
+ this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - NumCast(this.layoutDoc._starburstPileHeight, defaultSize) / 2;
+ this.layoutDoc._width = NumCast(this.layoutDoc._starburstPileWidth, defaultSize);
+ this.layoutDoc._height = NumCast(this.layoutDoc._starburstPileHeight, defaultSize);
+ this._layoutEngine = 'pass';
+ } else {
+ const defaultSize = 25;
+ this.layoutDoc.overflow = 'visible';
+ !this.layoutDoc._starburstRadius && (this.layoutDoc._starburstRadius = 500);
+ !this.layoutDoc._starburstDocScale && (this.layoutDoc._starburstDocScale = 2.5);
+ if (this._layoutEngine === 'pass') {
+ this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - defaultSize / 2;
+ this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - defaultSize / 2;
+ this.layoutDoc._starburstPileWidth = this.layoutDoc[WidthSym]();
+ this.layoutDoc._starburstPileHeight = this.layoutDoc[HeightSym]();
+ }
+ this.layoutDoc._width = this.layoutDoc._height = defaultSize;
+ this._layoutEngine = 'starburst';
+ }
+ });
+
+ _undoBatch: UndoManager.Batch | undefined;
+ pointerDown = (e: React.PointerEvent) => {
+ let dist = 0;
+ SelectionManager.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)) {
+ dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]);
+ if (dist > 100) {
+ if (!this._undoBatch) {
+ this._undoBatch = UndoManager.StartBatch("layout pile");
+ }
+ const doc = this.childDocs[0];
+ doc.x = e.clientX;
+ doc.y = e.clientY;
+ this.props.addDocTab(doc, "inParent") && this.props.removeDocument(doc);
+ dist = 0;
+ }
+ }
+ return false;
+ }, () => {
+ this._undoBatch?.end();
+ this._undoBatch = undefined;
+ SelectionManager.SetIsDragging(false);
+ if (!this.childDocs.length) {
+ this.props.ContainingCollectionView?.removeDocument(this.props.Document);
+ }
+ }, emptyFunction, false, this.layoutEngine() === "pass" && this.props.isSelected(true)); // this sets _doubleTap
+ }
+
+ onClick = (e: React.MouseEvent) => {
+ if (e.button === 0 && (this._doubleTap || this.layoutEngine() === "starburst")) {
+ SelectionManager.DeselectAll();
+ this.toggleStarburst();
+ e.stopPropagation();
+ }
+ // else if (this.layoutEngine() === "pass") {
+ // runInAction(() => this._contentsActive = false);
+ // setTimeout(action(() => this._contentsActive = true), 300);
+ // }
+ }
+
+ render() {
+
+ return <div className={"collectionPileView"} onContextMenu={this.specificMenu} onClick={this.onClick} onPointerDown={this.pointerDown}
+ style={{ width: this.props.PanelWidth(), height: `calc(100% - ${this.props.Document._chromeStatus === "enabled" ? 51 : 0}px)` }}>
+ {this.contents}
+ </div>;
+ }
+}
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 670d6dbb2..972714e34 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -54,7 +54,7 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
}
createColDropTarget = (ele: HTMLDivElement) => {
- this._colDropDisposer && this._colDropDisposer();
+ this._colDropDisposer?.();
if (ele) {
this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this));
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 24a3119cc..e3720bf01 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -49,7 +49,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
@computed get columnWidth() {
TraceMobx();
return Math.min(this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin,
- this.isStackingView ? Number.MAX_VALUE : NumCast(this.props.Document.columnWidth, 250));
+ this.isStackingView ? Number.MAX_VALUE : this.props.Document.columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.props.Document.columnWidth, 250));
}
@computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; }
@@ -189,8 +189,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
active={this.props.active}
whenActiveChanged={this.props.whenActiveChanged}
addDocTab={this.addDocTab}
- pinToPres={this.props.pinToPres}>
- </ContentFittingDocumentView>;
+ pinToPres={this.props.pinToPres}
+ />;
}
getDocWidth(d?: Doc) {
@@ -303,7 +303,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
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 && !SelectionManager.GetIsDragging()) {
- Doc.Layout(doc)._height = Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))));
+ Doc.Layout(doc)._height = Math.min(1200, Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", "")))));
}
}));
this.observer.observe(ref);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 5d926b7c7..323d7be25 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -156,7 +156,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@action
collapseSection = () => {
if (this.props.headingObject) {
- this._headingsHack++;
this.props.headingObject.setCollapsed(!this.props.headingObject.collapsed);
this.toggleVisibility();
}
@@ -225,8 +224,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
private toggleVisibility = action(() => this.collapsed = !this.collapsed);
- @observable _headingsHack: number = 1;
-
menuCallback = (x: number, y: number) => {
ContextMenu.Instance.clearItems();
const layoutItems: ContextMenuProps[] = [];
@@ -300,7 +297,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
contents: evContents,
oneLine: true,
HeadingObject: this.props.headingObject,
- HeadingsHack: this._headingsHack,
toggle: this.toggleVisibility,
color: this._color
};
@@ -309,7 +305,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
SetValue: this.addDocument,
contents: "+ NEW",
HeadingObject: this.props.headingObject,
- HeadingsHack: this._headingsHack,
toggle: this.toggleVisibility,
color: this._color
};
@@ -364,7 +359,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: SelectionManager.GetIsDragging() ? "100%" : undefined,
+ height: undefined, // SelectionManager.GetIsDragging() ? "100%" : undefined,
background: this._background
}}
ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 78ba3d6e6..1bfd408f8 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,30 +1,30 @@
import { action, computed, IReactionDisposer, reaction } from "mobx";
+import { basename } from 'path';
import CursorField from "../../../new_fields/CursorField";
-import { Doc, DocListCast, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
+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, StrCast } from "../../../new_fields/Types";
+import { Cast } from "../../../new_fields/Types";
+import { GestureUtils } from "../../../pen-gestures/GestureUtils";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
+import { Upload } from "../../../server/SharedMediaTypes";
import { Utils } from "../../../Utils";
+import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils";
import { DocServer } from "../../DocServer";
-import { DocumentType } from "../../documents/DocumentTypes";
import { Docs, DocumentOptions } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { Networking } from "../../Network";
import { DragManager } from "../../util/DragManager";
+import { ImageUtils } from "../../util/Import & Export/ImageUtils";
+import { InteractionUtils } from "../../util/InteractionUtils";
import { undoBatch, UndoManager } from "../../util/UndoManager";
import { DocComponent } from "../DocComponent";
import { FieldViewProps } from "../nodes/FieldView";
-import { FormattedTextBox, GoogleRef } from "../nodes/FormattedTextBox";
+import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTextBox";
import { CollectionView } from "./CollectionView";
import React = require("react");
-import { basename } from 'path';
-import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils";
-import { ImageUtils } from "../../util/Import & Export/ImageUtils";
-import { Networking } from "../../Network";
-import { GestureUtils } from "../../../pen-gestures/GestureUtils";
-import { InteractionUtils } from "../../util/InteractionUtils";
-import { Upload } from "../../../server/SharedMediaTypes";
export interface CollectionViewProps extends FieldViewProps {
addDocument: (document: Doc) => boolean;
@@ -64,7 +64,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
this.multiTouchDisposer?.();
if (ele) {
this._mainCont = ele;
- this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+ this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this));
this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this));
}
@@ -400,9 +400,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
if (generatedDocuments.length) {
const set = generatedDocuments.length > 1 && generatedDocuments.map(d => Doc.iconify(d));
if (set) {
- const pile = Docs.Create.FreeformDocument(generatedDocuments, { ...options, title: "pile", _LODdisable: true, });
- Doc.pileup(pile, generatedDocuments);
- addDocument(pile);
+ addDocument(Doc.pileup(generatedDocuments, options.x!, options.y!));
} else {
generatedDocuments.forEach(addDocument);
}
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 63498cea1..045134225 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -19,7 +19,6 @@ const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
import React = require("react");
-import { DocumentView } from "../nodes/DocumentView";
@observer
export class CollectionTimeView extends CollectionSubView(doc => doc) {
@@ -84,7 +83,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
}
@computed get contents() {
- return <div className="collectionTimeView-innards" key="timeline" style={{ width: "100%" }} onPointerDown={this.contentsDown}>
+ return <div className="collectionTimeView-innards" key="timeline" style={{ width: "100%", pointerEvents: this.props.active() ? undefined : "none" }} onPointerDown={this.contentsDown}>
<CollectionFreeFormView {...this.props} childClickScript={this._childClickedScript} viewDefDivClick={this._viewDefDivClick} fitToBox={true} freezeChildDimensions={BoolCast(this.layoutDoc._freezeChildDimensions, true)} layoutEngine={this.layoutEngine} />
</div>;
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ca2004b79..d938bd7ad 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -143,7 +143,7 @@ class TreeView extends React.Component<TreeViewProps> {
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer && this._treedropDisposer();
- ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)));
+ ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)), this.props.document);
}
onPointerEnter = (e: React.PointerEvent): void => {
@@ -261,7 +261,7 @@ class TreeView extends React.Component<TreeViewProps> {
docHeight = () => {
const layoutDoc = Doc.Layout(this.props.document);
const bounds = this.boundsOfCollectionDocument;
- return Math.min(this.MAX_EMBED_HEIGHT, (() => {
+ return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
if (aspect) return this.docWidth() * aspect;
if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
@@ -269,7 +269,7 @@ class TreeView extends React.Component<TreeViewProps> {
Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
NumCast(this.props.containingCollection._height)))) :
NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
- })());
+ })()));
}
@computed get expandedField() {
@@ -321,6 +321,9 @@ class TreeView extends React.Component<TreeViewProps> {
return rows;
}
+ rtfWidth = () => Math.min(Doc.Layout(this.props.document)?.[WidthSym](), this.props.panelWidth() - 20);
+ 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() {
const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined;
if (expandKey !== undefined) {
@@ -345,7 +348,9 @@ class TreeView extends React.Component<TreeViewProps> {
</div></ul>;
} else {
const layoutDoc = Doc.Layout(this.props.document);
- return <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}>
+ const panelHeight = layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight;
+ const panelWidth = layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth;
+ return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.props.document[Id] + this.props.document.title}>
<ContentFittingDocumentView
Document={layoutDoc}
DataDocument={this.templateDataDoc}
@@ -355,8 +360,10 @@ class TreeView extends React.Component<TreeViewProps> {
backgroundColor={this.props.backgroundColor}
fitToBox={this.boundsOfCollectionDocument !== undefined}
FreezeDimensions={true}
- PanelWidth={this.docWidth}
- PanelHeight={this.docHeight}
+ NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
+ NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
+ PanelWidth={panelWidth}
+ PanelHeight={panelHeight}
getTransform={this.docTransform}
CollectionDoc={this.props.containingCollection}
CollectionView={undefined}
@@ -663,7 +670,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this.treedropDisposer?.();
if (this._mainEle = ele) {
- this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+ this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.props.Document);
}
}
@@ -722,21 +729,10 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
});
});
- const { TextDocument, ImageDocument, CarouselDocument, TreeDocument } = Docs.Create;
+ const { ImageDocument } = Docs.Create;
const { Document } = this.props;
const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
- const detailedTemplate = `{ "doc": { "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] } ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
-
- const textDoc = TextDocument("", { title: "details", _autoHeight: true });
- const detailView = Docs.Create.StackingDocument([
- CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
- textDoc,
- TextDocument("", { title: "shortDescription", _autoHeight: true }),
- TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true })
- ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
- textDoc.data = new RichTextField(detailedTemplate, "year company");
- detailView.isTemplateDoc = makeTemplate(detailView);
-
+ const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactory, Doc, null);
const heroView = ImageDocument(fallbackImg, { title: "heroView", isTemplateDoc: true, isTemplateForField: "hero", }); // this acts like a template doc and a template field ... a little weird, but seems to work?
heroView.proto!.layout = ImageBox.LayoutString("hero");
heroView._showTitle = "title";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 47e79f088..801704673 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -46,6 +46,7 @@ import { InteractionUtils } from '../../util/InteractionUtils';
import { ObjectField } from '../../../new_fields/ObjectField';
import CollectionMapView from './CollectionMapView';
import { Transform } from 'prosemirror-transform';
+import { CollectionPileView } from './CollectionPileView';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -67,7 +68,8 @@ export enum CollectionViewType {
Carousel = "carousel",
Linear = "linear",
Staff = "staff",
- Map = "map"
+ Map = "map",
+ Pile = "pileup"
}
export interface CollectionRenderProps {
@@ -169,6 +171,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
case CollectionViewType.Multicolumn: return (<CollectionMulticolumnView key="collview" {...props} />);
case CollectionViewType.Multirow: return (<CollectionMultirowView key="rpwview" {...props} />);
case CollectionViewType.Linear: { return (<CollectionLinearView key="collview" {...props} />); }
+ case CollectionViewType.Pile: { return (<CollectionPileView key="collview" {...props} />); }
case CollectionViewType.Carousel: { return (<CollectionCarouselView key="collview" {...props} />); }
case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView key="collview" {...props} />); }
case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView key="collview" {...props} />); }
@@ -222,7 +225,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
this.setupViewTypes("Change Perspective...", (vtype => { this.props.Document._viewType = vtype; return this.props.Document; }), true);
- this.setupViewTypes("New Perspective...", vtype => {
+ this.setupViewTypes("Add a Perspective...", vtype => {
const newRendition = Doc.MakeAlias(this.props.Document);
newRendition._viewType = vtype;
this.props.addDocTab(newRendition, "onRight");
@@ -490,7 +493,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
{!this.props.isSelected() || this.props.PanelHeight() < 100 || this.props.Document.hideFilterView ? (null) :
<div className="collectionTimeView-dragger" title="library View Dragger" onPointerDown={this.onPointerDown} style={{ right: this.facetWidth() - 10 }} />
}
- {this.filterView}
+ {this.facetWidth() < 10 ? (null) : this.filterView}
</div>);
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index 5203eb55f..e4581eb46 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -33,6 +33,17 @@
outline-color: black;
}
+ .collectionViewBaseChrome-button{
+ font-size: 75%;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ background: rgb(238, 238, 238);
+ color: purple;
+ outline-color: black;
+ border: none;
+ padding: 12px 10px 11px 10px;
+ margin-left: 10px;
+ }
.collectionViewBaseChrome-cmdPicker {
margin-left: 3px;
margin-right: 0px;
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 7315d2c4e..d26e3a38b 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -215,9 +215,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
private dropDisposer?: DragManager.DragDropDisposer;
protected createDropTarget = (ele: HTMLDivElement) => {
- this.dropDisposer && this.dropDisposer();
+ this.dropDisposer?.();
if (ele) {
- this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
+ this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.document);
}
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 566a6788b..9a864078a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -9,13 +9,15 @@ 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";
export interface ViewDefBounds {
type: string;
- text?: string;
+ payload: any;
x: number;
y: number;
z?: number;
+ text?: string;
zIndex?: number;
width?: number;
height?: number;
@@ -23,12 +25,13 @@ export interface ViewDefBounds {
fontSize?: number;
highlight?: boolean;
color?: string;
- payload: any;
+ replica?: string;
+ pair?: { layout: Doc, data?: Doc };
}
export interface PoolData {
- x?: number;
- y?: number;
+ x: number;
+ y: number;
z?: number;
zIndex?: number;
width?: number;
@@ -36,6 +39,8 @@ export interface PoolData {
color?: string;
transition?: string;
highlight?: boolean;
+ replica: string;
+ pair: { layout: Doc, data?: Doc };
}
export interface ViewDefResult {
@@ -72,89 +77,103 @@ function getTextWidth(text: string, font: string): number {
interface PivotColumn {
docs: Doc[];
+ replicas: string[];
filters: string[];
}
export function computerPassLayout(
poolData: Map<string, PoolData>,
pivotDoc: Doc,
- childDocs: Doc[],
- filterDocs: Doc[],
childPairs: { layout: Doc, data?: Doc }[],
panelDim: number[],
viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[]
) {
- const docMap = new Map<Doc, ViewDefBounds>();
- childDocs.forEach((doc, i) => {
- docMap.set(doc, {
- type: "doc",
- x: NumCast(doc.x),
- y: NumCast(doc.y),
- width: doc[WidthSym](),
- height: doc[HeightSym](),
- payload: undefined
+ const docMap = new Map<string, PoolData>();
+ childPairs.forEach(({ layout, data }, i) => {
+ docMap.set(layout[Id], {
+ x: NumCast(layout.x),
+ y: NumCast(layout.y),
+ width: layout[WidthSym](),
+ height: layout[HeightSym](),
+ pair: { layout, data },
+ replica: ""
});
});
- return normalizeResults(panelDim, 12, childPairs, docMap, poolData, viewDefsToJSX, [], 0, [], childDocs.filter(c => !filterDocs.includes(c)));
+ return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []);
}
export function computerStarburstLayout(
poolData: Map<string, PoolData>,
pivotDoc: Doc,
- childDocs: Doc[],
- filterDocs: Doc[],
childPairs: { layout: Doc, data?: Doc }[],
panelDim: number[],
viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[]
) {
- const docMap = new Map<Doc, ViewDefBounds>();
+ const docMap = new Map<string, PoolData>();
const burstRadius = [NumCast(pivotDoc._starburstRadius, panelDim[0]), NumCast(pivotDoc._starburstRadius, panelDim[1])];
const docScale = NumCast(pivotDoc._starburstDocScale);
const docSize = docScale * 100; // assume a icon sized at 100
const scaleDim = [burstRadius[0] + docSize, burstRadius[1] + docSize];
- childDocs.forEach((doc, i) => {
- const deg = i / childDocs.length * Math.PI * 2;
- docMap.set(doc, {
- type: "doc",
- x: Math.cos(deg) * (burstRadius[0] / 3) - docScale * doc[WidthSym]() / 2,
- y: Math.sin(deg) * (burstRadius[1] / 3) - docScale * doc[HeightSym]() / 2,
- width: docScale * doc[WidthSym](),
- height: docScale * doc[HeightSym](),
- payload: undefined
+ childPairs.forEach(({ layout, data }, i) => {
+ const deg = i / childPairs.length * Math.PI * 2;
+ docMap.set(layout[Id], {
+ x: Math.cos(deg) * (burstRadius[0] / 3) - docScale * layout[WidthSym]() / 2,
+ y: Math.sin(deg) * (burstRadius[1] / 3) - docScale * layout[HeightSym]() / 2,
+ width: docScale * layout[WidthSym](),
+ height: docScale * layout[HeightSym](),
+ pair: { layout, data },
+ replica: ""
});
});
- return normalizeResults(scaleDim, 12, childPairs, docMap, poolData, viewDefsToJSX, [], 0, [], childDocs.filter(c => !filterDocs.includes(c)));
+ return normalizeResults(scaleDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []);
}
export function computePivotLayout(
poolData: Map<string, PoolData>,
pivotDoc: Doc,
- childDocs: Doc[],
- filterDocs: Doc[],
childPairs: { layout: Doc, data?: Doc }[],
panelDim: number[],
viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[]
) {
+ const docMap = new Map<string, PoolData>();
const fieldKey = "data";
const pivotColumnGroups = new Map<FieldResult<Field>, PivotColumn>();
const pivotFieldKey = toLabel(pivotDoc._pivotField);
- for (const doc of filterDocs) {
- const val = Field.toString(doc[pivotFieldKey] as Field);
- if (val) {
- !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val] });
- pivotColumnGroups.get(val)!.docs.push(doc);
+ childPairs.map(pair => {
+ const lval = Cast(pair.layout[pivotFieldKey], listSpec("string"), null);
+ const val = Field.toString(pair.layout[pivotFieldKey] as Field);
+ if (lval) {
+ lval.forEach((val, i) => {
+ !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] });
+ pivotColumnGroups.get(val)!.docs.push(pair.layout);
+ pivotColumnGroups.get(val)!.replicas.push(i.toString());
+ });
+ } else if (val) {
+ !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] });
+ pivotColumnGroups.get(val)!.docs.push(pair.layout);
+ pivotColumnGroups.get(val)!.replicas.push("");
+ } else {
+ docMap.set(pair.layout[Id], {
+ x: 0,
+ y: 0,
+ zIndex: -99,
+ width: 0,
+ height: 0,
+ pair,
+ replica: ""
+ });
}
- }
+ });
let nonNumbers = 0;
- childDocs.map(doc => {
- const num = toNumber(doc[pivotFieldKey]);
+ childPairs.map(pair => {
+ const num = toNumber(pair.layout[pivotFieldKey]);
if (num === undefined || Number.isNaN(num)) {
nonNumbers++;
}
});
- const pivotNumbers = nonNumbers / childDocs.length < .1;
+ const pivotNumbers = nonNumbers / childPairs.length < .1;
if (pivotColumnGroups.size > 10) {
const arrayofKeys = Array.from(pivotColumnGroups.keys());
const sortedKeys = pivotNumbers ? arrayofKeys.sort((n1: FieldResult, n2: FieldResult) => toNumber(n1)! - toNumber(n2)!) : arrayofKeys.sort();
@@ -166,6 +185,7 @@ export function computePivotLayout(
const newgrp = pivotColumnGroups.get(sortedKeys[j])!;
curgrp.docs.push(...newgrp.docs);
curgrp.filters.push(...newgrp.filters);
+ curgrp.replicas.push(...newgrp.replicas);
pivotColumnGroups.delete(sortedKeys[j]);
}
}
@@ -193,7 +213,6 @@ export function computePivotLayout(
}
}
- const docMap = new Map<Doc, ViewDefBounds>();
const groupNames: ViewDefBounds[] = [];
const expander = 1.05;
@@ -216,7 +235,7 @@ export function computePivotLayout(
fontSize,
payload: val
});
- for (const doc of val.docs) {
+ val.docs.forEach((doc, i) => {
const layoutDoc = Doc.Layout(doc);
let wid = pivotAxisWidth;
let hgt = layoutDoc._nativeWidth ? (NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth)) * pivotAxisWidth : pivotAxisWidth;
@@ -224,27 +243,27 @@ export function computePivotLayout(
hgt = pivotAxisWidth;
wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth;
}
- docMap.set(doc, {
- type: "doc",
+ docMap.set(doc[Id] + (val.replicas || ""), {
x: x + xCount * pivotAxisWidth * expander + (pivotAxisWidth - wid) / 2 + (val.docs.length < numCols ? (numCols - val.docs.length) * pivotAxisWidth / 2 : 0),
y: -y + (pivotAxisWidth - hgt) / 2,
width: wid,
height: hgt,
- payload: undefined
+ pair: { layout: doc },
+ replica: val.replicas[i]
});
xCount++;
if (xCount >= numCols) {
xCount = 0;
y += pivotAxisWidth * expander;
}
- }
+ });
x += pivotAxisWidth * (numCols * expander + gap);
});
const dividers = sortedPivotKeys.map((key, i) =>
({ type: "div", color: "lightGray", x: i * pivotAxisWidth * (numCols * expander + gap) - pivotAxisWidth * (expander - 1) / 2, y: -maxColHeight + pivotAxisWidth, width: pivotAxisWidth * numCols * expander, height: maxColHeight, payload: pivotColumnGroups.get(key)!.filters }));
groupNames.push(...dividers);
- return normalizeResults(panelDim, max_text, childPairs, docMap, poolData, viewDefsToJSX, groupNames, 0, [], childDocs.filter(c => !filterDocs.includes(c)));
+ return normalizeResults(panelDim, max_text, docMap, poolData, viewDefsToJSX, groupNames, 0, []);
}
function toNumber(val: FieldResult<Field>) {
@@ -254,15 +273,13 @@ function toNumber(val: FieldResult<Field>) {
export function computeTimelineLayout(
poolData: Map<string, PoolData>,
pivotDoc: Doc,
- childDocs: Doc[],
- filterDocs: Doc[],
childPairs: { layout: Doc, data?: Doc }[],
panelDim: number[],
viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[]
) {
const fieldKey = "data";
const pivotDateGroups = new Map<number, Doc[]>();
- const docMap = new Map<Doc, ViewDefBounds>();
+ const docMap = new Map<string, PoolData>();
const groupNames: ViewDefBounds[] = [];
const timelineFieldKey = Field.toString(pivotDoc._pivotField as Field);
const curTime = toNumber(pivotDoc[fieldKey + "-timelineCur"]);
@@ -278,11 +295,11 @@ export function computeTimelineLayout(
let minTime = minTimeReq === undefined ? Number.MAX_VALUE : minTimeReq;
let maxTime = maxTimeReq === undefined ? -Number.MAX_VALUE : maxTimeReq;
- filterDocs.map(doc => {
- const num = NumCast(doc[timelineFieldKey], Number(StrCast(doc[timelineFieldKey])));
+ childPairs.forEach(pair => {
+ const num = NumCast(pair.layout[timelineFieldKey], Number(StrCast(pair.layout[timelineFieldKey])));
if (!Number.isNaN(num) && (!minTimeReq || num >= minTimeReq) && (!maxTimeReq || num <= maxTimeReq)) {
!pivotDateGroups.get(num) && pivotDateGroups.set(num, []);
- pivotDateGroups.get(num)!.push(doc);
+ pivotDateGroups.get(num)!.push(pair.layout);
minTime = Math.min(num, minTime);
maxTime = Math.max(num, maxTime);
}
@@ -341,7 +358,7 @@ export function computeTimelineLayout(
}
const divider = { type: "div", color: Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
- return normalizeResults(panelDim, fontHeight, childPairs, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider], childDocs.filter(c => !filterDocs.includes(c)));
+ return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]);
function layoutDocsAtTime(keyDocs: Doc[], key: number) {
keyDocs.forEach(doc => {
@@ -353,44 +370,55 @@ export function computeTimelineLayout(
hgt = pivotAxisWidth;
wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth;
}
- docMap.set(doc, {
- type: "doc",
+ docMap.set(doc[Id], {
x: x, y: -Math.sqrt(stack) * pivotAxisWidth / 2 - pivotAxisWidth + (pivotAxisWidth - hgt) / 2,
- zIndex: (curTime === key ? 1000 : zind++), highlight: curTime === key, width: wid / (Math.max(stack, 1)), height: hgt / (Math.max(stack, 1)), payload: undefined
+ zIndex: (curTime === key ? 1000 : zind++),
+ highlight: curTime === key,
+ width: wid / (Math.max(stack, 1)),
+ height: hgt / (Math.max(stack, 1)),
+ pair: { layout: doc },
+ replica: ""
});
stacking[stack] = x + pivotAxisWidth;
});
}
}
-function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { data?: Doc, layout: Doc }[], docMap: Map<Doc, ViewDefBounds>,
- poolData: Map<string, PoolData>, viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], groupNames: ViewDefBounds[], minWidth: number, extras: ViewDefBounds[],
- extraDocs: Doc[]): ViewDefResult[] {
-
+function normalizeResults(
+ panelDim: number[],
+ fontHeight: number,
+ docMap: Map<string, PoolData>,
+ poolData: Map<string, PoolData>,
+ viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[],
+ groupNames: ViewDefBounds[],
+ minWidth: number,
+ extras: ViewDefBounds[]
+): ViewDefResult[] {
const grpEles = groupNames.map(gn => ({ x: gn.x, y: gn.y, width: gn.width, height: gn.height }) as ViewDefBounds);
- const docEles = childPairs.filter(d => docMap.get(d.layout)).map(pair => docMap.get(pair.layout) as ViewDefBounds);
- const aggBounds = aggregateBounds(docEles.concat(grpEles), 0, 0);
+ const docEles = Array.from(docMap.entries()).map(ele => ele[1]);
+ const aggBounds = aggregateBounds(grpEles.concat(docEles.map(de => ({ ...de, type: "doc", payload: "" }))).filter(e => e.zIndex !== -99), 0, 0);
aggBounds.r = Math.max(minWidth, aggBounds.r - aggBounds.x);
const wscale = panelDim[0] / (aggBounds.r - aggBounds.x);
let scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] ? (panelDim[1]) / (aggBounds.b - aggBounds.y) : wscale;
if (Number.isNaN(scale)) scale = 1;
- childPairs.filter(d => docMap.get(d.layout)).map(pair => {
- const newPosRaw = docMap.get(pair.layout);
+ Array.from(docMap.entries()).filter(ele => ele[1].pair).map(ele => {
+ const newPosRaw = ele[1];
if (newPosRaw) {
const newPos = {
x: newPosRaw.x * scale,
y: newPosRaw.y * scale,
z: newPosRaw.z,
+ replica: newPosRaw.replica,
highlight: newPosRaw.highlight,
zIndex: newPosRaw.zIndex,
width: (newPosRaw.width || 0) * scale,
- height: newPosRaw.height! * scale
+ height: newPosRaw.height! * scale,
+ pair: ele[1].pair
};
- poolData.set(pair.layout[Id], { transition: "transform 1s", ...newPos });
+ poolData.set(newPos.pair.layout[Id] + (newPos.replica || ""), { transition: "transform 1s", ...newPos });
}
});
- extraDocs.map(ed => poolData.set(ed[Id], { x: 0, y: 0, zIndex: -99 }));
return viewDefsToJSX(extras.concat(groupNames).map(gname => ({
type: gname.type,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 702b02a20..4b5e977df 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -36,7 +36,7 @@ export class CollectionFreeFormLinksView extends React.Component {
}
render() {
- return <div className="collectionfreeformlinksview-container">
+ return SelectionManager.GetIsDragging() ? (null) : <div className="collectionfreeformlinksview-container">
<svg className="collectionfreeformlinksview-svgCanvas">
{this.uniqueConnections}
</svg>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 4e4e85e13..60c39c825 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -13,6 +13,15 @@
border-radius: inherit;
}
+.collectionfreeformview-viewdef {
+ > .collectionFreeFormDocumentView-container {
+ pointer-events: none;
+ .contentFittingDocumentDocumentView-previewDoc {
+ pointer-events: all;
+ }
+ }
+}
+
.collectionfreeformview-ease {
transition: transform 500ms;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1f0bc89c5..d85233041 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -32,7 +32,7 @@ import { ContextMenuProps } from "../../ContextMenuItem";
import { InkingControl } from "../../InkingControl";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentViewProps, DocumentView } from "../../nodes/DocumentView";
-import { FormattedTextBox } from "../../nodes/FormattedTextBox";
+import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
import { pageSchema } from "../../nodes/ImageBox";
import PDFMenu from "../../pdf/PDFMenu";
import { CollectionDockingView } from "../CollectionDockingView";
@@ -44,6 +44,7 @@ import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import { CollectionViewType } from "../CollectionView";
+import { Timeline } from "../../animationtimeline/Timeline";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -85,14 +86,16 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
private _clusterDistance: number = 75;
private _hitCluster = false;
private _layoutComputeReaction: IReactionDisposer | undefined;
- private _layoutPoolData = new ObservableMap<string, any>();
- private _cachedPool: Map<string, any> = new Map();
+ private _layoutPoolData = new ObservableMap<string, PoolData>();
+ private _layoutSizeData = new ObservableMap<string, { width?: number, height?: number }>();
+ private _cachedPool: Map<string, PoolData> = new Map();
@observable private _pullCoords: number[] = [0, 0];
@observable private _pullDirection: string = "";
public get displayName() { return "CollectionFreeFormView(" + this.props.Document.title?.toString() + ")"; } // this makes mobx trace() statements more descriptive
@observable.shallow _layoutElements: ViewDefResult[] = []; // shallow because some layout items (eg pivot labels) are just generated 'divs' and can't be frozen as observables
@observable _clusterSets: (Doc[])[] = [];
+ @observable _timelineRef = React.createRef<Timeline>();
@computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; }
@computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; }
@@ -508,7 +511,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (this.layoutDoc.targetScale && (Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) {
if (Date.now() - this._lastTap < 300) {
const docpt = this.getTransform().transformPoint(e.clientX, e.clientY);
- this.scaleAtPt(docpt, NumCast(this.layoutDoc.targetScale, NumCast(this.layoutDoc.scale)));
+ this.scaleAtPt(docpt, 1);
e.stopPropagation();
e.preventDefault();
}
@@ -728,7 +731,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
if (!this.isAnnotationOverlay && clamp) {
// this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout);
- const measuredDocs = docs.filter(doc => doc && this.childDataProvider(doc)).map(doc => this.childDataProvider(doc));
+ const measuredDocs = docs.filter(doc => doc && this.childDataProvider(doc, "")).map(doc => this.childDataProvider(doc, ""));
if (measuredDocs.length) {
const ranges = measuredDocs.reduce(({ xrange, yrange }, { x, y, width, height }) => // computes range of content
({
@@ -821,18 +824,18 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document.scale, pt: this.Document.panTransformType };
- if (!willZoom && DocumentView._focusHack.length) {
- Doc.BrushDoc(this.props.Document);
- !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
- } else {
- if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
- if (!doc.z) this.setPan(newPanX, newPanY, "Ease", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
- }
- Doc.BrushDoc(this.props.Document);
- this.props.focus(this.props.Document);
- willZoom && this.setScaleToZoom(layoutdoc, scale);
+ // if (!willZoom && DocumentView._focusHack.length) {
+ // Doc.BrushDoc(this.props.Document);
+ // !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
+ // } else {
+ if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
+ if (!doc.z) this.setPan(newPanX, newPanY, "Ease", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
}
+ Doc.BrushDoc(this.props.Document);
+ this.props.focus(this.props.Document);
+ willZoom && this.setScaleToZoom(layoutdoc, scale);
Doc.linkFollowHighlight(doc);
+ //}
afterFocus && setTimeout(() => {
if (afterFocus?.()) {
@@ -853,7 +856,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@computed get libraryPath() { return this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : []; }
@computed get onChildClickHandler() { return this.props.childClickScript || ScriptCast(this.Document.onChildClick); }
backgroundHalo = () => BoolCast(this.Document.useClusters);
-
+ @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); }
+ parentActive = () => this.props.active() || this.backgroundActive ? true : false;
getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
return {
...this.props,
@@ -879,7 +883,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
focus: this.focusDocument,
backgroundColor: this.getClusterColor,
backgroundHalo: this.backgroundHalo,
- parentActive: this.props.active,
+ parentActive: this.parentActive,
bringToFront: this.bringToFront,
addDocTab: this.addDocTab,
};
@@ -899,16 +903,16 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
return this.props.addDocTab(doc, where);
});
- getCalculatedPositions(params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): PoolData {
+ getCalculatedPositions(params: { pair: { layout: Doc, data?: Doc }, index: number, collection: Doc, docs: Doc[], state: any }): PoolData {
const result = this.Document.arrangeScript?.script.run(params, console.log);
if (result?.success) {
- return { ...result, transition: "transform 1s" };
+ return { x: 0, y: 0, transition: "transform 1s", ...result, pair: params.pair, replica: "" };
}
- const layoutDoc = Doc.Layout(params.doc);
- const { x, y, z, color, zIndex } = params.doc;
+ const layoutDoc = Doc.Layout(params.pair.layout);
+ 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"),
- width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number")
+ width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number"), pair: params.pair, replica: ""
};
}
@@ -946,21 +950,22 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
}
- childDataProvider = computedFn(function childDataProvider(this: any, doc: Doc) {
- return this._layoutPoolData.get(doc[Id]);
+ childDataProvider = computedFn(function childDataProvider(this: any, doc: Doc, replica: string) {
+ return this._layoutPoolData.get(doc[Id] + (replica || ""));
+ }.bind(this));
+ childSizeProvider = computedFn(function childSizeProvider(this: any, doc: Doc, replica: string) {
+ return this._layoutSizeData.get(doc[Id] + (replica || ""));
}.bind(this));
doEngineLayout(poolData: Map<string, PoolData>,
engine: (
poolData: Map<string, PoolData>,
pivotDoc: Doc,
- childDocs: Doc[],
- filterDocs: Doc[],
childPairs: { layout: Doc, data?: Doc }[],
panelDim: number[],
- viewDefsToJSX: ((views: ViewDefBounds[]) => ViewDefResult[])) => ViewDefResult[]) {
- return engine(poolData, this.props.Document, this.childDocs, this.childDocs,
- this.childLayoutPairs, [this.props.PanelWidth(), this.props.PanelHeight()], this.viewDefsToJSX);
+ viewDefsToJSX: ((views: ViewDefBounds[]) => ViewDefResult[])) => ViewDefResult[]
+ ) {
+ return engine(poolData, this.props.Document, this.childLayoutPairs, [this.props.PanelWidth(), this.props.PanelHeight()], this.viewDefsToJSX);
}
doFreeformLayout(poolData: Map<string, PoolData>) {
@@ -970,15 +975,18 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : [];
this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => {
- const pos = this.getCalculatedPositions({ doc: pair.layout, index: i, collection: this.Document, docs: layoutDocs, state });
+ const pos = this.getCalculatedPositions({ pair, index: i, collection: this.Document, docs: layoutDocs, state });
poolData.set(pair.layout[Id], pos);
});
return elements;
}
@computed get doInternalLayoutComputation() {
- const newPool = new Map<string, any>();
- const engine = StrCast(this.layoutDoc._layoutEngine) || this.props.layoutEngine?.();
+ TraceMobx();
+
+
+ const newPool = new Map<string, PoolData>();
+ const engine = this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine);
switch (engine) {
case "pass": return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) };
case "timeline": return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) };
@@ -992,30 +1000,39 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
get doLayoutComputation() {
const { newPool, computedElementData } = this.doInternalLayoutComputation;
runInAction(() =>
- Array.from(newPool.keys()).map(key => {
- const lastPos = this._cachedPool.get(key); // last computed pos
- const newPos = newPool.get(key);
- if (!lastPos || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.zIndex !== lastPos.zIndex || newPos.width !== lastPos.width || newPos.height !== lastPos.height) {
- this._layoutPoolData.set(key, newPos);
+ Array.from(newPool.entries()).map(entry => {
+ 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) {
+ this._layoutPoolData.set(entry[0], newPos);
+ }
+ 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.keys()).forEach(k => this._cachedPool.set(k, newPool.get(k)));
+ Array.from(newPool.entries()).forEach(k => this._cachedPool.set(k[0], k[1]));
const elements: ViewDefResult[] = computedElementData.slice();
- const engine = this.props.layoutEngine?.() || this.props.Document._layoutEngine;
- this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).forEach(pair =>
+ const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
+ Array.from(newPool.entries()).filter(entry => this.isCurrent(entry[1].pair.layout)).forEach(entry =>
elements.push({
ele: <CollectionFreeFormDocumentView
- key={pair.layout[Id]}
- {...this.getChildDocumentViewProps(pair.layout, pair.data)}
+ key={entry[1].pair.layout[Id] + (entry[1].replica || "")}
+ {...this.getChildDocumentViewProps(entry[1].pair.layout, entry[1].pair.data)}
+ replica={entry[1].replica}
dataProvider={this.childDataProvider}
+ sizeProvider={this.childSizeProvider}
LayoutDoc={this.childLayoutDocFunc}
- pointerEvents={engine && engine !== "starburst" ? false : undefined}
- jitterRotation={NumCast(this.props.Document.jitterRotation)}
- fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)}
+ pointerEvents={
+ this.backgroundActive ?
+ true :
+ (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? false : undefined}
+ jitterRotation={NumCast(this.props.Document._jitterRotation)}
+ //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
+ fitToBox={BoolCast(this.props.freezeChildDimensions)} // bcz: check this
FreezeDimensions={BoolCast(this.props.freezeChildDimensions)}
/>,
- bounds: this.childDataProvider(pair.layout)
+ bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica)
}));
return elements;
@@ -1076,6 +1093,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
+ this._timelineRef.current!.timelineContextMenu(e);
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: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
@@ -1083,7 +1101,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
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: "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");
@@ -1111,8 +1129,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
input.click();
}
});
-
- ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
+ ContextMenu.Instance.addItem({ description: "Options ...", subitems: optionItems, icon: "eye" });
+ this._timelineRef.current!.timelineContextMenu(e);
}
private childViews = () => {
@@ -1150,9 +1168,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
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}>
<CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY} shifted={!this.nativeHeight && !this.isAnnotationOverlay}
- easing={this.easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
+ easing={this.easing} viewDefDivClick={this.props.viewDefDivClick} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
{this.children}
</CollectionFreeFormViewPannableContents>
+ <Timeline ref={this._timelineRef} {...this.props} />
</MarqueeView>;
}
@@ -1164,6 +1183,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 && SelectionManager.GetIsDragging(); }
render() {
TraceMobx();
const clientRect = this._mainCont?.getBoundingClientRect();
@@ -1179,7 +1199,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onWheel={this.onPointerWheel} onClick={this.onClick} //pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu}
style={{
- pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
+ pointerEvents: this.backgroundEvents ? "all" : undefined,
transform: this.contentScaling ? `scale(${this.contentScaling})` : "",
transformOrigin: this.contentScaling ? "left top" : "",
width: this.contentScaling ? `${100 / this.contentScaling}%` : "",
@@ -1223,6 +1243,7 @@ interface CollectionFreeFormViewPannableContentsProps {
panY: () => number;
zoomScaling: () => number;
easing: () => boolean;
+ viewDefDivClick?: ScriptField;
children: () => JSX.Element[];
shifted: boolean;
}
@@ -1230,7 +1251,7 @@ interface CollectionFreeFormViewPannableContentsProps {
@observer
class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps>{
render() {
- const freeformclass = "collectionfreeformview" + (this.props.easing() ? "-ease" : "-none");
+ const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : (this.props.easing() ? "-ease" : "-none"));
const cenx = this.props.centeringShiftX();
const ceny = this.props.centeringShiftY();
const panx = -this.props.panX();
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ab8174ba1..c70301b2f 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,12 +1,12 @@
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast, DataSym, WidthSym, HeightSym } from "../../../../new_fields/Doc";
+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 { Utils } from "../../../../Utils";
-import { Docs, DocUtils } from "../../../documents/Documents";
+import { Docs, DocUtils, DocumentOptions } from "../../../documents/Documents";
import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
@@ -19,7 +19,7 @@ import React = require("react");
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { RichTextField } from "../../../../new_fields/RichTextField";
import { CollectionView } from "../CollectionView";
-import { FormattedTextBox } from "../../nodes/FormattedTextBox";
+import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
import { ScriptField } from "../../../../new_fields/ScriptField";
interface MarqueeViewProps {
@@ -113,7 +113,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
if (template instanceof Doc) {
tbox._width = NumCast(template._width);
tbox.layoutKey = "layout_" + StrCast(template.title);
- tbox[StrCast(tbox.layoutKey)] = template;
+ Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template;
}
this.props.addLiveTextDocument(tbox);
}
@@ -310,11 +310,10 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.hideMarquee();
}
- getCollection = (selected: Doc[], asTemplate: boolean, isBackground?: boolean) => {
+ getCollection = (selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, isBackground?: boolean) => {
const bounds = this.Bounds;
// const inkData = this.ink ? this.ink.inkData : undefined;
- const creator = asTemplate ? Docs.Create.StackingDocument : Docs.Create.FreeformDocument;
- const newCollection = creator(selected, {
+ const newCollection = (creator || Docs.Create.FreeformDocument)(selected, {
x: bounds.left,
y: bounds.top,
_panX: 0,
@@ -338,8 +337,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const selected = this.marqueeSelect(false);
SelectionManager.DeselectAll();
selected.forEach(d => this.props.removeDocument(d));
- const newCollection = this.getCollection(selected, false);
- Doc.pileup(newCollection, selected);
+ const newCollection = Doc.pileup(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2);
this.props.addDocument(newCollection);
this.props.selectDocuments([newCollection], []);
MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -359,7 +357,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
return d;
});
}
- const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t");
+ const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === "t" ? Docs.Create.StackingDocument : undefined);
this.props.addDocument(newCollection);
this.props.selectDocuments([newCollection], []);
MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -470,7 +468,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
}
@action
background = (e: KeyboardEvent | React.PointerEvent | undefined) => {
- const newCollection = this.getCollection([], false, true);
+ const newCollection = this.getCollection([], undefined, true);
this.props.addDocument(newCollection);
MarqueeOptionsMenu.Instance.fadeOut(true);
this.hideMarquee();
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 0e1cc2010..9d09ecc3b 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -5,7 +5,7 @@ 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 { DragManager } from '../../../util/DragManager';
+import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
import { undoBatch } from '../../../util/UndoManager';
import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
@@ -214,21 +214,32 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
}
getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
return <ContentFittingDocumentView
- {...this.props}
Document={layout}
DataDocument={layout.resolvedDataDoc as Doc}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- addDocTab={this.addDocTab}
- fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
- FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
backgroundColor={this.props.backgroundColor}
- CollectionDoc={this.props.Document}
+ LayoutDoc={this.props.childLayoutTemplate}
+ LibraryPath={this.props.LibraryPath}
+ FreezeDimensions={this.props.freezeChildDimensions}
+ renderDepth={this.props.renderDepth + 1}
PanelWidth={width}
PanelHeight={height}
- getTransform={dxf}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+ rootSelected={this.rootSelected}
+ dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
onClick={this.onChildClickHandler}
- renderDepth={this.props.renderDepth + 1}
+ getTransform={dxf}
+ focus={this.props.focus}
+ CollectionDoc={this.props.CollectionView?.props.Document}
+ CollectionView={this.props.CollectionView}
+ addDocument={this.props.addDocument}
+ moveDocument={this.props.moveDocument}
+ removeDocument={this.props.removeDocument}
+ active={this.props.active}
+ whenActiveChanged={this.props.whenActiveChanged}
+ addDocTab={this.addDocTab}
+ pinToPres={this.props.pinToPres}
/>;
}
/**
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 1eb486c4f..af0cc3b5c 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -13,7 +13,7 @@ import { Transform } from '../../../util/Transform';
import HeightLabel from './MultirowHeightLabel';
import ResizeBar from './MultirowResizer';
import { undoBatch } from '../../../util/UndoManager';
-import { DragManager } from '../../../util/DragManager';
+import { DragManager, dropActionType } from '../../../util/DragManager';
import { List } from '../../../../new_fields/List';
type MultirowDocument = makeInterface<[typeof documentSchema]>;
@@ -214,21 +214,32 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
}
getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
return <ContentFittingDocumentView
- {...this.props}
Document={layout}
DataDocument={layout.resolvedDataDoc as Doc}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- addDocTab={this.addDocTab}
- fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
- FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
backgroundColor={this.props.backgroundColor}
- CollectionDoc={this.props.Document}
+ LayoutDoc={this.props.childLayoutTemplate}
+ LibraryPath={this.props.LibraryPath}
+ FreezeDimensions={this.props.freezeChildDimensions}
+ renderDepth={this.props.renderDepth + 1}
PanelWidth={width}
PanelHeight={height}
- getTransform={dxf}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+ rootSelected={this.rootSelected}
+ dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
onClick={this.onChildClickHandler}
- renderDepth={this.props.renderDepth + 1}
+ getTransform={dxf}
+ focus={this.props.focus}
+ CollectionDoc={this.props.CollectionView?.props.Document}
+ CollectionView={this.props.CollectionView}
+ addDocument={this.props.addDocument}
+ moveDocument={this.props.moveDocument}
+ removeDocument={this.props.removeDocument}
+ active={this.props.active}
+ whenActiveChanged={this.props.whenActiveChanged}
+ addDocTab={this.addDocTab}
+ pinToPres={this.props.pinToPres}
/>;
}
/**