diff --git a/src/vs/editor/contrib/hover/browser/hover.ts b/src/vs/editor/contrib/hover/browser/hover.ts index 61947151926226d171ad58d512440e901964fbd4..7ab8a3f1c14e514cf2b4c426068bee37abf306b4 100644 --- a/src/vs/editor/contrib/hover/browser/hover.ts +++ b/src/vs/editor/contrib/hover/browser/hover.ts @@ -6,17 +6,22 @@ 'use strict'; import 'vs/css!./hover'; +import nls = require('vs/nls'); +import {TPromise} from 'vs/base/common/winjs.base'; import {EditorBrowserRegistry} from 'vs/editor/browser/editorBrowserExtensions'; import EventEmitter = require('vs/base/common/eventEmitter'); +import {CommonEditorRegistry, ContextKey, EditorActionDescriptor} from 'vs/editor/common/editorCommonExtensions'; +import {Range} from 'vs/editor/common/core/range'; import EditorBrowser = require('vs/editor/browser/editorBrowser'); import EditorCommon = require('vs/editor/common/editorCommon'); +import {EditorAction, Behaviour} from 'vs/editor/common/editorAction'; import Platform = require('vs/base/common/platform'); import ModesContentHover = require('./modesContentHover'); import ModesGlyphHover = require('./modesGlyphHover'); import Keyboard = require('vs/base/browser/keyboardEvent'); import {IEditorService} from 'vs/platform/editor/common/editor'; -import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; -import {KeyCode} from 'vs/base/common/keyCodes'; +import {IKeybindingService, KbExpr} from 'vs/platform/keybinding/common/keybindingService'; +import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; class ModesHoverController implements EditorCommon.IEditorContribution { @@ -28,6 +33,10 @@ class ModesHoverController implements EditorCommon.IEditorContribution { private _contentWidget: ModesContentHover.ModesContentHoverWidget; private _glyphWidget: ModesGlyphHover.ModesGlyphHoverWidget; + static getModesHoverController(editor: EditorCommon.ICommonCodeEditor): ModesHoverController { + return editor.getContribution(ModesHoverController.ID); + } + constructor(editor: EditorBrowser.ICodeEditor, @IEditorService editorService: IEditorService, @IKeybindingService keybindingService: IKeybindingService @@ -87,7 +96,7 @@ class ModesHoverController implements EditorCommon.IEditorContribution { if (this._editor.getConfiguration().hover && targetType === EditorCommon.MouseTargetType.CONTENT_TEXT) { this._glyphWidget.hide(); - this._contentWidget.startShowingAt(mouseEvent.target.range); + this._contentWidget.startShowingAt(mouseEvent.target.range, false); } else if (targetType === EditorCommon.MouseTargetType.GUTTER_GLYPH_MARGIN) { this._contentWidget.hide(); this._glyphWidget.startShowingAt(mouseEvent.target.position.lineNumber); @@ -109,6 +118,10 @@ class ModesHoverController implements EditorCommon.IEditorContribution { this._contentWidget.hide(); } + public showContentHover(range: EditorCommon.IEditorRange, focus: boolean): void { + this._contentWidget.startShowingAt(range, focus); + } + public getId(): string { return ModesHoverController.ID; } @@ -128,4 +141,28 @@ class ModesHoverController implements EditorCommon.IEditorContribution { } } +class ShowHoverAction extends EditorAction { + static ID = 'editor.action.showHover'; + + constructor(descriptor: EditorCommon.IEditorActionDescriptorData, editor: EditorCommon.ICommonCodeEditor, @IEditorService editorService: IEditorService) { + super(descriptor, editor, Behaviour.TextFocus); + } + + public run(): TPromise { + const position = this.editor.getPosition(); + const word = this.editor.getModel().getWordAtPosition(position); + if (word) { + const range = new Range(position.lineNumber, position.column, position.lineNumber, word.endColumn); + (this.editor.getContribution(ModesHoverController.ID)).showContentHover(range, true); + } + + return TPromise.as(null); + } +} + EditorBrowserRegistry.registerEditorContribution(ModesHoverController); +CommonEditorRegistry.registerEditorAction(new EditorActionDescriptor(ShowHoverAction, ShowHoverAction.ID, nls.localize('showHover', "Show Hover"), { + context: ContextKey.EditorTextFocus, + kbExpr: KbExpr.has(EditorCommon.KEYBINDING_CONTEXT_EDITOR_TEXT_FOCUS), + primary: KeyMod.chord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_I) +})); diff --git a/src/vs/editor/contrib/hover/browser/hoverWidgets.ts b/src/vs/editor/contrib/hover/browser/hoverWidgets.ts index 712e381cf8309159bef8632a70e0daf73e00e293..8cec085e05a2a0adeda92efd9595e58bb6220591 100644 --- a/src/vs/editor/contrib/hover/browser/hoverWidgets.ts +++ b/src/vs/editor/contrib/hover/browser/hoverWidgets.ts @@ -4,6 +4,9 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; +import lifecycle = require('vs/base/common/lifecycle'); +import {CommonKeybindings} from 'vs/base/common/keyCodes'; +import dom = require('vs/base/browser/dom'); import EditorBrowser = require('vs/editor/browser/editorBrowser'); import EditorCommon = require('vs/editor/common/editorCommon'); import {Position} from 'vs/editor/common/core/position'; @@ -17,6 +20,8 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { private _containerDomNode: HTMLElement; _domNode: HTMLElement; _showAtPosition: EditorCommon.IEditorPosition; + private _stoleFocus: boolean; + private _toDispose: lifecycle.IDisposable[]; // Editor.IContentWidget.allowEditorOverflow public allowEditorOverflow = true; @@ -32,6 +37,13 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { this._domNode = document.createElement('div'); this._domNode.style.display = 'inline-block'; this._containerDomNode.appendChild(this._domNode); + this._domNode.tabIndex = 0; + this._toDispose = []; + this._toDispose.push(dom.addStandardDisposableListener(this._domNode, 'keydown', (e: dom.IKeyboardEvent) => { + if (e.equals(CommonKeybindings.ESCAPE)) { + this.hide(); + } + })); this._editor.addContentWidget(this); this._showAtPosition = null; @@ -45,7 +57,7 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { return this._containerDomNode; } - public showAt(position:EditorCommon.IPosition): void { + public showAt(position:EditorCommon.IPosition, focus: boolean): void { // Position has changed this._showAtPosition = new Position(position.lineNumber, position.column); @@ -67,6 +79,10 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { // Simply force a synchronous render on the editor // such that the widget does not really render with left = '0px' this._editor.render(); + this._stoleFocus = focus; + if (focus) { + this._domNode.focus(); + } } public hide(): void { @@ -75,6 +91,9 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { } this._isVisible = false; this._editor.layoutContentWidget(this); + if (this._stoleFocus) { + this._editor.focus(); + } } public getPosition():EditorBrowser.IContentWidgetPosition { @@ -92,6 +111,7 @@ export class ContentHoverWidget implements EditorBrowser.IContentWidget { public dispose(): void { this.hide(); + this._toDispose = lifecycle.disposeAll(this._toDispose); } } diff --git a/src/vs/editor/contrib/hover/browser/modesContentHover.ts b/src/vs/editor/contrib/hover/browser/modesContentHover.ts index 15dee42d12d21ffef4d0c2edb7cd991569b7fc42..4ae7a393483477ec9f419213999190b44e79b755 100644 --- a/src/vs/editor/contrib/hover/browser/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/browser/modesContentHover.ts @@ -125,6 +125,7 @@ export class ModesContentHoverWidget extends HoverWidget.ContentHoverWidget { private _isChangingDecorations: boolean; private _editorService: IEditorService; private _keybindingService: IKeybindingService; + private _shouldFocus: boolean; constructor(editor: EditorBrowser.ICodeEditor, editorService: IEditorService, keybindingService: IKeybindingService) { super(ModesContentHoverWidget.ID, editor); @@ -156,7 +157,7 @@ export class ModesContentHoverWidget extends HoverWidget.ContentHoverWidget { } } - public startShowingAt(range: EditorCommon.IEditorRange): void { + public startShowingAt(range: EditorCommon.IEditorRange, focus: boolean): void { if (this._lastRange) { if (this._lastRange.equalsRange(range)) { // We have to show the widget at the exact same range as before, so no work is needed @@ -191,6 +192,7 @@ export class ModesContentHoverWidget extends HoverWidget.ContentHoverWidget { this._lastRange = range; this._computer.setRange(range); + this._shouldFocus = focus; this._hoverOperation.start(); } @@ -284,7 +286,7 @@ export class ModesContentHoverWidget extends HoverWidget.ContentHoverWidget { this.showAt({ lineNumber: renderRange.startLineNumber, column: renderColumn - }); + }, this._shouldFocus); this._isChangingDecorations = true; this._highlightDecorations = this._editor.deltaDecorations(this._highlightDecorations, [{