mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-24 22:00:30 -04:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -345,14 +345,20 @@ export class CommonFindController extends Disposable implements editorCommon.IEd
|
||||
}
|
||||
|
||||
public getGlobalBufferTerm(): string {
|
||||
if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard && this._clipboardService) {
|
||||
if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard
|
||||
&& this._clipboardService
|
||||
&& !this._editor.getModel().isTooLargeForSyncing()
|
||||
) {
|
||||
return this._clipboardService.readFindText();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public setGlobalBufferTerm(text: string) {
|
||||
if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard && this._clipboardService) {
|
||||
if (this._editor.getConfiguration().contribInfo.find.globalFindClipboard
|
||||
&& this._clipboardService
|
||||
&& !this._editor.getModel().isTooLargeForSyncing()
|
||||
) {
|
||||
this._clipboardService.writeFindText(text);
|
||||
}
|
||||
}
|
||||
@@ -440,8 +446,8 @@ export class StartFindWithSelectionAction extends EditorAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: FIND_IDS.StartFindWithSelection,
|
||||
label: nls.localize('startFindAction', "Find"),
|
||||
alias: 'Find',
|
||||
label: nls.localize('startFindWithSelectionAction', "Find With Selection"),
|
||||
alias: 'Find With Selection',
|
||||
precondition: null,
|
||||
kbOpts: {
|
||||
kbExpr: null,
|
||||
|
||||
@@ -208,6 +208,50 @@ export class FindDecorations implements IDisposable {
|
||||
});
|
||||
}
|
||||
|
||||
public matchBeforePosition(position: Position): Range {
|
||||
if (this._decorations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
for (let i = this._decorations.length - 1; i >= 0; i--) {
|
||||
let decorationId = this._decorations[i];
|
||||
let r = this._editor.getModel().getDecorationRange(decorationId);
|
||||
if (!r || r.endLineNumber > position.lineNumber) {
|
||||
continue;
|
||||
}
|
||||
if (r.endLineNumber < position.lineNumber) {
|
||||
return r;
|
||||
}
|
||||
if (r.endColumn > position.column) {
|
||||
continue;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
return this._editor.getModel().getDecorationRange(this._decorations[this._decorations.length - 1]);
|
||||
}
|
||||
|
||||
public matchAfterPosition(position: Position): Range {
|
||||
if (this._decorations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
for (let i = 0, len = this._decorations.length; i < len; i++) {
|
||||
let decorationId = this._decorations[i];
|
||||
let r = this._editor.getModel().getDecorationRange(decorationId);
|
||||
if (!r || r.startLineNumber < position.lineNumber) {
|
||||
continue;
|
||||
}
|
||||
if (r.startLineNumber > position.lineNumber) {
|
||||
return r;
|
||||
}
|
||||
if (r.startColumn < position.column) {
|
||||
continue;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
return this._editor.getModel().getDecorationRange(this._decorations[0]);
|
||||
}
|
||||
|
||||
private _allDecorations(): string[] {
|
||||
let result: string[] = [];
|
||||
result = result.concat(this._decorations);
|
||||
@@ -223,6 +267,7 @@ export class FindDecorations implements IDisposable {
|
||||
|
||||
private static readonly _CURRENT_FIND_MATCH_DECORATION = ModelDecorationOptions.register({
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
zIndex: 13,
|
||||
className: 'currentFindMatch',
|
||||
showIfCollapsed: true,
|
||||
overviewRuler: {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ReplacePattern, parseReplaceString } from 'vs/editor/contrib/find/replacePattern';
|
||||
import { ReplaceCommand, ReplaceCommandThatPreservesSelection } from 'vs/editor/common/commands/replaceCommand';
|
||||
@@ -28,6 +28,7 @@ export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('findWidge
|
||||
export const CONTEXT_FIND_WIDGET_NOT_VISIBLE: ContextKeyExpr = CONTEXT_FIND_WIDGET_VISIBLE.toNegated();
|
||||
// Keep ContextKey use of 'Focussed' to not break when clauses
|
||||
export const CONTEXT_FIND_INPUT_FOCUSED = new RawContextKey<boolean>('findInputFocussed', false);
|
||||
export const CONTEXT_REPLACE_INPUT_FOCUSED = new RawContextKey<boolean>('replaceInputFocussed', false);
|
||||
|
||||
export const ToggleCaseSensitiveKeybinding: IKeybindings = {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_C,
|
||||
@@ -73,6 +74,7 @@ export const FIND_IDS = {
|
||||
};
|
||||
|
||||
export const MATCHES_LIMIT = 19999;
|
||||
const RESEARCH_DELAY = 240;
|
||||
|
||||
export class FindModelBoundToEditorModel {
|
||||
|
||||
@@ -81,6 +83,7 @@ export class FindModelBoundToEditorModel {
|
||||
private _toDispose: IDisposable[];
|
||||
private _decorations: FindDecorations;
|
||||
private _ignoreModelContentChanged: boolean;
|
||||
private _startSearchingTimer: TimeoutTimer;
|
||||
|
||||
private _updateDecorationsScheduler: RunOnceScheduler;
|
||||
private _isDisposed: boolean;
|
||||
@@ -90,6 +93,7 @@ export class FindModelBoundToEditorModel {
|
||||
this._state = state;
|
||||
this._toDispose = [];
|
||||
this._isDisposed = false;
|
||||
this._startSearchingTimer = new TimeoutTimer();
|
||||
|
||||
this._decorations = new FindDecorations(editor);
|
||||
this._toDispose.push(this._decorations);
|
||||
@@ -127,6 +131,7 @@ export class FindModelBoundToEditorModel {
|
||||
|
||||
public dispose(): void {
|
||||
this._isDisposed = true;
|
||||
dispose(this._startSearchingTimer);
|
||||
this._toDispose = dispose(this._toDispose);
|
||||
}
|
||||
|
||||
@@ -140,10 +145,24 @@ export class FindModelBoundToEditorModel {
|
||||
return;
|
||||
}
|
||||
if (e.searchString || e.isReplaceRevealed || e.isRegex || e.wholeWord || e.matchCase || e.searchScope) {
|
||||
if (e.searchScope) {
|
||||
this.research(e.moveCursor, this._state.searchScope);
|
||||
let model = this._editor.getModel();
|
||||
|
||||
if (model.isTooLargeForSyncing()) {
|
||||
this._startSearchingTimer.cancel();
|
||||
|
||||
this._startSearchingTimer.setIfNotSet(() => {
|
||||
if (e.searchScope) {
|
||||
this.research(e.moveCursor, this._state.searchScope);
|
||||
} else {
|
||||
this.research(e.moveCursor);
|
||||
}
|
||||
}, RESEARCH_DELAY);
|
||||
} else {
|
||||
this.research(e.moveCursor);
|
||||
if (e.searchScope) {
|
||||
this.research(e.moveCursor, this._state.searchScope);
|
||||
} else {
|
||||
this.research(e.moveCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +234,44 @@ export class FindModelBoundToEditorModel {
|
||||
this._editor.revealRangeInCenterIfOutsideViewport(match, editorCommon.ScrollType.Smooth);
|
||||
}
|
||||
|
||||
private _prevSearchPosition(before: Position) {
|
||||
let isUsingLineStops = this._state.isRegex && (
|
||||
this._state.searchString.indexOf('^') >= 0
|
||||
|| this._state.searchString.indexOf('$') >= 0
|
||||
);
|
||||
let { lineNumber, column } = before;
|
||||
let model = this._editor.getModel();
|
||||
|
||||
if (isUsingLineStops || column === 1) {
|
||||
if (lineNumber === 1) {
|
||||
lineNumber = model.getLineCount();
|
||||
} else {
|
||||
lineNumber--;
|
||||
}
|
||||
column = model.getLineMaxColumn(lineNumber);
|
||||
} else {
|
||||
column--;
|
||||
}
|
||||
|
||||
return new Position(lineNumber, column);
|
||||
}
|
||||
|
||||
private _moveToPrevMatch(before: Position, isRecursed: boolean = false): void {
|
||||
if (this._decorations.getCount() < MATCHES_LIMIT) {
|
||||
let prevMatchRange = this._decorations.matchBeforePosition(before);
|
||||
|
||||
if (prevMatchRange && prevMatchRange.isEmpty() && prevMatchRange.getStartPosition().equals(before)) {
|
||||
before = this._prevSearchPosition(before);
|
||||
prevMatchRange = this._decorations.matchBeforePosition(before);
|
||||
}
|
||||
|
||||
if (prevMatchRange) {
|
||||
this._setCurrentFindMatch(prevMatchRange);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._cannotFind()) {
|
||||
return;
|
||||
}
|
||||
@@ -242,24 +298,7 @@ export class FindModelBoundToEditorModel {
|
||||
|
||||
if (prevMatch && prevMatch.range.isEmpty() && prevMatch.range.getStartPosition().equals(position)) {
|
||||
// Looks like we're stuck at this position, unacceptable!
|
||||
|
||||
let isUsingLineStops = this._state.isRegex && (
|
||||
this._state.searchString.indexOf('^') >= 0
|
||||
|| this._state.searchString.indexOf('$') >= 0
|
||||
);
|
||||
|
||||
if (isUsingLineStops || column === 1) {
|
||||
if (lineNumber === 1) {
|
||||
lineNumber = model.getLineCount();
|
||||
} else {
|
||||
lineNumber--;
|
||||
}
|
||||
column = model.getLineMaxColumn(lineNumber);
|
||||
} else {
|
||||
column--;
|
||||
}
|
||||
|
||||
position = new Position(lineNumber, column);
|
||||
position = this._prevSearchPosition(position);
|
||||
prevMatch = model.findPreviousMatch(this._state.searchString, position, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getConfiguration().wordSeparators : null, false);
|
||||
}
|
||||
|
||||
@@ -279,7 +318,45 @@ export class FindModelBoundToEditorModel {
|
||||
this._moveToPrevMatch(this._editor.getSelection().getStartPosition());
|
||||
}
|
||||
|
||||
private _nextSearchPosition(after: Position) {
|
||||
let isUsingLineStops = this._state.isRegex && (
|
||||
this._state.searchString.indexOf('^') >= 0
|
||||
|| this._state.searchString.indexOf('$') >= 0
|
||||
);
|
||||
|
||||
let { lineNumber, column } = after;
|
||||
let model = this._editor.getModel();
|
||||
|
||||
if (isUsingLineStops || column === model.getLineMaxColumn(lineNumber)) {
|
||||
if (lineNumber === model.getLineCount()) {
|
||||
lineNumber = 1;
|
||||
} else {
|
||||
lineNumber++;
|
||||
}
|
||||
column = 1;
|
||||
} else {
|
||||
column++;
|
||||
}
|
||||
|
||||
return new Position(lineNumber, column);
|
||||
}
|
||||
|
||||
private _moveToNextMatch(after: Position): void {
|
||||
if (this._decorations.getCount() < MATCHES_LIMIT) {
|
||||
let nextMatchRange = this._decorations.matchAfterPosition(after);
|
||||
|
||||
if (nextMatchRange && nextMatchRange.isEmpty() && nextMatchRange.getStartPosition().equals(after)) {
|
||||
// Looks like we're stuck at this position, unacceptable!
|
||||
after = this._nextSearchPosition(after);
|
||||
nextMatchRange = this._decorations.matchAfterPosition(after);
|
||||
}
|
||||
if (nextMatchRange) {
|
||||
this._setCurrentFindMatch(nextMatchRange);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let nextMatch = this._getNextMatch(after, false, true);
|
||||
if (nextMatch) {
|
||||
this._setCurrentFindMatch(nextMatch.range);
|
||||
@@ -313,24 +390,7 @@ export class FindModelBoundToEditorModel {
|
||||
|
||||
if (forceMove && nextMatch && nextMatch.range.isEmpty() && nextMatch.range.getStartPosition().equals(position)) {
|
||||
// Looks like we're stuck at this position, unacceptable!
|
||||
|
||||
let isUsingLineStops = this._state.isRegex && (
|
||||
this._state.searchString.indexOf('^') >= 0
|
||||
|| this._state.searchString.indexOf('$') >= 0
|
||||
);
|
||||
|
||||
if (isUsingLineStops || column === model.getLineMaxColumn(lineNumber)) {
|
||||
if (lineNumber === model.getLineCount()) {
|
||||
lineNumber = 1;
|
||||
} else {
|
||||
lineNumber++;
|
||||
}
|
||||
column = 1;
|
||||
} else {
|
||||
column++;
|
||||
}
|
||||
|
||||
position = new Position(lineNumber, column);
|
||||
position = this._nextSearchPosition(position);
|
||||
nextMatch = model.findNextMatch(this._state.searchString, position, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getConfiguration().wordSeparators : null, captureMatches);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
|
||||
@@ -70,7 +70,7 @@ export class FindReplaceState implements IDisposable {
|
||||
private _matchesPosition: number;
|
||||
private _matchesCount: number;
|
||||
private _currentMatch: Range;
|
||||
private _onFindReplaceStateChange: Emitter<FindReplaceStateChangedEvent>;
|
||||
private readonly _onFindReplaceStateChange: Emitter<FindReplaceStateChangedEvent>;
|
||||
|
||||
public get searchString(): string { return this._searchString; }
|
||||
public get replaceString(): string { return this._replaceString; }
|
||||
|
||||
@@ -71,14 +71,6 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.monaco-editor .find-widget.visible.noanimation {
|
||||
-webkit-transition: none;
|
||||
-o-transition: none;
|
||||
-moz-transition: none;
|
||||
-ms-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.monaco-editor .find-widget > .find-part,
|
||||
.monaco-editor .find-widget > .replace-part {
|
||||
margin: 4px 0 0 17px;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Sash, IHorizontalSashLayoutProvider, ISashEvent, Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, IViewZone, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
|
||||
import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
|
||||
import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED, CONTEXT_REPLACE_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
|
||||
import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -65,10 +65,10 @@ const FIND_REPLACE_AREA_HEIGHT = 64; // The height of Find Widget when Replace I
|
||||
|
||||
|
||||
export class FindWidgetViewZone implements IViewZone {
|
||||
public afterLineNumber: number;
|
||||
public readonly afterLineNumber: number;
|
||||
public heightInPx: number;
|
||||
public suppressMouseDown: boolean;
|
||||
public domNode: HTMLElement;
|
||||
public readonly suppressMouseDown: boolean;
|
||||
public readonly domNode: HTMLElement;
|
||||
|
||||
constructor(afterLineNumber: number) {
|
||||
this.afterLineNumber = afterLineNumber;
|
||||
@@ -82,11 +82,11 @@ export class FindWidgetViewZone implements IViewZone {
|
||||
|
||||
export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSashLayoutProvider {
|
||||
private static readonly ID = 'editor.contrib.findWidget';
|
||||
private _codeEditor: ICodeEditor;
|
||||
private readonly _codeEditor: ICodeEditor;
|
||||
private _state: FindReplaceState;
|
||||
private _controller: IFindController;
|
||||
private _contextViewProvider: IContextViewProvider;
|
||||
private _keybindingService: IKeybindingService;
|
||||
private readonly _contextViewProvider: IContextViewProvider;
|
||||
private readonly _keybindingService: IKeybindingService;
|
||||
|
||||
private _domNode: HTMLElement;
|
||||
private _findInput: FindInput;
|
||||
@@ -104,8 +104,10 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
private _isVisible: boolean;
|
||||
private _isReplaceVisible: boolean;
|
||||
|
||||
private _focusTracker: dom.IFocusTracker;
|
||||
private _findFocusTracker: dom.IFocusTracker;
|
||||
private _findInputFocused: IContextKey<boolean>;
|
||||
private _replaceFocusTracker: dom.IFocusTracker;
|
||||
private _replaceInputFocused: IContextKey<boolean>;
|
||||
private _viewZone: FindWidgetViewZone;
|
||||
private _viewZoneId: number;
|
||||
|
||||
@@ -163,28 +165,25 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
}
|
||||
}));
|
||||
this._findInputFocused = CONTEXT_FIND_INPUT_FOCUSED.bindTo(contextKeyService);
|
||||
this._focusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement));
|
||||
this._register(this._focusTracker.onDidFocus(() => {
|
||||
this._findFocusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement));
|
||||
this._register(this._findFocusTracker.onDidFocus(() => {
|
||||
this._findInputFocused.set(true);
|
||||
|
||||
if (this._toggleSelectionFind.checked) {
|
||||
let selection = this._codeEditor.getSelection();
|
||||
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
|
||||
selection = selection.setEndPosition(selection.endLineNumber - 1, 1);
|
||||
}
|
||||
let currentMatch = this._state.currentMatch;
|
||||
if (selection.startLineNumber !== selection.endLineNumber) {
|
||||
if (!Range.equalsRange(selection, currentMatch)) {
|
||||
// Reseed find scope
|
||||
this._state.change({ searchScope: selection }, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._updateSearchScope();
|
||||
}));
|
||||
this._register(this._focusTracker.onDidBlur(() => {
|
||||
this._register(this._findFocusTracker.onDidBlur(() => {
|
||||
this._findInputFocused.set(false);
|
||||
}));
|
||||
|
||||
this._replaceInputFocused = CONTEXT_REPLACE_INPUT_FOCUSED.bindTo(contextKeyService);
|
||||
this._replaceFocusTracker = this._register(dom.trackFocus(this._replaceInputBox.inputElement));
|
||||
this._register(this._replaceFocusTracker.onDidFocus(() => {
|
||||
this._replaceInputFocused.set(true);
|
||||
this._updateSearchScope();
|
||||
}));
|
||||
this._register(this._replaceFocusTracker.onDidBlur(() => {
|
||||
this._replaceInputFocused.set(false);
|
||||
}));
|
||||
|
||||
this._codeEditor.addOverlayWidget(this);
|
||||
this._viewZone = new FindWidgetViewZone(0); // Put it before the first line then users can scroll beyond the first line.
|
||||
|
||||
@@ -382,12 +381,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
setTimeout(() => {
|
||||
dom.addClass(this._domNode, 'visible');
|
||||
this._domNode.setAttribute('aria-hidden', 'false');
|
||||
if (!animate) {
|
||||
dom.addClass(this._domNode, 'noanimation');
|
||||
setTimeout(() => {
|
||||
dom.removeClass(this._domNode, 'noanimation');
|
||||
}, 200);
|
||||
}
|
||||
}, 0);
|
||||
this._codeEditor.layoutOverlayWidget(this);
|
||||
|
||||
@@ -572,6 +565,22 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
this._findInput.highlightFindOptions();
|
||||
}
|
||||
|
||||
private _updateSearchScope(): void {
|
||||
if (this._toggleSelectionFind.checked) {
|
||||
let selection = this._codeEditor.getSelection();
|
||||
if (selection.endColumn === 1 && selection.endLineNumber > selection.startLineNumber) {
|
||||
selection = selection.setEndPosition(selection.endLineNumber - 1, 1);
|
||||
}
|
||||
let currentMatch = this._state.currentMatch;
|
||||
if (selection.startLineNumber !== selection.endLineNumber) {
|
||||
if (!Range.equalsRange(selection, currentMatch)) {
|
||||
// Reseed find scope
|
||||
this._state.change({ searchScope: selection }, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _onFindInputMouseDown(e: IMouseEvent): void {
|
||||
// on linux, middle key does pasting.
|
||||
if (e.middleButton) {
|
||||
@@ -726,8 +735,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
className: 'previous',
|
||||
onTrigger: () => {
|
||||
this._codeEditor.getAction(FIND_IDS.PreviousMatchFindAction).run().done(null, onUnexpectedError);
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
}));
|
||||
|
||||
// Next button
|
||||
@@ -736,8 +744,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
className: 'next',
|
||||
onTrigger: () => {
|
||||
this._codeEditor.getAction(FIND_IDS.NextMatchFindAction).run().done(null, onUnexpectedError);
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
}));
|
||||
|
||||
let findPart = document.createElement('div');
|
||||
@@ -828,8 +835,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
className: 'replace-all',
|
||||
onTrigger: () => {
|
||||
this._controller.replaceAll();
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
}));
|
||||
|
||||
let replacePart = document.createElement('div');
|
||||
@@ -858,8 +864,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
this._replaceInputBox.width = this._findInput.inputBox.width;
|
||||
}
|
||||
this._showViewZone();
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
}));
|
||||
this._toggleReplaceBtn.toggleClass('expand', this._isReplaceVisible);
|
||||
this._toggleReplaceBtn.toggleClass('collapse', !this._isReplaceVisible);
|
||||
@@ -911,19 +916,19 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
}
|
||||
|
||||
interface ISimpleCheckboxOpts {
|
||||
parent: HTMLElement;
|
||||
title: string;
|
||||
onChange: () => void;
|
||||
readonly parent: HTMLElement;
|
||||
readonly title: string;
|
||||
readonly onChange: () => void;
|
||||
}
|
||||
|
||||
class SimpleCheckbox extends Widget {
|
||||
|
||||
private static _COUNTER = 0;
|
||||
|
||||
private _opts: ISimpleCheckboxOpts;
|
||||
private _domNode: HTMLElement;
|
||||
private _checkbox: HTMLInputElement;
|
||||
private _label: HTMLLabelElement;
|
||||
private readonly _opts: ISimpleCheckboxOpts;
|
||||
private readonly _domNode: HTMLElement;
|
||||
private readonly _checkbox: HTMLInputElement;
|
||||
private readonly _label: HTMLLabelElement;
|
||||
|
||||
constructor(opts: ISimpleCheckboxOpts) {
|
||||
super();
|
||||
@@ -992,16 +997,16 @@ class SimpleCheckbox extends Widget {
|
||||
}
|
||||
|
||||
export interface ISimpleButtonOpts {
|
||||
label: string;
|
||||
className: string;
|
||||
onTrigger: () => void;
|
||||
onKeyDown: (e: IKeyboardEvent) => void;
|
||||
readonly label: string;
|
||||
readonly className: string;
|
||||
readonly onTrigger: () => void;
|
||||
readonly onKeyDown?: (e: IKeyboardEvent) => void;
|
||||
}
|
||||
|
||||
export class SimpleButton extends Widget {
|
||||
|
||||
private _opts: ISimpleButtonOpts;
|
||||
private _domNode: HTMLElement;
|
||||
private readonly _opts: ISimpleButtonOpts;
|
||||
private readonly _domNode: HTMLElement;
|
||||
|
||||
constructor(opts: ISimpleButtonOpts) {
|
||||
super();
|
||||
@@ -1018,13 +1023,16 @@ export class SimpleButton extends Widget {
|
||||
this._opts.onTrigger();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
this.onkeydown(this._domNode, (e) => {
|
||||
if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) {
|
||||
this._opts.onTrigger();
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
this._opts.onKeyDown(e);
|
||||
if (this._opts.onKeyDown) {
|
||||
this._opts.onKeyDown(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1058,48 +1066,50 @@ export class SimpleButton extends Widget {
|
||||
// theming
|
||||
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
function addBackgroundColorRule(selector: string, color: Color): void {
|
||||
const addBackgroundColorRule = (selector: string, color: Color): void => {
|
||||
if (color) {
|
||||
collector.addRule(`.monaco-editor ${selector} { background-color: ${color}; }`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
addBackgroundColorRule('.findMatch', theme.getColor(editorFindMatchHighlight));
|
||||
addBackgroundColorRule('.currentFindMatch', theme.getColor(editorFindMatch));
|
||||
addBackgroundColorRule('.findScope', theme.getColor(editorFindRangeHighlight));
|
||||
|
||||
let widgetBackground = theme.getColor(editorWidgetBackground);
|
||||
const widgetBackground = theme.getColor(editorWidgetBackground);
|
||||
addBackgroundColorRule('.find-widget', widgetBackground);
|
||||
|
||||
let widgetShadowColor = theme.getColor(widgetShadow);
|
||||
const widgetShadowColor = theme.getColor(widgetShadow);
|
||||
if (widgetShadowColor) {
|
||||
collector.addRule(`.monaco-editor .find-widget { box-shadow: 0 2px 8px ${widgetShadowColor}; }`);
|
||||
}
|
||||
|
||||
let findMatchHighlightBorder = theme.getColor(editorFindMatchHighlightBorder);
|
||||
const findMatchHighlightBorder = theme.getColor(editorFindMatchHighlightBorder);
|
||||
if (findMatchHighlightBorder) {
|
||||
collector.addRule(`.monaco-editor .findMatch { border: 1px dotted ${findMatchHighlightBorder}; -moz-box-sizing: border-box; box-sizing: border-box; }`);
|
||||
}
|
||||
let findMatchBorder = theme.getColor(editorFindMatchBorder);
|
||||
if (findMatchBorder) {
|
||||
collector.addRule(`.monaco-editor .currentFindMatch { border: 2px solid ${findMatchBorder}; padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; }`);
|
||||
}
|
||||
let findRangeHighlightBorder = theme.getColor(editorFindRangeHighlightBorder);
|
||||
if (findRangeHighlightBorder) {
|
||||
collector.addRule(`.monaco-editor .findScope { border: 1px dashed ${findRangeHighlightBorder}; }`);
|
||||
collector.addRule(`.monaco-editor .findMatch { border: 1px ${theme.type === 'hc' ? 'dotted' : 'solid'} ${findMatchHighlightBorder}; box-sizing: border-box; }`);
|
||||
}
|
||||
|
||||
let hcBorder = theme.getColor(contrastBorder);
|
||||
const findMatchBorder = theme.getColor(editorFindMatchBorder);
|
||||
if (findMatchBorder) {
|
||||
collector.addRule(`.monaco-editor .currentFindMatch { border: 2px solid ${findMatchBorder}; padding: 1px; box-sizing: border-box; }`);
|
||||
}
|
||||
|
||||
const findRangeHighlightBorder = theme.getColor(editorFindRangeHighlightBorder);
|
||||
if (findRangeHighlightBorder) {
|
||||
collector.addRule(`.monaco-editor .findScope { border: 1px ${theme.type === 'hc' ? 'dashed' : 'solid'} ${findRangeHighlightBorder}; }`);
|
||||
}
|
||||
|
||||
const hcBorder = theme.getColor(contrastBorder);
|
||||
if (hcBorder) {
|
||||
collector.addRule(`.monaco-editor .find-widget { border: 2px solid ${hcBorder}; }`);
|
||||
}
|
||||
|
||||
let error = theme.getColor(errorForeground);
|
||||
const error = theme.getColor(errorForeground);
|
||||
if (error) {
|
||||
collector.addRule(`.monaco-editor .find-widget.no-results .matchesCount { color: ${error}; }`);
|
||||
}
|
||||
|
||||
let border = theme.getColor(editorWidgetBorder);
|
||||
const border = theme.getColor(editorWidgetBorder);
|
||||
if (border) {
|
||||
collector.addRule(`.monaco-editor .find-widget .monaco-sash { background-color: ${border}; width: 3px !important; margin-left: -4px;}`);
|
||||
}
|
||||
|
||||
@@ -23,20 +23,20 @@ const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next mat
|
||||
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
|
||||
|
||||
export abstract class SimpleFindWidget extends Widget {
|
||||
protected _findInput: FindInput;
|
||||
protected _domNode: HTMLElement;
|
||||
protected _innerDomNode: HTMLElement;
|
||||
protected _isVisible: boolean;
|
||||
protected _focusTracker: dom.IFocusTracker;
|
||||
protected _findInputFocusTracker: dom.IFocusTracker;
|
||||
protected _findHistory: HistoryNavigator<string>;
|
||||
protected _updateHistoryDelayer: Delayer<void>;
|
||||
private _findInput: FindInput;
|
||||
private _domNode: HTMLElement;
|
||||
private _innerDomNode: HTMLElement;
|
||||
private _isVisible: boolean;
|
||||
private _focusTracker: dom.IFocusTracker;
|
||||
private _findInputFocusTracker: dom.IFocusTracker;
|
||||
private _findHistory: HistoryNavigator<string>;
|
||||
private _updateHistoryDelayer: Delayer<void>;
|
||||
|
||||
constructor(
|
||||
@IContextViewService private readonly _contextViewService: IContextViewService,
|
||||
private animate: boolean = true
|
||||
@IContextViewService private readonly _contextViewService: IContextViewService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._findInput = this._register(new FindInput(null, this._contextViewService, {
|
||||
label: NLS_FIND_INPUT_LABEL,
|
||||
placeholder: NLS_FIND_INPUT_PLACEHOLDER,
|
||||
@@ -65,31 +65,28 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
}
|
||||
}));
|
||||
|
||||
let prevBtn = new SimpleButton({
|
||||
const prevBtn = new SimpleButton({
|
||||
label: NLS_PREVIOUS_MATCH_BTN_LABEL,
|
||||
className: 'previous',
|
||||
onTrigger: () => {
|
||||
this.find(true);
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
});
|
||||
|
||||
let nextBtn = new SimpleButton({
|
||||
const nextBtn = new SimpleButton({
|
||||
label: NLS_NEXT_MATCH_BTN_LABEL,
|
||||
className: 'next',
|
||||
onTrigger: () => {
|
||||
this.find(false);
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
});
|
||||
|
||||
let closeBtn = new SimpleButton({
|
||||
const closeBtn = new SimpleButton({
|
||||
label: NLS_CLOSE_BTN_LABEL,
|
||||
className: 'close-fw',
|
||||
onTrigger: () => {
|
||||
this.hide();
|
||||
},
|
||||
onKeyDown: (e) => { }
|
||||
}
|
||||
});
|
||||
|
||||
this._innerDomNode = document.createElement('div');
|
||||
@@ -136,8 +133,8 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
return this._findInput.getValue();
|
||||
}
|
||||
|
||||
public updateTheme(theme?: ITheme): void {
|
||||
let inputStyles = {
|
||||
public updateTheme(theme: ITheme): void {
|
||||
const inputStyles = {
|
||||
inputActiveOptionBorder: theme.getColor(inputActiveOptionBorder),
|
||||
inputBackground: theme.getColor(inputBackground),
|
||||
inputForeground: theme.getColor(inputForeground),
|
||||
@@ -152,6 +149,14 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
this._findInput.style(inputStyles);
|
||||
}
|
||||
|
||||
dipose() {
|
||||
super.dispose();
|
||||
|
||||
if (this._domNode && this._domNode.parentElement) {
|
||||
this._domNode.parentElement.removeChild(this._domNode);
|
||||
}
|
||||
}
|
||||
|
||||
public getDomNode(): HTMLElement {
|
||||
return this._domNode;
|
||||
}
|
||||
@@ -171,11 +176,7 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
setTimeout(() => {
|
||||
dom.addClass(this._innerDomNode, 'visible');
|
||||
this._innerDomNode.setAttribute('aria-hidden', 'false');
|
||||
if (!this.animate) {
|
||||
dom.addClass(this._innerDomNode, 'noanimation');
|
||||
}
|
||||
setTimeout(() => {
|
||||
dom.removeClass(this._innerDomNode, 'noanimation');
|
||||
this._findInput.select();
|
||||
}, 200);
|
||||
}, 0);
|
||||
@@ -201,14 +202,14 @@ export abstract class SimpleFindWidget extends Widget {
|
||||
}
|
||||
|
||||
public showNextFindTerm() {
|
||||
let next = this._findHistory.next();
|
||||
const next = this._findHistory.next();
|
||||
if (next) {
|
||||
this._findInput.setValue(next);
|
||||
}
|
||||
}
|
||||
|
||||
public showPreviousFindTerm() {
|
||||
let previous = this._findHistory.previous();
|
||||
const previous = this._findHistory.previous();
|
||||
if (previous) {
|
||||
this._findInput.setValue(previous);
|
||||
}
|
||||
@@ -222,7 +223,7 @@ registerThemingParticipant((theme, collector) => {
|
||||
collector.addRule(`.monaco-workbench .simple-find-part { background-color: ${findWidgetBGColor} !important; }`);
|
||||
}
|
||||
|
||||
let widgetShadowColor = theme.getColor(widgetShadow);
|
||||
const widgetShadowColor = theme.getColor(widgetShadow);
|
||||
if (widgetShadowColor) {
|
||||
collector.addRule(`.monaco-workbench .simple-find-part { box-shadow: 0 2px 8px ${widgetShadowColor}; }`);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export class TestFindController extends CommonFindController {
|
||||
public delayUpdateHistory: boolean = false;
|
||||
public delayedUpdateHistoryPromise: TPromise<void>;
|
||||
|
||||
private _delayedUpdateHistoryEvent: Emitter<void> = new Emitter<void>();
|
||||
private readonly _delayedUpdateHistoryEvent: Emitter<void> = new Emitter<void>();
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@@ -335,7 +335,7 @@ suite('FindController', () => {
|
||||
findController.delayedUpdateHistoryPromise.then(() => {
|
||||
assert.deepEqual(['3'], toArray(findController.getHistory()));
|
||||
done();
|
||||
});
|
||||
}, error => done(error));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@ import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
|
||||
|
||||
suite('FindModel', () => {
|
||||
|
||||
function findTest(testName: string, callback: (editor: ICodeEditor, cursor: Cursor) => void): void {
|
||||
test(testName, () => {
|
||||
withTestCodeEditor([
|
||||
const textArr = [
|
||||
'// my cool header',
|
||||
'#include "cool.h"',
|
||||
'#include <iostream>',
|
||||
@@ -32,7 +34,19 @@ suite('FindModel', () => {
|
||||
'}',
|
||||
'// blablablaciao',
|
||||
''
|
||||
], {}, callback);
|
||||
];
|
||||
withTestCodeEditor(textArr, {}, callback);
|
||||
|
||||
const text = textArr.join('\n');
|
||||
const ptBuilder = new PieceTreeTextBufferBuilder();
|
||||
ptBuilder.acceptChunk(text.substr(0, 94));
|
||||
ptBuilder.acceptChunk(text.substr(94, 101));
|
||||
ptBuilder.acceptChunk(text.substr(195, 59));
|
||||
const factory = ptBuilder.finish();
|
||||
withTestCodeEditor([],
|
||||
{
|
||||
model: new TextModel(factory, TextModel.DEFAULT_CREATION_OPTIONS, null, null)
|
||||
}, callback);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user