提交 4031280b 编写于 作者: B Benjamin Pasero

Go to symbol in editor, open to side should reset scroll position in original editor (fix #111346)

上级 5e6a2779
......@@ -26,6 +26,20 @@ export interface IEditorNavigationQuickAccessOptions {
canAcceptInBackground?: boolean;
}
export interface IQuickAccessTextEditorContext {
/**
* The current active editor.
*/
readonly editor: IEditor;
/**
* If defined, allows to restore the original view state
* the text editor had before quick access opened.
*/
restoreViewState?: () => void;
}
/**
* A reusable quick access provider for the editor with support
* for adding decorations for navigating in the currently active file
......@@ -69,6 +83,7 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu
// With text control
const editor = this.activeTextEditorControl;
if (editor && this.canProvideWithTextEditor(editor)) {
const context: IQuickAccessTextEditorContext = { editor };
// Restore any view state if this picker was closed
// without actually going to a line
......@@ -84,18 +99,20 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu
lastKnownEditorViewState = withNullAsUndefined(editor.saveViewState());
}));
disposables.add(once(token.onCancellationRequested)(() => {
context.restoreViewState = () => {
if (lastKnownEditorViewState && editor === this.activeTextEditorControl) {
editor.restoreViewState(lastKnownEditorViewState);
}
}));
};
disposables.add(once(token.onCancellationRequested)(() => context.restoreViewState?.()));
}
// Clean up decorations on dispose
disposables.add(toDisposable(() => this.clearDecorations(editor)));
// Ask subclass for entries
disposables.add(this.provideWithTextEditor(editor, picker, token));
disposables.add(this.provideWithTextEditor(context, picker, token));
}
// Without text control
......@@ -116,14 +133,14 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu
/**
* Subclasses to implement to provide picks for the picker when an editor is active.
*/
protected abstract provideWithTextEditor(editor: IEditor, picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable;
protected abstract provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable;
/**
* Subclasses to implement to provide picks for the picker when no editor is active.
*/
protected abstract provideWithoutTextEditor(picker: IQuickPick<IQuickPickItem>, token: CancellationToken): IDisposable;
protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
protected gotoLocation({ editor }: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
editor.setSelection(options.range);
editor.revealRangeInCenter(options.range, ScrollType.Smooth);
if (!options.preserveFocus) {
......
......@@ -9,7 +9,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IEditor, ScrollType } from 'vs/editor/common/editorCommon';
import { IRange } from 'vs/editor/common/core/range';
import { AbstractEditorNavigationQuickAccessProvider } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
import { AbstractEditorNavigationQuickAccessProvider, IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
import { IPosition } from 'vs/editor/common/core/position';
import { getCodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorOption, RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
......@@ -33,7 +33,8 @@ export abstract class AbstractGotoLineQuickAccessProvider extends AbstractEditor
return Disposable.None;
}
protected provideWithTextEditor(editor: IEditor, picker: IQuickPick<IGotoLineQuickPickItem>, token: CancellationToken): IDisposable {
protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick<IGotoLineQuickPickItem>, token: CancellationToken): IDisposable {
const editor = context.editor;
const disposables = new DisposableStore();
// Goto line once picked
......@@ -44,7 +45,7 @@ export abstract class AbstractGotoLineQuickAccessProvider extends AbstractEditor
return;
}
this.gotoLocation(editor, { range: this.toRange(item.lineNumber, item.column), keyMods: picker.keyMods, preserveFocus: event.inBackground });
this.gotoLocation(context, { range: this.toRange(item.lineNumber, item.column), keyMods: picker.keyMods, preserveFocus: event.inBackground });
if (!event.inBackground) {
picker.hide();
......
......@@ -7,10 +7,10 @@ import { localize } from 'vs/nls';
import { IQuickPick, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IEditor, ScrollType } from 'vs/editor/common/editorCommon';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { IRange, Range } from 'vs/editor/common/core/range';
import { AbstractEditorNavigationQuickAccessProvider, IEditorNavigationQuickAccessOptions } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
import { AbstractEditorNavigationQuickAccessProvider, IEditorNavigationQuickAccessOptions, IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
import { DocumentSymbol, SymbolKinds, SymbolTag, DocumentSymbolProviderRegistry, SymbolKind } from 'vs/editor/common/modes';
import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
import { trim, format } from 'vs/base/common/strings';
......@@ -48,7 +48,8 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return Disposable.None;
}
protected provideWithTextEditor(editor: IEditor, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
const editor = context.editor;
const model = this.getModel(editor);
if (!model) {
return Disposable.None;
......@@ -56,16 +57,16 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
// Provide symbols from model if available in registry
if (DocumentSymbolProviderRegistry.has(model)) {
return this.doProvideWithEditorSymbols(editor, model, picker, token);
return this.doProvideWithEditorSymbols(context, model, picker, token);
}
// Otherwise show an entry for a model without registry
// But give a chance to resolve the symbols at a later
// point if possible
return this.doProvideWithoutEditorSymbols(editor, model, picker, token);
return this.doProvideWithoutEditorSymbols(context, model, picker, token);
}
private doProvideWithoutEditorSymbols(editor: IEditor, model: ITextModel, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
private doProvideWithoutEditorSymbols(context: IQuickAccessTextEditorContext, model: ITextModel, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
const disposables = new DisposableStore();
// Generic pick for not having any symbol information
......@@ -82,7 +83,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return;
}
disposables.add(this.doProvideWithEditorSymbols(editor, model, picker, token));
disposables.add(this.doProvideWithEditorSymbols(context, model, picker, token));
})();
return disposables;
......@@ -116,14 +117,15 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
return symbolProviderRegistryPromise;
}
private doProvideWithEditorSymbols(editor: IEditor, model: ITextModel, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
private doProvideWithEditorSymbols(context: IQuickAccessTextEditorContext, model: ITextModel, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
const editor = context.editor;
const disposables = new DisposableStore();
// Goto symbol once picked
disposables.add(picker.onDidAccept(event => {
const [item] = picker.selectedItems;
if (item && item.range) {
this.gotoLocation(editor, { range: item.range.selection, keyMods: picker.keyMods, preserveFocus: event.inBackground });
this.gotoLocation(context, { range: item.range.selection, keyMods: picker.keyMods, preserveFocus: event.inBackground });
if (!event.inBackground) {
picker.hide();
......@@ -134,7 +136,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
// Goto symbol side by side if enabled
disposables.add(picker.onDidTriggerItemButton(({ item }) => {
if (item && item.range) {
this.gotoLocation(editor, { range: item.range.selection, keyMods: picker.keyMods, forceSideBySide: true });
this.gotoLocation(context, { range: item.range.selection, keyMods: picker.keyMods, forceSideBySide: true });
picker.hide();
}
......
......@@ -5,7 +5,6 @@
import { localize } from 'vs/nls';
import { IKeyMods, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IEditor } from 'vs/editor/common/editorCommon';
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IRange } from 'vs/editor/common/core/range';
import { AbstractGotoLineQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoLineQuickAccess';
......@@ -17,6 +16,7 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProvider {
......@@ -41,10 +41,12 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv
return this.editorService.activeTextEditorControl;
}
protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
// Check for sideBySide use
if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) {
context.restoreViewState?.(); // since we open to the side, restore view state in this editor
this.editorService.openEditor(this.editorService.activeEditor, {
selection: options.range,
pinned: options.keyMods.alt || this.configuration.openEditorPinned,
......@@ -54,7 +56,7 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv
// Otherwise let parent handle it
else {
super.gotoLocation(editor, options);
super.gotoLocation(context, options);
}
}
}
......
......@@ -26,6 +26,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess';
export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider {
......@@ -42,11 +43,12 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
//#region DocumentSymbols (text editor required)
protected provideWithTextEditor(editor: IEditor, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
protected provideWithTextEditor(context: IQuickAccessTextEditorContext, picker: IQuickPick<IGotoSymbolQuickPickItem>, token: CancellationToken): IDisposable {
if (this.canPickFromTableOfContents()) {
return this.doGetTableOfContentsPicks(picker);
}
return super.provideWithTextEditor(editor, picker, token);
return super.provideWithTextEditor(context, picker, token);
}
private get configuration() {
......@@ -62,10 +64,12 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
return this.editorService.activeTextEditorControl;
}
protected gotoLocation(editor: IEditor, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
protected gotoLocation(context: IQuickAccessTextEditorContext, options: { range: IRange, keyMods: IKeyMods, forceSideBySide?: boolean, preserveFocus?: boolean }): void {
// Check for sideBySide use
if ((options.keyMods.ctrlCmd || options.forceSideBySide) && this.editorService.activeEditor) {
context.restoreViewState?.(); // since we open to the side, restore view state in this editor
this.editorService.openEditor(this.editorService.activeEditor, {
selection: options.range,
pinned: options.keyMods.alt || this.configuration.openEditorPinned,
......@@ -75,7 +79,7 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess
// Otherwise let parent handle it
else {
super.gotoLocation(editor, options);
super.gotoLocation(context, options);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册