diff options
author | bobzel <zzzman@gmail.com> | 2024-05-16 11:28:10 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-05-16 11:28:10 -0400 |
commit | 41e47a7b7789e8c192fb31188cf549178ec71a22 (patch) | |
tree | c94ee8ab0e952d633f21483ec8e450a471d2c925 | |
parent | fdd0e62c148fde01c82504700a83fcc56463a68d (diff) |
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.
7 files changed, 53 insertions, 60 deletions
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<Doc>, props: Opt<FieldViewProps & if (SnappingManager.LastPressedBtn === doc?.[Id]) return SnappingManager.userColor; // hack to indicate active menu panel item const dataKey = doc ? Doc.LayoutFieldKey(doc) : ""; const usePath = StrCast(doc?.[dataKey + "_usePath"]); - const alternate = usePath.includes(":hover") ? ( doc?.isHovering ? '_' + usePath.replace(":hover","") : "") : usePath ? "_" +usePath:usePath; + const alternate = usePath.includes(":hover") ? ( props?.isHovering?.() ? '_' + usePath.replace(":hover","") : "") : usePath ? "_" +usePath:usePath; let docColor: Opt<string> = 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<Doc>, props: Opt<FieldViewProps>, 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<Partial<collection const fromScreenXf = NumCast(refDoc.z) ? this.ScreenToLocalBoxXf() : this.screenToFreeformContentsXf; const [xpo, ypo] = fromScreenXf.transformPoint(de.x, de.y); const [x, y] = [xpo - docDragData.offset[0], ypo - docDragData.offset[1]]; - const zsorted = this.childLayoutPairs - .map(pair => 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<Partial<collection const rotation = Cast(_rotation,'number', !this.layoutDoc._rotation_jitter ? null : NumCast(this.layoutDoc._rotation_jitter) * random(-1, 1, NumCast(x), NumCast(y)) ); - const childProps = { ...this._props, fieldKey: '', styleProvider: this._clusters.styleProvider }; return { x: isNaN(NumCast(x)) ? 0 : NumCast(x), y: isNaN(NumCast(y)) ? 0 : NumCast(y), z: Cast(z, 'number'), autoDim, rotation, - color: Cast(color, 'string') ? StrCast(color) : this._clusters.styleProvider(childDoc, childProps, StyleProp.Color), - backgroundColor: Cast(backgroundColor, 'string') ? StrCast(backgroundColor) : this._clusters.styleProvider(childDoc, childProps, StyleProp.BackgroundColor), - opacity: !_width ? 0 : this._keyframeEditing ? 1 : Cast(opacity, 'number') ?? this._clusters.styleProvider?.(childDoc, childProps, StyleProp.Opacity), + color: Cast(color, 'string', null), + backgroundColor: Cast(backgroundColor, 'string', null), + opacity: !_width ? 0 : this._keyframeEditing ? 1 : Cast(opacity, 'number', null), zIndex: Cast(zIndex, 'number'), width: _width, height: _height, @@ -1209,6 +1210,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } doFreeformLayout(poolData: Map<string, PoolData>) { + 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<Partial<collection }) ); - this._clusters.initLayout(); return elements; }; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 62c4cc61a..d65e2d65e 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -126,15 +126,16 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF PanelHeight = () => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore styleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, 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<DocumentViewProps>() { 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<DocumentViewProps>() { <DocumentViewInternal {...this._props} parent={undefined} + isHovering={this.isHovering} fieldKey={this.LayoutFieldKey} DataTransition={this.DataTransition} DocumentView={this.selfView} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 3f351a072..818d26956 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -91,6 +91,7 @@ export interface FieldViewProps extends FieldViewSharedProps { docViewPath: () => 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<FormattedTextB } @computed get _fieldKey() { const usePath = this._props.ignoreUsePath ? '' : StrCast(this.layoutDoc[`${this._props.fieldKey}_usePath`]); - return this._props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering || this._props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : ''); + return this._props.fieldKey + (usePath && (!usePath.includes(':hover') || this._props.isHovering?.() || this._props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : ''); } - @observable _isHovering = false; onPassiveWheel = (e: WheelEvent) => { if (e.clientX > this.ProseRef!.getBoundingClientRect().right) { return; @@ -2038,11 +2037,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB return styleFromLayout?.height === '0px' ? null : ( <div className="formattedTextBox" - onPointerEnter={action(() => { - 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; |