From 3927c0fb2fbbc3dad2b2f653596998f8abacacde Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 19 Apr 2017 10:50:48 +0200 Subject: [PATCH] [theme] Provide a way to theme diff highlights. Fixes #19735 --- .../standalone/standaloneCodeEditor.ts | 6 +- .../browser/standalone/standaloneEditor.ts | 3 +- .../editor/browser/widget/diffEditorWidget.ts | 89 ++++++++++++++++--- .../browser/widget/media/diffEditor.css | 47 ++-------- 4 files changed, 90 insertions(+), 55 deletions(-) diff --git a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts index e7216e90572..b085ecc1411 100644 --- a/src/vs/editor/browser/standalone/standaloneCodeEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneCodeEditor.ts @@ -24,6 +24,7 @@ import { IStandaloneThemeService } from 'vs/editor/common/services/standaloneThe import { InternalEditorAction } from 'vs/editor/common/editorAction'; import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions'; import { IDiffEditorOptions, IEditorOptions } from "vs/editor/common/config/editorOptions"; +import { IThemeService } from "vs/platform/theme/common/themeService"; /** * The options to create an editor. @@ -282,14 +283,15 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon @IContextViewService contextViewService: IContextViewService, @IStandaloneThemeService standaloneColorService: IStandaloneThemeService, @IEditorWorkerService editorWorkerService: IEditorWorkerService, - @ICodeEditorService codeEditorService: ICodeEditorService + @ICodeEditorService codeEditorService: ICodeEditorService, + @IThemeService themeService: IThemeService ) { options = options || {}; if (typeof options.theme === 'string') { options.theme = standaloneColorService.setTheme(options.theme); } - super(domElement, options, editorWorkerService, contextKeyService, instantiationService, codeEditorService); + super(domElement, options, editorWorkerService, contextKeyService, instantiationService, codeEditorService, themeService); if (keybindingService instanceof StandaloneKeybindingService) { this._standaloneKeybindingService = keybindingService; diff --git a/src/vs/editor/browser/standalone/standaloneEditor.ts b/src/vs/editor/browser/standalone/standaloneEditor.ts index 85431a60334..7c3f6dcd538 100644 --- a/src/vs/editor/browser/standalone/standaloneEditor.ts +++ b/src/vs/editor/browser/standalone/standaloneEditor.ts @@ -126,7 +126,8 @@ export function createDiffEditor(domElement: HTMLElement, options?: IDiffEditorC services.get(IContextViewService), services.get(IStandaloneThemeService), services.get(IEditorWorkerService), - services.get(ICodeEditorService) + services.get(ICodeEditorService), + services.get(IStandaloneThemeService) ); }); } diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 36c5091945c..502c12e5eb6 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -6,6 +6,7 @@ 'use strict'; import 'vs/css!./media/diffEditor'; +import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; import { Disposable } from 'vs/base/common/lifecycle'; import * as objects from 'vs/base/common/objects'; @@ -32,6 +33,9 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { ColorId, MetadataConsts, FontStyle } from 'vs/editor/common/modes'; import Event, { Emitter } from 'vs/base/common/event'; import * as editorOptions from "vs/editor/common/config/editorOptions"; +import { registerThemingParticipant, IThemeService, ITheme } from "vs/platform/theme/common/themeService"; +import { registerColor } from "vs/platform/theme/common/colorRegistry"; +import { Color, RGBA } from "vs/base/common/color"; interface IEditorDiffDecorations { decorations: editorCommon.IModelDeltaDecoration[]; @@ -60,6 +64,7 @@ interface IEditorsZones { interface IDiffEditorWidgetStyle { getEditorsDiffDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalWhitespaces: editorCommon.IEditorWhitespace[], modifiedWhitespaces: editorCommon.IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorsDiffDecorationsWithZones; setEnableSplitViewResizing(enableSplitViewResizing: boolean): void; + applyColors(theme: ITheme): boolean; layout(): number; dispose(): void; } @@ -183,6 +188,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private _editorWorkerService: IEditorWorkerService; protected _contextKeyService: IContextKeyService; private _codeEditorService: ICodeEditorService; + private _themeService: IThemeService; constructor( domElement: HTMLElement, @@ -190,7 +196,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE @IEditorWorkerService editorWorkerService: IEditorWorkerService, @IContextKeyService contextKeyService: IContextKeyService, @IInstantiationService instantiationService: IInstantiationService, - @ICodeEditorService codeEditorService: ICodeEditorService + @ICodeEditorService codeEditorService: ICodeEditorService, + @IThemeService themeService: IThemeService ) { super(); @@ -198,6 +205,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._codeEditorService = codeEditorService; this._contextKeyService = contextKeyService.createScoped(domElement); this._contextKeyService.createKey('isInDiffEditor', true); + this._themeService = themeService; this.id = (++DIFF_EDITOR_ID); @@ -295,6 +303,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE } this._codeEditorService.addDiffEditor(this); + + themeService.onThemeChange(t => { + if (this._strategy && this._strategy.applyColors(t)) { + this._updateDecorationsRunner.schedule(); + } + }); } public get ignoreTrimWhitespace(): boolean { @@ -521,7 +535,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE // renderSideBySide if (renderSideBySideChanged) { if (this._renderSideBySide) { - this._setStrategy(new DiffEdtorWidgetSideBySide(this._createDataSource(), this._enableSplitViewResizing)); + this._setStrategy(new DiffEdtorWidgetSideBySide(this._createDataSource(), this._enableSplitViewResizing, )); } else { this._setStrategy(new DiffEdtorWidgetInline(this._createDataSource(), this._enableSplitViewResizing)); } @@ -979,6 +993,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE } this._strategy = newStrategy; + newStrategy.applyColors(this._themeService.getTheme()); if (this._lineChanges) { this._updateDecorations(); @@ -1091,12 +1106,23 @@ interface IDataSource { class DiffEditorWidgetStyle extends Disposable { _dataSource: IDataSource; + _insertColor: Color; + _removeColor: Color; constructor(dataSource: IDataSource) { super(); this._dataSource = dataSource; } + public applyColors(theme: ITheme): boolean { + let newInsertColor = (theme.getColor(diffInserted) || defaultInsertColor).transparent(2); + let newRemoveColor = (theme.getColor(diffRemoved) || defaultRemoveColor).transparent(2); + let hasChanges = !newInsertColor.equals(this._insertColor) || !newRemoveColor.equals(this._removeColor); + this._insertColor = newInsertColor; + this._removeColor = newRemoveColor; + return hasChanges; + } + public getEditorsDiffDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalWhitespaces: editorCommon.IEditorWhitespace[], modifiedWhitespaces: editorCommon.IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorsDiffDecorationsWithZones { // Get view zones modifiedWhitespaces = modifiedWhitespaces.sort((a, b) => { @@ -1495,14 +1521,16 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, 'char-delete', true)); } + let color = this._removeColor.toString(); + result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, editorCommon.OverviewRulerLane.Full, 0, - 'rgba(255, 0, 0, 0.4)', - 'rgba(255, 0, 0, 0.4)', - 'rgba(255, 0, 0, 0.4)' + color, + color, + color )); if (lineChange.charChanges) { @@ -1563,14 +1591,15 @@ class DiffEdtorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffEd if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, 'char-insert', true)); } + let color = this._insertColor.toString(); result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, editorCommon.OverviewRulerLane.Full, 0, - 'rgba(155, 185, 85, 0.4)', - 'rgba(155, 185, 85, 0.4)', - 'rgba(155, 185, 85, 0.4)' + color, + color, + color )); if (lineChange.charChanges) { @@ -1683,14 +1712,15 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } }); + let color = this._removeColor.toString(); result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.originalStartLineNumber, lineChange.originalEndLineNumber, editorCommon.OverviewRulerLane.Full, 0, - 'rgba(255, 0, 0, 0.4)', - 'rgba(255, 0, 0, 0.4)', - 'rgba(255, 0, 0, 0.4)' + color, + color, + color )); } } @@ -1722,14 +1752,15 @@ class DiffEdtorWidgetInline extends DiffEditorWidgetStyle implements IDiffEditor } }); + let color = this._insertColor.toString(); result.overviewZones.push(new editorCommon.OverviewRulerZone( lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber, editorCommon.OverviewRulerLane.Full, 0, - 'rgba(155, 185, 85, 0.4)', - 'rgba(155, 185, 85, 0.4)', - 'rgba(155, 185, 85, 0.4)' + color, + color, + color )); if (lineChange.charChanges) { @@ -1915,3 +1946,33 @@ function createFakeLinesDiv(): HTMLElement { r.className = 'diagonal-fill'; return r; } + +const defaultInsertColor = Color.fromRGBA(new RGBA(155, 185, 85, 255 * 0.2)); +const defaultRemoveColor = Color.fromRGBA(new RGBA(255, 0, 0, 255 * 0.2)); + +export const diffInserted = registerColor('diffInserted', { dark: defaultInsertColor, light: defaultInsertColor, hc: null }, nls.localize('diffInserted', 'Background color for text that got inserted.')); +export const diffRemoved = registerColor('diffRemoved', { dark: defaultRemoveColor, light: defaultRemoveColor, hc: null }, nls.localize('diffRemoved', 'Background color for text that got removed.')); +export const diffInsertedOutline = registerColor('diffInsertedOutline', { dark: null, light: null, hc: '#33ff2eff' }, nls.localize('diffInsertedOutline', 'Outline color for the text that got inserted.')); +export const diffRemovedOutline = registerColor('diffRemovedOutline', { dark: null, light: null, hc: '#FF008F' }, nls.localize('diffRemovedOutline', 'Outline color for text that got removed.')); + + +registerThemingParticipant((theme, collector) => { + let added = theme.getColor(diffInserted); + if (added) { + collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { background-color: ${added}; }`); + collector.addRule(`.monaco-editor .inline-added-margin-view-zone { background-color: ${added}; }`); + } + let removed = theme.getColor(diffRemoved); + if (removed) { + collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { background-color: ${removed}; }`); + collector.addRule(`.monaco-editor .inline-deleted-margin-view-zone { background-color: ${removed}; }`); + } + let addedOutline = theme.getColor(diffInsertedOutline); + if (addedOutline) { + collector.addRule(`.monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px dashed ${addedOutline}; }`); + } + let removedOutline = theme.getColor(diffRemovedOutline); + if (removedOutline) { + collector.addRule(`.monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px dashed ${removedOutline}; }`); + } +}); \ No newline at end of file diff --git a/src/vs/editor/browser/widget/media/diffEditor.css b/src/vs/editor/browser/widget/media/diffEditor.css index 89c9fc0908d..0c1bb226785 100644 --- a/src/vs/editor/browser/widget/media/diffEditor.css +++ b/src/vs/editor/browser/widget/media/diffEditor.css @@ -7,18 +7,20 @@ .monaco-diff-editor .diffOverview { z-index: 9; } -.monaco-diff-editor.vs .diffOverview { background: #f9f7f7; } -.monaco-diff-editor.vs-dark .diffOverview { background: #1E1E1E; } -.monaco-diff-editor.hc-black .diffOverview { background: #000; } + +/* colors not externalized: using transparancy on background */ +.monaco-diff-editor.vs .diffOverview { background: rgba(0, 0, 0, 0.03); } +.monaco-diff-editor.vs-dark .diffOverview { background: rgba(255, 255, 255, 0.01); } .monaco-diff-editor .diffViewport { box-shadow: inset 0px 0px 1px 0px #B9B9B9; - background: rgba(148, 148, 148, 0.19); -} -.monaco-diff-editor.vs-dark { - background: #1E1E1E; + background: rgba(0, 0, 0, 0.10); } +.monaco-diff-editor.vs-dark .diffViewport, +.monaco-diff-editor.hc-black .diffViewport { + background: rgba(255, 255, 255, 0.10); +} .monaco-scrollable-element.modified-in-monaco-diff-editor.vs .scrollbar { background: rgba(0,0,0,0); } .monaco-scrollable-element.modified-in-monaco-diff-editor.vs-dark .scrollbar { background: rgba(0,0,0,0); } .monaco-scrollable-element.modified-in-monaco-diff-editor.hc-black .scrollbar { background: none; } @@ -34,22 +36,6 @@ /* ---------- Diff ---------- */ -.monaco-editor .line-delete, -.monaco-editor .char-delete { - background: rgba(255, 0, 0, 0.2); -} -.monaco-editor.hc-black .line-delete, -.monaco-editor.hc-black .char-delete { - background: none; - border: 1px dashed #FF008F; -} - - -.monaco-editor .line-insert, -.monaco-editor .char-insert { - background: rgba(155, 185, 85, 0.2); -} - .monaco-editor .insert-sign, .monaco-editor .delete-sign { background-size: 60%; opacity: 0.7; @@ -66,22 +52,12 @@ .monaco-editor.vs-dark .delete-sign, .monaco-editor.hc-black .delete-sign { background-image: url('deletion-inverse.svg'); } .monaco-editor .inline-deleted-margin-view-zone { - background: rgba(255, 0, 0, 0.2); text-align: right; } .monaco-editor .inline-added-margin-view-zone { - background: rgba(155, 185, 85, 0.2); text-align: right; } - -.monaco-editor.hc-black .line-insert, -.monaco-editor.hc-black .char-insert { - background: none; - border: 1px dashed rgb(51, 255, 46); -} - - .monaco-editor .diagonal-fill { background: url('diagonal-fill.png'); } @@ -97,8 +73,3 @@ .monaco-editor .view-zones .view-lines .view-line span { display: inline-block; } - -/* High Contrast Theming */ -.monaco-diff-editor.hc-black { - background: #000; -} \ No newline at end of file