diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/ComparisonBox.tsx | 44 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentIcon.tsx | 31 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkAnchorBox.tsx | 26 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkBox.tsx | 48 |
4 files changed, 98 insertions, 51 deletions
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 72a473114..62523ba00 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -1,9 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable, override } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt } from '../../../fields/Doc'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; +import { copyProps, emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; @@ -24,14 +24,26 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl @observable _animating = ''; + _prevProps: ViewBoxAnnotatableProps & FieldViewProps; + @override _props: ViewBoxAnnotatableProps & FieldViewProps; + constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + + componentDidUpdate() { + copyProps(this); + } + @computed get clipWidth() { return NumCast(this.layoutDoc[this.clipWidthKey], 50); } get clipWidthKey() { - return '_' + this.props.fieldKey + '_clipWidth'; + return '_' + this._props.fieldKey + '_clipWidth'; } componentDidMount() { - this.props.setContentView?.(this); + this._props.setContentView?.(this); } protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => { this._disposers[disposerId]?.(); @@ -72,7 +84,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl if (this._isAnyChildContentActive) return; this._animating = 'all 200ms'; // on click, animate slider movement to the targetWidth - this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this.props.PanelWidth(); + this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth(); setTimeout( action(() => (this._animating = '')), 200 @@ -84,9 +96,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl @action private onPointerMove = ({ movementX }: PointerEvent) => { - const width = movementX * this.props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this.props.PanelWidth(); - if (width && width > 5 && width < this.props.PanelWidth()) { - this.layoutDoc[this.clipWidthKey] = (width * 100) / this.props.PanelWidth(); + const width = movementX * this._props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this._props.PanelWidth(); + if (width && width > 5 && width < this._props.PanelWidth()) { + this.layoutDoc[this.clipWidthKey] = (width * 100) / this._props.PanelWidth(); } return false; }; @@ -146,7 +158,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl }; docStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => { if (property === StyleProp.PointerEvents) return 'none'; - return this.props.styleProvider?.(doc, props, property); + return this._props.styleProvider?.(doc, props, property); }; moveDoc1 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_1'), true); moveDoc2 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true); @@ -171,7 +183,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl return targetDoc ? ( <> <DocumentView - {...this.props} + {...this._props} Document={targetDoc} TemplateDataDocument={undefined} moveDocument={which.endsWith('1') ? this.moveDoc1 : this.moveDoc2} @@ -181,7 +193,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl isContentActive={emptyFunction} isDocumentActive={returnFalse} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} - styleProvider={this._isAnyChildContentActive ? this.props.styleProvider : this.docStyleProvider} + styleProvider={this._isAnyChildContentActive ? this._props.styleProvider : this.docStyleProvider} hideLinkButton={true} pointerEvents={this._isAnyChildContentActive ? undefined : returnNone} /> @@ -195,15 +207,15 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl }; const displayBox = (which: string, index: number, cover: number) => { return ( - <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this.props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> + <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this._props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}> {displayDoc(which)} </div> ); }; return ( - <div className={`comparisonBox${this.props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}> - {displayBox(`${this.fieldKey}_2`, 1, this.props.PanelWidth() - 3)} + <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}> + {displayBox(`${this.fieldKey}_2`, 1, this._props.PanelWidth() - 3)} <div className="clip-div" style={{ width: this.clipWidth + '%', transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, 'gray') }}> {displayBox(`${this.fieldKey}_1`, 0, 0)} </div> @@ -212,9 +224,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl className="slide-bar" style={{ left: `calc(${this.clipWidth + '%'} - 0.5px)`, - cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined, + cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this._props.PanelWidth() - 5) / this._props.PanelWidth() ? 'w-resize' : undefined, }} - onPointerDown={e => !this._isAnyChildContentActive && this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ + onPointerDown={e => !this._isAnyChildContentActive && this.registerSliding(e, this._props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ > <div className="slide-handle" /> </div> diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index e8d8c05e3..0c780af2a 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -5,20 +5,35 @@ import { DocumentManager } from '../../util/DocumentManager'; import { Transformer, ts } from '../../util/Scripting'; import { Field } from '../../../fields/Doc'; import { Tooltip } from '@mui/material'; -import { action, observable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { Id } from '../../../fields/FieldSymbols'; import { factory } from 'typescript'; import { LightboxView } from '../LightboxView'; import { SettingsManager } from '../../util/SettingsManager'; +import { copyProps } from '../../../Utils'; -@observer -export class DocumentIcon extends React.Component<{ view: DocumentView; index: number }> { +interface DocumentIconProps { + view: DocumentView; + index: number; +} +export class DocumentIcon extends React.Component<DocumentIconProps> { @observable _hovered = false; + _prevProps: DocumentIconProps; + @observable _props: DocumentIconProps; + constructor(props: DocumentIconProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate() { + copyProps(this); + } + static get DocViews() { - return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v.props.docViewPath())) : DocumentManager.Instance.DocumentViews; + return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v._props.docViewPath())) : DocumentManager.Instance.DocumentViews; } render() { - const view = this.props.view; + const view = this._props.view; const { left, top, right, bottom } = view.getBounds() || { left: 0, top: 0, right: 0, bottom: 0 }; return ( @@ -33,8 +48,8 @@ export class DocumentIcon extends React.Component<{ view: DocumentView; index: n background: SettingsManager.userBackgroundColor, transform: `translate(${(left + right) / 2}px, ${top}px)`, }}> - <Tooltip title={<>{this.props.view.Document.title}</>}> - <p>d{this.props.index}</p> + <Tooltip title={<>{this._props.view.Document.title}</>}> + <p>d{this._props.index}</p> </Tooltip> </div> ); @@ -74,7 +89,7 @@ export class DocumentIconContainer extends React.Component { getVars() { const docs = DocumentIcon.DocViews; const capturedVariables: { [name: string]: Field } = {}; - usedDocuments.forEach(index => (capturedVariables[`d${index}`] = docs.length > index ? docs[index].props.Document : `d${index}`)); + usedDocuments.forEach(index => (capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`)); return capturedVariables; }, }; diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 09ba0bc95..31aa15588 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable, override } from 'mobx'; import { observer } from 'mobx-react'; import { Doc } from '../../../fields/Doc'; import { NumCast, StrCast } from '../../../fields/Types'; @@ -29,18 +29,26 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { @observable _x = 0; @observable _y = 0; + _prevProps: FieldViewProps; + @override _props: FieldViewProps; + constructor(props: FieldViewProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidMount() { - this.props.setContentView?.(this); + this._props.setContentView?.(this); } @computed get linkSource() { - return this.props.docViewPath()[this.props.docViewPath().length - 2].Document; // this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.LinkSource); + return this._props.docViewPath()[this._props.docViewPath().length - 2].Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource); } onPointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => { if (doubleTap) LinkFollower.FollowLink(this.Document, this.linkSource, false); - else this.props.select(false); + else this._props.select(false); }); }; onPointerMove = action((e: PointerEvent, down: number[], delta: number[]) => { @@ -68,16 +76,16 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { render() { TraceMobx(); - const small = this.props.PanelWidth() <= 1; // this happens when rendered in a treeView + const small = this._props.PanelWidth() <= 1; // this happens when rendered in a treeView const x = NumCast(this.layoutDoc[this.fieldKey + '_x'], 100); const y = NumCast(this.layoutDoc[this.fieldKey + '_y'], 100); - const background = this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.BackgroundColor + ':anchor'); + const background = this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.BackgroundColor + ':anchor'); const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1'; const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title); - const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1') + const selView = SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1') ? 'link_anchor_1' - : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2') + : SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2') ? 'link_anchor_2' : ''; return ( @@ -87,7 +95,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { className={`linkAnchorBox-cont${small ? '-small' : ''}`} onPointerEnter={e => LinkInfo.SetLinkInfo({ - docProps: this.props, + docProps: this._props, linkSrc: this.linkSource, linkDoc: this.Document, showHeader: true, diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index ff2597fb4..acafd6d09 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import { Bezier } from 'bezier-js'; -import { computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; +import { aggregateBounds, copyProps, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; import { Transform } from '../../util/Transform'; import { CollectionFreeFormView } from '../collections/collectionFreeForm'; @@ -20,21 +20,33 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { return FieldView.LayoutString(LinkBox, fieldKey); } + _prevProps: FieldViewProps; + @override _props: FieldViewProps; + constructor(props: FieldViewProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + + componentDidUpdate() { + copyProps(this); + } + onClickScriptDisable = returnAlways; @computed get anchor1() { const anchor1 = DocCast(this.dataDoc.link_anchor_1); const anchor_1 = anchor1?.layout_unrendered ? DocCast(anchor1.annotationOn) : anchor1; - return DocumentManager.Instance.getDocumentView(anchor_1, this.props.docViewPath()[this.props.docViewPath().length - 2]); // this.props.docViewPath().lastElement()); + return DocumentManager.Instance.getDocumentView(anchor_1, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement()); } @computed get anchor2() { const anchor2 = DocCast(this.dataDoc.link_anchor_2); const anchor_2 = anchor2?.layout_unrendered ? DocCast(anchor2.annotationOn) : anchor2; - return DocumentManager.Instance.getDocumentView(anchor_2, this.props.docViewPath()[this.props.docViewPath().length - 2]); // this.props.docViewPath().lastElement()); + return DocumentManager.Instance.getDocumentView(anchor_2, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement()); } screenBounds = () => { if (this.layoutDoc._layout_isSvg && this.anchor1 && this.anchor2 && this.anchor1.CollectionFreeFormView) { - const a_invXf = this.anchor1.props.ScreenToLocalTransform().inverse(); - const b_invXf = this.anchor2.props.ScreenToLocalTransform().inverse(); + const a_invXf = this.anchor1._props.ScreenToLocalTransform().inverse(); + const b_invXf = this.anchor2._props.ScreenToLocalTransform().inverse(); const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(NumCast(this.anchor1.Document._width), NumCast(this.anchor1.Document._height)) }; const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(NumCast(this.anchor2.Document._width), NumCast(this.anchor2.Document._height)) }; @@ -54,17 +66,17 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { }; disposer: IReactionDisposer | undefined; componentDidMount() { - this.props.setContentView?.(this); + this._props.setContentView?.(this); this.disposer = reaction( () => { if (this.layoutDoc._layout_isSvg && (this.anchor1 || this.anchor2)?.CollectionFreeFormView) { const a = (this.anchor1 ?? this.anchor2)!; const b = (this.anchor2 ?? this.anchor1)!; - const parxf = this.props.docViewPath()[this.props.docViewPath().length - 2].ComponentView as CollectionFreeFormView; - const this_xf = parxf?.screenToLocalXf ?? Transform.Identity; //this.props.ScreenToLocalTransform(); - const a_invXf = a.props.ScreenToLocalTransform().inverse(); - const b_invXf = b.props.ScreenToLocalTransform().inverse(); + const parxf = this._props.docViewPath()[this._props.docViewPath().length - 2].ComponentView as CollectionFreeFormView; + const this_xf = parxf?.screenToLocalXf ?? Transform.Identity; //this._props.ScreenToLocalTransform(); + const a_invXf = a._props.ScreenToLocalTransform().inverse(); + const b_invXf = b._props.ScreenToLocalTransform().inverse(); const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(NumCast(a.Document._width), NumCast(a.Document._height)) }; const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(NumCast(b.Document._width), NumCast(b.Document._height)) }; const a_bds = { tl: this_xf.transformPoint(a_scrBds.tl[0], a_scrBds.tl[1]), br: this_xf.transformPoint(a_scrBds.br[0], a_scrBds.br[1]) }; @@ -106,7 +118,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { @observable renderProps: { lx: number; rx: number; ty: number; by: number; pts: number[][] } | undefined = undefined; render() { if (this.renderProps) { - const highlight = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Highlighting); + const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting); const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined; const bez = new Bezier(this.renderProps.pts.map(p => ({ x: p[0], y: p[1] }))); @@ -131,7 +143,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { <path className="collectionfreeformlinkview-linkLine" style={{ - pointerEvents: this.props.pointerEvents?.() === 'none' ? 'none' : 'visibleStroke', // + pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'visibleStroke', // stroke: highlightColor ?? 'lightblue', strokeDasharray, strokeWidth, @@ -142,7 +154,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { /> <text filter={`url(#${this.Document[Id] + 'background'})`} - style={{ pointerEvents: this.props.pointerEvents?.() === 'none' ? 'none' : 'all', textAnchor: 'middle', fontSize: '12', stroke: 'black' }} + style={{ pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'all', textAnchor: 'middle', fontSize: '12', stroke: 'black' }} x={text.x - lx} y={text.y - ty}> <tspan> </tspan> @@ -154,14 +166,14 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { ); } return ( - <div className={`linkBox-container${this.props.isContentActive() ? '-interactive' : ''}`} style={{ background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor) }}> + <div className={`linkBox-container${this._props.isContentActive() ? '-interactive' : ''}`} style={{ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }}> <ComparisonBox - {...this.props} + {...this._props} fieldKey="link_anchor" setHeight={emptyFunction} dontRegisterView={true} - renderDepth={this.props.renderDepth + 1} - isContentActive={this.props.isContentActive} + renderDepth={this._props.renderDepth + 1} + isContentActive={this._props.isContentActive} addDocument={returnFalse} removeDocument={returnFalse} moveDocument={returnFalse} |
