Skip to content

Commit d6ee543

Browse files
committed
Merge branch 'joao/list-dynamic-horizontal-scrolling'
2 parents eadd81d + 5a5c5ec commit d6ee543

9 files changed

Lines changed: 116 additions & 48 deletions

File tree

src/vs/base/browser/ui/list/listPaging.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import 'vs/css!./list';
77
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
88
import { range } from 'vs/base/common/arrays';
99
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent } from './list';
10-
import { List, IListStyles, IListOptions, IListAccessibilityProvider } from './listWidget';
10+
import { List, IListStyles, IListOptions, IListAccessibilityProvider, IListOptionsUpdate } from './listWidget';
1111
import { IPagedModel } from 'vs/base/common/paging';
1212
import { Event } from 'vs/base/common/event';
1313
import { CancellationTokenSource } from 'vs/base/common/cancellation';
@@ -136,6 +136,10 @@ export class PagedList<T> implements IDisposable {
136136
this.list = new List(user, container, virtualDelegate, pagedRenderers, fromPagedListOptions(modelProvider, options));
137137
}
138138

139+
updateOptions(options: IListOptionsUpdate) {
140+
this.list.updateOptions(options);
141+
}
142+
139143
getHTMLElement(): HTMLElement {
140144
return this.list.getHTMLElement();
141145
}

src/vs/base/browser/ui/list/listView.ts

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export interface IListViewAccessibilityProvider<T> {
5151
export interface IListViewOptionsUpdate {
5252
readonly additionalScrollHeight?: number;
5353
readonly smoothScrolling?: boolean;
54+
readonly horizontalScrolling?: boolean;
5455
}
5556

5657
export interface IListViewOptions<T> extends IListViewOptionsUpdate {
@@ -61,7 +62,6 @@ export interface IListViewOptions<T> extends IListViewOptionsUpdate {
6162
readonly setRowHeight?: boolean;
6263
readonly supportDynamicHeights?: boolean;
6364
readonly mouseSupport?: boolean;
64-
readonly horizontalScrolling?: boolean;
6565
readonly accessibilityProvider?: IListViewAccessibilityProvider<T>;
6666
readonly transformOptimization?: boolean;
6767
}
@@ -227,7 +227,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
227227
private setRowLineHeight: boolean;
228228
private setRowHeight: boolean;
229229
private supportDynamicHeights: boolean;
230-
private horizontalScrolling: boolean;
231230
private additionalScrollHeight: number;
232231
private accessibilityProvider: ListViewAccessibilityProvider<T>;
233232
private scrollWidth: number | undefined;
@@ -249,6 +248,35 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
249248
get onWillScroll(): Event<ScrollEvent> { return this.scrollableElement.onWillScroll; }
250249
get containerDomNode(): HTMLElement { return this.rowsContainer; }
251250

251+
private _horizontalScrolling: boolean = false;
252+
private get horizontalScrolling(): boolean { return this._horizontalScrolling; }
253+
private set horizontalScrolling(value: boolean) {
254+
if (value === this._horizontalScrolling) {
255+
return;
256+
}
257+
258+
if (value && this.supportDynamicHeights) {
259+
throw new Error('Horizontal scrolling and dynamic heights not supported simultaneously');
260+
}
261+
262+
this._horizontalScrolling = value;
263+
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
264+
265+
if (this._horizontalScrolling) {
266+
for (const item of this.items) {
267+
this.measureItemWidth(item);
268+
}
269+
270+
this.updateScrollWidth();
271+
this.scrollableElement.setScrollDimensions({ width: DOM.getContentWidth(this.domNode) });
272+
this.rowsContainer.style.width = `${Math.max(this.scrollWidth || 0, this.renderWidth)}px`;
273+
} else {
274+
this.scrollableElementWidthDelayer.cancel();
275+
this.scrollableElement.setScrollDimensions({ width: this.renderWidth, scrollWidth: this.renderWidth });
276+
this.rowsContainer.style.width = '';
277+
}
278+
}
279+
252280
constructor(
253281
container: HTMLElement,
254282
private virtualDelegate: IListVirtualDelegate<T>,
@@ -280,8 +308,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
280308

281309
DOM.toggleClass(this.domNode, 'mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);
282310

283-
this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
284-
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling);
311+
this._horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
312+
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
285313

286314
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
287315

@@ -300,7 +328,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
300328
this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => DOM.scheduleAtNextAnimationFrame(cb));
301329
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
302330
alwaysConsumeMouseWheel: true,
303-
horizontal: this.horizontalScrolling ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden,
331+
horizontal: ScrollbarVisibility.Auto,
304332
vertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode),
305333
useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows),
306334
}, this.scrollable));
@@ -329,14 +357,18 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
329357
this.layout();
330358
}
331359

332-
updateOptions(options: IListViewOptions<T>) {
360+
updateOptions(options: IListViewOptionsUpdate) {
333361
if (options.additionalScrollHeight !== undefined) {
334362
this.additionalScrollHeight = options.additionalScrollHeight;
335363
}
336364

337365
if (options.smoothScrolling !== undefined) {
338366
this.scrollable.setSmoothScrollDuration(options.smoothScrolling ? 125 : 0);
339367
}
368+
369+
if (options.horizontalScrolling !== undefined) {
370+
this.horizontalScrolling = options.horizontalScrolling;
371+
}
340372
}
341373

342374
triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) {
@@ -485,6 +517,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
485517

486518
private eventuallyUpdateScrollWidth(): void {
487519
if (!this.horizontalScrolling) {
520+
this.scrollableElementWidthDelayer.cancel();
488521
return;
489522
}
490523

@@ -496,10 +529,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
496529
return;
497530
}
498531

499-
if (this.items.length === 0) {
500-
this.scrollableElement.setScrollDimensions({ scrollWidth: 0 });
501-
}
502-
503532
let scrollWidth = 0;
504533

505534
for (const item of this.items) {
@@ -509,7 +538,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
509538
}
510539

511540
this.scrollWidth = scrollWidth;
512-
this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth + 10 });
541+
this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth === 0 ? 0 : (scrollWidth + 10) });
513542
}
514543

515544
updateWidth(index: number): void {

src/vs/base/browser/ui/tree/abstractTree.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
962962
readonly filterOnType?: boolean;
963963
readonly openOnSingleClick?: boolean;
964964
readonly smoothScrolling?: boolean;
965+
readonly horizontalScrolling?: boolean;
965966
}
966967

967968
export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTreeOptionsUpdate, IListOptions<T> {
@@ -1361,7 +1362,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
13611362
this.view.updateOptions({
13621363
enableKeyboardNavigation: this._options.simpleKeyboardNavigation,
13631364
automaticKeyboardNavigation: this._options.automaticKeyboardNavigation,
1364-
smoothScrolling: this._options.smoothScrolling
1365+
smoothScrolling: this._options.smoothScrolling,
1366+
horizontalScrolling: this._options.horizontalScrolling
13651367
});
13661368

13671369
if (this.typeFilterController) {

src/vs/base/browser/ui/tree/asyncDataTree.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
407407
this.tree.updateOptions(options);
408408
}
409409

410+
get options(): IAsyncDataTreeOptions<T, TFilterData> {
411+
return this.tree.options as IAsyncDataTreeOptions<T, TFilterData>;
412+
}
413+
410414
// Widget
411415

412416
getHTMLElement(): HTMLElement {

0 commit comments

Comments
 (0)