Skip to content

Commit ab94d9b

Browse files
committed
scm: auto growing input editor
1 parent bb9549f commit ab94d9b

2 files changed

Lines changed: 46 additions & 13 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178

179179
.scm-viewlet .scm-input {
180180
height: 100%;
181+
margin-left: 6px;
181182
}
182183

183184
.scm-viewlet .scm-editor {

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

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,16 @@ interface InputTemplate {
245245

246246
class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore, InputTemplate> {
247247

248+
static readonly DEFAULT_HEIGHT = 26;
249+
248250
static readonly TEMPLATE_ID = 'input';
249251
get templateId(): string { return InputRenderer.TEMPLATE_ID; }
250252

253+
private contentHeights = new WeakMap<ISCMInput, number>();
254+
251255
constructor(
252-
private layoutCache: ISCMLayout,
256+
private outerLayout: ISCMLayout,
257+
private updateHeight: (input: ISCMInput, height: number) => void,
253258
@IInstantiationService private instantiationService: IInstantiationService,
254259
) { }
255260

@@ -260,16 +265,41 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,
260265
return { inputWidget, disposable: Disposable.None, templateDisposable: inputWidget };
261266
}
262267

263-
renderElement(node: ITreeNode<ISCMInput, FuzzyScore>, index: number, templateData: InputTemplate, height: number | undefined): void {
268+
renderElement(node: ITreeNode<ISCMInput, FuzzyScore>, index: number, templateData: InputTemplate): void {
264269
templateData.disposable.dispose();
265270

266271
const disposables = new DisposableStore();
267272
const input = node.element;
268273
templateData.inputWidget.input = input;
269274
disposables.add({ dispose: () => templateData.inputWidget.input = undefined });
270275

276+
// Rerender the element whenever the editor content height changes
277+
const onDidChangeContentHeight = () => {
278+
const contentHeight = templateData.inputWidget.getContentHeight();
279+
const lastContentHeight = this.contentHeights.get(input)!;
280+
this.contentHeights.set(input, contentHeight);
281+
282+
if (lastContentHeight !== contentHeight) {
283+
if (lastContentHeight !== undefined) {
284+
this.updateHeight(input, contentHeight + 10);
285+
templateData.inputWidget.layout();
286+
} else if (contentHeight !== InputRenderer.DEFAULT_HEIGHT) {
287+
// first time render, we must rerender on the next stack frame
288+
const timeout = setTimeout(() => {
289+
this.updateHeight(input, contentHeight + 10);
290+
templateData.inputWidget.layout();
291+
});
292+
disposables.add({ dispose: () => clearTimeout(timeout) });
293+
}
294+
}
295+
};
296+
297+
disposables.add(templateData.inputWidget.onDidChangeContentHeight(onDidChangeContentHeight));
298+
onDidChangeContentHeight();
299+
300+
// Layout the editor whenever the outer layout happens
271301
const layoutEditor = () => templateData.inputWidget.layout();
272-
disposables.add(this.layoutCache.onDidChange(layoutEditor));
302+
disposables.add(this.outerLayout.onDidChange(layoutEditor));
273303
layoutEditor();
274304

275305
templateData.disposable = disposables;
@@ -525,7 +555,7 @@ class ProviderListDelegate implements IListVirtualDelegate<TreeElement> {
525555

526556
getHeight(element: TreeElement) {
527557
if (isSCMInput(element)) {
528-
return 36;
558+
return InputRenderer.DEFAULT_HEIGHT + 10;
529559
} else {
530560
return 22;
531561
}
@@ -1087,8 +1117,7 @@ class SCMInputWidget extends Disposable {
10871117
private repositoryContextKey: IContextKey<ISCMRepository | undefined>;
10881118
private repositoryDisposables = new DisposableStore();
10891119

1090-
private _onDidChangeHeight = new Emitter<void>();
1091-
readonly onDidChangeHeight = this._onDidChangeHeight.event;
1120+
readonly onDidChangeContentHeight: Event<void>;
10921121

10931122
get input(): ISCMInput | undefined {
10941123
return this.model?.input;
@@ -1285,17 +1314,19 @@ class SCMInputWidget extends Disposable {
12851314
const onInputFontFamilyChanged = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.inputFontFamily'));
12861315
this._register(onInputFontFamilyChanged(() => this.inputEditor.updateOptions({ fontFamily: this.getInputEditorFontFamily() })));
12871316

1288-
const onDidChangeContentHeight = Event.filter(this.inputEditor.onDidContentSizeChange, e => e.contentHeightChanged);
1289-
this._register(onDidChangeContentHeight(() => this._onDidChangeHeight.fire()));
1317+
this.onDidChangeContentHeight = Event.signal(Event.filter(this.inputEditor.onDidContentSizeChange, e => e.contentHeightChanged));
12901318
}
12911319

1292-
layout(): void {
1293-
// const editorContentHeight = this.inputEditor.getContentHeight();
1294-
// const editorHeight = Math.min(editorContentHeight, 134);
1320+
getContentHeight(): number {
1321+
const editorContentHeight = this.inputEditor.getContentHeight();
1322+
return Math.min(editorContentHeight, 134);
1323+
}
12951324

1325+
layout(): void {
1326+
const editorHeight = this.getContentHeight();
12961327
const dimension: Dimension = {
12971328
width: this.element.clientWidth - 2,
1298-
height: 26,
1329+
height: editorHeight,
12991330
// height: editorHeight - 2
13001331
};
13011332

@@ -1378,9 +1409,10 @@ export class SCMViewPane extends ViewPane {
13781409
this._register(actionRunner);
13791410
this._register(actionRunner.onDidBeforeRun(() => this.tree.domFocus()));
13801411

1412+
const inputRenderer = new InputRenderer(this.layoutCache, (input, height) => this.tree.updateElementHeight(input, height), this.instantiationService);
13811413
const renderers = [
13821414
new RepositoryRenderer(this.commandService, this.themeService),
1383-
new InputRenderer(this.layoutCache, this.instantiationService),
1415+
inputRenderer,
13841416
new ResourceGroupRenderer(actionViewItemProvider, this.themeService, this.menus),
13851417
new ResourceRenderer(() => this.viewModel, this.listLabels, actionViewItemProvider, actionRunner, this.themeService, this.menus)
13861418
];

0 commit comments

Comments
 (0)