Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/find/browser/findOptionsWidget.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as dom from '../../../../base/browser/dom.js';
7
import './findOptionsWidget.css';
8
import { CaseSensitiveToggle, RegexToggle, WholeWordsToggle } from '../../../../base/browser/ui/findinput/findInputToggles.js';
9
import { Widget } from '../../../../base/browser/ui/widget.js';
10
import { RunOnceScheduler } from '../../../../base/common/async.js';
11
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from '../../../browser/editorBrowser.js';
12
import { FIND_IDS } from './findModel.js';
13
import { FindReplaceState } from './findState.js';
14
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
15
import { asCssVariable, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground } from '../../../../platform/theme/common/colorRegistry.js';
16
import { createInstantHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js';
17
18
export class FindOptionsWidget extends Widget implements IOverlayWidget {
19
20
private static readonly ID = 'editor.contrib.findOptionsWidget';
21
22
private readonly _editor: ICodeEditor;
23
private readonly _state: FindReplaceState;
24
private readonly _keybindingService: IKeybindingService;
25
26
private readonly _domNode: HTMLElement;
27
private readonly regex: RegexToggle;
28
private readonly wholeWords: WholeWordsToggle;
29
private readonly caseSensitive: CaseSensitiveToggle;
30
31
constructor(
32
editor: ICodeEditor,
33
state: FindReplaceState,
34
keybindingService: IKeybindingService
35
) {
36
super();
37
38
this._editor = editor;
39
this._state = state;
40
this._keybindingService = keybindingService;
41
42
this._domNode = document.createElement('div');
43
this._domNode.className = 'findOptionsWidget';
44
this._domNode.style.display = 'none';
45
this._domNode.style.top = '10px';
46
this._domNode.style.zIndex = '12';
47
this._domNode.setAttribute('role', 'presentation');
48
this._domNode.setAttribute('aria-hidden', 'true');
49
50
const toggleStyles = {
51
inputActiveOptionBorder: asCssVariable(inputActiveOptionBorder),
52
inputActiveOptionForeground: asCssVariable(inputActiveOptionForeground),
53
inputActiveOptionBackground: asCssVariable(inputActiveOptionBackground),
54
};
55
56
const hoverDelegate = this._register(createInstantHoverDelegate());
57
58
this.caseSensitive = this._register(new CaseSensitiveToggle({
59
appendTitle: this._keybindingLabelFor(FIND_IDS.ToggleCaseSensitiveCommand),
60
isChecked: this._state.matchCase,
61
hoverDelegate,
62
...toggleStyles
63
}));
64
this._domNode.appendChild(this.caseSensitive.domNode);
65
this._register(this.caseSensitive.onChange(() => {
66
this._state.change({
67
matchCase: this.caseSensitive.checked
68
}, false);
69
}));
70
71
this.wholeWords = this._register(new WholeWordsToggle({
72
appendTitle: this._keybindingLabelFor(FIND_IDS.ToggleWholeWordCommand),
73
isChecked: this._state.wholeWord,
74
hoverDelegate,
75
...toggleStyles
76
}));
77
this._domNode.appendChild(this.wholeWords.domNode);
78
this._register(this.wholeWords.onChange(() => {
79
this._state.change({
80
wholeWord: this.wholeWords.checked
81
}, false);
82
}));
83
84
this.regex = this._register(new RegexToggle({
85
appendTitle: this._keybindingLabelFor(FIND_IDS.ToggleRegexCommand),
86
isChecked: this._state.isRegex,
87
hoverDelegate,
88
...toggleStyles
89
}));
90
this._domNode.appendChild(this.regex.domNode);
91
this._register(this.regex.onChange(() => {
92
this._state.change({
93
isRegex: this.regex.checked
94
}, false);
95
}));
96
97
this._editor.addOverlayWidget(this);
98
99
this._register(this._state.onFindReplaceStateChange((e) => {
100
let somethingChanged = false;
101
if (e.isRegex) {
102
this.regex.checked = this._state.isRegex;
103
somethingChanged = true;
104
}
105
if (e.wholeWord) {
106
this.wholeWords.checked = this._state.wholeWord;
107
somethingChanged = true;
108
}
109
if (e.matchCase) {
110
this.caseSensitive.checked = this._state.matchCase;
111
somethingChanged = true;
112
}
113
if (!this._state.isRevealed && somethingChanged) {
114
this._revealTemporarily();
115
}
116
}));
117
118
this._register(dom.addDisposableListener(this._domNode, dom.EventType.MOUSE_LEAVE, (e) => this._onMouseLeave()));
119
this._register(dom.addDisposableListener(this._domNode, 'mouseover', (e) => this._onMouseOver()));
120
}
121
122
private _keybindingLabelFor(actionId: string): string {
123
const kb = this._keybindingService.lookupKeybinding(actionId);
124
if (!kb) {
125
return '';
126
}
127
return ` (${kb.getLabel()})`;
128
}
129
130
public override dispose(): void {
131
this._editor.removeOverlayWidget(this);
132
super.dispose();
133
}
134
135
// ----- IOverlayWidget API
136
137
public getId(): string {
138
return FindOptionsWidget.ID;
139
}
140
141
public getDomNode(): HTMLElement {
142
return this._domNode;
143
}
144
145
public getPosition(): IOverlayWidgetPosition {
146
return {
147
preference: OverlayWidgetPositionPreference.TOP_RIGHT_CORNER
148
};
149
}
150
151
public highlightFindOptions(): void {
152
this._revealTemporarily();
153
}
154
155
private _hideSoon = this._register(new RunOnceScheduler(() => this._hide(), 2000));
156
157
private _revealTemporarily(): void {
158
this._show();
159
this._hideSoon.schedule();
160
}
161
162
private _onMouseLeave(): void {
163
this._hideSoon.schedule();
164
}
165
166
private _onMouseOver(): void {
167
this._hideSoon.cancel();
168
}
169
170
private _isVisible: boolean = false;
171
172
private _show(): void {
173
if (this._isVisible) {
174
return;
175
}
176
this._isVisible = true;
177
this._domNode.style.display = 'block';
178
}
179
180
private _hide(): void {
181
if (!this._isVisible) {
182
return;
183
}
184
this._isVisible = false;
185
this._domNode.style.display = 'none';
186
}
187
}
188
189