提交 15a2d69d 编写于 作者: J Joao Moreno

Merge branch 'master' of github.com:Microsoft/vscode

......@@ -71,7 +71,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
capabilities: {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
completionProvider: clientDynamicRegisterSupport ? { resolveProvider: true, triggerCharacters: ['.', ':', '<', '"', '=', '/'] } : null,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['.', ':', '<', '"', '=', '/'] } : null,
hoverProvider: true,
documentHighlightProvider: true,
documentRangeFormattingProvider: false,
......
......@@ -74,7 +74,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
capabilities: {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
completionProvider: clientDynamicRegisterSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : null,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : null,
hoverProvider: true,
documentSymbolProvider: true,
documentRangeFormattingProvider: false
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-tree .monaco-tree-row > .content.actions {
position: relative;
display: flex;
}
.monaco-tree .monaco-tree-row > .content.actions > .sub-content {
flex: 1;
}
.monaco-tree .monaco-tree-row > .content.actions .action-item {
margin: 0;
}
/* Primary action bar */
.monaco-tree .monaco-tree-row > .content.actions > .primary-action-bar {
line-height: 1em;
}
.monaco-tree .monaco-tree-row > .content.actions > .primary-action-bar {
display: none;
padding: 0 0.8em 0 0.4em;
}
.monaco-tree .monaco-tree-row.focused > .content.has-actions > .primary-action-bar {
width: 0; /* in order to support a11y with keyboard, we use width: 0 to hide the actions, which still allows to "Tab" into the actions */
display: block;
}
.monaco-tree .monaco-tree-row:hover:not(.highlighted) > .content.has-actions > .primary-action-bar,
.monaco-tree.focused .monaco-tree-row.focused > .content.has-actions > .primary-action-bar,
.monaco-tree .monaco-tree-row > .content.has-actions.more > .primary-action-bar {
width: inherit;
display: block;
}
.monaco-tree .monaco-tree-row > .content.actions > .primary-action-bar .action-label {
margin-right: 0.2em;
margin-top: 4px;
background-repeat: no-repeat;
width: 16px;
height: 16px;
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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!./actionsRenderer';
import Lifecycle = require('vs/base/common/lifecycle');
import Builder = require('vs/base/browser/builder');
import Dom = require('vs/base/browser/dom');
import Actions = require('vs/base/common/actions');
import Events = require('vs/base/common/events');
import ActionBar = require('vs/base/browser/ui/actionbar/actionbar');
import TreeDefaults = require('./treeDefaults');
import Tree = require('vs/base/parts/tree/browser/tree');
var $ = Builder.$;
export interface IActionsRendererOptions {
actionProvider: Tree.IActionProvider;
actionRunner?: Actions.IActionRunner;
}
export class ActionsRenderer extends TreeDefaults.LegacyRenderer implements Lifecycle.IDisposable {
private static CONTENTS_CLEANUP_FN_KEY: string = '__$ActionsRenderer.contentCleanupFn';
private static NO_OP = () => { /* noop */ };
protected actionProvider: Tree.IActionProvider;
protected actionRunner: Actions.IActionRunner;
constructor(opts: IActionsRendererOptions) {
super();
this.actionProvider = opts.actionProvider;
this.actionRunner = opts.actionRunner;
}
public getHeight(tree: Tree.ITree, element: any): number {
return this.getContentHeight(tree, element);
}
protected render(tree: Tree.ITree, element: any, container: HTMLElement, previousCleanupFn?: Tree.IElementCallback): Tree.IElementCallback {
try {
Dom.clearNode(container);
} catch (e) {
if (!/The node to be removed is no longer a child of this node/.test(e.message)) {
throw e;
}
}
if (previousCleanupFn) {
previousCleanupFn(tree, element);
}
var $container = $(container).addClass('actions');
var $subContainer = $('.sub-content').appendTo($container);
var actionBar: ActionBar.ActionBar;
var actionBarListener: Lifecycle.IDisposable;
if (this.actionProvider.hasActions(tree, element)) {
$container.addClass('has-actions');
actionBar = new ActionBar.ActionBar($('.primary-action-bar').appendTo($container), {
context: this.getActionContext(tree, element),
actionItemProvider: a => this.actionProvider.getActionItem(tree, element, a),
actionRunner: this.actionRunner
});
this.actionProvider.getActions(tree, element).then((actions) => {
actionBar.push(actions, { icon: true, label: false });
});
actionBarListener = actionBar.addListener2(Events.EventType.RUN, (event: any) => {
if (event.error) {
this.onError(event.error);
}
});
} else {
$container.removeClass('has-actions');
}
var previousContentsCleanupFn = (previousCleanupFn ? previousCleanupFn[ActionsRenderer.CONTENTS_CLEANUP_FN_KEY] : ActionsRenderer.NO_OP) || ActionsRenderer.NO_OP;
previousContentsCleanupFn(tree, element);
var contentsCleanupFn = this.renderContents(tree, element, $subContainer.getHTMLElement(), null);
var cleanupFn = () => {
if (actionBarListener) {
actionBarListener.dispose();
}
if (actionBar) {
actionBar.dispose();
}
if (contentsCleanupFn) {
contentsCleanupFn(tree, element);
}
};
cleanupFn[ActionsRenderer.CONTENTS_CLEANUP_FN_KEY] = contentsCleanupFn;
return cleanupFn;
}
/* protected */ public getContentHeight(tree: Tree.ITree, element: any): number {
return 20;
}
/* protected */ public renderContents(tree: Tree.ITree, element: any, container: HTMLElement, previousCleanupFn: Tree.IElementCallback): Tree.IElementCallback {
return null;
}
/* protected */ public getActionContext(tree: Tree.ITree, element: any): any {
return null;
}
/* protected */ public onError(error: any): void {
return;
}
public dispose(): void {
this.actionProvider = null;
}
}
......@@ -1488,13 +1488,11 @@ export class Cursor extends EventEmitter {
private _indent(ctx: IMultipleCursorOperationContext): boolean {
this._applyEditForAll(ctx, (cursor) => TypeOperations.indent(this.context.config, this.context.model, cursor.modelState));
ctx.shouldRevealHorizontal = false;
return true;
}
private _outdent(ctx: IMultipleCursorOperationContext): boolean {
this._applyEditForAll(ctx, (cursor) => TypeOperations.outdent(this.context.config, this.context.model, cursor.modelState));
ctx.shouldRevealHorizontal = false;
return true;
}
......
......@@ -46,7 +46,7 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
private _findWidgetVisible: IContextKey<boolean>;
protected _state: FindReplaceState;
private _currentHistoryNavigator: HistoryNavigator<string>;
private _updateHistoryDelayer: Delayer<void>;
protected _updateHistoryDelayer: Delayer<void>;
private _model: FindModelBoundToEditorModel;
public static get(editor: editorCommon.ICommonCodeEditor): CommonFindController {
......
......@@ -5,11 +5,13 @@
'use strict';
import * as assert from 'assert';
import { TPromise } from 'vs/base/common/winjs.base';
import { Emitter } from 'vs/base/common/event';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { Range } from 'vs/editor/common/core/range';
import { IRange, EndOfLineSequence } from 'vs/editor/common/editorCommon';
import { IRange, EndOfLineSequence, ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import {
CommonFindController, FindStartFocusAction, IFindStartOptions,
NextMatchFindAction, StartFindAction, SelectHighlightsAction,
......@@ -17,11 +19,21 @@ import {
} from 'vs/editor/contrib/find/common/findController';
import { MockCodeEditor, withMockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
import { HistoryNavigator } from 'vs/base/common/history';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Delayer } from 'vs/base/common/async';
class TestFindController extends CommonFindController {
public hasFocus: boolean;
public delayUpdateHistory: boolean = false;
public delayedUpdateHistoryPromise: TPromise<void>;
private _delayedUpdateHistoryEvent: Emitter<void> = new Emitter<void>();
constructor(editor: ICommonCodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
super(editor, contextKeyService);
this._updateHistoryDelayer = new Delayer<void>(50);
}
protected _start(opts: IFindStartOptions): void {
super._start(opts);
......@@ -32,12 +44,26 @@ class TestFindController extends CommonFindController {
}
protected _delayedUpdateHistory() {
if (!this.delayedUpdateHistoryPromise) {
this.delayedUpdateHistoryPromise = new TPromise<void>((c, e) => {
const disposable = this._delayedUpdateHistoryEvent.event(() => {
disposable.dispose();
this.delayedUpdateHistoryPromise = null;
c(null);
});
});
}
if (this.delayUpdateHistory) {
super._delayedUpdateHistory();
} else {
this._updateHistory();
}
}
protected _updateHistory() {
super._updateHistory();
this._delayedUpdateHistoryEvent.fire();
}
}
suite('FindController', () => {
......@@ -237,10 +263,10 @@ suite('FindController', () => {
findController.getState().change({ searchString: '2' }, false);
findController.getState().change({ searchString: '3' }, false);
setTimeout(function () {
findController.delayedUpdateHistoryPromise.then(() => {
assert.deepEqual(['3'], toArray(findController.getHistory()));
done();
}, 500);
});
});
});
......
......@@ -22,7 +22,7 @@ import { Range } from 'vs/editor/common/core/range';
import { CodeSnippet } from 'vs/editor/contrib/snippet/common/snippet';
import { SnippetController } from 'vs/editor/contrib/snippet/common/snippetController';
import { Context as SuggestContext } from './suggest';
import { SuggestModel } from './suggestModel';
import { SuggestModel, State } from './suggestModel';
import { ICompletionItem } from './completionModel';
import { SuggestWidget } from './suggestWidget';
......@@ -125,7 +125,10 @@ export class SuggestController implements IEditorContribution {
const startColumn = item.position.column - item.suggestion.overwriteBefore;
const endColumn = position.column;
let value = true;
if (endColumn - startColumn === item.suggestion.insertText.length) {
if (
this.model.state === State.Auto
&& endColumn - startColumn === item.suggestion.insertText.length
) {
const oldText = this.editor.getModel().getValueInRange({
startLineNumber: position.lineNumber,
startColumn,
......
......@@ -78,7 +78,7 @@ export class LineContext {
}
}
const enum State {
export const enum State {
Idle = 0,
Manual = 1,
Auto = 2
......@@ -91,7 +91,7 @@ export class SuggestModel implements IDisposable {
private triggerCharacterListener: IDisposable;
private triggerAutoSuggestPromise: TPromise<void>;
private triggerRefilter = new TimeoutTimer();
private state: State;
private _state: State;
private requestPromise: TPromise<void>;
private context: LineContext;
......@@ -109,7 +109,7 @@ export class SuggestModel implements IDisposable {
get onDidSuggest(): Event<ISuggestEvent> { return this._onDidSuggest.event; }
constructor(private editor: ICommonCodeEditor) {
this.state = State.Idle;
this._state = State.Idle;
this.triggerAutoSuggestPromise = null;
this.requestPromise = null;
this.completionModel = null;
......@@ -205,6 +205,10 @@ export class SuggestModel implements IDisposable {
// --- trigger/retrigger/cancel suggest
get state(): State {
return this._state;
}
cancel(retrigger: boolean = false): void {
if (this.triggerAutoSuggestPromise) {
......@@ -217,7 +221,7 @@ export class SuggestModel implements IDisposable {
this.requestPromise = null;
}
this.state = State.Idle;
this._state = State.Idle;
this.completionModel = null;
this.context = null;
......@@ -225,11 +229,11 @@ export class SuggestModel implements IDisposable {
}
private updateActiveSuggestSession(): void {
if (this.state !== State.Idle) {
if (this._state !== State.Idle) {
if (!SuggestRegistry.has(this.editor.getModel())) {
this.cancel();
} else {
this.trigger(this.state === State.Auto, true);
this.trigger(this._state === State.Auto, true);
}
}
}
......@@ -256,7 +260,7 @@ export class SuggestModel implements IDisposable {
return;
}
if (this.state === State.Idle) {
if (this._state === State.Idle) {
// trigger 24x7 IntelliSense when idle, enabled, when cursor
// moved RIGHT, and when at a good position
......@@ -306,7 +310,7 @@ export class SuggestModel implements IDisposable {
// refine active suggestion
this.triggerRefilter.cancelAndSet(() => {
const position = this.editor.getPosition();
const ctx = new LineContext(model, position, this.state === State.Auto);
const ctx = new LineContext(model, position, this._state === State.Auto);
this.onNewContext(ctx);
}, 25);
}
......@@ -328,7 +332,7 @@ export class SuggestModel implements IDisposable {
// Cancel previous requests, change state & update UI
this.cancel(retrigger);
this.state = auto ? State.Auto : State.Manual;
this._state = auto ? State.Auto : State.Manual;
this._onDidTrigger.fire({ auto });
// Capture context when request was sent
......@@ -340,7 +344,7 @@ export class SuggestModel implements IDisposable {
).then(items => {
this.requestPromise = null;
if (this.state === State.Idle) {
if (this._state === State.Idle) {
return;
}
const model = this.editor.getModel();
......@@ -394,7 +398,7 @@ export class SuggestModel implements IDisposable {
if (ctx.column > this.context.column && this.completionModel.incomplete) {
// typed -> moved cursor RIGHT & incomple model -> retrigger
const { complete, incomplete } = this.completionModel.resolveIncompleteInfo();
this.trigger(this.state === State.Auto, true, incomplete, complete);
this.trigger(this._state === State.Auto, true, incomplete, complete);
} else {
// typed -> moved cursor RIGHT -> update UI
......
......@@ -6,12 +6,11 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { $, Builder } from 'vs/base/browser/builder';
import { ITree, IDataSource, IRenderer, IElementCallback, IActionProvider } from 'vs/base/parts/tree/browser/tree';
import { ITree, IDataSource, IRenderer, IActionProvider } from 'vs/base/parts/tree/browser/tree';
import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';
import { ClickBehavior, DefaultController } from 'vs/base/parts/tree/browser/treeDefaults';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { IActionRunner } from 'vs/base/common/actions';
import { ActionsRenderer } from 'vs/base/parts/tree/browser/actionsRenderer';
import { ContributableActionProvider } from 'vs/workbench/browser/actionBarRegistry';
import { ITreeExplorerService } from 'vs/workbench/parts/explorers/common/treeExplorerService';
import { IProgressService } from 'vs/platform/progress/common/progress';
......@@ -47,34 +46,45 @@ export class TreeDataSource implements IDataSource {
}
}
export class TreeRenderer extends ActionsRenderer implements IRenderer {
export interface ITreeExplorerTemplateData {
label: Builder;
}
export class TreeRenderer implements IRenderer {
private static ITEM_HEIGHT = 22;
private static TREE_TEMPLATE_ID = 'treeExplorer';
constructor(
state: TreeExplorerViewletState,
actionRunner: IActionRunner
) {
super({
actionProvider: state.actionProvider,
actionRunner: actionRunner
});
}
public getContentHeight(tree: ITree, element: any): number {
return 22;
public getHeight(tree: ITree, element: any): number {
return TreeRenderer.ITEM_HEIGHT;
}
public getTemplateId(tree: ITree, element: any): string {
return TreeRenderer.TREE_TEMPLATE_ID;
}
public renderContents(tree: ITree, node: InternalTreeExplorerNode, domElement: HTMLElement, previousCleanupFn: IElementCallback): IElementCallback {
const el = $(domElement).clearChildren();
public renderTemplate(tree: ITree, templateId: string, container: HTMLElement): ITreeExplorerTemplateData {
const el = $(container);
const item = $('.custom-viewlet-tree-node-item');
item.appendTo(el);
return this.renderFileFolderLabel(item, node);
const label = $('.custom-viewlet-tree-node-item-label').appendTo(item);
const link = $('a.plain').appendTo(label);
return { label: link };
}
private renderFileFolderLabel(container: Builder, node: InternalTreeExplorerNode): IElementCallback {
const label = $('.custom-viewlet-tree-node-item-label').appendTo(container);
$('a.plain').text(node.label).title(node.label).appendTo(label);
public renderElement(tree: ITree, node: InternalTreeExplorerNode, templateId: string, templateData: ITreeExplorerTemplateData): void {
templateData.label.text(node.label).title(node.label);
}
return null;
public disposeTemplate(tree: ITree, templateId: string, templateData: ITreeExplorerTemplateData): void {
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册