import { action, makeObservable, observable, runInAction } from 'mobx'; import { Doc, Opt } from '../../fields/Doc'; import { DocViews } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; import { Cast, DocCast } from '../../fields/Types'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; import { ScriptingGlobals } from './ScriptingGlobals'; import { UndoManager } from './UndoManager'; export class SelectionManager { // eslint-disable-next-line no-use-before-define private static _manager: SelectionManager; private static get Instance() { return SelectionManager._manager ?? new SelectionManager(); } @observable.shallow SelectedViews: DocumentView[] = []; @observable IsDragging: boolean = false; @observable SelectedSchemaDocument: Doc | undefined = undefined; private constructor() { SelectionManager._manager = this; makeObservable(this); } @action public static SelectSchemaViewDoc = (doc: Opt, deselectAllFirst?: boolean) => { if (deselectAllFirst) this.DeselectAll(); this.Instance.SelectedSchemaDocument = doc; }; public static SelectView = action((docView: DocumentView | undefined, extendSelection: boolean): void => { if (!docView) this.DeselectAll(); else if (!docView.IsSelected) { if (!extendSelection) this.DeselectAll(); this.Instance.SelectedViews.push(docView); docView.IsSelected = true; docView._props.whenChildContentsActiveChanged(true); docView.ComponentView?.select?.(false, false); } }); public static DeselectView = action((docView?: DocumentView): void => { if (docView && this.Instance.SelectedViews.includes(docView)) { docView.IsSelected = false; this.Instance.SelectedViews.splice(this.Instance.SelectedViews.indexOf(docView), 1); docView._props.whenChildContentsActiveChanged(false); } }); public static DeselectAll = (except?: Doc): void => { const found = this.Instance.SelectedViews.find(dv => dv.Document === except); runInAction(() => { LinkManager.Instance.currentLink = undefined; LinkManager.Instance.currentLinkAnchor = undefined; this.Instance.SelectedSchemaDocument = undefined; }); this.Instance.SelectedViews.forEach(dv => { dv.IsSelected = false; dv._props.whenChildContentsActiveChanged(false); }); runInAction(() => { this.Instance.SelectedViews.length = 0; }); if (found) this.SelectView(found, false); }; public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected); public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore } // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) { if (Doc.noviceMode && expertMode) return false; if (type === 'tab') { return SelectionManager.Views.lastElement()?._props.renderDepth === 0; } const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement()); return selected?.type === type || selected?.type_collection === type || !type; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function deselectAll() { SelectionManager.DeselectAll(); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function undo() { SelectionManager.DeselectAll(); return UndoManager.Undo(); }); export function ShowUndoStack() { SelectionManager.DeselectAll(); let buffer = ''; UndoManager.undoStack.forEach((batch, i) => { buffer += 'Batch => ' + UndoManager.undoStackNames[i] + '\n'; // /batch.forEach(undo => (buffer += ' ' + undo.prop + '\n')); }); alert(buffer); } // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function redo() { SelectionManager.DeselectAll(); return UndoManager.Redo(); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { const docs = SelectionManager.Views.map(dv => dv.Document).filter( d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)) ); return docs.length ? new List(docs) : prevValue; });