Skip to content

Commit

Permalink
Highlight symbol in text on click.
Browse files Browse the repository at this point in the history
  • Loading branch information
mihailik committed Jul 24, 2017
1 parent 8c12e4e commit 5f0224b
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 17 deletions.
26 changes: 26 additions & 0 deletions src/vs/editor/browser/codeEditor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

@keyframes navigation-symbol-highlight-pulse {
0%, 100% {
border-color: transparent;
box-shadow: 0px 0px 13px 3px transparent;
}

50% {
border-color: orange;
box-shadow: 0px 0px 13px 3px orange;
}
}

.navigation-symbol-highlight {
border: solid 1px transparent;
padding-left: 6px; padding-right: 6px;
margin-left: -7px; margin-right: -7px;
border-radius: 12px;
box-shadow: 0px 0px 13px 3px transparent;

animation: 500ms navigation-symbol-highlight-pulse;
}
106 changes: 89 additions & 17 deletions src/vs/editor/browser/codeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import 'vs/css!./codeEditor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
Expand All @@ -16,7 +17,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { Range, IRange } from 'vs/editor/common/core/range';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
Expand Down Expand Up @@ -224,6 +225,91 @@ export class CodeEditor extends CodeEditorWidget {
this.updateWithBreadcrumbSymbols(matchingSymbols);
}

private highlighted: string;
private toHighlightRange: IRange;
private highlightQueued: boolean;
private queueDehighlight: any;

private highightSymbol(symbol: SymbolInformation, highlightRange: IRange) {
if (this.queueDehighlight) {
clearTimeout(this.queueDehighlight);
}

this.toHighlightRange = highlightRange;

if (!this.highlightQueued) {
this.highlightQueued = true;
this.changeDecorations(changeAccessor => {
this.highlightQueued = false;

if (this.highlighted) {
changeAccessor.removeDecoration(this.highlighted);
this.highlighted = null;
}

if (this.toHighlightRange) {
const highlightId = changeAccessor.addDecoration(
this.toHighlightRange,
{
inlineClassName: 'navigation-symbol-highlight'
});
this.highlighted = highlightId;
this.toHighlightRange = null;
this.queueDehighlight = setTimeout(() => {
this.highightSymbol(null, null);
}, 500);
}
});
}
}

private symbolClick(symbol: SymbolInformation) {

this.highightSymbol(null, null);

let newPos = {
lineNumber: symbol.location.range.startLineNumber,
column: symbol.location.range.startColumn
};

const model = this.getModel();

if (model) {
let symStartLineNumber = newPos.lineNumber;
let selectionLine = model.getLineContent(symStartLineNumber);
let symStartColumn = selectionLine.indexOf(symbol.name);
if (symStartColumn < 0 && symbol.location.range.endLineNumber > symbol.location.range.startLineNumber) {
symStartLineNumber++;
selectionLine = model.getLineContent(symStartLineNumber);
symStartColumn = selectionLine.indexOf(symbol.name);
}

if (symStartColumn >= 0) {
let highlightRange = new Range(
symStartLineNumber, symStartColumn + 1,
symStartLineNumber, symStartColumn + 1 + symbol.name.length);
newPos = {
lineNumber: highlightRange.startLineNumber,
column: highlightRange.startColumn
};

this.highightSymbol(symbol, highlightRange);
}
}

this.setPosition(newPos);
const visibleRange = this.getCompletelyVisibleLinesRangeInViewport();
if (!this.positionWithinRange(newPos, visibleRange)) {
const posTop = this.getTopForLineNumber(newPos.lineNumber);
this.setScrollTop(posTop - 10);
}

setTimeout(() => {
this.focus();
}, 1);

}

private updateWithBreadcrumbSymbols(matchingSymbols: SymbolInformation[]) {
const highlightSymbol = matchingSymbols[matchingSymbols.length - 1];
let extraSymbolsTrail: SymbolInformation[];
Expand Down Expand Up @@ -287,22 +373,7 @@ export class CodeEditor extends CodeEditorWidget {
symSpan.style.opacity = '0.7';
}

symSpan.onclick = () => {
const newPos = {
lineNumber: sym.location.range.startLineNumber,
column: sym.location.range.startColumn
};
this.setPosition(newPos);
const visibleRange = this.getCompletelyVisibleLinesRangeInViewport();
if (!this.positionWithinRange(newPos, visibleRange)) {
const posTop = this.getTopForLineNumber(newPos.lineNumber);
this.setScrollTop(posTop - 10);
}

setTimeout(() => {
this.focus();
}, 1);
};
symSpan.onclick = () => this.symbolClick(sym);
symSpan.textContent = sym.name;
symSpan.title = SymbolKind[sym.kind] + ' @' + sym.containerName;
this.toolbarDomElement.appendChild(symSpan);
Expand Down Expand Up @@ -343,6 +414,7 @@ export class CodeEditor extends CodeEditorWidget {
this.disposeContentEditEvent = model.onDidChangeContent(() => {
this.allSymbolsSorted = null;
this.queueUpdateToolbar();
this.highightSymbol(null, null);
});
}
}
Expand Down

0 comments on commit 5f0224b

Please sign in to comment.