提交 0ece6004 编写于 作者: J Joao Moreno

wip: explorer horizontal scrolling

上级 0e8383eb
......@@ -459,6 +459,9 @@ const sizeUtils = {
getBorderLeftWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-left-width', 'borderLeftWidth');
},
getBorderRightWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-right-width', 'borderRightWidth');
},
getBorderTopWidth: function (element: HTMLElement): number {
return getDimension(element, 'border-top-width', 'borderTopWidth');
},
......@@ -466,6 +469,12 @@ const sizeUtils = {
return getDimension(element, 'border-bottom-width', 'borderBottomWidth');
},
getPaddingLeft: function (element: HTMLElement): number {
return getDimension(element, 'padding-left', 'paddingLeft');
},
getPaddingRight: function (element: HTMLElement): number {
return getDimension(element, 'padding-right', 'paddingRight');
},
getPaddingTop: function (element: HTMLElement): number {
return getDimension(element, 'padding-top', 'paddingTop');
},
......@@ -571,6 +580,12 @@ export function getTotalWidth(element: HTMLElement): number {
return element.offsetWidth + margin;
}
export function getContentWidth(element: HTMLElement): number {
let border = sizeUtils.getBorderLeftWidth(element) + sizeUtils.getBorderRightWidth(element);
let padding = sizeUtils.getPaddingLeft(element) + sizeUtils.getPaddingRight(element);
return element.offsetWidth - border - padding;
}
export function getTotalScrollWidth(element: HTMLElement): number {
let margin = sizeUtils.getMarginLeft(element) + sizeUtils.getMarginRight(element);
return element.scrollWidth + margin;
......
......@@ -668,11 +668,16 @@ export interface ITreeConfiguration {
accessibilityProvider?: IAccessibilityProvider;
}
export interface IContentWidthProvider {
getContentWidth(): number;
}
export interface ITreeOptions extends ITreeStyles {
twistiePixels?: number;
showTwistie?: boolean;
indentPixels?: number;
verticalScrollMode?: ScrollbarVisibility;
contentWidthProvider?: IContentWidthProvider;
alwaysFocused?: boolean;
autoExpandSingleChildren?: boolean;
useShadows?: boolean;
......
......@@ -212,7 +212,7 @@ export class Tree implements _.ITree {
}
getContentHeight(): number {
return this.view.getTotalHeight();
return this.view.getContentHeight();
}
public setHighlight(element?: any, eventPayload?: any): void {
......
......@@ -25,6 +25,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import Event, { Emitter } from 'vs/base/common/event';
import { IDomNodePagePosition } from 'vs/base/browser/dom';
import { DataTransfers } from 'vs/base/browser/dnd';
import { Delayer } from 'vs/base/common/async';
export interface IRow {
element: HTMLElement;
......@@ -383,6 +384,8 @@ export class TreeView extends HeightMap {
private msGesture: MSGesture;
private lastPointerType: string;
private lastClickTimeStamp: number = 0;
private contentWidthProvider?: _.IContentWidthProvider;
private contentWidthUpdateDelayer = new Delayer<void>(50);
private lastRenderTop: number;
private lastRenderHeight: number;
......@@ -460,16 +463,19 @@ 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, {
alwaysConsumeMouseWheel: true,
horizontal: ScrollbarVisibility.Hidden,
horizontal: horizontalScrollMode,
vertical: (typeof context.options.verticalScrollMode !== 'undefined' ? context.options.verticalScrollMode : ScrollbarVisibility.Auto),
useShadows: context.options.useShadows
});
this.scrollableElement.onScroll((e) => {
this.render(e.scrollTop, e.height);
this.render(e.scrollTop, e.height, e.scrollLeft, e.width, e.scrollWidth);
});
if (Browser.isIE) {
......@@ -670,9 +676,14 @@ export class TreeView extends HeightMap {
}
this.viewHeight = height || DOM.getContentHeight(this.wrapper); // render
this.scrollHeight = this.getContentHeight();
if (this.contentWidthProvider) {
this.viewWidth = DOM.getContentWidth(this.wrapper);
}
}
private render(scrollTop: number, viewHeight: number): void {
private render(scrollTop: number, viewHeight: number, scrollLeft: number, viewWidth: number, scrollWidth: number): void {
var i: number;
var stop: number;
......@@ -706,6 +717,11 @@ export class TreeView extends HeightMap {
this.rowsContainer.style.top = (topItem.top - renderTop) + 'px';
}
if (this.contentWidthProvider) {
this.rowsContainer.style.left = -scrollLeft + 'px';
this.rowsContainer.style.width = `${Math.max(scrollWidth, viewWidth)}px`;
}
this.lastRenderTop = renderTop;
this.lastRenderHeight = renderBottom - renderTop;
}
......@@ -746,6 +762,12 @@ export class TreeView extends HeightMap {
}
this.scrollTop = scrollTop;
if (this.contentWidthProvider) {
this.contentWidthUpdateDelayer.trigger(() => {
this.scrollWidth = this.contentWidthProvider.getContentWidth();
});
}
}
public focusNextPage(eventPayload?: any): void {
......@@ -803,11 +825,25 @@ export class TreeView extends HeightMap {
return scrollDimensions.height;
}
public set viewHeight(viewHeight: number) {
this.scrollableElement.setScrollDimensions({
height: viewHeight,
scrollHeight: this.getTotalHeight()
});
public set viewHeight(height: number) {
this.scrollableElement.setScrollDimensions({ height });
}
private set scrollHeight(scrollHeight: number) {
this.scrollableElement.setScrollDimensions({ scrollHeight });
}
public get viewWidth(): number {
const scrollDimensions = this.scrollableElement.getScrollDimensions();
return scrollDimensions.width;
}
public set viewWidth(viewWidth: number) {
this.scrollableElement.setScrollDimensions({ width: viewWidth });
}
private set scrollWidth(scrollWidth: number) {
this.scrollableElement.setScrollDimensions({ scrollWidth });
}
public get scrollTop(): number {
......@@ -817,7 +853,7 @@ export class TreeView extends HeightMap {
public set scrollTop(scrollTop: number) {
this.scrollableElement.setScrollDimensions({
scrollHeight: this.getTotalHeight()
scrollHeight: this.getContentHeight()
});
this.scrollableElement.setScrollPosition({
scrollTop: scrollTop
......@@ -825,12 +861,12 @@ export class TreeView extends HeightMap {
}
public getScrollPosition(): number {
const height = this.getTotalHeight() - this.viewHeight;
const height = this.getContentHeight() - this.viewHeight;
return height <= 0 ? 1 : this.scrollTop / height;
}
public setScrollPosition(pos: number): void {
const height = this.getTotalHeight() - this.viewHeight;
const height = this.getContentHeight() - this.viewHeight;
this.scrollTop = height * pos;
}
......
......@@ -22,7 +22,7 @@ export class HeightMap {
this.indexes = {};
}
public getTotalHeight(): number {
public getContentHeight(): number {
var last = this.heightMap[this.heightMap.length - 1];
return !last ? 0 : last.top + last.height;
}
......
......@@ -416,7 +416,8 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView
accessibilityProvider
}, {
autoExpandSingleChildren: true,
ariaLabel: nls.localize('treeAriaLabel', "Files Explorer")
ariaLabel: nls.localize('treeAriaLabel', "Files Explorer"),
contentWidthProvider: { getContentWidth: () => this.getOptimalWidth() }
});
// Bind context keys
......@@ -459,10 +460,32 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView
}
public getOptimalWidth(): number {
if (!this.explorerViewer) {
return 0;
}
let result = 0;
const parentNode = this.explorerViewer.getHTMLElement();
const childNodes = [].slice.call(parentNode.querySelectorAll('.explorer-item .label-name')); // select all file labels
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);
}
return DOM.getLargestChildWidth(parentNode, childNodes);
return result + 12; // 12 for right padding
}
private onFileOperation(e: FileOperationEvent): void {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册