aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/js/editor
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-08-22 19:54:51 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-08-22 19:54:51 +0200
commit8cbf8fdcfdceab8a330bdc82e4260a55c125c37d (patch)
tree0354dcc6ce0704fc953e7665ecfcc700609549a2 /language-web/src/main/js/editor
parentBump Material-UI version (diff)
downloadrefinery-8cbf8fdcfdceab8a330bdc82e4260a55c125c37d.tar.gz
refinery-8cbf8fdcfdceab8a330bdc82e4260a55c125c37d.tar.zst
refinery-8cbf8fdcfdceab8a330bdc82e4260a55c125c37d.zip
Covert language-web to TypeScript
Diffstat (limited to 'language-web/src/main/js/editor')
-rw-r--r--language-web/src/main/js/editor/Editor.jsx52
-rw-r--r--language-web/src/main/js/editor/Editor.tsx20
-rw-r--r--language-web/src/main/js/editor/EditorButtons.tsx (renamed from language-web/src/main/js/editor/EditorButtons.jsx)2
-rw-r--r--language-web/src/main/js/editor/EditorStore.jsx87
-rw-r--r--language-web/src/main/js/editor/EditorStore.ts127
5 files changed, 148 insertions, 140 deletions
diff --git a/language-web/src/main/js/editor/Editor.jsx b/language-web/src/main/js/editor/Editor.jsx
deleted file mode 100644
index 4cd9b3bd..00000000
--- a/language-web/src/main/js/editor/Editor.jsx
+++ /dev/null
@@ -1,52 +0,0 @@
1import { observer } from 'mobx-react-lite';
2import 'mode-problem';
3import React, { useCallback } from 'react';
4import { Controlled as CodeMirror } from 'react-codemirror2-react-17';
5import { createServices, removeServices } from 'xtext/xtext-codemirror';
6
7import { useRootStore } from '../RootStore';
8
9export default observer(() => {
10 const editorStore = useRootStore().editorStore;
11
12 const codeMirrorOptions = {
13 mode: 'xtext/problem',
14 indentUnit: 2,
15 theme: 'material-darker',
16 lineNumbers: editorStore.showLineNumbers,
17 };
18
19 const xtextOptions = {
20 xtextLang: 'problem',
21 enableFormattingAction: true,
22 }
23
24 const editorDidMount = useCallback((editor) => {
25 createServices(editor, xtextOptions);
26 editorStore.updateEditor(editor);
27 }, [editorStore]);
28
29 const editorWillUnmount = useCallback((editor) => {
30 editorStore.editor = null;
31 removeServices(editor);
32 }, [editorStore]);
33
34 const onBeforeChange = useCallback((_editor, _data, value) => {
35 editorStore.updateValue(value);
36 }, [editorStore]);
37
38 const onChange = useCallback((_editor, _data, _value) => {
39 editorStore.reportChanged();
40 }, [editorStore]);
41
42 return (
43 <CodeMirror
44 value={editorStore.value}
45 options={codeMirrorOptions}
46 editorDidMount={editorDidMount}
47 editorWillUnmount={editorWillUnmount}
48 onBeforeChange={onBeforeChange}
49 onChange={onChange}
50 />
51 );
52});
diff --git a/language-web/src/main/js/editor/Editor.tsx b/language-web/src/main/js/editor/Editor.tsx
new file mode 100644
index 00000000..f81c5c37
--- /dev/null
+++ b/language-web/src/main/js/editor/Editor.tsx
@@ -0,0 +1,20 @@
1import { observer } from 'mobx-react-lite';
2import React from 'react';
3import { Controlled as CodeMirror } from 'react-codemirror2';
4
5import { useRootStore } from '../RootStore';
6
7export default observer(() => {
8 const { editorStore } = useRootStore();
9
10 return (
11 <CodeMirror
12 value={editorStore.value}
13 options={editorStore.codeMirrorOptions}
14 editorDidMount={(editor) => editorStore.editorDidMount(editor)}
15 editorWillUnmount={() => editorStore.editorWillUnmount()}
16 onBeforeChange={(_editor, _data, value) => editorStore.updateValue(value)}
17 onChange={() => editorStore.reportChanged()}
18 />
19 );
20});
diff --git a/language-web/src/main/js/editor/EditorButtons.jsx b/language-web/src/main/js/editor/EditorButtons.tsx
index a5a57f93..1a187635 100644
--- a/language-web/src/main/js/editor/EditorButtons.jsx
+++ b/language-web/src/main/js/editor/EditorButtons.tsx
@@ -29,7 +29,7 @@ const useStyles = makeStyles()(theme => ({
29})); 29}));
30 30
31export default observer(() => { 31export default observer(() => {
32 const editorStore = useRootStore().editorStore; 32 const { editorStore } = useRootStore();
33 const { classes, cx } = useStyles(); 33 const { classes, cx } = useStyles();
34 return ( 34 return (
35 <> 35 <>
diff --git a/language-web/src/main/js/editor/EditorStore.jsx b/language-web/src/main/js/editor/EditorStore.jsx
deleted file mode 100644
index b6f9bc0a..00000000
--- a/language-web/src/main/js/editor/EditorStore.jsx
+++ /dev/null
@@ -1,87 +0,0 @@
1import CodeMirror from 'codemirror';
2import { createAtom, makeAutoObservable, observable } from 'mobx';
3
4export default class EditorStore {
5 atom;
6 /** @type {CodeMirror} */
7 editor = null;
8 /** @type {string} */
9 value = '';
10 /** @type {boolean} */
11 showLineNumbers = false;
12 /** @type {boolean} */
13 showLigatures = true;
14
15 constructor() {
16 this.atom = createAtom('EditorStore');
17 makeAutoObservable(this, {
18 atom: false,
19 editor: observable.ref,
20 });
21 }
22
23 /**
24 * Attaches a new CodeMirror instance.
25 *
26 * The store will node subscribe to any CodeMirror events. Instead,
27 * the editor component should subscribe to them and relay them to the store.
28 *
29 * @param {CodeMirror} newEditor The new CodeMirror instance
30 */
31 updateEditor(newEditor) {
32 this.editor = newEditor;
33 }
34
35 /**
36 * Updates the contents of the editor.
37 *
38 * @param {string} newValue The new contents of the editor
39 */
40 updateValue(newValue) {
41 this.value = newValue;
42 }
43
44 reportChanged() {
45 this.atom.reportChanged();
46 }
47
48 /**
49 * @returns {boolean} `true` if there is history to undo
50 */
51 get canUndo() {
52 this.atom.reportObserved();
53 if (!this.editor) {
54 return false;
55 }
56 const { undo: undoSize } = this.editor.historySize();
57 return undoSize > 0;
58 }
59
60 undo() {
61 this.editor.undo();
62 }
63
64 /**
65 * @returns {boolean} `true` if there is history to redo
66 */
67 get canRedo() {
68 this.atom.reportObserved();
69 if (!this.editor) {
70 return false;
71 }
72 const { redo: redoSize } = this.editor.historySize();
73 return redoSize > 0;
74 }
75
76 redo() {
77 this.editor.redo();
78 }
79
80 toggleLineNumbers() {
81 this.showLineNumbers = !this.showLineNumbers;
82 }
83
84 toggleLigatures() {
85 this.showLigatures = !this.showLigatures;
86 }
87}
diff --git a/language-web/src/main/js/editor/EditorStore.ts b/language-web/src/main/js/editor/EditorStore.ts
new file mode 100644
index 00000000..167e1ade
--- /dev/null
+++ b/language-web/src/main/js/editor/EditorStore.ts
@@ -0,0 +1,127 @@
1import { Editor, EditorConfiguration } from 'codemirror';
2import {
3 createAtom,
4 makeAutoObservable,
5 observable,
6} from 'mobx';
7import 'mode-problem';
8import {
9 IXtextOptions,
10 IXtextServices,
11 createServices,
12 removeServices,
13} from 'xtext/xtext-codemirror';
14
15const xtextLang = 'problem';
16
17const xtextOptions: IXtextOptions = {
18 xtextLang,
19 enableFormattingAction: true,
20};
21
22const codeMirrorGlobalOptions: EditorConfiguration = {
23 mode: `xtext/${xtextLang}`,
24 indentUnit: 2,
25 theme: 'material-darker',
26};
27
28export default class EditorStore {
29 _atom;
30 editor?: Editor;
31 xtextServices?: IXtextServices;
32 value = '';
33 showLineNumbers = false;
34
35 constructor() {
36 this._atom = createAtom('EditorStore');
37 makeAutoObservable(this, {
38 _atom: false,
39 editor: observable.ref,
40 xtextServices: observable.ref,
41 });
42 }
43
44 /**
45 * Attaches a new CodeMirror instance and creates Xtext services.
46 *
47 * The store will not subscribe to any CodeMirror events. Instead,
48 * the editor component should subscribe to them and relay them to the store.
49 *
50 * @param newEditor The new CodeMirror instance
51 */
52 editorDidMount(newEditor: Editor) {
53 if (this.editor) {
54 throw new Error('CoreMirror editor mounted before unmounting');
55 }
56 this.editor = newEditor;
57 this.xtextServices = createServices(newEditor, xtextOptions);
58 }
59
60 editorWillUnmount() {
61 if (this.editor) {
62 removeServices(this.editor);
63 }
64 this.editor = undefined;
65 this.xtextServices = undefined;
66 }
67
68 /**
69 * Updates the contents of the editor.
70 *
71 * @param newValue The new contents of the editor
72 */
73 updateValue(newValue: string) {
74 this.value = newValue;
75 }
76
77 reportChanged() {
78 this._atom.reportChanged();
79 }
80
81 _observeEditorChanges() {
82 this._atom.reportObserved();
83 }
84
85 get codeMirrorOptions(): EditorConfiguration {
86 return {
87 ...codeMirrorGlobalOptions,
88 lineNumbers: this.showLineNumbers,
89 };
90 }
91
92 /**
93 * @returns `true` if there is history to undo
94 */
95 get canUndo() {
96 this._observeEditorChanges();
97 if (!this.editor) {
98 return false;
99 }
100 const { undo: undoSize } = this.editor.historySize();
101 return undoSize > 0;
102 }
103
104 undo() {
105 this.editor?.undo();
106 }
107
108 /**
109 * @returns `true` if there is history to redo
110 */
111 get canRedo() {
112 this._observeEditorChanges();
113 if (!this.editor) {
114 return false;
115 }
116 const { redo: redoSize } = this.editor.historySize();
117 return redoSize > 0;
118 }
119
120 redo() {
121 this.editor?.redo();
122 }
123
124 toggleLineNumbers() {
125 this.showLineNumbers = !this.showLineNumbers;
126 }
127}