diff --git a/src/vs/workbench/parts/search/browser/media/searchviewlet.css b/src/vs/workbench/parts/search/browser/media/searchviewlet.css index efe80207fc91e..e9cf57c2accfc 100644 --- a/src/vs/workbench/parts/search/browser/media/searchviewlet.css +++ b/src/vs/workbench/parts/search/browser/media/searchviewlet.css @@ -292,6 +292,16 @@ animation-name: inherit !important; } +.search-viewlet .replace.findInFileMatch { + text-decoration: line-through; + background-color: rgba(255, 0, 0, 0.2); +} + +.search-viewlet .replaceMatch { + background-color: rgba(155, 185, 85, 0.5); +} + +.hc-black .monaco-workbench .search-viewlet .replaceMatch, .hc-black .monaco-workbench .search-viewlet .findInFileMatch, .monaco-editor.hc-black .findInFileMatch { background: none !important; @@ -299,18 +309,12 @@ box-sizing: border-box; } - -.search-viewlet .replaceMatch { - background-color: rgba(234, 92, 0, 0.45); -} - -.search-viewlet .removeMatch { - text-decoration: line-through; +.hc-black .monaco-workbench .search-viewlet .replace.findInFileMatch { + border: 1px dashed #FF008F; } -.hc-black .monaco-workbench .search-viewlet .replaceMatch, -.monaco-editor.hc-black .replaceMatch { - border-color: #F44336; +.hc-black .monaco-workbench .search-viewlet .replaceMatch { + border: 1px dashed rgb(51, 255, 46); } /* Theming */ diff --git a/src/vs/workbench/parts/search/browser/searchResultsView.ts b/src/vs/workbench/parts/search/browser/searchResultsView.ts index e57e3461ea725..0fa48569c7025 100644 --- a/src/vs/workbench/parts/search/browser/searchResultsView.ts +++ b/src/vs/workbench/parts/search/browser/searchResultsView.ts @@ -173,18 +173,11 @@ export class SearchRenderer extends ActionsRenderer { elements.push(strings.escape(preview.before)); let input= tree.getInput(); + elements.push(''); + elements.push(strings.escape(preview.inside)); if (input.isReplaceActive()) { - let replaceValue= input.replaceText; - if (replaceValue) { - elements.push(''); - elements.push(strings.escape(replaceValue)); - } else { - elements.push(''); - elements.push(strings.escape(preview.inside)); - } - } else { - elements.push(''); - elements.push(strings.escape(preview.inside)); + elements.push(''); + elements.push(strings.escape(input.replaceText)); } elements.push(''); elements.push(strings.escape(preview.after)); diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index a0c0f9ce0af38..0fb5ea6df3cb7 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -319,18 +319,21 @@ export class SearchViewlet extends Viewlet { let occurrences= this.viewModel.count(); let fileCount= this.viewModel.fileCount(); - let afterReplaceAllMessage= nls.localize('replaceAll.message', "Replaced {0} occurrences across {1} files.", occurrences, fileCount); + let replaceValue= this.searchWidget.getReplaceValue() || ''; + let afterReplaceAllMessage= replaceValue ? nls.localize('replaceAll.message', "Replaced {0} occurrences across {1} files with {2}.", occurrences, fileCount, replaceValue) + : nls.localize('removeAll.message', "Removed {0} occurrences across {1} files.", occurrences, fileCount); let confirmation= { title: nls.localize('replaceAll.confirmation.title', "Replace All"), - message: nls.localize('replaceAll.confirmation.message', "Replace {0} occurrences across {1} files?", occurrences, fileCount), + message: replaceValue ? nls.localize('replaceAll.confirmation.message', "Replace {0} occurrences with '{1}' across {2} files?", occurrences, replaceValue, fileCount) + : nls.localize('removeAll.confirmation.message', "Remove {0} occurrences across {1} files?", occurrences, fileCount), primaryButton: nls.localize('replaceAll.confirm.button', "Replace") }; if (this.messageService.confirm(confirmation)) { let replaceAllTimer = this.telemetryService.timedPublicLog('replaceAll.started'); this.replacingAll= true; - this.replaceService.replace(this.viewModel.matches(), this.viewModel.replaceText, progressRunner).then(() => { + this.replaceService.replace(this.viewModel.matches(), replaceValue, progressRunner).then(() => { replaceAllTimer.stop(); this.replacingAll= false; setTimeout(() => { diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index ad9595d3d09fd..4470ce5b9cf03 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -28,9 +28,13 @@ export interface ISearchWidgetOptions { export class SearchWidget extends Widget { + private static REPLACE_ALL_DISABLED_LABEL= nls.localize('file.replaceAll.disabled.label', "Replace All (Submit Search to Enable)"); + private static REPLACE_ALL_ENABLED_LABEL= nls.localize('file.replaceAll.enabled.label', "Replace All"); + public domNode: HTMLElement; public searchInput: FindInput; private replaceInput: InputBox; + private searchSubmitted: boolean= false; private replaceInputContainer: HTMLElement; private toggleReplaceButton: Button; @@ -87,12 +91,13 @@ export class SearchWidget extends Widget { } public clear() { + this.searchSubmitted= false; this.searchInput.clear(); this.replaceInput.value= ''; } public isReplaceActive(): boolean { - return this.isReplaceShown() && this.replaceAllAction.enabled; + return this.isReplaceShown() && this.replaceAllAction.enabled && !!this.replaceInput.value; } public isReplaceShown(): boolean { @@ -103,6 +108,14 @@ export class SearchWidget extends Widget { return this.isReplaceActive() ? this.replaceInput.value : null; } + public setReplaceAllActionState(enabled:boolean):void { + if (this.replaceAllAction.enabled !== enabled) { + this.replaceAllAction.enabled= enabled; + this.replaceAllAction.label= enabled ? SearchWidget.REPLACE_ALL_ENABLED_LABEL : SearchWidget.REPLACE_ALL_DISABLED_LABEL; + this._onReplaceState.fire(); + } + } + private render(container: Builder, options: ISearchWidgetOptions): void { this.domNode = container.div({ 'class': 'search-widget' }).style({ position: 'relative' }).getHTMLElement(); this.renderToggleReplaceButton(this.domNode); @@ -133,12 +146,10 @@ export class SearchWidget extends Widget { this.searchInput.setRegex(!!options.isRegex); this.searchInput.setCaseSensitive(!!options.isCaseSensitive); this.searchInput.setWholeWords(!!options.isWholeWords); - this._register(dom.addDisposableListener(this.searchInput.inputBox.inputElement, dom.EventType.FOCUS, () => this.updateReplaceActionState())); - this._register(dom.addDisposableListener(this.searchInput.inputBox.inputElement, dom.EventType.BLUR, () => this.updateReplaceActionState())); } private renderReplaceInput(parent: HTMLElement): void { - this.replaceAllAction = new Action('action-replace-all', nls.localize('file.replaceAll.label', "Replace All"), 'action-replace-all', false, () => { + this.replaceAllAction = new Action('action-replace-all', SearchWidget.REPLACE_ALL_DISABLED_LABEL, 'action-replace-all', false, () => { this._onReplaceAll.fire(); return TPromise.as(null); }); @@ -151,6 +162,8 @@ export class SearchWidget extends Widget { this.onkeydown(this.replaceInput.inputElement, (keyboardEvent) => this.onReplaceInputKeyDown(keyboardEvent)); this.onkeyup(this.replaceInput.inputElement, (keyboardEvent) => this.onReplaceInputKeyUp(keyboardEvent)); this.replaceInput.onDidChange(() => this._onReplaceValueChanged.fire()); + this.searchInput.inputBox.onDidChange(() => this.onSearchInputChanged()); + this.onSearchSubmit(() => this.updateReplaceActionState()); } private onToggleReplaceButton():void { @@ -161,14 +174,9 @@ export class SearchWidget extends Widget { this.updateReplaceActionState(); } - private updateReplaceActionState():boolean { - let enabled= this.isReplaceShown() && !this.searchInput.inputBox.hasFocus(); - if (this.replaceAllAction.enabled !== enabled) { - this.replaceAllAction.enabled= enabled; - this._onReplaceState.fire(); - return true; - } - return false; + private updateReplaceActionState():void { + let enabled= this.isReplaceShown() && this.searchSubmitted; + this.setReplaceAllActionState(enabled); } private validatSearchInput(value: string): any { @@ -189,6 +197,11 @@ export class SearchWidget extends Widget { } } + private onSearchInputChanged(): void { + this.searchSubmitted= false; + this.updateReplaceActionState(); + } + private onSearchInputKeyUp(keyboardEvent: IKeyboardEvent) { switch (keyboardEvent.keyCode) { case KeyCode.Enter: @@ -246,6 +259,7 @@ export class SearchWidget extends Widget { private submitSearch(refresh: boolean= true): void { if (this.searchInput.getValue()) { + this.searchSubmitted= true; this._onSearchSubmit.fire(refresh); } }