From c4f86d2a30748a86234d32148de9487a8c6d2d4c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 3 May 2016 11:49:16 +0200 Subject: [PATCH] :lipstick: zone widget --- src/vs/base/common/lifecycle.ts | 7 + .../contrib/zoneWidget/browser/zoneWidget.ts | 147 ++++++++---------- 2 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 1d4842f620c..74042437db5 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -80,3 +80,10 @@ export abstract class Disposable implements IDisposable { return t; } } + +export class Disposables extends Disposable { + + public add(disposable: IDisposable): void { + this._register(disposable); + } +} diff --git a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts index f4cd9147cb8..8b906df291f 100644 --- a/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/browser/zoneWidget.ts @@ -6,10 +6,12 @@ 'use strict'; import 'vs/css!./zoneWidget'; -import {ListenerUnbind} from 'vs/base/common/eventEmitter'; +import {Disposables} from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; import * as dom from 'vs/base/browser/dom'; import {EventType, IEditorLayoutInfo, IPosition, IRange} from 'vs/editor/common/editorCommon'; +import {Range} from 'vs/editor/common/core/range'; +import {Position} from 'vs/editor/common/core/position'; import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, IViewZoneChangeAccessor} from 'vs/editor/browser/editorBrowser'; export interface IOptions { @@ -20,7 +22,7 @@ export interface IOptions { isAccessible?: boolean; } -var defaultOptions:IOptions = { +var defaultOptions: IOptions = { showArrow: true, showFrame: true, frameColor: '', @@ -31,14 +33,14 @@ var WIDGET_ID = 'vs.editor.contrib.zoneWidget'; class ViewZoneDelegate implements IViewZone { - public domNode:HTMLElement; - public afterLineNumber:number; - public afterColumn:number; - public heightInLines:number; - private _onDomNodeTop:(top:number)=>void; - private _onComputedHeight:(height:number)=>void; + public domNode: HTMLElement; + public afterLineNumber: number; + public afterColumn: number; + public heightInLines: number; + private _onDomNodeTop: (top: number) => void; + private _onComputedHeight: (height: number) => void; - constructor (domNode:HTMLElement, afterLineNumber:number, afterColumn:number, heightInLines:number, onDomNodeTop:(top:number)=>void, onComputedHeight:(height:number)=>void) { + constructor(domNode: HTMLElement, afterLineNumber: number, afterColumn: number, heightInLines: number, onDomNodeTop: (top: number) => void, onComputedHeight: (height: number) => void) { this.domNode = domNode; this.afterLineNumber = afterLineNumber; this.afterColumn = afterColumn; @@ -47,11 +49,11 @@ class ViewZoneDelegate implements IViewZone { this._onComputedHeight = onComputedHeight; } - public onDomNodeTop(top:number):void { + public onDomNodeTop(top: number): void { this._onDomNodeTop(top); } - public onComputedHeight(height:number):void { + public onComputedHeight(height: number): void { this._onComputedHeight(height); } } @@ -61,7 +63,7 @@ class OverlayWidgetDelegate implements IOverlayWidget { private _id: string; private _domNode: HTMLElement; - constructor (id: string, domNode: HTMLElement) { + constructor(id: string, domNode: HTMLElement) { this._id = id; this._domNode = domNode; } @@ -80,44 +82,35 @@ class OverlayWidgetDelegate implements IOverlayWidget { } -export class ZoneWidget { +export class ZoneWidget { - private zoneId:number; - private lastView:any; - private overlayWidget: OverlayWidgetDelegate; + private _zoneId: number = -1; + private _overlayWidget: OverlayWidgetDelegate = null; + private _disposables = new Disposables(); - public container: HTMLElement; - public shadowTop: HTMLElement; - public shadowBottom: HTMLElement; - public domNode:HTMLElement; - public position:IPosition; - public editor:ICodeEditor; - public options:IOptions; + public container: HTMLElement = null; + public domNode: HTMLElement; + public position: IPosition; + public editor: ICodeEditor; + public options: IOptions; - private listenersToRemove:ListenerUnbind[]; - - constructor(editor:ICodeEditor, options:IOptions = {}) { + constructor(editor: ICodeEditor, options: IOptions = {}) { this.editor = editor; this.options = objects.mixin(objects.clone(defaultOptions), options); - this.zoneId = -1; - this.overlayWidget = null; - this.lastView = null; this.domNode = document.createElement('div'); if (!this.options.isAccessible) { this.domNode.setAttribute('aria-hidden', 'true'); this.domNode.setAttribute('role', 'presentation'); } - this.container = null; - this.listenersToRemove = []; - this.listenersToRemove.push(this.editor.addListener(EventType.EditorLayout, (info:IEditorLayoutInfo) => { - var width = this.getWidth(info); + this._disposables.add(this.editor.addListener2(EventType.EditorLayout, (info: IEditorLayoutInfo) => { + var width = this._getWidth(info); this.domNode.style.width = width + 'px'; this.onWidth(width); })); } - public create():void { + public create(): void { dom.addClass(this.domNode, 'zone-widget'); dom.addClass(this.domNode, this.options.className); @@ -129,44 +122,37 @@ export class ZoneWidget { this.fillContainer(this.container); } - private getWidth(info:IEditorLayoutInfo=this.editor.getLayoutInfo()):number { + private _getWidth(info: IEditorLayoutInfo = this.editor.getLayoutInfo()): number { return info.width - info.verticalScrollbarWidth; } - private onViewZoneTop(top:number):void { + private _onViewZoneTop(top: number): void { this.domNode.style.top = top + 'px'; } - private onViewZoneHeight(height:number):void { + private _onViewZoneHeight(height: number): void { this.domNode.style.height = height + 'px'; this.doLayout(height - this._decoratingElementsHeight()); } - public show(where:IRange, heightInLines:number):void; - public show(where:IPosition, heightInLines:number):void; - public show(where:any, heightInLines:number):void { - if(typeof where.startLineNumber === 'number') { - this.showImpl(where, heightInLines); - } else { - this.showImpl({ - startLineNumber: (where).lineNumber, - startColumn: (where).column, - endLineNumber: (where).lineNumber, - endColumn: (where).column - }, heightInLines); - } + public show(rangeOrPos: IRange | IPosition, heightInLines: number): void { + const range = Range.isIRange(rangeOrPos) + ? rangeOrPos + : Position.asEmptyRange(rangeOrPos); + + this._showImpl(range, heightInLines); } private _decoratingElementsHeight(): number { let lineHeight = this.editor.getConfiguration().lineHeight; let result = 0; - if(this.options.showArrow) { + if (this.options.showArrow) { let arrowHeight = Math.round(lineHeight / 3); result += 2 * arrowHeight; } - if(this.options.showFrame) { + if (this.options.showFrame) { let frameThickness = Math.round(lineHeight / 9); result += 2 * frameThickness; } @@ -174,13 +160,13 @@ export class ZoneWidget { return result; } - private showImpl(where:IRange, heightInLines:number):void { + private _showImpl(where: IRange, heightInLines: number): void { var position = { lineNumber: where.startLineNumber, column: where.startColumn }; - this.domNode.style.width = this.getWidth() + 'px'; + this.domNode.style.width = this._getWidth() + 'px'; // Reveal position, to get the line rendered, such that the arrow can be positioned properly this.editor.revealPosition(position); @@ -192,7 +178,7 @@ export class ZoneWidget { arrowHeight = 0, frameThickness = 0; // Render the arrow one 1/3 of an editor line height - if(this.options.showArrow) { + if (this.options.showArrow) { arrowHeight = Math.round(lineHeight / 3); arrow = document.createElement('div'); @@ -206,18 +192,18 @@ export class ZoneWidget { } // Render the frame as 1/9 of an editor line height - if(this.options.showFrame) { + if (this.options.showFrame) { frameThickness = Math.round(lineHeight / 9); } // insert zone widget - this.editor.changeViewZones((accessor:IViewZoneChangeAccessor) => { - if (this.zoneId !== -1) { - accessor.removeZone(this.zoneId); + this.editor.changeViewZones((accessor: IViewZoneChangeAccessor) => { + if (this._zoneId !== -1) { + accessor.removeZone(this._zoneId); } - if (this.overlayWidget) { - this.editor.removeOverlayWidget(this.overlayWidget); - this.overlayWidget = null; + if (this._overlayWidget) { + this.editor.removeOverlayWidget(this._overlayWidget); + this._overlayWidget = null; } this.domNode.style.top = '-1000px'; var viewZone = new ViewZoneDelegate( @@ -225,16 +211,16 @@ export class ZoneWidget { position.lineNumber, position.column, heightInLines, - (top:number) => this.onViewZoneTop(top), - (height:number) => this.onViewZoneHeight(height) + (top: number) => this._onViewZoneTop(top), + (height: number) => this._onViewZoneHeight(height) ); - this.zoneId = accessor.addZone(viewZone); - this.overlayWidget = new OverlayWidgetDelegate(WIDGET_ID + this.zoneId, this.domNode); - this.editor.addOverlayWidget(this.overlayWidget); + this._zoneId = accessor.addZone(viewZone); + this._overlayWidget = new OverlayWidgetDelegate(WIDGET_ID + this._zoneId, this.domNode); + this.editor.addOverlayWidget(this._overlayWidget); }); - if(this.options.showFrame) { + if (this.options.showFrame) { this.container.style.borderTopColor = this.options.frameColor; this.container.style.borderBottomColor = this.options.frameColor; this.container.style.borderTopWidth = frameThickness + 'px'; @@ -258,35 +244,32 @@ export class ZoneWidget { this.position = position; } - public dispose():void { + public dispose(): void { - this.listenersToRemove.forEach(function (element) { - element(); - }); - this.listenersToRemove = []; + this._disposables.dispose(); - if (this.overlayWidget) { - this.editor.removeOverlayWidget(this.overlayWidget); - this.overlayWidget = null; + if (this._overlayWidget) { + this.editor.removeOverlayWidget(this._overlayWidget); + this._overlayWidget = null; } - if (this.zoneId !== -1) { + if (this._zoneId !== -1) { this.editor.changeViewZones((accessor) => { - accessor.removeZone(this.zoneId); - this.zoneId = -1; + accessor.removeZone(this._zoneId); + this._zoneId = -1; }); } } - public fillContainer(container:HTMLElement):void { + public fillContainer(container: HTMLElement): void { // implement in subclass } - public onWidth(widthInPixel:number):void { + public onWidth(widthInPixel: number): void { // implement in subclass } - public doLayout(heightInPixel:number):void { + public doLayout(heightInPixel: number): void { // implement in subclass } } -- GitLab