提交 86e5a0b4 编写于 作者: J Joao Moreno

wip: tree user-independent horizontal scrolling

上级 0ece6004
......@@ -677,7 +677,7 @@ export interface ITreeOptions extends ITreeStyles {
showTwistie?: boolean;
indentPixels?: number;
verticalScrollMode?: ScrollbarVisibility;
contentWidthProvider?: IContentWidthProvider;
horizontalScrollMode?: ScrollbarVisibility;
alwaysFocused?: boolean;
autoExpandSingleChildren?: boolean;
useShadows?: boolean;
......
......@@ -101,6 +101,7 @@ export class RowCache implements Lifecycle.IDisposable {
export interface IViewContext extends _.ITreeContext {
cache: RowCache;
horizontalScrolling: boolean;
}
export class ViewItem implements IViewItem {
......@@ -113,6 +114,7 @@ export class ViewItem implements IViewItem {
public top: number;
public height: number;
public width: number = 0;
public onDragStart: (e: DragEvent) => void;
public needsRender: boolean;
......@@ -251,7 +253,19 @@ export class ViewItem implements IViewItem {
}
if (!skipUserRender) {
const style = window.getComputedStyle(this.element);
const paddingLeft = parseFloat(style.paddingLeft);
if (this.context.horizontalScrolling) {
this.element.style.width = 'fit-content';
}
this.context.renderer.renderElement(this.context.tree, this.model.getElement(), this.templateId, this.row.templateData);
if (this.context.horizontalScrolling) {
this.width = DOM.getContentWidth(this.element) + paddingLeft;
this.element.style.width = '';
}
}
}
......@@ -384,7 +398,8 @@ export class TreeView extends HeightMap {
private msGesture: MSGesture;
private lastPointerType: string;
private lastClickTimeStamp: number = 0;
private contentWidthProvider?: _.IContentWidthProvider;
private horizontalScrolling: boolean = true;
private contentWidthUpdateDelayer = new Delayer<void>(50);
private lastRenderTop: number;
......@@ -423,6 +438,9 @@ export class TreeView extends HeightMap {
TreeView.counter++;
this.instance = TreeView.counter;
const horizontalScrollMode = typeof context.options.horizontalScrollMode === 'undefined' ? ScrollbarVisibility.Hidden : context.options.horizontalScrollMode;
const horizontalScrolling = horizontalScrollMode !== ScrollbarVisibility.Hidden;
this.context = {
dataSource: context.dataSource,
renderer: context.renderer,
......@@ -433,7 +451,8 @@ export class TreeView extends HeightMap {
tree: context.tree,
accessibilityProvider: context.accessibilityProvider,
options: context.options,
cache: new RowCache(context)
cache: new RowCache(context),
horizontalScrolling
};
this.modelListeners = [];
......@@ -463,9 +482,6 @@ export class TreeView extends HeightMap {
DOM.addClass(this.domNode, 'no-row-padding');
}
const horizontalScrollMode = typeof context.options.contentWidthProvider === 'undefined' ? ScrollbarVisibility.Hidden : ScrollbarVisibility.Auto;
this.contentWidthProvider = context.options.contentWidthProvider;
this.wrapper = document.createElement('div');
this.wrapper.className = 'monaco-tree-wrapper';
this.scrollableElement = new ScrollableElement(this.wrapper, {
......@@ -678,7 +694,7 @@ export class TreeView extends HeightMap {
this.viewHeight = height || DOM.getContentHeight(this.wrapper); // render
this.scrollHeight = this.getContentHeight();
if (this.contentWidthProvider) {
if (this.horizontalScrolling) {
this.viewWidth = DOM.getContentWidth(this.wrapper);
}
}
......@@ -717,7 +733,7 @@ export class TreeView extends HeightMap {
this.rowsContainer.style.top = (topItem.top - renderTop) + 'px';
}
if (this.contentWidthProvider) {
if (this.horizontalScrolling) {
this.rowsContainer.style.left = -scrollLeft + 'px';
this.rowsContainer.style.width = `${Math.max(scrollWidth, viewWidth)}px`;
}
......@@ -763,9 +779,16 @@ export class TreeView extends HeightMap {
this.scrollTop = scrollTop;
if (this.contentWidthProvider) {
if (this.horizontalScrolling) {
this.contentWidthUpdateDelayer.trigger(() => {
this.scrollWidth = this.contentWidthProvider.getContentWidth();
const keys = Object.keys(this.items);
let scrollWidth = 0;
for (const key of keys) {
scrollWidth = Math.max(scrollWidth, this.items[key].width);
}
this.scrollWidth = scrollWidth + 10 /* scrollbar */;
});
}
}
......
......@@ -10,6 +10,7 @@ export interface IViewItem {
model: Item;
top: number;
height: number;
width: number;
}
export class HeightMap {
......
......@@ -45,7 +45,8 @@ class TestHeightMap extends HeightMap {
return {
model: item,
top: 0,
height: item.getHeight()
height: item.getHeight(),
width: 0
};
}
}
......
......@@ -24,6 +24,7 @@ import { DefaultController, IControllerOptions, OpenMode, ClickBehavior } from '
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import Event, { Emitter } from 'vs/base/common/event';
import { ScrollbarVisibility } from '../../../base/common/scrollable';
export type ListWidget = List<any> | PagedList<any> | ITree;
......@@ -299,7 +300,7 @@ export class WorkbenchTree extends Tree {
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService private configurationService: IConfigurationService
) {
super(container, handleTreeController(configuration, instantiationService), mixin(options, { keyboardSupport: false } as ITreeOptions, false));
super(container, handleTreeController(configuration, instantiationService), { horizontalScrollMode: ScrollbarVisibility.Auto, keyboardSupport: false, ...options });
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);
......
......@@ -416,8 +416,7 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView
accessibilityProvider
}, {
autoExpandSingleChildren: true,
ariaLabel: nls.localize('treeAriaLabel', "Files Explorer"),
contentWidthProvider: { getContentWidth: () => this.getOptimalWidth() }
ariaLabel: nls.localize('treeAriaLabel', "Files Explorer")
});
// Bind context keys
......@@ -460,32 +459,10 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView
}
public getOptimalWidth(): number {
if (!this.explorerViewer) {
return 0;
}
let result = 0;
const parentNode = this.explorerViewer.getHTMLElement();
const rows = [].slice.call(parentNode.querySelectorAll('.monaco-tree-row')) as HTMLElement[];
for (const row of rows) {
const rowStyle = window.getComputedStyle(row);
const content = row.querySelector('.content') as HTMLElement;
const twistieStyle = window.getComputedStyle(content, ':before');
const iconLabel = content.querySelector('.monaco-icon-label') as HTMLElement;
const iconStyle = window.getComputedStyle(iconLabel, ':before'); // width + padding
const decorationsStyle = window.getComputedStyle(iconLabel, ':after'); // width + padding
const label = iconLabel.querySelector('.monaco-icon-label-description-container > .label-name') as HTMLElement;
const twistieWidth = (twistieStyle.display !== 'none' && twistieStyle.content) ? parseFloat(twistieStyle.width) + parseFloat(twistieStyle.paddingLeft) + parseFloat(twistieStyle.paddingRight) : 0;
const iconWidth = iconStyle.content ? parseFloat(iconStyle.width) + parseFloat(iconStyle.paddingLeft) + parseFloat(iconStyle.paddingRight) : 0;
const decorationsWidth = decorationsStyle.content ? parseFloat(decorationsStyle.width) + parseFloat(decorationsStyle.paddingLeft) + parseFloat(decorationsStyle.paddingRight) : 0;
const width = parseFloat(rowStyle.paddingLeft) + twistieWidth + iconWidth + decorationsWidth + label.offsetWidth;
result = Math.max(result, width);
}
const childNodes = [].slice.call(parentNode.querySelectorAll('.explorer-item .label-name')); // select all file labels
return result + 12; // 12 for right padding
return DOM.getLargestChildWidth(parentNode, childNodes);
}
private onFileOperation(e: FileOperationEvent): void {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册