diff --git a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts index 73ae56f5e380cb6e85dbe4e1167583c56e73c7c0..ed1121cfcdd72160ee365a44ddd3e7db57713ae0 100644 --- a/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts +++ b/src/vs/editor/browser/viewParts/editorScrollbar/editorScrollbar.ts @@ -99,7 +99,13 @@ export class EditorScrollbar extends ViewPart { const layoutInfo = this._context.configuration.editor.layoutInfo; this.scrollbarDomNode.setLeft(layoutInfo.contentLeft); - this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth); + + const side = this._context.configuration.editor.viewInfo.minimap.side; + if (side === 'right') { + this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth); + } else { + this.scrollbarDomNode.setWidth(layoutInfo.contentWidth); + } this.scrollbarDomNode.setHeight(layoutInfo.contentHeight); } diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 8b4cc2a9979b62a400037a39e71b7bd5d966022d..23ba983dd87d74ca35c0b1ea6e1865fea8dea9f9 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -76,6 +76,8 @@ class MinimapOptions { public readonly showSlider: 'always' | 'mouseover'; + public readonly side: 'right' | 'left'; + public readonly pixelRatio: number; public readonly typicalHalfwidthCharacterWidth: number; @@ -118,6 +120,7 @@ class MinimapOptions { this.renderMinimap = layoutInfo.renderMinimap | 0; this.scrollBeyondLastLine = viewInfo.scrollBeyondLastLine; this.showSlider = viewInfo.minimap.showSlider; + this.side = viewInfo.minimap.side; this.pixelRatio = pixelRatio; this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth; this.lineHeight = configuration.editor.lineHeight; @@ -135,6 +138,7 @@ class MinimapOptions { return (this.renderMinimap === other.renderMinimap && this.scrollBeyondLastLine === other.scrollBeyondLastLine && this.showSlider === other.showSlider + && this.side === other.side && this.pixelRatio === other.pixelRatio && this.typicalHalfwidthCharacterWidth === other.typicalHalfwidthCharacterWidth && this.lineHeight === other.lineHeight @@ -456,7 +460,11 @@ export class Minimap extends ViewPart { this._domNode.setPosition('absolute'); this._domNode.setAttribute('role', 'presentation'); this._domNode.setAttribute('aria-hidden', 'true'); - this._domNode.setRight(this._context.configuration.editor.layoutInfo.verticalScrollbarWidth); + if (this._options.side === 'right') { + this._domNode.setRight(this._context.configuration.editor.layoutInfo.verticalScrollbarWidth); + } else { + this._domNode.setLeft(0); + } this._shadow = createFastDomNode(document.createElement('div')); this._shadow.setClassName('minimap-shadow-hidden'); diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index 7bf275a9b80240a28ba95914aaf80ebc3f257dbb..4d57a3fa2b86f15ea25496026584fd016cf07ccd 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -264,6 +264,12 @@ const editorConfiguration: IConfigurationNode = { 'default': EDITOR_DEFAULTS.viewInfo.minimap.enabled, 'description': nls.localize('minimap.enabled', "Controls if the minimap is shown") }, + 'editor.minimap.side': { + 'type': 'string', + 'enum': ['left', 'right'], + 'default': EDITOR_DEFAULTS.viewInfo.minimap.side, + 'description': nls.localize('minimap.side', "Controls display minimap which side.Possible values are \'right\' and \'left\'") + }, 'editor.minimap.showSlider': { 'type': 'string', 'enum': ['always', 'mouseover'], diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 0b49b501f246442218987fadf1718302eb6d9eea..87bca6ec55be04adf63e52eb1e19ffe1840144d1 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -102,6 +102,11 @@ export interface IEditorMinimapOptions { * Defaults to false. */ enabled?: boolean; + /** + * Control the side of the minimap in editor. + * Defaults to 'right'. + */ + side?: 'right' | 'left'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. @@ -736,6 +741,7 @@ export interface InternalEditorScrollbarOptions { export interface InternalEditorMinimapOptions { readonly enabled: boolean; + readonly side: 'right' | 'left'; readonly showSlider: 'always' | 'mouseover'; readonly renderCharacters: boolean; readonly maxColumn: number; @@ -1095,6 +1101,7 @@ export class InternalEditorOptions { private static _equalsMinimapOptions(a: InternalEditorMinimapOptions, b: InternalEditorMinimapOptions): boolean { return ( a.enabled === b.enabled + && a.side === b.side && a.showSlider === b.showSlider && a.renderCharacters === b.renderCharacters && a.maxColumn === b.maxColumn @@ -1547,6 +1554,7 @@ export class EditorOptionsValidator { } return { enabled: _boolean(opts.enabled, defaults.enabled), + side: _stringSet<'right' | 'left'>(opts.side, defaults.side, ['right', 'left']), showSlider: _stringSet<'always' | 'mouseover'>(opts.showSlider, defaults.showSlider, ['always', 'mouseover']), renderCharacters: _boolean(opts.renderCharacters, defaults.renderCharacters), maxColumn: _clampedInt(opts.maxColumn, defaults.maxColumn, 1, 10000), @@ -1761,6 +1769,7 @@ export class InternalEditorOptionsFactory { scrollbar: opts.viewInfo.scrollbar, minimap: { enabled: (accessibilityIsOn ? false : opts.viewInfo.minimap.enabled), // DISABLED WHEN SCREEN READER IS ATTACHED + side: opts.viewInfo.minimap.side, renderCharacters: opts.viewInfo.minimap.renderCharacters, showSlider: opts.viewInfo.minimap.showSlider, maxColumn: opts.viewInfo.minimap.maxColumn @@ -1842,6 +1851,7 @@ export class InternalEditorOptionsFactory { scrollbarArrowSize: opts.viewInfo.scrollbar.arrowSize, verticalScrollbarHasArrows: opts.viewInfo.scrollbar.verticalHasArrows, minimap: opts.viewInfo.minimap.enabled, + minimapSide: opts.viewInfo.minimap.side, minimapRenderCharacters: opts.viewInfo.minimap.renderCharacters, minimapMaxColumn: opts.viewInfo.minimap.maxColumn, pixelRatio: env.pixelRatio @@ -1974,6 +1984,7 @@ export interface IEditorLayoutProviderOpts { horizontalScrollbarHeight: number; minimap: boolean; + minimapSide: string; minimapRenderCharacters: boolean; minimapMaxColumn: number; pixelRatio: number; @@ -1994,11 +2005,12 @@ export class EditorLayoutProvider { const lineDecorationsWidth = _opts.lineDecorationsWidth | 0; const typicalHalfwidthCharacterWidth = _opts.typicalHalfwidthCharacterWidth; const maxDigitWidth = _opts.maxDigitWidth; - const verticalScrollbarWidth = _opts.verticalScrollbarWidth | 0; + let verticalScrollbarWidth = _opts.verticalScrollbarWidth | 0; const verticalScrollbarHasArrows = _opts.verticalScrollbarHasArrows; const scrollbarArrowSize = _opts.scrollbarArrowSize | 0; const horizontalScrollbarHeight = _opts.horizontalScrollbarHeight | 0; const minimap = _opts.minimap; + const minimapSide = _opts.minimapSide; const minimapRenderCharacters = _opts.minimapRenderCharacters; const minimapMaxColumn = _opts.minimapMaxColumn | 0; const pixelRatio = _opts.pixelRatio; @@ -2014,17 +2026,22 @@ export class EditorLayoutProvider { glyphMarginWidth = lineHeight; } - const glyphMarginLeft = 0; - const lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; - const decorationsLeft = lineNumbersLeft + lineNumbersWidth; - const contentLeft = decorationsLeft + lineDecorationsWidth; - const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth; let renderMinimap: RenderMinimap; let minimapWidth: number; let contentWidth: number; + let contentLeft: number; + let glyphMarginLeft: number; + let lineNumbersLeft: number; + let decorationsLeft: number; + + glyphMarginLeft = 0; if (!minimap) { + lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; + decorationsLeft = lineNumbersLeft + lineNumbersWidth; + + contentLeft = decorationsLeft + lineDecorationsWidth; minimapWidth = 0; renderMinimap = RenderMinimap.None; contentWidth = remainingWidth; @@ -2056,6 +2073,17 @@ export class EditorLayoutProvider { minimapWidth = Math.floor(minimapMaxColumn * minimapCharWidth); } contentWidth = remainingWidth - minimapWidth; + + if (typeof minimapSide === 'string') { + if (minimapSide === 'left') { + glyphMarginLeft = minimapWidth; + } + } + + lineNumbersLeft = glyphMarginLeft + glyphMarginWidth; + decorationsLeft = lineNumbersLeft + lineNumbersWidth; + contentLeft = decorationsLeft + lineDecorationsWidth; + } const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth) / typicalHalfwidthCharacterWidth)); @@ -2197,6 +2225,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = { }, minimap: { enabled: true, + side: 'right', showSlider: 'mouseover', renderCharacters: true, maxColumn: 120 diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index 53ac8d481a61ba3013bb7a6c0945546df072b796..58760b1e5a00baf821f6ecbaf82345cda957f8fe 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -31,6 +31,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -87,6 +88,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 13, verticalScrollbarHasArrows: true, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -143,6 +145,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -199,6 +202,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -255,6 +259,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -311,6 +316,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -367,6 +373,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -423,6 +430,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -479,6 +487,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -535,6 +544,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: false, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -591,6 +601,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 1, @@ -647,6 +658,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 2, @@ -703,6 +715,64 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { scrollbarArrowSize: 0, verticalScrollbarHasArrows: false, minimap: true, + minimapSide: 'right', + minimapRenderCharacters: true, + minimapMaxColumn: 150, + pixelRatio: 4, + }, { + width: 1000, + height: 800, + + glyphMarginLeft: 0, + glyphMarginWidth: 0, + glyphMarginHeight: 800, + + lineNumbersLeft: 0, + lineNumbersWidth: 0, + lineNumbersHeight: 800, + + decorationsLeft: 0, + decorationsWidth: 10, + decorationsHeight: 800, + + contentLeft: 10, + contentWidth: 943, + contentHeight: 800, + + renderMinimap: RenderMinimap.Large, + minimapWidth: 47, + viewportColumn: 94, + + verticalScrollbarWidth: 0, + horizontalScrollbarHeight: 0, + + overviewRuler: { + top: 0, + width: 0, + height: 800, + right: 0 + } + }); + }); + + test('EditorLayoutProvider 10 - render minimap to left', () => { + doTest({ + outerWidth: 1000, + outerHeight: 800, + showGlyphMargin: false, + lineHeight: 16, + showLineNumbers: false, + lineNumbersMinChars: 0, + lineNumbersDigitCount: 1, + lineDecorationsWidth: 10, + typicalHalfwidthCharacterWidth: 10, + maxDigitWidth: 10, + verticalScrollbarWidth: 0, + horizontalScrollbarHeight: 0, + scrollbarArrowSize: 0, + verticalScrollbarHasArrows: false, + minimap: true, + minimapSide: 'left', minimapRenderCharacters: true, minimapMaxColumn: 150, pixelRatio: 4, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index ef21f827a94ecc69cbdc01262fc79f5c2fb798e3..752db02cf8a34dd9dfa27634ab198021d2c969ac 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -2431,6 +2431,11 @@ declare module monaco.editor { * Defaults to false. */ enabled?: boolean; + /** + * Control the side of the minimap in editor. + * Defaults to 'right'. + */ + side?: 'right' | 'left'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. @@ -2993,6 +2998,7 @@ declare module monaco.editor { export interface InternalEditorMinimapOptions { readonly enabled: boolean; + readonly side: 'right' | 'left'; readonly showSlider: 'always' | 'mouseover'; readonly renderCharacters: boolean; readonly maxColumn: number; diff --git a/src/vs/platform/telemetry/common/telemetryUtils.ts b/src/vs/platform/telemetry/common/telemetryUtils.ts index 41c3db8d63fd502119d0c91b4740b3c98ca339c1..1b3b0233b7b60e221ab4921571a5cb81f7383c75 100644 --- a/src/vs/platform/telemetry/common/telemetryUtils.ts +++ b/src/vs/platform/telemetry/common/telemetryUtils.ts @@ -75,6 +75,7 @@ const configurationValueWhitelist = [ 'editor.roundedSelection', 'editor.scrollBeyondLastLine', 'editor.minimap.enabled', + 'editor.minimap.side', 'editor.minimap.renderCharacters', 'editor.minimap.maxColumn', 'editor.find.seedSearchStringFromSelection',