diff options
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3d6b53ccc..30d5a5184 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,6 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { Dropdown, DropdownType, Type } from 'browndash-components'; -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 { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; @@ -136,7 +136,7 @@ export interface DocComponentView { componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null; incrementalRendering?: () => void; layout_fitWidth?: () => boolean; // whether the component always fits width (eg, KeyValueBox) - overridePointerEvents?: () => 'all' | 'none' | undefined; // if the conmponent overrides the pointer events for the document + overridePointerEvents?: () => 'all' | 'none' | undefined; // if the conmponent overrides the pointer events for the document (e.g, KeyValueBox always allows pointer events) fieldKey?: string; annotationKey?: string; getTitle?: () => string; @@ -272,8 +272,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps return this._animateScaleTime ?? 100; } public get displayName() { - return 'DocumentView(' + this.props.Document.title + ')'; + return 'DocumentViewInternal(' + this.props.Document.title + ')'; } // this makes mobx trace() statements more descriptive + public get ContentDiv() { return this._mainCont.current; } @@ -317,8 +318,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @computed get titleHeight() { return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.TitleHeight) || 0; } + @observable _pointerEvents: 'none' | 'all' | 'visiblePainted' | undefined; @computed get pointerEvents(): 'none' | 'all' | 'visiblePainted' | undefined { - return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents); + TraceMobx(); + return this._pointerEvents; } @computed get finalLayoutKey() { return StrCast(this.Document.layout_fieldKey, 'layout'); @@ -330,6 +333,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps return this.props.NativeHeight(); } @computed get disableClickScriptFunc() { + TraceMobx(); const onScriptDisable = this.props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable; // prettier-ignore return ( @@ -356,6 +360,25 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } componentDidMount() { this.setupHandlers(); + this._disposers.contentActive = reaction( + () => { + // true - if the document has been activated directly or indirectly (by having its children selected) + // false - if its pointer events are explicitly turned off or if it's container tells it that it's inactive + // undefined - it is not active, but it should be responsive to actions that might activate it or its contents (eg clicking) + return this.props.isContentActive() === false || this.props.pointerEvents?.() === 'none' + ? false + : Doc.ActiveTool !== InkTool.None || SnappingManager.GetCanEmbed() || this.rootSelected() || this.rootDoc.forceActive || this._componentView?.isAnyChildContentActive?.() || this.props.isContentActive() + ? true + : undefined; + }, + active => (this._isContentActive = active), + { fireImmediately: true } + ); + this._disposers.pointerevents = reaction( + () => this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents), + pointerevents => (this._pointerEvents = pointerevents), + { fireImmediately: true } + ); } preDropFunc = (e: Event, de: DragManager.DropEvent) => { const dropAction = this.layoutDoc.dropAction as dropActionType; @@ -883,23 +906,22 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps onClickFunc: any = () => (this.disableClickScriptFunc ? undefined : this.onClickHandler); setHeight = (height: number) => (this.layoutDoc._height = height); setContentView = action((view: { getAnchor?: (addAsAnnotation: boolean) => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view)); - @computed get _isContentActive() { - // true - if the document has been activated directly or indirectly (by having its children selected) - // false - if its pointer events are explicitly turned off or if it's container tells it that it's inactive - // undefined - it is not active, but it should be responsive to actions that might active it or its contents (eg clicking) - return this.props.isContentActive() === false || this.props.pointerEvents?.() === 'none' - ? false - : Doc.ActiveTool !== InkTool.None || SnappingManager.GetIsDragging() || this.rootSelected() || this.rootDoc.forceActive || this._componentView?.isAnyChildContentActive?.() || this.props.isContentActive() - ? true - : undefined; - } + @observable _isContentActive: boolean | undefined; + isContentActive = (): boolean | undefined => this._isContentActive; childFilters = () => [...this.props.childFilters(), ...StrListCast(this.layoutDoc.childFilters)]; /// disable pointer events on content when there's an enabled onClick script (but not the browse script) and the contents aren't forced active, or if contents are marked inactive @computed get _contentPointerEvents() { - if (this.props.contentPointerEvents) return this.props.contentPointerEvents; - return (!this.disableClickScriptFunc && this.onClickHandler && !this.props.onBrowseClick?.() && this.isContentActive() !== true) || this.isContentActive() === false ? 'none' : this.pointerEvents; + TraceMobx(); + return this.props.contentPointerEvents ?? + ((!this.disableClickScriptFunc && // + this.onClickHandler && + !this.props.onBrowseClick?.() && + this.isContentActive() !== true) || + this.isContentActive() === false) + ? 'none' + : this.pointerEvents; } contentPointerEvents = () => this._contentPointerEvents; @computed get contents() { @@ -1304,8 +1326,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} - onPointerEnter={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.rootDoc)} - onPointerOver={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.rootDoc)} + onPointerEnter={e => (!SnappingManager.GetIsDragging() || SnappingManager.GetCanEmbed()) && Doc.BrushDoc(this.rootDoc)} + onPointerOver={e => (!SnappingManager.GetIsDragging() || SnappingManager.GetCanEmbed()) && Doc.BrushDoc(this.rootDoc)} onPointerLeave={e => !isParentOf(this.ContentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.rootDoc)} style={{ borderRadius: this.borderRounding, @@ -1426,9 +1448,9 @@ export class DocumentView extends React.Component<DocumentViewProps> { @computed get hideLinkButton() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkBtn + (this.isSelected() ? ':selected' : '')); } + hideLinkCount = () => this.props.renderDepth === -1 || (this.isSelected() && this.props.renderDepth) || !this._isHovering || this.hideLinkButton; @computed get linkCountView() { - const hideCount = this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (this.isSelected() && this.props.renderDepth) || !this._isHovering || this.hideLinkButton; - return hideCount ? null : <DocumentLinksButton View={this} scaling={this.scaleToScreenSpace} OnHover={true} Bottom={this.topMost} ShowCount={true} />; + return <DocumentLinksButton hideCount={this.hideLinkCount} View={this} scaling={this.scaleToScreenSpace} OnHover={true} Bottom={this.topMost} ShowCount={true} />; } @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; |