update replace input box size when resizing and display preserve case button properly

This commit is contained in:
Peng Lyu 2019-08-20 11:49:59 -07:00
parent 45dd218d90
commit 67145b2732
6 changed files with 476 additions and 81 deletions

View file

@ -24,6 +24,7 @@ export interface IFindInputOptions extends IFindInputStyles {
readonly validation?: IInputValidator;
readonly label: string;
readonly flexibleHeight?: boolean;
readonly flexibleWidth?: boolean;
readonly flexibleMaxHeight?: number;
readonly appendCaseSensitiveLabel?: string;
@ -120,6 +121,7 @@ export class FindInput extends Widget {
const appendRegexLabel = options.appendRegexLabel || '';
const history = options.history || [];
const flexibleHeight = !!options.flexibleHeight;
const flexibleWidth = !!options.flexibleWidth;
const flexibleMaxHeight = options.flexibleMaxHeight;
this.domNode = document.createElement('div');
@ -145,6 +147,7 @@ export class FindInput extends Widget {
inputValidationErrorBorder: this.inputValidationErrorBorder,
history,
flexibleHeight,
flexibleWidth,
flexibleMaxHeight
}));
@ -197,11 +200,7 @@ export class FindInput extends Widget {
}));
if (this._showOptionButtons) {
const paddingRight = (this.caseSensitive.width() + this.wholeWords.width() + this.regex.width()) + 'px';
this.inputBox.inputElement.style.paddingRight = paddingRight;
if (this.inputBox.mirrorElement) {
this.inputBox.mirrorElement.style.paddingRight = paddingRight;
}
this.inputBox.paddingRight = this.caseSensitive.width() + this.wholeWords.width() + this.regex.width();
}
// Arrow-Key support to navigate between options

View file

