提交 cf86c78b 编写于 作者: A Alex Dima

Use FastDomNode for scrollbars

上级 bc6d7655
......@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
export abstract class FastDomNode {
private _domNode: HTMLElement;
......@@ -16,7 +18,9 @@ export abstract class FastDomNode {
private _right: number;
private _fontSize: number;
private _lineHeight: number;
private _className: string;
private _display: string;
private _position: string;
private _visibility: string;
private _transform: string;
private _lineNumber: string;
......@@ -36,7 +40,9 @@ export abstract class FastDomNode {
this._right = -1;
this._fontSize = -1;
this._lineHeight = -1;
this._className = '';
this._display = '';
this._position = '';
this._visibility = '';
this._transform = '';
this._lineNumber = '';
......@@ -114,6 +120,19 @@ export abstract class FastDomNode {
this._domNode.style.lineHeight = this._lineHeight + 'px';
}
public setClassName(className: string): void {
if (this._className === className) {
return;
}
this._className = className;
this._domNode.className = this._className;
}
public toggleClassName(className: string, shouldHaveIt?: boolean): void {
dom.toggleClass(this._domNode, className, shouldHaveIt);
this._className = this._domNode.className;
}
public setDisplay(display: string): void {
if (this._display === display) {
return;
......@@ -122,6 +141,14 @@ export abstract class FastDomNode {
this._domNode.style.display = this._display;
}
public setPosition(position: string): void {
if (this._position === position) {
return;
}
this._position = position;
this._domNode.style.position = this._position;
}
public setVisibility(visibility: string): void {
if (this._visibility === visibility) {
return;
......
......@@ -13,6 +13,7 @@ import {Disposable} from 'vs/base/common/lifecycle';
import {GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger} from 'vs/base/browser/globalMouseMoveMonitor';
import {Widget} from 'vs/base/browser/ui/widget';
import {TimeoutTimer, IntervalTimer} from 'vs/base/common/async';
import {FastDomNode, createFastDomNode} from 'vs/base/browser/styleMutator';
/**
* The arrow image size.
......@@ -72,16 +73,26 @@ export class ScrollbarState {
private _computedSliderPosition: number;
constructor(arrowSize: number, scrollbarSize: number, oppositeScrollbarSize: number) {
this._scrollbarSize = Math.round(scrollbarSize);
this._oppositeScrollbarSize = Math.round(oppositeScrollbarSize);
this._arrowSize = Math.round(arrowSize);
this._visibleSize = 0;
this._scrollSize = 0;
this._scrollPosition = 0;
this._scrollbarSize = scrollbarSize;
this._oppositeScrollbarSize = oppositeScrollbarSize;
this._arrowSize = arrowSize;
this._computedAvailableSize = 0;
this._computedRepresentableSize = 0;
this._computedRatio = 0;
this._computedIsNeeded = false;
this._computedSliderSize = 0;
this._computedSliderPosition = 0;
this._refreshComputedValues();
}
public setVisibleSize(visibleSize: number): boolean {
visibleSize = Math.round(visibleSize);
if (this._visibleSize !== visibleSize) {
this._visibleSize = visibleSize;
this._refreshComputedValues();
......@@ -91,6 +102,7 @@ export class ScrollbarState {
}
public setScrollSize(scrollSize: number): boolean {
scrollSize = Math.round(scrollSize);
if (this._scrollSize !== scrollSize) {
this._scrollSize = scrollSize;
this._refreshComputedValues();
......@@ -100,6 +112,7 @@ export class ScrollbarState {
}
public setScrollPosition(scrollPosition: number): boolean {
scrollPosition = Math.round(scrollPosition);
if (this._scrollPosition !== scrollPosition) {
this._scrollPosition = scrollPosition;
this._refreshComputedValues();
......@@ -247,7 +260,7 @@ class VisibilityController extends Disposable {
private _visibility: Visibility;
private _visibleClassName: string;
private _invisibleClassName: string;
private _domNode: HTMLElement;
private _domNode: FastDomNode;
private _shouldBeVisible: boolean;
private _isNeeded: boolean;
private _isVisible: boolean;
......@@ -293,9 +306,9 @@ class VisibilityController extends Disposable {
}
}
public setDomNode(domNode: HTMLElement): void {
public setDomNode(domNode: FastDomNode): void {
this._domNode = domNode;
this._domNode.className = this._invisibleClassName;
this._domNode.setClassName(this._invisibleClassName);
// Now that the flags & the dom node are in a consistent state, ensure the Hidden/Visible configuration
this.setShouldBeVisible(false);
......@@ -325,7 +338,7 @@ class VisibilityController extends Disposable {
// The CSS animation doesn't play otherwise
this._revealTimer.setIfNotSet(() => {
this._domNode.className = this._visibleClassName;
this._domNode.setClassName(this._visibleClassName);
}, 0);
}
......@@ -335,7 +348,7 @@ class VisibilityController extends Disposable {
return;
}
this._isVisible = false;
this._domNode.className = this._invisibleClassName + (withFadeAway ? ' fade' : '');
this._domNode.setClassName(this._invisibleClassName + (withFadeAway ? ' fade' : ''));
}
}
......@@ -353,8 +366,8 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
private _visibilityController: VisibilityController;
private _mouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
public domNode: HTMLElement;
public slider: HTMLElement;
public domNode: FastDomNode;
public slider: FastDomNode;
constructor(forbidTranslate3dUse: boolean, parent: IParent, scrollbarState: ScrollbarState, visibility: Visibility, extraScrollbarClassName: string) {
super();
......@@ -371,16 +384,16 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
* Creates the container dom node for the scrollbar & hooks up the events
*/
protected _createDomNode(): void {
this.domNode = document.createElement('div');
this.domNode = createFastDomNode(document.createElement('div'));
if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) {
// Put the worker reporter in its own layer
this.domNode.style.transform = 'translate3d(0px, 0px, 0px)';
// Put the scrollbar in its own layer
this.domNode.setTransform('translate3d(0px, 0px, 0px)');
}
this._visibilityController.setDomNode(this.domNode);
this.domNode.style.position = 'absolute';
this.domNode.setPosition('absolute');
this.onmousedown(this.domNode, (e) => this._domNodeMouseDown(e));
this.onmousedown(this.domNode.domNode, (e) => this._domNodeMouseDown(e));
}
/**
......@@ -388,22 +401,25 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
*/
protected _createArrow(className: string, top: number, left: number, bottom: number, right: number, bgWidth: number, bgHeight: number, mouseWheelEventFactory: IMouseWheelEventFactory): void {
let arrow = this._register(new ScrollbarArrow(className, top, left, bottom, right, bgWidth, bgHeight, mouseWheelEventFactory, this._parent));
this.domNode.appendChild(arrow.bgDomNode);
this.domNode.appendChild(arrow.domNode);
this.domNode.domNode.appendChild(arrow.bgDomNode);
this.domNode.domNode.appendChild(arrow.domNode);
}
/**
* Creates the slider dom node, adds it to the container & hooks up the events
*/
protected _createSlider(top: number, left: number, width: number, height: number): void {
this.slider = document.createElement('div');
this.slider.className = 'slider';
this.slider.style.position = 'absolute';
setPosition(this.slider, top, left, null, null);
setSize(this.slider, width, height);
this.domNode.appendChild(this.slider);
this.slider = createFastDomNode(document.createElement('div'));
this.slider.setClassName('slider');
this.slider.setPosition('absolute');
this.slider.setTop(top);
this.slider.setLeft(left);
this.slider.setWidth(width);
this.slider.setHeight(height);
this.domNode.domNode.appendChild(this.slider.domNode);
this.onmousedown(this.slider, (e) => this._sliderMouseDown(e));
this.onmousedown(this.slider.domNode, (e) => this._sliderMouseDown(e));
}
// ----------------- Update state
......@@ -447,7 +463,7 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
// ----------------- DOM events
private _domNodeMouseDown(e: IMouseEvent): void {
if (e.target !== this.domNode) {
if (e.target !== this.domNode.domNode) {
return;
}
this._onMouseDown(e);
......@@ -455,7 +471,7 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
public delegateMouseDown(browserEvent: MouseEvent): void {
let e = new StandardMouseEvent(browserEvent);
let domTop = this.domNode.getClientRects()[0].top;
let domTop = this.domNode.domNode.getClientRects()[0].top;
let sliderStart = domTop + this._scrollbarState.getSliderPosition();
let sliderStop = domTop + this._scrollbarState.getSliderPosition() + this._scrollbarState.getSliderSize();
let mousePos = this._sliderMousePosition(e);
......@@ -469,7 +485,7 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
}
private _onMouseDown(e: IMouseEvent): void {
let domNodePosition = DomUtils.getDomNodePosition(this.domNode);
let domNodePosition = DomUtils.getDomNodePosition(this.domNode.domNode);
let desiredSliderPosition = this._mouseDownRelativePosition(e, domNodePosition) - this._scrollbarState.getArrowSize() - this._scrollbarState.getSliderSize() / 2;
this.setDesiredScrollPosition(this._scrollbarState.convertSliderPositionToScrollPosition(desiredSliderPosition));
this._sliderMouseDown(e);
......@@ -480,7 +496,7 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
let initialMouseOrthogonalPosition = this._sliderOrthogonalMousePosition(e);
let initialScrollPosition = this._getScrollPosition();
let draggingDelta = this._sliderMousePosition(e) - this._scrollbarState.getSliderPosition();
DomUtils.toggleClass(this.slider, 'active', true);
this.slider.toggleClassName('active', true);
this._mouseMoveMonitor.startMonitoring(
standardMouseMoveMerger,
......@@ -497,7 +513,7 @@ export abstract class AbstractScrollbar extends Widget implements IScrollbar {
}
},
() => {
DomUtils.toggleClass(this.slider, 'active', false);
this.slider.toggleClassName('active', false);
this._parent.onDragEnd();
}
);
......
......@@ -10,7 +10,6 @@ import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent';
import {IDomNodePosition} from 'vs/base/browser/dom';
import {IParent, IScrollableElementOptions, Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {IScrollable} from 'vs/base/common/scrollable';
import {StyleMutator} from 'vs/base/browser/styleMutator';
export class HorizontalScrollbar extends AbstractScrollbar {
......@@ -42,19 +41,19 @@ export class HorizontalScrollbar extends AbstractScrollbar {
}
protected _updateSlider(sliderSize: number, sliderPosition: number): void {
StyleMutator.setWidth(this.slider, sliderSize);
this.slider.setWidth(sliderSize);
if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) {
StyleMutator.setTransform(this.slider, 'translate3d(' + sliderPosition + 'px, 0px, 0px)');
this.slider.setTransform('translate3d(' + sliderPosition + 'px, 0px, 0px)');
} else {
StyleMutator.setLeft(this.slider, sliderPosition);
this.slider.setLeft(sliderPosition);
}
}
protected _renderDomNode(largeSize: number, smallSize: number): void {
StyleMutator.setWidth(this.domNode, largeSize);
StyleMutator.setHeight(this.domNode, smallSize);
StyleMutator.setLeft(this.domNode, 0);
StyleMutator.setBottom(this.domNode, 0);
this.domNode.setWidth(largeSize);
this.domNode.setHeight(smallSize);
this.domNode.setLeft(0);
this.domNode.setBottom(0);
}
protected _mouseDownRelativePosition(e: IMouseEvent, domNodePosition: IDomNodePosition): number {
......
......@@ -5,6 +5,7 @@
'use strict';
import {IScrollable} from 'vs/base/common/scrollable';
import {FastDomNode} from 'vs/base/browser/styleMutator';
export interface IScrollableElementCreationOptions {
/**
......@@ -185,9 +186,9 @@ export interface IMouseWheelEvent {
}
export interface IScrollbar {
domNode: HTMLElement;
domNode: FastDomNode;
dispose(): void;
slider: HTMLElement;
slider: FastDomNode;
onElementSize(size: number): void;
onElementScrollSize(scrollSize: number): void;
onElementScrollPosition(scrollPosition: number): void;
......
......@@ -74,8 +74,8 @@ export class ScrollableElement extends Widget implements IScrollableElement {
this._domNode.style.position = 'relative';
this._domNode.style.overflow = 'hidden';
this._domNode.appendChild(this._originalElement);
this._domNode.appendChild(this._horizontalScrollbar.domNode);
this._domNode.appendChild(this._verticalScrollbar.domNode);
this._domNode.appendChild(this._horizontalScrollbar.domNode.domNode);
this._domNode.appendChild(this._verticalScrollbar.domNode.domNode);
if (this._options.useShadows) {
this._leftShadowDomNode = document.createElement('div');
......@@ -126,7 +126,7 @@ export class ScrollableElement extends Widget implements IScrollableElement {
public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo {
return {
parent: this._domNode,
insertBefore: this._verticalScrollbar.domNode,
insertBefore: this._verticalScrollbar.domNode.domNode,
};
}
......
......@@ -10,7 +10,6 @@ import {IMouseEvent, StandardMouseWheelEvent} from 'vs/base/browser/mouseEvent';
import {IDomNodePosition} from 'vs/base/browser/dom';
import {IParent, IScrollableElementOptions, Visibility} from 'vs/base/browser/ui/scrollbar/scrollableElement';
import {IScrollable} from 'vs/base/common/scrollable';
import {StyleMutator} from 'vs/base/browser/styleMutator';
export class VerticalScrollbar extends AbstractScrollbar {
......@@ -43,19 +42,19 @@ export class VerticalScrollbar extends AbstractScrollbar {
}
protected _updateSlider(sliderSize: number, sliderPosition: number): void {
StyleMutator.setHeight(this.slider, sliderSize);
this.slider.setHeight(sliderSize);
if (!this._forbidTranslate3dUse && Browser.canUseTranslate3d) {
StyleMutator.setTransform(this.slider, 'translate3d(0px, ' + sliderPosition + 'px, 0px)');
this.slider.setTransform('translate3d(0px, ' + sliderPosition + 'px, 0px)');
} else {
StyleMutator.setTop(this.slider, sliderPosition);
this.slider.setTop(sliderPosition);
}
}
protected _renderDomNode(largeSize: number, smallSize: number): void {
StyleMutator.setWidth(this.domNode, smallSize);
StyleMutator.setHeight(this.domNode, largeSize);
StyleMutator.setRight(this.domNode, 0);
StyleMutator.setTop(this.domNode, 0);
this.domNode.setWidth(smallSize);
this.domNode.setHeight(largeSize);
this.domNode.setRight(0);
this.domNode.setTop(0);
}
protected _mouseDownRelativePosition(e: IMouseEvent, domNodePosition: IDomNodePosition): number {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册