Skip to content

Commit dcc9e66

Browse files
committed
1 parent ed06321 commit dcc9e66

2 files changed

Lines changed: 75 additions & 54 deletions

File tree

src/vs/workbench/contrib/scm/browser/media/scm.css

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,14 @@
183183
outline-offset: -1px;
184184
}
185185

186-
.scm-view .scm-editor-container > .scm-editor-validation {
187-
position: absolute;
188-
width: 100%;
189-
z-index: 10;
190-
left: 0px;
186+
.scm-editor-validation {
191187
box-sizing: border-box;
192188
font-size: 0.9em;
193189
padding: 1px 3px;
194-
display: none;
195-
top: calc(100%);
196-
}
197-
198-
.scm-view .scm-editor-container.synthetic-focus > .scm-editor-validation {
199190
display: block;
191+
border-width: 1px;
192+
border-style: solid;
193+
border-top: none;
200194
}
201195

202196
.scm-view .scm-editor-placeholder {

src/vs/workbench/contrib/scm/browser/scmViewPane.ts

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { IDisposable, Disposable, DisposableStore, combinedDisposable } from 'vs
1010
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
1111
import { append, $, addClass, toggleClass, removeClass, Dimension } from 'vs/base/browser/dom';
1212
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
13-
import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMService, ISCMRepository, ISCMInput } from 'vs/workbench/contrib/scm/common/scm';
13+
import { ISCMResourceGroup, ISCMResource, InputValidationType, ISCMService, ISCMRepository, ISCMInput, IInputValidation } from 'vs/workbench/contrib/scm/common/scm';
1414
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
1515
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
1616
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -78,6 +78,7 @@ import { DEFAULT_FONT_FAMILY } from 'vs/workbench/browser/style';
7878
import { Command } from 'vs/editor/common/modes';
7979
import { renderCodicons } from 'vs/base/common/codicons';
8080
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
81+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
8182

8283
type TreeElement = ISCMRepository | ISCMInput | ISCMResourceGroup | IResourceNode<ISCMResource, ISCMResourceGroup> | ISCMResource;
8384

@@ -1179,20 +1180,24 @@ class SCMInputWidget extends Disposable {
11791180
private element: HTMLElement;
11801181
private editorContainer: HTMLElement;
11811182
private placeholderTextContainer: HTMLElement;
1182-
private validationContainer: HTMLElement;
11831183
private inputEditor: CodeEditorWidget;
11841184

11851185
private model: { readonly input: ISCMInput; readonly textModel: ITextModel; } | undefined;
11861186
private repositoryContextKey: IContextKey<ISCMRepository | undefined>;
11871187
private repositoryDisposables = new DisposableStore();
11881188

1189+
private validation: IInputValidation | undefined;
1190+
private validationDisposable: IDisposable = Disposable.None;
1191+
11891192
readonly onDidChangeContentHeight: Event<void>;
11901193

11911194
get input(): ISCMInput | undefined {
11921195
return this.model?.input;
11931196
}
11941197

11951198
set input(input: ISCMInput | undefined) {
1199+
this.validationDisposable.dispose();
1200+
11961201
this.repositoryDisposables.dispose();
11971202
this.repositoryDisposables = new DisposableStore();
11981203
this.repositoryContextKey.set(input?.repository);
@@ -1229,25 +1234,8 @@ class SCMInputWidget extends Disposable {
12291234
const offset = position && textModel.getOffsetAt(position);
12301235
const value = textModel.getValue();
12311236

1232-
const result = await input.validateInput(value, offset || 0);
1233-
1234-
if (!result) {
1235-
removeClass(this.editorContainer, 'validation-info');
1236-
removeClass(this.editorContainer, 'validation-warning');
1237-
removeClass(this.editorContainer, 'validation-error');
1238-
removeClass(this.validationContainer, 'validation-info');
1239-
removeClass(this.validationContainer, 'validation-warning');
1240-
removeClass(this.validationContainer, 'validation-error');
1241-
this.validationContainer.textContent = null;
1242-
} else {
1243-
toggleClass(this.editorContainer, 'validation-info', result.type === InputValidationType.Information);
1244-
toggleClass(this.editorContainer, 'validation-warning', result.type === InputValidationType.Warning);
1245-
toggleClass(this.editorContainer, 'validation-error', result.type === InputValidationType.Error);
1246-
toggleClass(this.validationContainer, 'validation-info', result.type === InputValidationType.Information);
1247-
toggleClass(this.validationContainer, 'validation-warning', result.type === InputValidationType.Warning);
1248-
toggleClass(this.validationContainer, 'validation-error', result.type === InputValidationType.Error);
1249-
this.validationContainer.textContent = result.message;
1250-
}
1237+
this.validation = await input.validateInput(value, offset || 0);
1238+
this.renderValidation();
12511239
};
12521240

12531241
const triggerValidation = () => validationDelayer.trigger(validate);
@@ -1324,13 +1312,13 @@ class SCMInputWidget extends Disposable {
13241312
@IKeybindingService private keybindingService: IKeybindingService,
13251313
@IConfigurationService private configurationService: IConfigurationService,
13261314
@IInstantiationService instantiationService: IInstantiationService,
1315+
@IContextViewService private readonly contextViewService: IContextViewService,
13271316
) {
13281317
super();
13291318

13301319
this.element = append(container, $('.scm-editor'));
13311320
this.editorContainer = append(this.element, $('.scm-editor-container'));
13321321
this.placeholderTextContainer = append(this.editorContainer, $('.scm-editor-placeholder'));
1333-
this.validationContainer = append(this.editorContainer, $('.scm-editor-validation'));
13341322

13351323
const contextKeyService2 = contextKeyService.createScoped(this.element);
13361324
this.repositoryContextKey = contextKeyService2.createKey('scmRepository', undefined);
@@ -1368,8 +1356,14 @@ class SCMInputWidget extends Disposable {
13681356
this.inputEditor = instantiationService2.createInstance(CodeEditorWidget, this.editorContainer, editorOptions, codeEditorWidgetOptions);
13691357
this._register(this.inputEditor);
13701358

1371-
this._register(this.inputEditor.onDidFocusEditorText(() => addClass(this.editorContainer, 'synthetic-focus')));
1372-
this._register(this.inputEditor.onDidBlurEditorText(() => removeClass(this.editorContainer, 'synthetic-focus')));
1359+
this._register(this.inputEditor.onDidFocusEditorText(() => {
1360+
addClass(this.editorContainer, 'synthetic-focus');
1361+
this.renderValidation();
1362+
}));
1363+
this._register(this.inputEditor.onDidBlurEditorText(() => {
1364+
removeClass(this.editorContainer, 'synthetic-focus');
1365+
this.validationDisposable.dispose();
1366+
}));
13731367

13741368
const onInputFontFamilyChanged = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.inputFontFamily'));
13751369
this._register(onInputFontFamilyChanged(() => this.inputEditor.updateOptions({ fontFamily: this.getInputEditorFontFamily() })));
@@ -1390,6 +1384,33 @@ class SCMInputWidget extends Disposable {
13901384
};
13911385

13921386
this.inputEditor.layout(dimension);
1387+
this.renderValidation();
1388+
}
1389+
1390+
private renderValidation(): void {
1391+
this.validationDisposable.dispose();
1392+
1393+
toggleClass(this.editorContainer, 'validation-info', this.validation?.type === InputValidationType.Information);
1394+
toggleClass(this.editorContainer, 'validation-warning', this.validation?.type === InputValidationType.Warning);
1395+
toggleClass(this.editorContainer, 'validation-error', this.validation?.type === InputValidationType.Error);
1396+
1397+
if (!this.validation || !this.inputEditor.hasTextFocus()) {
1398+
return;
1399+
}
1400+
1401+
this.validationDisposable = this.contextViewService.showContextView({
1402+
getAnchor: () => this.editorContainer,
1403+
render: container => {
1404+
const element = append(container, $('.scm-editor-validation'));
1405+
toggleClass(element, 'validation-info', this.validation!.type === InputValidationType.Information);
1406+
toggleClass(element, 'validation-warning', this.validation!.type === InputValidationType.Warning);
1407+
toggleClass(element, 'validation-error', this.validation!.type === InputValidationType.Error);
1408+
element.style.width = `${this.editorContainer.clientWidth}px`;
1409+
element.textContent = this.validation!.message;
1410+
return Disposable.None;
1411+
},
1412+
anchorAlignment: AnchorAlignment.LEFT
1413+
});
13931414
}
13941415

13951416
private getInputEditorFontFamily(): string {
@@ -1405,6 +1426,12 @@ class SCMInputWidget extends Disposable {
14051426

14061427
return this.defaultInputFontFamily;
14071428
}
1429+
1430+
dispose(): void {
1431+
this.repositoryDisposables.dispose();
1432+
this.validationDisposable.dispose();
1433+
super.dispose();
1434+
}
14081435
}
14091436

14101437
export class SCMViewPane extends ViewPane {
@@ -1678,82 +1705,82 @@ export class SCMViewPane extends ViewPane {
16781705
registerThemingParticipant((theme, collector) => {
16791706
const inputBackgroundColor = theme.getColor(inputBackground);
16801707
if (inputBackgroundColor) {
1681-
collector.addRule(`.scm-viewlet .scm-editor-container .monaco-editor-background,
1682-
.scm-viewlet .scm-editor-container .monaco-editor,
1683-
.scm-viewlet .scm-editor-container .monaco-editor .margin
1708+
collector.addRule(`.scm-view .scm-editor-container .monaco-editor-background,
1709+
.scm-view .scm-editor-container .monaco-editor,
1710+
.scm-view .scm-editor-container .monaco-editor .margin
16841711
{ background-color: ${inputBackgroundColor}; }`);
16851712
}
16861713

16871714
const inputForegroundColor = theme.getColor(inputForeground);
16881715
if (inputForegroundColor) {
1689-
collector.addRule(`.scm-viewlet .scm-editor-container .mtk1 { color: ${inputForegroundColor}; }`);
1716+
collector.addRule(`.scm-view .scm-editor-container .mtk1 { color: ${inputForegroundColor}; }`);
16901717
}
16911718

16921719
const inputBorderColor = theme.getColor(inputBorder);
16931720
if (inputBorderColor) {
1694-
collector.addRule(`.scm-viewlet .scm-editor-container { outline: 1px solid ${inputBorderColor}; }`);
1721+
collector.addRule(`.scm-view .scm-editor-container { outline: 1px solid ${inputBorderColor}; }`);
16951722
}
16961723

16971724
const focusBorderColor = theme.getColor(focusBorder);
16981725
if (focusBorderColor) {
1699-
collector.addRule(`.scm-viewlet .scm-editor-container.synthetic-focus { outline: 1px solid ${focusBorderColor}; }`);
1726+
collector.addRule(`.scm-view .scm-editor-container.synthetic-focus { outline: 1px solid ${focusBorderColor}; }`);
17001727
}
17011728

17021729
const inputPlaceholderForegroundColor = theme.getColor(inputPlaceholderForeground);
17031730
if (inputPlaceholderForegroundColor) {
1704-
collector.addRule(`.scm-viewlet .scm-editor-placeholder { color: ${inputPlaceholderForegroundColor}; }`);
1731+
collector.addRule(`.scm-view .scm-editor-placeholder { color: ${inputPlaceholderForegroundColor}; }`);
17051732
}
17061733

17071734
const inputValidationInfoBorderColor = theme.getColor(inputValidationInfoBorder);
17081735
if (inputValidationInfoBorderColor) {
1709-
collector.addRule(`.scm-viewlet .scm-editor-container.validation-info { outline: 1px solid ${inputValidationInfoBorderColor}; }`);
1710-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-info { border: 1px solid ${inputValidationInfoBorderColor}; }`);
1736+
collector.addRule(`.scm-view .scm-editor-container.validation-info { outline: 1px solid ${inputValidationInfoBorderColor}; }`);
1737+
collector.addRule(`.scm-editor-validation.validation-info { border-color: ${inputValidationInfoBorderColor}; }`);
17111738
}
17121739

17131740
const inputValidationInfoBackgroundColor = theme.getColor(inputValidationInfoBackground);
17141741
if (inputValidationInfoBackgroundColor) {
1715-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-info { background-color: ${inputValidationInfoBackgroundColor}; }`);
1742+
collector.addRule(`.scm-editor-validation.validation-info { background-color: ${inputValidationInfoBackgroundColor}; }`);
17161743
}
17171744

17181745
const inputValidationInfoForegroundColor = theme.getColor(inputValidationInfoForeground);
17191746
if (inputValidationInfoForegroundColor) {
1720-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-info { color: ${inputValidationInfoForegroundColor}; }`);
1747+
collector.addRule(`.scm-editor-validation.validation-info { color: ${inputValidationInfoForegroundColor}; }`);
17211748
}
17221749

17231750
const inputValidationWarningBorderColor = theme.getColor(inputValidationWarningBorder);
17241751
if (inputValidationWarningBorderColor) {
1725-
collector.addRule(`.scm-viewlet .scm-editor-container.validation-warning { outline: 1px solid ${inputValidationWarningBorderColor}; }`);
1726-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-warning { border: 1px solid ${inputValidationWarningBorderColor}; }`);
1752+
collector.addRule(`.scm-view .scm-editor-container.validation-warning { outline: 1px solid ${inputValidationWarningBorderColor}; }`);
1753+
collector.addRule(`.scm-editor-validation.validation-warning { border-color: ${inputValidationWarningBorderColor}; }`);
17271754
}
17281755

17291756
const inputValidationWarningBackgroundColor = theme.getColor(inputValidationWarningBackground);
17301757
if (inputValidationWarningBackgroundColor) {
1731-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-warning { background-color: ${inputValidationWarningBackgroundColor}; }`);
1758+
collector.addRule(`.scm-editor-validation.validation-warning { background-color: ${inputValidationWarningBackgroundColor}; }`);
17321759
}
17331760

17341761
const inputValidationWarningForegroundColor = theme.getColor(inputValidationWarningForeground);
17351762
if (inputValidationWarningForegroundColor) {
1736-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-warning { color: ${inputValidationWarningForegroundColor}; }`);
1763+
collector.addRule(`.scm-editor-validation.validation-warning { color: ${inputValidationWarningForegroundColor}; }`);
17371764
}
17381765

17391766
const inputValidationErrorBorderColor = theme.getColor(inputValidationErrorBorder);
17401767
if (inputValidationErrorBorderColor) {
1741-
collector.addRule(`.scm-viewlet .scm-editor-container.validation-error { outline: 1px solid ${inputValidationErrorBorderColor}; }`);
1742-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-error { border: 1px solid ${inputValidationErrorBorderColor}; }`);
1768+
collector.addRule(`.scm-view .scm-editor-container.validation-error { outline: 1px solid ${inputValidationErrorBorderColor}; }`);
1769+
collector.addRule(`.scm-editor-validation.validation-error { border-color: ${inputValidationErrorBorderColor}; }`);
17431770
}
17441771

17451772
const inputValidationErrorBackgroundColor = theme.getColor(inputValidationErrorBackground);
17461773
if (inputValidationErrorBackgroundColor) {
1747-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-error { background-color: ${inputValidationErrorBackgroundColor}; }`);
1774+
collector.addRule(`.scm-editor-validation.validation-error { background-color: ${inputValidationErrorBackgroundColor}; }`);
17481775
}
17491776

17501777
const inputValidationErrorForegroundColor = theme.getColor(inputValidationErrorForeground);
17511778
if (inputValidationErrorForegroundColor) {
1752-
collector.addRule(`.scm-viewlet .scm-editor-validation.validation-error { color: ${inputValidationErrorForegroundColor}; }`);
1779+
collector.addRule(`.scm-editor-validation.validation-error { color: ${inputValidationErrorForegroundColor}; }`);
17531780
}
17541781

17551782
const repositoryStatusActionsBorderColor = theme.getColor(SIDE_BAR_BORDER);
17561783
if (repositoryStatusActionsBorderColor) {
1757-
collector.addRule(`.scm-viewlet .scm-provider > .status > .monaco-action-bar > .actions-container { border-color: ${repositoryStatusActionsBorderColor}; }`);
1784+
collector.addRule(`.scm-view .scm-provider > .status > .monaco-action-bar > .actions-container { border-color: ${repositoryStatusActionsBorderColor}; }`);
17581785
}
17591786
});

0 commit comments

Comments
 (0)