diff options
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 228 |
1 files changed, 118 insertions, 110 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2a44a9739..4262c2d57 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -5,19 +5,19 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx' import { observer } from 'mobx-react'; import * as React from 'react'; import { FaUndo } from 'react-icons/fa'; -import { Utils, emptyFunction, lightOrDark, numberValue, returnFalse, setupMoveUpEvents } from '../../Utils'; +import { lightOrDark, returnFalse, setupMoveUpEvents } from '../../ClientUtils'; +import { Utils, emptyFunction, numberValue } from '../../Utils'; import { DateField } from '../../fields/DateField'; -import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; +import { Doc, DocListCast, Field, FieldType, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols'; +import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; import { DocumentType } from '../documents/DocumentTypes'; import { Docs } from '../documents/Documents'; -import { DocumentManager } from '../util/DocumentManager'; import { DragManager } from '../util/DragManager'; -import { SelectionManager } from '../util/SelectionManager'; import { SettingsManager } from '../util/SettingsManager'; import { SnappingManager } from '../util/SnappingManager'; import { UndoManager } from '../util/UndoManager'; @@ -30,11 +30,11 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { Colors } from './global/globalEnums'; -import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; +import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; +import { DocumentView } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; -import { KeyValueBox } from './nodes/KeyValueBox'; +import { OpenWhereMod } from './nodes/OpenWhere'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { identity } from 'lodash'; interface DocumentDecorationsProps { PanelWidth: number; @@ -44,6 +44,7 @@ interface DocumentDecorationsProps { } @observer export class DocumentDecorations extends ObservableReactComponent<DocumentDecorationsProps> { + // eslint-disable-next-line no-use-before-define static Instance: DocumentDecorations; private _resizeHdlId = ''; private _keyinput = React.createRef<HTMLInputElement>(); @@ -77,14 +78,14 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora let inputting = false; if (this._titleControlString.startsWith('$')) { const titleFieldKey = this._titleControlString.substring(1); - if (SelectionManager.Views[0]?.Document[titleFieldKey] !== this._accumulatedTitle) { + if (DocumentView.Selected()[0]?.Document[titleFieldKey] !== this._accumulatedTitle) { inputting = true; } } const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2}; const {x,y} = Utils.rotPt(e.clientX - center.x, e.clientY - center.y, - NumCast(SelectionManager.Views.lastElement()?.screenToViewTransform().Rotate)); + NumCast(DocumentView.Selected().lastElement()?.screenToViewTransform().Rotate)); (this._showNothing = !inputting && !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && // (this.Bounds.x > center.x+x || this.Bounds.r < center.x+x || this.Bounds.y > center.y+y || this.Bounds.b < center.y+y ))); @@ -106,7 +107,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora @computed get Bounds() { return (SnappingManager.IsLinkFollowing || SnappingManager.ExploreMode) ? { x: 0, y: 0, r: 0, b: 0 } - : SelectionManager.Views + : DocumentView.Selected() .filter(dv => dv._props.renderDepth > 0) .map(dv => dv.getBounds) .reduce((bounds, rect) => !rect ? bounds @@ -123,17 +124,19 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora this._titleControlString = this._accumulatedTitle; } else if (this._titleControlString.startsWith('$')) { if (this._accumulatedTitle.startsWith('-->#')) { - SelectionManager.Docs.forEach(doc => (doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`))); + DocumentView.SelectedDocs().forEach(doc => { + doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`); + }); } const titleFieldKey = this._titleControlString.substring(1); UndoManager.RunInBatch( () => titleFieldKey && - SelectionManager.Views.forEach(d => { + DocumentView.Selected().forEach(dv => { if (titleFieldKey === 'title') { - d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); + dv.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); } - KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); + Doc.SetField(dv.Document, titleFieldKey, this._accumulatedTitle); }), 'edit title' ); @@ -148,23 +151,23 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; onContainerDown = (e: React.PointerEvent) => { - const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document); - if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) { - setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), emptyFunction, emptyFunction); + const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.Selected()[0].Document); + if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) { + setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(true, moveEv), emptyFunction, emptyFunction); e.stopPropagation(); } }; onTitleDown = (e: React.PointerEvent) => { - const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document); - if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) { + const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.SelectedDocs()[0]); + if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) { setupMoveUpEvents( this, e, - e => this.onBackgroundMove(true, e), + moveEv => this.onBackgroundMove(true, moveEv), emptyFunction, - action(e => { - const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined; + action(() => { + const selected = DocumentView.SelectedDocs().length === 1 ? DocumentView.SelectedDocs()[0] : undefined; !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString); this._editingTitle = true; this._keyinput.current && setTimeout(this._keyinput.current.focus); @@ -175,24 +178,21 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; onBackgroundDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, e => this.onBackgroundMove(false, e), emptyFunction, emptyFunction); + setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(false, moveEv), emptyFunction, emptyFunction); e.stopPropagation(); }; @action onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => { - const dragDocView = SelectionManager.Views[0]; + const dragDocView = DocumentView.Selected()[0]; const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document); - if (effectiveLayoutAcl != AclAdmin && effectiveLayoutAcl != AclEdit && effectiveLayoutAcl != AclAugment) { + if (effectiveLayoutAcl !== AclAdmin && effectiveLayoutAcl !== AclEdit && effectiveLayoutAcl !== AclAugment) { return false; } const containers = new Set<Doc | undefined>(); - SelectionManager.Views.forEach(v => containers.add(DocCast(v.Document.embedContainer))); + DocumentView.Selected().forEach(v => containers.add(DocCast(v.Document.embedContainer))); if (containers.size > 1) return false; const { left, top } = dragDocView.getBounds || { left: 0, top: 0 }; - const dragData = new DragManager.DocumentDragData( - SelectionManager.Views.map(dv => dv.Document), - dragDocView._props.dropAction - ); + const dragData = new DragManager.DocumentDragData(DocumentView.SelectedDocs(), dragDocView._props.dropAction); dragData.offset = dragDocView.screenToContentsTransform().transformDirection(e.x - left, e.y - top); dragData.moveDocument = dragDocView._props.moveDocument; dragData.removeDocument = dragDocView._props.removeDocument; @@ -200,12 +200,14 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora dragData.canEmbed = dragTitle; this._hidden = true; DragManager.StartDocumentDrag( - SelectionManager.Views.map(dv => dv.ContentDiv!), + DocumentView.Selected().map(dv => dv.ContentDiv!), dragData, e.x, e.y, { - dragComplete: action(e => (this._hidden = false)), + dragComplete: action(() => { + this._hidden = false; + }), hideSource: true, } ); @@ -215,22 +217,23 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora _deleteAfterIconify = false; _iconifyBatch: UndoManager.Batch | undefined; onCloseClick = (forceDeleteOrIconify: boolean | undefined) => { - const views = SelectionManager.Views.filter(v => v && v._props.renderDepth > 0); + const views = DocumentView.Selected().filter(v => v && v._props.renderDepth > 0); if (forceDeleteOrIconify === false && this._iconifyBatch) return; - this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false; - var iconifyingCount = views.length; + this._deleteAfterIconify = !!(forceDeleteOrIconify || this._iconifyBatch); + let iconifyingCount = views.length; const finished = action((force?: boolean) => { if ((force || --iconifyingCount === 0) && this._iconifyBatch) { if (this._deleteAfterIconify) { views.forEach(iconView => { - Doc.setNativeView(iconView.Document); - if (iconView.Document.activeFrame) { - iconView.Document.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation. + const iconViewDoc = iconView.Document; + Doc.setNativeView(iconViewDoc); + if (iconViewDoc.activeFrame) { + iconViewDoc.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation. } else { iconView._props.removeDocument?.(iconView.Document); } }); - views.forEach(SelectionManager.DeselectView); + views.forEach(DocumentView.DeselectView); } this._iconifyBatch?.end(); this._iconifyBatch = undefined; @@ -240,6 +243,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora (document.activeElement as any).blur?.(); this._iconifyBatch = UndoManager.StartBatch(forceDeleteOrIconify ? 'delete selected docs' : 'iconifying'); } else { + // eslint-disable-next-line no-param-reassign forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes } @@ -248,70 +252,66 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; onMaximizeDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views.lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false); + setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [DocumentView.SelectedDocs().lastElement()]) ?? false, emptyFunction, this.onMaximizeClick, false, false); e.stopPropagation(); }; onMaximizeClick = (e: any): void => { - const selectedDocs = SelectionManager.Views; + const selectedDocs = DocumentView.SelectedDocs(); if (selectedDocs.length) { if (e.ctrlKey) { // open an embedding in a new tab with Ctrl Key - CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0].Document), OpenWhereMod.right); + CollectionDockingView.AddSplit(Doc.BestEmbedding(selectedDocs[0]), OpenWhereMod.right); } else if (e.shiftKey) { // open centered in a new workspace with Shift Key - const embedding = Doc.MakeEmbedding(selectedDocs[0].Document); + const embedding = Doc.MakeEmbedding(selectedDocs[0]); embedding.embedContainer = undefined; embedding.x = -NumCast(embedding._width) / 2; embedding.y = -NumCast(embedding._height) / 2; CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([embedding], { title: 'Tab for ' + embedding.title }), OpenWhereMod.right); } else if (e.altKey) { // open same document in new tab - CollectionDockingView.ToggleSplit(selectedDocs[0].Document, OpenWhereMod.right); + CollectionDockingView.ToggleSplit(selectedDocs[0], OpenWhereMod.right); } else { - var openDoc = selectedDocs[0].Document; + let openDoc = selectedDocs[0]; if (openDoc.layout_fieldKey === 'layout_icon') { openDoc = Doc.GetEmbeddings(openDoc).find(embedding => !embedding.embedContainer) ?? Doc.MakeEmbedding(openDoc); Doc.deiconifyView(openDoc); } - LightboxView.Instance.SetLightboxDoc( - openDoc, - undefined, - selectedDocs.slice(1).map(view => view.Document) - ); + LightboxView.Instance.SetLightboxDoc(openDoc, undefined, selectedDocs.slice(1)); } } - SelectionManager.DeselectAll(); + DocumentView.DeselectAll(); }; onIconifyClick = (): void => { - SelectionManager.Views.forEach(dv => dv?.iconify()); - SelectionManager.DeselectAll(); + DocumentView.Selected().forEach(dv => dv?.iconify()); + DocumentView.DeselectAll(); }; - onSelectContainerDocClick = () => SelectionManager.Views?.[0]?.containerViewPath?.().lastElement()?.select(false); + onSelectContainerDocClick = () => DocumentView.Selected()?.[0]?.containerViewPath?.().lastElement()?.select(false); /** * sets up events when user clicks on the border radius editor */ @action onRadiusDown = (e: React.PointerEvent): void => { - SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()); + SnappingManager.SetIsResizing(DocumentView.SelectedDocs().lastElement()?.[Id]); this._isRounding = true; this._resizeUndo = UndoManager.StartBatch('DocDecs set radius'); setupMoveUpEvents( this, e, - e => { + moveEv => { const [x, y] = [this.Bounds.x + 3, this.Bounds.y + 3]; const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2); - const dist = e.clientX < x && e.clientY < y ? 0 : Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y)); - SelectionManager.Docs.map(doc => { + const dist = moveEv.clientX < x && moveEv.clientY < y ? 0 : Math.sqrt((moveEv.clientX - x) * (moveEv.clientX - x) + (moveEv.clientY - y) * (moveEv.clientY - y)); + DocumentView.SelectedDocs().forEach(doc => { const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2); const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box doc._layout_borderRounding = `${radius}px`; }); return false; }, - action(e => { + action(() => { SnappingManager.SetIsResizing(undefined); this._isRounding = false; this._resizeUndo?.end(); @@ -329,30 +329,31 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora e, returnFalse, // don't care about move or up event, emptyFunction, // just care about whether we get a click event - e => UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => Doc.toggleLockedPosition(doc)), 'toggleBackground') + () => UndoManager.RunInBatch(() => DocumentView.Selected().forEach(dv => Doc.toggleLockedPosition(dv.Document)), 'toggleBackground') ); e.stopPropagation(); }; setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => { + const selDoc = seldocview.Document; const newloccentern = seldocview.screenToContentsTransform().transformPoint(rotCenter[0], rotCenter[1]); const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2]; const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.Document._rotation) / 180) * Math.PI); - seldocview.Document._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); - seldocview.Document._rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height); + selDoc._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width); + selDoc._rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height); }; @action onRotateCenterDown = (e: React.PointerEvent): void => { this._isRotating = true; - const seldocview = SelectionManager.Views[0]; + const seldocview = DocumentView.Selected()[0]; setupMoveUpEvents( this, e, - (e: PointerEvent, down: number[], delta: number[]) => // return false to keep getting events + (moveEv: PointerEvent, down: number[], delta: number[]) => // return false to keep getting events this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]) as any as boolean, - action(e => (this._isRotating = false)), // upEvent - action(e => (seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0)), + action(() => { this._isRotating = false; }), // upEvent + action(() => { seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0; }), true ); // prettier-ignore e.stopPropagation(); @@ -363,11 +364,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora this._isRotating = true; const rcScreen = { X: this.rotCenter[0], Y: this.rotCenter[1] }; const rotateUndo = UndoManager.StartBatch('drag rotation'); - const selectedInk = SelectionManager.Views.filter(i => i.ComponentView instanceof InkingStroke); + const selectedInk = DocumentView.Selected().filter(i => i.ComponentView instanceof InkingStroke); const centerPoint = this.rotCenter.slice(); const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>(); - const seldocview = SelectionManager.Views[0]; - SelectionManager.Views.forEach(dv => { + const seldocview = DocumentView.Selected()[0]; + DocumentView.Selected().forEach(dv => { const accumRot = (NumCast(dv.Document._rotation) / 180) * Math.PI; const localRotCtr = dv.screenToViewTransform().transformPoint(rcScreen.X, rcScreen.Y); const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document.width) / 2, localRotCtr[1] - NumCast(dv.Document.height) / 2]; @@ -376,7 +377,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora infos.set(dv.Document, { unrotatedDocPos, startRotCtr, accumRot }); }); const infoRot = (angle: number, isAbs = false) => { - SelectionManager.Views.forEach( + DocumentView.Selected().forEach( action(dv => { const { unrotatedDocPos, startRotCtr, accumRot } = infos.get(dv.Document)!; const endRotCtr = Utils.rotPt(startRotCtr.x, startRotCtr.y, isAbs ? angle : accumRot + angle); @@ -390,9 +391,9 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora setupMoveUpEvents( this, e, - (e: PointerEvent, down: number[], delta: number[]) => { - const previousPoint = { X: e.clientX, Y: e.clientY }; - const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] }; + (moveEv: PointerEvent, down: number[], delta: number[]) => { + const previousPoint = { X: moveEv.clientX, Y: moveEv.clientY }; + const movedPoint = { X: moveEv.clientX - delta[0], Y: moveEv.clientY - delta[1] }; const deltaAng = InkStrokeProperties.angleChange(movedPoint, previousPoint, rcScreen); if (selectedInk.length) { deltaAng && InkStrokeProperties.Instance.rotateInk(selectedInk, deltaAng, rcScreen); @@ -418,13 +419,15 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora this._isRotating = false; rotateUndo?.end(); }), // upEvent - action(e => (this._showRotCenter = !this._showRotCenter)) // clickEvent + action(() => { + this._showRotCenter = !this._showRotCenter; + }) // clickEvent ); }; @action onPointerDown = (e: React.PointerEvent): void => { - SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them + SnappingManager.SetIsResizing(DocumentView.Selected().lastElement()?.Document[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); e.stopPropagation(); const id = (this._resizeHdlId = e.currentTarget.className); @@ -436,7 +439,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; this._resizeUndo = UndoManager.StartBatch('drag resizing'); this._snapPt = { x: e.pageX, y: e.pageY }; - SelectionManager.Views.forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); + DocumentView.Selected().forEach(docView => CollectionFreeFormView.from(docView)?.dragStarting(false, false)); }; projectDragToAspect = (e: PointerEvent, docView: DocumentView, fixedAspect: number) => { @@ -453,12 +456,12 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const tl = docView.screenToContentsTransform().inverse().transformPoint(0, 0); return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]); }; - onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => { - const first = SelectionManager.Views[0]; + onPointerMove = (e: PointerEvent): boolean => { + const first = DocumentView.Selected()[0]; const effectiveAcl = GetEffectiveAcl(first.Document); - if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false; + if (!(effectiveAcl === AclAdmin || effectiveAcl === AclEdit || effectiveAcl === AclAugment)) return false; if (!first) return false; - var fixedAspect = Doc.NativeAspect(first.layoutDoc); + const fixedAspect = Doc.NativeAspect(first.layoutDoc); const dragHdl = this._resizeHdlId.split(' ')[0].replace('documentDecorations-', '').replace('Resizer', ''); const thisPt = // do snapping of drag point @@ -471,12 +474,12 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora !this._interactionLock && runInAction(async () => { // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate) this._interactionLock = true; this._snapPt = thisPt; - e.ctrlKey && (SelectionManager.Views.forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions())); - const fixedAspect = SelectionManager.Docs.some(this.hasFixedAspect); - const scaleAspect = {x:scale.x === 1 && fixedAspect ? scale.y : scale.x, y: scale.x !== 1 && fixedAspect ? scale.x : scale.y}; - SelectionManager.Views.forEach(docView => + e.ctrlKey && (DocumentView.Selected().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions())); + const hasFixedAspect = DocumentView.Selected().map(dv => dv.Document).some(this.hasFixedAspect); + const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y}; + DocumentView.Selected().forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore - await new Promise<any>(res => setTimeout(() => res(this._interactionLock = undefined))); + await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})}); }); // prettier-ignore return false; @@ -513,7 +516,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const doc = docView.Document; if (doc.isGroup) { DocListCast(doc.data) - .map(member => DocumentManager.Instance.getDocumentView(member, docView)!) + .map(member => DocumentView.getDocumentView(member, docView)!) .forEach(member => this.resizeView(member, refPt, scale, opts)); doc.xPadding = NumCast(doc.xPadding) * scale.x; doc.yPadding = NumCast(doc.yPadding) * scale.y; @@ -553,10 +556,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora doc._layout_modificationDate = new DateField(); if (scale.y !== 1) { - docView.layoutDoc._layout_autoHeight = undefined; + const docLayout = docView.layoutDoc; + docLayout._layout_autoHeight = undefined; if (docView.layoutDoc._layout_autoHeight) { // if autoHeight is still on because of a prototype - docView.layoutDoc._layout_autoHeight = false; // then don't inherit, but explicitly set it to false + docLayout._layout_autoHeight = false; // then don't inherit, but explicitly set it to false } } } @@ -586,15 +590,17 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora }; @action - onPointerUp = (e: PointerEvent): void => { + onPointerUp = (): void => { SnappingManager.SetIsResizing(undefined); SnappingManager.clearSnapLines(); this._resizeHdlId = ''; this._resizeUndo?.end(); // detect layout_autoHeight gesture and apply - SelectionManager.Views.forEach(view => NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true)); - //need to change points for resize, or else rotation/control points will fail. + DocumentView.Selected().forEach(view => { + NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true); + }); + // need to change points for resize, or else rotation/control points will fail. this._inkDragDocs .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => { @@ -610,18 +616,18 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora @computed get selectionTitle(): string { - if (SelectionManager.Views.length === 1) { - const selected = SelectionManager.Views[0]; + if (DocumentView.Selected().length === 1) { + const selected = DocumentView.Selected()[0]; if (this._titleControlString.startsWith('$')) { - return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as Field) || '-unset-'; + return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as FieldType) || '-unset-'; } return this._accumulatedTitle; } - return SelectionManager.Views.length > 1 ? '-multiple-' : '-unset-'; + return DocumentView.Selected().length > 1 ? '-multiple-' : '-unset-'; } @computed get rotCenter() { - const lastView = SelectionManager.Views.lastElement(); + const lastView = DocumentView.Selected().lastElement(); if (lastView) { const invXf = lastView.screenToContentsTransform().inverse(); const seldoc = lastView.layoutDoc; @@ -633,7 +639,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora render() { const { b, r, x, y } = this.Bounds; - const seldocview = SelectionManager.Views.lastElement(); + const seldocview = DocumentView.Selected().lastElement(); if (SnappingManager.IsDragging || r - x < 1 || x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(r) || isNaN(b) || isNaN(x) || isNaN(y)) { setTimeout( action(() => { @@ -648,7 +654,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const acl = GetEffectiveAcl(!this._showLayoutAcl ? Doc.GetProto(seldocview.Document) : seldocview.Document); const docShareMode = HierarchyMapping.get(acl)!.name; const shareMode = StrCast(docShareMode); - var shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image; + const shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image; // hide the decorations if the parent chooses to hide it or if the document itself hides it const hideDecorations = SnappingManager.IsResizing || seldocview._props.hideDecorations || seldocview.Document.layout_hideDecorations; @@ -662,7 +668,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora hideDecorations || seldocview._props.hideOpenButton || seldocview.Document.layout_hideOpenButton || - SelectionManager.Views.some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) || + DocumentView.Selected().some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) || this._isRounding || this._isRotating; const hideDeleteButton = @@ -672,13 +678,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora this._isRotating || seldocview._props.hideDeleteButton || seldocview.Document.hideDeleteButton || - SelectionManager.Views.some(docView => { + DocumentView.Selected().some(docView => { const collectionAcl = docView.containerViewPath?.()?.lastElement() ? GetEffectiveAcl(docView.containerViewPath?.().lastElement().dataDoc) : AclEdit; return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin; }); const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top"> - <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => click!(e)))}> + <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, clickEv => click!(clickEv)))}> <FontAwesomeIcon icon={icon as any} /> </div> </Tooltip> @@ -686,8 +692,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora const bounds = this.ClippedBounds; const useLock = bounds.r - bounds.x > 135; - const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate? - const rotation = SelectionManager.Views.length == 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0; + const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && CollectionFreeFormDocumentView.from(seldocview); // when do we want an object to not rotate? + const rotation = DocumentView.Selected().length === 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0; // Radius constants const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView; @@ -727,11 +733,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora name="dynbox" autoComplete="on" value={hideTitle ? '' : this._accumulatedTitle} - onBlur={action((e: React.FocusEvent) => { + onBlur={action(() => { this._editingTitle = false; this.titleBlur(); })} - onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} + onChange={action(e => { + !hideTitle && (this._accumulatedTitle = e.target.value); + })} onKeyDown={hideTitle ? emptyFunction : this.titleEntered} onPointerDown={e => e.stopPropagation()} /> @@ -755,7 +763,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora ); const centery = hideTitle ? 0 : this._titleHeight; const transformOrigin = `${50}% calc(50% + ${centery / 2}px)`; - const freeformDoc = SelectionManager.Views.some(v => v.CollectionFreeFormDocumentView); + const freeformDoc = DocumentView.Selected().some(v => CollectionFreeFormDocumentView.from(v)); return ( <div className="documentDecorations" style={{ display: this._showNothing && !freeformDoc ? 'none' : undefined }}> <div @@ -768,7 +776,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora transformOrigin, background: SnappingManager.ShiftKey ? undefined : 'yellow', pointerEvents: SnappingManager.ShiftKey || SnappingManager.IsResizing ? 'none' : 'all', - display: SelectionManager.Views.length <= 1 || hideDecorations ? 'none' : undefined, + display: DocumentView.Selected().length <= 1 || hideDecorations ? 'none' : undefined, transform: `rotate(${rotation}deg)`, }} onPointerDown={this.onBackgroundDown} @@ -789,8 +797,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora display: hideDeleteButton && hideTitle && hideOpenButton ? 'none' : undefined, }} onPointerDown={this.onContainerDown}> - {hideDeleteButton ? null : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')} - {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')} + {hideDeleteButton ? null : topBtn('close', 'times', undefined, () => this.onCloseClick(true), 'Close')} + {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, () => this.onCloseClick(undefined), 'Minimize')} {titleArea} {hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')} </div> @@ -825,7 +833,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora style={{ transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, }}> - <DocumentButtonBar views={() => SelectionManager.Views} /> + <DocumentButtonBar views={() => DocumentView.Selected()} /> </div> )} </div> |