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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import { action, observable, ObservableMap } from 'mobx';
import { computedFn } from 'mobx-utils';
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 namespace SelectionManager {
class Manager {
@observable IsDragging: boolean = false;
SelectedViewsMap: ObservableMap<DocumentView, Doc> = new ObservableMap();
@observable SelectedViews: DocumentView[] = [];
@observable SelectedSchemaDocument: Doc | undefined;
@action
SelectSchemaViewDoc(doc: Opt<Doc>) {
manager.SelectedSchemaDocument = doc;
}
@action
SelectView(docView: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
if (!manager.SelectedViewsMap.get(docView)) {
if (!ctrlPressed) {
this.DeselectAll();
}
manager.SelectedViews.push(docView);
manager.SelectedViewsMap.set(docView, docView.rootDoc);
docView.props.whenChildContentsActiveChanged(true);
} else if (!ctrlPressed && (Array.from(manager.SelectedViewsMap.entries()).length > 1 || manager.SelectedSchemaDocument)) {
Array.from(manager.SelectedViewsMap.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
manager.SelectedSchemaDocument = undefined;
manager.SelectedViews.length = 0;
manager.SelectedViewsMap.clear();
manager.SelectedViews.push(docView);
manager.SelectedViewsMap.set(docView, docView.rootDoc);
}
}
@action
DeselectView(docView?: DocumentView): void {
if (docView && manager.SelectedViewsMap.get(docView)) {
manager.SelectedViewsMap.delete(docView);
manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1);
docView.props.whenChildContentsActiveChanged(false);
}
}
@action
DeselectAll(): void {
LinkManager.currentLink = undefined;
LinkManager.currentLinkAnchor = undefined;
manager.SelectedSchemaDocument = undefined;
Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
manager.SelectedViewsMap.clear();
manager.SelectedViews.length = 0;
}
}
const manager = new Manager();
export function DeselectView(docView?: DocumentView): void {
manager.DeselectView(docView);
}
export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void {
if (!docView) DeselectAll();
else manager.SelectView(docView, ctrlPressed);
}
export function SelectSchemaViewDoc(document: Opt<Doc>, deselectAllFirst?: boolean): void {
if (deselectAllFirst) manager.DeselectAll();
manager.SelectSchemaViewDoc(document);
}
const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) {
// wrapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
return manager.SelectedViewsMap.get(doc) ? true : false;
});
// computed functions, such as used in IsSelected generate errors if they're called outside of a
// reaction context. Specifying the context with 'outsideReaction' allows an efficiency feature
// to avoid unnecessary mobx invalidations when running inside a reaction.
export function IsSelected(doc: DocumentView | undefined, outsideReaction?: boolean): boolean {
return !doc
? false
: outsideReaction
? manager.SelectedViewsMap.get(doc)
? true
: false // get() accesses a hashtable -- setting anything in the hashtable generates a mobx invalidation for every get()
: IsSelectedCache(doc);
}
export function DeselectAll(except?: Doc): void {
let found: DocumentView | undefined = undefined;
if (except) {
for (const view of Array.from(manager.SelectedViewsMap.keys())) {
if (view.props.Document === except) found = view;
}
}
manager.DeselectAll();
if (found) manager.SelectView(found, false);
}
export function Views(): Array<DocumentView> {
return manager.SelectedViews;
// Array.from(manager.SelectedViewsMap.keys()); //.filter(dv => manager.SelectedViews.get(dv)?._type_collection !== CollectionViewType.Docking);
}
export function SelectedSchemaDoc(): Doc | undefined {
return manager.SelectedSchemaDocument;
}
export function Docs(): Doc[] {
return manager.SelectedViews.map(dv => dv.rootDoc).filter(doc => doc?._type_collection !== CollectionViewType.Docking);
// Array.from(manager.SelectedViewsMap.values()).filter(doc => doc?._type_collection !== CollectionViewType.Docking);
}
}
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;
}
let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
return selected?.type === type || selected?.type_collection === type || !type;
});
ScriptingGlobals.add(function deselectAll() {
SelectionManager.DeselectAll();
});
ScriptingGlobals.add(function undo() {
SelectionManager.DeselectAll();
return UndoManager.Undo();
});
export function ShowUndoStack() {
SelectionManager.DeselectAll();
var buffer = '';
UndoManager.undoStack.forEach((batch, i) => {
buffer += 'Batch => ' + UndoManager.undoStackNames[i] + '\n';
///batch.forEach(undo => (buffer += ' ' + undo.prop + '\n'));
});
alert(buffer);
}
ScriptingGlobals.add(function redo() {
SelectionManager.DeselectAll();
return UndoManager.Redo();
});
ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
const docs = SelectionManager.Views()
.map(dv => dv.props.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;
});
|