aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx2
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx129
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx2
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx10
-rw-r--r--src/client/views/nodes/DocumentView.tsx8
6 files changed, 96 insertions, 57 deletions
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 3c66faf0c..3bdc427d6 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -28,7 +28,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
componentWillUnmount() { this._dropDisposer?.(); }
- protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+ protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view
this._dropDisposer?.();
if (ele) {
this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 6c2c27e8e..733c07031 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -23,7 +23,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
componentWillUnmount() { this._dropDisposer?.(); }
- protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+ protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view
this._dropDisposer?.();
if (ele) {
this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3443f33e1..3d664e146 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,5 +1,5 @@
import { Bezier } from "bezier-js";
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx";
import { observer } from "mobx-react";
import { computedFn } from "mobx-utils";
import { DateField } from "../../../../fields/DateField";
@@ -95,6 +95,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
private _clusterDistance: number = 75;
private _hitCluster: number = -1;
private _disposers: { [name: string]: IReactionDisposer } = {};
+ private _renderCutoffData = observable.map<string, boolean>();
private _layoutPoolData = observable.map<string, PoolData>();
private _layoutSizeData = observable.map<string, { width?: number, height?: number }>();
private _cachedPool: Map<string, PoolData> = new Map();
@@ -1155,7 +1156,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
renderDepth={this.props.renderDepth + 1}
replica={entry.replica}
renderIndex={renderIndex}
- renderCutoff={this.NumLoaded}
+ renderCutoffProvider={this.renderCutoffProvider}
ContainingCollectionView={this.props.CollectionView}
ContainingCollectionDoc={this.props.Document}
CollectionFreeFormView={this}
@@ -1259,6 +1260,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
}
+
+ renderCutoffProvider = computedFn(function renderCutoffProvider(this: any, doc: Doc) {
+ return !this._renderCutoffData.get(doc[Id] + "");
+ }.bind(this));
+
+
childPositionProviderUnmemoized = (doc: Doc, replica: string) => {
return this._layoutPoolData.get(doc[Id] + (replica || ""));
}
@@ -1304,7 +1311,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
@observable _numLoaded = 1;
- NumLoaded = () => this._numLoaded;
get doLayoutComputation() {
const { newPool, computedElementData } = this.doInternalLayoutComputation;
const array = Array.from(newPool.entries());
@@ -1567,9 +1573,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
incrementalRender = action(() => {
if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())) {
- this._numLoaded++;
+ const unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
+ const loadIncrement = 5;
+ for (var i = 0; i < Math.min(unrendered.length, loadIncrement); i++) {
+ this._renderCutoffData.set(unrendered[i][Id] + "", true);
+ }
}
- this._numLoaded < this.views.length && setTimeout(this.incrementalRender, 1);
+ this.childDocs.some(doc => !this._renderCutoffData.get(doc[Id])) && setTimeout(this.incrementalRender, 1);
});
children = () => {
@@ -1582,46 +1592,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
];
}
- chooseGridSpace = (gridSpace: number): number => {
- if (!this.zoomScaling()) return 50;
- const divisions = this.props.PanelWidth() / this.zoomScaling() / gridSpace + 3;
- return divisions < 60 ? gridSpace : this.chooseGridSpace(gridSpace * 10);
- }
-
- @computed get backgroundGrid() {
- const gridSpace = this.chooseGridSpace(NumCast(this.layoutDoc["_backgroundGrid-spacing"], 50));
- const shiftX = (this.props.isAnnotationOverlay ? 0 : -this.panX() % gridSpace - gridSpace) * this.zoomScaling();
- const shiftY = (this.props.isAnnotationOverlay ? 0 : -this.panY() % gridSpace - gridSpace) * this.zoomScaling();
- const renderGridSpace = gridSpace * this.zoomScaling();
- const w = this.props.PanelWidth() + 2 * renderGridSpace;
- const h = this.props.PanelHeight() + 2 * renderGridSpace;
- const strokeStyle = CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "rgba(255,255,255,0.5)" : "rgba(0, 0,0,0.5)";
- return <canvas className="collectionFreeFormView-grid" width={w} height={h} style={{ transform: `translate(${shiftX}px, ${shiftY}px)` }}
- ref={(el) => {
- const ctx = el?.getContext('2d');
- if (ctx) {
- const Cx = this.cachedCenteringShiftX % renderGridSpace;
- const Cy = this.cachedCenteringShiftY % renderGridSpace;
- ctx.lineWidth = Math.min(1, Math.max(0.5, this.zoomScaling()));
- ctx.setLineDash(gridSpace > 50 ? [3, 3] : [1, 5]);
- ctx.clearRect(0, 0, w, h);
- if (ctx) {
- ctx.strokeStyle = strokeStyle;
- ctx.beginPath();
- for (let x = Cx - renderGridSpace; x <= w - Cx; x += renderGridSpace) {
- ctx.moveTo(x, Cy - h);
- ctx.lineTo(x, Cy + h);
- }
- for (let y = Cy - renderGridSpace; y <= h - Cy; y += renderGridSpace) {
- ctx.moveTo(Cx - w, y);
- ctx.lineTo(Cx + w, y);
- }
- ctx.stroke();
- }
- }
- }} />;
- }
-
@computed get placeholder() {
return <div className="collectionfreeformview-placeholder" style={{ background: this.Document.backgroundColor }}>
<span className="collectionfreeformview-placeholderSpan">{this.props.Document.title?.toString()}</span>
@@ -1629,6 +1599,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
@computed get marqueeView() {
+ TraceMobx();
return <MarqueeView
{...this.props}
ungroup={this.props.Document._isGroup ? this.promoteCollection : undefined}
@@ -1643,7 +1614,18 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
getTransform={this.getTransform}
isAnnotationOverlay={this.isAnnotationOverlay}>
<div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0 : undefined }}>
- {this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)}
+ {this.layoutDoc._backgroundGridShow ?
+ <CollectionFreeFormBackgroundGrid
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={this.props.PanelHeight}
+ panX={this.panX}
+ panY={this.panY}
+ zoomScaling={this.zoomScaling}
+ layoutDoc={this.layoutDoc}
+ isAnnotationOverlay={this.isAnnotationOverlay}
+ cachedCenteringShiftX={this.cachedCenteringShiftX}
+ cachedCenteringShiftY={this.cachedCenteringShiftY}
+ /> : (null)}
<CollectionFreeFormViewPannableContents
isAnnotationOverlay={this.isAnnotationOverlay}
isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable}
@@ -1874,4 +1856,59 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
{this.zoomProgressivize}
</div>;
}
+}
+
+interface CollectionFreeFormViewBackgroundGridProps {
+ panX: () => number;
+ panY: () => number;
+ PanelWidth: () => number;
+ PanelHeight: () => number;
+ isAnnotationOverlay?: boolean;
+ zoomScaling: () => number;
+ layoutDoc: Doc;
+ cachedCenteringShiftX: number;
+ cachedCenteringShiftY: number;
+}
+@observer
+class CollectionFreeFormBackgroundGrid extends React.Component<CollectionFreeFormViewBackgroundGridProps> {
+
+
+ chooseGridSpace = (gridSpace: number): number => {
+ if (!this.props.zoomScaling()) return 50;
+ const divisions = this.props.PanelWidth() / this.props.zoomScaling() / gridSpace + 3;
+ return divisions < 60 ? gridSpace : this.chooseGridSpace(gridSpace * 10);
+ }
+ render() {
+ const gridSpace = this.chooseGridSpace(NumCast(this.props.layoutDoc["_backgroundGrid-spacing"], 50));
+ const shiftX = (this.props.isAnnotationOverlay ? 0 : -this.props.panX() % gridSpace - gridSpace) * this.props.zoomScaling();
+ const shiftY = (this.props.isAnnotationOverlay ? 0 : -this.props.panY() % gridSpace - gridSpace) * this.props.zoomScaling();
+ const renderGridSpace = gridSpace * this.props.zoomScaling();
+ const w = this.props.PanelWidth() + 2 * renderGridSpace;
+ const h = this.props.PanelHeight() + 2 * renderGridSpace;
+ const strokeStyle = CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "rgba(255,255,255,0.5)" : "rgba(0, 0,0,0.5)";
+ return <canvas className="collectionFreeFormView-grid" width={w} height={h} style={{ transform: `translate(${shiftX}px, ${shiftY}px)` }}
+ ref={(el) => {
+ const ctx = el?.getContext('2d');
+ if (ctx) {
+ const Cx = this.props.cachedCenteringShiftX % renderGridSpace;
+ const Cy = this.props.cachedCenteringShiftY % renderGridSpace;
+ ctx.lineWidth = Math.min(1, Math.max(0.5, this.props.zoomScaling()));
+ ctx.setLineDash(gridSpace > 50 ? [3, 3] : [1, 5]);
+ ctx.clearRect(0, 0, w, h);
+ if (ctx) {
+ ctx.strokeStyle = strokeStyle;
+ ctx.beginPath();
+ for (let x = Cx - renderGridSpace; x <= w - Cx; x += renderGridSpace) {
+ ctx.moveTo(x, Cy - h);
+ ctx.lineTo(x, Cy + h);
+ }
+ for (let y = Cy - renderGridSpace; y <= h - Cy; y += renderGridSpace) {
+ ctx.moveTo(Cx - w, y);
+ ctx.lineTo(Cx + w, y);
+ }
+ ctx.stroke();
+ }
+ }
+ }} />;
+ }
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index d67122eff..9466d8753 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -74,7 +74,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
{ fireImmediately: true }
);
}
- protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+ protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view
this._dropDisposer && this._dropDisposer();
if (ele) {
this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 460982c8a..235c8accb 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -18,17 +18,18 @@ import { StyleProp } from "../StyleProvider";
import "./CollectionFreeFormDocumentView.scss";
import { DocumentView, DocumentViewProps } from "./DocumentView";
import React = require("react");
+import { Id } from "../../../fields/FieldSymbols";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined;
layerProvider: ((doc: Doc, assign?: boolean) => boolean) | undefined;
+ renderCutoffProvider: (doc: Doc) => boolean;
zIndex?: number;
highlight?: boolean;
jitterRotation: number;
dataTransition?: string;
replica: string;
- renderCutoff: () => number;
renderIndex: number;
CollectionFreeFormView: CollectionFreeFormView;
}
@@ -178,10 +179,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
mixBlendMode,
display: this.ZInd === -99 ? "none" : undefined
}} >
- {this.props.renderCutoff() >= this.props.renderIndex ?
- <DocumentView {...divProps} ref={action((r: DocumentView | null) => this._contentView = r)} />
+ {this.props.renderCutoffProvider(this.props.Document) ?
+ <div style={{ position: "absolute", width: this.panelWidth(), height: this.panelHeight(), background: "lightGreen" }} />
:
- <div style={{ position: "absolute", width: this.panelWidth(), height: this.panelHeight(), background: "lightGreen" }}></div>}
+ <DocumentView {...divProps} ref={action((r: DocumentView | null) => this._contentView = r)} />
+ }
</div>;
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 91f2359af..6468913fb 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -986,7 +986,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
captionStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewInternalProps>, property: string) => this.props?.styleProvider?.(doc, props, property + ":caption");
@computed get innards() {
TraceMobx();
- const ffscale = (this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1);
+ const ffscale = () => (this.props.DocumentView().props.CollectionFreeFormDocumentView?.().props.ScreenToLocalTransform().Scale || 1);
const showTitle = this.ShowTitle?.split(":")[0];
const showTitleHover = this.ShowTitle?.includes(":hover");
const showCaption = !this.props.hideCaptions && this.Document._viewType !== CollectionViewType.Carousel ? StrCast(this.layoutDoc._showCaption) : undefined;
@@ -994,14 +994,14 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
<div className="documentView-captionWrapper"
style={{
pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : this.isContentActive() || this.props.isDocumentActive?.() ? "all" : undefined,
- minWidth: 50 * ffscale,
- maxHeight: `max(100%, ${20 * ffscale}px)`
+ minWidth: 50 * ffscale(),
+ maxHeight: `max(100%, ${20 * ffscale()}px)`
}}>
<FormattedTextBox {...OmitKeys(this.props, ['children']).omit}
yPadding={10}
xPadding={10}
fieldKey={showCaption}
- fontSize={12 * Math.max(1, 2 * ffscale / 3)}
+ fontSize={12 * Math.max(1, 2 * ffscale() / 3)}
styleProvider={this.captionStyleProvider}
dontRegisterView={true}
noSidebar={true}