mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 01:25:37 -05:00
640 lines
24 KiB
TypeScript
640 lines
24 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as dom from 'vs/base/browser/dom';
|
|
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
|
import { ISashEvent, IVerticalSashLayoutProvider, Sash } from 'vs/base/browser/ui/sash/sash';
|
|
import { Color } from 'vs/base/common/color';
|
|
import { Emitter, Event } from 'vs/base/common/event';
|
|
import { dispose, IDisposable, IReference } from 'vs/base/common/lifecycle';
|
|
import { Schemas } from 'vs/base/common/network';
|
|
import { basenameOrAuthority, dirname } from 'vs/base/common/resources';
|
|
import 'vs/css!./media/referencesWidget';
|
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
|
import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
|
|
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
|
import { IRange, Range } from 'vs/editor/common/core/range';
|
|
import * as editorCommon from 'vs/editor/common/editorCommon';
|
|
import { IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/model';
|
|
import { ModelDecorationOptions, TextModel } from 'vs/editor/common/model/textModel';
|
|
import { Location } from 'vs/editor/common/modes';
|
|
import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
|
import { AriaProvider, DataSource, Delegate, FileReferencesRenderer, OneReferenceRenderer, TreeElement } from 'vs/editor/contrib/referenceSearch/referencesTree';
|
|
import * as nls from 'vs/nls';
|
|
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
import { ILabelService } from 'vs/platform/label/common/label';
|
|
import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
|
import { activeContrastBorder, contrastBorder, registerColor } from 'vs/platform/theme/common/colorRegistry';
|
|
import { ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
|
import { PeekViewWidget } from './peekViewWidget';
|
|
import { FileReferences, OneReference, ReferencesModel } from './referencesModel';
|
|
|
|
class DecorationsManager implements IDisposable {
|
|
|
|
private static readonly DecorationOptions = ModelDecorationOptions.register({
|
|
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
|
className: 'reference-decoration'
|
|
});
|
|
|
|
private _decorations = new Map<string, OneReference>();
|
|
private _decorationIgnoreSet = new Set<string>();
|
|
private _callOnDispose: IDisposable[] = [];
|
|
private _callOnModelChange: IDisposable[] = [];
|
|
|
|
constructor(private _editor: ICodeEditor, private _model: ReferencesModel) {
|
|
this._callOnDispose.push(this._editor.onDidChangeModel(() => this._onModelChanged()));
|
|
this._onModelChanged();
|
|
}
|
|
|
|
public dispose(): void {
|
|
this._callOnModelChange = dispose(this._callOnModelChange);
|
|
this._callOnDispose = dispose(this._callOnDispose);
|
|
this.removeDecorations();
|
|
}
|
|
|
|
private _onModelChanged(): void {
|
|
this._callOnModelChange = dispose(this._callOnModelChange);
|
|
const model = this._editor.getModel();
|
|
if (model) {
|
|
for (const ref of this._model.groups) {
|
|
if (ref.uri.toString() === model.uri.toString()) {
|
|
this._addDecorations(ref);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private _addDecorations(reference: FileReferences): void {
|
|
this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged()));
|
|
|
|
const newDecorations: IModelDeltaDecoration[] = [];
|
|
const newDecorationsActualIndex: number[] = [];
|
|
|
|
for (let i = 0, len = reference.children.length; i < len; i++) {
|
|
let oneReference = reference.children[i];
|
|
if (this._decorationIgnoreSet.has(oneReference.id)) {
|
|
continue;
|
|
}
|
|
newDecorations.push({
|
|
range: oneReference.range,
|
|
options: DecorationsManager.DecorationOptions
|
|
});
|
|
newDecorationsActualIndex.push(i);
|
|
}
|
|
|
|
const decorations = this._editor.deltaDecorations([], newDecorations);
|
|
for (let i = 0; i < decorations.length; i++) {
|
|
this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]);
|
|
}
|
|
}
|
|
|
|
private _onDecorationChanged(): void {
|
|
const toRemove: string[] = [];
|
|
|
|
this._decorations.forEach((reference, decorationId) => {
|
|
const newRange = this._editor.getModel().getDecorationRange(decorationId);
|
|
|
|
if (!newRange) {
|
|
return;
|
|
}
|
|
|
|
let ignore = false;
|
|
|
|
if (Range.equalsRange(newRange, reference.range)) {
|
|
return;
|
|
|
|
} else if (Range.spansMultipleLines(newRange)) {
|
|
ignore = true;
|
|
|
|
} else {
|
|
const lineLength = reference.range.endColumn - reference.range.startColumn;
|
|
const newLineLength = newRange.endColumn - newRange.startColumn;
|
|
|
|
if (lineLength !== newLineLength) {
|
|
ignore = true;
|
|
}
|
|
}
|
|
|
|
if (ignore) {
|
|
this._decorationIgnoreSet.add(reference.id);
|
|
toRemove.push(decorationId);
|
|
} else {
|
|
reference.range = newRange;
|
|
}
|
|
});
|
|
|
|
for (let i = 0, len = toRemove.length; i < len; i++) {
|
|
this._decorations.delete(toRemove[i]);
|
|
}
|
|
this._editor.deltaDecorations(toRemove, []);
|
|
}
|
|
|
|
public removeDecorations(): void {
|
|
let toRemove: string[] = [];
|
|
this._decorations.forEach((value, key) => {
|
|
toRemove.push(key);
|
|
});
|
|
this._editor.deltaDecorations(toRemove, []);
|
|
this._decorations.clear();
|
|
}
|
|
}
|
|
|
|
class VSash {
|
|
|
|
private _disposables: IDisposable[] = [];
|
|
private _sash: Sash;
|
|
private _ratio: number;
|
|
private _height: number;
|
|
private _width: number;
|
|
private _onDidChangePercentages = new Emitter<VSash>();
|
|
|
|
constructor(container: HTMLElement, ratio: number) {
|
|
this._ratio = ratio;
|
|
this._sash = new Sash(container, <IVerticalSashLayoutProvider>{
|
|
getVerticalSashLeft: () => this._width * this._ratio,
|
|
getVerticalSashHeight: () => this._height
|
|
});
|
|
|
|
// compute the current widget clientX postion since
|
|
// the sash works with clientX when dragging
|
|
let clientX: number;
|
|
this._disposables.push(this._sash.onDidStart((e: ISashEvent) => {
|
|
clientX = e.startX - (this._width * this.ratio);
|
|
}));
|
|
|
|
this._disposables.push(this._sash.onDidChange((e: ISashEvent) => {
|
|
// compute the new position of the sash and from that
|
|
// compute the new ratio that we are using
|
|
let newLeft = e.currentX - clientX;
|
|
if (newLeft > 20 && newLeft + 20 < this._width) {
|
|
this._ratio = newLeft / this._width;
|
|
this._sash.layout();
|
|
this._onDidChangePercentages.fire(this);
|
|
}
|
|
}));
|
|
}
|
|
|
|
dispose() {
|
|
this._sash.dispose();
|
|
this._onDidChangePercentages.dispose();
|
|
dispose(this._disposables);
|
|
}
|
|
|
|
get onDidChangePercentages() {
|
|
return this._onDidChangePercentages.event;
|
|
}
|
|
|
|
set width(value: number) {
|
|
this._width = value;
|
|
this._sash.layout();
|
|
}
|
|
|
|
set height(value: number) {
|
|
this._height = value;
|
|
this._sash.layout();
|
|
}
|
|
|
|
get percentages() {
|
|
let left = 100 * this._ratio;
|
|
let right = 100 - left;
|
|
return [`${left}%`, `${right}%`];
|
|
}
|
|
|
|
get ratio() {
|
|
return this._ratio;
|
|
}
|
|
}
|
|
|
|
export interface LayoutData {
|
|
ratio: number;
|
|
heightInLines: number;
|
|
}
|
|
|
|
export interface SelectionEvent {
|
|
kind: 'goto' | 'show' | 'side' | 'open';
|
|
source: 'editor' | 'tree' | 'title';
|
|
element: Location;
|
|
}
|
|
|
|
export const ctxReferenceWidgetSearchTreeFocused = new RawContextKey<boolean>('referenceSearchTreeFocused', true);
|
|
|
|
/**
|
|
* ZoneWidget that is shown inside the editor
|
|
*/
|
|
export class ReferenceWidget extends PeekViewWidget {
|
|
|
|
private _model: ReferencesModel;
|
|
private _decorationsManager: DecorationsManager;
|
|
|
|
private _disposeOnNewModel: IDisposable[] = [];
|
|
private _callOnDispose: IDisposable[] = [];
|
|
private _onDidSelectReference = new Emitter<SelectionEvent>();
|
|
|
|
private _treeDataSource: DataSource;
|
|
private _tree: WorkbenchAsyncDataTree<TreeElement>;
|
|
private _treeContainer: HTMLElement;
|
|
private _sash: VSash;
|
|
private _preview: ICodeEditor;
|
|
private _previewModelReference: IReference<ITextEditorModel>;
|
|
private _previewNotAvailableMessage: TextModel;
|
|
private _previewContainer: HTMLElement;
|
|
private _messageContainer: HTMLElement;
|
|
|
|
constructor(
|
|
editor: ICodeEditor,
|
|
private _defaultTreeKeyboardSupport: boolean,
|
|
public layoutData: LayoutData,
|
|
@IThemeService themeService: IThemeService,
|
|
@ITextModelService private readonly _textModelResolverService: ITextModelService,
|
|
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
|
@ILabelService private readonly _uriLabel: ILabelService
|
|
) {
|
|
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true });
|
|
|
|
this._applyTheme(themeService.getTheme());
|
|
this._callOnDispose.push(themeService.onThemeChange(this._applyTheme.bind(this)));
|
|
this.create();
|
|
}
|
|
|
|
private _applyTheme(theme: ITheme) {
|
|
const borderColor = theme.getColor(peekViewBorder) || Color.transparent;
|
|
this.style({
|
|
arrowColor: borderColor,
|
|
frameColor: borderColor,
|
|
headerBackgroundColor: theme.getColor(peekViewTitleBackground) || Color.transparent,
|
|
primaryHeadingColor: theme.getColor(peekViewTitleForeground),
|
|
secondaryHeadingColor: theme.getColor(peekViewTitleInfoForeground)
|
|
});
|
|
}
|
|
|
|
public dispose(): void {
|
|
this.setModel(null);
|
|
this._callOnDispose = dispose(this._callOnDispose);
|
|
dispose<IDisposable>(this._preview, this._previewNotAvailableMessage, this._tree, this._sash, this._previewModelReference);
|
|
super.dispose();
|
|
}
|
|
|
|
get onDidSelectReference(): Event<SelectionEvent> {
|
|
return this._onDidSelectReference.event;
|
|
}
|
|
|
|
show(where: IRange) {
|
|
this.editor.revealRangeInCenterIfOutsideViewport(where, editorCommon.ScrollType.Smooth);
|
|
super.show(where, this.layoutData.heightInLines || 18);
|
|
}
|
|
|
|
focus(): void {
|
|
this._tree.domFocus();
|
|
}
|
|
|
|
protected _onTitleClick(e: IMouseEvent): void {
|
|
if (this._preview && this._preview.getModel()) {
|
|
this._onDidSelectReference.fire({
|
|
element: this._getFocusedReference(),
|
|
kind: e.ctrlKey || e.metaKey || e.altKey ? 'side' : 'open',
|
|
source: 'title'
|
|
});
|
|
}
|
|
}
|
|
|
|
protected _fillBody(containerElement: HTMLElement): void {
|
|
this.setCssClass('reference-zone-widget');
|
|
|
|
// message pane
|
|
this._messageContainer = dom.append(containerElement, dom.$('div.messages'));
|
|
dom.hide(this._messageContainer);
|
|
|
|
// editor
|
|
this._previewContainer = dom.append(containerElement, dom.$('div.preview.inline'));
|
|
let options: IEditorOptions = {
|
|
scrollBeyondLastLine: false,
|
|
scrollbar: {
|
|
verticalScrollbarSize: 14,
|
|
horizontal: 'auto',
|
|
useShadows: true,
|
|
verticalHasArrows: false,
|
|
horizontalHasArrows: false
|
|
},
|
|
overviewRulerLanes: 2,
|
|
fixedOverflowWidgets: true,
|
|
minimap: {
|
|
enabled: false
|
|
}
|
|
};
|
|
this._preview = this._instantiationService.createInstance(EmbeddedCodeEditorWidget, this._previewContainer, options, this.editor);
|
|
dom.hide(this._previewContainer);
|
|
this._previewNotAvailableMessage = TextModel.createFromString(nls.localize('missingPreviewMessage', "no preview available"));
|
|
|
|
// sash
|
|
this._sash = new VSash(containerElement, this.layoutData.ratio || .8);
|
|
this._sash.onDidChangePercentages(() => {
|
|
let [left, right] = this._sash.percentages;
|
|
this._previewContainer.style.width = left;
|
|
this._treeContainer.style.width = right;
|
|
this._preview.layout();
|
|
this._tree.layout();
|
|
this.layoutData.ratio = this._sash.ratio;
|
|
});
|
|
|
|
// tree
|
|
this._treeContainer = dom.append(containerElement, dom.$('div.ref-tree.inline'));
|
|
|
|
const renderer = [
|
|
this._instantiationService.createInstance(FileReferencesRenderer),
|
|
this._instantiationService.createInstance(OneReferenceRenderer),
|
|
];
|
|
|
|
const treeOptions = {
|
|
ariaLabel: nls.localize('treeAriaLabel', "References"),
|
|
keyboardSupport: this._defaultTreeKeyboardSupport,
|
|
accessibilityProvider: new AriaProvider()
|
|
};
|
|
|
|
this._treeDataSource = this._instantiationService.createInstance(DataSource);
|
|
|
|
this._tree = this._instantiationService.createInstance(
|
|
WorkbenchAsyncDataTree, this._treeContainer, new Delegate(),
|
|
renderer as any,
|
|
this._treeDataSource,
|
|
treeOptions
|
|
) as any as WorkbenchAsyncDataTree<TreeElement>;
|
|
|
|
ctxReferenceWidgetSearchTreeFocused.bindTo(this._tree.contextKeyService);
|
|
|
|
// listen on selection and focus
|
|
let onEvent = (element: any, kind: 'show' | 'goto' | 'side') => {
|
|
if (element instanceof OneReference) {
|
|
if (kind === 'show') {
|
|
this._revealReference(element, false);
|
|
}
|
|
this._onDidSelectReference.fire({ element, kind, source: 'tree' });
|
|
}
|
|
};
|
|
this._tree.onDidChangeFocus(e => {
|
|
onEvent(e.elements[0], 'show');
|
|
});
|
|
this._tree.onDidChangeSelection(e => {
|
|
let aside = false;
|
|
let goto = false;
|
|
if (e.browserEvent instanceof KeyboardEvent) {
|
|
// todo@joh make this a command
|
|
goto = true;
|
|
|
|
} else if (e.browserEvent instanceof MouseEvent) {
|
|
aside = e.browserEvent.metaKey || e.browserEvent.metaKey || e.browserEvent.altKey;
|
|
goto = e.browserEvent.detail === 2;
|
|
}
|
|
if (aside) {
|
|
onEvent(e.elements[0], 'side');
|
|
} else if (goto) {
|
|
onEvent(e.elements[0], 'goto');
|
|
} else {
|
|
onEvent(e.elements[0], 'show');
|
|
}
|
|
});
|
|
|
|
dom.hide(this._treeContainer);
|
|
}
|
|
|
|
protected _doLayoutBody(heightInPixel: number, widthInPixel: number): void {
|
|
super._doLayoutBody(heightInPixel, widthInPixel);
|
|
|
|
const height = heightInPixel + 'px';
|
|
this._sash.height = heightInPixel;
|
|
this._sash.width = widthInPixel;
|
|
|
|
// set height/width
|
|
const [left, right] = this._sash.percentages;
|
|
this._previewContainer.style.height = height;
|
|
this._previewContainer.style.width = left;
|
|
this._treeContainer.style.height = height;
|
|
this._treeContainer.style.width = right;
|
|
// forward
|
|
this._tree.layout(heightInPixel);
|
|
this._preview.layout();
|
|
|
|
// store layout data
|
|
this.layoutData = {
|
|
heightInLines: this._viewZone.heightInLines,
|
|
ratio: this._sash.ratio
|
|
};
|
|
}
|
|
|
|
public _onWidth(widthInPixel: number): void {
|
|
this._sash.width = widthInPixel;
|
|
this._preview.layout();
|
|
}
|
|
|
|
public setSelection(selection: OneReference): Promise<any> {
|
|
return this._revealReference(selection, true).then(() => {
|
|
if (!this._model) {
|
|
// disposed
|
|
return;
|
|
}
|
|
// show in tree
|
|
this._tree.setSelection([selection]);
|
|
this._tree.setFocus([selection]);
|
|
});
|
|
}
|
|
|
|
public setModel(newModel: ReferencesModel): Thenable<any> {
|
|
// clean up
|
|
this._disposeOnNewModel = dispose(this._disposeOnNewModel);
|
|
this._model = newModel;
|
|
if (this._model) {
|
|
return this._onNewModel();
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
private _onNewModel(): Thenable<any> {
|
|
|
|
if (this._model.empty) {
|
|
this.setTitle('');
|
|
this._messageContainer.innerHTML = nls.localize('noResults', "No results");
|
|
dom.show(this._messageContainer);
|
|
return Promise.resolve(void 0);
|
|
}
|
|
|
|
dom.hide(this._messageContainer);
|
|
this._decorationsManager = new DecorationsManager(this._preview, this._model);
|
|
this._disposeOnNewModel.push(this._decorationsManager);
|
|
|
|
// listen on model changes
|
|
this._disposeOnNewModel.push(this._model.onDidChangeReferenceRange(reference => this._tree.refresh(reference)));
|
|
|
|
// listen on editor
|
|
this._disposeOnNewModel.push(this._preview.onMouseDown(e => {
|
|
const { event, target } = e;
|
|
if (event.detail !== 2) {
|
|
return;
|
|
}
|
|
const element = this._getFocusedReference();
|
|
if (!element) {
|
|
return;
|
|
}
|
|
this._onDidSelectReference.fire({
|
|
element: { uri: element.uri, range: target.range },
|
|
kind: (event.ctrlKey || event.metaKey || event.altKey) ? 'side' : 'open',
|
|
source: 'editor'
|
|
});
|
|
}));
|
|
|
|
// make sure things are rendered
|
|
dom.addClass(this.container, 'results-loaded');
|
|
dom.show(this._treeContainer);
|
|
dom.show(this._previewContainer);
|
|
this._preview.layout();
|
|
this._tree.layout();
|
|
this.focus();
|
|
|
|
// pick input and a reference to begin with
|
|
this._treeDataSource.root = this._model.groups.length === 1 ? this._model.groups[0] : this._model;
|
|
return this._tree.refresh(null);
|
|
}
|
|
|
|
private _getFocusedReference(): OneReference {
|
|
const [element] = this._tree.getFocus();
|
|
if (element instanceof OneReference) {
|
|
return element;
|
|
} else if (element instanceof FileReferences) {
|
|
if (element.children.length > 0) {
|
|
return element.children[0];
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
private _revealedReference?: OneReference;
|
|
|
|
private async _revealReference(reference: OneReference, revealParent: boolean): Promise<void> {
|
|
|
|
// check if there is anything to do...
|
|
if (this._revealedReference === reference) {
|
|
return;
|
|
}
|
|
this._revealedReference = reference;
|
|
|
|
// Update widget header
|
|
if (reference.uri.scheme !== Schemas.inMemory) {
|
|
this.setTitle(basenameOrAuthority(reference.uri), this._uriLabel.getUriLabel(dirname(reference.uri)));
|
|
} else {
|
|
this.setTitle(nls.localize('peekView.alternateTitle', "References"));
|
|
}
|
|
|
|
const promise = this._textModelResolverService.createModelReference(reference.uri);
|
|
|
|
if (this._treeDataSource.root === reference.parent) {
|
|
this._tree.reveal(reference);
|
|
} else {
|
|
if (revealParent) {
|
|
this._tree.reveal(reference.parent);
|
|
}
|
|
await this._tree.expand(reference.parent);
|
|
this._tree.reveal(reference);
|
|
}
|
|
|
|
const ref = await promise;
|
|
|
|
if (!this._model) {
|
|
// disposed
|
|
ref.dispose();
|
|
return;
|
|
}
|
|
|
|
dispose(this._previewModelReference);
|
|
|
|
// show in editor
|
|
const model = ref.object;
|
|
if (model) {
|
|
const scrollType = this._preview.getModel() === model.textEditorModel ? editorCommon.ScrollType.Smooth : editorCommon.ScrollType.Immediate;
|
|
const sel = Range.lift(reference.range).collapseToStart();
|
|
this._previewModelReference = ref;
|
|
this._preview.setModel(model.textEditorModel);
|
|
this._preview.setSelection(sel);
|
|
this._preview.revealRangeInCenter(sel, scrollType);
|
|
} else {
|
|
this._preview.setModel(this._previewNotAvailableMessage);
|
|
ref.dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
// theming
|
|
|
|
export const peekViewTitleBackground = registerColor('peekViewTitle.background', { dark: '#1E1E1E', light: '#FFFFFF', hc: '#0C141F' }, nls.localize('peekViewTitleBackground', 'Background color of the peek view title area.'));
|
|
export const peekViewTitleForeground = registerColor('peekViewTitleLabel.foreground', { dark: '#FFFFFF', light: '#333333', hc: '#FFFFFF' }, nls.localize('peekViewTitleForeground', 'Color of the peek view title.'));
|
|
export const peekViewTitleInfoForeground = registerColor('peekViewTitleDescription.foreground', { dark: '#ccccccb3', light: '#6c6c6cb3', hc: '#FFFFFF99' }, nls.localize('peekViewTitleInfoForeground', 'Color of the peek view title info.'));
|
|
export const peekViewBorder = registerColor('peekView.border', { dark: '#007acc', light: '#007acc', hc: contrastBorder }, nls.localize('peekViewBorder', 'Color of the peek view borders and arrow.'));
|
|
|
|
export const peekViewResultsBackground = registerColor('peekViewResult.background', { dark: '#252526', light: '#F3F3F3', hc: Color.black }, nls.localize('peekViewResultsBackground', 'Background color of the peek view result list.'));
|
|
export const peekViewResultsMatchForeground = registerColor('peekViewResult.lineForeground', { dark: '#bbbbbb', light: '#646465', hc: Color.white }, nls.localize('peekViewResultsMatchForeground', 'Foreground color for line nodes in the peek view result list.'));
|
|
export const peekViewResultsFileForeground = registerColor('peekViewResult.fileForeground', { dark: Color.white, light: '#1E1E1E', hc: Color.white }, nls.localize('peekViewResultsFileForeground', 'Foreground color for file nodes in the peek view result list.'));
|
|
export const peekViewResultsSelectionBackground = registerColor('peekViewResult.selectionBackground', { dark: '#3399ff33', light: '#3399ff33', hc: null }, nls.localize('peekViewResultsSelectionBackground', 'Background color of the selected entry in the peek view result list.'));
|
|
export const peekViewResultsSelectionForeground = registerColor('peekViewResult.selectionForeground', { dark: Color.white, light: '#6C6C6C', hc: Color.white }, nls.localize('peekViewResultsSelectionForeground', 'Foreground color of the selected entry in the peek view result list.'));
|
|
export const peekViewEditorBackground = registerColor('peekViewEditor.background', { dark: '#001F33', light: '#F2F8FC', hc: Color.black }, nls.localize('peekViewEditorBackground', 'Background color of the peek view editor.'));
|
|
export const peekViewEditorGutterBackground = registerColor('peekViewEditorGutter.background', { dark: peekViewEditorBackground, light: peekViewEditorBackground, hc: peekViewEditorBackground }, nls.localize('peekViewEditorGutterBackground', 'Background color of the gutter in the peek view editor.'));
|
|
|
|
export const peekViewResultsMatchHighlight = registerColor('peekViewResult.matchHighlightBackground', { dark: '#ea5c004d', light: '#ea5c004d', hc: null }, nls.localize('peekViewResultsMatchHighlight', 'Match highlight color in the peek view result list.'));
|
|
export const peekViewEditorMatchHighlight = registerColor('peekViewEditor.matchHighlightBackground', { dark: '#ff8f0099', light: '#f5d802de', hc: null }, nls.localize('peekViewEditorMatchHighlight', 'Match highlight color in the peek view editor.'));
|
|
export const peekViewEditorMatchHighlightBorder = registerColor('peekViewEditor.matchHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('peekViewEditorMatchHighlightBorder', 'Match highlight border in the peek view editor.'));
|
|
|
|
|
|
registerThemingParticipant((theme, collector) => {
|
|
const findMatchHighlightColor = theme.getColor(peekViewResultsMatchHighlight);
|
|
if (findMatchHighlightColor) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { background-color: ${findMatchHighlightColor}; }`);
|
|
}
|
|
const referenceHighlightColor = theme.getColor(peekViewEditorMatchHighlight);
|
|
if (referenceHighlightColor) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .preview .reference-decoration { background-color: ${referenceHighlightColor}; }`);
|
|
}
|
|
const referenceHighlightBorder = theme.getColor(peekViewEditorMatchHighlightBorder);
|
|
if (referenceHighlightBorder) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .preview .reference-decoration { border: 2px solid ${referenceHighlightBorder}; box-sizing: border-box; }`);
|
|
}
|
|
const hcOutline = theme.getColor(activeContrastBorder);
|
|
if (hcOutline) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .referenceMatch { border: 1px dotted ${hcOutline}; box-sizing: border-box; }`);
|
|
}
|
|
const resultsBackground = theme.getColor(peekViewResultsBackground);
|
|
if (resultsBackground) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree { background-color: ${resultsBackground}; }`);
|
|
}
|
|
const resultsMatchForeground = theme.getColor(peekViewResultsMatchForeground);
|
|
if (resultsMatchForeground) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree { color: ${resultsMatchForeground}; }`);
|
|
}
|
|
const resultsFileForeground = theme.getColor(peekViewResultsFileForeground);
|
|
if (resultsFileForeground) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .reference-file { color: ${resultsFileForeground}; }`);
|
|
}
|
|
const resultsSelectedBackground = theme.getColor(peekViewResultsSelectionBackground);
|
|
if (resultsSelectedBackground) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows > .monaco-list-row.selected:not(.highlighted) { background-color: ${resultsSelectedBackground}; }`);
|
|
}
|
|
const resultsSelectedForeground = theme.getColor(peekViewResultsSelectionForeground);
|
|
if (resultsSelectedForeground) {
|
|
collector.addRule(`.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows > .monaco-list-row.selected:not(.highlighted) { color: ${resultsSelectedForeground} !important; }`);
|
|
}
|
|
const editorBackground = theme.getColor(peekViewEditorBackground);
|
|
if (editorBackground) {
|
|
collector.addRule(
|
|
`.monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background,` +
|
|
`.monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input {` +
|
|
` background-color: ${editorBackground};` +
|
|
`}`);
|
|
}
|
|
const editorGutterBackground = theme.getColor(peekViewEditorGutterBackground);
|
|
if (editorGutterBackground) {
|
|
collector.addRule(
|
|
`.monaco-editor .reference-zone-widget .preview .monaco-editor .margin {` +
|
|
` background-color: ${editorGutterBackground};` +
|
|
`}`);
|
|
}
|
|
});
|