-
-
Notifications
You must be signed in to change notification settings - Fork 93
Expand file tree
/
Copy pathVscodeFancyRangeHighlighterRenderer.ts
More file actions
120 lines (109 loc) · 3.61 KB
/
VscodeFancyRangeHighlighterRenderer.ts
File metadata and controls
120 lines (109 loc) · 3.61 KB
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
111
112
113
114
115
116
117
118
119
120
import type { DecorationRenderOptions, TextEditorDecorationType } from "vscode";
import { DecorationRangeBehavior } from "vscode";
import type { DecorationStyle } from "@cursorless/lib-common";
import {
BORDER_WIDTH,
CompositeKeyDefaultMap,
getBorderColor,
getBorderRadius,
getBorderStyle,
} from "@cursorless/lib-common";
import { toVscodeRange } from "@cursorless/lib-vscode-common";
import { vscodeApi } from "../../../../vscodeApi";
import type { VscodeTextEditor } from "../../VscodeTextEditor";
import type { RangeTypeColors } from "../RangeTypeColors";
import type {
DifferentiatedStyle,
DifferentiatedStyledRangeList,
} from "./decorationStyle.types";
import { getDifferentiatedStyleMapKey } from "./getDifferentiatedStyleMapKey";
/**
* Handles the actual rendering of decorations for
* {@link VscodeFancyRangeHighlighter}.
*/
export class VscodeFancyRangeHighlighterRenderer {
private decorationTypes: CompositeKeyDefaultMap<
DifferentiatedStyle,
TextEditorDecorationType
>;
constructor(colors: RangeTypeColors) {
this.decorationTypes = new CompositeKeyDefaultMap(
({ style }) => getDecorationStyle(colors, style),
getDifferentiatedStyleMapKey,
);
}
/**
* Renders the given ranges in the given editor.
*
* @param editor The editor to render the decorations in.
* @param decoratedRanges A list with one element per differentiated style,
* each of which contains a list of ranges to render for that style. We render
* the ranges in order of increasing differentiation index.
* {@link VscodeFancyRangeHighlighter} uses this to ensure that nested ranges
* are rendered after their parents. Otherwise they partially interleave,
* which looks bad.
*/
setRanges(
editor: VscodeTextEditor,
decoratedRanges: DifferentiatedStyledRangeList[],
): void {
/**
* Keep track of which styles have no ranges, so that we can set their
* range list to `[]`
*/
const untouchedDecorationTypes = new Set(this.decorationTypes.values());
decoratedRanges.sort(
(a, b) =>
a.differentiatedStyle.differentiationIndex -
b.differentiatedStyle.differentiationIndex,
);
decoratedRanges.forEach(
({ differentiatedStyle: styleParameters, ranges }) => {
const decorationType = this.decorationTypes.get(styleParameters);
vscodeApi.editor.setDecorations(
editor.vscodeEditor,
decorationType,
ranges.map(toVscodeRange),
);
untouchedDecorationTypes.delete(decorationType);
},
);
untouchedDecorationTypes.forEach((decorationType) => {
editor.vscodeEditor.setDecorations(decorationType, []);
});
}
dispose() {
Array.from(this.decorationTypes.values()).forEach((decorationType) => {
decorationType.dispose();
});
}
}
function getDecorationStyle(
colors: RangeTypeColors,
borders: DecorationStyle,
): TextEditorDecorationType {
const options: DecorationRenderOptions = {
light: {
backgroundColor: colors.background.light,
borderColor: getBorderColor(
colors.borderSolid.light,
colors.borderPorous.light,
borders,
),
},
dark: {
backgroundColor: colors.background.dark,
borderColor: getBorderColor(
colors.borderSolid.dark,
colors.borderPorous.dark,
borders,
),
},
borderStyle: getBorderStyle(borders),
borderWidth: BORDER_WIDTH,
borderRadius: getBorderRadius(borders),
rangeBehavior: DecorationRangeBehavior.ClosedClosed,
isWholeLine: borders.isWholeLine,
};
return vscodeApi.window.createTextEditorDecorationType(options);
}