From 41e47a7b7789e8c192fb31188cf549178ec71a22 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 16 May 2024 11:28:10 -0400 Subject: moved isHovering to DocumentView as instance variable instead from FormattedText as a Document field. cleaned up cluster style provider. fixed freeformView to not trigger as many updates when a doc is dropped, and fixed layoutEngines to not return a background or color unless actually set by the engine. --- src/client/views/StyleProvider.tsx | 2 +- .../CollectionFreeFormClusters.ts | 16 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 71 +++++++++++----------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 13 ++-- src/client/views/nodes/DocumentView.tsx | 2 + src/client/views/nodes/FieldView.tsx | 1 + .../views/nodes/formattedText/FormattedTextBox.tsx | 8 +-- 7 files changed, 53 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3842f930a..557f7db37 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -218,7 +218,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt = StrCast(doc?.[fieldKey+alternate], StrCast(doc?.['backgroundColor' +alternate], isCaption ? 'rgba(0,0,0,0.4)' : '')); if (doc?.[StrCast(doc?.layout_fieldKey)] instanceof Doc) docColor = StrCast(doc._backgroundColor,docColor) // prettier-ignore diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts b/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts index 26a52cd2a..6415d5225 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormClusters.ts @@ -2,7 +2,7 @@ import { action, observable } from 'mobx'; import { CollectionFreeFormView } from '.'; import { intersectRect } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; -import { NumCast, StrCast } from '../../../../fields/Types'; +import { Cast, NumCast, StrCast } from '../../../../fields/Types'; import { DocumentType } from '../../../documents/DocumentTypes'; import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; @@ -179,7 +179,6 @@ export class CollectionFreeFormClusters { }; styleProvider = (doc: Opt, props: Opt, property: string) => { - let styleProp = this.viewStyleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 if (doc && this.childDocs?.includes(doc)) switch (property.split(':')[0]) { case StyleProp.BackgroundColor: @@ -189,14 +188,9 @@ export class CollectionFreeFormClusters { if (this._clusterSets.length <= cluster) { setTimeout(() => doc && this.addDocument(doc)); } else { - // choose a cluster color from a palette - const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)']; - styleProp = colors[cluster % colors.length]; - const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor); - // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document - set?.forEach(s => { - styleProp = StrCast(s.backgroundColor); - }); + const palette = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)']; + // override palette cluster color with an explicitly set cluster doc color + return this._clusterSets[cluster]?.reduce((b, s) => StrCast(s.backgroundColor, b), palette[cluster % palette.length]); } } } @@ -208,7 +202,7 @@ export class CollectionFreeFormClusters { break; default: } - return styleProp; + return this.viewStyleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 }; tryToSelect = (addToSel: boolean) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 53493a968..cc195385b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -404,38 +404,40 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout) - .slice() - .sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); - zsorted.forEach((doc, index) => { - doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1; - }); - const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); - const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)]; - - docDragData.droppedDocuments.forEach((d, i) => { - const layoutDoc = Doc.Layout(d); - const delta = Utils.rotPt(x - dropPos[0], y - dropPos[1], fromScreenXf.Rotate); - if (this.Document._currentFrame !== undefined) { - CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false); - const pvals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); // get filled in values (uses defaults when not value is specified) for position - const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000), false); // get non-default values for everything else - vals.x = NumCast(pvals.x) + delta.x; - vals.y = NumCast(pvals.y) + delta.y; - CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals); - } else { - d.x = NumCast(d.x) + delta.x; - d.y = NumCast(d.y) + delta.y; - } - d._layout_modificationDate = new DateField(); - const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)]; - layoutDoc._width = NumCast(layoutDoc._width, 300); - layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300); - !d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront + runInAction(() => { + // needs to be in action to avoid having each edit trigger a freeform layout engine recompute - this triggers just one for each document at the end + const zsorted = this.childLayoutPairs + .map(pair => pair.layout) // + .sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex)); + zsorted.forEach((doc, index) => { + doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1; + }); + const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000)); + const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)]; + + docDragData.droppedDocuments.forEach((d, i) => { + const layoutDoc = Doc.Layout(d); + const delta = Utils.rotPt(x - dropPos[0], y - dropPos[1], fromScreenXf.Rotate); + if (this.Document._currentFrame !== undefined) { + CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false); + const pvals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); // get filled in values (uses defaults when not value is specified) for position + const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000), false); // get non-default values for everything else + vals.x = NumCast(pvals.x) + delta.x; + vals.y = NumCast(pvals.y) + delta.y; + CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals); + } else { + d.x = NumCast(d.x) + delta.x; + d.y = NumCast(d.y) + delta.y; + } + d._layout_modificationDate = new DateField(); + const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)]; + layoutDoc._width = NumCast(layoutDoc._width, 300); + layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300); + !d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront + }); + (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this._clusters.addDocuments(docDragData.droppedDocuments); }); - (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this._clusters.addDocuments(docDragData.droppedDocuments); return true; } @@ -1128,16 +1130,15 @@ export class CollectionFreeFormView extends CollectionSubView) { + this._clusters.initLayout(); this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => poolData.set(pair.layout[Id], this.getCalculatedPositions(pair))); return [] as ViewDefResult[]; } @@ -1237,7 +1239,6 @@ export class CollectionFreeFormView extends CollectionSubView this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { - if (doc === this.layoutDoc) { + const overrideProp = () => { switch (property.split(':')[0]) { - case StyleProp.Opacity: return this.Opacity; // only change the opacity for this specific document, not its children + case StyleProp.Opacity: return this.Opacity; case StyleProp.BackgroundColor: return this.BackgroundColor; case StyleProp.Color: return this.Color; - default: - } // prettier-ignore - } - return this._props.styleProvider?.(doc, props, property); + default: return undefined; + }}; // prettier-ignore + + // only override values for this specific document, not any children + return (doc === this.layoutDoc && overrideProp()) ?? this._props.styleProvider?.(doc, props, property); }; public static getValues(doc: Doc, time: number, fillIn: boolean = true) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f56c8288e..66540678d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1383,6 +1383,7 @@ export class DocumentView extends DocComponent() { PanelHeight = () => this.panelHeight; NativeDimScaling = () => this.nativeScaling; hideLinkCount = () => !!this.hideLinkButton; + isHovering = () => this._isHovering; selfView = () => this; /** * @returns Transform to the document view (in the coordinate system of whatever contains the DocumentView) @@ -1449,6 +1450,7 @@ export class DocumentView extends DocComponent() { DocumentView[]; setHeight?: (height: number) => void; NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal + isHovering?: () => boolean; // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React) // See currentUserUtils headerTemplate for examples of creating text boxes from html which set some of these fields diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 93cb67491..de9ba87d3 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1990,9 +1990,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { if (e.clientX > this.ProseRef!.getBoundingClientRect().right) { return; @@ -2038,11 +2037,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - this._isHovering = true; - this.layoutDoc[`_${this._props.fieldKey}_usePath`] && (this.Document.isHovering = true); - })} - onPointerLeave={action(() => { this.Document.isHovering = this._isHovering = false; })} // prettier-ignore ref={r => { this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); this._oldWheel = r; -- cgit v1.2.3-70-g09d2