提交 83c5096f 编写于 作者: A Alex Dima

More clean-up in scrollableElement

上级 28438e23
......@@ -9,8 +9,7 @@ import { toObject, assign } from 'vs/base/common/objects';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Gesture } from 'vs/base/browser/touch';
import * as DOM from 'vs/base/browser/dom';
import { IScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElementImpl';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { RangeMap, IRange } from './rangeMap';
import { IDelegate, IRenderer } from './list';
import { RowCache, IRow } from './rowCache';
......@@ -62,7 +61,7 @@ export class ListView<T> implements IScrollable, IDisposable {
private _domNode: HTMLElement;
private gesture: Gesture;
private rowsContainer: HTMLElement;
private scrollableElement: IScrollableElement;
private scrollableElement: ScrollableElement;
private _onScroll = new Emitter<ScrollEvent>();
private _lastScrollEvent: ScrollEvent;
......
......@@ -8,13 +8,12 @@ import * as Browser from 'vs/base/browser/browser';
import * as Platform from 'vs/base/common/platform';
import * as DomUtils from 'vs/base/browser/dom';
import {IMouseEvent, StandardMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent';
import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger} from 'vs/base/browser/globalMouseMoveMonitor';
import {Widget} from 'vs/base/browser/ui/widget';
import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator';
import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState';
import {ScrollbarArrow, ScrollbarArrowOptions} from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import {ScrollbarVisibilityController} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
import {Visibility, ScrollbarVisibilityController} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
import {DelegateScrollable} from 'vs/base/common/scrollable';
/**
......
......@@ -8,10 +8,11 @@ import * as Browser from 'vs/base/browser/browser';
import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent';
import {IDomNodePosition} from 'vs/base/browser/dom';
import {ScrollableElementResolvedOptions, Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {DelegateScrollable} from 'vs/base/common/scrollable';
import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState';
import {ARROW_IMG_SIZE} from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
export class HorizontalScrollbar extends AbstractScrollbar {
......
......@@ -4,174 +4,410 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
export interface ScrollableElementCreationOptions {
/**
* Prevent the scrollbar rendering from using translate3d. Defaults to false.
*/
forbidTranslate3dUse?: boolean;
/**
* The scrollable element should not do any DOM mutations until renderNow() is called.
* Defaults to false.
*/
lazyRender?: boolean;
/**
* CSS Class name for the scrollable element.
*/
className?: string;
/**
* Drop subtle horizontal and vertical shadows.
* Defaults to false.
*/
useShadows?: boolean;
/**
* Handle mouse wheel (listen to mouse wheel scrolling).
* Defaults to true
*/
handleMouseWheel?: boolean;
/**
* Flip axes. Treat vertical scrolling like horizontal and vice-versa.
* Defaults to false;
*/
flipAxes?: boolean;
/**
* A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
/**
* Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right).
* Defaults to 11.
*/
arrowSize?: number;
/**
* The dom node events should be bound to.
* If no listenOnDomNode is provided, the dom node passed to the constructor will be used for event listening.
*/
listenOnDomNode?: HTMLElement;
/**
* Control the visibility of the horizontal scrollbar.
* Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible)
* Defaults to 'auto'.
*/
horizontal?: string;
/**
* Height (in px) of the horizontal scrollbar.
* Defaults to 10.
*/
horizontalScrollbarSize?: number;
/**
* Height (in px) of the horizontal scrollbar slider.
* Defaults to `horizontalScrollbarSize`
*/
horizontalSliderSize?: number;
/**
* Render arrows (left/right) for the horizontal scrollbar.
* Defaults to false.
*/
horizontalHasArrows?: boolean;
import 'vs/css!./media/scrollbars';
import * as DomUtils from 'vs/base/browser/dom';
import * as Platform from 'vs/base/common/platform';
import {StandardMouseWheelEvent, IMouseEvent} from 'vs/base/browser/mouseEvent';
import {HorizontalScrollbar} from 'vs/base/browser/ui/scrollbar/horizontalScrollbar';
import {VerticalScrollbar} from 'vs/base/browser/ui/scrollbar/verticalScrollbar';
import {ScrollableElementCreationOptions, ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {visibilityFromString} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IScrollable, DelegateScrollable} from 'vs/base/common/scrollable';
import {Widget} from 'vs/base/browser/ui/widget';
import {TimeoutTimer} from 'vs/base/common/async';
import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator';
import {ScrollbarHost} from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
const HIDE_TIMEOUT = 500;
const SCROLL_WHEEL_SENSITIVITY = 50;
export interface IOverviewRulerLayoutInfo {
parent: HTMLElement;
insertBefore: HTMLElement;
}
export interface IDimensions {
width: number;
height: number;
}
export class ScrollableElement extends Widget {
private _options: ScrollableElementResolvedOptions;
private _scrollable: DelegateScrollable;
private _verticalScrollbar: VerticalScrollbar;
private _horizontalScrollbar: HorizontalScrollbar;
private _domNode: HTMLElement;
private _leftShadowDomNode: FastDomNode;
private _topShadowDomNode: FastDomNode;
private _topLeftShadowDomNode: FastDomNode;
private _listenOnDomNode: HTMLElement;
private _mouseWheelToDispose: IDisposable[];
private _onElementDimensionsTimeout: TimeoutTimer;
private _isDragging: boolean;
private _mouseIsOver: boolean;
private _hideTimeout: TimeoutTimer;
private _shouldRender: boolean;
constructor(element: HTMLElement, scrollable:IScrollable, options: ScrollableElementCreationOptions, dimensions: IDimensions = null) {
super();
element.style.overflow = 'hidden';
this._options = resolveOptions(options);
this._scrollable = this._register(new DelegateScrollable(scrollable, () => this._onScroll()));
let scrollbarHost:ScrollbarHost = {
onMouseWheel: (mouseWheelEvent: StandardMouseWheelEvent) => this._onMouseWheel(mouseWheelEvent),
onDragStart: () => this._onDragStart(),
onDragEnd: () => this._onDragEnd(),
};
this._verticalScrollbar = this._register(new VerticalScrollbar(this._scrollable, this._options, scrollbarHost));
this._horizontalScrollbar = this._register(new HorizontalScrollbar(this._scrollable, this._options, scrollbarHost));
this._domNode = document.createElement('div');
this._domNode.className = 'monaco-scrollable-element ' + this._options.className;
this._domNode.setAttribute('role', 'presentation');
this._domNode.style.position = 'relative';
this._domNode.style.overflow = 'hidden';
this._domNode.appendChild(element);
this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode);
this._domNode.appendChild(this._verticalScrollbar.domNode.domNode);
if (this._options.useShadows) {
this._leftShadowDomNode = createFastDomNode(document.createElement('div'));
this._leftShadowDomNode.setClassName('shadow');
this._domNode.appendChild(this._leftShadowDomNode.domNode);
this._topShadowDomNode = createFastDomNode(document.createElement('div'));
this._topShadowDomNode.setClassName('shadow');
this._domNode.appendChild(this._topShadowDomNode.domNode);
this._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner');
this._domNode.appendChild(this._topLeftShadowDomNode.domNode);
}
this._listenOnDomNode = this._options.listenOnDomNode || this._domNode;
this._mouseWheelToDispose = [];
this._setListeningToMouseWheel(this._options.handleMouseWheel);
this.onmouseover(this._listenOnDomNode, (e) => this._onMouseOver(e));
this.onnonbubblingmouseout(this._listenOnDomNode, (e) => this._onMouseOut(e));
this._onElementDimensionsTimeout = this._register(new TimeoutTimer());
this._hideTimeout = this._register(new TimeoutTimer());
this._isDragging = false;
this._mouseIsOver = false;
this.onElementDimensions(dimensions, true);
this._shouldRender = true;
this._shouldRender = this._horizontalScrollbar.onElementScrollSize(this._scrollable.getScrollWidth()) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollSize(this._scrollable.getScrollHeight()) || this._shouldRender;
}
public dispose(): void {
this._mouseWheelToDispose = dispose(this._mouseWheelToDispose);
super.dispose();
}
/**
* Control the visibility of the vertical scrollbar.
* Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible)
* Defaults to 'auto'.
* Get the generated 'scrollable' dom node
*/
vertical?: string;
public getDomNode(): HTMLElement {
return this._domNode;
}
public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo {
return {
parent: this._domNode,
insertBefore: this._verticalScrollbar.domNode.domNode,
};
}
/**
* Width (in px) of the vertical scrollbar.
* Defaults to 10.
* Delegate a mouse down event to the vertical scrollbar.
* This is to help with clicking somewhere else and having the scrollbar react.
*/
verticalScrollbarSize?: number;
public delegateVerticalScrollbarMouseDown(browserEvent: MouseEvent): void {
this._verticalScrollbar.delegateMouseDown(browserEvent);
}
/**
* Width (in px) of the vertical scrollbar slider.
* Defaults to `verticalScrollbarSize`
* Let the scrollable element know that the generated dom node's width / height might have changed.
*/
verticalSliderSize?: number;
public onElementDimensions(dimensions: IDimensions = null, synchronous: boolean = false): void {
if (synchronous) {
this._actualElementDimensions(dimensions);
this._onElementDimensionsTimeout.cancel();
} else {
this._onElementDimensionsTimeout.cancelAndSet(() => this._actualElementDimensions(dimensions), 0);
}
}
private _actualElementDimensions(dimensions: IDimensions = null): void {
if (!dimensions) {
dimensions = {
width: this._domNode.clientWidth,
height: this._domNode.clientHeight
};
}
let width = Math.round(dimensions.width);
let height = Math.round(dimensions.height);
this._shouldRender = this._verticalScrollbar.onElementSize(height) || this._shouldRender;
this._shouldRender = this._horizontalScrollbar.onElementSize(width) || this._shouldRender;
}
/**
* Render arrows (top/bottom) for the vertical scrollbar.
* Defaults to false.
* Update the class name of the scrollable element.
*/
verticalHasArrows?: boolean;
public updateClassName(newClassName: string): void {
this._options.className = newClassName;
// Defaults are different on Macs
if (Platform.isMacintosh) {
this._options.className += ' mac';
}
this._domNode.className = 'monaco-scrollable-element ' + this._options.className;
}
/**
* Add a `last-scroll-time` attribute to scroll targets or parents of scroll targets matching the following class name
* Update configuration options for the scrollbar.
* Really this is Editor.IEditorScrollbarOptions, but base shouldn't
* depend on Editor.
*/
saveLastScrollTimeOnClassName?: string;
}
public updateOptions(newOptions: ScrollableElementCreationOptions): void {
// only support handleMouseWheel changes for now
let massagedOptions = resolveOptions(newOptions);
this._options.handleMouseWheel = massagedOptions.handleMouseWheel;
this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity;
this._setListeningToMouseWheel(this._options.handleMouseWheel);
}
export interface ScrollableElementResolvedOptions {
forbidTranslate3dUse: boolean;
lazyRender: boolean;
className: string;
useShadows: boolean;
handleMouseWheel: boolean;
flipAxes: boolean;
mouseWheelScrollSensitivity: number;
arrowSize: number;
listenOnDomNode: HTMLElement;
horizontal: Visibility;
horizontalScrollbarSize: number;
horizontalSliderSize: number;
horizontalHasArrows: boolean;
vertical: Visibility;
verticalScrollbarSize: number;
verticalSliderSize: number;
verticalHasArrows: boolean;
saveLastScrollTimeOnClassName: string;
}
// -------------------- mouse wheel scrolling --------------------
export interface IOverviewRulerLayoutInfo {
parent: HTMLElement;
insertBefore: HTMLElement;
}
private _setListeningToMouseWheel(shouldListen: boolean): void {
let isListening = (this._mouseWheelToDispose.length > 0);
export interface IDimensions {
width: number;
height: number;
}
if (isListening === shouldListen) {
// No change
return;
}
// Stop listening (if necessary)
this._mouseWheelToDispose = dispose(this._mouseWheelToDispose);
// Start listening (if necessary)
if (shouldListen) {
let onMouseWheel = (browserEvent: MouseWheelEvent) => {
let e = new StandardMouseWheelEvent(browserEvent);
this._onMouseWheel(e);
};
this._mouseWheelToDispose.push(DomUtils.addDisposableListener(this._listenOnDomNode, 'mousewheel', onMouseWheel));
this._mouseWheelToDispose.push(DomUtils.addDisposableListener(this._listenOnDomNode, 'DOMMouseScroll', onMouseWheel));
}
}
private _onMouseWheel(e: StandardMouseWheelEvent): void {
if (Platform.isMacintosh && e.browserEvent && this._options.saveLastScrollTimeOnClassName) {
// Mark dom node with timestamp of wheel event
let target = <HTMLElement>e.browserEvent.target;
if (target && target.nodeType === 1) {
let r = DomUtils.findParentWithClass(target, this._options.saveLastScrollTimeOnClassName);
if (r) {
r.setAttribute('last-scroll-time', String(new Date().getTime()));
}
}
}
let desiredScrollTop = -1;
let desiredScrollLeft = -1;
/**
* An Element that uses fancy scrollbars.
*/
export interface IScrollableElement {
if (e.deltaY || e.deltaX) {
let deltaY = e.deltaY * this._options.mouseWheelScrollSensitivity;
let deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity;
if (this._options.flipAxes) {
deltaY = e.deltaX;
deltaX = e.deltaY;
}
getDomNode(): HTMLElement;
if (Platform.isMacintosh) {
// Give preference to vertical scrolling
if (deltaY && Math.abs(deltaX) < 0.2) {
deltaX = 0;
}
if (Math.abs(deltaY) > Math.abs(deltaX) * 0.5) {
deltaX = 0;
}
}
if (deltaY) {
let currentScrollTop = this._scrollable.getScrollTop();
desiredScrollTop = this._verticalScrollbar.validateScrollPosition((desiredScrollTop !== -1 ? desiredScrollTop : currentScrollTop) - SCROLL_WHEEL_SENSITIVITY * deltaY);
if (desiredScrollTop === currentScrollTop) {
desiredScrollTop = -1;
}
}
if (deltaX) {
let currentScrollLeft = this._scrollable.getScrollLeft();
desiredScrollLeft = this._horizontalScrollbar.validateScrollPosition((desiredScrollLeft !== -1 ? desiredScrollLeft : currentScrollLeft) - SCROLL_WHEEL_SENSITIVITY * deltaX);
if (desiredScrollLeft === currentScrollLeft) {
desiredScrollLeft = -1;
}
}
onElementDimensions(dimensions?: IDimensions): void;
if (desiredScrollTop !== -1 || desiredScrollLeft !== -1) {
if (desiredScrollTop !== -1) {
this._shouldRender = this._verticalScrollbar.setDesiredScrollPosition(desiredScrollTop) || this._shouldRender;
desiredScrollTop = -1;
}
if (desiredScrollLeft !== -1) {
this._shouldRender = this._horizontalScrollbar.setDesiredScrollPosition(desiredScrollLeft) || this._shouldRender;
desiredScrollLeft = -1;
}
}
}
e.preventDefault();
e.stopPropagation();
}
private _onScroll(): void {
let scrollHeight = this._scrollable.getScrollHeight();
let scrollTop = this._scrollable.getScrollTop();
let scrollWidth = this._scrollable.getScrollWidth();
let scrollLeft = this._scrollable.getScrollLeft();
this._shouldRender = this._horizontalScrollbar.onElementScrollSize(scrollWidth) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollSize(scrollHeight) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollPosition(scrollTop) || this._shouldRender;
this._shouldRender = this._horizontalScrollbar.onElementScrollPosition(scrollLeft) || this._shouldRender;
if (this._options.useShadows) {
this._shouldRender = true;
}
this._reveal();
if (!this._options.lazyRender) {
this._render();
}
}
/**
* Dispose.
* Render / mutate the DOM now.
* Should be used together with the ctor option `lazyRender`.
*/
dispose(): void;
public renderNow(): void {
if (!this._options.lazyRender) {
throw new Error('Please use `lazyRender` together with `renderNow`!');
}
this._render();
}
renderNow(): void;
private _render(): void {
if (!this._shouldRender) {
return;
}
this._shouldRender = false;
updateClassName(newClassName: string): void;
this._horizontalScrollbar.render();
this._verticalScrollbar.render();
if (this._options.useShadows) {
let enableTop = this._scrollable.getScrollTop() > 0;
let enableLeft = this._scrollable.getScrollLeft() > 0;
updateOptions(newOptions: ScrollableElementCreationOptions): void;
this._leftShadowDomNode.setClassName('shadow' + (enableLeft ? ' left' : ''));
this._topShadowDomNode.setClassName('shadow' + (enableTop ? ' top' : ''));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
}
}
getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo;
// -------------------- fade in / fade out --------------------
private _onDragStart(): void {
this._isDragging = true;
this._reveal();
}
delegateVerticalScrollbarMouseDown(browserEvent: MouseEvent): void;
}
private _onDragEnd(): void {
this._isDragging = false;
this._hide();
}
export enum Visibility {
Auto,
Hidden,
Visible
}
private _onMouseOut(e: IMouseEvent): void {
this._mouseIsOver = false;
this._hide();
}
export function visibilityFromString(visibility: string): Visibility {
switch (visibility) {
case 'hidden':
return Visibility.Hidden;
case 'visible':
return Visibility.Visible;
default:
return Visibility.Auto;
private _onMouseOver(e: IMouseEvent): void {
this._mouseIsOver = true;
this._reveal();
}
private _reveal(): void {
this._verticalScrollbar.beginReveal();
this._horizontalScrollbar.beginReveal();
this._scheduleHide();
}
private _hide(): void {
if (!this._mouseIsOver && !this._isDragging) {
this._verticalScrollbar.beginHide();
this._horizontalScrollbar.beginHide();
}
}
private _scheduleHide(): void {
this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT);
}
}
function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableElementResolvedOptions {
let result: ScrollableElementResolvedOptions = {
forbidTranslate3dUse: (typeof opts.forbidTranslate3dUse !== 'undefined' ? opts.forbidTranslate3dUse : false),
lazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false),
className: (typeof opts.className !== 'undefined' ? opts.className : ''),
useShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true),
handleMouseWheel: (typeof opts.handleMouseWheel !== 'undefined' ? opts.handleMouseWheel : true),
flipAxes: (typeof opts.flipAxes !== 'undefined' ? opts.flipAxes : false),
mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1),
arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11),
listenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null),
horizontal: visibilityFromString(typeof opts.horizontal !== 'undefined' ? opts.horizontal : 'auto'),
horizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10),
horizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0),
horizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false),
vertical: visibilityFromString(typeof opts.vertical !== 'undefined' ? opts.vertical : 'auto'),
verticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10),
verticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false),
verticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0),
saveLastScrollTimeOnClassName: (typeof opts.saveLastScrollTimeOnClassName !== 'undefined' ? opts.saveLastScrollTimeOnClassName : null)
};
result.horizontalSliderSize = (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : result.horizontalScrollbarSize);
result.verticalSliderSize = (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : result.verticalScrollbarSize);
// Defaults are different on Macs
if (Platform.isMacintosh) {
result.className += ' mac';
}
return result;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/scrollbars';
import * as DomUtils from 'vs/base/browser/dom';
import * as Platform from 'vs/base/common/platform';
import {StandardMouseWheelEvent, IMouseEvent} from 'vs/base/browser/mouseEvent';
import {HorizontalScrollbar} from 'vs/base/browser/ui/scrollbar/horizontalScrollbar';
import {VerticalScrollbar} from 'vs/base/browser/ui/scrollbar/verticalScrollbar';
import {
ScrollableElementResolvedOptions, IDimensions, visibilityFromString,
IScrollableElement, ScrollableElementCreationOptions, IOverviewRulerLayoutInfo
} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {IScrollable, DelegateScrollable} from 'vs/base/common/scrollable';
import {Widget} from 'vs/base/browser/ui/widget';
import {TimeoutTimer} from 'vs/base/common/async';
import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator';
import {ScrollbarHost} from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
const HIDE_TIMEOUT = 500;
const SCROLL_WHEEL_SENSITIVITY = 50;
export class ScrollableElement extends Widget implements IScrollableElement {
private _options: ScrollableElementResolvedOptions;
private _scrollable: DelegateScrollable;
private _verticalScrollbar: VerticalScrollbar;
private _horizontalScrollbar: HorizontalScrollbar;
private _domNode: HTMLElement;
private _leftShadowDomNode: FastDomNode;
private _topShadowDomNode: FastDomNode;
private _topLeftShadowDomNode: FastDomNode;
private _listenOnDomNode: HTMLElement;
private _mouseWheelToDispose: IDisposable[];
private _onElementDimensionsTimeout: TimeoutTimer;
private _isDragging: boolean;
private _mouseIsOver: boolean;
private _hideTimeout: TimeoutTimer;
private _shouldRender: boolean;
constructor(element: HTMLElement, scrollable:IScrollable, options: ScrollableElementCreationOptions, dimensions: IDimensions = null) {
super();
element.style.overflow = 'hidden';
this._options = resolveOptions(options);
this._scrollable = this._register(new DelegateScrollable(scrollable, () => this._onScroll()));
let scrollbarHost:ScrollbarHost = {
onMouseWheel: (mouseWheelEvent: StandardMouseWheelEvent) => this._onMouseWheel(mouseWheelEvent),
onDragStart: () => this._onDragStart(),
onDragEnd: () => this._onDragEnd(),
};
this._verticalScrollbar = this._register(new VerticalScrollbar(this._scrollable, this._options, scrollbarHost));
this._horizontalScrollbar = this._register(new HorizontalScrollbar(this._scrollable, this._options, scrollbarHost));
this._domNode = document.createElement('div');
this._domNode.className = 'monaco-scrollable-element ' + this._options.className;
this._domNode.setAttribute('role', 'presentation');
this._domNode.style.position = 'relative';
this._domNode.style.overflow = 'hidden';
this._domNode.appendChild(element);
this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode);
this._domNode.appendChild(this._verticalScrollbar.domNode.domNode);
if (this._options.useShadows) {
this._leftShadowDomNode = createFastDomNode(document.createElement('div'));
this._leftShadowDomNode.setClassName('shadow');
this._domNode.appendChild(this._leftShadowDomNode.domNode);
this._topShadowDomNode = createFastDomNode(document.createElement('div'));
this._topShadowDomNode.setClassName('shadow');
this._domNode.appendChild(this._topShadowDomNode.domNode);
this._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner');
this._domNode.appendChild(this._topLeftShadowDomNode.domNode);
}
this._listenOnDomNode = this._options.listenOnDomNode || this._domNode;
this._mouseWheelToDispose = [];
this._setListeningToMouseWheel(this._options.handleMouseWheel);
this.onmouseover(this._listenOnDomNode, (e) => this._onMouseOver(e));
this.onnonbubblingmouseout(this._listenOnDomNode, (e) => this._onMouseOut(e));
this._onElementDimensionsTimeout = this._register(new TimeoutTimer());
this._hideTimeout = this._register(new TimeoutTimer());
this._isDragging = false;
this._mouseIsOver = false;
this.onElementDimensions(dimensions, true);
this._shouldRender = true;
this._shouldRender = this._horizontalScrollbar.onElementScrollSize(this._scrollable.getScrollWidth()) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollSize(this._scrollable.getScrollHeight()) || this._shouldRender;
}
public dispose(): void {
this._mouseWheelToDispose = dispose(this._mouseWheelToDispose);
super.dispose();
}
/**
* Get the generated 'scrollable' dom node
*/
public getDomNode(): HTMLElement {
return this._domNode;
}
public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo {
return {
parent: this._domNode,
insertBefore: this._verticalScrollbar.domNode.domNode,
};
}
/**
* Delegate a mouse down event to the vertical scrollbar.
* This is to help with clicking somewhere else and having the scrollbar react.
*/
public delegateVerticalScrollbarMouseDown(browserEvent: MouseEvent): void {
this._verticalScrollbar.delegateMouseDown(browserEvent);
}
/**
* Let the scrollable element know that the generated dom node's width / height might have changed.
*/
public onElementDimensions(dimensions: IDimensions = null, synchronous: boolean = false): void {
if (synchronous) {
this._actualElementDimensions(dimensions);
this._onElementDimensionsTimeout.cancel();
} else {
this._onElementDimensionsTimeout.cancelAndSet(() => this._actualElementDimensions(dimensions), 0);
}
}
private _actualElementDimensions(dimensions: IDimensions = null): void {
if (!dimensions) {
dimensions = {
width: this._domNode.clientWidth,
height: this._domNode.clientHeight
};
}
let width = Math.round(dimensions.width);
let height = Math.round(dimensions.height);
this._shouldRender = this._verticalScrollbar.onElementSize(height) || this._shouldRender;
this._shouldRender = this._horizontalScrollbar.onElementSize(width) || this._shouldRender;
}
/**
* Update the class name of the scrollable element.
*/
public updateClassName(newClassName: string): void {
this._options.className = newClassName;
// Defaults are different on Macs
if (Platform.isMacintosh) {
this._options.className += ' mac';
}
this._domNode.className = 'monaco-scrollable-element ' + this._options.className;
}
/**
* Update configuration options for the scrollbar.
* Really this is Editor.IEditorScrollbarOptions, but base shouldn't
* depend on Editor.
*/
public updateOptions(newOptions: ScrollableElementCreationOptions): void {
// only support handleMouseWheel changes for now
let massagedOptions = resolveOptions(newOptions);
this._options.handleMouseWheel = massagedOptions.handleMouseWheel;
this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity;
this._setListeningToMouseWheel(this._options.handleMouseWheel);
}
// -------------------- mouse wheel scrolling --------------------
private _setListeningToMouseWheel(shouldListen: boolean): void {
let isListening = (this._mouseWheelToDispose.length > 0);
if (isListening === shouldListen) {
// No change
return;
}
// Stop listening (if necessary)
this._mouseWheelToDispose = dispose(this._mouseWheelToDispose);
// Start listening (if necessary)
if (shouldListen) {
let onMouseWheel = (browserEvent: MouseWheelEvent) => {
let e = new StandardMouseWheelEvent(browserEvent);
this._onMouseWheel(e);
};
this._mouseWheelToDispose.push(DomUtils.addDisposableListener(this._listenOnDomNode, 'mousewheel', onMouseWheel));
this._mouseWheelToDispose.push(DomUtils.addDisposableListener(this._listenOnDomNode, 'DOMMouseScroll', onMouseWheel));
}
}
private _onMouseWheel(e: StandardMouseWheelEvent): void {
if (Platform.isMacintosh && e.browserEvent && this._options.saveLastScrollTimeOnClassName) {
// Mark dom node with timestamp of wheel event
let target = <HTMLElement>e.browserEvent.target;
if (target && target.nodeType === 1) {
let r = DomUtils.findParentWithClass(target, this._options.saveLastScrollTimeOnClassName);
if (r) {
r.setAttribute('last-scroll-time', String(new Date().getTime()));
}
}
}
let desiredScrollTop = -1;
let desiredScrollLeft = -1;
if (e.deltaY || e.deltaX) {
let deltaY = e.deltaY * this._options.mouseWheelScrollSensitivity;
let deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity;
if (this._options.flipAxes) {
deltaY = e.deltaX;
deltaX = e.deltaY;
}
if (Platform.isMacintosh) {
// Give preference to vertical scrolling
if (deltaY && Math.abs(deltaX) < 0.2) {
deltaX = 0;
}
if (Math.abs(deltaY) > Math.abs(deltaX) * 0.5) {
deltaX = 0;
}
}
if (deltaY) {
let currentScrollTop = this._scrollable.getScrollTop();
desiredScrollTop = this._verticalScrollbar.validateScrollPosition((desiredScrollTop !== -1 ? desiredScrollTop : currentScrollTop) - SCROLL_WHEEL_SENSITIVITY * deltaY);
if (desiredScrollTop === currentScrollTop) {
desiredScrollTop = -1;
}
}
if (deltaX) {
let currentScrollLeft = this._scrollable.getScrollLeft();
desiredScrollLeft = this._horizontalScrollbar.validateScrollPosition((desiredScrollLeft !== -1 ? desiredScrollLeft : currentScrollLeft) - SCROLL_WHEEL_SENSITIVITY * deltaX);
if (desiredScrollLeft === currentScrollLeft) {
desiredScrollLeft = -1;
}
}
if (desiredScrollTop !== -1 || desiredScrollLeft !== -1) {
if (desiredScrollTop !== -1) {
this._shouldRender = this._verticalScrollbar.setDesiredScrollPosition(desiredScrollTop) || this._shouldRender;
desiredScrollTop = -1;
}
if (desiredScrollLeft !== -1) {
this._shouldRender = this._horizontalScrollbar.setDesiredScrollPosition(desiredScrollLeft) || this._shouldRender;
desiredScrollLeft = -1;
}
}
}
e.preventDefault();
e.stopPropagation();
}
private _onScroll(): void {
let scrollHeight = this._scrollable.getScrollHeight();
let scrollTop = this._scrollable.getScrollTop();
let scrollWidth = this._scrollable.getScrollWidth();
let scrollLeft = this._scrollable.getScrollLeft();
this._shouldRender = this._horizontalScrollbar.onElementScrollSize(scrollWidth) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollSize(scrollHeight) || this._shouldRender;
this._shouldRender = this._verticalScrollbar.onElementScrollPosition(scrollTop) || this._shouldRender;
this._shouldRender = this._horizontalScrollbar.onElementScrollPosition(scrollLeft) || this._shouldRender;
if (this._options.useShadows) {
this._shouldRender = true;
}
this._reveal();
if (!this._options.lazyRender) {
this._render();
}
}
/**
* Render / mutate the DOM now.
* Should be used together with the ctor option `lazyRender`.
*/
public renderNow(): void {
if (!this._options.lazyRender) {
throw new Error('Please use `lazyRender` together with `renderNow`!');
}
this._render();
}
private _render(): void {
if (!this._shouldRender) {
return;
}
this._shouldRender = false;
this._horizontalScrollbar.render();
this._verticalScrollbar.render();
if (this._options.useShadows) {
let enableTop = this._scrollable.getScrollTop() > 0;
let enableLeft = this._scrollable.getScrollLeft() > 0;
this._leftShadowDomNode.setClassName('shadow' + (enableLeft ? ' left' : ''));
this._topShadowDomNode.setClassName('shadow' + (enableTop ? ' top' : ''));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
}
}
// -------------------- fade in / fade out --------------------
private _onDragStart(): void {
this._isDragging = true;
this._reveal();
}
private _onDragEnd(): void {
this._isDragging = false;
this._hide();
}
private _onMouseOut(e: IMouseEvent): void {
this._mouseIsOver = false;
this._hide();
}
private _onMouseOver(e: IMouseEvent): void {
this._mouseIsOver = true;
this._reveal();
}
private _reveal(): void {
this._verticalScrollbar.beginReveal();
this._horizontalScrollbar.beginReveal();
this._scheduleHide();
}
private _hide(): void {
if (!this._mouseIsOver && !this._isDragging) {
this._verticalScrollbar.beginHide();
this._horizontalScrollbar.beginHide();
}
}
private _scheduleHide(): void {
this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT);
}
}
function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableElementResolvedOptions {
let result: ScrollableElementResolvedOptions = {
forbidTranslate3dUse: (typeof opts.forbidTranslate3dUse !== 'undefined' ? opts.forbidTranslate3dUse : false),
lazyRender: (typeof opts.lazyRender !== 'undefined' ? opts.lazyRender : false),
className: (typeof opts.className !== 'undefined' ? opts.className : ''),
useShadows: (typeof opts.useShadows !== 'undefined' ? opts.useShadows : true),
handleMouseWheel: (typeof opts.handleMouseWheel !== 'undefined' ? opts.handleMouseWheel : true),
flipAxes: (typeof opts.flipAxes !== 'undefined' ? opts.flipAxes : false),
mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1),
arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11),
listenOnDomNode: (typeof opts.listenOnDomNode !== 'undefined' ? opts.listenOnDomNode : null),
horizontal: visibilityFromString(typeof opts.horizontal !== 'undefined' ? opts.horizontal : 'auto'),
horizontalScrollbarSize: (typeof opts.horizontalScrollbarSize !== 'undefined' ? opts.horizontalScrollbarSize : 10),
horizontalSliderSize: (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : 0),
horizontalHasArrows: (typeof opts.horizontalHasArrows !== 'undefined' ? opts.horizontalHasArrows : false),
vertical: visibilityFromString(typeof opts.vertical !== 'undefined' ? opts.vertical : 'auto'),
verticalScrollbarSize: (typeof opts.verticalScrollbarSize !== 'undefined' ? opts.verticalScrollbarSize : 10),
verticalHasArrows: (typeof opts.verticalHasArrows !== 'undefined' ? opts.verticalHasArrows : false),
verticalSliderSize: (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : 0),
saveLastScrollTimeOnClassName: (typeof opts.saveLastScrollTimeOnClassName !== 'undefined' ? opts.saveLastScrollTimeOnClassName : null)
};
result.horizontalSliderSize = (typeof opts.horizontalSliderSize !== 'undefined' ? opts.horizontalSliderSize : result.horizontalScrollbarSize);
result.verticalSliderSize = (typeof opts.verticalSliderSize !== 'undefined' ? opts.verticalSliderSize : result.verticalScrollbarSize);
// Defaults are different on Macs
if (Platform.isMacintosh) {
result.className += ' mac';
}
return result;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
export interface ScrollableElementCreationOptions {
/**
* Prevent the scrollbar rendering from using translate3d. Defaults to false.
*/
forbidTranslate3dUse?: boolean;
/**
* The scrollable element should not do any DOM mutations until renderNow() is called.
* Defaults to false.
*/
lazyRender?: boolean;
/**
* CSS Class name for the scrollable element.
*/
className?: string;
/**
* Drop subtle horizontal and vertical shadows.
* Defaults to false.
*/
useShadows?: boolean;
/**
* Handle mouse wheel (listen to mouse wheel scrolling).
* Defaults to true
*/
handleMouseWheel?: boolean;
/**
* Flip axes. Treat vertical scrolling like horizontal and vice-versa.
* Defaults to false;
*/
flipAxes?: boolean;
/**
* A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
/**
* Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right).
* Defaults to 11.
*/
arrowSize?: number;
/**
* The dom node events should be bound to.
* If no listenOnDomNode is provided, the dom node passed to the constructor will be used for event listening.
*/
listenOnDomNode?: HTMLElement;
/**
* Control the visibility of the horizontal scrollbar.
* Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible)
* Defaults to 'auto'.
*/
horizontal?: string;
/**
* Height (in px) of the horizontal scrollbar.
* Defaults to 10.
*/
horizontalScrollbarSize?: number;
/**
* Height (in px) of the horizontal scrollbar slider.
* Defaults to `horizontalScrollbarSize`
*/
horizontalSliderSize?: number;
/**
* Render arrows (left/right) for the horizontal scrollbar.
* Defaults to false.
*/
horizontalHasArrows?: boolean;
/**
* Control the visibility of the vertical scrollbar.
* Accepted values: 'auto' (on mouse over), 'visible' (always visible), 'hidden' (never visible)
* Defaults to 'auto'.
*/
vertical?: string;
/**
* Width (in px) of the vertical scrollbar.
* Defaults to 10.
*/
verticalScrollbarSize?: number;
/**
* Width (in px) of the vertical scrollbar slider.
* Defaults to `verticalScrollbarSize`
*/
verticalSliderSize?: number;
/**
* Render arrows (top/bottom) for the vertical scrollbar.
* Defaults to false.
*/
verticalHasArrows?: boolean;
/**
* Add a `last-scroll-time` attribute to scroll targets or parents of scroll targets matching the following class name
*/
saveLastScrollTimeOnClassName?: string;
}
export interface ScrollableElementResolvedOptions {
forbidTranslate3dUse: boolean;
lazyRender: boolean;
className: string;
useShadows: boolean;
handleMouseWheel: boolean;
flipAxes: boolean;
mouseWheelScrollSensitivity: number;
arrowSize: number;
listenOnDomNode: HTMLElement;
horizontal: Visibility;
horizontalScrollbarSize: number;
horizontalSliderSize: number;
horizontalHasArrows: boolean;
vertical: Visibility;
verticalScrollbarSize: number;
verticalSliderSize: number;
verticalHasArrows: boolean;
saveLastScrollTimeOnClassName: string;
}
......@@ -4,11 +4,27 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {Disposable} from 'vs/base/common/lifecycle';
import {TimeoutTimer} from 'vs/base/common/async';
import {FastDomNode} from 'vs/base/browser/styleMutator';
export enum Visibility {
Auto,
Hidden,
Visible
}
export function visibilityFromString(visibility: string): Visibility {
switch (visibility) {
case 'hidden':
return Visibility.Hidden;
case 'visible':
return Visibility.Visible;
default:
return Visibility.Auto;
}
}
export class ScrollbarVisibilityController extends Disposable {
private _visibility: Visibility;
private _visibleClassName: string;
......
......@@ -8,10 +8,11 @@ import * as Browser from 'vs/base/browser/browser';
import {AbstractScrollbar, ScrollbarHost, IMouseMoveEventData} from 'vs/base/browser/ui/scrollbar/abstractScrollbar';
import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent';
import {IDomNodePosition} from 'vs/base/browser/dom';
import {ScrollableElementResolvedOptions, Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollableElementResolvedOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {DelegateScrollable} from 'vs/base/common/scrollable';
import {ScrollbarState} from 'vs/base/browser/ui/scrollbar/scrollbarState';
import {ARROW_IMG_SIZE} from 'vs/base/browser/ui/scrollbar/scrollbarArrow';
import {Visibility} from 'vs/base/browser/ui/scrollbar/scrollbarVisibilityController';
export class VerticalScrollbar extends AbstractScrollbar {
......
......@@ -17,8 +17,7 @@ import Keyboard = require('vs/base/browser/keyboardEvent');
import Model = require('vs/base/parts/tree/browser/treeModel');
import dnd = require('./treeDnd');
import { ArrayIterator, MappedIterator } from 'vs/base/common/iterator';
import Scroll = require('vs/base/browser/ui/scrollbar/scrollableElement');
import ScrollableElementImpl = require('vs/base/browser/ui/scrollbar/scrollableElementImpl');
import ScrollableElementImpl = require('vs/base/browser/ui/scrollbar/scrollableElement');
import { HeightMap } from 'vs/base/parts/tree/browser/treeViewModel';
import _ = require('vs/base/parts/tree/browser/tree');
import { IViewItem } from 'vs/base/parts/tree/browser/treeViewModel';
......@@ -409,7 +408,7 @@ export class TreeView extends HeightMap implements IScrollable {
private domNode: HTMLElement;
private wrapper: HTMLElement;
private rowsContainer: HTMLElement;
private scrollableElement: Scroll.IScrollableElement;
private scrollableElement: ScrollableElementImpl.ScrollableElement;
private wrapperGesture: Touch.Gesture;
private msGesture: MSGesture;
private lastPointerType:string;
......
......@@ -6,8 +6,8 @@
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import {IOverviewRulerLayoutInfo, IScrollableElement, ScrollableElementCreationOptions} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl';
import {ScrollableElementCreationOptions} from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import {IOverviewRulerLayoutInfo, ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {EventType, IConfiguration, IConfigurationChangedEvent, IScrollEvent, IViewEventBus} from 'vs/editor/common/editorCommon';
import {EditorScrollable} from 'vs/editor/common/viewLayout/editorScrollable';
import {ClassNames} from 'vs/editor/browser/editorBrowser';
......@@ -26,7 +26,7 @@ export class ScrollManager implements IDisposable {
private toDispose:IDisposable[];
private scrollable: EditorScrollable;
private linesContent: HTMLElement;
private scrollbar: IScrollableElement;
private scrollbar: ScrollableElement;
constructor(scrollable:EditorScrollable, configuration:IConfiguration, privateViewEventBus:IViewEventBus, linesContent:HTMLElement, viewDomNode:HTMLElement, overflowGuardDomNode:HTMLElement) {
this.toDispose = [];
......
......@@ -17,7 +17,7 @@ import {addClass, append, emmet as $, hide, removeClass, show, toggleClass} from
import {HighlightedLabel} from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import {IDelegate, IFocusChangeEvent, IRenderer, ISelectionChangeEvent} from 'vs/base/browser/ui/list/list';
import {List} from 'vs/base/browser/ui/list/listWidget';
import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl';
import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {IKeybindingContextKey, IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
......
......@@ -12,8 +12,7 @@ import URI from 'vs/base/common/uri';
import {Sash, ISashEvent, IVerticalSashLayoutProvider} from 'vs/base/browser/ui/sash/sash';
import {Dimension, Builder, $} from 'vs/base/browser/builder';
import {ResourceViewer} from 'vs/base/browser/ui/resourceviewer/resourceViewer';
import {IScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElementImpl';
import {ScrollableElement} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {BaseEditor} from 'vs/workbench/browser/parts/editor/baseEditor';
import {EditorInput, EditorOptions} from 'vs/workbench/common/editor';
import {BinaryEditorModel} from 'vs/workbench/common/editor/binaryEditorModel';
......@@ -33,10 +32,10 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas
private leftBinaryContainer: Builder;
private leftScrollable: DomNodeScrollable;
private leftScrollbar: IScrollableElement;
private leftScrollbar: ScrollableElement;
private rightBinaryContainer: Builder;
private rightScrollable: DomNodeScrollable;
private rightScrollbar: IScrollableElement;
private rightScrollbar: ScrollableElement;
private sash: Sash;
private dimension: Dimension;
private leftContainerWidth: number;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册