summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/ide/lib/editor.js
blob: 668221c0296b0c40af50f4223417edb20c926f22 (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
import _ from 'underscore';
import DecorationsController from './decorations/controller';
import DirtyDiffController from './diff/controller';
import Disposable from './common/disposable';
import ModelManager from './common/model_manager';
import editorOptions from './editor_options';

export default class Editor {
  static create(monaco) {
    this.editorInstance = new Editor(monaco);

    return this.editorInstance;
  }

  constructor(monaco) {
    this.monaco = monaco;
    this.currentModel = null;
    this.instance = null;
    this.dirtyDiffController = null;
    this.disposable = new Disposable();

    this.disposable.add(
      this.modelManager = new ModelManager(this.monaco),
      this.decorationsController = new DecorationsController(this),
    );

    this.debouncedUpdate = _.debounce(() => {
      this.updateDimensions();
    }, 200);
    window.addEventListener('resize', this.debouncedUpdate, false);
  }

  createInstance(domElement) {
    if (!this.instance) {
      this.disposable.add(
        this.instance = this.monaco.editor.create(domElement, {
          model: null,
          readOnly: false,
          contextmenu: true,
          scrollBeyondLastLine: false,
          minimap: {
            enabled: false,
          },
        }),
        this.dirtyDiffController = new DirtyDiffController(
          this.modelManager, this.decorationsController,
        ),
      );
    }
  }

  createModel(file) {
    return this.modelManager.addModel(file);
  }

  attachModel(model) {
    this.instance.setModel(model.getModel());
    this.dirtyDiffController.attachModel(model);

    this.currentModel = model;

    this.instance.updateOptions(editorOptions.reduce((acc, obj) => {
      Object.keys(obj).forEach((key) => {
        Object.assign(acc, {
          [key]: obj[key](model),
        });
      });
      return acc;
    }, {}));

    this.dirtyDiffController.reDecorate(model);
  }

  clearEditor() {
    if (this.instance) {
      this.instance.setModel(null);
    }
  }

  dispose() {
    this.disposable.dispose();
    window.removeEventListener('resize', this.debouncedUpdate);

    // dispose main monaco instance
    if (this.instance) {
      this.instance = null;
    }
  }

  updateDimensions() {
    this.instance.layout();
  }

  setPosition({ lineNumber, column }) {
    this.instance.revealPositionInCenter({
      lineNumber,
      column,
    });
    this.instance.setPosition({
      lineNumber,
      column,
    });
  }

  onPositionChange(cb) {
    this.disposable.add(
      this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)),
    );
  }
}