mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Revert "Revert "Merge from vscode ada4bddb8edc69eea6ebaaa0e88c5f903cbd43d8 (#5529)" (#5553)" (#5562)
This reverts commit c9a4f8f664.
This commit is contained in:
@@ -45,13 +45,13 @@ class WindowManager {
|
||||
|
||||
// --- Pixel Ratio
|
||||
public getPixelRatio(): number {
|
||||
let ctx = document.createElement('canvas').getContext('2d');
|
||||
let ctx: any = document.createElement('canvas').getContext('2d');
|
||||
let dpr = window.devicePixelRatio || 1;
|
||||
let bsr = (<any>ctx).webkitBackingStorePixelRatio ||
|
||||
(<any>ctx).mozBackingStorePixelRatio ||
|
||||
(<any>ctx).msBackingStorePixelRatio ||
|
||||
(<any>ctx).oBackingStorePixelRatio ||
|
||||
(<any>ctx).backingStorePixelRatio || 1;
|
||||
let bsr = ctx.webkitBackingStorePixelRatio ||
|
||||
ctx.mozBackingStorePixelRatio ||
|
||||
ctx.msBackingStorePixelRatio ||
|
||||
ctx.oBackingStorePixelRatio ||
|
||||
ctx.backingStorePixelRatio || 1;
|
||||
return dpr / bsr;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { SubmenuAction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
@@ -25,7 +25,7 @@ export class ContextSubMenu extends SubmenuAction {
|
||||
export interface IContextMenuDelegate {
|
||||
getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; };
|
||||
getActions(): Array<IAction | ContextSubMenu>;
|
||||
getActionItem?(action: IAction): IActionItem | undefined;
|
||||
getActionViewItem?(action: IAction): IActionViewItem | undefined;
|
||||
getActionsContext?(event?: IContextMenuEvent): any;
|
||||
getKeyBinding?(action: IAction): ResolvedKeybinding | undefined;
|
||||
getMenuClassName?(): string;
|
||||
|
||||
@@ -329,7 +329,7 @@ function parseFormattedText(content: string): IFormatParseTree {
|
||||
children: []
|
||||
};
|
||||
|
||||
let actionItemIndex = 0;
|
||||
let actionViewItemIndex = 0;
|
||||
let current = root;
|
||||
const stack: IFormatParseTree[] = [];
|
||||
const stream = new StringStream(content);
|
||||
@@ -359,8 +359,8 @@ function parseFormattedText(content: string): IFormatParseTree {
|
||||
};
|
||||
|
||||
if (type === FormatType.Action) {
|
||||
newCurrent.index = actionItemIndex;
|
||||
actionItemIndex++;
|
||||
newCurrent.index = actionViewItemIndex;
|
||||
actionViewItemIndex++;
|
||||
}
|
||||
|
||||
current.children!.push(newCurrent);
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
|
||||
export interface IActionItem {
|
||||
export interface IActionViewItem {
|
||||
actionRunner: IActionRunner;
|
||||
setActionContext(context: any): void;
|
||||
render(element: HTMLElement): void;
|
||||
@@ -28,12 +28,12 @@ export interface IActionItem {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export interface IBaseActionItemOptions {
|
||||
export interface IBaseActionViewItemOptions {
|
||||
draggable?: boolean;
|
||||
isMenu?: boolean;
|
||||
}
|
||||
|
||||
export class BaseActionItem extends Disposable implements IActionItem {
|
||||
export class BaseActionViewItem extends Disposable implements IActionViewItem {
|
||||
|
||||
element?: HTMLElement;
|
||||
_context: any;
|
||||
@@ -41,7 +41,7 @@ export class BaseActionItem extends Disposable implements IActionItem {
|
||||
|
||||
private _actionRunner: IActionRunner;
|
||||
|
||||
constructor(context: any, action: IAction, protected options?: IBaseActionItemOptions) {
|
||||
constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) {
|
||||
super();
|
||||
|
||||
this._context = context || this;
|
||||
@@ -226,20 +226,20 @@ export class Separator extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IActionItemOptions extends IBaseActionItemOptions {
|
||||
export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
|
||||
icon?: boolean;
|
||||
label?: boolean;
|
||||
keybinding?: string | null;
|
||||
}
|
||||
|
||||
export class ActionItem extends BaseActionItem {
|
||||
export class ActionViewItem extends BaseActionViewItem {
|
||||
|
||||
protected label: HTMLElement;
|
||||
protected options: IActionItemOptions;
|
||||
protected options: IActionViewItemOptions;
|
||||
|
||||
private cssClass?: string;
|
||||
|
||||
constructor(context: any, action: IAction, options: IActionItemOptions = {}) {
|
||||
constructor(context: any, action: IAction, options: IActionViewItemOptions = {}) {
|
||||
super(context, action, options);
|
||||
|
||||
this.options = options;
|
||||
@@ -363,14 +363,14 @@ export interface ActionTrigger {
|
||||
keyDown: boolean;
|
||||
}
|
||||
|
||||
export interface IActionItemProvider {
|
||||
(action: IAction): IActionItem | undefined;
|
||||
export interface IActionViewItemProvider {
|
||||
(action: IAction): IActionViewItem | undefined;
|
||||
}
|
||||
|
||||
export interface IActionBarOptions {
|
||||
orientation?: ActionsOrientation;
|
||||
context?: any;
|
||||
actionItemProvider?: IActionItemProvider;
|
||||
actionViewItemProvider?: IActionViewItemProvider;
|
||||
actionRunner?: IActionRunner;
|
||||
ariaLabel?: string;
|
||||
animated?: boolean;
|
||||
@@ -386,7 +386,7 @@ const defaultOptions: IActionBarOptions = {
|
||||
}
|
||||
};
|
||||
|
||||
export interface IActionOptions extends IActionItemOptions {
|
||||
export interface IActionOptions extends IActionViewItemOptions {
|
||||
index?: number;
|
||||
}
|
||||
|
||||
@@ -397,8 +397,8 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
private _actionRunner: IActionRunner;
|
||||
private _context: any;
|
||||
|
||||
// Items
|
||||
items: IActionItem[];
|
||||
// View Items
|
||||
viewItems: IActionViewItem[];
|
||||
protected focusedItem?: number;
|
||||
private focusTracker: DOM.IFocusTracker;
|
||||
|
||||
@@ -438,7 +438,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
this._register(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
|
||||
this._register(this._actionRunner.onDidBeforeRun(e => this._onDidBeforeRun.fire(e)));
|
||||
|
||||
this.items = [];
|
||||
this.viewItems = [];
|
||||
this.focusedItem = undefined;
|
||||
|
||||
this.domNode = document.createElement('div');
|
||||
@@ -575,7 +575,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
set context(context: any) {
|
||||
this._context = context;
|
||||
this.items.forEach(i => i.setActionContext(context));
|
||||
this.viewItems.forEach(i => i.setActionContext(context));
|
||||
}
|
||||
|
||||
get actionRunner(): IActionRunner {
|
||||
@@ -585,7 +585,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
set actionRunner(actionRunner: IActionRunner) {
|
||||
if (actionRunner) {
|
||||
this._actionRunner = actionRunner;
|
||||
this.items.forEach(item => item.actionRunner = actionRunner);
|
||||
this.viewItems.forEach(item => item.actionRunner = actionRunner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,36 +599,36 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
let index = types.isNumber(options.index) ? options.index : null;
|
||||
|
||||
actions.forEach((action: IAction) => {
|
||||
const actionItemElement = document.createElement('li');
|
||||
actionItemElement.className = 'action-item';
|
||||
actionItemElement.setAttribute('role', 'presentation');
|
||||
const actionViewItemElement = document.createElement('li');
|
||||
actionViewItemElement.className = 'action-item';
|
||||
actionViewItemElement.setAttribute('role', 'presentation');
|
||||
|
||||
// Prevent native context menu on actions
|
||||
this._register(DOM.addDisposableListener(actionItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => {
|
||||
this._register(DOM.addDisposableListener(actionViewItemElement, DOM.EventType.CONTEXT_MENU, (e: DOM.EventLike) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}));
|
||||
|
||||
let item: IActionItem | undefined;
|
||||
let item: IActionViewItem | undefined;
|
||||
|
||||
if (this.options.actionItemProvider) {
|
||||
item = this.options.actionItemProvider(action);
|
||||
if (this.options.actionViewItemProvider) {
|
||||
item = this.options.actionViewItemProvider(action);
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
item = new ActionItem(this.context, action, options);
|
||||
item = new ActionViewItem(this.context, action, options);
|
||||
}
|
||||
|
||||
item.actionRunner = this._actionRunner;
|
||||
item.setActionContext(this.context);
|
||||
item.render(actionItemElement);
|
||||
item.render(actionViewItemElement);
|
||||
|
||||
if (index === null || index < 0 || index >= this.actionsList.children.length) {
|
||||
this.actionsList.appendChild(actionItemElement);
|
||||
this.items.push(item);
|
||||
this.actionsList.appendChild(actionViewItemElement);
|
||||
this.viewItems.push(item);
|
||||
} else {
|
||||
this.actionsList.insertBefore(actionItemElement, this.actionsList.children[index]);
|
||||
this.items.splice(index, 0, item);
|
||||
this.actionsList.insertBefore(actionViewItemElement, this.actionsList.children[index]);
|
||||
this.viewItems.splice(index, 0, item);
|
||||
index++;
|
||||
}
|
||||
});
|
||||
@@ -657,23 +657,23 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
pull(index: number): void {
|
||||
if (index >= 0 && index < this.items.length) {
|
||||
if (index >= 0 && index < this.viewItems.length) {
|
||||
this.actionsList.removeChild(this.actionsList.childNodes[index]);
|
||||
dispose(this.items.splice(index, 1));
|
||||
dispose(this.viewItems.splice(index, 1));
|
||||
}
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.items = dispose(this.items);
|
||||
this.viewItems = dispose(this.viewItems);
|
||||
DOM.clearNode(this.actionsList);
|
||||
}
|
||||
|
||||
length(): number {
|
||||
return this.items.length;
|
||||
return this.viewItems.length;
|
||||
}
|
||||
|
||||
isEmpty(): boolean {
|
||||
return this.items.length === 0;
|
||||
return this.viewItems.length === 0;
|
||||
}
|
||||
|
||||
focus(index?: number): void;
|
||||
@@ -691,7 +691,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
if (selectFirst && typeof this.focusedItem === 'undefined') {
|
||||
// Focus the first enabled item
|
||||
this.focusedItem = this.items.length - 1;
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
this.focusNext();
|
||||
} else {
|
||||
if (index !== undefined) {
|
||||
@@ -704,15 +704,15 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
protected focusNext(): void {
|
||||
if (typeof this.focusedItem === 'undefined') {
|
||||
this.focusedItem = this.items.length - 1;
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
}
|
||||
|
||||
const startIndex = this.focusedItem;
|
||||
let item: IActionItem;
|
||||
let item: IActionViewItem;
|
||||
|
||||
do {
|
||||
this.focusedItem = (this.focusedItem + 1) % this.items.length;
|
||||
item = this.items[this.focusedItem];
|
||||
this.focusedItem = (this.focusedItem + 1) % this.viewItems.length;
|
||||
item = this.viewItems[this.focusedItem];
|
||||
} while (this.focusedItem !== startIndex && !item.isEnabled());
|
||||
|
||||
if (this.focusedItem === startIndex && !item.isEnabled()) {
|
||||
@@ -728,16 +728,16 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
const startIndex = this.focusedItem;
|
||||
let item: IActionItem;
|
||||
let item: IActionViewItem;
|
||||
|
||||
do {
|
||||
this.focusedItem = this.focusedItem - 1;
|
||||
|
||||
if (this.focusedItem < 0) {
|
||||
this.focusedItem = this.items.length - 1;
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
}
|
||||
|
||||
item = this.items[this.focusedItem];
|
||||
item = this.viewItems[this.focusedItem];
|
||||
} while (this.focusedItem !== startIndex && !item.isEnabled());
|
||||
|
||||
if (this.focusedItem === startIndex && !item.isEnabled()) {
|
||||
@@ -752,21 +752,21 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
this.actionsList.focus();
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.items.length; i++) {
|
||||
const item = this.items[i];
|
||||
const actionItem = item;
|
||||
for (let i = 0; i < this.viewItems.length; i++) {
|
||||
const item = this.viewItems[i];
|
||||
const actionViewItem = item;
|
||||
|
||||
if (i === this.focusedItem) {
|
||||
if (types.isFunction(actionItem.isEnabled)) {
|
||||
if (actionItem.isEnabled() && types.isFunction(actionItem.focus)) {
|
||||
actionItem.focus(fromRight);
|
||||
if (types.isFunction(actionViewItem.isEnabled)) {
|
||||
if (actionViewItem.isEnabled() && types.isFunction(actionViewItem.focus)) {
|
||||
actionViewItem.focus(fromRight);
|
||||
} else {
|
||||
this.actionsList.focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (types.isFunction(actionItem.blur)) {
|
||||
actionItem.blur();
|
||||
if (types.isFunction(actionViewItem.blur)) {
|
||||
actionViewItem.blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,16 +778,16 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
// trigger action
|
||||
const actionItem = this.items[this.focusedItem];
|
||||
if (actionItem instanceof BaseActionItem) {
|
||||
const context = (actionItem._context === null || actionItem._context === undefined) ? event : actionItem._context;
|
||||
this.run(actionItem._action, context);
|
||||
const actionViewItem = this.viewItems[this.focusedItem];
|
||||
if (actionViewItem instanceof BaseActionViewItem) {
|
||||
const context = (actionViewItem._context === null || actionViewItem._context === undefined) ? event : actionViewItem._context;
|
||||
this.run(actionViewItem._action, context);
|
||||
}
|
||||
}
|
||||
|
||||
private cancel(): void {
|
||||
if (document.activeElement instanceof HTMLElement) {
|
||||
(<HTMLElement>document.activeElement).blur(); // remove focus from focused action
|
||||
document.activeElement.blur(); // remove focus from focused action
|
||||
}
|
||||
|
||||
this._onDidCancel.fire();
|
||||
@@ -798,8 +798,8 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this.items);
|
||||
this.items = [];
|
||||
dispose(this.viewItems);
|
||||
this.viewItems = [];
|
||||
|
||||
DOM.removeNode(this.getContainer());
|
||||
|
||||
@@ -807,7 +807,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectActionItem extends BaseActionItem {
|
||||
export class SelectActionViewItem extends BaseActionViewItem {
|
||||
protected selectBox: SelectBox;
|
||||
|
||||
constructor(ctx: any, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface ICheckboxOpts extends ICheckboxStyles {
|
||||
@@ -28,7 +28,7 @@ const defaultOpts = {
|
||||
inputActiveOptionBorder: Color.fromHex('#007ACC')
|
||||
};
|
||||
|
||||
export class CheckboxActionItem extends BaseActionItem {
|
||||
export class CheckboxActionViewItem extends BaseActionViewItem {
|
||||
|
||||
private checkbox: Checkbox;
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
@@ -132,13 +132,13 @@ export class ContextView extends Disposable {
|
||||
|
||||
ContextView.BUBBLE_UP_EVENTS.forEach(event => {
|
||||
toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => {
|
||||
this.onDOMEvent(e, <HTMLElement>document.activeElement, false);
|
||||
this.onDOMEvent(e, false);
|
||||
}));
|
||||
});
|
||||
|
||||
ContextView.BUBBLE_DOWN_EVENTS.forEach(event => {
|
||||
toDisposeOnSetContainer.push(DOM.addStandardDisposableListener(this.container!, event, (e: Event) => {
|
||||
this.onDOMEvent(e, <HTMLElement>document.activeElement, true);
|
||||
this.onDOMEvent(e, true);
|
||||
}, true));
|
||||
});
|
||||
|
||||
@@ -213,13 +213,11 @@ export class ContextView extends Disposable {
|
||||
height: elementPosition.height
|
||||
};
|
||||
} else {
|
||||
let realAnchor = <IAnchor>anchor;
|
||||
|
||||
around = {
|
||||
top: realAnchor.y,
|
||||
left: realAnchor.x,
|
||||
width: realAnchor.width || 1,
|
||||
height: realAnchor.height || 2
|
||||
top: anchor.y,
|
||||
left: anchor.x,
|
||||
width: anchor.width || 1,
|
||||
height: anchor.height || 2
|
||||
};
|
||||
}
|
||||
|
||||
@@ -278,7 +276,7 @@ export class ContextView extends Disposable {
|
||||
return !!this.delegate;
|
||||
}
|
||||
|
||||
private onDOMEvent(e: Event, element: HTMLElement, onCapture: boolean): void {
|
||||
private onDOMEvent(e: Event, onCapture: boolean): void {
|
||||
if (this.delegate) {
|
||||
if (this.delegate.onDOMEvent) {
|
||||
this.delegate.onDOMEvent(e, <HTMLElement>document.activeElement);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./dropdown';
|
||||
import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch';
|
||||
import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { BaseActionViewItem, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextViewProvider, IAnchor, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IMenuOptions } from 'vs/base/browser/ui/menu/menu';
|
||||
@@ -247,7 +247,7 @@ export class DropdownMenu extends BaseDropdown {
|
||||
getAnchor: () => this.element,
|
||||
getActions: () => this.actions,
|
||||
getActionsContext: () => this.menuOptions ? this.menuOptions.context : null,
|
||||
getActionItem: action => this.menuOptions && this.menuOptions.actionItemProvider ? this.menuOptions.actionItemProvider(action) : undefined,
|
||||
getActionViewItem: action => this.menuOptions && this.menuOptions.actionViewItemProvider ? this.menuOptions.actionViewItemProvider(action) : undefined,
|
||||
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : undefined,
|
||||
getMenuClassName: () => this.menuClassName,
|
||||
onHide: () => this.onHide(),
|
||||
@@ -266,23 +266,23 @@ export class DropdownMenu extends BaseDropdown {
|
||||
}
|
||||
}
|
||||
|
||||
export class DropdownMenuActionItem extends BaseActionItem {
|
||||
export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
private menuActionsOrProvider: any;
|
||||
private dropdownMenu: DropdownMenu;
|
||||
private contextMenuProvider: IContextMenuProvider;
|
||||
private actionItemProvider?: IActionItemProvider;
|
||||
private actionViewItemProvider?: IActionViewItemProvider;
|
||||
private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
private clazz: string | undefined;
|
||||
private anchorAlignmentProvider: (() => AnchorAlignment) | undefined;
|
||||
|
||||
constructor(action: IAction, menuActions: IAction[], contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
|
||||
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
|
||||
constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) {
|
||||
constructor(action: IAction, menuActions: 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) {
|
||||
super(null, action);
|
||||
|
||||
this.menuActionsOrProvider = menuActionsOrProvider;
|
||||
this.contextMenuProvider = contextMenuProvider;
|
||||
this.actionItemProvider = actionItemProvider;
|
||||
this.actionViewItemProvider = actionViewItemProvider;
|
||||
this.actionRunner = actionRunner;
|
||||
this.keybindings = keybindings;
|
||||
this.clazz = clazz;
|
||||
@@ -319,7 +319,7 @@ export class DropdownMenuActionItem extends BaseActionItem {
|
||||
this.dropdownMenu = this._register(new DropdownMenu(container, options));
|
||||
|
||||
this.dropdownMenu.menuOptions = {
|
||||
actionItemProvider: this.actionItemProvider,
|
||||
actionViewItemProvider: this.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
getKeyBinding: this.keybindings,
|
||||
context: this._context
|
||||
|
||||
@@ -161,7 +161,7 @@ export class InputBox extends Widget {
|
||||
let tagName = this.options.flexibleHeight ? 'textarea' : 'input';
|
||||
|
||||
let wrapper = dom.append(this.element, $('.wrapper'));
|
||||
this.input = <HTMLInputElement>dom.append(wrapper, $(tagName + '.input'));
|
||||
this.input = dom.append(wrapper, $(tagName + '.input'));
|
||||
this.input.setAttribute('autocorrect', 'off');
|
||||
this.input.setAttribute('autocapitalize', 'off');
|
||||
this.input.setAttribute('spellcheck', 'false');
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'vs/css!./menu';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IActionRunner, IAction, Action } from 'vs/base/common/actions';
|
||||
import { ActionBar, IActionItemProvider, ActionsOrientation, Separator, ActionItem, IActionItemOptions, BaseActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar, IActionViewItemProvider, ActionsOrientation, Separator, ActionViewItem, IActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses } from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -39,7 +39,7 @@ export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = createMenuEscapedMnemonicRegE
|
||||
|
||||
export interface IMenuOptions {
|
||||
context?: any;
|
||||
actionItemProvider?: IActionItemProvider;
|
||||
actionViewItemProvider?: IActionViewItemProvider;
|
||||
actionRunner?: IActionRunner;
|
||||
getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
ariaLabel?: string;
|
||||
@@ -70,7 +70,7 @@ interface ISubMenuData {
|
||||
}
|
||||
|
||||
export class Menu extends ActionBar {
|
||||
private mnemonics: Map<string, Array<MenuActionItem>>;
|
||||
private mnemonics: Map<string, Array<BaseMenuActionViewItem>>;
|
||||
private menuDisposables: IDisposable[];
|
||||
private scrollableElement: DomScrollableElement;
|
||||
private menuElement: HTMLElement;
|
||||
@@ -88,7 +88,7 @@ export class Menu extends ActionBar {
|
||||
|
||||
super(menuElement, {
|
||||
orientation: ActionsOrientation.VERTICAL,
|
||||
actionItemProvider: action => this.doGetActionItem(action, options, parentData),
|
||||
actionViewItemProvider: action => this.doGetActionViewItem(action, options, parentData),
|
||||
context: options.context,
|
||||
actionRunner: options.actionRunner,
|
||||
ariaLabel: options.ariaLabel,
|
||||
@@ -113,7 +113,7 @@ export class Menu extends ActionBar {
|
||||
const actions = this.mnemonics.get(key)!;
|
||||
|
||||
if (actions.length === 1) {
|
||||
if (actions[0] instanceof SubmenuActionItem) {
|
||||
if (actions[0] instanceof SubmenuMenuActionViewItem) {
|
||||
this.focusItemByElement(actions[0].container);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ export class Menu extends ActionBar {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
|
||||
if (event.equals(KeyCode.Home) || event.equals(KeyCode.PageUp)) {
|
||||
this.focusedItem = this.items.length - 1;
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
this.focusNext();
|
||||
EventHelper.stop(e, true);
|
||||
} else if (event.equals(KeyCode.End) || event.equals(KeyCode.PageDown)) {
|
||||
@@ -189,7 +189,7 @@ export class Menu extends ActionBar {
|
||||
parent: this
|
||||
};
|
||||
|
||||
this.mnemonics = new Map<string, Array<MenuActionItem>>();
|
||||
this.mnemonics = new Map<string, Array<BaseMenuActionViewItem>>();
|
||||
|
||||
this.push(actions, { icon: true, label: true, isMenu: true });
|
||||
|
||||
@@ -223,7 +223,7 @@ export class Menu extends ActionBar {
|
||||
container.appendChild(this.scrollableElement.getDomNode());
|
||||
this.scrollableElement.scanDomNode();
|
||||
|
||||
this.items.filter(item => !(item instanceof MenuSeparatorActionItem)).forEach((item: MenuActionItem, index: number, array: any[]) => {
|
||||
this.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item: BaseMenuActionViewItem, index: number, array: any[]) => {
|
||||
item.updatePositionInSet(index + 1, array.length);
|
||||
});
|
||||
}
|
||||
@@ -241,9 +241,9 @@ export class Menu extends ActionBar {
|
||||
this.domNode.style.backgroundColor = bgColor;
|
||||
container.style.boxShadow = shadow;
|
||||
|
||||
if (this.items) {
|
||||
this.items.forEach(item => {
|
||||
if (item instanceof MenuActionItem || item instanceof MenuSeparatorActionItem) {
|
||||
if (this.viewItems) {
|
||||
this.viewItems.forEach(item => {
|
||||
if (item instanceof BaseMenuActionViewItem || item instanceof MenuSeparatorActionViewItem) {
|
||||
item.style(style);
|
||||
}
|
||||
});
|
||||
@@ -263,12 +263,12 @@ export class Menu extends ActionBar {
|
||||
}
|
||||
|
||||
trigger(index: number): void {
|
||||
if (index <= this.items.length && index >= 0) {
|
||||
const item = this.items[index];
|
||||
if (item instanceof SubmenuActionItem) {
|
||||
if (index <= this.viewItems.length && index >= 0) {
|
||||
const item = this.viewItems[index];
|
||||
if (item instanceof SubmenuMenuActionViewItem) {
|
||||
super.focus(index);
|
||||
item.open(true);
|
||||
} else if (item instanceof MenuActionItem) {
|
||||
} else if (item instanceof BaseMenuActionViewItem) {
|
||||
super.run(item._action, item._context);
|
||||
} else {
|
||||
return;
|
||||
@@ -295,27 +295,27 @@ export class Menu extends ActionBar {
|
||||
}
|
||||
}
|
||||
|
||||
private doGetActionItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionItem {
|
||||
private doGetActionViewItem(action: IAction, options: IMenuOptions, parentData: ISubMenuData): BaseActionViewItem {
|
||||
if (action instanceof Separator) {
|
||||
return new MenuSeparatorActionItem(options.context, action, { icon: true });
|
||||
return new MenuSeparatorActionViewItem(options.context, action, { icon: true });
|
||||
} else if (action instanceof SubmenuAction) {
|
||||
const menuActionItem = new SubmenuActionItem(action, action.entries, parentData, options);
|
||||
const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.entries, parentData, options);
|
||||
|
||||
if (options.enableMnemonics) {
|
||||
const mnemonic = menuActionItem.getMnemonic();
|
||||
if (mnemonic && menuActionItem.isEnabled()) {
|
||||
let actionItems: MenuActionItem[] = [];
|
||||
const mnemonic = menuActionViewItem.getMnemonic();
|
||||
if (mnemonic && menuActionViewItem.isEnabled()) {
|
||||
let actionViewItems: BaseMenuActionViewItem[] = [];
|
||||
if (this.mnemonics.has(mnemonic)) {
|
||||
actionItems = this.mnemonics.get(mnemonic)!;
|
||||
actionViewItems = this.mnemonics.get(mnemonic)!;
|
||||
}
|
||||
|
||||
actionItems.push(menuActionItem);
|
||||
actionViewItems.push(menuActionViewItem);
|
||||
|
||||
this.mnemonics.set(mnemonic, actionItems);
|
||||
this.mnemonics.set(mnemonic, actionViewItems);
|
||||
}
|
||||
}
|
||||
|
||||
return menuActionItem;
|
||||
return menuActionViewItem;
|
||||
} else {
|
||||
const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics };
|
||||
if (options.getKeyBinding) {
|
||||
@@ -329,32 +329,32 @@ export class Menu extends ActionBar {
|
||||
}
|
||||
}
|
||||
|
||||
const menuActionItem = new MenuActionItem(options.context, action, menuItemOptions);
|
||||
const menuActionViewItem = new BaseMenuActionViewItem(options.context, action, menuItemOptions);
|
||||
|
||||
if (options.enableMnemonics) {
|
||||
const mnemonic = menuActionItem.getMnemonic();
|
||||
if (mnemonic && menuActionItem.isEnabled()) {
|
||||
let actionItems: MenuActionItem[] = [];
|
||||
const mnemonic = menuActionViewItem.getMnemonic();
|
||||
if (mnemonic && menuActionViewItem.isEnabled()) {
|
||||
let actionViewItems: BaseMenuActionViewItem[] = [];
|
||||
if (this.mnemonics.has(mnemonic)) {
|
||||
actionItems = this.mnemonics.get(mnemonic)!;
|
||||
actionViewItems = this.mnemonics.get(mnemonic)!;
|
||||
}
|
||||
|
||||
actionItems.push(menuActionItem);
|
||||
actionViewItems.push(menuActionViewItem);
|
||||
|
||||
this.mnemonics.set(mnemonic, actionItems);
|
||||
this.mnemonics.set(mnemonic, actionViewItems);
|
||||
}
|
||||
}
|
||||
|
||||
return menuActionItem;
|
||||
return menuActionViewItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface IMenuItemOptions extends IActionItemOptions {
|
||||
interface IMenuItemOptions extends IActionViewItemOptions {
|
||||
enableMnemonics?: boolean;
|
||||
}
|
||||
|
||||
class MenuActionItem extends BaseActionItem {
|
||||
class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
|
||||
public container: HTMLElement;
|
||||
|
||||
@@ -562,7 +562,7 @@ class MenuActionItem extends BaseActionItem {
|
||||
}
|
||||
}
|
||||
|
||||
class SubmenuActionItem extends MenuActionItem {
|
||||
class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
|
||||
private mysubmenu: Menu | null;
|
||||
private submenuContainer: HTMLElement | undefined;
|
||||
private submenuIndicator: HTMLElement;
|
||||
@@ -778,7 +778,7 @@ class SubmenuActionItem extends MenuActionItem {
|
||||
}
|
||||
}
|
||||
|
||||
class MenuSeparatorActionItem extends ActionItem {
|
||||
class MenuSeparatorActionViewItem extends ActionViewItem {
|
||||
style(style: IMenuStyles): void {
|
||||
this.label.style.borderBottomColor = style.separatorColor ? `${style.separatorColor}` : null;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ class SelectListRenderer implements IListRenderer<ISelectOptionItem, ISelectList
|
||||
|
||||
constructor() { }
|
||||
|
||||
renderTemplate(container: HTMLElement): any {
|
||||
const data = <ISelectListTemplateData>Object.create(null);
|
||||
renderTemplate(container: HTMLElement): ISelectListTemplateData {
|
||||
const data: ISelectListTemplateData = Object.create(null);
|
||||
data.disposables = [];
|
||||
data.root = container;
|
||||
data.text = dom.append(container, $('.option-text'));
|
||||
@@ -54,10 +54,10 @@ class SelectListRenderer implements IListRenderer<ISelectOptionItem, ISelectList
|
||||
}
|
||||
|
||||
renderElement(element: ISelectOptionItem, index: number, templateData: ISelectListTemplateData): void {
|
||||
const data = <ISelectListTemplateData>templateData;
|
||||
const text = (<ISelectOptionItem>element).text;
|
||||
const decoratorRight = (<ISelectOptionItem>element).decoratorRight;
|
||||
const isDisabled = (<ISelectOptionItem>element).isDisabled;
|
||||
const data: ISelectListTemplateData = templateData;
|
||||
const text = element.text;
|
||||
const decoratorRight = element.decoratorRight;
|
||||
const isDisabled = element.isDisabled;
|
||||
|
||||
data.text.textContent = text;
|
||||
data.decoratorRight.innerText = (!!decoratorRight ? decoratorRight : '');
|
||||
@@ -73,10 +73,10 @@ class SelectListRenderer implements IListRenderer<ISelectOptionItem, ISelectList
|
||||
|
||||
// pseudo-select disabled option
|
||||
if (isDisabled) {
|
||||
dom.addClass((<HTMLElement>data.root), 'option-disabled');
|
||||
dom.addClass(data.root, 'option-disabled');
|
||||
} else {
|
||||
// Make sure we do class removal from prior template rendering
|
||||
dom.removeClass((<HTMLElement>data.root), 'option-disabled');
|
||||
dom.removeClass(data.root, 'option-disabled');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,9 +836,9 @@ export class SelectBoxList implements ISelectBoxDelegate, IListVirtualDelegate<I
|
||||
private renderDescriptionMarkdown(text: string): HTMLElement {
|
||||
const cleanRenderedMarkdown = (element: Node) => {
|
||||
for (let i = 0; i < element.childNodes.length; i++) {
|
||||
const child = element.childNodes.item(i);
|
||||
const child = <Element>element.childNodes.item(i);
|
||||
|
||||
const tagName = (<Element>child).tagName && (<Element>child).tagName.toLowerCase();
|
||||
const tagName = child.tagName && child.tagName.toLowerCase();
|
||||
if (tagName === 'img') {
|
||||
element.removeChild(child);
|
||||
} else {
|
||||
|
||||
@@ -234,8 +234,8 @@ export class SplitView extends Disposable {
|
||||
});
|
||||
|
||||
const sashEventMapper = this.orientation === Orientation.VERTICAL
|
||||
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent)
|
||||
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent);
|
||||
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey })
|
||||
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey });
|
||||
|
||||
const onStart = Event.map(sash.onDidStart, sashEventMapper);
|
||||
const onStartDisposable = onStart(this.onSashStart, this);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import 'vs/css!./toolbar';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action, IActionRunner, IAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuProvider, DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuProvider, DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
@@ -17,7 +17,7 @@ export const CONTEXT = 'context.toolbar';
|
||||
|
||||
export interface IToolBarOptions {
|
||||
orientation?: ActionsOrientation;
|
||||
actionItemProvider?: IActionItemProvider;
|
||||
actionViewItemProvider?: IActionViewItemProvider;
|
||||
ariaLabel?: string;
|
||||
getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
actionRunner?: IActionRunner;
|
||||
@@ -32,7 +32,7 @@ export class ToolBar extends Disposable {
|
||||
private options: IToolBarOptions;
|
||||
private actionBar: ActionBar;
|
||||
private toggleMenuAction: ToggleMenuAction;
|
||||
private toggleMenuActionItem?: DropdownMenuActionItem;
|
||||
private toggleMenuActionViewItem?: DropdownMenuActionViewItem;
|
||||
private hasSecondaryActions: boolean;
|
||||
private lookupKeybindings: boolean;
|
||||
|
||||
@@ -42,7 +42,7 @@ export class ToolBar extends Disposable {
|
||||
this.options = options;
|
||||
this.lookupKeybindings = typeof this.options.getKeyBinding === 'function';
|
||||
|
||||
this.toggleMenuAction = this._register(new ToggleMenuAction(() => this.toggleMenuActionItem && this.toggleMenuActionItem.show(), options.toggleMenuTitle));
|
||||
this.toggleMenuAction = this._register(new ToggleMenuAction(() => this.toggleMenuActionViewItem && this.toggleMenuActionViewItem.show(), options.toggleMenuTitle));
|
||||
|
||||
let element = document.createElement('div');
|
||||
element.className = 'monaco-toolbar';
|
||||
@@ -52,33 +52,33 @@ export class ToolBar extends Disposable {
|
||||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionRunner: options.actionRunner,
|
||||
actionItemProvider: (action: Action) => {
|
||||
actionViewItemProvider: (action: Action) => {
|
||||
|
||||
// Return special action item for the toggle menu action
|
||||
if (action.id === ToggleMenuAction.ID) {
|
||||
|
||||
// Dispose old
|
||||
if (this.toggleMenuActionItem) {
|
||||
this.toggleMenuActionItem.dispose();
|
||||
if (this.toggleMenuActionViewItem) {
|
||||
this.toggleMenuActionViewItem.dispose();
|
||||
}
|
||||
|
||||
// Create new
|
||||
this.toggleMenuActionItem = new DropdownMenuActionItem(
|
||||
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
|
||||
action,
|
||||
(<ToggleMenuAction>action).menuActions,
|
||||
contextMenuProvider,
|
||||
this.options.actionItemProvider,
|
||||
this.options.actionViewItemProvider,
|
||||
this.actionRunner,
|
||||
this.options.getKeyBinding,
|
||||
'toolbar-toggle-more',
|
||||
this.options.anchorAlignmentProvider
|
||||
);
|
||||
this.toggleMenuActionItem!.setActionContext(this.actionBar.context);
|
||||
this.toggleMenuActionViewItem!.setActionContext(this.actionBar.context);
|
||||
|
||||
return this.toggleMenuActionItem;
|
||||
return this.toggleMenuActionViewItem;
|
||||
}
|
||||
|
||||
return options.actionItemProvider ? options.actionItemProvider(action) : undefined;
|
||||
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -93,8 +93,8 @@ export class ToolBar extends Disposable {
|
||||
|
||||
set context(context: any) {
|
||||
this.actionBar.context = context;
|
||||
if (this.toggleMenuActionItem) {
|
||||
this.toggleMenuActionItem.setActionContext(context);
|
||||
if (this.toggleMenuActionViewItem) {
|
||||
this.toggleMenuActionViewItem.setActionContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,9 +156,9 @@ export class ToolBar extends Disposable {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.toggleMenuActionItem) {
|
||||
this.toggleMenuActionItem.dispose();
|
||||
this.toggleMenuActionItem = undefined;
|
||||
if (this.toggleMenuActionViewItem) {
|
||||
this.toggleMenuActionViewItem.dispose();
|
||||
this.toggleMenuActionViewItem = undefined;
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
|
||||
@@ -29,7 +29,7 @@ export interface IActionRunner extends IDisposable {
|
||||
onDidBeforeRun: Event<IRunEvent>;
|
||||
}
|
||||
|
||||
export interface IActionItem {
|
||||
export interface IActionViewItem {
|
||||
actionRunner: IActionRunner;
|
||||
setActionContext(context: any): void;
|
||||
render(element: any /* HTMLElement */): void;
|
||||
|
||||
@@ -79,7 +79,7 @@ export function getFirstFrame(arg0: IRemoteConsoleLog | string | undefined): ISt
|
||||
uri: URI.file(matches[1]),
|
||||
line: Number(matches[2]),
|
||||
column: Number(matches[3])
|
||||
} as IStackFrame;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,19 +139,22 @@ export function isUNC(path: string): boolean {
|
||||
}
|
||||
|
||||
// Reference: https://en.wikipedia.org/wiki/Filename
|
||||
const INVALID_FILE_CHARS = isWindows ? /[\\/:\*\?"<>\|]/g : /[\\/]/g;
|
||||
const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g;
|
||||
const UNIX_INVALID_FILE_CHARS = /[\\/]/g;
|
||||
const WINDOWS_FORBIDDEN_NAMES = /^(con|prn|aux|clock\$|nul|lpt[0-9]|com[0-9])$/i;
|
||||
export function isValidBasename(name: string | null | undefined): boolean {
|
||||
export function isValidBasename(name: string | null | undefined, isWindowsOS: boolean = isWindows): boolean {
|
||||
const invalidFileChars = isWindowsOS ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS;
|
||||
|
||||
if (!name || name.length === 0 || /^\s+$/.test(name)) {
|
||||
return false; // require a name that is not just whitespace
|
||||
}
|
||||
|
||||
INVALID_FILE_CHARS.lastIndex = 0; // the holy grail of software development
|
||||
if (INVALID_FILE_CHARS.test(name)) {
|
||||
invalidFileChars.lastIndex = 0; // the holy grail of software development
|
||||
if (invalidFileChars.test(name)) {
|
||||
return false; // check for certain invalid file characters
|
||||
}
|
||||
|
||||
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(name)) {
|
||||
if (isWindowsOS && WINDOWS_FORBIDDEN_NAMES.test(name)) {
|
||||
return false; // check for certain invalid file names
|
||||
}
|
||||
|
||||
@@ -159,16 +162,16 @@ export function isValidBasename(name: string | null | undefined): boolean {
|
||||
return false; // check for reserved values
|
||||
}
|
||||
|
||||
if (isWindows && name[name.length - 1] === '.') {
|
||||
if (isWindowsOS && name[name.length - 1] === '.') {
|
||||
return false; // Windows: file cannot end with a "."
|
||||
}
|
||||
|
||||
if (isWindows && name.length !== name.trim().length) {
|
||||
if (isWindowsOS && name.length !== name.trim().length) {
|
||||
return false; // Windows: file cannot end with a whitespace
|
||||
}
|
||||
|
||||
if (name.length > 255) {
|
||||
return false; // most file systems do not allow files > 255 lenth
|
||||
return false; // most file systems do not allow files > 255 length
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -197,7 +197,11 @@ function guessMimeTypeByFirstline(firstLine: string): string | null {
|
||||
}
|
||||
|
||||
if (firstLine.length > 0) {
|
||||
for (const association of registeredAssociations) {
|
||||
|
||||
// We want to prioritize associations based on the order they are registered so that the last registered
|
||||
// association wins over all other. This is for https://github.com/Microsoft/vscode/issues/20074
|
||||
for (let i = registeredAssociations.length - 1; i >= 0; i--) {
|
||||
const association = registeredAssociations[i];
|
||||
if (!association.firstline) {
|
||||
continue;
|
||||
}
|
||||
@@ -230,10 +234,11 @@ export function isUnspecific(mime: string[] | string): boolean {
|
||||
* 2. Otherwise, if there are other extensions, suggest the first one.
|
||||
* 3. Otherwise, suggest the prefix.
|
||||
*/
|
||||
export function suggestFilename(langId: string | null, prefix: string): string {
|
||||
export function suggestFilename(mode: string | undefined, prefix: string): string {
|
||||
const extensions = registeredAssociations
|
||||
.filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === langId)
|
||||
.filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === mode)
|
||||
.map(assoc => assoc.extension);
|
||||
|
||||
const extensionsWithDotFirst = coalesce(extensions)
|
||||
.filter(assoc => startsWith(assoc, '.'));
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export function deepClone<T>(obj: T): T {
|
||||
return obj as any;
|
||||
}
|
||||
const result: any = Array.isArray(obj) ? [] : {};
|
||||
Object.keys(obj).forEach((key: string) => {
|
||||
Object.keys(obj as any).forEach((key: string) => {
|
||||
if (obj[key] && typeof obj[key] === 'object') {
|
||||
result[key] = deepClone(obj[key]);
|
||||
} else {
|
||||
|
||||
@@ -79,7 +79,7 @@ export abstract class Parser {
|
||||
this._problemReporter.fatal(message);
|
||||
}
|
||||
|
||||
protected static merge<T>(destination: T, source: T, overwrite: boolean): void {
|
||||
protected static merge<T extends object>(destination: T, source: T, overwrite: boolean): void {
|
||||
Object.keys(source).forEach((key: string) => {
|
||||
const destValue = destination[key];
|
||||
const sourceValue = source[key];
|
||||
|
||||
@@ -176,28 +176,46 @@ export function isAbsolutePath(resource: URI): boolean {
|
||||
/**
|
||||
* Returns true if the URI path has a trailing path separator
|
||||
*/
|
||||
export function hasTrailingPathSeparator(resource: URI): boolean {
|
||||
export function hasTrailingPathSeparator(resource: URI, sep: string = paths.sep): boolean {
|
||||
if (resource.scheme === Schemas.file) {
|
||||
const fsp = originalFSPath(resource);
|
||||
return fsp.length > extpath.getRoot(fsp).length && fsp[fsp.length - 1] === paths.sep;
|
||||
return fsp.length > extpath.getRoot(fsp).length && fsp[fsp.length - 1] === sep;
|
||||
} else {
|
||||
const p = resource.path;
|
||||
return p.length > 1 && p.charCodeAt(p.length - 1) === CharCode.Slash; // ignore the slash at offset 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a trailing path seperator, if theres one.
|
||||
* Removes a trailing path separator, if there's one.
|
||||
* Important: Doesn't remove the first slash, it would make the URI invalid
|
||||
*/
|
||||
export function removeTrailingPathSeparator(resource: URI): URI {
|
||||
if (hasTrailingPathSeparator(resource)) {
|
||||
export function removeTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI {
|
||||
if (hasTrailingPathSeparator(resource, sep)) {
|
||||
return resource.with({ path: resource.path.substr(0, resource.path.length - 1) });
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trailing path separator to the URI if there isn't one already.
|
||||
* For example, c:\ would be unchanged, but c:\users would become c:\users\
|
||||
*/
|
||||
export function addTrailingPathSeparator(resource: URI, sep: string = paths.sep): URI {
|
||||
let isRootSep: boolean = false;
|
||||
if (resource.scheme === Schemas.file) {
|
||||
const fsp = originalFSPath(resource);
|
||||
isRootSep = ((fsp !== undefined) && (fsp.length === extpath.getRoot(fsp).length) && (fsp[fsp.length - 1] === sep));
|
||||
} else {
|
||||
sep = '/';
|
||||
const p = resource.path;
|
||||
isRootSep = p.length === 1 && p.charCodeAt(p.length - 1) === CharCode.Slash;
|
||||
}
|
||||
if (!isRootSep && !hasTrailingPathSeparator(resource, sep)) {
|
||||
return resource.with({ path: resource.path + '/' });
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a relative path between two URIs. If the URIs don't have the same schema or authority, `undefined` is returned.
|
||||
|
||||
@@ -233,7 +233,7 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean {
|
||||
// We check against an empty string. If the regular expression doesn't advance
|
||||
// (e.g. ends in an endless loop) it will match an empty string.
|
||||
const match = regexp.exec('');
|
||||
return !!(match && <any>regexp.lastIndex === 0);
|
||||
return !!(match && regexp.lastIndex === 0);
|
||||
}
|
||||
|
||||
export function regExpContainsBackreference(regexpValue: string): boolean {
|
||||
|
||||
@@ -670,4 +670,15 @@ export async function mkdirp(path: string, mode?: number, token?: CancellationTo
|
||||
// Any other error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See https://github.com/Microsoft/vscode/issues/30180
|
||||
const WIN32_MAX_FILE_SIZE = 300 * 1024 * 1024; // 300 MB
|
||||
const GENERAL_MAX_FILE_SIZE = 16 * 1024 * 1024 * 1024; // 16 GB
|
||||
|
||||
// See https://github.com/v8/v8/blob/5918a23a3d571b9625e5cce246bdd5b46ff7cd8b/src/heap/heap.cc#L149
|
||||
const WIN32_MAX_HEAP_SIZE = 700 * 1024 * 1024; // 700 MB
|
||||
const GENERAL_MAX_HEAP_SIZE = 700 * 2 * 1024 * 1024; // 1400 MB
|
||||
|
||||
export const MAX_FILE_SIZE = process.arch === 'ia32' ? WIN32_MAX_FILE_SIZE : GENERAL_MAX_FILE_SIZE;
|
||||
export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE;
|
||||
@@ -159,7 +159,7 @@ export function asText(context: IRequestContext): Promise<string | null> {
|
||||
});
|
||||
}
|
||||
|
||||
export function asJson<T>(context: IRequestContext): Promise<T | null> {
|
||||
export function asJson<T = {}>(context: IRequestContext): Promise<T | null> {
|
||||
return new Promise((c, e) => {
|
||||
if (!isSuccess(context)) {
|
||||
return e('Server returned ' + context.res.statusCode);
|
||||
|
||||
@@ -218,7 +218,7 @@ class ProtocolReader extends Disposable {
|
||||
// save new state => next time will read the body
|
||||
this._state.readHead = false;
|
||||
this._state.readLen = buff.readUInt32BE(9);
|
||||
this._state.messageType = <ProtocolMessageType>buff.readUInt8(0);
|
||||
this._state.messageType = buff.readUInt8(0);
|
||||
this._state.id = buff.readUInt32BE(1);
|
||||
this._state.ack = buff.readUInt32BE(5);
|
||||
} else {
|
||||
|
||||
@@ -36,11 +36,11 @@ let IDS = 0;
|
||||
export class QuickOpenItemAccessorClass implements IItemAccessor<QuickOpenEntry> {
|
||||
|
||||
getItemLabel(entry: QuickOpenEntry): string | null {
|
||||
return entry.getLabel();
|
||||
return types.withUndefinedAsNull(entry.getLabel());
|
||||
}
|
||||
|
||||
getItemDescription(entry: QuickOpenEntry): string | null {
|
||||
return entry.getDescription();
|
||||
return types.withUndefinedAsNull(entry.getDescription());
|
||||
}
|
||||
|
||||
getItemPath(entry: QuickOpenEntry): string | undefined {
|
||||
@@ -75,15 +75,15 @@ export class QuickOpenEntry {
|
||||
/**
|
||||
* The label of the entry to identify it from others in the list
|
||||
*/
|
||||
getLabel(): string | null {
|
||||
return null;
|
||||
getLabel(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The options for the label to use for this entry
|
||||
*/
|
||||
getLabelOptions(): IIconLabelValueOptions | null {
|
||||
return null;
|
||||
getLabelOptions(): IIconLabelValueOptions | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,51 +97,51 @@ export class QuickOpenEntry {
|
||||
/**
|
||||
* Detail information about the entry that is optional and can be shown below the label
|
||||
*/
|
||||
getDetail(): string | null {
|
||||
return null;
|
||||
getDetail(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The icon of the entry to identify it from others in the list
|
||||
*/
|
||||
getIcon(): string | null {
|
||||
return null;
|
||||
getIcon(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A secondary description that is optional and can be shown right to the label
|
||||
*/
|
||||
getDescription(): string | null {
|
||||
return null;
|
||||
getDescription(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A tooltip to show when hovering over the entry.
|
||||
*/
|
||||
getTooltip(): string | null {
|
||||
return null;
|
||||
getTooltip(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A tooltip to show when hovering over the description portion of the entry.
|
||||
*/
|
||||
getDescriptionTooltip(): string | null {
|
||||
return null;
|
||||
getDescriptionTooltip(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional keybinding to show for an entry.
|
||||
*/
|
||||
getKeybinding(): ResolvedKeybinding | null {
|
||||
return null;
|
||||
getKeybinding(): ResolvedKeybinding | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A resource for this entry. Resource URIs can be used to compare different kinds of entries and group
|
||||
* them together.
|
||||
*/
|
||||
getResource(): URI | null {
|
||||
return null;
|
||||
getResource(): URI | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,11 +229,11 @@ export class QuickOpenEntryGroup extends QuickOpenEntry {
|
||||
this.withBorder = showBorder;
|
||||
}
|
||||
|
||||
getLabel(): string | null {
|
||||
getLabel(): string | undefined {
|
||||
return this.entry ? this.entry.getLabel() : super.getLabel();
|
||||
}
|
||||
|
||||
getLabelOptions(): IIconLabelValueOptions | null {
|
||||
getLabelOptions(): IIconLabelValueOptions | undefined {
|
||||
return this.entry ? this.entry.getLabelOptions() : super.getLabelOptions();
|
||||
}
|
||||
|
||||
@@ -241,19 +241,19 @@ export class QuickOpenEntryGroup extends QuickOpenEntry {
|
||||
return this.entry ? this.entry.getAriaLabel() : super.getAriaLabel();
|
||||
}
|
||||
|
||||
getDetail(): string | null {
|
||||
getDetail(): string | undefined {
|
||||
return this.entry ? this.entry.getDetail() : super.getDetail();
|
||||
}
|
||||
|
||||
getResource(): URI | null {
|
||||
getResource(): URI | undefined {
|
||||
return this.entry ? this.entry.getResource() : super.getResource();
|
||||
}
|
||||
|
||||
getIcon(): string | null {
|
||||
getIcon(): string | undefined {
|
||||
return this.entry ? this.entry.getIcon() : super.getIcon();
|
||||
}
|
||||
|
||||
getDescription(): string | null {
|
||||
getDescription(): string | undefined {
|
||||
return this.entry ? this.entry.getDescription() : super.getDescription();
|
||||
}
|
||||
|
||||
@@ -459,13 +459,13 @@ class Renderer implements IRenderer<QuickOpenEntry> {
|
||||
// Label
|
||||
const options: IIconLabelValueOptions = entry.getLabelOptions() || Object.create(null);
|
||||
options.matches = labelHighlights || [];
|
||||
options.title = types.withNullAsUndefined(entry.getTooltip());
|
||||
options.descriptionTitle = entry.getDescriptionTooltip() || types.withNullAsUndefined(entry.getDescription()); // tooltip over description because it could overflow
|
||||
options.title = entry.getTooltip();
|
||||
options.descriptionTitle = entry.getDescriptionTooltip() || entry.getDescription(); // tooltip over description because it could overflow
|
||||
options.descriptionMatches = descriptionHighlights || [];
|
||||
data.label.setLabel(types.withNullAsUndefined(entry.getLabel()), types.withNullAsUndefined(entry.getDescription()), options);
|
||||
data.label.setLabel(types.withNullAsUndefined(entry.getLabel()), entry.getDescription(), options);
|
||||
|
||||
// Meta
|
||||
data.detail.set(types.withNullAsUndefined(entry.getDetail()), detailHighlights);
|
||||
data.detail.set(entry.getDetail(), detailHighlights);
|
||||
|
||||
// Keybinding
|
||||
data.keybinding.set(entry.getKeybinding()!);
|
||||
@@ -556,7 +556,7 @@ export class QuickOpenModel implements
|
||||
}
|
||||
|
||||
getLabel(entry: QuickOpenEntry): string | null {
|
||||
return entry.getLabel();
|
||||
return types.withUndefinedAsNull(entry.getLabel());
|
||||
}
|
||||
|
||||
getAriaLabel(entry: QuickOpenEntry): string {
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as assert from 'assert';
|
||||
import { guessMimeTypes, registerTextMime, suggestFilename } from 'vs/base/common/mime';
|
||||
|
||||
suite('Mime', () => {
|
||||
|
||||
test('Dynamically Register Text Mime', () => {
|
||||
let guess = guessMimeTypes('foo.monaco');
|
||||
assert.deepEqual(guess, ['application/unknown']);
|
||||
@@ -56,6 +57,11 @@ suite('Mime', () => {
|
||||
registerTextMime({ id: 'docker', filepattern: 'dockerfile*', mime: 'text/looser' });
|
||||
guess = guessMimeTypes('dockerfile');
|
||||
assert.deepEqual(guess, ['text/winner', 'text/plain']);
|
||||
|
||||
registerTextMime({ id: 'azure-looser', mime: 'text/azure-looser', firstline: /azure/ });
|
||||
registerTextMime({ id: 'azure-winner', mime: 'text/azure-winner', firstline: /azure/ });
|
||||
guess = guessMimeTypes('azure', 'azure');
|
||||
assert.deepEqual(guess, ['text/azure-winner', 'text/plain']);
|
||||
});
|
||||
|
||||
test('Specificity priority 1', () => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, relativePath, removeTrailingPathSeparator, hasTrailingPathSeparator, resolvePath } from 'vs/base/common/resources';
|
||||
import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, relativePath, removeTrailingPathSeparator, hasTrailingPathSeparator, resolvePath, addTrailingPathSeparator } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { toSlashes } from 'vs/base/common/extpath';
|
||||
@@ -178,6 +178,9 @@ suite('Resources', () => {
|
||||
assertEqualURI(removeTrailingPathSeparator(u1), expected, u1.toString());
|
||||
}
|
||||
|
||||
function assertAddTrailingSeparator(u1: URI, expected: URI) {
|
||||
assertEqualURI(addTrailingPathSeparator(u1), expected, u1.toString());
|
||||
}
|
||||
|
||||
test('trailingPathSeparator', () => {
|
||||
assertTrailingSeparator(URI.parse('foo://a/foo'), false);
|
||||
@@ -190,6 +193,11 @@ suite('Resources', () => {
|
||||
assertRemoveTrailingSeparator(URI.parse('foo://a/'), URI.parse('foo://a/'));
|
||||
assertRemoveTrailingSeparator(URI.parse('foo://a'), URI.parse('foo://a'));
|
||||
|
||||
assertAddTrailingSeparator(URI.parse('foo://a/foo'), URI.parse('foo://a/foo/'));
|
||||
assertAddTrailingSeparator(URI.parse('foo://a/foo/'), URI.parse('foo://a/foo/'));
|
||||
assertAddTrailingSeparator(URI.parse('foo://a/'), URI.parse('foo://a/'));
|
||||
assertAddTrailingSeparator(URI.parse('foo://a'), URI.parse('foo://a/'));
|
||||
|
||||
if (isWindows) {
|
||||
assertTrailingSeparator(URI.file('c:\\a\\foo'), false);
|
||||
assertTrailingSeparator(URI.file('c:\\a\\foo\\'), true);
|
||||
@@ -202,6 +210,12 @@ suite('Resources', () => {
|
||||
assertRemoveTrailingSeparator(URI.file('c:\\'), URI.file('c:\\'));
|
||||
assertRemoveTrailingSeparator(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share\\some'));
|
||||
assertRemoveTrailingSeparator(URI.file('\\\\server\\share\\'), URI.file('\\\\server\\share\\'));
|
||||
|
||||
assertAddTrailingSeparator(URI.file('c:\\a\\foo'), URI.file('c:\\a\\foo\\'));
|
||||
assertAddTrailingSeparator(URI.file('c:\\a\\foo\\'), URI.file('c:\\a\\foo\\'));
|
||||
assertAddTrailingSeparator(URI.file('c:\\'), URI.file('c:\\'));
|
||||
assertAddTrailingSeparator(URI.file('\\\\server\\share\\some'), URI.file('\\\\server\\share\\some\\'));
|
||||
assertAddTrailingSeparator(URI.file('\\\\server\\share\\some\\'), URI.file('\\\\server\\share\\some\\'));
|
||||
} else {
|
||||
assertTrailingSeparator(URI.file('/foo/bar'), false);
|
||||
assertTrailingSeparator(URI.file('/foo/bar/'), true);
|
||||
@@ -210,12 +224,16 @@ suite('Resources', () => {
|
||||
assertRemoveTrailingSeparator(URI.file('/foo/bar'), URI.file('/foo/bar'));
|
||||
assertRemoveTrailingSeparator(URI.file('/foo/bar/'), URI.file('/foo/bar'));
|
||||
assertRemoveTrailingSeparator(URI.file('/'), URI.file('/'));
|
||||
|
||||
assertAddTrailingSeparator(URI.file('/foo/bar'), URI.file('/foo/bar/'));
|
||||
assertAddTrailingSeparator(URI.file('/foo/bar/'), URI.file('/foo/bar/'));
|
||||
assertAddTrailingSeparator(URI.file('/'), URI.file('/'));
|
||||
}
|
||||
});
|
||||
|
||||
function assertEqualURI(actual: URI, expected: URI, message?: string) {
|
||||
if (!isEqual(expected, actual)) {
|
||||
assert.equal(expected.toString(), actual.toString(), message);
|
||||
assert.equal(actual.toString(), expected.toString(), message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ suite('Config', () => {
|
||||
const newDir = path.join(parentDir, 'config', id);
|
||||
const testFile = path.join(newDir, 'config.json');
|
||||
|
||||
let watcher = new ConfigWatcher(testFile);
|
||||
let watcher = new ConfigWatcher<{}>(testFile);
|
||||
|
||||
let config = watcher.getConfig();
|
||||
assert.ok(config);
|
||||
|
||||
Reference in New Issue
Block a user