aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/SelectionManager.ts
blob: a1f2849cd7fccdb429b7bf4ab9061e07f60ef4e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { action, makeObservable, observable, runInAction } from 'mobx';
import { Doc, Opt } from '../../fields/Doc';
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);
        DocumentView.DeselectAll = SelectionManager.DeselectAll;
        DocumentView.DeselectView = SelectionManager.DeselectView;
        DocumentView.SelectView = SelectionManager.SelectView;
        DocumentView.SelectedDocs = SelectionManager.Docs;
        DocumentView.Selected = SelectionManager.Views;
        DocumentView.SelectSchemaDoc = SelectionManager.SelectSchemaViewDoc;
        DocumentView.SelectedSchemaDoc = () => this.SelectedSchemaDocument;
    }

    @action
    public static SelectSchemaViewDoc = (doc: Opt<Doc>, 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(() => {
            if (LinkManager.Instance) {
                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 Views() { return SelectionManager.Instance.SelectedViews; } // prettier-ignore
    public static get SelectedSchemaDoc() { return SelectionManager.Instance.SelectedSchemaDocument; } // prettier-ignore
    public static Docs() { return SelectionManager.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 SelectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
    if (Doc.noviceMode && expertMode) return false;
    if (type === 'tab') {
        return DocumentView.Selected().lastElement()?._props.renderDepth === 0;
    }
    const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(DocumentView.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
    const matchOverlayFreeform = type === CollectionViewType.Freeform && DocumentView.Selected().lastElement()?.ComponentView?.annotationKey;
    return matchOverlayFreeform || 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: Doc[]) {
    const docs = SelectionManager.Docs().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;
});