From 4eebba084d243ac1b0cd034f4dd4d33a05e8ad8b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 23 Mar 2017 22:44:36 +0100 Subject: [PATCH] [theme] style find/replace widget --- .../theme-abyss/themes/abyss-color-theme.json | 5 ++ src/vs/base/browser/ui/checkbox/checkbox.css | 20 ------ src/vs/base/browser/ui/checkbox/checkbox.ts | 31 +++++++- src/vs/base/browser/ui/findinput/findInput.ts | 32 +++++++-- .../ui/findinput/findInputCheckboxes.ts | 11 ++- src/vs/editor/contrib/find/browser/find.ts | 6 +- .../contrib/find/browser/findWidget.css | 72 ++----------------- .../editor/contrib/find/browser/findWidget.ts | 59 +++++++++++---- 8 files changed, 126 insertions(+), 110 deletions(-) diff --git a/extensions/theme-abyss/themes/abyss-color-theme.json b/extensions/theme-abyss/themes/abyss-color-theme.json index 9997f54fa2f..942db6b12c8 100644 --- a/extensions/theme-abyss/themes/abyss-color-theme.json +++ b/extensions/theme-abyss/themes/abyss-color-theme.json @@ -266,11 +266,16 @@ "editorPeekEditorBackground": "#001F33", "editorPeekTitleBackground": "#060621", "editorPeekBorders": "#7777cc", + "editorLineNumbers": "#8686ff", "editorMarkerNavigationBackground": "#060621", "editorMarkerNavigationError": "#FF0000", "editorMarkerNavigationWarning": "#00FF00", + "editorFindWidgetBackground": "#051336", + "editorFindInputBackground": "#181f2f", + "editorFindCheckedBorders": "#0000FF", + // Workbench Colors "tabsContainerBackground": "#1c1c2a", "inactiveTabBackground": "#10192c", diff --git a/src/vs/base/browser/ui/checkbox/checkbox.css b/src/vs/base/browser/ui/checkbox/checkbox.css index 936b3ffceb5..60db38b2087 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.css +++ b/src/vs/base/browser/ui/checkbox/checkbox.css @@ -33,22 +33,6 @@ opacity: 1; } -.custom-checkbox:hover { - background-color: #EEE; -} - -.custom-checkbox.checked { - border-color: #007ACC; -} - -.vs-dark .custom-checkbox:hover { - background-color: #292929; -} - -.vs-dark .custom-checkbox.checked { - border-color: #007ACC; -} - .hc-black .custom-checkbox { background: none; border: none; @@ -56,8 +40,4 @@ .hc-black .custom-checkbox:hover { background: none; -} - -.hc-black .custom-checkbox.checked { - border: 1px solid #f38518; } \ No newline at end of file diff --git a/src/vs/base/browser/ui/checkbox/checkbox.ts b/src/vs/base/browser/ui/checkbox/checkbox.ts index c497a4d7b64..96c21c41667 100644 --- a/src/vs/base/browser/ui/checkbox/checkbox.ts +++ b/src/vs/base/browser/ui/checkbox/checkbox.ts @@ -8,11 +8,13 @@ import 'vs/css!./checkbox'; import DOM = require('vs/base/browser/dom'); +import * as objects from 'vs/base/common/objects'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Widget } from 'vs/base/browser/ui/widget'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { Color } from "vs/base/common/color"; -export interface ICheckboxOpts { +export interface ICheckboxOpts extends ICheckboxStyles { actionClassName: string; title: string; isChecked: boolean; @@ -20,6 +22,14 @@ export interface ICheckboxOpts { onKeyDown?: (e: IKeyboardEvent) => void; } +export interface ICheckboxStyles { + checkedBorderColor?: Color; +} + +const defaultOpts = { + checkedBorderColor: Color.fromHex('#007ACC') +}; + export class Checkbox extends Widget { private _opts: ICheckboxOpts; @@ -29,7 +39,8 @@ export class Checkbox extends Widget { constructor(opts: ICheckboxOpts) { super(); - this._opts = opts; + this._opts = objects.clone(opts); + objects.mixin(this._opts, defaultOpts); this._checked = this._opts.isChecked; this.domNode = document.createElement('div'); @@ -40,6 +51,8 @@ export class Checkbox extends Widget { this.domNode.setAttribute('aria-checked', String(this._checked)); this.domNode.setAttribute('aria-label', this._opts.title); + this._applyStyles(); + this.onclick(this.domNode, (ev) => { this.checked = !this._checked; this._opts.onChange(false); @@ -72,6 +85,7 @@ export class Checkbox extends Widget { this._checked = newIsChecked; this.domNode.setAttribute('aria-checked', String(this._checked)); this.domNode.className = this._className(); + this._applyStyles(); } private _className(): string { @@ -82,6 +96,19 @@ export class Checkbox extends Widget { return 2 /*marginleft*/ + 2 /*border*/ + 2 /*padding*/ + 16 /* icon width */; } + public style(styles: ICheckboxStyles) { + if (styles.checkedBorderColor) { + this._opts.checkedBorderColor = styles.checkedBorderColor; + } + this._applyStyles(); + } + + protected _applyStyles() { + if (this.domNode) { + this.domNode.style.borderColor = this._checked ? this._opts.checkedBorderColor.toString() : null; + } + } + public enable(): void { this.domNode.tabIndex = 0; this.domNode.setAttribute('aria-disabled', String(false)); diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 60a2c7fbf42..389d89484ea 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -15,8 +15,9 @@ import Event, { Emitter } from 'vs/base/common/event'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { CaseSensitiveCheckbox, WholeWordsCheckbox, RegexCheckbox } from 'vs/base/browser/ui/findinput/findInputCheckboxes'; +import { Color } from "vs/base/common/color"; -export interface IFindInputOptions { +export interface IFindInputOptions extends IFindInputStyles { placeholder?: string; width?: number; validation?: IInputValidator; @@ -27,6 +28,10 @@ export interface IFindInputOptions { appendRegexLabel?: string; } +export interface IFindInputStyles { + checkedBorderColor?: Color; +} + const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); export class FindInput extends Widget { @@ -38,6 +43,7 @@ export class FindInput extends Widget { private placeholder: string; private validation: IInputValidator; private label: string; + private checkedBorderColor: Color; private regex: RegexCheckbox; private wholeWords: WholeWordsCheckbox; @@ -67,6 +73,7 @@ export class FindInput extends Widget { this.placeholder = options.placeholder || ''; this.validation = options.validation; this.label = options.label || NLS_DEFAULT_LABEL; + this.checkedBorderColor = options.checkedBorderColor; this.regex = null; this.wholeWords = null; @@ -132,6 +139,20 @@ export class FindInput extends Widget { } } + public style(styles: IFindInputStyles) { + this.checkedBorderColor = styles.checkedBorderColor; + this._applyStyles(); + } + + protected _applyStyles() { + if (this.domNode) { + const styles = { checkedBorderColor: this.checkedBorderColor }; + this.regex.style(styles); + this.wholeWords.style(styles); + this.caseSensitive.style(styles); + } + } + public select(): void { this.inputBox.select(); } @@ -207,7 +228,8 @@ export class FindInput extends Widget { } this.setInputWidth(); this.validate(); - } + }, + checkedBorderColor: this.checkedBorderColor })); this.wholeWords = this._register(new WholeWordsCheckbox({ appendTitle: appendWholeWordsLabel, @@ -219,7 +241,8 @@ export class FindInput extends Widget { } this.setInputWidth(); this.validate(); - } + }, + checkedBorderColor: this.checkedBorderColor })); this.caseSensitive = this._register(new CaseSensitiveCheckbox({ appendTitle: appendCaseSensitiveLabel, @@ -234,7 +257,8 @@ export class FindInput extends Widget { }, onKeyDown: (e) => { this._onCaseSensitiveKeyDown.fire(e); - } + }, + checkedBorderColor: this.checkedBorderColor })); // Arrow-Key support to navigate between options diff --git a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts index e15aafbc407..0230dd1d304 100644 --- a/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts +++ b/src/vs/base/browser/ui/findinput/findInputCheckboxes.ts @@ -9,12 +9,14 @@ import 'vs/css!./findInputCheckboxes'; import * as nls from 'vs/nls'; import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { Color } from "vs/base/common/color"; export interface IFindInputCheckboxOpts { appendTitle: string; isChecked: boolean; onChange: (viaKeyboard: boolean) => void; onKeyDown?: (e: IKeyboardEvent) => void; + checkedBorderColor?: Color; } const NLS_CASE_SENSITIVE_CHECKBOX_LABEL = nls.localize('caseDescription', "Match Case"); @@ -28,7 +30,8 @@ export class CaseSensitiveCheckbox extends Checkbox { title: NLS_CASE_SENSITIVE_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, onChange: opts.onChange, - onKeyDown: opts.onKeyDown + onKeyDown: opts.onKeyDown, + checkedBorderColor: opts.checkedBorderColor }); } } @@ -40,7 +43,8 @@ export class WholeWordsCheckbox extends Checkbox { title: NLS_WHOLE_WORD_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, onChange: opts.onChange, - onKeyDown: opts.onKeyDown + onKeyDown: opts.onKeyDown, + checkedBorderColor: opts.checkedBorderColor }); } } @@ -52,7 +56,8 @@ export class RegexCheckbox extends Checkbox { title: NLS_REGEX_CHECKBOX_LABEL + opts.appendTitle, isChecked: opts.isChecked, onChange: opts.onChange, - onKeyDown: opts.onKeyDown + onKeyDown: opts.onKeyDown, + checkedBorderColor: opts.checkedBorderColor }); } } diff --git a/src/vs/editor/contrib/find/browser/find.ts b/src/vs/editor/contrib/find/browser/find.ts index f283b487585..6ee4e8d0518 100644 --- a/src/vs/editor/contrib/find/browser/find.ts +++ b/src/vs/editor/contrib/find/browser/find.ts @@ -12,6 +12,7 @@ import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions'; import { FindWidget, IFindController } from 'vs/editor/contrib/find/browser/findWidget'; import { FindOptionsWidget } from 'vs/editor/contrib/find/browser/findOptionsWidget'; import { CommonFindController, FindStartFocusAction, IFindStartOptions } from 'vs/editor/contrib/find/common/findController'; +import { IThemeService } from "vs/platform/theme/common/themeService"; @editorContribution export class FindController extends CommonFindController implements IFindController { @@ -23,11 +24,12 @@ export class FindController extends CommonFindController implements IFindControl editor: ICodeEditor, @IContextViewService contextViewService: IContextViewService, @IContextKeyService contextKeyService: IContextKeyService, - @IKeybindingService keybindingService: IKeybindingService + @IKeybindingService keybindingService: IKeybindingService, + @IThemeService themeService: IThemeService ) { super(editor, contextKeyService); - this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService, contextKeyService)); + this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService, contextKeyService, themeService)); this._findOptionsWidget = this._register(new FindOptionsWidget(editor, this._state, keybindingService)); } diff --git a/src/vs/editor/contrib/find/browser/findWidget.css b/src/vs/editor/contrib/find/browser/findWidget.css index 91f4f37bd69..776ccfaa856 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.css +++ b/src/vs/editor/contrib/find/browser/findWidget.css @@ -65,11 +65,6 @@ min-height: 0; } -.monaco-editor .find-widget .monaco-findInput, -.monaco-editor .find-widget .replace-input { - background-color: white; -} - .monaco-editor .find-widget .replace-input .input { font-size: 13px; } @@ -136,7 +131,7 @@ } .monaco-editor .find-widget .button:not(.disabled):hover { - background-color: #DDD; + background-color: rgba(0, 0, 0, 0.1); } .monaco-editor .find-widget .button.left { @@ -279,7 +274,6 @@ } .monaco-editor .findMatch { - background-color: rgba(234, 92, 0, 0.3); -webkit-animation-duration: 0; -webkit-animation-name: inherit !important; -moz-animation-duration: 0; @@ -290,22 +284,12 @@ animation-name: inherit !important; } -.monaco-editor .currentFindMatch { - background-color: #A8AC94; -} - -.monaco-editor .findScope { - background-color: rgba(180, 180, 180, 0.3); -} - /* Theming */ .monaco-editor .find-widget { - background-color: #EFEFF2; box-shadow: 0 2px 8px #A8A8A8; } .monaco-editor.vs-dark .find-widget { - background-color: #2D2D30; box-shadow: 0 2px 8px #000; } @@ -325,11 +309,11 @@ } .monaco-editor.vs-dark .find-widget .monaco-checkbox .checkbox:not(:disabled):hover:before + .label { - background-color: #2f3334; + background-color: rgba(255, 255, 255, 0.1); } .monaco-editor.vs-dark .find-widget .monaco-checkbox .checkbox:checked + .label { - background-color: rgba(150, 150, 150, 0.3); + background-color: rgba(255, 255, 255, 0.1); } .monaco-editor.hc-black .find-widget .close-fw, @@ -359,28 +343,10 @@ .monaco-editor.hc-black .find-widget .button:not(.disabled):hover, .monaco-editor.vs-dark .find-widget .button:not(.disabled):hover { - background-color: #2f3334; -} - -.monaco-editor.vs-dark .currentFindMatch { - background-color: #515C6A; -} - -.monaco-editor.vs-dark .findScope { - background-color: rgba(58, 61, 65, 0.4); -} - -.monaco-editor.vs-dark .find-widget .monaco-findInput, -.monaco-editor.vs-dark .find-widget .replace-input { - background-color: #3C3C3C; + background-color: rgba(255, 255, 255, 0.1); } /* High Contrast Theming */ -.monaco-editor.hc-black .find-widget { - border: 2px solid #6FC3DF; - background: #0C141F; - box-shadow: none; -} .monaco-editor.hc-black .find-widget .button:before { position: relative; @@ -389,31 +355,5 @@ } .monaco-editor.hc-black .find-widget .monaco-checkbox .checkbox:checked + .label { - background-color: rgba(150, 150, 150, 0.3); -} - -.monaco-editor.hc-black .findMatch { - background: none; - border: 1px dotted #f38518; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.monaco-editor.hc-black .currentFindMatch { - background: none; - padding: 1px; - border: 2px solid #f38518; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.monaco-editor.hc-black .findScope { - background: none; - border: 1px dashed #f38518; - opacity: .4; -} - -.monaco-editor.hc-black .find-widget .monaco-findInput, -.monaco-editor.hc-black .find-widget .replace-input { - background-color: #000; -} + background-color: rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index 5dc01c2872b..1f5ff721be1 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -24,10 +24,9 @@ import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contri import { Range } from 'vs/editor/common/core/range'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { CONTEXT_FIND_INPUT_FOCUSSED } from 'vs/editor/contrib/find/common/findController'; - -import * as colorRegistry from 'vs/platform/theme/common/colorRegistry'; -import { ITheme, ICssStyleCollector, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { ITheme, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; +import { editorFindRangeHighlight, editorCurrentFindMatchHighlight, editorFindMatchHighlight, registerColor, highContrastOutline, highContrastBorder } from "vs/platform/theme/common/colorRegistry"; export interface IFindController { replace(): void; @@ -90,7 +89,8 @@ export class FindWidget extends Widget implements IOverlayWidget { state: FindReplaceState, contextViewProvider: IContextViewProvider, keybindingService: IKeybindingService, - contextKeyService: IContextKeyService + contextKeyService: IContextKeyService, + themeService: IThemeService ) { super(); this._codeEditor = codeEditor; @@ -168,6 +168,9 @@ export class FindWidget extends Widget implements IOverlayWidget { }); this._codeEditor.addOverlayWidget(this); + + this._applyTheme(themeService.getTheme()); + this._register(themeService.onThemeChange(this._applyTheme.bind(this))); } // ----- IOverlayWidget API @@ -344,6 +347,11 @@ export class FindWidget extends Widget implements IOverlayWidget { } } + private _applyTheme(theme: ITheme) { + let inputStyles = { checkedBorderColor: theme.getColor(editorFindCheckedBorders) }; + this._findInput.style(inputStyles); + } + // ----- Public public focusFindInput(): void { @@ -778,14 +786,39 @@ class SimpleButton extends Widget { } } -registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { - addBackgroundColorRule(theme, '.findMatch', theme.getColor(colorRegistry.editorFindMatchHighlight), collector); - addBackgroundColorRule(theme, '.currentFindMatch', theme.getColor(colorRegistry.editorCurrentFindMatchHighlight), collector); - addBackgroundColorRule(theme, '.findScope', theme.getColor(colorRegistry.editorFindRangeHighlight), collector); +// theming + +export const editorFindWidgetBackground = registerColor('editorFindWidgetBackground', { dark: '#2D2D30', light: '#EFEFF2', hc: '#0C141F' }, nls.localize('editorFindWidgetBackground', 'Find widget background')); +export const editorFindInputBackground = registerColor('editorFindInputBackground', { dark: '#3C3C3C', light: Color.white, hc: Color.black }, nls.localize('editorFindInputBackground', 'Find widget input field background')); +export const editorFindCheckedBorders = registerColor('editorFindCheckedBorders', { dark: '#007ACC', light: '#007ACC', hc: highContrastOutline }, nls.localize('editorFindCheckedBorders', 'Find widget checked border color')); + +registerThemingParticipant((theme, collector) => { + function addBackgroundColorRule(selector: string, color: Color): void { + if (color) { + collector.addRule(`.monaco-editor.${theme.selector} ${selector} { background-color: ${color}; }`); + } + } + + addBackgroundColorRule('.findMatch', theme.getColor(editorFindMatchHighlight)); + addBackgroundColorRule('.currentFindMatch', theme.getColor(editorCurrentFindMatchHighlight)); + addBackgroundColorRule('.findScope', theme.getColor(editorFindRangeHighlight)); + + let inputBackground = theme.getColor(editorFindInputBackground); + addBackgroundColorRule('.find-widget .monaco-findInput', inputBackground); + addBackgroundColorRule('.find-widget .replace-input', inputBackground); + + let widgetBackground = theme.getColor(editorFindWidgetBackground); + addBackgroundColorRule('.find-widget', widgetBackground); + + let hcOutline = theme.getColor(highContrastOutline); + if (hcOutline) { + collector.addRule(`.monaco-editor.${theme.selector} .findScope { border: 1px dashed ${hcOutline.transparent(0.4)}; }`); + collector.addRule(`.monaco-editor.${theme.selector} .currentFindMatch { border: 2px solid ${hcOutline}; padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; }`); + collector.addRule(`.monaco-editor.${theme.selector} .findMatch { border: 1px dotted ${hcOutline}; -moz-box-sizing: border-box; box-sizing: border-box; }`); + } + let hcBorder = theme.getColor(highContrastBorder); + if (hcBorder) { + collector.addRule(`.monaco-editor.${theme.selector} .find-widget { border: 2px solid ${hcBorder}; box-shadow: none; }`); + } }); -function addBackgroundColorRule(theme: ITheme, selector: string, color: Color, collector: ICssStyleCollector): void { - if (color) { - collector.addRule(`.monaco-editor.${theme.selector} ${selector} { background-color: ${color}; }`); - } -} \ No newline at end of file