提交 24743e88 编写于 作者: S Sandeep Somavarapu

fix #8365

上级 6014db1a
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditor } from 'vs/platform/editor/common/editor';
import { FileEditorInput } from 'vs/workbench/parts/files/common/editors/fileEditorInput';
export interface IRangeHighlightDecoration {
resource: URI;
range: Range;
}
export class RangeHighlightDecorations implements IDisposable {
private rangeHighlightDecorationId: string = null;
private editor: editorCommon.ICommonCodeEditor = null;
private editorDisposables: IDisposable[] = [];
constructor(@IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
}
public clearCurrentFileRangeDecoration() {
if (this.editor && this.rangeHighlightDecorationId) {
this.doClearRangeDecoration(this.editor, this.rangeHighlightDecorationId);
}
this.rangeHighlightDecorationId = null;
}
public highlightRange(range: IRangeHighlightDecoration, editor?: IEditor) {
editor = editor ? editor : this.getEditor(range);
if (editor) {
this.doHighlightRange(<editorCommon.ICommonCodeEditor>editor.getControl(), range);
}
}
private doHighlightRange(editor: editorCommon.ICommonCodeEditor, selectionRange: IRangeHighlightDecoration) {
this.clearCurrentFileRangeDecoration();
editor.changeDecorations((changeAccessor: editorCommon.IModelDecorationsChangeAccessor) => {
this.rangeHighlightDecorationId = changeAccessor.addDecoration(selectionRange.range, this.createRangeHighlightDecoration());
});
this.updateEditor(editor);
}
private getEditor(resourceRange: IRangeHighlightDecoration): IEditor {
let editorInput = this.editorService.getActiveEditorInput();
if (editorInput instanceof FileEditorInput) {
if (editorInput.getResource().fsPath === resourceRange.resource.fsPath) {
return this.editorService.getActiveEditor();
}
}
return null;
}
private updateEditor(editor: editorCommon.ICommonCodeEditor) {
if (this.editor !== editor) {
this.disposeEditorListeners();
this.editor = editor;
this.editorDisposables.push(this.editor.onDidChangeCursorPosition((e: editorCommon.ICursorPositionChangedEvent) => {
if (
e.reason === editorCommon.CursorChangeReason.Explicit
|| e.reason === editorCommon.CursorChangeReason.Undo
|| e.reason === editorCommon.CursorChangeReason.Redo
) {
this.doClearRangeDecoration(this.editor, this.rangeHighlightDecorationId);
}
}));
this.editorDisposables.push(this.editor.onDidChangeModel(() => { this.doClearRangeDecoration(this.editor, this.rangeHighlightDecorationId); }));
this.editorDisposables.push(this.editor.onDidDispose(() => {
this.doClearRangeDecoration(this.editor, this.rangeHighlightDecorationId);
this.editor = null;
}));
}
}
private disposeEditorListeners() {
this.editorDisposables.forEach(disposable => disposable.dispose());
this.editorDisposables = [];
}
private doClearRangeDecoration(model: editorCommon.ICommonCodeEditor, rangeHighlightDecorationId: string) {
model.deltaDecorations([rangeHighlightDecorationId], []);
}
private createRangeHighlightDecoration(): editorCommon.IModelDecorationOptions {
return {
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className: 'rangeHighlight',
isWholeLine: true
};
}
public dispose() {
this.clearCurrentFileRangeDecoration();
this.disposeEditorListeners();
this.editor = null;
}
}
\ No newline at end of file
......@@ -34,6 +34,7 @@ import { ActionProvider } from 'vs/workbench/parts/markers/browser/markersAction
import { CollapseAllAction, FilterAction, FilterInputBoxActionItem } from 'vs/workbench/parts/markers/browser/markersPanelActions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import Messages from 'vs/workbench/parts/markers/common/messages';
import { RangeHighlightDecorations, IRangeHighlightDecoration } from 'vs/workbench/common/editor/rangeDecorations';
export class MarkersPanel extends Panel {
......@@ -42,12 +43,13 @@ export class MarkersPanel extends Panel {
private toDispose: lifecycle.IDisposable[];
private delayedRefresh: Delayer<void>;
private lastSelectedRelativeTop: number= 0;
private lastSelectedRelativeTop: number = 0;
private currentActiveFile: URI = null;
private hasToAutoReveal: boolean;
private tree: Tree.ITree;
private autoExpanded: Set.ArraySet<string>;
private rangeHighlightDecorations: RangeHighlightDecorations;
private actions: IAction[];
private filterAction: FilterAction;
......@@ -76,6 +78,9 @@ export class MarkersPanel extends Panel {
super.create(parent);
this.markersModel = new MarkersModel();
this.rangeHighlightDecorations = this.instantiationService.createInstance(RangeHighlightDecorations);
this.toDispose.push(this.rangeHighlightDecorations);
dom.addClass(parent.getHTMLElement(), 'markers-panel');
const conf = this.configurationService.getConfiguration<IProblemsConfiguration>();
......@@ -113,12 +118,21 @@ export class MarkersPanel extends Panel {
if (this.tree.getSelection().length === 0) {
this.tree.focusFirst();
}
this.highlightCurrentSelectedMarkerRange();
this.autoReveal(true);
} else {
this.messageBox.focus();
}
}
public setVisible(visible: boolean): TPromise<void> {
let promise: TPromise<void> = super.setVisible(visible);
if (!visible) {
this.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
return promise;
}
public getActions(): IAction[] {
this.collapseAllAction.enabled = this.markersModel.hasFilteredResources();
return this.actions;
......@@ -156,11 +170,11 @@ export class MarkersPanel extends Panel {
this.treeContainer = dom.append(parent, dom.$('.tree-container'));
var actionProvider = this.instantiationService.createInstance(ActionProvider);
var renderer = this.instantiationService.createInstance(Viewer.Renderer, this.getActionRunner(), actionProvider);
var controller = this.instantiationService.createInstance(Controller);
let controller = this.instantiationService.createInstance(Controller, this.rangeHighlightDecorations);
this.tree = new TreeImpl.Tree(this.treeContainer, {
dataSource: new Viewer.DataSource(),
renderer: renderer,
controller: controller,
renderer,
controller,
accessibilityProvider: new Viewer.MarkersTreeAccessibilityProvider()
}, {
indentPixels: 0,
......@@ -192,6 +206,7 @@ export class MarkersPanel extends Panel {
this.updateResources(changedResources);
this.delayedRefresh.trigger(() => {
this.refreshPanel(true);
this.updateRangeHighlights();
this.autoReveal();
});
}
......@@ -207,9 +222,9 @@ export class MarkersPanel extends Panel {
}
private onSelected(): void {
let selection= this.tree.getSelection();
let selection = this.tree.getSelection();
if (selection && selection.length > 0) {
this.lastSelectedRelativeTop= this.tree.getRelativeTop(selection[0]);
this.lastSelectedRelativeTop = this.tree.getRelativeTop(selection[0]);
}
}
......@@ -247,14 +262,14 @@ export class MarkersPanel extends Panel {
});
}
private autoReveal(focus: boolean= false): void {
private autoReveal(focus: boolean = false): void {
let conf = this.configurationService.getConfiguration<IProblemsConfiguration>();
if (conf && conf.problems && conf.problems.autoReveal) {
this.revealMarkersForCurrentActiveEditor(focus);
}
}
private revealMarkersForCurrentActiveEditor(focus: boolean= false): void {
private revealMarkersForCurrentActiveEditor(focus: boolean = false): void {
let currentActiveResource = this.getResourceForCurrentActiveFile();
if (currentActiveResource) {
if (this.tree.isExpanded(currentActiveResource) && this.hasSelectedMarkerFor(currentActiveResource)) {
......@@ -297,6 +312,20 @@ export class MarkersPanel extends Panel {
return false;
}
private updateRangeHighlights() {
this.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
if (this.tree.isDOMFocused()) {
this.highlightCurrentSelectedMarkerRange();
}
}
private highlightCurrentSelectedMarkerRange() {
let selections = this.tree.getSelection();
if (selections && selections.length === 1 && selections[0] instanceof Marker) {
this.rangeHighlightDecorations.highlightRange(<IRangeHighlightDecoration>selections[0]);
}
}
public getActionItem(action: Action): IActionItem {
if (action.id === FilterAction.ID) {
return this.instantiationService.createInstance(FilterInputBoxActionItem, this, action);
......
......@@ -10,19 +10,20 @@ import keyboard = require('vs/base/browser/keyboardEvent');
import tree = require('vs/base/parts/tree/browser/tree');
import treedefaults = require('vs/base/parts/tree/browser/treeDefaults');
import { MarkersModel, Marker } from 'vs/workbench/parts/markers/common/markersModel';
import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IMarker } from 'vs/platform/markers/common/markers';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
export class Controller extends treedefaults.DefaultController {
constructor(@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@ITelemetryService private telemetryService: ITelemetryService) {
constructor(private rangeHighlightDecorations: RangeHighlightDecorations, @IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@ITelemetryService private telemetryService: ITelemetryService) {
super();
}
protected onLeftClick(tree: tree.ITree, element: any, event: mouse.IMouseEvent): boolean {
let currentFoucssed= tree.getFocus();
let currentFoucssed = tree.getFocus();
if (super.onLeftClick(tree, element, event)) {
if (this.openFileAtElement(element, event.detail !== 2, event.ctrlKey || event.metaKey, event.detail === 2)) {
return true;
......@@ -47,17 +48,19 @@ export class Controller extends treedefaults.DefaultController {
}
protected onSpace(tree: tree.ITree, event: keyboard.IKeyboardEvent): boolean {
let element= tree.getFocus();
let element = tree.getFocus();
if (element instanceof Marker) {
tree.setSelection([element]);
return this.openFileAtElement(tree.getFocus(), true, false, false);
} else {
this.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
return super.onSpace(tree, event);
}
private openFileAtElement(element: any, preserveFocus: boolean, sideByside: boolean, pinned: boolean): boolean {
if (element instanceof Marker) {
this.telemetryService.publicLog('problems.marker.opened', {source: element.source});
this.telemetryService.publicLog('problems.marker.opened', { source: element.source });
let marker = <IMarker>element.marker;
this.editorService.openEditor({
resource: marker.resource,
......@@ -72,9 +75,17 @@ export class Controller extends treedefaults.DefaultController {
pinned,
revealIfVisible: true
},
}, sideByside).done(null, errors.onUnexpectedError);
}, sideByside).done((editor) => {
if (preserveFocus) {
this.rangeHighlightDecorations.highlightRange(element, editor);
} else {
this.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
}, errors.onUnexpectedError);
return true;
} else {
this.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
return false;
}
}
}
\ No newline at end of file
......@@ -28,7 +28,15 @@ export class Resource {
export class Marker {
constructor(public id:string, public marker: IMarker,
public labelMatches: IMatch[] = [],
public sourceMatches: IMatch[] = []){}
public sourceMatches: IMatch[] = []) { }
public get resource(): URI {
return this.marker.resource;
}
public get range(): Range {
return new Range(this.marker.startLineNumber, this.marker.startColumn, this.marker.endLineNumber, this.marker.endLineNumber);
}
}
export class FilterOptions {
......
......@@ -900,6 +900,7 @@ export class SearchViewlet extends Viewlet {
private onFocus(lineMatch: any, preserveFocus?: boolean, sideBySide?: boolean, pinned?: boolean): TPromise<any> {
if (!(lineMatch instanceof Match)) {
this.viewModel.searchResult.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
return TPromise.as(true);
}
......@@ -919,7 +920,16 @@ export class SearchViewlet extends Viewlet {
selection,
revealIfVisible: true
}
}, sideBySide);
}, sideBySide).then((editor) => {
if (element instanceof Match && preserveFocus) {
this.viewModel.searchResult.rangeHighlightDecorations.highlightRange({
resource,
range: element.range()
}, editor);
} else {
this.viewModel.searchResult.rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
}, errors.onUnexpectedError);
}
private getSelectionFrom(element: FileMatchOrMatch): any {
......
......@@ -25,6 +25,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ISearchService } from 'vs/platform/search/common/search';
import { IReplaceService } from 'vs/workbench/parts/search/common/replace';
import { IProgressRunner } from 'vs/platform/progress/common/progress';
import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations';
export class Match {
......@@ -311,11 +312,14 @@ export class SearchResult extends Disposable {
private _showHighlights: boolean;
private _replacingAll: boolean = false;
private _rangeHighlightDecorations: RangeHighlightDecorations;
constructor(private _searchModel: SearchModel, @IReplaceService private replaceService: IReplaceService, @ITelemetryService private telemetryService: ITelemetryService,
@IInstantiationService private instantiationService: IInstantiationService) {
super();
this._fileMatches = new LinkedMap<URI, FileMatch>();
this._unDisposedFileMatches = new LinkedMap<URI, FileMatch>();
this._rangeHighlightDecorations = this.instantiationService.createInstance(RangeHighlightDecorations);
}
public set query(query: Search.IPatternInfo) {
......@@ -398,9 +402,25 @@ export class SearchResult extends Disposable {
return;
}
this._showHighlights = value;
let selectedMatch:Match = null;
this.matches().forEach((fileMatch: FileMatch) => {
fileMatch.updateHighlights();
if (!selectedMatch) {
selectedMatch = fileMatch.getSelectedMatch();
}
});
if (this._showHighlights && selectedMatch) {
this._rangeHighlightDecorations.highlightRange({
resource: selectedMatch.parent().resource(),
range: selectedMatch.range()
});
} else {
this._rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
}
public get rangeHighlightDecorations(): RangeHighlightDecorations {
return this._rangeHighlightDecorations;
}
private onFileChange(fileMatch: FileMatch): void {
......@@ -445,10 +465,12 @@ export class SearchResult extends Disposable {
this._unDisposedFileMatches.values().forEach((fileMatch: FileMatch) => fileMatch.dispose());
this._fileMatches.clear();
this._unDisposedFileMatches.clear();
this._rangeHighlightDecorations.clearCurrentFileRangeDecoration();
}
public dispose(): void {
this.disposeMatches();
this._rangeHighlightDecorations.dispose();
super.dispose();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册