提交 3aa0a3dc 编写于 作者: J Joao Moreno

pimp up glyph hover

上级 dbbadcd0
......@@ -60,7 +60,7 @@ class ModesHoverController implements editorCommon.IEditorContribution {
}));
this._contentWidget = new ModesContentHoverWidget(editor, openerService, modeService);
this._glyphWidget = new ModesGlyphHoverWidget(editor);
this._glyphWidget = new ModesGlyphHoverWidget(editor, openerService, modeService);
}
}
......
......@@ -156,8 +156,8 @@ export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWi
private _id: string;
protected _editor: editorBrowser.ICodeEditor;
protected _isVisible: boolean;
protected _domNode: HTMLElement;
private _isVisible: boolean;
private _domNode: HTMLElement;
protected _showAtLineNumber: number;
constructor(id: string, editor: editorBrowser.ICodeEditor) {
......@@ -167,23 +167,30 @@ export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWi
this._isVisible = false;
this._domNode = document.createElement('div');
this._domNode.className = 'monaco-editor-hover monaco-editor-background';
this._domNode.style.display = 'none';
this._domNode.className = 'monaco-editor-hover hidden';
this._domNode.setAttribute('aria-hidden', 'true');
this._domNode.setAttribute('role', 'presentation');
this._showAtLineNumber = -1;
this._editor.applyFontInfo(this._domNode);
this._register(this._editor.onDidChangeConfiguration((e:IConfigurationChangedEvent) => {
if (e.fontInfo) {
this._editor.applyFontInfo(this._domNode);
this.updateFont();
}
}));
this._editor.addOverlayWidget(this);
}
protected get isVisible(): boolean {
return this._isVisible;
}
protected set isVisible(value: boolean) {
this._isVisible = value;
toggleClass(this._domNode, 'hidden', !this._isVisible);
}
public getId(): string {
return this._id;
}
......@@ -195,25 +202,26 @@ export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWi
public showAt(lineNumber: number): void {
this._showAtLineNumber = lineNumber;
if (!this._isVisible) {
this._isVisible = true;
this._domNode.style.display = 'block';
if (!this.isVisible) {
this.isVisible = true;
}
let editorLayout = this._editor.getLayoutInfo();
let topForLineNumber = this._editor.getTopForLineNumber(this._showAtLineNumber);
let editorScrollTop = this._editor.getScrollTop();
const editorLayout = this._editor.getLayoutInfo();
const topForLineNumber = this._editor.getTopForLineNumber(this._showAtLineNumber);
const editorScrollTop = this._editor.getScrollTop();
const lineHeight = this._editor.getConfiguration().lineHeight;
const nodeHeight = this._domNode.clientHeight;
const top = topForLineNumber - editorScrollTop - ((nodeHeight - lineHeight) / 2);
this._domNode.style.left = (editorLayout.glyphMarginLeft + editorLayout.glyphMarginWidth) + 'px';
this._domNode.style.top = (topForLineNumber - editorScrollTop) + 'px';
this._domNode.style.left = `${ editorLayout.glyphMarginLeft + editorLayout.glyphMarginWidth }px`;
this._domNode.style.top = `${ Math.max(Math.round(top), 0) }px`;
}
public hide(): void {
if (!this._isVisible) {
if (!this.isVisible) {
return;
}
this._isVisible = false;
this._domNode.style.display = 'none';
this.isVisible = false;
}
public getPosition():editorBrowser.IOverlayWidgetPosition {
......@@ -224,4 +232,17 @@ export class GlyphHoverWidget extends Widget implements editorBrowser.IOverlayWi
this._editor.removeOverlayWidget(this);
super.dispose();
}
private updateFont(): void {
const codeTags: HTMLPhraseElement[] = Array.prototype.slice.call(this._domNode.getElementsByTagName('code'));
const codeClasses: HTMLElement[] = Array.prototype.slice.call(this._domNode.getElementsByClassName('code'));
[...codeTags, ...codeClasses].forEach(node => this._editor.applyFontInfo(node));
}
protected updateContents(node: Node): void {
this._domNode.textContent = '';
this._domNode.appendChild(node);
this.updateFont();
}
}
......@@ -8,6 +8,13 @@ import {IModelDecoration, IRange} from 'vs/editor/common/editorCommon';
import {ICodeEditor} from 'vs/editor/browser/editorBrowser';
import {HoverOperation, IHoverComputer} from './hoverOperation';
import {GlyphHoverWidget} from './hoverWidgets';
import {$} from 'vs/base/browser/dom';
import {renderMarkedString} from 'vs/base/browser/htmlContentRenderer';
import {IOpenerService, NullOpenerService} from 'vs/platform/opener/common/opener';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {IModeService} from 'vs/editor/common/services/modeService';
import {tokenizeToString} from 'vs/editor/common/modes/textToHtmlTokenizer';
export interface IHoverMessage {
value?: string;
......@@ -77,9 +84,11 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
private _computer: MarginComputer;
private _hoverOperation: HoverOperation<IHoverMessage[]>;
constructor(editor: ICodeEditor) {
constructor(editor: ICodeEditor, private openerService: IOpenerService, private modeService: IModeService) {
super(ModesGlyphHoverWidget.ID, editor);
this.openerService = openerService || NullOpenerService;
this._lastLineNumber = -1;
this._computer = new MarginComputer(this._editor);
......@@ -99,7 +108,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
}
public onModelDecorationsChanged(): void {
if (this._isVisible) {
if (this.isVisible) {
// The decorations have changed and the hover is visible,
// we need to recompute the displayed text
this._hoverOperation.cancel();
......@@ -141,29 +150,25 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
private _renderMessages(lineNumber: number, messages: IHoverMessage[]): void {
var fragment = document.createDocumentFragment();
const fragment = document.createDocumentFragment();
messages.forEach((msg) => {
var row:HTMLElement = document.createElement('div');
var span:HTMLElement = null;
if (msg.className) {
span = document.createElement('span');
span.textContent = msg.value;
span.className = msg.className;
row.appendChild(span);
} else {
row.textContent = msg.value;
}
fragment.appendChild(row);
const renderedContents = renderMarkedString(msg.value, {
actionCallback: content => this.openerService.open(URI.parse(content)),
codeBlockRenderer: (modeId, value): string | TPromise<string> => {
const mode = this.modeService.getMode(modeId || this._editor.getModel().getModeId());
const getMode = mode => mode ? TPromise.as(mode) : this.modeService.getOrCreateMode(modeId);
return getMode(mode)
.then(null, err => null)
.then(mode => `<div class="code">${ tokenizeToString(value, mode) }</div>`);
}
});
fragment.appendChild($('div.hover-row', null, renderedContents));
});
this._domNode.textContent = '';
this._domNode.appendChild(fragment);
// show
this.updateContents(fragment);
this.showAt(lineNumber);
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册