Archived
Merge from vscode 52dcb723a39ae75bee1bd56b3312d7fcdc87aeed (#6719)
This commit is contained in:
@@ -56,7 +56,7 @@ class WindowManager {
|
||||
}
|
||||
|
||||
// --- Fullscreen
|
||||
private _fullscreen: boolean;
|
||||
private _fullscreen: boolean = false;
|
||||
private readonly _onDidChangeFullscreen = new Emitter<void>();
|
||||
|
||||
public readonly onDidChangeFullscreen: Event<void> = this._onDidChangeFullscreen.event;
|
||||
|
||||
@@ -50,8 +50,8 @@ interface IDomClassList {
|
||||
|
||||
const _manualClassList = new class implements IDomClassList {
|
||||
|
||||
private _lastStart: number;
|
||||
private _lastEnd: number;
|
||||
private _lastStart: number = -1;
|
||||
private _lastEnd: number = -1;
|
||||
|
||||
private _findClassName(node: HTMLElement, className: string): void {
|
||||
|
||||
@@ -1200,7 +1200,7 @@ export function asDomUri(uri: URI): URI {
|
||||
if (Schemas.vscodeRemote === uri.scheme) {
|
||||
// rewrite vscode-remote-uris to uris of the window location
|
||||
// so that they can be intercepted by the service worker
|
||||
return _location.with({ path: '/vscode-resources/fetch', query: `u=${JSON.stringify(uri)}` });
|
||||
return _location.with({ path: '/vscode-remote', query: JSON.stringify(uri) });
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export class Gesture extends Disposable {
|
||||
private static INSTANCE: Gesture;
|
||||
private static HOLD_DELAY = 700;
|
||||
|
||||
private dispatched: boolean;
|
||||
private dispatched = false;
|
||||
private targets: HTMLElement[];
|
||||
private handle: IDisposable | null;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
|
||||
_context: any;
|
||||
_action: IAction;
|
||||
|
||||
private _actionRunner: IActionRunner;
|
||||
private _actionRunner!: IActionRunner;
|
||||
|
||||
constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) {
|
||||
super();
|
||||
@@ -232,7 +232,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
|
||||
|
||||
export class ActionViewItem extends BaseActionViewItem {
|
||||
|
||||
protected label: HTMLElement;
|
||||
protected label!: HTMLElement;
|
||||
protected options: IActionViewItemOptions;
|
||||
|
||||
private cssClass?: string;
|
||||
|
||||
@@ -77,8 +77,8 @@ export class BreadcrumbsWidget {
|
||||
private _focusedItemIdx: number = -1;
|
||||
private _selectedItemIdx: number = -1;
|
||||
|
||||
private _pendingLayout: IDisposable;
|
||||
private _dimension: dom.Dimension;
|
||||
private _pendingLayout: IDisposable | undefined;
|
||||
private _dimension: dom.Dimension | undefined;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement
|
||||
|
||||
@@ -20,10 +20,12 @@ const GOLDEN_RATIO = {
|
||||
rightMarginRatio: 0.1909
|
||||
};
|
||||
|
||||
function createEmptyView(background: Color): ISplitViewView {
|
||||
function createEmptyView(background: Color | undefined): ISplitViewView {
|
||||
const element = $('.centered-layout-margin');
|
||||
element.style.height = '100%';
|
||||
element.style.backgroundColor = background.toString();
|
||||
if (background) {
|
||||
element.style.backgroundColor = background.toString();
|
||||
}
|
||||
|
||||
return {
|
||||
element,
|
||||
@@ -53,7 +55,7 @@ export class CenteredViewLayout implements IDisposable {
|
||||
private splitView?: SplitView;
|
||||
private width: number = 0;
|
||||
private height: number = 0;
|
||||
private style: ICenteredViewStyles;
|
||||
private style!: ICenteredViewStyles;
|
||||
private didLayout = false;
|
||||
private emptyViews: ISplitViewView[] | undefined;
|
||||
private readonly splitViewDisposables = new DisposableStore();
|
||||
@@ -132,7 +134,8 @@ export class CenteredViewLayout implements IDisposable {
|
||||
|
||||
this.splitView.layout(this.width);
|
||||
this.splitView.addView(toSplitViewView(this.view, () => this.height), 0);
|
||||
this.emptyViews = [createEmptyView(this.style.background), createEmptyView(this.style.background)];
|
||||
const backgroundColor = this.style ? this.style.background : undefined;
|
||||
this.emptyViews = [createEmptyView(backgroundColor), createEmptyView(backgroundColor)];
|
||||
this.splitView.addView(this.emptyViews[0], this.state.leftMarginRatio * this.width, 0);
|
||||
this.splitView.addView(this.emptyViews[1], this.state.rightMarginRatio * this.width, 2);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3.76345L5.80687 11.9351L5.08584 11.8927L1 7.29614L1.76345 6.61752L5.50997 10.8324L14.3214 3L15 3.76345Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 278 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3.76345L5.80687 11.9351L5.08584 11.8927L1 7.29614L1.76345 6.61752L5.50997 10.8324L14.3214 3L15 3.76345Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 278 B |
@@ -39,4 +39,24 @@
|
||||
|
||||
.hc-black .monaco-custom-checkbox:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.monaco-custom-checkbox.monaco-simple-checkbox {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
margin-right: 9px;
|
||||
margin-left: 0px;
|
||||
padding: 0px;
|
||||
opacity: 1;
|
||||
background-size: 16px !important;
|
||||
}
|
||||
|
||||
.monaco-custom-checkbox.monaco-simple-checkbox.checked {
|
||||
background: url('check-light.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-custom-checkbox.monaco-simple-checkbox.checked {
|
||||
background: url('check-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,12 @@ export interface ICheckboxStyles {
|
||||
inputActiveOptionBackground?: Color;
|
||||
}
|
||||
|
||||
export interface ISimpleCheckboxStyles {
|
||||
checkboxBackground?: Color;
|
||||
checkboxBorder?: Color;
|
||||
checkboxForeground?: Color;
|
||||
}
|
||||
|
||||
const defaultOpts = {
|
||||
inputActiveOptionBorder: Color.fromHex('#007ACC00'),
|
||||
inputActiveOptionBackground: Color.fromHex('#0E639C50')
|
||||
@@ -32,7 +38,7 @@ const defaultOpts = {
|
||||
|
||||
export class CheckboxActionViewItem extends BaseActionViewItem {
|
||||
|
||||
private checkbox: Checkbox;
|
||||
private checkbox!: Checkbox;
|
||||
private readonly disposables = new DisposableStore();
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
@@ -45,7 +51,7 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
|
||||
title: this._action.label
|
||||
});
|
||||
this.disposables.add(this.checkbox);
|
||||
this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox.checked, this));
|
||||
this.disposables.add(this.checkbox.onChange(() => this._action.checked = this.checkbox!.checked, this));
|
||||
this.element.appendChild(this.checkbox.domNode);
|
||||
}
|
||||
|
||||
@@ -174,3 +180,46 @@ export class Checkbox extends Widget {
|
||||
this.domNode.setAttribute('aria-disabled', String(true));
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleCheckbox extends Widget {
|
||||
private checkbox: Checkbox;
|
||||
private styles: ISimpleCheckboxStyles;
|
||||
|
||||
readonly domNode: HTMLElement;
|
||||
|
||||
constructor(private title: string, private isChecked: boolean) {
|
||||
super();
|
||||
|
||||
this.checkbox = new Checkbox({ title: this.title, isChecked: this.isChecked, actionClassName: 'monaco-simple-checkbox' });
|
||||
|
||||
this.domNode = this.checkbox.domNode;
|
||||
|
||||
this.styles = {};
|
||||
|
||||
this.checkbox.onChange(() => {
|
||||
this.applyStyles();
|
||||
});
|
||||
}
|
||||
|
||||
get checked(): boolean {
|
||||
return this.checkbox.checked;
|
||||
}
|
||||
|
||||
set checked(newIsChecked: boolean) {
|
||||
this.checkbox.checked = newIsChecked;
|
||||
|
||||
this.applyStyles();
|
||||
}
|
||||
|
||||
style(styles: ISimpleCheckboxStyles): void {
|
||||
this.styles = styles;
|
||||
|
||||
this.applyStyles();
|
||||
}
|
||||
|
||||
protected applyStyles(): void {
|
||||
this.domNode.style.color = this.styles.checkboxForeground ? this.styles.checkboxForeground.toString() : null;
|
||||
this.domNode.style.backgroundColor = this.styles.checkboxBackground ? this.styles.checkboxBackground.toString() : null;
|
||||
this.domNode.style.borderColor = this.styles.checkboxBorder ? this.styles.checkboxBorder.toString() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./contextview';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Range } from 'vs/base/common/range';
|
||||
|
||||
export interface IAnchor {
|
||||
@@ -100,11 +100,11 @@ export class ContextView extends Disposable {
|
||||
private static readonly BUBBLE_UP_EVENTS = ['click', 'keydown', 'focus', 'blur'];
|
||||
private static readonly BUBBLE_DOWN_EVENTS = ['click'];
|
||||
|
||||
private container: HTMLElement | null;
|
||||
private container: HTMLElement | null = null;
|
||||
private view: HTMLElement;
|
||||
private delegate: IDelegate | null;
|
||||
private toDisposeOnClean: IDisposable | null;
|
||||
private toDisposeOnSetContainer: IDisposable;
|
||||
private delegate: IDelegate | null = null;
|
||||
private toDisposeOnClean: IDisposable = Disposable.None;
|
||||
private toDisposeOnSetContainer: IDisposable = Disposable.None;
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
super();
|
||||
@@ -120,7 +120,7 @@ export class ContextView extends Disposable {
|
||||
|
||||
setContainer(container: HTMLElement | null): void {
|
||||
if (this.container) {
|
||||
dispose(this.toDisposeOnSetContainer);
|
||||
this.toDisposeOnSetContainer.dispose();
|
||||
this.container.removeChild(this.view);
|
||||
this.container = null;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ export class ContextView extends Disposable {
|
||||
DOM.show(this.view);
|
||||
|
||||
// Render content
|
||||
this.toDisposeOnClean = delegate.render(this.view);
|
||||
this.toDisposeOnClean = delegate.render(this.view) || Disposable.None;
|
||||
|
||||
// Set active delegate
|
||||
this.delegate = delegate;
|
||||
@@ -267,10 +267,7 @@ export class ContextView extends Disposable {
|
||||
delegate.onHide(data);
|
||||
}
|
||||
|
||||
if (this.toDisposeOnClean) {
|
||||
this.toDisposeOnClean.dispose();
|
||||
this.toDisposeOnClean = null;
|
||||
}
|
||||
this.toDisposeOnClean.dispose();
|
||||
|
||||
DOM.hide(this.view);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ const defaultOpts = {
|
||||
export class CountBadge {
|
||||
|
||||
private element: HTMLElement;
|
||||
private count: number;
|
||||
private count: number = 0;
|
||||
private countFormat: string;
|
||||
private titleFormat: string;
|
||||
|
||||
|
||||
@@ -149,6 +149,11 @@
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-checkbox-row {
|
||||
padding: 15px 0px 0px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/** Dialog: Buttons Row */
|
||||
.monaco-workbench .dialog-box > .dialog-buttons-row {
|
||||
display: flex;
|
||||
@@ -175,4 +180,4 @@
|
||||
margin: 4px 5px; /* allows button focus outline to be visible */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,23 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { isMacintosh, isLinux } from 'vs/base/common/platform';
|
||||
import { SimpleCheckbox, ISimpleCheckboxStyles } from 'vs/base/browser/ui/checkbox/checkbox';
|
||||
|
||||
export interface IDialogOptions {
|
||||
cancelId?: number;
|
||||
detail?: string;
|
||||
checkboxLabel?: string;
|
||||
checkboxChecked?: boolean;
|
||||
type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
|
||||
keyEventProcessor?: (event: StandardKeyboardEvent) => void;
|
||||
}
|
||||
|
||||
export interface IDialogStyles extends IButtonStyles {
|
||||
export interface IDialogResult {
|
||||
button: number;
|
||||
checkboxChecked?: boolean;
|
||||
}
|
||||
|
||||
export interface IDialogStyles extends IButtonStyles, ISimpleCheckboxStyles {
|
||||
dialogForeground?: Color;
|
||||
dialogBackground?: Color;
|
||||
dialogShadow?: Color;
|
||||
@@ -42,6 +50,7 @@ export class Dialog extends Disposable {
|
||||
private buttonsContainer: HTMLElement | undefined;
|
||||
private messageDetailElement: HTMLElement | undefined;
|
||||
private iconElement: HTMLElement | undefined;
|
||||
private checkbox: SimpleCheckbox | undefined;
|
||||
private toolbarContainer: HTMLElement | undefined;
|
||||
private buttonGroup: ButtonGroup | undefined;
|
||||
private styles: IDialogStyles | undefined;
|
||||
@@ -68,6 +77,19 @@ export class Dialog extends Disposable {
|
||||
this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
|
||||
this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
|
||||
|
||||
if (this.options.checkboxLabel) {
|
||||
const checkboxRowElement = messageContainer.appendChild($('.dialog-checkbox-row'));
|
||||
|
||||
this.checkbox = this._register(new SimpleCheckbox(this.options.checkboxLabel, !!this.options.checkboxChecked));
|
||||
|
||||
checkboxRowElement.appendChild(this.checkbox.domNode);
|
||||
|
||||
const checkboxMessageElement = checkboxRowElement.appendChild($('.dialog-checkbox-message'));
|
||||
checkboxMessageElement.innerText = this.options.checkboxLabel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row'));
|
||||
this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar'));
|
||||
}
|
||||
@@ -78,12 +100,12 @@ export class Dialog extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
async show(): Promise<number> {
|
||||
async show(): Promise<IDialogResult> {
|
||||
this.focusToReturn = document.activeElement as HTMLElement;
|
||||
|
||||
return new Promise<number>((resolve) => {
|
||||
return new Promise<IDialogResult>((resolve) => {
|
||||
if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) {
|
||||
resolve(0);
|
||||
resolve({ button: 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -112,7 +134,7 @@ export class Dialog extends Disposable {
|
||||
|
||||
this._register(button.onDidClick(e => {
|
||||
EventHelper.stop(e);
|
||||
resolve(buttonMap[index].index);
|
||||
resolve({ button: buttonMap[index].index, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -147,7 +169,7 @@ export class Dialog extends Disposable {
|
||||
const evt = new StandardKeyboardEvent(e);
|
||||
|
||||
if (evt.equals(KeyCode.Escape)) {
|
||||
resolve(this.options.cancelId || 0);
|
||||
resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -187,7 +209,7 @@ export class Dialog extends Disposable {
|
||||
const actionBar = new ActionBar(this.toolbarContainer, {});
|
||||
|
||||
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => {
|
||||
resolve(this.options.cancelId || 0);
|
||||
resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
@@ -221,6 +243,10 @@ export class Dialog extends Disposable {
|
||||
if (this.buttonGroup) {
|
||||
this.buttonGroup.buttons.forEach(button => button.style(style));
|
||||
}
|
||||
|
||||
if (this.checkbox) {
|
||||
this.checkbox.style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,4 +287,4 @@ export class Dialog extends Disposable {
|
||||
|
||||
return buttonMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ export class BaseDropdown extends ActionRunner {
|
||||
private boxContainer?: HTMLElement;
|
||||
private _label?: HTMLElement;
|
||||
private contents?: HTMLElement;
|
||||
private visible: boolean;
|
||||
private visible: boolean | undefined;
|
||||
|
||||
constructor(container: HTMLElement, options: IBaseDropdownOptions) {
|
||||
super();
|
||||
@@ -109,7 +109,7 @@ export class BaseDropdown extends ActionRunner {
|
||||
}
|
||||
|
||||
isVisible(): boolean {
|
||||
return this.visible;
|
||||
return !!this.visible;
|
||||
}
|
||||
|
||||
protected onEvent(e: Event, activeElement: HTMLElement): void {
|
||||
@@ -272,7 +272,7 @@ export class DropdownMenu extends BaseDropdown {
|
||||
|
||||
export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
private menuActionsOrProvider: any;
|
||||
private dropdownMenu: DropdownMenu;
|
||||
private dropdownMenu: DropdownMenu | undefined;
|
||||
private contextMenuProvider: IContextMenuProvider;
|
||||
private actionViewItemProvider?: IActionViewItemProvider;
|
||||
private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
@@ -281,7 +281,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
|
||||
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
|
||||
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
|
||||
constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) {
|
||||
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) {
|
||||
super(null, action);
|
||||
|
||||
this.menuActionsOrProvider = menuActionsOrProvider;
|
||||
|
||||
@@ -114,7 +114,130 @@ export class FindInput extends Widget {
|
||||
this.inputValidationErrorBackground = options.inputValidationErrorBackground;
|
||||
this.inputValidationErrorForeground = options.inputValidationErrorForeground;
|
||||
|
||||
this.buildDomNode(options.appendCaseSensitiveLabel || '', options.appendWholeWordsLabel || '', options.appendRegexLabel || '', options.history || [], !!options.flexibleHeight);
|
||||
const appendCaseSensitiveLabel = options.appendCaseSensitiveLabel || '';
|
||||
const appendWholeWordsLabel = options.appendWholeWordsLabel || '';
|
||||
const appendRegexLabel = options.appendRegexLabel || '';
|
||||
const history = options.history || [];
|
||||
const flexibleHeight = !!options.flexibleHeight;
|
||||
|
||||
this.domNode = document.createElement('div');
|
||||
dom.addClass(this.domNode, 'monaco-findInput');
|
||||
|
||||
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
|
||||
placeholder: this.placeholder || '',
|
||||
ariaLabel: this.label || '',
|
||||
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
|
||||
}));
|
||||
|
||||
this.regex = this._register(new RegexCheckbox({
|
||||
appendTitle: appendRegexLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.regex.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
this._register(this.regex.onKeyDown(e => {
|
||||
this._onRegexKeyDown.fire(e);
|
||||
}));
|
||||
|
||||
this.wholeWords = this._register(new WholeWordsCheckbox({
|
||||
appendTitle: appendWholeWordsLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.wholeWords.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
|
||||
this.caseSensitive = this._register(new CaseSensitiveCheckbox({
|
||||
appendTitle: appendCaseSensitiveLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.caseSensitive.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
this._register(this.caseSensitive.onKeyDown(e => {
|
||||
this._onCaseSensitiveKeyDown.fire(e);
|
||||
}));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow-Key support to navigate between options
|
||||
let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.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.caseSensitive.domNode);
|
||||
controls.appendChild(this.wholeWords.domNode);
|
||||
controls.appendChild(this.regex.domNode);
|
||||
|
||||
this.domNode.appendChild(controls);
|
||||
|
||||
if (parent) {
|
||||
parent.appendChild(this.domNode);
|
||||
@@ -270,127 +393,6 @@ export class FindInput extends Widget {
|
||||
dom.addClass(this.domNode, 'highlight-' + (this._lastHighlightFindOptions));
|
||||
}
|
||||
|
||||
private buildDomNode(appendCaseSensitiveLabel: string, appendWholeWordsLabel: string, appendRegexLabel: string, history: string[], flexibleHeight: boolean): void {
|
||||
this.domNode = document.createElement('div');
|
||||
dom.addClass(this.domNode, 'monaco-findInput');
|
||||
|
||||
this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
|
||||
placeholder: this.placeholder || '',
|
||||
ariaLabel: this.label || '',
|
||||
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
|
||||
}));
|
||||
|
||||
this.regex = this._register(new RegexCheckbox({
|
||||
appendTitle: appendRegexLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.regex.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
this._register(this.regex.onKeyDown(e => {
|
||||
this._onRegexKeyDown.fire(e);
|
||||
}));
|
||||
|
||||
this.wholeWords = this._register(new WholeWordsCheckbox({
|
||||
appendTitle: appendWholeWordsLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.wholeWords.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
|
||||
this.caseSensitive = this._register(new CaseSensitiveCheckbox({
|
||||
appendTitle: appendCaseSensitiveLabel,
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground
|
||||
}));
|
||||
this._register(this.caseSensitive.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
this.validate();
|
||||
}));
|
||||
this._register(this.caseSensitive.onKeyDown(e => {
|
||||
this._onCaseSensitiveKeyDown.fire(e);
|
||||
}));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow-Key support to navigate between options
|
||||
let indexes = [this.caseSensitive.domNode, this.wholeWords.domNode, this.regex.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.caseSensitive.domNode);
|
||||
controls.appendChild(this.wholeWords.domNode);
|
||||
controls.appendChild(this.regex.domNode);
|
||||
|
||||
this.domNode.appendChild(controls);
|
||||
}
|
||||
|
||||
public validate(): void {
|
||||
if (this.inputBox) {
|
||||
this.inputBox.validate();
|
||||
|
||||
@@ -277,6 +277,24 @@ export class Grid<T extends IView = IView> extends Disposable {
|
||||
this._addView(newView, viewSize, location);
|
||||
}
|
||||
|
||||
addViewAt(newView: T, size: number | DistributeSizing | InvisibleSizing, location: number[]): void {
|
||||
if (this.views.has(newView)) {
|
||||
throw new Error('Can\'t add same view twice');
|
||||
}
|
||||
|
||||
let viewSize: number | GridViewSizing;
|
||||
|
||||
if (typeof size === 'number') {
|
||||
viewSize = size;
|
||||
} else if (size.type === 'distribute') {
|
||||
viewSize = GridViewSizing.Distribute;
|
||||
} else {
|
||||
viewSize = size;
|
||||
}
|
||||
|
||||
this._addView(newView, viewSize, location);
|
||||
}
|
||||
|
||||
protected _addView(newView: T, size: number | GridViewSizing, location: number[]): void {
|
||||
this.views.set(newView, newView.element);
|
||||
this.gridview.addView(newView, size, location);
|
||||
@@ -308,6 +326,26 @@ export class Grid<T extends IView = IView> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
moveViewTo(view: T, location: number[]): void {
|
||||
const sourceLocation = this.getViewLocation(view);
|
||||
const [sourceParentLocation, from] = tail(sourceLocation);
|
||||
const [targetParentLocation, to] = tail(location);
|
||||
|
||||
if (equals(sourceParentLocation, targetParentLocation)) {
|
||||
this.gridview.moveView(sourceParentLocation, from, to);
|
||||
} else {
|
||||
const size = this.getViewSize(view);
|
||||
const orientation = getLocationOrientation(this.gridview.orientation, sourceLocation);
|
||||
const cachedViewSize = this.getViewCachedVisibleSize(view);
|
||||
const sizing = typeof cachedViewSize === 'undefined'
|
||||
? (orientation === Orientation.HORIZONTAL ? size.width : size.height)
|
||||
: Sizing.Invisible(cachedViewSize);
|
||||
|
||||
this.removeView(view);
|
||||
this.addViewAt(view, sizing, location);
|
||||
}
|
||||
}
|
||||
|
||||
swapViews(from: T, to: T): void {
|
||||
const fromLocation = this.getViewLocation(from);
|
||||
const toLocation = this.getViewLocation(to);
|
||||
@@ -319,11 +357,20 @@ export class Grid<T extends IView = IView> extends Disposable {
|
||||
return this.gridview.resizeView(location, size);
|
||||
}
|
||||
|
||||
getViewSize(view: T): IViewSize {
|
||||
getViewSize(view?: T): IViewSize {
|
||||
if (!view) {
|
||||
return this.gridview.getViewSize();
|
||||
}
|
||||
|
||||
const location = this.getViewLocation(view);
|
||||
return this.gridview.getViewSize(location);
|
||||
}
|
||||
|
||||
getViewCachedVisibleSize(view: T): number | undefined {
|
||||
const location = this.getViewLocation(view);
|
||||
return this.gridview.getViewCachedVisibleSize(location);
|
||||
}
|
||||
|
||||
maximizeViewSize(view: T): void {
|
||||
const location = this.getViewLocation(view);
|
||||
this.gridview.maximizeViewSize(location);
|
||||
@@ -373,7 +420,7 @@ export class Grid<T extends IView = IView> extends Disposable {
|
||||
.map(node => node.view);
|
||||
}
|
||||
|
||||
private getViewLocation(view: T): number[] {
|
||||
getViewLocation(view: T): number[] {
|
||||
const element = this.views.get(view);
|
||||
|
||||
if (!element) {
|
||||
@@ -422,7 +469,7 @@ export interface ISerializableView extends IView {
|
||||
}
|
||||
|
||||
export interface IViewDeserializer<T extends ISerializableView> {
|
||||
fromJSON(json: object | null): T;
|
||||
fromJSON(json: any): T;
|
||||
}
|
||||
|
||||
interface InitialLayoutContext<T extends ISerializableView> {
|
||||
@@ -433,7 +480,7 @@ interface InitialLayoutContext<T extends ISerializableView> {
|
||||
|
||||
export interface ISerializedLeafNode {
|
||||
type: 'leaf';
|
||||
data: object | null;
|
||||
data: any;
|
||||
size: number;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'
|
||||
import { $ } from 'vs/base/browser/dom';
|
||||
import { tail2 as tail } from 'vs/base/common/arrays';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { clamp } from 'vs/base/common/numbers';
|
||||
|
||||
export { Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview';
|
||||
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
@@ -277,9 +278,7 @@ class BranchNode implements ISplitView, IDisposable {
|
||||
throw new Error('Invalid from index');
|
||||
}
|
||||
|
||||
if (to < 0 || to > this.children.length) {
|
||||
throw new Error('Invalid to index');
|
||||
}
|
||||
to = clamp(to, 0, this.children.length);
|
||||
|
||||
if (from < to) {
|
||||
to--;
|
||||
@@ -300,9 +299,7 @@ class BranchNode implements ISplitView, IDisposable {
|
||||
throw new Error('Invalid from index');
|
||||
}
|
||||
|
||||
if (to < 0 || to >= this.children.length) {
|
||||
throw new Error('Invalid to index');
|
||||
}
|
||||
to = clamp(to, 0, this.children.length);
|
||||
|
||||
this.splitview.swapViews(from, to);
|
||||
[this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash, this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash] = [this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash, this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash];
|
||||
@@ -351,6 +348,7 @@ class BranchNode implements ISplitView, IDisposable {
|
||||
}
|
||||
|
||||
this.splitview.setViewVisible(index, visible);
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
|
||||
getChildCachedVisibleSize(index: number): number | undefined {
|
||||
@@ -442,9 +440,6 @@ class LeafNode implements ISplitView, IDisposable {
|
||||
private _size: number = 0;
|
||||
get size(): number { return this._size; }
|
||||
|
||||
private _cachedVisibleSize: number | undefined;
|
||||
get cachedVisibleSize(): number | undefined { return this._cachedVisibleSize; }
|
||||
|
||||
private _orthogonalSize: number;
|
||||
get orthogonalSize(): number { return this._orthogonalSize; }
|
||||
|
||||
@@ -553,12 +548,6 @@ class LeafNode implements ISplitView, IDisposable {
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
if (visible) {
|
||||
this._cachedVisibleSize = undefined;
|
||||
} else {
|
||||
this._cachedVisibleSize = this._size;
|
||||
}
|
||||
|
||||
if (this.view.setVisible) {
|
||||
this.view.setVisible(visible);
|
||||
}
|
||||
@@ -610,7 +599,7 @@ export class GridView implements IDisposable {
|
||||
private styles: IGridViewStyles;
|
||||
private proportionalLayout: boolean;
|
||||
|
||||
private _root: BranchNode;
|
||||
private _root!: BranchNode;
|
||||
private onDidSashResetRelay = new Relay<number[]>();
|
||||
readonly onDidSashReset: Event<number[]> = this.onDidSashResetRelay.event;
|
||||
|
||||
@@ -765,6 +754,7 @@ export class GridView implements IDisposable {
|
||||
const [, parentIndex] = tail(rest);
|
||||
|
||||
const sibling = parent.children[0];
|
||||
const isSiblingVisible = parent.isChildVisible(0);
|
||||
parent.removeChild(0);
|
||||
|
||||
const sizes = grandParent.children.map((_, i) => grandParent.getChildSize(i));
|
||||
@@ -779,7 +769,8 @@ export class GridView implements IDisposable {
|
||||
}
|
||||
} else {
|
||||
const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), this.layoutController, sibling.size);
|
||||
grandParent.addChild(newSibling, sibling.orthogonalSize, parentIndex);
|
||||
const sizing = isSiblingVisible ? sibling.orthogonalSize : Sizing.Invisible(sibling.orthogonalSize);
|
||||
grandParent.addChild(newSibling, sizing, parentIndex);
|
||||
}
|
||||
|
||||
for (let i = 0; i < sizes.length; i++) {
|
||||
@@ -868,11 +859,26 @@ export class GridView implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
getViewSize(location: number[]): IViewSize {
|
||||
getViewSize(location?: number[]): IViewSize {
|
||||
if (!location) {
|
||||
return { width: this.root.width, height: this.root.height };
|
||||
}
|
||||
|
||||
const [, node] = this.getNode(location);
|
||||
return { width: node.width, height: node.height };
|
||||
}
|
||||
|
||||
getViewCachedVisibleSize(location: number[]): number | undefined {
|
||||
const [rest, index] = tail(location);
|
||||
const [, parent] = this.getNode(rest);
|
||||
|
||||
if (!(parent instanceof BranchNode)) {
|
||||
throw new Error('Invalid location');
|
||||
}
|
||||
|
||||
return parent.getChildCachedVisibleSize(index);
|
||||
}
|
||||
|
||||
maximizeViewSize(location: number[]): void {
|
||||
const [ancestors, node] = this.getNode(location);
|
||||
|
||||
@@ -929,12 +935,13 @@ export class GridView implements IDisposable {
|
||||
return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height });
|
||||
}
|
||||
|
||||
private _getViews(node: Node, orientation: Orientation, box: Box): GridNode {
|
||||
private _getViews(node: Node, orientation: Orientation, box: Box, cachedVisibleSize?: number): GridNode {
|
||||
if (node instanceof LeafNode) {
|
||||
return { view: node.view, box, cachedVisibleSize: node.cachedVisibleSize };
|
||||
return { view: node.view, box, cachedVisibleSize };
|
||||
}
|
||||
|
||||
const children: GridNode[] = [];
|
||||
let i = 0;
|
||||
let offset = 0;
|
||||
|
||||
for (const child of node.children) {
|
||||
@@ -942,8 +949,9 @@ export class GridView implements IDisposable {
|
||||
const childBox: Box = orientation === Orientation.HORIZONTAL
|
||||
? { top: box.top, left: box.left + offset, width: child.width, height: box.height }
|
||||
: { top: box.top + offset, left: box.left, width: box.width, height: child.height };
|
||||
const cachedVisibleSize = node.getChildCachedVisibleSize(i++);
|
||||
|
||||
children.push(this._getViews(child, childOrientation, childBox));
|
||||
children.push(this._getViews(child, childOrientation, childBox, cachedVisibleSize));
|
||||
offset += orientation === Orientation.HORIZONTAL ? child.width : child.height;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
export interface IIconLabelCreationOptions {
|
||||
supportHighlights?: boolean;
|
||||
supportDescriptionHighlights?: boolean;
|
||||
donotSupportOcticons?: boolean;
|
||||
supportOcticons?: boolean;
|
||||
}
|
||||
|
||||
export interface IIconLabelValueOptions {
|
||||
@@ -100,13 +100,13 @@ export class IconLabel extends Disposable {
|
||||
this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container'))));
|
||||
|
||||
if (options && options.supportHighlights) {
|
||||
this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !options.donotSupportOcticons);
|
||||
this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !!options.supportOcticons);
|
||||
} else {
|
||||
this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name'))));
|
||||
}
|
||||
|
||||
if (options && options.supportDescriptionHighlights) {
|
||||
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !options.donotSupportOcticons);
|
||||
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !!options.supportOcticons);
|
||||
} else {
|
||||
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description'))));
|
||||
}
|
||||
|
||||
@@ -58,7 +58,12 @@
|
||||
|
||||
.monaco-inputbox > .wrapper > textarea.input {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
-ms-overflow-style: none; /* IE 10+ */
|
||||
overflow: -moz-scrollbars-none; /* Firefox */
|
||||
}
|
||||
|
||||
.monaco-inputbox > .wrapper > textarea.input::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-inputbox > .wrapper > .mirror {
|
||||
@@ -116,4 +121,4 @@
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ import { Color } from 'vs/base/common/color';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { HistoryNavigator } from 'vs/base/common/history';
|
||||
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
|
||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -28,6 +31,7 @@ export interface IInputOptions extends IInputBoxStyles {
|
||||
readonly type?: string;
|
||||
readonly validationOptions?: IInputValidationOptions;
|
||||
readonly flexibleHeight?: boolean;
|
||||
readonly flexibleMaxHeight?: number;
|
||||
readonly actions?: ReadonlyArray<IAction>;
|
||||
|
||||
|
||||
@@ -93,7 +97,6 @@ export class InputBox extends Widget {
|
||||
private contextViewProvider?: IContextViewProvider;
|
||||
element: HTMLElement;
|
||||
private input: HTMLInputElement;
|
||||
private mirror: HTMLElement;
|
||||
private actionbar?: ActionBar;
|
||||
private options: IInputOptions;
|
||||
private message: IMessage | null;
|
||||
@@ -101,7 +104,12 @@ export class InputBox extends Widget {
|
||||
private ariaLabel: string;
|
||||
private validation?: IInputValidator;
|
||||
private state: 'idle' | 'open' | 'closed' = 'idle';
|
||||
private cachedHeight: number | null;
|
||||
|
||||
private mirror: HTMLElement | undefined;
|
||||
private cachedHeight: number | undefined;
|
||||
private cachedContentHeight: number | undefined;
|
||||
private maxHeight: number = Number.POSITIVE_INFINITY;
|
||||
private scrollableElement: ScrollableElement | undefined;
|
||||
|
||||
// {{SQL CARBON EDIT}} - Add showValidationMessage and set inputBackground, inputForeground, and inputBorder as protected
|
||||
protected showValidationMessage: boolean;
|
||||
@@ -133,7 +141,6 @@ export class InputBox extends Widget {
|
||||
this.options = options || Object.create(null);
|
||||
mixin(this.options, defaultOpts, false);
|
||||
this.message = null;
|
||||
this.cachedHeight = null;
|
||||
this.placeholder = this.options.placeholder || '';
|
||||
this.ariaLabel = this.options.ariaLabel || '';
|
||||
|
||||
@@ -171,8 +178,26 @@ export class InputBox extends Widget {
|
||||
this.onblur(this.input, () => dom.removeClass(this.element, 'synthetic-focus'));
|
||||
|
||||
if (this.options.flexibleHeight) {
|
||||
this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;
|
||||
|
||||
this.mirror = dom.append(wrapper, $('div.mirror'));
|
||||
this.mirror.innerHTML = ' ';
|
||||
|
||||
this.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });
|
||||
dom.append(container, this.scrollableElement.getDomNode());
|
||||
this._register(this.scrollableElement);
|
||||
|
||||
// from ScrollableElement to DOM
|
||||
this._register(this.scrollableElement.onScroll(e => this.input.scrollTop = e.scrollTop));
|
||||
|
||||
const onSelectionChange = Event.filter(domEvent(document, 'selectionchange'), () => {
|
||||
const selection = document.getSelection();
|
||||
return !!selection && selection.anchorNode === wrapper;
|
||||
});
|
||||
|
||||
// from DOM to ScrollableElement
|
||||
this._register(onSelectionChange(this.updateScrollDimensions, this));
|
||||
this._register(this.onDidHeightChange(this.updateScrollDimensions, this));
|
||||
} else {
|
||||
this.input.type = this.options.type || 'text';
|
||||
this.input.setAttribute('wrap', 'off');
|
||||
@@ -254,7 +279,7 @@ export class InputBox extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
public get mirrorElement(): HTMLElement {
|
||||
public get mirrorElement(): HTMLElement | undefined {
|
||||
return this.mirror;
|
||||
}
|
||||
|
||||
@@ -274,7 +299,7 @@ export class InputBox extends Widget {
|
||||
}
|
||||
|
||||
public get height(): number {
|
||||
return this.cachedHeight === null ? dom.getTotalHeight(this.element) : this.cachedHeight;
|
||||
return typeof this.cachedHeight === 'number' ? this.cachedHeight : dom.getTotalHeight(this.element);
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
@@ -325,6 +350,19 @@ export class InputBox extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
private updateScrollDimensions(): void {
|
||||
if (typeof this.cachedContentHeight !== 'number' || typeof this.cachedHeight !== 'number') {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollHeight = this.cachedContentHeight;
|
||||
const height = this.cachedHeight;
|
||||
const scrollTop = this.input.scrollTop;
|
||||
|
||||
this.scrollableElement!.setScrollDimensions({ scrollHeight, height });
|
||||
this.scrollableElement!.setScrollPosition({ scrollTop });
|
||||
}
|
||||
|
||||
public showMessage(message: IMessage, force?: boolean): void {
|
||||
this.message = message;
|
||||
|
||||
@@ -544,12 +582,13 @@ export class InputBox extends Widget {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousHeight = this.cachedHeight;
|
||||
this.cachedHeight = dom.getTotalHeight(this.mirror);
|
||||
const previousHeight = this.cachedContentHeight;
|
||||
this.cachedContentHeight = dom.getTotalHeight(this.mirror);
|
||||
|
||||
if (previousHeight !== this.cachedHeight) {
|
||||
if (previousHeight !== this.cachedContentHeight) {
|
||||
this.cachedHeight = Math.min(this.cachedContentHeight, this.maxHeight);
|
||||
this.input.style.height = this.cachedHeight + 'px';
|
||||
this._onDidHeightChange.fire(this.cachedHeight);
|
||||
this._onDidHeightChange.fire(this.cachedContentHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class PagedRenderer<TElement, TTemplateData> implements IListRenderer<number, IT
|
||||
export class PagedList<T> implements IDisposable {
|
||||
|
||||
private list: List<number>;
|
||||
private _model: IPagedModel<T>;
|
||||
private _model!: IPagedModel<T>;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
|
||||
@@ -57,6 +57,7 @@ export interface IListViewOptions<T> {
|
||||
readonly mouseSupport?: boolean;
|
||||
readonly horizontalScrolling?: boolean;
|
||||
readonly ariaProvider?: IAriaProvider<T>;
|
||||
readonly additionalScrollHeight?: number;
|
||||
}
|
||||
|
||||
const DefaultOptions = {
|
||||
@@ -163,19 +164,19 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
private lastRenderTop: number;
|
||||
private lastRenderHeight: number;
|
||||
private renderWidth = 0;
|
||||
private gesture: Gesture;
|
||||
private rowsContainer: HTMLElement;
|
||||
private scrollableElement: ScrollableElement;
|
||||
private _scrollHeight: number;
|
||||
private _scrollHeight: number = 0;
|
||||
private scrollableElementUpdateDisposable: IDisposable | null = null;
|
||||
private scrollableElementWidthDelayer = new Delayer<void>(50);
|
||||
private splicing = false;
|
||||
private dragOverAnimationDisposable: IDisposable | undefined;
|
||||
private dragOverAnimationStopDisposable: IDisposable = Disposable.None;
|
||||
private dragOverMouseY: number;
|
||||
private dragOverMouseY: number = 0;
|
||||
private setRowLineHeight: boolean;
|
||||
private supportDynamicHeights: boolean;
|
||||
private horizontalScrolling: boolean;
|
||||
private additionalScrollHeight: number;
|
||||
private ariaProvider: IAriaProvider<T>;
|
||||
private scrollWidth: number | undefined;
|
||||
private canUseTranslate3d: boolean | undefined = undefined;
|
||||
@@ -229,6 +230,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
|
||||
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling);
|
||||
|
||||
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
|
||||
|
||||
this.ariaProvider = options.ariaProvider || { getSetSize: (e, i, length) => length, getPosInSet: (_, index) => index + 1 };
|
||||
|
||||
this.rowsContainer = document.createElement('div');
|
||||
@@ -245,7 +248,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
this.domNode.appendChild(this.scrollableElement.getDomNode());
|
||||
container.appendChild(this.domNode);
|
||||
|
||||
this.disposables = [this.rangeMap, this.gesture, this.scrollableElement, this.cache];
|
||||
this.disposables = [this.rangeMap, this.scrollableElement, this.cache];
|
||||
|
||||
this.scrollableElement.onScroll(this.onScroll, this, this.disposables);
|
||||
domEvent(this.rowsContainer, TouchEventType.Change)(this.onTouchChange, this, this.disposables);
|
||||
@@ -689,7 +692,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
}
|
||||
|
||||
get scrollHeight(): number {
|
||||
return this._scrollHeight + (this.horizontalScrolling ? 10 : 0);
|
||||
return this._scrollHeight + (this.horizontalScrolling ? 10 : 0) + this.additionalScrollHeight;
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
@@ -519,7 +519,7 @@ const DefaultOpenController: IOpenController = {
|
||||
export class MouseController<T> implements IDisposable {
|
||||
|
||||
private multipleSelectionSupport: boolean;
|
||||
readonly multipleSelectionController: IMultipleSelectionController<T>;
|
||||
readonly multipleSelectionController: IMultipleSelectionController<T> | undefined;
|
||||
private openController: IOpenController;
|
||||
private mouseSupport: boolean;
|
||||
private readonly disposables = new DisposableStore();
|
||||
@@ -618,7 +618,7 @@ export class MouseController<T> implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
private onDoubleClick(e: IListMouseEvent<T>): void {
|
||||
protected onDoubleClick(e: IListMouseEvent<T>): void {
|
||||
if (isInputElement(e.browserEvent.target as HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,22 +20,8 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
|
||||
function createMenuMnemonicRegExp() {
|
||||
try {
|
||||
return new RegExp('\\(&([^\\s&])\\)|(?<!&)&([^\\s&])');
|
||||
} catch (err) {
|
||||
return new RegExp('\uFFFF'); // never match please
|
||||
}
|
||||
}
|
||||
export const MENU_MNEMONIC_REGEX = createMenuMnemonicRegExp();
|
||||
function createMenuEscapedMnemonicRegExp() {
|
||||
try {
|
||||
return new RegExp('(?<!&)(?:&)([^\\s&])');
|
||||
} catch (err) {
|
||||
return new RegExp('\uFFFF'); // never match please
|
||||
}
|
||||
}
|
||||
export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = createMenuEscapedMnemonicRegExp();
|
||||
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
|
||||
export const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\s&])/g;
|
||||
|
||||
export interface IMenuOptions {
|
||||
context?: any;
|
||||
@@ -369,6 +355,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
protected options: IMenuItemOptions;
|
||||
protected item: HTMLElement;
|
||||
|
||||
private runOnceToEnableMouseUp: RunOnceScheduler;
|
||||
private label: HTMLElement;
|
||||
private check: HTMLElement;
|
||||
private mnemonic: string;
|
||||
@@ -390,10 +377,24 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
if (label) {
|
||||
let matches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
if (matches) {
|
||||
this.mnemonic = (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase();
|
||||
this.mnemonic = (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add mouse up listener later to avoid accidental clicks
|
||||
this.runOnceToEnableMouseUp = new RunOnceScheduler(() => {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {
|
||||
EventHelper.stop(e, true);
|
||||
this.onClick(e);
|
||||
}));
|
||||
}, 50);
|
||||
|
||||
this._register(this.runOnceToEnableMouseUp);
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
@@ -425,10 +426,8 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
append(this.item, $('span.keybinding')).textContent = this.options.keybinding;
|
||||
}
|
||||
|
||||
this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {
|
||||
EventHelper.stop(e, true);
|
||||
this.onClick(e);
|
||||
}));
|
||||
// Adds mouse up listener to actually run the action
|
||||
this.runOnceToEnableMouseUp.schedule();
|
||||
|
||||
this.updateClass();
|
||||
this.updateLabel();
|
||||
@@ -467,9 +466,23 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
const matches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
if (matches) {
|
||||
label = strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<u aria-hidden="true">$1</u>');
|
||||
label = strings.escape(label);
|
||||
|
||||
// This is global, reset it
|
||||
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
|
||||
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
// We can't use negative lookbehind so if we match our negative and skip
|
||||
while (escMatch && escMatch[1]) {
|
||||
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
|
||||
}
|
||||
|
||||
if (escMatch) {
|
||||
label = `${label.substr(0, escMatch.index)}<u aria-hidden="true">${escMatch[3]}</u>${label.substr(escMatch.index + escMatch[0].length)}`;
|
||||
}
|
||||
|
||||
label = label.replace(/&&/g, '&');
|
||||
this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase());
|
||||
this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase());
|
||||
} else {
|
||||
label = label.replace(/&&/g, '&');
|
||||
}
|
||||
@@ -802,7 +815,7 @@ export function cleanMnemonic(label: string): string {
|
||||
return label;
|
||||
}
|
||||
|
||||
const mnemonicInText = matches[0].charAt(0) === '&';
|
||||
const mnemonicInText = !matches[1];
|
||||
|
||||
return label.replace(regex, mnemonicInText ? '$2' : '').trim();
|
||||
return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ export class MenuBar extends Disposable {
|
||||
|
||||
// Register mnemonics
|
||||
if (mnemonicMatches) {
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2];
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
|
||||
|
||||
this.registerMnemonic(this.menuCache.length, mnemonic);
|
||||
}
|
||||
@@ -472,15 +472,34 @@ export class MenuBar extends Disposable {
|
||||
const cleanMenuLabel = cleanMnemonic(label);
|
||||
|
||||
// Update the button label to reflect mnemonics
|
||||
titleElement.innerHTML = this.options.enableMnemonics ?
|
||||
strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<mnemonic aria-hidden="true">$1</mnemonic>').replace(/&&/g, '&') :
|
||||
cleanMenuLabel.replace(/&&/g, '&');
|
||||
|
||||
if (this.options.enableMnemonics) {
|
||||
let innerHtml = strings.escape(label);
|
||||
|
||||
// This is global so reset it
|
||||
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
|
||||
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
|
||||
|
||||
// We can't use negative lookbehind so we match our negative and skip
|
||||
while (escMatch && escMatch[1]) {
|
||||
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
|
||||
}
|
||||
|
||||
if (escMatch) {
|
||||
innerHtml = `${innerHtml.substr(0, escMatch.index)}<mnemonic aria-hidden="true">${escMatch[3]}</mnemonic>${innerHtml.substr(escMatch.index + escMatch[0].length)}`;
|
||||
}
|
||||
|
||||
innerHtml = innerHtml.replace(/&&/g, '&');
|
||||
titleElement.innerHTML = innerHtml;
|
||||
} else {
|
||||
titleElement.innerHTML = cleanMenuLabel.replace(/&&/g, '&');
|
||||
}
|
||||
|
||||
let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
// Register mnemonics
|
||||
if (mnemonicMatches) {
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2];
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
|
||||
|
||||
if (this.options.enableMnemonics) {
|
||||
buttonElement.setAttribute('aria-keyshortcuts', 'Alt+' + mnemonic.toLocaleLowerCase());
|
||||
|
||||
@@ -61,7 +61,7 @@ export class Sash extends Disposable {
|
||||
private el: HTMLElement;
|
||||
private layoutProvider: ISashLayoutProvider;
|
||||
private hidden: boolean;
|
||||
private orientation: Orientation;
|
||||
private orientation!: Orientation;
|
||||
|
||||
private _state: SashState = SashState.Enabled;
|
||||
get state(): SashState { return this._state; }
|
||||
|
||||
@@ -49,7 +49,7 @@ export abstract class AbstractScrollbar extends Widget {
|
||||
private _mouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
|
||||
|
||||
public domNode: FastDomNode<HTMLElement>;
|
||||
public slider: FastDomNode<HTMLElement>;
|
||||
public slider!: FastDomNode<HTMLElement>;
|
||||
|
||||
protected _shouldRender: boolean;
|
||||
|
||||
|
||||
@@ -148,9 +148,9 @@ export abstract class AbstractScrollableElement extends Widget {
|
||||
private readonly _horizontalScrollbar: HorizontalScrollbar;
|
||||
private readonly _domNode: HTMLElement;
|
||||
|
||||
private readonly _leftShadowDomNode: FastDomNode<HTMLElement>;
|
||||
private readonly _topShadowDomNode: FastDomNode<HTMLElement>;
|
||||
private readonly _topLeftShadowDomNode: FastDomNode<HTMLElement>;
|
||||
private readonly _leftShadowDomNode: FastDomNode<HTMLElement> | null;
|
||||
private readonly _topShadowDomNode: FastDomNode<HTMLElement> | null;
|
||||
private readonly _topLeftShadowDomNode: FastDomNode<HTMLElement> | null;
|
||||
|
||||
private readonly _listenOnDomNode: HTMLElement;
|
||||
|
||||
@@ -207,6 +207,10 @@ export abstract class AbstractScrollableElement extends Widget {
|
||||
this._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));
|
||||
this._topLeftShadowDomNode.setClassName('shadow top-left-corner');
|
||||
this._domNode.appendChild(this._topLeftShadowDomNode.domNode);
|
||||
} else {
|
||||
this._leftShadowDomNode = null;
|
||||
this._topShadowDomNode = null;
|
||||
this._topLeftShadowDomNode = null;
|
||||
}
|
||||
|
||||
this._listenOnDomNode = this._options.listenOnDomNode || this._domNode;
|
||||
@@ -430,9 +434,9 @@ export abstract class AbstractScrollableElement extends Widget {
|
||||
let enableTop = scrollState.scrollTop > 0;
|
||||
let enableLeft = scrollState.scrollLeft > 0;
|
||||
|
||||
this._leftShadowDomNode.setClassName('shadow' + (enableLeft ? ' left' : ''));
|
||||
this._topShadowDomNode.setClassName('shadow' + (enableTop ? ' top' : ''));
|
||||
this._topLeftShadowDomNode.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
|
||||
this._leftShadowDomNode!.setClassName('shadow' + (enableLeft ? ' left' : ''));
|
||||
this._topShadowDomNode!.setClassName('shadow' + (enableTop ? ' top' : ''));
|
||||
this._topLeftShadowDomNode!.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'vs/css!./selectBox';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { deepClone, mixin } from 'vs/base/common/objects';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative';
|
||||
@@ -77,14 +77,11 @@ export class SelectBox extends Widget implements ISelectBoxDelegate {
|
||||
protected selectBackground?: Color;
|
||||
protected selectForeground?: Color;
|
||||
protected selectBorder?: Color;
|
||||
private styles: ISelectBoxStyles;
|
||||
private selectBoxDelegate: ISelectBoxDelegate;
|
||||
|
||||
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) {
|
||||
super();
|
||||
|
||||
mixin(this.styles, defaultStyles, false);
|
||||
|
||||
// Default to native SelectBox for OSX unless overridden
|
||||
if (isMacintosh && !(selectBoxOptions && selectBoxOptions.useCustomDrawn)) {
|
||||
this.selectBoxDelegate = new SelectBoxNative(options, selected, styles, selectBoxOptions);
|
||||
|
||||
@@ -93,23 +93,24 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
|
||||
private _isVisible: boolean;
|
||||
private selectBoxOptions: ISelectBoxOptions;
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
public selectElement: HTMLSelectElement;
|
||||
private options: ISelectOptionItem[];
|
||||
private options: ISelectOptionItem[] = [];
|
||||
private selected: number;
|
||||
private readonly _onDidSelect: Emitter<ISelectData>;
|
||||
private styles: ISelectBoxStyles;
|
||||
private listRenderer: SelectListRenderer;
|
||||
private contextViewProvider: IContextViewProvider;
|
||||
private selectDropDownContainer: HTMLElement;
|
||||
private styleElement: HTMLStyleElement;
|
||||
private selectList: List<ISelectOptionItem>;
|
||||
private selectDropDownListContainer: HTMLElement;
|
||||
private widthControlElement: HTMLElement;
|
||||
private _currentSelection: number;
|
||||
private _dropDownPosition: AnchorPosition;
|
||||
private listRenderer!: SelectListRenderer;
|
||||
private contextViewProvider!: IContextViewProvider;
|
||||
private selectDropDownContainer!: HTMLElement;
|
||||
private styleElement!: HTMLStyleElement;
|
||||
private selectList!: List<ISelectOptionItem>;
|
||||
private selectDropDownListContainer!: HTMLElement;
|
||||
private widthControlElement!: HTMLElement;
|
||||
private _currentSelection = 0;
|
||||
private _dropDownPosition!: AnchorPosition;
|
||||
private _hasDetails: boolean = false;
|
||||
private selectionDetailsPane: HTMLElement;
|
||||
private selectionDetailsPane!: HTMLElement;
|
||||
private _skipLayout: boolean = false;
|
||||
|
||||
private _sticky: boolean = false; // for dev purposes only
|
||||
@@ -247,7 +248,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
}
|
||||
|
||||
public setOptions(options: ISelectOptionItem[], selected?: number): void {
|
||||
if (!this.options || !arrays.equals(this.options, options)) {
|
||||
if (!arrays.equals(this.options, options)) {
|
||||
this.options = options;
|
||||
this.selectElement.options.length = 0;
|
||||
this._hasDetails = false;
|
||||
@@ -272,7 +273,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
|
||||
// Mirror options in drop-down
|
||||
// Populate select list for non-native select mode
|
||||
if (this.selectList && !!this.options) {
|
||||
if (this.selectList) {
|
||||
this.selectList.splice(0, this.selectList.length, this.options);
|
||||
}
|
||||
}
|
||||
@@ -704,7 +705,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
private setWidthControlElement(container: HTMLElement): number {
|
||||
let elementWidth = 0;
|
||||
|
||||
if (container && !!this.options) {
|
||||
if (container) {
|
||||
let longest = 0;
|
||||
let longestLength = 0;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
|
||||
public selectElement: HTMLSelectElement;
|
||||
private selectBoxOptions: ISelectBoxOptions;
|
||||
private options: ISelectOptionItem[];
|
||||
private selected: number;
|
||||
private selected = 0;
|
||||
private readonly _onDidSelect: Emitter<ISelectData>;
|
||||
private styles: ISelectBoxStyles;
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ export abstract class Panel extends Disposable implements IView {
|
||||
private static readonly HEADER_SIZE = 22;
|
||||
|
||||
readonly element: HTMLElement;
|
||||
private header: HTMLElement;
|
||||
private body: HTMLElement;
|
||||
private header!: HTMLElement;
|
||||
private body!: HTMLElement;
|
||||
|
||||
protected _expanded: boolean;
|
||||
|
||||
@@ -109,7 +109,7 @@ export abstract class Panel extends Disposable implements IView {
|
||||
return headerSize + maximumBodySize;
|
||||
}
|
||||
|
||||
width: number;
|
||||
width: number = 0;
|
||||
|
||||
constructor(options: IPanelOptions = {}) {
|
||||
super();
|
||||
@@ -371,7 +371,7 @@ export class PanelView extends Disposable {
|
||||
private dndContext: IDndContext = { draggable: null };
|
||||
private el: HTMLElement;
|
||||
private panelItems: IPanelItem[] = [];
|
||||
private width: number;
|
||||
private width: number = 0;
|
||||
private splitview: SplitView;
|
||||
private animationTimer: number | undefined = undefined;
|
||||
|
||||
|
||||
@@ -72,4 +72,4 @@
|
||||
.monaco-split-view2.separator-border.vertical > .split-view-container > .split-view-view:not(:first-child)::before {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ abstract class ViewItem {
|
||||
return typeof this._cachedVisibleSize === 'undefined';
|
||||
}
|
||||
|
||||
set visible(visible: boolean) {
|
||||
setVisible(visible: boolean, size?: number): void {
|
||||
if (visible === this.visible) {
|
||||
return;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ abstract class ViewItem {
|
||||
this.size = clamp(this._cachedVisibleSize!, this.viewMinimumSize, this.viewMaximumSize);
|
||||
this._cachedVisibleSize = undefined;
|
||||
} else {
|
||||
this._cachedVisibleSize = this.size;
|
||||
this._cachedVisibleSize = typeof size === 'number' ? size : this.size;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,10 @@ abstract class ViewItem {
|
||||
dom.addClass(container, 'visible');
|
||||
}
|
||||
|
||||
abstract layout(): void;
|
||||
layout(): void {
|
||||
this.container.scrollTop = 0;
|
||||
this.container.scrollLeft = 0;
|
||||
}
|
||||
|
||||
layoutView(orientation: Orientation): void {
|
||||
this.view.layout(this.size, orientation);
|
||||
@@ -140,6 +143,7 @@ abstract class ViewItem {
|
||||
class VerticalViewItem extends ViewItem {
|
||||
|
||||
layout(): void {
|
||||
super.layout();
|
||||
this.container.style.height = `${this.size}px`;
|
||||
this.layoutView(Orientation.VERTICAL);
|
||||
}
|
||||
@@ -148,6 +152,7 @@ class VerticalViewItem extends ViewItem {
|
||||
class HorizontalViewItem extends ViewItem {
|
||||
|
||||
layout(): void {
|
||||
super.layout();
|
||||
this.container.style.width = `${this.size}px`;
|
||||
this.layoutView(Orientation.HORIZONTAL);
|
||||
}
|
||||
@@ -161,6 +166,7 @@ interface ISashItem {
|
||||
interface ISashDragSnapState {
|
||||
readonly index: number;
|
||||
readonly limitDelta: number;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface ISashDragState {
|
||||
@@ -203,7 +209,7 @@ export class SplitView extends Disposable {
|
||||
private proportions: undefined | number[] = undefined;
|
||||
private viewItems: ViewItem[] = [];
|
||||
private sashItems: ISashItem[] = [];
|
||||
private sashDragState: ISashDragState;
|
||||
private sashDragState: ISashDragState | undefined;
|
||||
private state: State = State.Idle;
|
||||
private inverseAltBehavior: boolean;
|
||||
private proportionalLayout: boolean;
|
||||
@@ -414,9 +420,10 @@ export class SplitView extends Disposable {
|
||||
throw new Error('Cant modify splitview');
|
||||
}
|
||||
|
||||
const size = this.getViewSize(from);
|
||||
const cachedVisibleSize = this.getViewCachedVisibleSize(from);
|
||||
const sizing = typeof cachedVisibleSize === 'undefined' ? this.getViewSize(from) : Sizing.Invisible(cachedVisibleSize);
|
||||
const view = this.removeView(from);
|
||||
this.addView(view, size, to);
|
||||
this.addView(view, sizing, to);
|
||||
}
|
||||
|
||||
swapViews(from: number, to: number): void {
|
||||
@@ -452,10 +459,11 @@ export class SplitView extends Disposable {
|
||||
}
|
||||
|
||||
const viewItem = this.viewItems[index];
|
||||
viewItem.visible = visible;
|
||||
viewItem.setVisible(visible);
|
||||
|
||||
this.distributeEmptySpace(index);
|
||||
this.layoutViews();
|
||||
this.saveProportions();
|
||||
}
|
||||
|
||||
getViewCachedVisibleSize(index: number): number | undefined {
|
||||
@@ -499,8 +507,8 @@ export class SplitView extends Disposable {
|
||||
|
||||
// This way, we can press Alt while we resize a sash, macOS style!
|
||||
const disposable = combinedDisposable(
|
||||
domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState.current, e.altKey)),
|
||||
domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState.current, false))
|
||||
domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState!.current, e.altKey)),
|
||||
domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState!.current, false))
|
||||
);
|
||||
|
||||
const resetSashDragState = (start: number, alt: boolean) => {
|
||||
@@ -550,7 +558,8 @@ export class SplitView extends Disposable {
|
||||
|
||||
snapBefore = {
|
||||
index: snapBeforeIndex,
|
||||
limitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize
|
||||
limitDelta: viewItem.visible ? minDelta - halfSize : minDelta + halfSize,
|
||||
size: viewItem.size
|
||||
};
|
||||
}
|
||||
|
||||
@@ -560,7 +569,8 @@ export class SplitView extends Disposable {
|
||||
|
||||
snapAfter = {
|
||||
index: snapAfterIndex,
|
||||
limitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize
|
||||
limitDelta: viewItem.visible ? maxDelta + halfSize : maxDelta - halfSize,
|
||||
size: viewItem.size
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -572,8 +582,8 @@ export class SplitView extends Disposable {
|
||||
}
|
||||
|
||||
private onSashChange({ current }: ISashEvent): void {
|
||||
const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState;
|
||||
this.sashDragState.current = current;
|
||||
const { index, start, sizes, alt, minDelta, maxDelta, snapBefore, snapAfter } = this.sashDragState!;
|
||||
this.sashDragState!.current = current;
|
||||
|
||||
const delta = current - start;
|
||||
const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter);
|
||||
@@ -596,7 +606,7 @@ export class SplitView extends Disposable {
|
||||
|
||||
private onSashEnd(index: number): void {
|
||||
this._onDidSashChange.fire(index);
|
||||
this.sashDragState.disposable.dispose();
|
||||
this.sashDragState!.disposable.dispose();
|
||||
this.saveProportions();
|
||||
}
|
||||
|
||||
@@ -738,14 +748,14 @@ export class SplitView extends Disposable {
|
||||
const snapView = this.viewItems[snapBefore.index];
|
||||
const visible = delta >= snapBefore.limitDelta;
|
||||
snapped = visible !== snapView.visible;
|
||||
snapView.visible = visible;
|
||||
snapView.setVisible(visible, snapBefore.size);
|
||||
}
|
||||
|
||||
if (!snapped && snapAfter) {
|
||||
const snapView = this.viewItems[snapAfter.index];
|
||||
const visible = delta < snapAfter.limitDelta;
|
||||
snapped = visible !== snapView.visible;
|
||||
snapView.visible = visible;
|
||||
snapView.setVisible(visible, snapAfter.size);
|
||||
}
|
||||
|
||||
if (snapped) {
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ToolBar extends Disposable {
|
||||
private actionBar: ActionBar;
|
||||
private toggleMenuAction: ToggleMenuAction;
|
||||
private toggleMenuActionViewItem = this._register(new MutableDisposable<DropdownMenuActionViewItem>());
|
||||
private hasSecondaryActions: boolean;
|
||||
private hasSecondaryActions: boolean = false;
|
||||
private lookupKeybindings: boolean;
|
||||
|
||||
constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) {
|
||||
@@ -162,6 +162,7 @@ class ToggleMenuAction extends Action {
|
||||
title = title || nls.localize('moreActions', "More Actions...");
|
||||
super(ToggleMenuAction.ID, title, undefined, true);
|
||||
|
||||
this._menuActions = [];
|
||||
this.toggleDropdownMenu = toggleDropdownMenu;
|
||||
}
|
||||
|
||||
@@ -178,4 +179,4 @@ class ToggleMenuAction extends Action {
|
||||
set menuActions(actions: ReadonlyArray<IAction>) {
|
||||
this._menuActions = actions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,8 +451,8 @@ class TypeFilter<T> implements ITreeFilter<T, FuzzyScore>, IDisposable {
|
||||
private _matchCount = 0;
|
||||
get matchCount(): number { return this._matchCount; }
|
||||
|
||||
private _pattern: string;
|
||||
private _lowercasePattern: string;
|
||||
private _pattern: string = '';
|
||||
private _lowercasePattern: string = '';
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
set pattern(pattern: string) {
|
||||
@@ -543,7 +543,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
private _filterOnType: boolean;
|
||||
get filterOnType(): boolean { return this._filterOnType; }
|
||||
|
||||
private _empty: boolean;
|
||||
private _empty: boolean = false;
|
||||
get empty(): boolean { return this._empty; }
|
||||
|
||||
private _onDidChangeEmptyState = new Emitter<boolean>();
|
||||
@@ -897,6 +897,7 @@ export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTr
|
||||
readonly autoExpandSingleChildren?: boolean;
|
||||
readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;
|
||||
readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean);
|
||||
readonly additionalScrollHeight?: number;
|
||||
}
|
||||
|
||||
function dfs<T, TFilterData>(node: ITreeNode<T, TFilterData>, fn: (node: ITreeNode<T, TFilterData>) => void): void {
|
||||
@@ -1063,6 +1064,16 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
||||
|
||||
super.onPointer(e);
|
||||
}
|
||||
|
||||
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
|
||||
const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie');
|
||||
|
||||
if (onTwistie) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.onDoubleClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
interface ITreeNodeListOptions<T, TFilterData, TRef> extends IListOptions<ITreeNode<T, TFilterData>> {
|
||||
|
||||
@@ -238,7 +238,8 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
|
||||
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
|
||||
)
|
||||
),
|
||||
ariaProvider: undefined
|
||||
ariaProvider: undefined,
|
||||
additionalScrollHeight: options.additionalScrollHeight
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTree
|
||||
|
||||
export class CompressedObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<ICompressedTreeNode<T> | null, TFilterData, T | null> {
|
||||
|
||||
protected model: CompressedTreeModel<T, TFilterData>;
|
||||
protected model!: CompressedTreeModel<T, TFilterData>;
|
||||
|
||||
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<ICompressedTreeNode<T> | null, TFilterData>> { return this.model.onDidChangeCollapseState; }
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export interface IDataTreeViewState {
|
||||
|
||||
export class DataTree<TInput, T, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
|
||||
|
||||
protected model: ObjectTreeModel<T, TFilterData>;
|
||||
protected model!: ObjectTreeModel<T, TFilterData>;
|
||||
private input: TInput | undefined;
|
||||
|
||||
private identityProvider: IIdentityProvider<T> | undefined;
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface IIndexTreeOptions<T, TFilterData = void> extends IAbstractTreeO
|
||||
|
||||
export class IndexTree<T, TFilterData = void> extends AbstractTree<T, TFilterData, number[]> {
|
||||
|
||||
protected model: IndexTreeModel<T, TFilterData>;
|
||||
protected model!: IndexTreeModel<T, TFilterData>;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTree
|
||||
|
||||
export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
|
||||
|
||||
protected model: IObjectTreeModel<T, TFilterData>;
|
||||
protected model!: IObjectTreeModel<T, TFilterData>;
|
||||
|
||||
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T | null, TFilterData>> { return this.model.onDidChangeCollapseState; }
|
||||
|
||||
|
||||
@@ -64,11 +64,11 @@ export class Action extends Disposable implements IAction {
|
||||
|
||||
protected readonly _id: string;
|
||||
protected _label: string;
|
||||
protected _tooltip: string;
|
||||
protected _tooltip: string | undefined;
|
||||
protected _cssClass: string | undefined;
|
||||
protected _enabled: boolean;
|
||||
protected _checked: boolean;
|
||||
protected _radio: boolean;
|
||||
protected _enabled: boolean = true;
|
||||
protected _checked: boolean = false;
|
||||
protected _radio: boolean = false;
|
||||
protected readonly _actionCallback?: (event?: any) => Promise<any>;
|
||||
|
||||
constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Promise<any>) {
|
||||
@@ -100,7 +100,7 @@ export class Action extends Disposable implements IAction {
|
||||
}
|
||||
|
||||
get tooltip(): string {
|
||||
return this._tooltip;
|
||||
return this._tooltip || '';
|
||||
}
|
||||
|
||||
set tooltip(value: string) {
|
||||
|
||||
@@ -293,7 +293,7 @@ export class Color {
|
||||
}
|
||||
}
|
||||
|
||||
equals(other: Color): boolean {
|
||||
equals(other: Color | null): boolean {
|
||||
return !!other && RGBA.equals(this.rgba, other.rgba) && HSLA.equals(this.hsla, other.hsla) && HSVA.equals(this.hsva, other.hsva);
|
||||
}
|
||||
|
||||
@@ -608,4 +608,4 @@ export namespace Color {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,7 +645,7 @@ export interface IWaitUntil {
|
||||
|
||||
export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
|
||||
|
||||
private _asyncDeliveryQueue: [Listener<T>, T, Promise<any>[]][];
|
||||
private _asyncDeliveryQueue?: [Listener<T>, T, Promise<any>[]][];
|
||||
|
||||
async fireAsync(eventFn: (thenables: Promise<any>[], listener: Function) => T): Promise<void> {
|
||||
if (!this._listeners) {
|
||||
|
||||
@@ -7,9 +7,9 @@ import { INavigator, ArrayNavigator } from 'vs/base/common/iterator';
|
||||
|
||||
export class HistoryNavigator<T> implements INavigator<T> {
|
||||
|
||||
private _history: Set<T>;
|
||||
private _history!: Set<T>;
|
||||
private _limit: number;
|
||||
private _navigator: ArrayNavigator<T>;
|
||||
private _navigator!: ArrayNavigator<T>;
|
||||
|
||||
constructor(history: T[] = [], limit: number = 10) {
|
||||
this._initialize(history);
|
||||
|
||||
@@ -112,9 +112,9 @@ export class StringIterator implements IKeyIterator {
|
||||
|
||||
export class PathIterator implements IKeyIterator {
|
||||
|
||||
private _value: string;
|
||||
private _from: number;
|
||||
private _to: number;
|
||||
private _value!: string;
|
||||
private _from!: number;
|
||||
private _to!: number;
|
||||
|
||||
reset(key: string): this {
|
||||
this._value = key.replace(/\\$|\/$/, '');
|
||||
@@ -176,9 +176,9 @@ export class PathIterator implements IKeyIterator {
|
||||
}
|
||||
|
||||
class TernarySearchTreeNode<E> {
|
||||
segment: string;
|
||||
segment!: string;
|
||||
value: E | undefined;
|
||||
key: string;
|
||||
key!: string;
|
||||
left: TernarySearchTreeNode<E> | undefined;
|
||||
mid: TernarySearchTreeNode<E> | undefined;
|
||||
right: TernarySearchTreeNode<E> | undefined;
|
||||
|
||||
@@ -58,6 +58,8 @@ class ErrorInvalidArgType extends Error {
|
||||
|
||||
msg += `. Received type ${typeof actual}`;
|
||||
super(msg);
|
||||
|
||||
this.code = 'ERR_INVALID_ARG_TYPE';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ export const UTF8_with_bom = 'utf8bom';
|
||||
export const UTF16be = 'utf16be';
|
||||
export const UTF16le = 'utf16le';
|
||||
|
||||
export type UTF_ENCODING = typeof UTF8 | typeof UTF8_with_bom | typeof UTF16be | typeof UTF16le;
|
||||
|
||||
export function isUTFEncoding(encoding: string): encoding is UTF_ENCODING {
|
||||
return [UTF8, UTF8_with_bom, UTF16be, UTF16le].some(utfEncoding => utfEncoding === encoding);
|
||||
}
|
||||
|
||||
export const UTF16be_BOM = [0xFE, 0xFF];
|
||||
export const UTF16le_BOM = [0xFF, 0xFE];
|
||||
export const UTF8_BOM = [0xEF, 0xBB, 0xBF];
|
||||
@@ -41,8 +47,8 @@ export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions
|
||||
|
||||
return new Promise<IDecodeStreamResult>((resolve, reject) => {
|
||||
const writer = new class extends Writable {
|
||||
private decodeStream: NodeJS.ReadWriteStream;
|
||||
private decodeStreamPromise: Promise<void>;
|
||||
private decodeStream: NodeJS.ReadWriteStream | undefined;
|
||||
private decodeStreamPromise: Promise<void> | undefined;
|
||||
|
||||
private bufferedChunks: Buffer[] = [];
|
||||
private bytesBuffered = 0;
|
||||
@@ -116,7 +122,7 @@ export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions
|
||||
// detection. thus, wrap up starting the stream even
|
||||
// without all the data to get things going
|
||||
else {
|
||||
this._startDecodeStream(() => this.decodeStream.end(callback));
|
||||
this._startDecodeStream(() => this.decodeStream!.end(callback));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,20 +138,6 @@ export async function readdir(path: string): Promise<string[]> {
|
||||
return handleDirectoryChildren(await promisify(fs.readdir)(path));
|
||||
}
|
||||
|
||||
export async function readdirWithFileTypes(path: string): Promise<fs.Dirent[]> {
|
||||
const children = await promisify(fs.readdir)(path, { withFileTypes: true });
|
||||
|
||||
// Mac: uses NFD unicode form on disk, but we want NFC
|
||||
// See also https://github.com/nodejs/node/issues/2165
|
||||
if (platform.isMacintosh) {
|
||||
for (const child of children) {
|
||||
child.name = normalizeNFC(child.name);
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
export function readdirSync(path: string): string[] {
|
||||
return handleDirectoryChildren(fs.readdirSync(path));
|
||||
}
|
||||
|
||||
+108
-1
@@ -4,6 +4,10 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { VSBufferReadableStream, VSBufferReadable, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { Readable } from 'stream';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { UTF8, UTF8_with_bom, UTF8_BOM, UTF16be, UTF16le_BOM, UTF16be_BOM, UTF16le, UTF_ENCODING } from 'vs/base/node/encoding';
|
||||
|
||||
/**
|
||||
* Reads a file until a matching string is found.
|
||||
@@ -66,4 +70,107 @@ export function readToMatchingString(file: string, matchingString: string, chunk
|
||||
readChunk();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function streamToNodeReadable(stream: VSBufferReadableStream): Readable {
|
||||
return new class extends Readable {
|
||||
private listening = false;
|
||||
|
||||
_read(size?: number): void {
|
||||
if (!this.listening) {
|
||||
this.listening = true;
|
||||
|
||||
// Data
|
||||
stream.on('data', data => {
|
||||
try {
|
||||
if (!this.push(data.buffer)) {
|
||||
stream.pause(); // pause the stream if we should not push anymore
|
||||
}
|
||||
} catch (error) {
|
||||
this.emit(error);
|
||||
}
|
||||
});
|
||||
|
||||
// End
|
||||
stream.on('end', () => {
|
||||
try {
|
||||
this.push(null); // signal EOS
|
||||
} catch (error) {
|
||||
this.emit(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Error
|
||||
stream.on('error', error => this.emit('error', error));
|
||||
}
|
||||
|
||||
// ensure the stream is flowing
|
||||
stream.resume();
|
||||
}
|
||||
|
||||
_destroy(error: Error | null, callback: (error: Error | null) => void): void {
|
||||
stream.destroy();
|
||||
|
||||
callback(null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function nodeReadableToString(stream: NodeJS.ReadableStream): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let result = '';
|
||||
|
||||
stream.on('data', chunk => result += chunk);
|
||||
stream.on('error', reject);
|
||||
stream.on('end', () => resolve(result));
|
||||
});
|
||||
}
|
||||
|
||||
export function nodeStreamToVSBufferReadable(stream: NodeJS.ReadWriteStream, addBOM?: { encoding: UTF_ENCODING }): VSBufferReadable {
|
||||
let bytesRead = 0;
|
||||
let done = false;
|
||||
|
||||
return {
|
||||
read(): VSBuffer | null {
|
||||
if (done) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const res = stream.read();
|
||||
if (isUndefinedOrNull(res)) {
|
||||
done = true;
|
||||
|
||||
// If we are instructed to add a BOM but we detect that no
|
||||
// bytes have been read, we must ensure to return the BOM
|
||||
// ourselves so that we comply with the contract.
|
||||
if (bytesRead === 0 && addBOM) {
|
||||
switch (addBOM.encoding) {
|
||||
case UTF8:
|
||||
case UTF8_with_bom:
|
||||
return VSBuffer.wrap(Buffer.from(UTF8_BOM));
|
||||
case UTF16be:
|
||||
return VSBuffer.wrap(Buffer.from(UTF16be_BOM));
|
||||
case UTF16le:
|
||||
return VSBuffer.wrap(Buffer.from(UTF16le_BOM));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Handle String
|
||||
if (typeof res === 'string') {
|
||||
bytesRead += res.length;
|
||||
|
||||
return VSBuffer.fromString(res);
|
||||
}
|
||||
|
||||
// Handle Buffer
|
||||
else {
|
||||
bytesRead += res.byteLength;
|
||||
|
||||
return VSBuffer.wrap(res);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class QueueProtocol implements IMessagePassingProtocol {
|
||||
});
|
||||
|
||||
readonly onMessage = this._onMessage.event;
|
||||
other: QueueProtocol;
|
||||
other!: QueueProtocol;
|
||||
|
||||
send(buffer: VSBuffer): void {
|
||||
this.other.receive(buffer);
|
||||
|
||||
@@ -57,7 +57,7 @@ export class QuickOpenEntry {
|
||||
private labelHighlights: IHighlight[];
|
||||
private descriptionHighlights?: IHighlight[];
|
||||
private detailHighlights?: IHighlight[];
|
||||
private hidden: boolean;
|
||||
private hidden: boolean | undefined;
|
||||
|
||||
constructor(highlights: IHighlight[] = []) {
|
||||
this.id = (IDS++).toString();
|
||||
@@ -148,7 +148,7 @@ export class QuickOpenEntry {
|
||||
* Allows to reuse the same model while filtering. Hidden entries will not show up in the viewer.
|
||||
*/
|
||||
isHidden(): boolean {
|
||||
return this.hidden;
|
||||
return !!this.hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,7 +352,7 @@ class Renderer implements IRenderer<QuickOpenEntry> {
|
||||
row1.appendChild(icon);
|
||||
|
||||
// Label
|
||||
const label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true });
|
||||
const label = new IconLabel(row1, { supportHighlights: true, supportDescriptionHighlights: true, supportOcticons: true });
|
||||
|
||||
// Keybinding
|
||||
const keybindingContainer = document.createElement('span');
|
||||
|
||||
@@ -862,10 +862,10 @@ export interface IRefreshEvent extends IBaseEvent {
|
||||
export class TreeModel {
|
||||
|
||||
private context: _.ITreeContext;
|
||||
private lock: Lock;
|
||||
private lock!: Lock;
|
||||
private input: Item | null;
|
||||
private registry: ItemRegistry;
|
||||
private registryDisposable: IDisposable;
|
||||
private registry!: ItemRegistry;
|
||||
private registryDisposable!: IDisposable;
|
||||
private traitsToItems: ITraitMap;
|
||||
|
||||
private _onSetInput = new Emitter<IInputEvent>();
|
||||
|
||||
@@ -121,15 +121,15 @@ export class ViewItem implements IViewItem {
|
||||
public top: number;
|
||||
public height: number;
|
||||
public width: number = 0;
|
||||
public onDragStart: (e: DragEvent) => void;
|
||||
public onDragStart!: (e: DragEvent) => void;
|
||||
|
||||
public needsRender: boolean;
|
||||
public uri: string | null;
|
||||
public needsRender: boolean = false;
|
||||
public uri: string | null = null;
|
||||
public unbindDragStart: Lifecycle.IDisposable = Lifecycle.Disposable.None;
|
||||
public loadingTimer: any;
|
||||
|
||||
public _styles: any;
|
||||
private _draggable: boolean;
|
||||
private _draggable: boolean = false;
|
||||
|
||||
constructor(context: IViewContext, model: Model.Item) {
|
||||
this.context = context;
|
||||
@@ -174,7 +174,7 @@ export class ViewItem implements IViewItem {
|
||||
return (this.row && this.row.element)!;
|
||||
}
|
||||
|
||||
private _templateId: string;
|
||||
private _templateId: string | undefined;
|
||||
private get templateId(): string {
|
||||
return this._templateId || (this._templateId = (this.context.renderer!.getTemplateId && this.context.renderer!.getTemplateId(this.context.tree, this.model.getElement())));
|
||||
}
|
||||
@@ -415,8 +415,8 @@ export class TreeView extends HeightMap {
|
||||
private treeStyler: _.ITreeStyler;
|
||||
private rowsContainer: HTMLElement;
|
||||
private scrollableElement: ScrollableElement;
|
||||
private msGesture: MSGesture;
|
||||
private lastPointerType: string;
|
||||
private msGesture: MSGesture | undefined;
|
||||
private lastPointerType: string = '';
|
||||
private lastClickTimeStamp: number = 0;
|
||||
|
||||
private horizontalScrolling: boolean;
|
||||
@@ -425,14 +425,14 @@ export class TreeView extends HeightMap {
|
||||
private lastRenderTop: number;
|
||||
private lastRenderHeight: number;
|
||||
|
||||
private inputItem: ViewItem;
|
||||
private inputItem!: ViewItem;
|
||||
private items: { [id: string]: ViewItem; };
|
||||
|
||||
private isRefreshing = false;
|
||||
private refreshingPreviousChildrenIds: { [id: string]: string[] } = {};
|
||||
private currentDragAndDropData: IDragAndDropData | null = null;
|
||||
private currentDropElement: any;
|
||||
private currentDropElementReaction: _.IDragOverReaction;
|
||||
private currentDropElementReaction!: _.IDragOverReaction;
|
||||
private currentDropTarget: ViewItem | null = null;
|
||||
private shouldInvalidateDropReaction: boolean;
|
||||
private currentDropTargets: ViewItem[] | null = null;
|
||||
@@ -443,7 +443,7 @@ export class TreeView extends HeightMap {
|
||||
|
||||
private didJustPressContextMenuKey: boolean;
|
||||
|
||||
private highlightedItemWasDraggable: boolean;
|
||||
private highlightedItemWasDraggable: boolean = false;
|
||||
private onHiddenScrollTop: number | null = null;
|
||||
|
||||
private readonly _onDOMFocus = new Emitter<void>();
|
||||
@@ -633,7 +633,7 @@ export class TreeView extends HeightMap {
|
||||
private setupMSGesture(): void {
|
||||
if ((<any>window).MSGesture) {
|
||||
this.msGesture = new MSGesture();
|
||||
setTimeout(() => this.msGesture.target = this.wrapper, 100); // TODO@joh, TODO@IETeam
|
||||
setTimeout(() => this.msGesture!.target = this.wrapper, 100); // TODO@joh, TODO@IETeam
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ export type ValueCallback<T = any> = (value: T | Promise<T>) => void;
|
||||
|
||||
export class DeferredPromise<T> {
|
||||
|
||||
private completeCallback: ValueCallback<T>;
|
||||
private errorCallback: (err: any) => void;
|
||||
private completeCallback!: ValueCallback<T>;
|
||||
private errorCallback!: (err: any) => void;
|
||||
|
||||
public p: Promise<any>;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { isWindows, isLinux } from 'vs/base/common/platform';
|
||||
import { canNormalize } from 'vs/base/common/normalization';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { join } from 'path';
|
||||
|
||||
const chunkSize = 64 * 1024;
|
||||
const readError = 'Error while reading';
|
||||
@@ -387,31 +386,6 @@ suite('PFS', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('readdirWithFileTypes', async () => {
|
||||
if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) {
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
const testDir = join(parentDir, 'pfs', id);
|
||||
|
||||
const newDir = path.join(testDir, 'öäü');
|
||||
await pfs.mkdirp(newDir, 493);
|
||||
|
||||
await pfs.writeFile(join(testDir, 'somefile.txt'), 'contents');
|
||||
|
||||
assert.ok(fs.existsSync(newDir));
|
||||
|
||||
const children = await pfs.readdirWithFileTypes(testDir);
|
||||
|
||||
assert.equal(children.some(n => n.name === 'öäü'), true); // Mac always converts to NFD, so
|
||||
assert.equal(children.some(n => n.isDirectory()), true);
|
||||
|
||||
assert.equal(children.some(n => n.name === 'somefile.txt'), true);
|
||||
assert.equal(children.some(n => n.isFile()), true);
|
||||
|
||||
await pfs.rimraf(parentDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('writeFile (string)', async () => {
|
||||
const smallData = 'Hello World';
|
||||
const bigData = (new Array(100 * 1024)).join('Large String\n');
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Application insights telemetry library -->
|
||||
<script src="https://az416426.vo.msecnd.net/scripts/a/ai.0.js"></script>
|
||||
|
||||
<!-- Require our AMD loader -->
|
||||
<script src="./out/vs/loader.js"></script>
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
'xterm-addon-search': `${window.location.origin}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
|
||||
'xterm-addon-web-links': `${window.location.origin}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`,
|
||||
'semver-umd': `${window.location.origin}/node_modules/semver-umd/lib/semver-umd.js`,
|
||||
'@microsoft/applicationinsights-web': `${window.location.origin}/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,4 +25,4 @@
|
||||
|
||||
api.create(document.body, options);
|
||||
});
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -64,9 +64,9 @@ export function startup(configuration: IssueReporterConfiguration) {
|
||||
}
|
||||
|
||||
export class IssueReporter extends Disposable {
|
||||
private environmentService: IEnvironmentService;
|
||||
private telemetryService: ITelemetryService;
|
||||
private logService: ILogService;
|
||||
private environmentService!: IEnvironmentService;
|
||||
private telemetryService!: ITelemetryService;
|
||||
private logService!: ILogService;
|
||||
private readonly issueReporterModel: IssueReporterModel;
|
||||
private numberOfSearchResultsDisplayed = 0;
|
||||
private receivedSystemInfo = false;
|
||||
@@ -74,7 +74,7 @@ export class IssueReporter extends Disposable {
|
||||
private shouldQueueSearch = false;
|
||||
private hasBeenSubmitted = false;
|
||||
|
||||
private readonly previewButton: Button;
|
||||
private readonly previewButton!: Button;
|
||||
|
||||
constructor(configuration: IssueReporterConfiguration) {
|
||||
super();
|
||||
|
||||
@@ -77,7 +77,7 @@ const eventPrefix = 'monacoworkbench';
|
||||
class MainProcessService implements IMainProcessService {
|
||||
constructor(private server: Server, private mainRouter: StaticRouter) { }
|
||||
|
||||
_serviceBrand: ServiceIdentifier<any>;
|
||||
_serviceBrand!: ServiceIdentifier<any>;
|
||||
|
||||
getChannel(channelName: string): IChannel {
|
||||
return this.server.getChannel(channelName, this.mainRouter);
|
||||
|
||||
@@ -16,9 +16,9 @@ process['lazyEnv'] = getLazyEnv();
|
||||
|
||||
// Load workbench main
|
||||
bootstrapWindow.load([
|
||||
'vs/workbench/workbench.main',
|
||||
'vs/nls!vs/workbench/workbench.main',
|
||||
'vs/css!vs/workbench/workbench.main'
|
||||
'vs/workbench/workbench.desktop.main',
|
||||
'vs/nls!vs/workbench/workbench.desktop.main',
|
||||
'vs/css!vs/workbench/workbench.desktop.main'
|
||||
],
|
||||
function (workbench, configuration) {
|
||||
perf.mark('didLoadWorkbenchMain');
|
||||
|
||||
@@ -18,7 +18,7 @@ export class SharedProcess implements ISharedProcess {
|
||||
|
||||
private barrier = new Barrier();
|
||||
|
||||
private window: Electron.BrowserWindow | null;
|
||||
private window: Electron.BrowserWindow | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly machineId: string,
|
||||
|
||||
@@ -360,17 +360,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
|
||||
this.pendingLoadConfig = undefined;
|
||||
}
|
||||
|
||||
// To prevent flashing, we set the window visible after the page has finished to load but before Code is loaded
|
||||
if (this._win && !this._win.isVisible()) {
|
||||
if (this.windowState.mode === WindowMode.Maximized) {
|
||||
this._win.maximize();
|
||||
}
|
||||
|
||||
if (!this._win.isVisible()) { // maximize also makes visible
|
||||
this._win.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Window Focus
|
||||
@@ -838,17 +827,16 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
}
|
||||
|
||||
private useNativeFullScreen(): boolean {
|
||||
return true; // TODO@ben enable simple fullscreen again (https://github.com/microsoft/vscode/issues/75054)
|
||||
// const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
// if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
|
||||
// return true; // default
|
||||
// }
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
if (!windowConfig || typeof windowConfig.nativeFullScreen !== 'boolean') {
|
||||
return true; // default
|
||||
}
|
||||
|
||||
// if (windowConfig.nativeTabs) {
|
||||
// return true; // https://github.com/electron/electron/issues/16142
|
||||
// }
|
||||
if (windowConfig.nativeTabs) {
|
||||
return true; // https://github.com/electron/electron/issues/16142
|
||||
}
|
||||
|
||||
// return windowConfig.nativeFullScreen !== false;
|
||||
return windowConfig.nativeFullScreen !== false;
|
||||
}
|
||||
|
||||
isMinimized(): boolean {
|
||||
|
||||
@@ -1149,9 +1149,10 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
|
||||
}
|
||||
}
|
||||
|
||||
// Linux/Windows: by default we open files in the new window unless triggered via DIALOG or MENU context
|
||||
// Linux/Windows: by default we open files in the new window unless triggered via DIALOG / MENU context
|
||||
// or from the integrated terminal where we assume the user prefers to open in the current window
|
||||
else {
|
||||
if (openConfig.context !== OpenContext.DIALOG && openConfig.context !== OpenContext.MENU) {
|
||||
if (openConfig.context !== OpenContext.DIALOG && openConfig.context !== OpenContext.MENU && !(openConfig.userEnv && openConfig.userEnv['TERM_PROGRAM'] === 'vscode')) {
|
||||
openFilesInNewWindow = true;
|
||||
}
|
||||
}
|
||||
@@ -1255,10 +1256,9 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
|
||||
openConfig.cli['file-uri'] = fileUris;
|
||||
|
||||
// if there are no files or folders cli args left, use the "remote" cli argument
|
||||
if (!cliArgs.length && !folderUris.length && !fileUris.length) {
|
||||
if (authority) {
|
||||
openConfig.cli.remote = authority;
|
||||
}
|
||||
const noFilesOrFolders = !cliArgs.length && !folderUris.length && !fileUris.length;
|
||||
if (noFilesOrFolders && authority) {
|
||||
openConfig.cli.remote = authority;
|
||||
}
|
||||
|
||||
// Open it
|
||||
@@ -1266,7 +1266,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
|
||||
context: openConfig.context,
|
||||
cli: openConfig.cli,
|
||||
forceNewWindow: true,
|
||||
forceEmpty: !cliArgs.length && !folderUris.length && !fileUris.length,
|
||||
forceEmpty: noFilesOrFolders,
|
||||
userEnv: openConfig.userEnv,
|
||||
noRecentEntry: true,
|
||||
waitMarkerFileURI: openConfig.waitMarkerFileURI
|
||||
@@ -2116,4 +2116,4 @@ function resourceFromURIToOpen(u: IURIToOpen): URI {
|
||||
}
|
||||
|
||||
return u.fileUri;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,33 @@ import * as assert from 'assert';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
|
||||
suite('Windows Native Helpers', () => {
|
||||
test('windows-mutex', async () => {
|
||||
if (!isWindows) {
|
||||
return;
|
||||
}
|
||||
if (!isWindows) {
|
||||
return;
|
||||
}
|
||||
|
||||
test('windows-mutex', async () => {
|
||||
const mutex = await import('windows-mutex');
|
||||
assert.ok(mutex, 'Unable to load windows-mutex dependency.');
|
||||
assert.ok(mutex && typeof mutex.isActive === 'function', 'Unable to load windows-mutex dependency.');
|
||||
assert.ok(typeof mutex.isActive === 'function', 'Unable to load windows-mutex dependency.');
|
||||
});
|
||||
|
||||
test('windows-foreground-love', async () => {
|
||||
if (!isWindows) {
|
||||
return;
|
||||
}
|
||||
|
||||
const foregroundLove = await import('windows-foreground-love');
|
||||
assert.ok(foregroundLove, 'Unable to load windows-foreground-love dependency.');
|
||||
assert.ok(foregroundLove && typeof foregroundLove.allowSetForegroundWindow === 'function', 'Unable to load windows-foreground-love dependency.');
|
||||
});
|
||||
});
|
||||
|
||||
test('windows-process-tree', async () => {
|
||||
const processTree = await import('windows-process-tree');
|
||||
assert.ok(processTree && typeof processTree.getProcessTree === 'function', 'Unable to load windows-process-tree dependency.');
|
||||
});
|
||||
|
||||
test('vscode-windows-ca-certs', async () => {
|
||||
const windowsCerts = await import('vscode-windows-ca-certs');
|
||||
assert.ok(windowsCerts, 'Unable to load vscode-windows-ca-certs dependency.');
|
||||
});
|
||||
|
||||
test('vscode-windows-registry', async () => {
|
||||
const windowsRegistry = await import('vscode-windows-registry');
|
||||
assert.ok(windowsRegistry && typeof windowsRegistry.GetStringRegKey === 'function', 'Unable to load vscode-windows-registry dependency.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Range as EditorRange } from 'vs/editor/common/core/range';
|
||||
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
|
||||
import { ViewContext } from 'vs/editor/common/view/viewContext';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
|
||||
|
||||
export interface IViewZoneData {
|
||||
viewZoneId: number;
|
||||
@@ -410,7 +411,7 @@ class HitTestRequest extends BareHitTestRequest {
|
||||
let mouseColumn = this.mouseColumn;
|
||||
if (position && position.column < this._ctx.model.getLineMaxColumn(position.lineNumber)) {
|
||||
// Most likely, the line contains foreign decorations...
|
||||
mouseColumn = position.column;
|
||||
mouseColumn = CursorColumns.visibleColumnFromColumn(this._ctx.model.getLineContent(position.lineNumber), position.column, this._ctx.model.getOptions().tabSize) + 1;
|
||||
}
|
||||
return new MouseTarget(this.target, type, mouseColumn, position, range, detail);
|
||||
}
|
||||
|
||||
@@ -446,14 +446,8 @@ export class TextAreaHandler extends ViewPart {
|
||||
private _primaryCursorVisibleRange: HorizontalRange | null = null;
|
||||
|
||||
public prepareRender(ctx: RenderingContext): void {
|
||||
if (this._accessibilitySupport === AccessibilitySupport.Enabled) {
|
||||
// Do not move the textarea with the cursor, as this generates accessibility events that might confuse screen readers
|
||||
// See https://github.com/Microsoft/vscode/issues/26730
|
||||
this._primaryCursorVisibleRange = null;
|
||||
} else {
|
||||
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
|
||||
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
|
||||
}
|
||||
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
|
||||
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
|
||||
}
|
||||
|
||||
public render(ctx: RestrictedRenderingContext): void {
|
||||
|
||||
@@ -119,6 +119,7 @@ export class TextAreaInput extends Disposable {
|
||||
this._asyncTriggerCut = this._register(new RunOnceScheduler(() => this._onCut.fire(), 0));
|
||||
|
||||
this._textAreaState = TextAreaState.EMPTY;
|
||||
this._selectionChangeListener = null;
|
||||
this.writeScreenReaderContent('ctor');
|
||||
|
||||
this._hasFocus = false;
|
||||
|
||||
@@ -35,16 +35,25 @@ export class EditorState {
|
||||
if ((this.flags & CodeEditorStateFlag.Value) !== 0) {
|
||||
const model = editor.getModel();
|
||||
this.modelVersionId = model ? strings.format('{0}#{1}', model.uri.toString(), model.getVersionId()) : null;
|
||||
} else {
|
||||
this.modelVersionId = null;
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Position) !== 0) {
|
||||
this.position = editor.getPosition();
|
||||
} else {
|
||||
this.position = null;
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Selection) !== 0) {
|
||||
this.selection = editor.getSelection();
|
||||
} else {
|
||||
this.selection = null;
|
||||
}
|
||||
if ((this.flags & CodeEditorStateFlag.Scroll) !== 0) {
|
||||
this.scrollLeft = editor.getScrollLeft();
|
||||
this.scrollTop = editor.getScrollTop();
|
||||
} else {
|
||||
this.scrollLeft = -1;
|
||||
this.scrollTop = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,13 +127,13 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
|
||||
public refCount: number;
|
||||
|
||||
public className: string | undefined;
|
||||
public inlineClassName: string;
|
||||
public inlineClassNameAffectsLetterSpacing: boolean;
|
||||
public inlineClassName: string | undefined;
|
||||
public inlineClassNameAffectsLetterSpacing: boolean | undefined;
|
||||
public beforeContentClassName: string | undefined;
|
||||
public afterContentClassName: string | undefined;
|
||||
public glyphMarginClassName: string | undefined;
|
||||
public isWholeLine: boolean;
|
||||
public overviewRuler: IModelDecorationOverviewRulerOptions;
|
||||
public overviewRuler: IModelDecorationOverviewRulerOptions | undefined;
|
||||
public stickiness: TrackedRangeStickiness | undefined;
|
||||
|
||||
constructor(themeService: IThemeService, providerArgs: ProviderArguments) {
|
||||
|
||||
@@ -128,22 +128,6 @@ export class View extends ViewEventHandler {
|
||||
this._textAreaHandler = new TextAreaHandler(this._context, viewController, this.createTextAreaHandlerHelper());
|
||||
this.viewParts.push(this._textAreaHandler);
|
||||
|
||||
this.createViewParts();
|
||||
this._setLayout();
|
||||
|
||||
// Pointer handler
|
||||
this.pointerHandler = this._register(new PointerHandler(this._context, viewController, this.createPointerHandlerHelper()));
|
||||
|
||||
this._register(model.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
this.eventDispatcher.emitMany(events);
|
||||
}));
|
||||
|
||||
this._register(this._cursor.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
this.eventDispatcher.emitMany(events);
|
||||
}));
|
||||
}
|
||||
|
||||
private createViewParts(): void {
|
||||
// These two dom nodes must be constructed up front, since references are needed in the layout provider (scrolling & co.)
|
||||
this.linesContent = createFastDomNode(document.createElement('div'));
|
||||
this.linesContent.setClassName('lines-content' + ' monaco-editor-background');
|
||||
@@ -233,6 +217,19 @@ export class View extends ViewEventHandler {
|
||||
this.overflowGuardContainer.appendChild(minimap.getDomNode());
|
||||
this.domNode.appendChild(this.overflowGuardContainer);
|
||||
this.domNode.appendChild(this.contentWidgets.overflowingContentWidgetsDomNode);
|
||||
|
||||
this._setLayout();
|
||||
|
||||
// Pointer handler
|
||||
this.pointerHandler = this._register(new PointerHandler(this._context, viewController, this.createPointerHandlerHelper()));
|
||||
|
||||
this._register(model.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
this.eventDispatcher.emitMany(events);
|
||||
}));
|
||||
|
||||
this._register(this._cursor.addEventListener((events: viewEvents.ViewEvent[]) => {
|
||||
this.eventDispatcher.emitMany(events);
|
||||
}));
|
||||
}
|
||||
|
||||
private _flushAccumulatedAndRenderNow(): void {
|
||||
@@ -541,7 +538,7 @@ export class View extends ViewEventHandler {
|
||||
|
||||
public layoutContentWidget(widgetData: IContentWidgetData): void {
|
||||
const newPosition = widgetData.position ? widgetData.position.position : null;
|
||||
const newRange = widgetData.position ? widgetData.position.range : null;
|
||||
const newRange = widgetData.position ? widgetData.position.range || null : null;
|
||||
const newPreference = widgetData.position ? widgetData.position.preference : null;
|
||||
this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newRange, newPreference);
|
||||
this._scheduleRender();
|
||||
|
||||
@@ -34,8 +34,8 @@ export interface ILine {
|
||||
|
||||
export class RenderedLinesCollection<T extends ILine> {
|
||||
private readonly _createLine: () => T;
|
||||
private _lines: T[];
|
||||
private _rendLineNumberStart: number;
|
||||
private _lines!: T[];
|
||||
private _rendLineNumberStart!: number;
|
||||
|
||||
constructor(createLine: () => T) {
|
||||
this._createLine = createLine;
|
||||
|
||||
@@ -14,7 +14,6 @@ import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/v
|
||||
import { ViewContext } from 'vs/editor/common/view/viewContext';
|
||||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
class Coordinate {
|
||||
_coordinateBrand: void;
|
||||
@@ -111,7 +110,7 @@ export class ViewContentWidgets extends ViewPart {
|
||||
this.setShouldRender();
|
||||
}
|
||||
|
||||
public setWidgetPosition(widget: IContentWidget, position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
|
||||
public setWidgetPosition(widget: IContentWidget, position: IPosition | null, range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {
|
||||
const myWidget = this._widgets[widget.getId()];
|
||||
myWidget.setPosition(position, range, preference);
|
||||
|
||||
@@ -202,8 +201,8 @@ class Widget {
|
||||
this._context = context;
|
||||
this._viewDomNode = viewDomNode;
|
||||
this._actual = actual;
|
||||
this.domNode = createFastDomNode(this._actual.getDomNode());
|
||||
|
||||
this.domNode = createFastDomNode(this._actual.getDomNode());
|
||||
this.id = this._actual.getId();
|
||||
this.allowEditorOverflow = this._actual.allowEditorOverflow || false;
|
||||
this.suppressMouseDown = this._actual.suppressMouseDown || false;
|
||||
@@ -213,7 +212,10 @@ class Widget {
|
||||
this._contentLeft = this._context.configuration.editor.layoutInfo.contentLeft;
|
||||
this._lineHeight = this._context.configuration.editor.lineHeight;
|
||||
|
||||
this._setPosition(null, null);
|
||||
this._position = null;
|
||||
this._range = null;
|
||||
this._viewPosition = null;
|
||||
this._viewRange = null;
|
||||
this._preference = [];
|
||||
this._cachedDomNodeClientWidth = -1;
|
||||
this._cachedDomNodeClientHeight = -1;
|
||||
@@ -242,9 +244,9 @@ class Widget {
|
||||
this._setPosition(this._position, this._range);
|
||||
}
|
||||
|
||||
private _setPosition(position: IPosition | null | undefined, range: IRange | null | undefined): void {
|
||||
this._position = withUndefinedAsNull(position);
|
||||
this._range = withUndefinedAsNull(range);
|
||||
private _setPosition(position: IPosition | null, range: IRange | null): void {
|
||||
this._position = position;
|
||||
this._range = range;
|
||||
this._viewPosition = null;
|
||||
this._viewRange = null;
|
||||
|
||||
@@ -270,9 +272,9 @@ class Widget {
|
||||
);
|
||||
}
|
||||
|
||||
public setPosition(position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
|
||||
public setPosition(position: IPosition | null, range: IRange | null, preference: ContentWidgetPositionPreference[] | null): void {
|
||||
this._setPosition(position, range);
|
||||
this._preference = withUndefinedAsNull(preference);
|
||||
this._preference = preference;
|
||||
this._cachedDomNodeClientWidth = -1;
|
||||
this._cachedDomNodeClientHeight = -1;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
|
||||
private _renderResult: string[] | null;
|
||||
private _enabled: boolean;
|
||||
private _activeIndentEnabled: boolean;
|
||||
private _maxIndentLeft: number;
|
||||
|
||||
constructor(context: ViewContext) {
|
||||
super();
|
||||
@@ -30,6 +31,9 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
|
||||
this._spaceWidth = this._context.configuration.editor.fontInfo.spaceWidth;
|
||||
this._enabled = this._context.configuration.editor.viewInfo.renderIndentGuides;
|
||||
this._activeIndentEnabled = this._context.configuration.editor.viewInfo.highlightActiveIndentGuide;
|
||||
const wrappingColumn = this._context.configuration.editor.wrappingInfo.wrappingColumn;
|
||||
this._maxIndentLeft = wrappingColumn === -1 ? -1 : (wrappingColumn * this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth);
|
||||
|
||||
this._renderResult = null;
|
||||
|
||||
this._context.addEventHandler(this);
|
||||
@@ -54,6 +58,10 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
|
||||
this._enabled = this._context.configuration.editor.viewInfo.renderIndentGuides;
|
||||
this._activeIndentEnabled = this._context.configuration.editor.viewInfo.highlightActiveIndentGuide;
|
||||
}
|
||||
if (e.wrappingInfo || e.fontInfo) {
|
||||
const wrappingColumn = this._context.configuration.editor.wrappingInfo.wrappingColumn;
|
||||
this._maxIndentLeft = wrappingColumn === -1 ? -1 : (wrappingColumn * this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean {
|
||||
@@ -133,7 +141,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
|
||||
const className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr');
|
||||
result += `<div class="${className}" style="left:${left}px;height:${lineHeight}px;width:${indentWidth}px"></div>`;
|
||||
left += indentWidth;
|
||||
if (left > scrollWidth) {
|
||||
if (left > scrollWidth || (this._maxIndentLeft > 0 && left > this._maxIndentLeft)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,12 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
|
||||
|
||||
private readonly _context: ViewContext;
|
||||
|
||||
private _lineHeight: number;
|
||||
private _renderLineNumbers: RenderLineNumbersType;
|
||||
private _renderCustomLineNumbers: ((lineNumber: number) => string) | null;
|
||||
private _renderFinalNewline: boolean;
|
||||
private _lineNumbersLeft: number;
|
||||
private _lineNumbersWidth: number;
|
||||
private _lineHeight!: number;
|
||||
private _renderLineNumbers!: RenderLineNumbersType;
|
||||
private _renderCustomLineNumbers!: ((lineNumber: number) => string) | null;
|
||||
private _renderFinalNewline!: boolean;
|
||||
private _lineNumbersLeft!: number;
|
||||
private _lineNumbersWidth!: number;
|
||||
private _lastCursorModelPosition: Position;
|
||||
private _renderResult: string[] | null;
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
|
||||
private _typicalHalfwidthCharacterWidth: number;
|
||||
private _isViewportWrapping: boolean;
|
||||
private _revealHorizontalRightPadding: number;
|
||||
private _scrollOff: number;
|
||||
private _canUseLayerHinting: boolean;
|
||||
private _viewLineOptions: ViewLineOptions;
|
||||
|
||||
@@ -94,6 +95,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
|
||||
this._typicalHalfwidthCharacterWidth = conf.editor.fontInfo.typicalHalfwidthCharacterWidth;
|
||||
this._isViewportWrapping = conf.editor.wrappingInfo.isViewportWrapping;
|
||||
this._revealHorizontalRightPadding = conf.editor.viewInfo.revealHorizontalRightPadding;
|
||||
this._scrollOff = conf.editor.viewInfo.cursorSurroundingLines;
|
||||
this._canUseLayerHinting = conf.editor.canUseLayerHinting;
|
||||
this._viewLineOptions = new ViewLineOptions(conf, this._context.theme.type);
|
||||
|
||||
@@ -150,6 +152,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
|
||||
}
|
||||
if (e.viewInfo) {
|
||||
this._revealHorizontalRightPadding = conf.editor.viewInfo.revealHorizontalRightPadding;
|
||||
this._scrollOff = conf.editor.viewInfo.cursorSurroundingLines;
|
||||
}
|
||||
if (e.canUseLayerHinting) {
|
||||
this._canUseLayerHinting = conf.editor.canUseLayerHinting;
|
||||
@@ -596,6 +599,11 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
|
||||
// Have a box that includes one extra line height (for the horizontal scrollbar)
|
||||
boxStartY = this._context.viewLayout.getVerticalOffsetForLineNumber(range.startLineNumber);
|
||||
boxEndY = this._context.viewLayout.getVerticalOffsetForLineNumber(range.endLineNumber) + this._lineHeight;
|
||||
|
||||
const context = Math.min((viewportHeight / this._lineHeight) / 2, this._scrollOff);
|
||||
boxStartY -= context * this._lineHeight;
|
||||
boxEndY += Math.max(0, (context - 1)) * this._lineHeight;
|
||||
|
||||
if (verticalType === viewEvents.VerticalRevealType.Simple || verticalType === viewEvents.VerticalRevealType.Bottom) {
|
||||
// Reveal one line more when the last line would be covered by the scrollbar - arrow down case or revealing a line explicitly at bottom
|
||||
boxEndY += this._lineHeight;
|
||||
|
||||
@@ -28,7 +28,16 @@ export class Margin extends ViewPart {
|
||||
this._glyphMarginLeft = this._context.configuration.editor.layoutInfo.glyphMarginLeft;
|
||||
this._glyphMarginWidth = this._context.configuration.editor.layoutInfo.glyphMarginWidth;
|
||||
|
||||
this._domNode = this._createDomNode();
|
||||
this._domNode = createFastDomNode(document.createElement('div'));
|
||||
this._domNode.setClassName(Margin.OUTER_CLASS_NAME);
|
||||
this._domNode.setPosition('absolute');
|
||||
this._domNode.setAttribute('role', 'presentation');
|
||||
this._domNode.setAttribute('aria-hidden', 'true');
|
||||
|
||||
this._glyphMarginBackgroundDomNode = createFastDomNode(document.createElement('div'));
|
||||
this._glyphMarginBackgroundDomNode.setClassName(Margin.CLASS_NAME);
|
||||
|
||||
this._domNode.appendChild(this._glyphMarginBackgroundDomNode);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -39,20 +48,6 @@ export class Margin extends ViewPart {
|
||||
return this._domNode;
|
||||
}
|
||||
|
||||
private _createDomNode(): FastDomNode<HTMLElement> {
|
||||
const domNode = createFastDomNode(document.createElement('div'));
|
||||
domNode.setClassName(Margin.OUTER_CLASS_NAME);
|
||||
domNode.setPosition('absolute');
|
||||
domNode.setAttribute('role', 'presentation');
|
||||
domNode.setAttribute('aria-hidden', 'true');
|
||||
|
||||
this._glyphMarginBackgroundDomNode = createFastDomNode(document.createElement('div'));
|
||||
this._glyphMarginBackgroundDomNode.setClassName(Margin.CLASS_NAME);
|
||||
|
||||
domNode.appendChild(this._glyphMarginBackgroundDomNode);
|
||||
return domNode;
|
||||
}
|
||||
|
||||
// --- begin event handlers
|
||||
|
||||
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
|
||||
|
||||
@@ -742,10 +742,6 @@ export class Minimap extends ViewPart {
|
||||
|
||||
canvasContext.clearRect(0, 0, canvasInnerWidth, canvasInnerHeight);
|
||||
|
||||
// If the minimap is rendered using blocks, text takes up half the line height
|
||||
const lineHeightRatio = renderMinimap === RenderMinimap.LargeBlocks || renderMinimap === RenderMinimap.SmallBlocks ? 0.5 : 1;
|
||||
const height = lineHeight * lineHeightRatio;
|
||||
|
||||
// Loop over decorations, ignoring those that don't have the minimap property set and rendering rectangles for each line the decoration spans
|
||||
const lineOffsetMap = new Map<number, number[]>();
|
||||
for (let i = 0; i < decorations.length; i++) {
|
||||
@@ -756,7 +752,7 @@ export class Minimap extends ViewPart {
|
||||
}
|
||||
|
||||
for (let line = decoration.range.startLineNumber; line <= decoration.range.endLineNumber; line++) {
|
||||
this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration, layout, line, height, lineHeight, tabSize, characterWidth);
|
||||
this.renderDecorationOnLine(canvasContext, lineOffsetMap, decoration, layout, line, lineHeight, lineHeight, tabSize, characterWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ export class DecorationsOverviewRuler extends ViewPart {
|
||||
|
||||
private readonly _tokensColorTrackerListener: IDisposable;
|
||||
private readonly _domNode: FastDomNode<HTMLCanvasElement>;
|
||||
private _settings: Settings;
|
||||
private _settings!: Settings;
|
||||
private _cursorPositions: Position[];
|
||||
|
||||
constructor(context: ViewContext) {
|
||||
|
||||
@@ -68,7 +68,7 @@ export class ViewCursor {
|
||||
Configuration.applyFontInfo(this._domNode, this._context.configuration.editor.fontInfo);
|
||||
this._domNode.setDisplay('none');
|
||||
|
||||
this.updatePosition(new Position(1, 1));
|
||||
this._position = new Position(1, 1);
|
||||
|
||||
this._lastRenderedContent = '';
|
||||
this._renderData = null;
|
||||
@@ -113,7 +113,7 @@ export class ViewCursor {
|
||||
}
|
||||
|
||||
public onCursorPositionChanged(position: Position): boolean {
|
||||
this.updatePosition(position);
|
||||
this._position = position;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -210,8 +210,4 @@ export class ViewCursor {
|
||||
width: 2
|
||||
};
|
||||
}
|
||||
|
||||
private updatePosition(newPosition: Position): void {
|
||||
this._position = newPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ export class ViewCursors extends ViewPart {
|
||||
this._cursorSmoothCaretAnimation = this._context.configuration.editor.viewInfo.cursorSmoothCaretAnimation;
|
||||
this._selectionIsEmpty = true;
|
||||
|
||||
this._isVisible = false;
|
||||
|
||||
this._primaryCursor = new ViewCursor(this._context);
|
||||
this._secondaryCursors = [];
|
||||
this._renderData = [];
|
||||
|
||||
@@ -279,7 +279,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
|
||||
this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));
|
||||
|
||||
this._attachModel(null);
|
||||
this._modelData = null;
|
||||
|
||||
this._contributions = {};
|
||||
this._actions = {};
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { ISashEvent, IVerticalSashLayoutProvider, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { RunOnceScheduler, IntervalTimer } from 'vs/base/common/async';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -159,17 +159,17 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
private _width: number;
|
||||
private _height: number;
|
||||
private _reviewHeight: number;
|
||||
private readonly _measureDomElementToken: number;
|
||||
private readonly _measureDomElementToken: IntervalTimer | null;
|
||||
|
||||
private originalEditor: CodeEditorWidget;
|
||||
private _originalDomNode: HTMLElement;
|
||||
private readonly originalEditor: CodeEditorWidget;
|
||||
private readonly _originalDomNode: HTMLElement;
|
||||
private readonly _originalEditorState: VisualEditorState;
|
||||
private _originalOverviewRuler: editorBrowser.IOverviewRuler;
|
||||
private _originalOverviewRuler: editorBrowser.IOverviewRuler | null;
|
||||
|
||||
private modifiedEditor: CodeEditorWidget;
|
||||
private _modifiedDomNode: HTMLElement;
|
||||
private readonly modifiedEditor: CodeEditorWidget;
|
||||
private readonly _modifiedDomNode: HTMLElement;
|
||||
private readonly _modifiedEditorState: VisualEditorState;
|
||||
private _modifiedOverviewRuler: editorBrowser.IOverviewRuler;
|
||||
private _modifiedOverviewRuler: editorBrowser.IOverviewRuler | null;
|
||||
|
||||
private _currentlyChangingViewZones: boolean;
|
||||
private _beginUpdateDecorationsTimeout: number;
|
||||
@@ -185,7 +185,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
private _renderSideBySide: boolean;
|
||||
private _renderIndicators: boolean;
|
||||
private _enableSplitViewResizing: boolean;
|
||||
private _strategy: IDiffEditorWidgetStyle;
|
||||
private _strategy!: IDiffEditorWidgetStyle;
|
||||
|
||||
private readonly _updateDecorationsRunner: RunOnceScheduler;
|
||||
|
||||
@@ -271,8 +271,19 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}));
|
||||
this._containerDomElement.appendChild(this._overviewDomElement);
|
||||
|
||||
this._createLeftHandSide();
|
||||
this._createRightHandSide();
|
||||
// Create left side
|
||||
this._originalDomNode = document.createElement('div');
|
||||
this._originalDomNode.className = 'editor original';
|
||||
this._originalDomNode.style.position = 'absolute';
|
||||
this._originalDomNode.style.height = '100%';
|
||||
this._containerDomElement.appendChild(this._originalDomNode);
|
||||
|
||||
// Create right side
|
||||
this._modifiedDomNode = document.createElement('div');
|
||||
this._modifiedDomNode.className = 'editor modified';
|
||||
this._modifiedDomNode.style.position = 'absolute';
|
||||
this._modifiedDomNode.style.height = '100%';
|
||||
this._containerDomElement.appendChild(this._modifiedDomNode);
|
||||
|
||||
this._beginUpdateDecorationsTimeout = -1;
|
||||
this._currentlyChangingViewZones = false;
|
||||
@@ -304,8 +315,11 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
rightServices.set(IContextKeyService, rightContextKeyService);
|
||||
const rightScopedInstantiationService = instantiationService.createChild(rightServices);
|
||||
|
||||
this._createLeftHandSideEditor(options, leftScopedInstantiationService);
|
||||
this._createRightHandSideEditor(options, rightScopedInstantiationService);
|
||||
this.originalEditor = this._createLeftHandSideEditor(options, leftScopedInstantiationService);
|
||||
this.modifiedEditor = this._createRightHandSideEditor(options, rightScopedInstantiationService);
|
||||
|
||||
this._originalOverviewRuler = null;
|
||||
this._modifiedOverviewRuler = null;
|
||||
|
||||
this._reviewPane = new DiffReview(this);
|
||||
this._containerDomElement.appendChild(this._reviewPane.domNode.domNode);
|
||||
@@ -313,7 +327,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._containerDomElement.appendChild(this._reviewPane.actionBarContainer.domNode);
|
||||
|
||||
if (options.automaticLayout) {
|
||||
this._measureDomElementToken = window.setInterval(() => this._measureDomElement(false), 100);
|
||||
this._measureDomElementToken = new IntervalTimer();
|
||||
this._measureDomElementToken.cancelAndSet(() => this._measureDomElement(false), 100);
|
||||
} else {
|
||||
this._measureDomElementToken = null;
|
||||
}
|
||||
|
||||
// enableSplitViewResizing
|
||||
@@ -393,26 +410,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._layoutOverviewRulers();
|
||||
}
|
||||
|
||||
private _createLeftHandSide(): void {
|
||||
this._originalDomNode = document.createElement('div');
|
||||
this._originalDomNode.className = 'editor original';
|
||||
this._originalDomNode.style.position = 'absolute';
|
||||
this._originalDomNode.style.height = '100%';
|
||||
this._containerDomElement.appendChild(this._originalDomNode);
|
||||
}
|
||||
private _createLeftHandSideEditor(options: editorOptions.IDiffEditorOptions, instantiationService: IInstantiationService): CodeEditorWidget {
|
||||
const editor = this._createInnerEditor(instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options, this._originalIsEditable));
|
||||
|
||||
private _createRightHandSide(): void {
|
||||
this._modifiedDomNode = document.createElement('div');
|
||||
this._modifiedDomNode.className = 'editor modified';
|
||||
this._modifiedDomNode.style.position = 'absolute';
|
||||
this._modifiedDomNode.style.height = '100%';
|
||||
this._containerDomElement.appendChild(this._modifiedDomNode);
|
||||
}
|
||||
|
||||
private _createLeftHandSideEditor(options: editorOptions.IDiffEditorOptions, instantiationService: IInstantiationService): void {
|
||||
this.originalEditor = this._createInnerEditor(instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options, this._originalIsEditable));
|
||||
|
||||
this._register(this.originalEditor.onDidScrollChange((e) => {
|
||||
this._register(editor.onDidScrollChange((e) => {
|
||||
if (this._isHandlingScrollEvent) {
|
||||
return;
|
||||
}
|
||||
@@ -429,21 +430,23 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._layoutOverviewViewport();
|
||||
}));
|
||||
|
||||
this._register(this.originalEditor.onDidChangeViewZones(() => {
|
||||
this._register(editor.onDidChangeViewZones(() => {
|
||||
this._onViewZonesChanged();
|
||||
}));
|
||||
|
||||
this._register(this.originalEditor.onDidChangeModelContent(() => {
|
||||
this._register(editor.onDidChangeModelContent(() => {
|
||||
if (this._isVisible) {
|
||||
this._beginUpdateDecorationsSoon();
|
||||
}
|
||||
}));
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
private _createRightHandSideEditor(options: editorOptions.IDiffEditorOptions, instantiationService: IInstantiationService): void {
|
||||
this.modifiedEditor = this._createInnerEditor(instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options));
|
||||
private _createRightHandSideEditor(options: editorOptions.IDiffEditorOptions, instantiationService: IInstantiationService): CodeEditorWidget {
|
||||
const editor = this._createInnerEditor(instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options));
|
||||
|
||||
this._register(this.modifiedEditor.onDidScrollChange((e) => {
|
||||
this._register(editor.onDidScrollChange((e) => {
|
||||
if (this._isHandlingScrollEvent) {
|
||||
return;
|
||||
}
|
||||
@@ -460,21 +463,23 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._layoutOverviewViewport();
|
||||
}));
|
||||
|
||||
this._register(this.modifiedEditor.onDidChangeViewZones(() => {
|
||||
this._register(editor.onDidChangeViewZones(() => {
|
||||
this._onViewZonesChanged();
|
||||
}));
|
||||
|
||||
this._register(this.modifiedEditor.onDidChangeConfiguration((e) => {
|
||||
if (e.fontInfo && this.modifiedEditor.getModel()) {
|
||||
this._register(editor.onDidChangeConfiguration((e) => {
|
||||
if (e.fontInfo && editor.getModel()) {
|
||||
this._onViewZonesChanged();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.modifiedEditor.onDidChangeModelContent(() => {
|
||||
this._register(editor.onDidChangeModelContent(() => {
|
||||
if (this._isVisible) {
|
||||
this._beginUpdateDecorationsSoon();
|
||||
}
|
||||
}));
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
protected _createInnerEditor(instantiationService: IInstantiationService, container: HTMLElement, options: editorOptions.IEditorOptions): CodeEditorWidget {
|
||||
@@ -489,7 +494,9 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._beginUpdateDecorationsTimeout = -1;
|
||||
}
|
||||
|
||||
window.clearInterval(this._measureDomElementToken);
|
||||
if (this._measureDomElementToken) {
|
||||
this._measureDomElementToken.dispose();
|
||||
}
|
||||
|
||||
this._cleanViewZonesAndDecorations();
|
||||
|
||||
@@ -825,6 +832,9 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
private _layoutOverviewRulers(): void {
|
||||
if (!this._originalOverviewRuler || !this._modifiedOverviewRuler) {
|
||||
return;
|
||||
}
|
||||
let freeSpace = DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH - 2 * DiffEditorWidget.ONE_OVERVIEW_WIDTH;
|
||||
let layoutInfo = this.modifiedEditor.getLayoutInfo();
|
||||
if (layoutInfo) {
|
||||
@@ -926,7 +936,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
private _updateDecorations(): void {
|
||||
if (!this.originalEditor.getModel() || !this.modifiedEditor.getModel()) {
|
||||
if (!this.originalEditor.getModel() || !this.modifiedEditor.getModel() || !this._originalOverviewRuler || !this._modifiedOverviewRuler) {
|
||||
return;
|
||||
}
|
||||
const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []);
|
||||
@@ -1194,12 +1204,14 @@ interface IDataSource {
|
||||
abstract class DiffEditorWidgetStyle extends Disposable implements IDiffEditorWidgetStyle {
|
||||
|
||||
_dataSource: IDataSource;
|
||||
_insertColor: Color;
|
||||
_removeColor: Color;
|
||||
_insertColor: Color | null;
|
||||
_removeColor: Color | null;
|
||||
|
||||
constructor(dataSource: IDataSource) {
|
||||
super();
|
||||
this._dataSource = dataSource;
|
||||
this._insertColor = null;
|
||||
this._removeColor = null;
|
||||
}
|
||||
|
||||
public applyColors(theme: ITheme): boolean {
|
||||
@@ -1277,6 +1289,7 @@ class ForeignViewZonesIterator {
|
||||
constructor(source: IEditorWhitespace[]) {
|
||||
this._source = source;
|
||||
this._index = -1;
|
||||
this.current = null;
|
||||
this.advance();
|
||||
}
|
||||
|
||||
@@ -1555,7 +1568,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
||||
private readonly _sash: Sash;
|
||||
private _sashRatio: number | null;
|
||||
private _sashPosition: number | null;
|
||||
private _startSashPosition: number;
|
||||
private _startSashPosition: number | null;
|
||||
|
||||
constructor(dataSource: IDataSource, enableSplitViewResizing: boolean) {
|
||||
super(dataSource);
|
||||
@@ -1563,6 +1576,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
||||
this._disableSash = (enableSplitViewResizing === false);
|
||||
this._sashRatio = null;
|
||||
this._sashPosition = null;
|
||||
this._startSashPosition = null;
|
||||
this._sash = this._register(new Sash(this._dataSource.getContainerDomNode(), this));
|
||||
|
||||
if (this._disableSash) {
|
||||
@@ -1619,7 +1633,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
||||
private onSashDrag(e: ISashEvent): void {
|
||||
let w = this._dataSource.getWidth();
|
||||
let contentWidth = w - DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH;
|
||||
let sashPosition = this.layout((this._startSashPosition + (e.currentX - e.startX)) / contentWidth);
|
||||
let sashPosition = this.layout((this._startSashPosition! + (e.currentX - e.startX)) / contentWidth);
|
||||
|
||||
this._sashRatio = sashPosition / contentWidth;
|
||||
|
||||
@@ -1654,7 +1668,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
||||
}
|
||||
|
||||
protected _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
|
||||
const overviewZoneColor = this._removeColor.toString();
|
||||
const overviewZoneColor = String(this._removeColor);
|
||||
|
||||
let result: IEditorDiffDecorations = {
|
||||
decorations: [],
|
||||
@@ -1714,7 +1728,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
||||
}
|
||||
|
||||
protected _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
|
||||
const overviewZoneColor = this._insertColor.toString();
|
||||
const overviewZoneColor = String(this._insertColor);
|
||||
|
||||
let result: IEditorDiffDecorations = {
|
||||
decorations: [],
|
||||
@@ -1834,7 +1848,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito
|
||||
}
|
||||
|
||||
protected _getOriginalEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
|
||||
const overviewZoneColor = this._removeColor.toString();
|
||||
const overviewZoneColor = String(this._removeColor);
|
||||
|
||||
let result: IEditorDiffDecorations = {
|
||||
decorations: [],
|
||||
@@ -1863,7 +1877,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito
|
||||
}
|
||||
|
||||
protected _getModifiedEditorDecorations(lineChanges: editorCommon.ILineChange[], ignoreTrimWhitespace: boolean, renderIndicators: boolean, originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorDiffDecorations {
|
||||
const overviewZoneColor = this._insertColor.toString();
|
||||
const overviewZoneColor = String(this._insertColor);
|
||||
|
||||
let result: IEditorDiffDecorations = {
|
||||
decorations: [],
|
||||
|
||||
@@ -101,12 +101,13 @@ export class ReplaceCommandThatPreservesSelection implements ICommand {
|
||||
private readonly _range: Range;
|
||||
private readonly _text: string;
|
||||
private readonly _initialSelection: Selection;
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
|
||||
constructor(editRange: Range, text: string, initialSelection: Selection) {
|
||||
this._range = editRange;
|
||||
this._text = text;
|
||||
this._initialSelection = initialSelection;
|
||||
this._selectionId = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {
|
||||
@@ -115,6 +116,6 @@ export class ReplaceCommandThatPreservesSelection implements ICommand {
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this._selectionId);
|
||||
return helper.getTrackedSelection(this._selectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,13 +70,14 @@ export class ShiftCommand implements ICommand {
|
||||
|
||||
private readonly _opts: IShiftCommandOpts;
|
||||
private readonly _selection: Selection;
|
||||
private _selectionId: string;
|
||||
private _selectionId: string | null;
|
||||
private _useLastEditRangeForCursorEndPosition: boolean;
|
||||
private _selectionStartColumnStaysPut: boolean;
|
||||
|
||||
constructor(range: Selection, opts: IShiftCommandOpts) {
|
||||
this._opts = opts;
|
||||
this._selection = range;
|
||||
this._selectionId = null;
|
||||
this._useLastEditRangeForCursorEndPosition = false;
|
||||
this._selectionStartColumnStaysPut = false;
|
||||
}
|
||||
@@ -241,7 +242,7 @@ export class ShiftCommand implements ICommand {
|
||||
let lastOp = helper.getInverseEditOperations()[0];
|
||||
return new Selection(lastOp.range.endLineNumber, lastOp.range.endColumn, lastOp.range.endLineNumber, lastOp.range.endColumn);
|
||||
}
|
||||
const result = helper.getTrackedSelection(this._selectionId);
|
||||
const result = helper.getTrackedSelection(this._selectionId!);
|
||||
|
||||
if (this._selectionStartColumnStaysPut) {
|
||||
// The selection start should not move
|
||||
|
||||
@@ -13,28 +13,29 @@ import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/mod
|
||||
|
||||
export class TrimTrailingWhitespaceCommand implements ICommand {
|
||||
|
||||
private readonly selection: Selection;
|
||||
private selectionId: string;
|
||||
private readonly cursors: Position[];
|
||||
private readonly _selection: Selection;
|
||||
private _selectionId: string | null;
|
||||
private readonly _cursors: Position[];
|
||||
|
||||
constructor(selection: Selection, cursors: Position[]) {
|
||||
this.selection = selection;
|
||||
this.cursors = cursors;
|
||||
this._selection = selection;
|
||||
this._cursors = cursors;
|
||||
this._selectionId = null;
|
||||
}
|
||||
|
||||
public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void {
|
||||
let ops = trimTrailingWhitespace(model, this.cursors);
|
||||
let ops = trimTrailingWhitespace(model, this._cursors);
|
||||
for (let i = 0, len = ops.length; i < len; i++) {
|
||||
let op = ops[i];
|
||||
|
||||
builder.addEditOperation(op.range, op.text);
|
||||
}
|
||||
|
||||
this.selectionId = builder.trackSelection(this.selection);
|
||||
this._selectionId = builder.trackSelection(this._selection);
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
return helper.getTrackedSelection(this.selectionId);
|
||||
return helper.getTrackedSelection(this._selectionId!);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed
|
||||
public readonly isSimpleWidget: boolean;
|
||||
protected _rawOptions: editorOptions.IEditorOptions;
|
||||
protected _validatedOptions: editorOptions.IValidatedEditorOptions;
|
||||
public editor: editorOptions.InternalEditorOptions;
|
||||
public editor!: editorOptions.InternalEditorOptions;
|
||||
private _isDominatedByLongLines: boolean;
|
||||
private _lineNumbersDigitCount: number;
|
||||
|
||||
@@ -268,6 +268,11 @@ const editorConfiguration: IConfigurationNode = {
|
||||
'default': 'on',
|
||||
'description': nls.localize('lineNumbers', "Controls the display of line numbers.")
|
||||
},
|
||||
'editor.cursorSurroundingLines': {
|
||||
'type': 'number',
|
||||
'default': EDITOR_DEFAULTS.viewInfo.cursorSurroundingLines,
|
||||
'description': nls.localize('cursorSurroundingLines', "Controls the minimal number of visible leading and trailing lines surrounding the cursor. Known as 'scrollOff' or `scrollOffset` in some other editors.")
|
||||
},
|
||||
'editor.renderFinalNewline': {
|
||||
'type': 'boolean',
|
||||
'default': EDITOR_DEFAULTS.viewInfo.renderFinalNewline,
|
||||
|
||||
@@ -268,6 +268,11 @@ export interface IEditorOptions {
|
||||
* Defaults to true.
|
||||
*/
|
||||
lineNumbers?: 'on' | 'off' | 'relative' | 'interval' | ((lineNumber: number) => string);
|
||||
/**
|
||||
* Controls the minimal number of visible leading and trailing lines surrounding the cursor.
|
||||
* Defaults to 0.
|
||||
*/
|
||||
cursorSurroundingLines?: number;
|
||||
/**
|
||||
* Render last line number when the file ends with a newline.
|
||||
* Defaults to true.
|
||||
@@ -988,6 +993,7 @@ export interface InternalEditorViewOptions {
|
||||
readonly ariaLabel: string;
|
||||
readonly renderLineNumbers: RenderLineNumbersType;
|
||||
readonly renderCustomLineNumbers: ((lineNumber: number) => string) | null;
|
||||
readonly cursorSurroundingLines: number;
|
||||
readonly renderFinalNewline: boolean;
|
||||
readonly selectOnLineNumbers: boolean;
|
||||
readonly glyphMargin: boolean;
|
||||
@@ -1296,6 +1302,7 @@ export class InternalEditorOptions {
|
||||
&& a.ariaLabel === b.ariaLabel
|
||||
&& a.renderLineNumbers === b.renderLineNumbers
|
||||
&& a.renderCustomLineNumbers === b.renderCustomLineNumbers
|
||||
&& a.cursorSurroundingLines === b.cursorSurroundingLines
|
||||
&& a.renderFinalNewline === b.renderFinalNewline
|
||||
&& a.selectOnLineNumbers === b.selectOnLineNumbers
|
||||
&& a.glyphMargin === b.glyphMargin
|
||||
@@ -2055,6 +2062,7 @@ export class EditorOptionsValidator {
|
||||
disableMonospaceOptimizations: disableMonospaceOptimizations,
|
||||
rulers: rulers,
|
||||
ariaLabel: _string(opts.ariaLabel, defaults.ariaLabel),
|
||||
cursorSurroundingLines: _clampedInt(opts.cursorSurroundingLines, defaults.cursorWidth, 0, Number.MAX_VALUE),
|
||||
renderLineNumbers: renderLineNumbers,
|
||||
renderCustomLineNumbers: renderCustomLineNumbers,
|
||||
renderFinalNewline: _boolean(opts.renderFinalNewline, defaults.renderFinalNewline),
|
||||
@@ -2178,6 +2186,7 @@ export class InternalEditorOptionsFactory {
|
||||
ariaLabel: (accessibilityIsOff ? nls.localize('accessibilityOffAriaLabel', "The editor is not accessible at this time. Press Alt+F1 for options.") : opts.viewInfo.ariaLabel),
|
||||
renderLineNumbers: opts.viewInfo.renderLineNumbers,
|
||||
renderCustomLineNumbers: opts.viewInfo.renderCustomLineNumbers,
|
||||
cursorSurroundingLines: opts.viewInfo.cursorSurroundingLines,
|
||||
renderFinalNewline: opts.viewInfo.renderFinalNewline,
|
||||
selectOnLineNumbers: opts.viewInfo.selectOnLineNumbers,
|
||||
glyphMargin: opts.viewInfo.glyphMargin,
|
||||
@@ -2197,7 +2206,7 @@ export class InternalEditorOptionsFactory {
|
||||
stopRenderingLineAfter: opts.viewInfo.stopRenderingLineAfter,
|
||||
renderWhitespace: (accessibilityIsOn ? 'none' : opts.viewInfo.renderWhitespace), // DISABLED WHEN SCREEN READER IS ATTACHED
|
||||
renderControlCharacters: (accessibilityIsOn ? false : opts.viewInfo.renderControlCharacters), // DISABLED WHEN SCREEN READER IS ATTACHED
|
||||
fontLigatures: (accessibilityIsOn ? false : opts.viewInfo.fontLigatures), // DISABLED WHEN SCREEN READER IS ATTACHED
|
||||
fontLigatures: opts.viewInfo.fontLigatures,
|
||||
renderIndentGuides: (accessibilityIsOn ? false : opts.viewInfo.renderIndentGuides), // DISABLED WHEN SCREEN READER IS ATTACHED
|
||||
highlightActiveIndentGuide: opts.viewInfo.highlightActiveIndentGuide,
|
||||
renderLineHighlight: opts.viewInfo.renderLineHighlight,
|
||||
@@ -2644,6 +2653,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
|
||||
ariaLabel: nls.localize('editorViewAccessibleLabel', "Editor content"),
|
||||
renderLineNumbers: RenderLineNumbersType.On,
|
||||
renderCustomLineNumbers: null,
|
||||
cursorSurroundingLines: 0,
|
||||
renderFinalNewline: true,
|
||||
selectOnLineNumbers: true,
|
||||
glyphMargin: true,
|
||||
|
||||
@@ -437,8 +437,6 @@ export class TypeOperations {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isEqualPair = (ch === config.autoClosingPairsClose[ch]);
|
||||
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
|
||||
@@ -454,14 +452,6 @@ export class TypeOperations {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isEqualPair) {
|
||||
const lineTextBeforeCursor = lineText.substr(0, position.column - 1);
|
||||
const chCntBefore = this._countNeedlesInHaystack(lineTextBeforeCursor, ch);
|
||||
if (chCntBefore % 2 === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Must over-type a closing character typed by the editor
|
||||
let found = false;
|
||||
for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
|
||||
@@ -947,6 +937,7 @@ export class TypeWithAutoClosingCommand extends ReplaceCommandWithOffsetCursorSt
|
||||
super(selection, openCharacter + closeCharacter, 0, -closeCharacter.length);
|
||||
this._closeCharacter = closeCharacter;
|
||||
this.closeCharacterRange = null;
|
||||
this.enclosingRange = null;
|
||||
}
|
||||
|
||||
public computeCursorState(model: ITextModel, helper: ICursorStateComputerData): Selection {
|
||||
|
||||
@@ -11,8 +11,8 @@ import { TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
|
||||
export class OneCursor {
|
||||
|
||||
public modelState: SingleCursorState;
|
||||
public viewState: SingleCursorState;
|
||||
public modelState!: SingleCursorState;
|
||||
public viewState!: SingleCursorState;
|
||||
|
||||
private _selTrackedRange: string | null;
|
||||
private _trackSelection: boolean;
|
||||
|
||||
@@ -328,6 +328,8 @@ export class DiffComputer {
|
||||
this.modifiedLines = modifiedLines;
|
||||
this.original = new LineMarkerSequence(originalLines);
|
||||
this.modified = new LineMarkerSequence(modifiedLines);
|
||||
|
||||
this.computationStartTime = (new Date()).getTime();
|
||||
}
|
||||
|
||||
public computeDiff(): ILineChange[] {
|
||||
|
||||
@@ -7,8 +7,8 @@ import { CharCode } from 'vs/base/common/charCode';
|
||||
import { ITextBuffer } from 'vs/editor/common/model';
|
||||
|
||||
class SpacesDiffResult {
|
||||
public spacesDiff: number;
|
||||
public looksLikeAlignment: boolean;
|
||||
public spacesDiff: number = 0;
|
||||
public looksLikeAlignment: boolean = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,8 +158,19 @@ export function guessIndentation(source: ITextBuffer, defaultTabSize: number, de
|
||||
spacesDiff(previousLineText, previousLineIndentation, currentLineText, currentLineIndentation, tmp);
|
||||
|
||||
if (tmp.looksLikeAlignment) {
|
||||
// skip this line entirely
|
||||
continue;
|
||||
// if defaultInsertSpaces === true && the spaces count == tabSize, we may want to count it as valid indentation
|
||||
//
|
||||
// - item1
|
||||
// - item2
|
||||
//
|
||||
// otherwise skip this line entirely
|
||||
//
|
||||
// const a = 1,
|
||||
// b = 2;
|
||||
|
||||
if (!(defaultInsertSpaces && defaultTabSize === tmp.spacesDiff)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let currentSpacesDiff = tmp.spacesDiff;
|
||||
|
||||
@@ -265,16 +265,16 @@ class PieceTreeSearchCache {
|
||||
}
|
||||
|
||||
export class PieceTreeBase {
|
||||
root: TreeNode;
|
||||
protected _buffers: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.
|
||||
protected _lineCnt: number;
|
||||
protected _length: number;
|
||||
protected _EOL: string;
|
||||
protected _EOLLength: number;
|
||||
protected _EOLNormalized: boolean;
|
||||
private _lastChangeBufferPos: BufferCursor;
|
||||
private _searchCache: PieceTreeSearchCache;
|
||||
private _lastVisitedLine: { lineNumber: number; value: string; };
|
||||
root!: TreeNode;
|
||||
protected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer.
|
||||
protected _lineCnt!: number;
|
||||
protected _length!: number;
|
||||
protected _EOL!: string;
|
||||
protected _EOLLength!: number;
|
||||
protected _EOLNormalized!: boolean;
|
||||
private _lastChangeBufferPos!: BufferCursor;
|
||||
private _searchCache!: PieceTreeSearchCache;
|
||||
private _lastVisitedLine!: { lineNumber: number; value: string; };
|
||||
|
||||
constructor(chunks: StringBuffer[], eol: '\r\n' | '\n', eolNormalized: boolean) {
|
||||
this.create(chunks, eol, eolNormalized);
|
||||
|
||||
@@ -329,7 +329,9 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
this._isTooLargeForSyncing = (bufferTextLength > TextModel.MODEL_SYNC_LIMIT);
|
||||
|
||||
this._setVersionId(1);
|
||||
this._versionId = 1;
|
||||
this._alternativeVersionId = 1;
|
||||
|
||||
this._isDisposed = false;
|
||||
this._isDisposing = false;
|
||||
|
||||
@@ -693,11 +695,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
|
||||
private _increaseVersionId(): void {
|
||||
this._setVersionId(this._versionId + 1);
|
||||
}
|
||||
|
||||
private _setVersionId(newVersionId: number): void {
|
||||
this._versionId = newVersionId;
|
||||
this._versionId = this._versionId + 1;
|
||||
this._alternativeVersionId = this._versionId;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ export class TokenizationStateStore {
|
||||
private _invalidLineStartIndex: number;
|
||||
|
||||
constructor() {
|
||||
this._reset(null);
|
||||
this._beginState = [];
|
||||
this._valid = [];
|
||||
this._len = 0;
|
||||
this._invalidLineStartIndex = 0;
|
||||
}
|
||||
|
||||
private _reset(initialState: IState | null): void {
|
||||
|
||||
@@ -1288,7 +1288,7 @@ export interface CommentThread {
|
||||
threadId: string;
|
||||
resource: string | null;
|
||||
range: IRange;
|
||||
label: string;
|
||||
label: string | undefined;
|
||||
contextValue: string | undefined;
|
||||
comments: Comment[] | undefined;
|
||||
onDidChangeComments: Event<Comment[] | undefined>;
|
||||
@@ -1296,7 +1296,7 @@ export interface CommentThread {
|
||||
input?: CommentInput;
|
||||
onDidChangeInput: Event<CommentInput | undefined>;
|
||||
onDidChangeRange: Event<IRange>;
|
||||
onDidChangeLabel: Event<string>;
|
||||
onDidChangeLabel: Event<string | undefined>;
|
||||
onDidChangeCollasibleState: Event<CommentThreadCollapsibleState | undefined>;
|
||||
isDisposed: boolean;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ export class RichEditSupport {
|
||||
public readonly characterPair: CharacterPairSupport;
|
||||
public readonly wordDefinition: RegExp;
|
||||
public readonly onEnter: OnEnterSupport | null;
|
||||
public readonly indentRulesSupport: IndentRulesSupport;
|
||||
public readonly indentRulesSupport: IndentRulesSupport | null;
|
||||
public readonly indentationRules: IndentationRule | undefined;
|
||||
public readonly foldingRules: FoldingRules;
|
||||
|
||||
@@ -81,6 +81,8 @@ export class RichEditSupport {
|
||||
this.indentationRules = this._conf.indentationRules;
|
||||
if (this._conf.indentationRules) {
|
||||
this.indentRulesSupport = new IndentRulesSupport(this._conf.indentationRules);
|
||||
} else {
|
||||
this.indentRulesSupport = null;
|
||||
}
|
||||
|
||||
this.foldingRules = this._conf.folding || {};
|
||||
@@ -170,7 +172,9 @@ export class RichEditSupport {
|
||||
}
|
||||
|
||||
export class LanguageConfigurationChangeEvent {
|
||||
languageIdentifier: LanguageIdentifier;
|
||||
constructor(
|
||||
public readonly languageIdentifier: LanguageIdentifier
|
||||
) { }
|
||||
}
|
||||
|
||||
export class LanguageConfigurationRegistryImpl {
|
||||
@@ -184,11 +188,11 @@ export class LanguageConfigurationRegistryImpl {
|
||||
let previous = this._getRichEditSupport(languageIdentifier.id);
|
||||
let current = new RichEditSupport(languageIdentifier, previous, configuration);
|
||||
this._entries.set(languageIdentifier.id, current);
|
||||
this._onDidChange.fire({ languageIdentifier });
|
||||
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
|
||||
return toDisposable(() => {
|
||||
if (this._entries.get(languageIdentifier.id) === current) {
|
||||
this._entries.set(languageIdentifier.id, previous);
|
||||
this._onDidChange.fire({ languageIdentifier });
|
||||
this._onDidChange.fire(new LanguageConfigurationChangeEvent(languageIdentifier));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
|
||||
partContent += '​';
|
||||
break;
|
||||
|
||||
case CharCode.Space:
|
||||
partContent += ' ';
|
||||
break;
|
||||
|
||||
default:
|
||||
partContent += String.fromCharCode(charCode);
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ class WorkerManager extends Disposable {
|
||||
super();
|
||||
this._modelService = modelService;
|
||||
this._editorWorkerClient = null;
|
||||
this._lastWorkerUsedTime = (new Date()).getTime();
|
||||
|
||||
let stopWorkerInterval = this._register(new IntervalTimer());
|
||||
stopWorkerInterval.cancelAndSet(() => this._checkStopIdleWorker(), Math.round(STOP_WORKER_DELTA_TIME_MS / 2));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user