@ -0,0 +1,378 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./findInput';
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
import { IMessage as InputBoxMessage, IInputValidator, IInputBoxStyles, HistoryInputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { Widget } from 'vs/base/browser/ui/widget';
import { Event, Emitter } from 'vs/base/common/event';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Color } from 'vs/base/common/color';
import { ICheckboxStyles, Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { IFindInputCheckboxOpts } from 'vs/base/browser/ui/findinput/findInputCheckboxes';
export interface IReplaceInputOptions extends IReplaceInputStyles {
readonly placeholder?: string;
readonly width?: number;
readonly validation?: IInputValidator;
readonly label: string;
readonly flexibleHeight?: boolean;
readonly flexibleWidth?: boolean;
readonly flexibleMaxHeight?: number;
readonly history?: string[];
}
export interface IReplaceInputStyles extends IInputBoxStyles {
inputActiveOptionBorder?: Color;
}
const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input");
const NLS_PRESERVE_CASE_LABEL = nls.localize('label.preserveCaseCheckbox', "Preserve Case");
export class PreserveCaseCheckbox extends Checkbox {
constructor(opts: IFindInputCheckboxOpts) {
super({
// TODO: does this need its own icon?
actionClassName: 'monaco-case-sensitive',
title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder
});
}
}
export class ReplaceInput extends Widget {
static readonly OPTION_CHANGE: string = 'optionChange';
private contextViewProvider: IContextViewProvider | undefined;
private placeholder: string;
private validation?: IInputValidator;
private label: string;
private fixFocusOnOptionClickEnabled = true;
private inputActiveOptionBorder?: Color;
private inputBackground?: Color;
private inputForeground?: Color;
private inputBorder?: Color;
private inputValidationInfoBorder?: Color;
private inputValidationInfoBackground?: Color;
private inputValidationInfoForeground?: Color;
private inputValidationWarningBorder?: Color;
private inputValidationWarningBackground?: Color;
private inputValidationWarningForeground?: Color;
private inputValidationErrorBorder?: Color;
private inputValidationErrorBackground?: Color;
private inputValidationErrorForeground?: Color;
private preserveCase: PreserveCaseCheckbox;
private cachedOptionsWidth: number = 0;
public domNode: HTMLElement;
public inputBox: HistoryInputBox;
private readonly _onDidOptionChange = this._register(new Emitter<boolean>());
public readonly onDidOptionChange: Event<boolean /* via keyboard */> = this._onDidOptionChange.event;
private readonly _onKeyDown = this._register(new Emitter<IKeyboardEvent>());
public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;
private readonly _onMouseDown = this._register(new Emitter<IMouseEvent>());
public readonly onMouseDown: Event<IMouseEvent> = this._onMouseDown.event;
private readonly _onInput = this._register(new Emitter<void>());
public readonly onInput: Event<void> = this._onInput.event;
private readonly _onKeyUp = this._register(new Emitter<IKeyboardEvent>());
public readonly onKeyUp: Event<IKeyboardEvent> = this._onKeyUp.event;
private _onPreserveCaseKeyDown = this._register(new Emitter<IKeyboardEvent>());
public readonly onPreserveCaseKeyDown: Event<IKeyboardEvent> = this._onPreserveCaseKeyDown.event;
constructor(parent: HTMLElement | null, contextViewProvider: IContextViewProvider | undefined, private readonly _showOptionButtons: boolean, options: IReplaceInputOptions) {
super();
this.contextViewProvider = contextViewProvider;
this.placeholder = options.placeholder || '';
this.validation = options.validation;
this.label = options.label || NLS_DEFAULT_LABEL;
this.inputActiveOptionBorder = options.inputActiveOptionBorder;
this.inputBackground = options.inputBackground;
this.inputForeground = options.inputForeground;
this.inputBorder = options.inputBorder;
this.inputValidationInfoBorder = options.inputValidationInfoBorder;
this.inputValidationInfoBackground = options.inputValidationInfoBackground;
this.inputValidationInfoForeground = options.inputValidationInfoForeground;
this.inputValidationWarningBorder = options.inputValidationWarningBorder;
this.inputValidationWarningBackground = options.inputValidationWarningBackground;
this.inputValidationWarningForeground = options.inputValidationWarningForeground;
this.inputValidationErrorBorder = options.inputValidationErrorBorder;
this.inputValidationErrorBackground = options.inputValidationErrorBackground;
this.inputValidationErrorForeground = options.inputValidationErrorForeground;
const flexibleHeight = !!options.flexibleHeight;
const flexibleWidth = !!options.flexibleWidth;
const flexibleMaxHeight = options.flexibleMaxHeight;
this.buildDomNode(options.history || [], flexibleHeight, flexibleWidth, flexibleMaxHeight);
if (parent) {
parent.appendChild(this.domNode);
}
this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));
this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));
this.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());
this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));
}
public enable(): void {
dom.removeClass(this.domNode, 'disabled');
this.inputBox.enable();
this.preserveCase.enable();
}
public disable(): void {
dom.addClass(this.domNode, 'disabled');
this.inputBox.disable();
this.preserveCase.disable();
}
public setFocusInputOnOptionClick(value: boolean): void {
this.fixFocusOnOptionClickEnabled = value;
}
public setEnabled(enabled: boolean): void {
if (enabled) {
this.enable();
} else {
this.disable();
}
}
public clear(): void {
this.clearValidation();
this.setValue('');
this.focus();
}
public getValue(): string {
return this.inputBox.value;
}
public setValue(value: string): void {
if (this.inputBox.value !== value) {
this.inputBox.value = value;
}
}
public onSearchSubmit(): void {
this.inputBox.addToHistory();
}
public style(styles: IReplaceInputStyles): void {
this.inputActiveOptionBorder = styles.inputActiveOptionBorder;
this.inputBackground = styles.inputBackground;
this.inputForeground = styles.inputForeground;
this.inputBorder = styles.inputBorder;
this.inputValidationInfoBackground = styles.inputValidationInfoBackground;
this.inputValidationInfoForeground = styles.inputValidationInfoForeground;
this.inputValidationInfoBorder = styles.inputValidationInfoBorder;
this.inputValidationWarningBackground = styles.inputValidationWarningBackground;
this.inputValidationWarningForeground = styles.inputValidationWarningForeground;
this.inputValidationWarningBorder = styles.inputValidationWarningBorder;
this.inputValidationErrorBackground = styles.inputValidationErrorBackground;
this.inputValidationErrorForeground = styles.inputValidationErrorForeground;
this.inputValidationErrorBorder = styles.inputValidationErrorBorder;
this.applyStyles();
}
protected applyStyles(): void {
if (this.domNode) {
const checkBoxStyles: ICheckboxStyles = {
inputActiveOptionBorder: this.inputActiveOptionBorder,
};
this.preserveCase.style(checkBoxStyles);
const inputBoxStyles: IInputBoxStyles = {
inputBackground: this.inputBackground,
inputForeground: this.inputForeground,
inputBorder: this.inputBorder,
inputValidationInfoBackground: this.inputValidationInfoBackground,
inputValidationInfoForeground: this.inputValidationInfoForeground,
inputValidationInfoBorder: this.inputValidationInfoBorder,
inputValidationWarningBackground: this.inputValidationWarningBackground,
inputValidationWarningForeground: this.inputValidationWarningForeground,
inputValidationWarningBorder: this.inputValidationWarningBorder,
inputValidationErrorBackground: this.inputValidationErrorBackground,
inputValidationErrorForeground: this.inputValidationErrorForeground,
inputValidationErrorBorder: this.inputValidationErrorBorder
};
this.inputBox.style(inputBoxStyles);
}
}
public select(): void {
this.inputBox.select();
}
public focus(): void {
this.inputBox.focus();
}
public getPreserveCase(): boolean {
return this.preserveCase.checked;
}
public setPreserveCase(value: boolean): void {
this.preserveCase.checked = value;
}
public focusOnPreserve(): void {
this.preserveCase.focus();
}
private _lastHighlightFindOptions: number = 0;
public highlightFindOptions(): void {
dom.removeClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions));
this._lastHighlightFindOptions = 1 - this._lastHighlightFindOptions;
dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions));
}
private buildDomNode(history: string[], flexibleHeight: boolean, flexibleWidth: boolean, flexibleMaxHeight: number | undefined): void {
this.domNode = document.createElement('div');
dom.addClass(this.domNode, 'monaco-findInput');
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
ariaLabel: this.label || '',
placeholder: this.placeholder || '',
validationOptions: {
validation: this.validation
},
inputBackground: this.inputBackground,
inputForeground: this.inputForeground,
inputBorder: this.inputBorder,
inputValidationInfoBackground: this.inputValidationInfoBackground,
inputValidationInfoForeground: this.inputValidationInfoForeground,
inputValidationInfoBorder: this.inputValidationInfoBorder,
inputValidationWarningBackground: this.inputValidationWarningBackground,
inputValidationWarningForeground: this.inputValidationWarningForeground,
inputValidationWarningBorder: this.inputValidationWarningBorder,
inputValidationErrorBackground: this.inputValidationErrorBackground,
inputValidationErrorForeground: this.inputValidationErrorForeground,
inputValidationErrorBorder: this.inputValidationErrorBorder,
history,
flexibleHeight,
flexibleWidth,
flexibleMaxHeight
}));
this.preserveCase = this._register(new PreserveCaseCheckbox({
appendTitle: '',
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder
}));
this._register(this.preserveCase.onChange(viaKeyboard => {
this._onDidOptionChange.fire(viaKeyboard);
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
this.inputBox.focus();
}
this.validate();
}));
this._register(this.preserveCase.onKeyDown(e => {
this._onPreserveCaseKeyDown.fire(e);
}));
if (this._showOptionButtons) {
this.cachedOptionsWidth = this.preserveCase.width();
// const paddingRight = () + 'px';
// this.inputBox.inputElement.style.paddingRight = paddingRight;
// if (this.inputBox.mirrorElement) {
// this.inputBox.mirrorElement.style.paddingRight = paddingRight;
// }
} else {
this.cachedOptionsWidth = 0;
}
// Arrow-Key support to navigate between options
let indexes = [this.preserveCase.domNode];
this.onkeydown(this.domNode, (event: IKeyboardEvent) => {
if (event.equals(KeyCode.LeftArrow) || event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Escape)) {
let index = indexes.indexOf(<HTMLElement>document.activeElement);
if (index >= 0) {
let newIndex: number = -1;
if (event.equals(KeyCode.RightArrow)) {
newIndex = (index + 1) % indexes.length;
} else if (event.equals(KeyCode.LeftArrow)) {
if (index === 0) {
newIndex = indexes.length - 1;
} else {
newIndex = index - 1;
}
}
if (event.equals(KeyCode.Escape)) {
indexes[index].blur();
} else if (newIndex >= 0) {
indexes[newIndex].focus();
}
dom.EventHelper.stop(event, true);
}
}
});
let controls = document.createElement('div');
controls.className = 'controls';
controls.style.display = this._showOptionButtons ? 'block' : 'none';
controls.appendChild(this.preserveCase.domNode);
this.domNode.appendChild(controls);
}
public validate(): void {
if (this.inputBox) {
this.inputBox.validate();
}
}
public showMessage(message: InputBoxMessage): void {
if (this.inputBox) {
this.inputBox.showMessage(message);
}
}
public clearMessage(): void {
if (this.inputBox) {
this.inputBox.hideMessage();
}
}
private clearValidation(): void {
if (this.inputBox) {
this.inputBox.hideMessage();
}
}
public set width(newWidth: number) {
this.inputBox.paddingRight = this.cachedOptionsWidth;
this.inputBox.width = newWidth;
this.domNode.style.width = newWidth + 'px';
}
public dispose(): void {
super.dispose();
}
}

