Fix: merge conflict
[myslice.git] / to-be-integrated / third-party / codemirror-3.15 / addon / fold / foldgutter.js
1 (function() {
2   "use strict";
3
4   CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
5     if (old && old != CodeMirror.Init) {
6       cm.clearGutter(cm.state.foldGutter.options.gutter);
7       cm.state.foldGutter = null;
8       cm.off("gutterClick", onGutterClick);
9       cm.off("change", onChange);
10       cm.off("viewportChange", onViewportChange);
11       cm.off("fold", onFold);
12       cm.off("unfold", onFold);
13     }
14     if (val) {
15       cm.state.foldGutter = new State(parseOptions(val));
16       updateInViewport(cm);
17       cm.on("gutterClick", onGutterClick);
18       cm.on("change", onChange);
19       cm.on("viewportChange", onViewportChange);
20       cm.on("fold", onFold);
21       cm.on("unfold", onFold);
22     }
23   });
24
25   var Pos = CodeMirror.Pos;
26
27   function State(options) {
28     this.options = options;
29     this.from = this.to = 0;
30   }
31
32   function parseOptions(opts) {
33     if (opts === true) opts = {};
34     if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
35     if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
36     if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
37     return opts;
38   }
39
40   function isFolded(cm, line) {
41     var marks = cm.findMarksAt(Pos(line));
42     for (var i = 0; i < marks.length; ++i)
43       if (marks[i].__isFold && marks[i].find().from.line == line) return true;
44   }
45
46   function marker(spec) {
47     if (typeof spec == "string") {
48       var elt = document.createElement("div");
49       elt.className = spec;
50       return elt;
51     } else {
52       return spec.cloneNode(true);
53     }
54   }
55
56   function updateFoldInfo(cm, from, to) {
57     var opts = cm.state.foldGutter.options, cur = from;
58     cm.eachLine(from, to, function(line) {
59       var mark = null;
60       if (isFolded(cm, cur)) {
61         mark = marker(opts.indicatorFolded);
62       } else {
63         var pos = Pos(cur, 0), func = opts.rangeFinder || cm.getHelper(pos, "fold");
64         var range = func && func(cm, pos);
65         if (range && range.from.line + 1 < range.to.line)
66           mark = marker(opts.indicatorOpen);
67       }
68       cm.setGutterMarker(line, opts.gutter, mark);
69       ++cur;
70     });
71   }
72
73   function updateInViewport(cm) {
74     var vp = cm.getViewport(), state = cm.state.foldGutter;
75     if (!state) return;
76     cm.operation(function() {
77       updateFoldInfo(cm, vp.from, vp.to);
78     });
79     state.from = vp.from; state.to = vp.to;
80   }
81
82   function onGutterClick(cm, line, gutter) {
83     var opts = cm.state.foldGutter.options;
84     if (gutter != opts.gutter) return;
85     cm.foldCode(Pos(line, 0), opts.rangeFinder);
86   }
87
88   function onChange(cm) {
89     var state = cm.state.foldGutter;
90     state.from = state.to = 0;
91     clearTimeout(state.changeUpdate);
92     state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, 600);
93   }
94
95   function onViewportChange(cm) {
96     var state = cm.state.foldGutter;
97     clearTimeout(state.changeUpdate);
98     state.changeUpdate = setTimeout(function() {
99       var vp = cm.getViewport();
100       if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
101         updateInViewport(cm);
102       } else {
103         cm.operation(function() {
104           if (vp.from < state.from) {
105             updateFoldInfo(cm, vp.from, state.from);
106             state.from = vp.from;
107           }
108           if (vp.to > state.to) {
109             updateFoldInfo(cm, state.to, vp.to);
110             state.to = vp.to;
111           }
112         });
113       }
114     }, 400);
115   }
116
117   function onFold(cm, from) {
118     var state = cm.state.foldGutter, line = from.line;
119     if (line >= state.from && line < state.to)
120       updateFoldInfo(cm, line, line + 1);
121   }
122 })();