From 67dc5341552b4552dfa65245d16b73a629071629 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 11 Sep 2019 10:06:07 -0700 Subject: [PATCH] Add selection highlight decorations to minimap, closes #21404 --- .../browser/viewParts/minimap/minimap.ts | 47 +++++++++++++------ src/vs/platform/theme/common/colorRegistry.ts | 1 + 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index d7fb6e544086d..93761c9a8ef3d 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -24,9 +24,11 @@ import { getOrCreateMinimapCharRenderer } from 'vs/editor/common/view/runtimeMin import { ViewContext } from 'vs/editor/common/view/viewContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { ViewLineData, ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel'; -import { scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry'; +import { scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, minimapSelection } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ModelDecorationMinimapOptions } from 'vs/editor/common/model/textModel'; +import { Selection } from 'vs/editor/common/core/selection'; +import { Color } from 'vs/base/common/color'; function getMinimapLineHeight(renderMinimap: RenderMinimap): number { if (renderMinimap === RenderMinimap.Large) { @@ -453,6 +455,8 @@ export class Minimap extends ViewPart { private _options: MinimapOptions; private _lastRenderData: RenderData | null; private _lastDecorations: ViewModelDecoration[] | undefined; + private _selections: Selection[] = []; + private _selectionColor: Color | undefined; private _renderDecorations: boolean = false; private _buffers: MinimapBuffers | null; @@ -462,6 +466,7 @@ export class Minimap extends ViewPart { this._options = new MinimapOptions(this._context.configuration); this._lastRenderData = null; this._buffers = null; + this._selectionColor = this._context.theme.getColor(minimapSelection); this._domNode = createFastDomNode(document.createElement('div')); PartFingerprints.write(this._domNode, PartFingerprint.Minimap); @@ -631,6 +636,11 @@ export class Minimap extends ViewPart { public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { return this._onOptionsMaybeChanged(); } + public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { + this._selections = e.selections; + this._renderDecorations = true; + return true; + } public onFlushed(e: viewEvents.ViewFlushedEvent): boolean { this._lastRenderData = null; return true; @@ -680,9 +690,9 @@ export class Minimap extends ViewPart { public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean { this._context.model.invalidateMinimapColorCache(); - // Only bother calling render if decorations are currently shown - this._renderDecorations = !!this._lastDecorations; - return !!this._lastDecorations; + this._selectionColor = this._context.theme.getColor(minimapSelection); + this._renderDecorations = true; + return true; } // --- end event handlers @@ -744,8 +754,16 @@ export class Minimap extends ViewPart { canvasContext.clearRect(0, 0, canvasInnerWidth, canvasInnerHeight); - // Loop over decorations, ignoring those that don't have the minimap property set and rendering rectangles for each line the decoration spans const lineOffsetMap = new Map(); + for (let i = 0; i < this._selections.length; i++) { + const selection = this._selections[i]; + + for (let line = selection.startLineNumber; line <= selection.endLineNumber; line++) { + this.renderDecorationOnLine(canvasContext, lineOffsetMap, selection, this._selectionColor, layout, line, lineHeight, lineHeight, tabSize, characterWidth); + } + } + + // Loop over decorations, ignoring those that don't have the minimap property set and rendering rectangles for each line the decoration spans for (let i = 0; i < decorations.length; i++) { const decoration = decorations[i]; @@ -754,7 +772,8 @@ export class Minimap extends ViewPart { } for (let line = decoration.range.startLineNumber; line <= decoration.range.endLineNumber; line++) { - this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration, layout, line, lineHeight, lineHeight, tabSize, characterWidth); + const decorationColor = (decoration.options.minimap).getColor(this._context.theme); + this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration.range, decorationColor, layout, line, lineHeight, lineHeight, tabSize, characterWidth); } } @@ -764,7 +783,8 @@ export class Minimap extends ViewPart { private renderDecorationOnLine(canvasContext: CanvasRenderingContext2D, lineOffsetMap: Map, - decoration: ViewModelDecoration, + decorationRange: Range, + decorationColor: Color | undefined, layout: MinimapLayout, lineNumber: number, height: number, @@ -793,7 +813,7 @@ export class Minimap extends ViewPart { lineOffsetMap.set(lineNumber, lineIndexToXOffset); } - const { startColumn, endColumn, startLineNumber, endLineNumber } = decoration.range; + const { startColumn, endColumn, startLineNumber, endLineNumber } = decorationRange; const x = startLineNumber === lineNumber ? lineIndexToXOffset[startColumn - 1] : 0; const endColumnForLine = endLineNumber > lineNumber ? lineIndexToXOffset.length - 1 : endColumn - 1; @@ -802,24 +822,21 @@ export class Minimap extends ViewPart { // If the decoration starts at the last character of the column and spans over it, ensure it has a width const width = lineIndexToXOffset[endColumnForLine] - x || 2; - this.renderDecoration(canvasContext, decoration.options.minimap, x, y, width, height); + this.renderDecoration(canvasContext, decorationColor, x, y, width, height); } if (isFirstDecorationForLine) { - this.renderLineHighlight(canvasContext, decoration.options.minimap, y, height); + this.renderLineHighlight(canvasContext, decorationColor, y, height); } } - private renderLineHighlight(canvasContext: CanvasRenderingContext2D, minimapOptions: ModelDecorationMinimapOptions, y: number, height: number): void { - const decorationColor = minimapOptions.getColor(this._context.theme); + private renderLineHighlight(canvasContext: CanvasRenderingContext2D, decorationColor: Color | undefined, y: number, height: number): void { canvasContext.fillStyle = decorationColor && decorationColor.transparent(0.5).toString() || ''; canvasContext.fillRect(0, y, canvasContext.canvas.width, height); } - private renderDecoration(canvasContext: CanvasRenderingContext2D, minimapOptions: ModelDecorationMinimapOptions, x: number, y: number, width: number, height: number) { - const decorationColor = minimapOptions.getColor(this._context.theme); - + private renderDecoration(canvasContext: CanvasRenderingContext2D, decorationColor: Color | undefined, x: number, y: number, width: number, height: number) { canvasContext.fillStyle = decorationColor && decorationColor.toString() || ''; canvasContext.fillRect(x, y, width, height); } diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index 47b428fbb8406..f5fc75c932415 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -397,6 +397,7 @@ export const overviewRulerFindMatchForeground = registerColor('editorOverviewRul export const overviewRulerSelectionHighlightForeground = registerColor('editorOverviewRuler.selectionHighlightForeground', { dark: '#A0A0A0CC', light: '#A0A0A0CC', hc: '#A0A0A0CC' }, nls.localize('overviewRulerSelectionHighlightForeground', 'Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.'), true); export const minimapFindMatch = registerColor('minimap.findMatchHighlight', { light: '#d18616', dark: '#d18616', hc: '#AB5A00' }, nls.localize('minimapFindMatchHighlight', 'Minimap marker color for find matches.'), true); +export const minimapSelection = registerColor('minimap.selectionHighlight', { light: '#ADD6FF', dark: '#264F78', hc: '#f3f518' }, nls.localize('minimapSelectionHighlight', 'Minimap marker color for the current editor selection.'), true); // ----- color functions