View file

@ -32,6 +32,7 @@ export interface IInputOptions extends IInputBoxStyles {
readonly type?: string;
readonly validationOptions?: IInputValidationOptions;
readonly flexibleHeight?: boolean;
readonly flexibleWidth?: boolean;
readonly flexibleMaxHeight?: number;
readonly actions?: ReadonlyArray<IAction>;
}
@ -173,6 +174,12 @@ export class InputBox extends Widget {
this.mirror.innerHTML = '&nbsp;';
this.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });
if (this.options.flexibleWidth) {
this.input.setAttribute('wrap', 'off');
this.mirror.style.whiteSpace = 'pre';
}
dom.append(container, this.scrollableElement.getDomNode());
this._register(this.scrollableElement);
@ -321,12 +328,36 @@ export class InputBox extends Widget {
}
public set width(width: number) {
this.input.style.width = width + 'px';
if (this.options.flexibleHeight && this.options.flexibleWidth) {
// textarea with horizontal scrolling
let horizontalPadding = 0;
if (this.mirror) {
const paddingLeft = parseFloat(this.mirror.style.paddingLeft || '') || 0;
const paddingRight = parseFloat(this.mirror.style.paddingRight || '') || 0;
horizontalPadding = paddingLeft + paddingRight;
}
this.input.style.width = (width - horizontalPadding) + 'px';
} else {
this.input.style.width = width + 'px';
}
if (this.mirror) {
this.mirror.style.width = width + 'px';
}
}
public set paddingRight(paddingRight: number) {
if (this.options.flexibleHeight && this.options.flexibleWidth) {
this.input.style.width = `calc(100% - ${paddingRight}px)`;
} else {
this.input.style.paddingRight = paddingRight + 'px';
}
if (this.mirror) {
this.mirror.style.paddingRight = paddingRight + 'px';
}
}
private updateScrollDimensions(): void {
if (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number') {
return;

View file

@ -62,7 +62,7 @@
min-height: 0;
}
.monaco-editor .find-widget .replace-input .input {
.monaco-editor .find-widget .monaco-findInput .input {
font-size: 13px;
}
@ -79,12 +79,8 @@
min-height: 25px;
}
.monaco-editor .find-widget > .find-part .monaco-inputbox > .wrapper > .input {
width: 100% !important;
padding-right: 66px;
}
.monaco-editor .find-widget > .replace-part .monaco-inputbox > .wrapper > .input {
.monaco-editor .find-widget > .replace-part .monaco-inputbox > .wrapper > .mirror {
padding-right: 22px;
}
@ -120,8 +116,7 @@
width: 100%;
}
.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element .scrollbar.vertical,
.monaco-editor .find-widget .replace-input .monaco-scrollable-element .scrollbar.vertical {
.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element .scrollbar.vertical {
/* Hide vertical scrollbar */
opacity: 0;
}
@ -257,15 +252,17 @@
display: none;
}
.monaco-editor .find-widget > .replace-part > .replace-input {
.monaco-editor .find-widget > .replace-part > .monaco-findInput {
position: relative;
display: flex;
display: -webkit-flex;
vertical-align: middle;
width: auto !important;
flex: auto;
flex-grow: 0;
flex-shrink: 0;
}
.monaco-editor .find-widget > .replace-part > .replace-input > .controls {
.monaco-editor .find-widget > .replace-part > .monaco-findInput > .controls {
position: absolute;
top: 3px;
right: 2px;

View file

@ -10,10 +10,9 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { FindInput, IFindInputStyles } from 'vs/base/browser/ui/findinput/findInput';
import { HistoryInputBox, IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox';
import { IMessage as InputBoxMessage } from 'vs/base/browser/ui/inputbox/inputBox';
import { IHorizontalSashLayoutProvider, ISashEvent, Orientation, Sash } from 'vs/base/browser/ui/sash/sash';
import { Widget } from 'vs/base/browser/ui/widget';
import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox';
import { Delayer } from 'vs/base/common/async';
import { Color } from 'vs/base/common/color';
import { onUnexpectedError } from 'vs/base/common/errors';
@ -30,9 +29,10 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { contrastBorder, editorFindMatch, editorFindMatchBorder, editorFindMatchHighlight, editorFindMatchHighlightBorder, editorFindRangeHighlight, editorFindRangeHighlightBorder, editorWidgetBackground, editorWidgetBorder, editorWidgetResizeBorder, errorForeground, inputActiveOptionBorder, inputActiveOptionBackground, inputBackground, inputBorder, inputForeground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, inputValidationInfoBackground, inputValidationInfoBorder, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningBorder, inputValidationWarningForeground, widgetShadow, editorWidgetForeground } from 'vs/platform/theme/common/colorRegistry';
import { ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ContextScopedFindInput, ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedHistoryWidget';
import { ContextScopedFindInput, ContextScopedReplaceInput } from 'vs/platform/browser/contextScopedHistoryWidget';
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { alert as alertFn } from 'vs/base/browser/ui/aria/aria';
import { ReplaceInput } from 'vs/base/browser/ui/findinput/replaceInput';
export interface IFindController {
replace(): void;
@ -48,7 +48,6 @@ const NLS_TOGGLE_SELECTION_FIND_TITLE = nls.localize('label.toggleSelectionFind'
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
const NLS_REPLACE_INPUT_LABEL = nls.localize('label.replace', "Replace");
const NLS_REPLACE_INPUT_PLACEHOLDER = nls.localize('placeholder.replace', "Replace");
const NLS_PRESERVE_CASE_LABEL = nls.localize('label.preserveCaseCheckbox', "Preserve Case");
const NLS_REPLACE_BTN_LABEL = nls.localize('label.replaceButton', "Replace");
const NLS_REPLACE_ALL_BTN_LABEL = nls.localize('label.replaceAllButton', "Replace All");
const NLS_TOGGLE_REPLACE_MODE_BTN_LABEL = nls.localize('label.toggleReplaceButton', "Toggle Replace mode");
@ -59,7 +58,6 @@ const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results");
const FIND_WIDGET_INITIAL_WIDTH = 411;
const PART_WIDTH = 275;
const FIND_INPUT_AREA_WIDTH = PART_WIDTH - 54;
const REPLACE_INPUT_AREA_WIDTH = FIND_INPUT_AREA_WIDTH;
let MAX_MATCHES_COUNT_WIDTH = 69;
let FIND_ALL_CONTROLS_WIDTH = 17/** Find Input margin-left */ + (MAX_MATCHES_COUNT_WIDTH + 3 + 1) /** Match Results */ + 23 /** Button */ * 4 + 2/** sash */;
@ -110,7 +108,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private _domNode!: HTMLElement;
private _cachedHeight: number | null;
private _findInput!: FindInput;
private _replaceInputBox!: HistoryInputBox;
private _replaceInput!: ReplaceInput;
private _toggleReplaceBtn!: SimpleButton;
private _matchesCount!: HTMLElement;
@ -118,7 +116,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private _nextBtn!: SimpleButton;
private _toggleSelectionFind!: SimpleCheckbox;
private _closeBtn!: SimpleButton;
private _preserveCase!: Checkbox;
private _replaceBtn!: SimpleButton;
private _replaceAllBtn!: SimpleButton;
@ -218,7 +215,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}));
this._replaceInputFocused = CONTEXT_REPLACE_INPUT_FOCUSED.bindTo(contextKeyService);
this._replaceFocusTracker = this._register(dom.trackFocus(this._replaceInputBox.inputElement));
this._replaceFocusTracker = this._register(dom.trackFocus(this._replaceInput.inputBox.inputElement));
this._register(this._replaceFocusTracker.onDidFocus(() => {
this._replaceInputFocused.set(true);
this._updateSearchScope();
@ -288,7 +285,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._updateButtons();
}
if (e.replaceString) {
this._replaceInputBox.value = this._state.replaceString;
this._replaceInput.inputBox.value = this._state.replaceString;
}
if (e.isRevealed) {
if (this._state.isRevealed) {
@ -301,7 +298,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
if (this._state.isReplaceRevealed) {
if (!this._codeEditor.getConfiguration().readOnly && !this._isReplaceVisible) {
this._isReplaceVisible = true;
this._replaceInputBox.width = this._findInput.inputBox.width;
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
this._updateButtons();
}
} else {
@ -358,7 +355,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._findInput.inputBox.addToHistory();
}
if (this._state.replaceString) {
this._replaceInputBox.addToHistory();
this._replaceInput.inputBox.addToHistory();
}
}
@ -423,7 +420,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private _updateButtons(): void {
this._findInput.setEnabled(this._isVisible);
this._replaceInputBox.setEnabled(this._isVisible && this._isReplaceVisible);
this._replaceInput.setEnabled(this._isVisible && this._isReplaceVisible);
this._updateToggleSelectionFindButton();
this._closeBtn.setEnabled(this._isVisible);
@ -617,8 +614,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
inputValidationErrorBorder: theme.getColor(inputValidationErrorBorder),
};
this._findInput.style(inputStyles);
this._replaceInputBox.style(inputStyles);
this._preserveCase.style(inputStyles);
this._replaceInput.style(inputStyles);
}
private _tryUpdateWidgetWidth() {
@ -648,7 +644,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
if (widgetWidth > FIND_WIDGET_INITIAL_WIDTH) {
// as the widget is resized by users, we may need to change the max width of the widget as the editor width changes.
this._domNode.style.maxWidth = `${editorWidth - 28 - minimapWidth - 15}px`;
this._replaceInputBox.width = dom.getTotalWidth(this._findInput.inputBox.inputElement);
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
return;
}
}
@ -675,7 +671,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._findInput.inputBox.layout();
let findInputWidth = this._findInput.inputBox.width;
if (findInputWidth > 0) {
this._replaceInputBox.width = findInputWidth;
this._replaceInput.width = findInputWidth;
}
}
}
@ -693,7 +689,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
// replace input margin
totalheight += 4;
totalheight += this._replaceInputBox.height + 2 /** input box border */;
totalheight += this._replaceInput.inputBox.height + 2 /** input box border */;
}
// margin bottom
@ -722,9 +718,9 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
public focusReplaceInput(): void {
this._replaceInputBox.select();
this._replaceInput.select();
// Edge browser requires focus() in addition to select()
this._replaceInputBox.focus();
this._replaceInput.focus();
}
public highlightFindOptions(): void {
@ -790,7 +786,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
if (e.equals(KeyCode.Tab)) {
if (this._isReplaceVisible) {
this._replaceInputBox.focus();
this._replaceInput.focus();
} else {
this._findInput.focusOnCaseSensitive();
}
@ -822,16 +818,16 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
if (e.equals(KeyMod.WinCtrl | KeyCode.Enter)) {
const inputElement = this._replaceInputBox.inputElement;
const inputElement = this._replaceInput.inputBox.inputElement;
const start = inputElement.selectionStart;
const end = inputElement.selectionEnd;
const content = inputElement.value;
if (start && end) {
const value = content.substr(0, start) + '\n' + content.substr(end);
this._replaceInputBox.value = value;
this._replaceInput.inputBox.value = value;
inputElement.setSelectionRange(start + 1, start + 1);
this._replaceInputBox.layout();
this._replaceInput.inputBox.layout();
e.preventDefault();
return;
}
@ -862,11 +858,11 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
if (e.equals(KeyCode.UpArrow)) {
return stopPropagationForMultiLineUpwards(e, this._replaceInputBox.value, this._replaceInputBox.element.querySelector('textarea'));
return stopPropagationForMultiLineUpwards(e, this._replaceInput.inputBox.value, this._replaceInput.inputBox.element.querySelector('textarea'));
}
if (e.equals(KeyCode.DownArrow)) {
return stopPropagationForMultiLineDownwards(e, this._replaceInputBox.value, this._replaceInputBox.element.querySelector('textarea'));
return stopPropagationForMultiLineDownwards(e, this._replaceInput.inputBox.value, this._replaceInput.inputBox.element.querySelector('textarea'));
}
}
@ -913,6 +909,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
},
flexibleHeight: true,
flexibleWidth: true,
flexibleMaxHeight: 118
}, this._contextKeyService, true));
this._findInput.setRegex(!!this._state.isRegex);
@ -935,7 +932,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._register(this._findInput.onCaseSensitiveKeyDown((e) => {
if (e.equals(KeyMod.Shift | KeyCode.Tab)) {
if (this._isReplaceVisible) {
this._replaceInputBox.focus();
this._replaceInput.focus();
e.preventDefault();
}
}
@ -943,7 +940,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._register(this._findInput.onRegexKeyDown((e) => {
if (e.equals(KeyCode.Tab)) {
if (this._isReplaceVisible) {
this._preserveCase.focus();
this._replaceInput.focusOnPreserve();
e.preventDefault();
}
}
@ -1034,41 +1031,30 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
actionsContainer.appendChild(this._closeBtn.domNode);
// Replace input
let replaceInput = document.createElement('div');
replaceInput.className = 'replace-input';
replaceInput.style.width = REPLACE_INPUT_AREA_WIDTH + 'px';
this._replaceInputBox = this._register(new ContextScopedHistoryInputBox(replaceInput, undefined, {
ariaLabel: NLS_REPLACE_INPUT_LABEL,
this._replaceInput = this._register(new ContextScopedReplaceInput(null, undefined, {
label: NLS_REPLACE_INPUT_LABEL,
placeholder: NLS_REPLACE_INPUT_PLACEHOLDER,
history: [],
flexibleHeight: true,
flexibleWidth: true,
flexibleMaxHeight: 118
}, this._contextKeyService));
this._register(dom.addStandardDisposableListener(this._replaceInputBox.inputElement, 'keydown', (e) => this._onReplaceInputKeyDown(e)));
this._register(this._replaceInputBox.onDidChange(() => {
this._state.change({ replaceString: this._replaceInputBox.value }, false);
}, this._contextKeyService, true));
this._replaceInput.setPreserveCase(!!this._state.preserveCase);
this._register(this._replaceInput.onKeyDown((e) => this._onReplaceInputKeyDown(e)));
this._register(this._replaceInput.inputBox.onDidChange(() => {
this._state.change({ replaceString: this._replaceInput.inputBox.value }, false);
}));
this._register(this._replaceInputBox.onDidHeightChange((e) => {
this._register(this._replaceInput.inputBox.onDidHeightChange((e) => {
if (this._isReplaceVisible && this._tryUpdateHeight()) {
this._showViewZone();
}
}));
this._preserveCase = this._register(new Checkbox({
actionClassName: 'monaco-preserve-case',
title: NLS_PRESERVE_CASE_LABEL,
isChecked: false,
this._register(this._replaceInput.onDidOptionChange(() => {
this._state.change({
preserveCase: this._replaceInput.getPreserveCase()
}, true);
}));
this._preserveCase.checked = !!this._state.preserveCase;
this._register(this._preserveCase.onChange(viaKeyboard => {
if (!viaKeyboard) {
this._state.change({ preserveCase: !this._state.preserveCase }, false);
this._replaceInputBox.focus();
}
}));
this._register(this._preserveCase.onKeyDown((e) => {
this._register(this._replaceInput.onPreserveCaseKeyDown((e) => {
if (e.equals(KeyCode.Tab)) {
if (this._prevBtn.isEnabled()) {
this._prevBtn.focus();
@ -1082,8 +1068,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
e.preventDefault();
}
}
));
}));
// Replace one button
this._replaceBtn = this._register(new SimpleButton({
@ -1109,15 +1094,9 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
}));
let controls = document.createElement('div');
controls.className = 'controls';
controls.style.display = 'block';
controls.appendChild(this._preserveCase.domNode);
replaceInput.appendChild(controls);
let replacePart = document.createElement('div');
replacePart.className = 'replace-part';
replacePart.appendChild(replaceInput);
replacePart.appendChild(this._replaceInput.domNode);
const replaceActionsContainer = document.createElement('div');
replaceActionsContainer.className = 'replace-actions';
@ -1133,8 +1112,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
onTrigger: () => {
this._state.change({ isReplaceRevealed: !this._isReplaceVisible }, false);
if (this._isReplaceVisible) {
this._replaceInputBox.width = this._findInput.inputBox.width;
this._replaceInputBox.layout();
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
this._replaceInput.inputBox.layout();
}
this._showViewZone();
}
@ -1179,7 +1158,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._domNode.style.width = `${width}px`;
this._findInput.inputBox.width = inputBoxWidth;
if (this._isReplaceVisible) {
this._replaceInputBox.width = inputBoxWidth;
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
}
this._findInput.inputBox.layout();

View file

@ -10,6 +10,7 @@ import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ReplaceInput, IReplaceInputOptions } from 'vs/base/browser/ui/findinput/replaceInput';
export const HistoryNavigationWidgetContext = 'historyNavigationWidget';
export const HistoryNavigationEnablementContext = 'historyNavigationEnabled';
@ -60,6 +61,16 @@ export class ContextScopedFindInput extends FindInput {
super(container, contextViewProvider, showFindOptions, options);
this._register(createAndBindHistoryNavigationWidgetScopedContextKeyService(contextKeyService, <IContextScopedHistoryNavigationWidget>{ target: this.inputBox.element, historyNavigator: this.inputBox }).scopedContextKeyService);
}
}
export class ContextScopedReplaceInput extends ReplaceInput {
constructor(container: HTMLElement | null, contextViewProvider: IContextViewProvider | undefined, options: IReplaceInputOptions,
@IContextKeyService contextKeyService: IContextKeyService, showReplaceOptions: boolean = false
) {
super(container, contextViewProvider, showReplaceOptions, options);
this._register(createAndBindHistoryNavigationWidgetScopedContextKeyService(contextKeyService, <IContextScopedHistoryNavigationWidget>{ target: this.inputBox.element, historyNavigator: this.inputBox }).scopedContextKeyService);
}
}