annotate .cms/lib/codemirror/src/display/view_tracking.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 import { buildViewArray } from "../line/line_data.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 import { sawCollapsedSpans } from "../line/saw_special_spans.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3 import { visualLineEndNo, visualLineNo } from "../line/spans.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 import { findViewIndex } from "../measurement/position_measurement.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 import { indexOf } from "../util/misc.js"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 // Updates the display.view data structure for a given change to the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 // document. From and to are in pre-change coordinates. Lendiff is
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 // the amount of lines added or subtracted by the change. This is
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 // used for changes that span multiple lines, or change the way
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 // lines are divided into visual lines. regLineChange (below)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 // registers single-line changes.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13 export function regChange(cm, from, to, lendiff) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 if (from == null) from = cm.doc.first
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 if (to == null) to = cm.doc.first + cm.doc.size
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 if (!lendiff) lendiff = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 let display = cm.display
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 if (lendiff && to < display.viewTo &&
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 (display.updateLineNumbers == null || display.updateLineNumbers > from))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 display.updateLineNumbers = from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 cm.curOp.viewChanged = true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 if (from >= display.viewTo) { // Change after
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 } else if (to <= display.viewFrom) { // Change before
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29 if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 display.viewFrom += lendiff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 display.viewTo += lendiff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 } else if (from <= display.viewFrom) { // Top overlap
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38 let cut = viewCuttingPoint(cm, to, to + lendiff, 1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 if (cut) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 display.view = display.view.slice(cut.index)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 display.viewFrom = cut.lineN
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 display.viewTo += lendiff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 } else if (to >= display.viewTo) { // Bottom overlap
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 let cut = viewCuttingPoint(cm, from, from, -1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 if (cut) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 display.view = display.view.slice(0, cut.index)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50 display.viewTo = cut.lineN
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54 } else { // Gap in the middle
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55 let cutTop = viewCuttingPoint(cm, from, from, -1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 let cutBot = viewCuttingPoint(cm, to, to + lendiff, 1)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 if (cutTop && cutBot) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58 display.view = display.view.slice(0, cutTop.index)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60 .concat(display.view.slice(cutBot.index))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 display.viewTo += lendiff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 resetView(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 let ext = display.externalMeasured
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 if (ext) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69 if (to < ext.lineN)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 ext.lineN += lendiff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 else if (from < ext.lineN + ext.size)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 display.externalMeasured = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 // Register a change to a single line. Type must be one of "text",
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 // "gutter", "class", "widget"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 export function regLineChange(cm, line, type) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 cm.curOp.viewChanged = true
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 let display = cm.display, ext = cm.display.externalMeasured
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 display.externalMeasured = null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 if (line < display.viewFrom || line >= display.viewTo) return
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 let lineView = display.view[findViewIndex(cm, line)]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86 if (lineView.node == null) return
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 let arr = lineView.changes || (lineView.changes = [])
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88 if (indexOf(arr, type) == -1) arr.push(type)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 // Clear the view.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92 export function resetView(cm) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93 cm.display.viewFrom = cm.display.viewTo = cm.doc.first
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 cm.display.view = []
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95 cm.display.viewOffset = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 function viewCuttingPoint(cm, oldN, newN, dir) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99 let index = findViewIndex(cm, oldN), diff, view = cm.display.view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101 return {index: index, lineN: newN}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102 let n = cm.display.viewFrom
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103 for (let i = 0; i < index; i++)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104 n += view[i].size
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105 if (n != oldN) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 if (dir > 0) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 if (index == view.length - 1) return null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 diff = (n + view[index].size) - oldN
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109 index++
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111 diff = n - oldN
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113 oldN += diff; newN += diff
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115 while (visualLineNo(cm.doc, newN) != newN) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116 if (index == (dir < 0 ? 0 : view.length - 1)) return null
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 newN += dir * view[index - (dir < 0 ? 1 : 0)].size
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118 index += dir
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120 return {index: index, lineN: newN}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123 // Force the view to cover a given range, adding empty view element
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124 // or clipping off existing ones as needed.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 export function adjustView(cm, from, to) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 let display = cm.display, view = display.view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128 display.view = buildViewArray(cm, from, to)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 display.viewFrom = from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 if (display.viewFrom > from)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132 display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 else if (display.viewFrom < from)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134 display.view = display.view.slice(findViewIndex(cm, from))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135 display.viewFrom = from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 if (display.viewTo < to)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137 display.view = display.view.concat(buildViewArray(cm, display.viewTo, to))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138 else if (display.viewTo > to)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139 display.view = display.view.slice(0, findViewIndex(cm, to))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 display.viewTo = to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 // Count the number of lines in the view whose DOM representation is
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145 // out of date (or nonexistent).
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 export function countDirtyView(cm) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147 let view = cm.display.view, dirty = 0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 for (let i = 0; i < view.length; i++) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 let lineView = view[i]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150 if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 return dirty
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153 }