aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/js/editor
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-07-01 12:31:07 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-07-01 12:31:07 +0200
commit8595c9a22830b1baacc49bb694d70389b2539eba (patch)
treecb496cd34661a0d3ec4c9b5a333e948f24e437f4 /language-web/src/main/js/editor
parentConvert to React app (diff)
downloadrefinery-8595c9a22830b1baacc49bb694d70389b2539eba.tar.gz
refinery-8595c9a22830b1baacc49bb694d70389b2539eba.tar.zst
refinery-8595c9a22830b1baacc49bb694d70389b2539eba.zip
Add material-ui and mobx integration
Diffstat (limited to 'language-web/src/main/js/editor')
-rw-r--r--language-web/src/main/js/editor/Editor.jsx50
-rw-r--r--language-web/src/main/js/editor/EditorButtons.jsx27
-rw-r--r--language-web/src/main/js/editor/EditorStore.jsx75
3 files changed, 152 insertions, 0 deletions
diff --git a/language-web/src/main/js/editor/Editor.jsx b/language-web/src/main/js/editor/Editor.jsx
new file mode 100644
index 00000000..c4b2e183
--- /dev/null
+++ b/language-web/src/main/js/editor/Editor.jsx
@@ -0,0 +1,50 @@
1import { observer } from 'mobx-react-lite';
2import 'mode-problem';
3import React, { useCallback } from 'react';
4import { Controlled as CodeMirror } from 'react-codemirror2';
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 };
16
17 const xtextOptions = {
18 xtextLang: 'problem',
19 enableFormattingAction: true,
20 }
21
22 const editorDidMount = useCallback((editor) => {
23 createServices(editor, xtextOptions);
24 editorStore.updateEditor(editor);
25 }, [editorStore]);
26
27 const editorWillUnmount = useCallback((editor) => {
28 editorStore.editor = null;
29 removeServices(editor);
30 }, [editorStore]);
31
32 const onBeforeChange = useCallback((_editor, _data, value) => {
33 editorStore.updateValue(value);
34 }, [editorStore]);
35
36 const onChange = useCallback((_editor, _data, _value) => {
37 editorStore.reportChanged();
38 }, [editorStore]);
39
40 return (
41 <CodeMirror
42 value={editorStore.value}
43 options={codeMirrorOptions}
44 editorDidMount={editorDidMount}
45 editorWillUnmount={editorWillUnmount}
46 onBeforeChange={onBeforeChange}
47 onChange={onChange}
48 />
49 );
50});
diff --git a/language-web/src/main/js/editor/EditorButtons.jsx b/language-web/src/main/js/editor/EditorButtons.jsx
new file mode 100644
index 00000000..b9f0d076
--- /dev/null
+++ b/language-web/src/main/js/editor/EditorButtons.jsx
@@ -0,0 +1,27 @@
1import { observer } from 'mobx-react-lite';
2import React from 'react';
3import IconButton from '@material-ui/core/IconButton';
4import RedoIcon from '@material-ui/icons/Redo';
5import UndoIcon from '@material-ui/icons/Undo';
6
7import { useRootStore } from '../RootStore';
8
9export default observer(() => {
10 const editorStore = useRootStore().editorStore;
11 return (
12 <>
13 <IconButton
14 disabled={!editorStore.canUndo}
15 onClick={() => editorStore.undo()}
16 >
17 <UndoIcon fontSize='small'/>
18 </IconButton>
19 <IconButton
20 disabled={!editorStore.canRedo}
21 onClick={() => editorStore.redo()}
22 >
23 <RedoIcon fontSize='small'/>
24 </IconButton>
25 </>
26 );
27});
diff --git a/language-web/src/main/js/editor/EditorStore.jsx b/language-web/src/main/js/editor/EditorStore.jsx
new file mode 100644
index 00000000..9c286c28
--- /dev/null
+++ b/language-web/src/main/js/editor/EditorStore.jsx
@@ -0,0 +1,75 @@
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
11 constructor() {
12 this.atom = createAtom('EditorStore');
13 makeAutoObservable(this, {
14 atom: false,
15 editor: observable.ref,
16 });
17 }
18
19 /**
20 * Attaches a new CodeMirror instance.
21 *
22 * The store will node subscribe to any CodeMirror events. Instead,
23 * the editor component should subscribe to them and relay them to the store.
24 *
25 * @param {CodeMirror} newEditor The new CodeMirror instance
26 */
27 updateEditor(newEditor) {
28 this.editor = newEditor;
29 }
30
31 /**
32 * Updates the contents of the editor.
33 *
34 * @param {string} newValue The new contents of the editor
35 */
36 updateValue(newValue) {
37 this.value = newValue;
38 }
39
40 reportChanged() {
41 this.atom.reportChanged();
42 }
43
44 /**
45 * @returns {boolean} `true` if there is history to undo
46 */
47 get canUndo() {
48 this.atom.reportObserved();
49 if (!this.editor) {
50 return false;
51 }
52 const { undo: undoSize } = this.editor.historySize();
53 return undoSize > 0;
54 }
55
56 undo() {
57 this.editor.undo();
58 }
59
60 /**
61 * @returns {boolean} `true` if there is history to redo
62 */
63 get canRedo() {
64 this.atom.reportObserved();
65 if (!this.editor) {
66 return false;
67 }
68 const { redo: redoSize } = this.editor.historySize();
69 return redoSize > 0;
70 }
71
72 redo() {
73 this.editor.redo();
74 }
75}