Mercurial
comparison .cms/lib/codemirror/src/model/line_widget.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 import { runInOp } from "../display/operations.js" | |
2 import { addToScrollTop } from "../display/scrolling.js" | |
3 import { regLineChange } from "../display/view_tracking.js" | |
4 import { heightAtLine, lineIsHidden } from "../line/spans.js" | |
5 import { lineNo, updateLineHeight } from "../line/utils_line.js" | |
6 import { widgetHeight } from "../measurement/widgets.js" | |
7 import { changeLine } from "./changes.js" | |
8 import { eventMixin } from "../util/event.js" | |
9 import { signalLater } from "../util/operation_group.js" | |
10 | |
11 // Line widgets are block elements displayed above or below a line. | |
12 | |
13 export class LineWidget { | |
14 constructor(doc, node, options) { | |
15 if (options) for (let opt in options) if (options.hasOwnProperty(opt)) | |
16 this[opt] = options[opt] | |
17 this.doc = doc | |
18 this.node = node | |
19 } | |
20 | |
21 clear() { | |
22 let cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line) | |
23 if (no == null || !ws) return | |
24 for (let i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1) | |
25 if (!ws.length) line.widgets = null | |
26 let height = widgetHeight(this) | |
27 updateLineHeight(line, Math.max(0, line.height - height)) | |
28 if (cm) { | |
29 runInOp(cm, () => { | |
30 adjustScrollWhenAboveVisible(cm, line, -height) | |
31 regLineChange(cm, no, "widget") | |
32 }) | |
33 signalLater(cm, "lineWidgetCleared", cm, this, no) | |
34 } | |
35 } | |
36 | |
37 changed() { | |
38 let oldH = this.height, cm = this.doc.cm, line = this.line | |
39 this.height = null | |
40 let diff = widgetHeight(this) - oldH | |
41 if (!diff) return | |
42 if (!lineIsHidden(this.doc, line)) updateLineHeight(line, line.height + diff) | |
43 if (cm) { | |
44 runInOp(cm, () => { | |
45 cm.curOp.forceUpdate = true | |
46 adjustScrollWhenAboveVisible(cm, line, diff) | |
47 signalLater(cm, "lineWidgetChanged", cm, this, lineNo(line)) | |
48 }) | |
49 } | |
50 } | |
51 } | |
52 eventMixin(LineWidget) | |
53 | |
54 function adjustScrollWhenAboveVisible(cm, line, diff) { | |
55 if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) | |
56 addToScrollTop(cm, diff) | |
57 } | |
58 | |
59 export function addLineWidget(doc, handle, node, options) { | |
60 let widget = new LineWidget(doc, node, options) | |
61 let cm = doc.cm | |
62 if (cm && widget.noHScroll) cm.display.alignWidgets = true | |
63 changeLine(doc, handle, "widget", line => { | |
64 let widgets = line.widgets || (line.widgets = []) | |
65 if (widget.insertAt == null) widgets.push(widget) | |
66 else widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget) | |
67 widget.line = line | |
68 if (cm && !lineIsHidden(doc, line)) { | |
69 let aboveVisible = heightAtLine(line) < doc.scrollTop | |
70 updateLineHeight(line, line.height + widgetHeight(widget)) | |
71 if (aboveVisible) addToScrollTop(cm, widget.height) | |
72 cm.curOp.forceUpdate = true | |
73 } | |
74 return true | |
75 }) | |
76 if (cm) signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)) | |
77 return widget | |
78 } |