mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Merge from vscode 731f9c25632dbbf01ee3a7892ad9d2791fe0260c
This commit is contained in:
@@ -77,7 +77,6 @@ const vscodeResources = [
|
||||
'out-build/vs/code/electron-browser/workbench/**',
|
||||
'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
|
||||
'out-build/vs/code/electron-browser/issue/issueReporter.js',
|
||||
'out-build/vs/code/electron-browser/processExplorer/processExplorer.js',
|
||||
'out-build/sql/workbench/electron-browser/splashscreen/*', // {{SQL CARBON EDIT}} STart
|
||||
'out-build/sql/**/*.{svg,png,cur,html}',
|
||||
'out-build/sql/base/browser/ui/table/media/*.{gif,png,svg}',
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"url": "vscode://schemas/keybindings"
|
||||
},
|
||||
{
|
||||
"fileMatch": "vscode://defaultsettings/*/*.json",
|
||||
"fileMatch": "vscode://defaultsettings/defaultSettings.json",
|
||||
"url": "vscode://schemas/settings/default"
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -163,13 +163,15 @@ document.addEventListener('click', event => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass through known schemes
|
||||
if (passThroughLinkSchemes.some(scheme => node.href.startsWith(scheme))) {
|
||||
return;
|
||||
let hrefText = node.getAttribute('data-href');
|
||||
if (!hrefText) {
|
||||
// Pass through known schemes
|
||||
if (passThroughLinkSchemes.some(scheme => node.href.startsWith(scheme))) {
|
||||
return;
|
||||
}
|
||||
hrefText = node.getAttribute('href');
|
||||
}
|
||||
|
||||
const hrefText = node.getAttribute('data-href') || node.getAttribute('href');
|
||||
|
||||
// If original link doesn't look like a url, delegate back to VS Code to resolve
|
||||
if (!/^[a-z\-]+:/i.test(hrefText)) {
|
||||
messaging.postMessage('openLink', { href: hrefText });
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
"*",
|
||||
"onAuthenticationRequest:microsoft"
|
||||
],
|
||||
"extensionKind": [
|
||||
"ui",
|
||||
"workspace"
|
||||
],
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"main": "./out/extension.js",
|
||||
"browser": "./dist/browser/extension.js",
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
|
||||
"spdlog": "^0.11.1",
|
||||
"sudo-prompt": "9.1.1",
|
||||
"tas-client": "^0.0.950",
|
||||
"v8-inspect-profiler": "^0.0.20",
|
||||
"vscode-nsfw": "1.2.8",
|
||||
"vscode-oniguruma": "1.3.1",
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./buttonMenu';
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { BaseActionViewItem, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, IActionRunner, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { append, $, addClasses } from 'vs/base/browser/dom';
|
||||
import { IDropdownMenuOptions, DropdownMenu, IActionProvider, IContextMenuProvider, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { IDropdownMenuOptions, DropdownMenu, IActionProvider, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
private menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider;
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions';
|
||||
import { IAction, IActionRunner, ActionRunner, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import {
|
||||
IActionBarOptions, ActionsOrientation, IActionViewItem,
|
||||
IActionOptions, ActionViewItem, BaseActionViewItem
|
||||
IActionBarOptions, ActionsOrientation,
|
||||
IActionOptions
|
||||
} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import * as lifecycle from 'vs/base/common/lifecycle';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ActionViewItem, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
const defaultOptions: IActionBarOptions = {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import {
|
||||
IActionBarOptions, ActionsOrientation, IActionViewItem,
|
||||
IActionBarOptions, ActionsOrientation,
|
||||
IActionOptions
|
||||
} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
|
||||
@@ -8,8 +8,8 @@ import 'vs/css!./media/icons';
|
||||
|
||||
import { ActionBar } from './actionbar';
|
||||
|
||||
import { IActionRunner, IAction } from 'vs/base/common/actions';
|
||||
import { ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IActionRunner, IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IToolBarOptions } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { OverflowActionBar } from 'sql/base/browser/ui/taskbar/overflowActionbar';
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IAction, ActionRunner } from 'vs/base/common/actions';
|
||||
import { IAction, ActionRunner, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IMenuService, MenuId, MenuItemAction, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { ContextAwareMenuEntryActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenuService, MenuId, MenuItemAction, registerAction2, Action2, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuEntryActionViewItem, createAndFillInContextMenuActions, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IContextKeyService, ContextKeyExpr, ContextKeyEqualsExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { TreeItemCollapsibleState, ITreeViewDataProvider, TreeViewItemHandleArg, ITreeViewDescriptor, IViewsRegistry, ITreeItemLabel, Extensions, IViewDescriptorService, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
@@ -21,7 +21,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { dirname, basename } from 'vs/base/common/resources';
|
||||
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -47,6 +47,7 @@ import { ITreeItem, ITreeView } from 'sql/workbench/common/views';
|
||||
import { UserCancelledConnectionError } from 'sql/base/common/errors';
|
||||
import { IOEShimService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerViewTreeShim';
|
||||
import { NodeContextKey } from 'sql/workbench/browser/parts/views/nodeContext';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export class TreeViewPane extends ViewPane {
|
||||
|
||||
@@ -429,7 +430,15 @@ export class TreeView extends Disposable implements ITreeView {
|
||||
}
|
||||
|
||||
private createTree() {
|
||||
const actionViewItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuEntryActionViewItem, action) : undefined;
|
||||
const actionViewItemProvider = (action: IAction) => {
|
||||
if (action instanceof MenuItemAction) {
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
const treeMenus = this._register(this.instantiationService.createInstance(TreeMenus, this.id));
|
||||
this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels, this));
|
||||
const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.id, <T>(task: Promise<T>) => this.progressService.withProgress({ location: this.id }, () => task));
|
||||
|
||||
@@ -20,8 +20,7 @@ import { EditDataInput } from 'sql/workbench/browser/editData/editDataInput';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import * as queryContext from 'sql/workbench/contrib/query/common/queryContext';
|
||||
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { IQueryModelService } from 'sql/workbench/services/query/common/queryModel';
|
||||
import { IEditorDescriptorService } from 'sql/workbench/services/queryEditor/browser/editorDescriptorService';
|
||||
import {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { localize } from 'vs/nls';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, Separator, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CellActionBase, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
|
||||
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
|
||||
import { CellTypes, CellType } from 'sql/workbench/services/notebook/common/contracts';
|
||||
|
||||
@@ -11,7 +11,6 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { TestLifecycleService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
|
||||
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
@@ -20,6 +19,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { ContextMenuService } from 'vs/platform/contextview/browser/contextMenuService';
|
||||
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Separator } from 'vs/base/common/actions';
|
||||
|
||||
suite('CellToolbarActions', function (): void {
|
||||
suite('removeDuplicatedAndStartingSeparators', function (): void {
|
||||
|
||||
@@ -32,11 +32,11 @@ import { range, find } from 'vs/base/common/arrays';
|
||||
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { Disposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { Separator, ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { isInDOM, Dimension } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
@@ -24,7 +24,6 @@ import { TreeNodeContextKey } from 'sql/workbench/services/objectExplorer/common
|
||||
import { IQueryManagementService } from 'sql/workbench/services/query/common/queryManagement';
|
||||
import { ServerInfoContextKey } from 'sql/workbench/services/connection/common/serverInfoContextKey';
|
||||
import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { firstIndex, find } from 'vs/base/common/arrays';
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, IActionRunner, IActionViewItem } from 'vs/base/common/actions';
|
||||
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';
|
||||
|
||||
export interface IContextMenuEvent {
|
||||
@@ -16,15 +14,9 @@ export interface IContextMenuEvent {
|
||||
readonly metaKey?: boolean;
|
||||
}
|
||||
|
||||
export class ContextSubMenu extends SubmenuAction {
|
||||
constructor(label: string, public entries: Array<ContextSubMenu | IAction>) {
|
||||
super(label, entries, 'contextsubmenu');
|
||||
}
|
||||
}
|
||||
|
||||
export interface IContextMenuDelegate {
|
||||
getAnchor(): HTMLElement | { x: number; y: number; width?: number; height?: number; };
|
||||
getActions(): ReadonlyArray<IAction | ContextSubMenu>;
|
||||
getActions(): IAction[];
|
||||
getCheckedActionsRepresentation?(action: IAction): 'radio' | 'checkbox';
|
||||
getActionViewItem?(action: IAction): IActionViewItem | undefined;
|
||||
getActionsContext?(event?: IContextMenuEvent): any;
|
||||
@@ -36,3 +28,7 @@ export interface IContextMenuDelegate {
|
||||
anchorAlignment?: AnchorAlignment;
|
||||
domForShadowRoot?: HTMLElement;
|
||||
}
|
||||
|
||||
export interface IContextMenuProvider {
|
||||
showContextMenu(delegate: IContextMenuDelegate): void;
|
||||
}
|
||||
|
||||
406
src/vs/base/browser/ui/actionbar/actionViewItems.ts
Normal file
406
src/vs/base/browser/ui/actionbar/actionViewItems.ts
Normal file
@@ -0,0 +1,406 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./actionbar';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { SelectBox, ISelectOptionItem, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, Separator, IActionViewItem } from 'vs/base/common/actions';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { EventType, Gesture } from 'vs/base/browser/touch';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
|
||||
export interface IBaseActionViewItemOptions {
|
||||
draggable?: boolean;
|
||||
isMenu?: boolean;
|
||||
useEventAsContext?: boolean;
|
||||
}
|
||||
|
||||
export class BaseActionViewItem extends Disposable implements IActionViewItem {
|
||||
|
||||
element: HTMLElement | undefined;
|
||||
|
||||
_context: any;
|
||||
_action: IAction;
|
||||
|
||||
private _actionRunner: IActionRunner | undefined;
|
||||
|
||||
constructor(context: any, action: IAction, protected options: IBaseActionViewItemOptions = {}) {
|
||||
super();
|
||||
|
||||
this._context = context || this;
|
||||
this._action = action;
|
||||
|
||||
if (action instanceof Action) {
|
||||
this._register(action.onDidChange(event => {
|
||||
if (!this.element) {
|
||||
// we have not been rendered yet, so there
|
||||
// is no point in updating the UI
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleActionChangeEvent(event);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private handleActionChangeEvent(event: IActionChangeEvent): void {
|
||||
if (event.enabled !== undefined) {
|
||||
this.updateEnabled();
|
||||
}
|
||||
|
||||
if (event.checked !== undefined) {
|
||||
this.updateChecked();
|
||||
}
|
||||
|
||||
if (event.class !== undefined) {
|
||||
this.updateClass();
|
||||
}
|
||||
|
||||
if (event.label !== undefined) {
|
||||
this.updateLabel();
|
||||
this.updateTooltip();
|
||||
}
|
||||
|
||||
if (event.tooltip !== undefined) {
|
||||
this.updateTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
get actionRunner(): IActionRunner {
|
||||
if (!this._actionRunner) {
|
||||
this._actionRunner = this._register(new ActionRunner());
|
||||
}
|
||||
|
||||
return this._actionRunner;
|
||||
}
|
||||
|
||||
set actionRunner(actionRunner: IActionRunner) {
|
||||
this._actionRunner = actionRunner;
|
||||
}
|
||||
|
||||
getAction(): IAction {
|
||||
return this._action;
|
||||
}
|
||||
|
||||
isEnabled(): boolean {
|
||||
return this._action.enabled;
|
||||
}
|
||||
|
||||
setActionContext(newContext: unknown): void {
|
||||
this._context = newContext;
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
const element = this.element = container;
|
||||
this._register(Gesture.addTarget(container));
|
||||
|
||||
const enableDragging = this.options && this.options.draggable;
|
||||
if (enableDragging) {
|
||||
container.draggable = true;
|
||||
|
||||
if (isFirefox) {
|
||||
// Firefox: requires to set a text data transfer to get going
|
||||
this._register(DOM.addDisposableListener(container, DOM.EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
|
||||
}
|
||||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(element, EventType.Tap, e => this.onClick(e)));
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.MOUSE_DOWN, e => {
|
||||
if (!enableDragging) {
|
||||
DOM.EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
|
||||
}
|
||||
|
||||
if (this._action.enabled && e.button === 0) {
|
||||
DOM.addClass(element, 'active');
|
||||
}
|
||||
}));
|
||||
|
||||
if (platform.isMacintosh) {
|
||||
// macOS: allow to trigger the button when holding Ctrl+key and pressing the
|
||||
// main mouse button. This is for scenarios where e.g. some interaction forces
|
||||
// the Ctrl+key to be pressed and hold but the user still wants to interact
|
||||
// with the actions (for example quick access in quick navigation mode).
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.CONTEXT_MENU, e => {
|
||||
if (e.button === 0 && e.ctrlKey === true) {
|
||||
this.onClick(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, e => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
|
||||
// > Writing to the clipboard
|
||||
// > You can use the "cut" and "copy" commands without any special
|
||||
// permission if you are using them in a short-lived event handler
|
||||
// for a user action (for example, a click handler).
|
||||
|
||||
// => to get the Copy and Paste context menu actions working on Firefox,
|
||||
// there should be no timeout here
|
||||
if (this.options && this.options.isMenu) {
|
||||
this.onClick(e);
|
||||
} else {
|
||||
platform.setImmediate(() => this.onClick(e));
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.DBLCLICK, e => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
}));
|
||||
|
||||
[DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT].forEach(event => {
|
||||
this._register(DOM.addDisposableListener(element, event, e => {
|
||||
DOM.EventHelper.stop(e);
|
||||
DOM.removeClass(element, 'active');
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
onClick(event: DOM.EventLike): void {
|
||||
DOM.EventHelper.stop(event, true);
|
||||
|
||||
const context = types.isUndefinedOrNull(this._context) ? this.options?.useEventAsContext ? event : undefined : this._context;
|
||||
this.actionRunner.run(this._action, context);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.element) {
|
||||
this.element.focus();
|
||||
DOM.addClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (this.element) {
|
||||
this.element.blur();
|
||||
DOM.removeClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
protected updateEnabled(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateLabel(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateTooltip(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateClass(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateChecked(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.element) {
|
||||
DOM.removeNode(this.element);
|
||||
this.element = undefined;
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
|
||||
icon?: boolean;
|
||||
label?: boolean;
|
||||
keybinding?: string | null;
|
||||
}
|
||||
|
||||
export class ActionViewItem extends BaseActionViewItem {
|
||||
|
||||
protected label: HTMLElement | undefined;
|
||||
protected options: IActionViewItemOptions;
|
||||
|
||||
private cssClass?: string;
|
||||
|
||||
constructor(context: unknown, action: IAction, options: IActionViewItemOptions = {}) {
|
||||
super(context, action, options);
|
||||
|
||||
this.options = options;
|
||||
this.options.icon = options.icon !== undefined ? options.icon : false;
|
||||
this.options.label = options.label !== undefined ? options.label : true;
|
||||
this.cssClass = '';
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
super.render(container);
|
||||
|
||||
if (this.element) {
|
||||
this.label = DOM.append(this.element, DOM.$('a.action-label'));
|
||||
}
|
||||
|
||||
if (this.label) {
|
||||
if (this._action.id === Separator.ID) {
|
||||
this.label.setAttribute('role', 'presentation'); // A separator is a presentation item
|
||||
} else {
|
||||
if (this.options.isMenu) {
|
||||
this.label.setAttribute('role', 'menuitem');
|
||||
} else {
|
||||
this.label.setAttribute('role', 'button');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.label && this.options.keybinding && this.element) {
|
||||
DOM.append(this.element, DOM.$('span.keybinding')).textContent = this.options.keybinding;
|
||||
}
|
||||
|
||||
this.updateClass();
|
||||
this.updateLabel();
|
||||
this.updateTooltip();
|
||||
this.updateEnabled();
|
||||
this.updateChecked();
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
super.focus();
|
||||
|
||||
if (this.label) {
|
||||
this.label.focus();
|
||||
}
|
||||
}
|
||||
|
||||
updateLabel(): void {
|
||||
if (this.options.label && this.label) {
|
||||
this.label.textContent = this.getAction().label;
|
||||
}
|
||||
}
|
||||
|
||||
updateTooltip(): void {
|
||||
let title: string | null = null;
|
||||
|
||||
if (this.getAction().tooltip) {
|
||||
title = this.getAction().tooltip;
|
||||
|
||||
} else if (!this.options.label && this.getAction().label && this.options.icon) {
|
||||
title = this.getAction().label;
|
||||
|
||||
if (this.options.keybinding) {
|
||||
title = nls.localize({ key: 'titleLabel', comment: ['action title', 'action keybinding'] }, "{0} ({1})", title, this.options.keybinding);
|
||||
}
|
||||
}
|
||||
|
||||
if (title && this.label) {
|
||||
this.label.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
updateClass(): void {
|
||||
if (this.cssClass && this.label) {
|
||||
DOM.removeClasses(this.label, this.cssClass);
|
||||
}
|
||||
|
||||
if (this.options.icon) {
|
||||
this.cssClass = this.getAction().class;
|
||||
|
||||
if (this.label) {
|
||||
DOM.addClass(this.label, 'codicon');
|
||||
if (this.cssClass) {
|
||||
DOM.addClasses(this.label, this.cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateEnabled();
|
||||
} else {
|
||||
if (this.label) {
|
||||
DOM.removeClass(this.label, 'codicon');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
if (this.label) {
|
||||
this.label.removeAttribute('aria-disabled');
|
||||
DOM.removeClass(this.label, 'disabled');
|
||||
this.label.tabIndex = 0;
|
||||
}
|
||||
|
||||
if (this.element) {
|
||||
DOM.removeClass(this.element, 'disabled');
|
||||
}
|
||||
} else {
|
||||
if (this.label) {
|
||||
this.label.setAttribute('aria-disabled', 'true');
|
||||
DOM.addClass(this.label, 'disabled');
|
||||
DOM.removeTabIndexAndUpdateFocus(this.label);
|
||||
}
|
||||
|
||||
if (this.element) {
|
||||
DOM.addClass(this.element, 'disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateChecked(): void {
|
||||
if (this.label) {
|
||||
if (this.getAction().checked) {
|
||||
DOM.addClass(this.label, 'checked');
|
||||
} else {
|
||||
DOM.removeClass(this.label, 'checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectActionViewItem extends BaseActionViewItem {
|
||||
protected selectBox: SelectBox;
|
||||
|
||||
constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) {
|
||||
super(ctx, action);
|
||||
|
||||
this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
|
||||
|
||||
this._register(this.selectBox);
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
setOptions(options: ISelectOptionItem[], selected?: number): void {
|
||||
this.selectBox.setOptions(options, selected);
|
||||
}
|
||||
|
||||
select(index: number): void {
|
||||
this.selectBox.select(index);
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.selectBox.onDidSelect(e => {
|
||||
this.actionRunner.run(this._action, this.getActionContext(e.selected, e.index));
|
||||
}));
|
||||
}
|
||||
|
||||
protected getActionContext(option: string, index: number) {
|
||||
return option;
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.selectBox) {
|
||||
this.selectBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (this.selectBox) {
|
||||
this.selectBox.blur();
|
||||
}
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
this.selectBox.render(container);
|
||||
}
|
||||
}
|
||||
@@ -4,382 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./actionbar';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { SelectBox, ISelectOptionItem, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, IRunEvent } from 'vs/base/common/actions';
|
||||
import { Disposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IAction, IActionRunner, ActionRunner, IRunEvent, Separator, IActionViewItem, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { EventType, Gesture } from 'vs/base/browser/touch';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
|
||||
export interface IActionViewItem extends IDisposable {
|
||||
actionRunner: IActionRunner;
|
||||
setActionContext(context: any): void;
|
||||
render(element: HTMLElement): void;
|
||||
isEnabled(): boolean;
|
||||
focus(fromRight?: boolean): void;
|
||||
blur(): void;
|
||||
}
|
||||
|
||||
export interface IBaseActionViewItemOptions {
|
||||
draggable?: boolean;
|
||||
isMenu?: boolean;
|
||||
useEventAsContext?: boolean;
|
||||
}
|
||||
|
||||
export class BaseActionViewItem extends Disposable implements IActionViewItem {
|
||||
|
||||
element: HTMLElement | undefined;
|
||||
|
||||
_context: any;
|
||||
_action: IAction;
|
||||
|
||||
private _actionRunner: IActionRunner | undefined;
|
||||
|
||||
constructor(context: any, action: IAction, protected options?: IBaseActionViewItemOptions) {
|
||||
super();
|
||||
|
||||
this._context = context || this;
|
||||
this._action = action;
|
||||
|
||||
if (action instanceof Action) {
|
||||
this._register(action.onDidChange(event => {
|
||||
if (!this.element) {
|
||||
// we have not been rendered yet, so there
|
||||
// is no point in updating the UI
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleActionChangeEvent(event);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private handleActionChangeEvent(event: IActionChangeEvent): void {
|
||||
if (event.enabled !== undefined) {
|
||||
this.updateEnabled();
|
||||
}
|
||||
|
||||
if (event.checked !== undefined) {
|
||||
this.updateChecked();
|
||||
}
|
||||
|
||||
if (event.class !== undefined) {
|
||||
this.updateClass();
|
||||
}
|
||||
|
||||
if (event.label !== undefined) {
|
||||
this.updateLabel();
|
||||
this.updateTooltip();
|
||||
}
|
||||
|
||||
if (event.tooltip !== undefined) {
|
||||
this.updateTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
get actionRunner(): IActionRunner {
|
||||
if (!this._actionRunner) {
|
||||
this._actionRunner = this._register(new ActionRunner());
|
||||
}
|
||||
|
||||
return this._actionRunner;
|
||||
}
|
||||
|
||||
set actionRunner(actionRunner: IActionRunner) {
|
||||
this._actionRunner = actionRunner;
|
||||
}
|
||||
|
||||
getAction(): IAction {
|
||||
return this._action;
|
||||
}
|
||||
|
||||
isEnabled(): boolean {
|
||||
return this._action.enabled;
|
||||
}
|
||||
|
||||
setActionContext(newContext: unknown): void {
|
||||
this._context = newContext;
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
const element = this.element = container;
|
||||
this._register(Gesture.addTarget(container));
|
||||
|
||||
const enableDragging = this.options && this.options.draggable;
|
||||
if (enableDragging) {
|
||||
container.draggable = true;
|
||||
|
||||
if (isFirefox) {
|
||||
// Firefox: requires to set a text data transfer to get going
|
||||
this._register(DOM.addDisposableListener(container, DOM.EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
|
||||
}
|
||||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(element, EventType.Tap, e => this.onClick(e)));
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.MOUSE_DOWN, e => {
|
||||
if (!enableDragging) {
|
||||
DOM.EventHelper.stop(e, true); // do not run when dragging is on because that would disable it
|
||||
}
|
||||
|
||||
if (this._action.enabled && e.button === 0) {
|
||||
DOM.addClass(element, 'active');
|
||||
}
|
||||
}));
|
||||
|
||||
if (platform.isMacintosh) {
|
||||
// macOS: allow to trigger the button when holding Ctrl+key and pressing the
|
||||
// main mouse button. This is for scenarios where e.g. some interaction forces
|
||||
// the Ctrl+key to be pressed and hold but the user still wants to interact
|
||||
// with the actions (for example quick access in quick navigation mode).
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.CONTEXT_MENU, e => {
|
||||
if (e.button === 0 && e.ctrlKey === true) {
|
||||
this.onClick(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.CLICK, e => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
|
||||
// > Writing to the clipboard
|
||||
// > You can use the "cut" and "copy" commands without any special
|
||||
// permission if you are using them in a short-lived event handler
|
||||
// for a user action (for example, a click handler).
|
||||
|
||||
// => to get the Copy and Paste context menu actions working on Firefox,
|
||||
// there should be no timeout here
|
||||
if (this.options && this.options.isMenu) {
|
||||
this.onClick(e);
|
||||
} else {
|
||||
platform.setImmediate(() => this.onClick(e));
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(DOM.addDisposableListener(element, DOM.EventType.DBLCLICK, e => {
|
||||
DOM.EventHelper.stop(e, true);
|
||||
}));
|
||||
|
||||
[DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT].forEach(event => {
|
||||
this._register(DOM.addDisposableListener(element, event, e => {
|
||||
DOM.EventHelper.stop(e);
|
||||
DOM.removeClass(element, 'active');
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
onClick(event: DOM.EventLike): void {
|
||||
DOM.EventHelper.stop(event, true);
|
||||
|
||||
const context = types.isUndefinedOrNull(this._context) ? this.options?.useEventAsContext ? event : undefined : this._context;
|
||||
this.actionRunner.run(this._action, context);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.element) {
|
||||
this.element.focus();
|
||||
DOM.addClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (this.element) {
|
||||
this.element.blur();
|
||||
DOM.removeClass(this.element, 'focused');
|
||||
}
|
||||
}
|
||||
|
||||
protected updateEnabled(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateLabel(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateTooltip(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateClass(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
protected updateChecked(): void {
|
||||
// implement in subclass
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (this.element) {
|
||||
DOM.removeNode(this.element);
|
||||
this.element = undefined;
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class Separator extends Action {
|
||||
|
||||
static readonly ID = 'vs.actions.separator';
|
||||
|
||||
constructor(label?: string) {
|
||||
super(Separator.ID, label, label ? 'separator text' : 'separator');
|
||||
this.checked = false;
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
|
||||
icon?: boolean;
|
||||
label?: boolean;
|
||||
keybinding?: string | null;
|
||||
}
|
||||
|
||||
export class ActionViewItem extends BaseActionViewItem {
|
||||
|
||||
protected label: HTMLElement | undefined;
|
||||
protected options: IActionViewItemOptions;
|
||||
|
||||
private cssClass?: string;
|
||||
|
||||
constructor(context: unknown, action: IAction, options: IActionViewItemOptions = {}) {
|
||||
super(context, action, options);
|
||||
|
||||
this.options = options;
|
||||
this.options.icon = options.icon !== undefined ? options.icon : false;
|
||||
this.options.label = options.label !== undefined ? options.label : true;
|
||||
this.cssClass = '';
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
super.render(container);
|
||||
|
||||
if (this.element) {
|
||||
this.label = DOM.append(this.element, DOM.$('a.action-label'));
|
||||
}
|
||||
|
||||
if (this.label) {
|
||||
if (this._action.id === Separator.ID) {
|
||||
this.label.setAttribute('role', 'presentation'); // A separator is a presentation item
|
||||
} else {
|
||||
if (this.options.isMenu) {
|
||||
this.label.setAttribute('role', 'menuitem');
|
||||
} else {
|
||||
this.label.setAttribute('role', 'button');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.label && this.options.keybinding && this.element) {
|
||||
DOM.append(this.element, DOM.$('span.keybinding')).textContent = this.options.keybinding;
|
||||
}
|
||||
|
||||
this.updateClass();
|
||||
this.updateLabel();
|
||||
this.updateTooltip();
|
||||
this.updateEnabled();
|
||||
this.updateChecked();
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
super.focus();
|
||||
|
||||
if (this.label) {
|
||||
this.label.focus();
|
||||
}
|
||||
}
|
||||
|
||||
updateLabel(): void {
|
||||
if (this.options.label && this.label) {
|
||||
this.label.textContent = this.getAction().label;
|
||||
}
|
||||
}
|
||||
|
||||
updateTooltip(): void {
|
||||
let title: string | null = null;
|
||||
|
||||
if (this.getAction().tooltip) {
|
||||
title = this.getAction().tooltip;
|
||||
|
||||
} else if (!this.options.label && this.getAction().label && this.options.icon) {
|
||||
title = this.getAction().label;
|
||||
|
||||
if (this.options.keybinding) {
|
||||
title = nls.localize({ key: 'titleLabel', comment: ['action title', 'action keybinding'] }, "{0} ({1})", title, this.options.keybinding);
|
||||
}
|
||||
}
|
||||
|
||||
if (title && this.label) {
|
||||
this.label.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
updateClass(): void {
|
||||
if (this.cssClass && this.label) {
|
||||
DOM.removeClasses(this.label, this.cssClass);
|
||||
}
|
||||
|
||||
if (this.options.icon) {
|
||||
this.cssClass = this.getAction().class;
|
||||
|
||||
if (this.label) {
|
||||
DOM.addClass(this.label, 'codicon');
|
||||
if (this.cssClass) {
|
||||
DOM.addClasses(this.label, this.cssClass);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateEnabled();
|
||||
} else {
|
||||
if (this.label) {
|
||||
DOM.removeClass(this.label, 'codicon');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateEnabled(): void {
|
||||
if (this.getAction().enabled) {
|
||||
if (this.label) {
|
||||
this.label.removeAttribute('aria-disabled');
|
||||
DOM.removeClass(this.label, 'disabled');
|
||||
this.label.tabIndex = 0;
|
||||
}
|
||||
|
||||
if (this.element) {
|
||||
DOM.removeClass(this.element, 'disabled');
|
||||
}
|
||||
} else {
|
||||
if (this.label) {
|
||||
this.label.setAttribute('aria-disabled', 'true');
|
||||
DOM.addClass(this.label, 'disabled');
|
||||
DOM.removeTabIndexAndUpdateFocus(this.label);
|
||||
}
|
||||
|
||||
if (this.element) {
|
||||
DOM.addClass(this.element, 'disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateChecked(): void {
|
||||
if (this.label) {
|
||||
if (this.getAction().checked) {
|
||||
DOM.addClass(this.label, 'checked');
|
||||
} else {
|
||||
DOM.removeClass(this.label, 'checked');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import { IActionViewItemOptions, ActionViewItem, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export const enum ActionsOrientation {
|
||||
HORIZONTAL,
|
||||
@@ -393,41 +25,30 @@ export interface ActionTrigger {
|
||||
keyDown: boolean;
|
||||
}
|
||||
|
||||
export interface IActionViewItemProvider {
|
||||
(action: IAction): IActionViewItem | undefined;
|
||||
}
|
||||
|
||||
export interface IActionBarOptions {
|
||||
orientation?: ActionsOrientation;
|
||||
context?: any;
|
||||
actionViewItemProvider?: IActionViewItemProvider;
|
||||
actionRunner?: IActionRunner;
|
||||
ariaLabel?: string;
|
||||
animated?: boolean;
|
||||
triggerKeys?: ActionTrigger;
|
||||
allowContextMenu?: boolean;
|
||||
preventLoopNavigation?: boolean;
|
||||
readonly orientation?: ActionsOrientation;
|
||||
readonly context?: any;
|
||||
readonly actionViewItemProvider?: IActionViewItemProvider;
|
||||
readonly actionRunner?: IActionRunner;
|
||||
readonly ariaLabel?: string;
|
||||
readonly animated?: boolean;
|
||||
readonly triggerKeys?: ActionTrigger;
|
||||
readonly allowContextMenu?: boolean;
|
||||
readonly preventLoopNavigation?: boolean;
|
||||
}
|
||||
|
||||
const defaultOptions: IActionBarOptions = {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
context: null,
|
||||
triggerKeys: {
|
||||
keys: [KeyCode.Enter, KeyCode.Space],
|
||||
keyDown: false
|
||||
}
|
||||
};
|
||||
|
||||
export interface IActionOptions extends IActionViewItemOptions {
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
options: IActionBarOptions;
|
||||
private readonly options: IActionBarOptions;
|
||||
|
||||
private _actionRunner: IActionRunner;
|
||||
private _context: unknown;
|
||||
private _orientation: ActionsOrientation;
|
||||
private _triggerKeys: ActionTrigger;
|
||||
|
||||
// View Items
|
||||
viewItems: IActionViewItem[];
|
||||
@@ -450,15 +71,16 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
private _onDidBeforeRun = this._register(new Emitter<IRunEvent>());
|
||||
readonly onDidBeforeRun: Event<IRunEvent> = this._onDidBeforeRun.event;
|
||||
|
||||
constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) {
|
||||
constructor(container: HTMLElement, options: IActionBarOptions = {}) {
|
||||
super();
|
||||
|
||||
this.options = options;
|
||||
this._context = options.context;
|
||||
|
||||
if (!this.options.triggerKeys) {
|
||||
this.options.triggerKeys = defaultOptions.triggerKeys;
|
||||
}
|
||||
this._context = options.context ?? null;
|
||||
this._orientation = this.options.orientation ?? ActionsOrientation.HORIZONTAL;
|
||||
this._triggerKeys = this.options.triggerKeys ?? {
|
||||
keys: [KeyCode.Enter, KeyCode.Space],
|
||||
keyDown: false
|
||||
};
|
||||
|
||||
if (this.options.actionRunner) {
|
||||
this._actionRunner = this.options.actionRunner;
|
||||
@@ -483,7 +105,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
let previousKey: KeyCode;
|
||||
let nextKey: KeyCode;
|
||||
|
||||
switch (this.options.orientation) {
|
||||
switch (this._orientation) {
|
||||
case ActionsOrientation.HORIZONTAL:
|
||||
previousKey = KeyCode.LeftArrow;
|
||||
nextKey = KeyCode.RightArrow;
|
||||
@@ -517,7 +139,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
this._onDidCancel.fire();
|
||||
} else if (this.isTriggerKeyEvent(event)) {
|
||||
// Staying out of the else branch even if not triggered
|
||||
if (this.options.triggerKeys && this.options.triggerKeys.keyDown) {
|
||||
if (this._triggerKeys.keyDown) {
|
||||
this.doTrigger(event);
|
||||
}
|
||||
} else {
|
||||
@@ -535,7 +157,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
// Run action on Enter/Space
|
||||
if (this.isTriggerKeyEvent(event)) {
|
||||
if (this.options.triggerKeys && !this.options.triggerKeys.keyDown) {
|
||||
if (!this._triggerKeys.keyDown) {
|
||||
this.doTrigger(event);
|
||||
}
|
||||
|
||||
@@ -582,11 +204,9 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
private isTriggerKeyEvent(event: StandardKeyboardEvent): boolean {
|
||||
let ret = false;
|
||||
if (this.options.triggerKeys) {
|
||||
this.options.triggerKeys.keys.forEach(keyCode => {
|
||||
ret = ret || event.equals(keyCode);
|
||||
});
|
||||
}
|
||||
this._triggerKeys.keys.forEach(keyCode => {
|
||||
ret = ret || event.equals(keyCode);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -845,53 +465,6 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectActionViewItem extends BaseActionViewItem {
|
||||
protected selectBox: SelectBox;
|
||||
|
||||
constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) {
|
||||
super(ctx, action);
|
||||
|
||||
this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
|
||||
|
||||
this._register(this.selectBox);
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
setOptions(options: ISelectOptionItem[], selected?: number): void {
|
||||
this.selectBox.setOptions(options, selected);
|
||||
}
|
||||
|
||||
select(index: number): void {
|
||||
this.selectBox.select(index);
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.selectBox.onDidSelect(e => {
|
||||
this.actionRunner.run(this._action, this.getActionContext(e.selected, e.index));
|
||||
}));
|
||||
}
|
||||
|
||||
protected getActionContext(option: string, index: number) {
|
||||
return option;
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.selectBox) {
|
||||
this.selectBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
blur(): void {
|
||||
if (this.selectBox) {
|
||||
this.selectBox.blur();
|
||||
}
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
this.selectBox.render(container);
|
||||
}
|
||||
}
|
||||
|
||||
export function prepareActions(actions: IAction[]): IAction[] {
|
||||
if (!actions.length) {
|
||||
return actions;
|
||||
|
||||
@@ -10,9 +10,9 @@ import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export interface ICheckboxOpts extends ICheckboxStyles {
|
||||
readonly actionClassName?: string;
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
|
||||
import 'vs/css!./dropdown';
|
||||
import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch';
|
||||
import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { BaseActionViewItem, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionRunner, IAction } from 'vs/base/common/actions';
|
||||
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';
|
||||
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { EventHelper, EventType, removeClass, addClass, append, $, addDisposableListener, addClasses, DOMEvent } from 'vs/base/browser/dom';
|
||||
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { EventHelper, EventType, removeClass, addClass, append, $, addDisposableListener, DOMEvent } from 'vs/base/browser/dom';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
@@ -201,17 +200,13 @@ export class Dropdown extends BaseDropdown {
|
||||
}
|
||||
}
|
||||
|
||||
export interface IContextMenuProvider {
|
||||
showContextMenu(delegate: IContextMenuDelegate): void;
|
||||
}
|
||||
|
||||
export interface IActionProvider {
|
||||
getActions(): ReadonlyArray<IAction>;
|
||||
getActions(): IAction[];
|
||||
}
|
||||
|
||||
export interface IDropdownMenuOptions extends IBaseDropdownOptions {
|
||||
contextMenuProvider: IContextMenuProvider;
|
||||
actions?: ReadonlyArray<IAction>;
|
||||
actions?: IAction[];
|
||||
actionProvider?: IActionProvider;
|
||||
menuClassName?: string;
|
||||
menuAsChild?: boolean; // scope down for #99448
|
||||
@@ -220,7 +215,7 @@ export interface IDropdownMenuOptions extends IBaseDropdownOptions {
|
||||
export class DropdownMenu extends BaseDropdown {
|
||||
private _contextMenuProvider: IContextMenuProvider;
|
||||
private _menuOptions: IMenuOptions | undefined;
|
||||
private _actions: ReadonlyArray<IAction> = [];
|
||||
private _actions: IAction[] = [];
|
||||
private actionProvider?: IActionProvider;
|
||||
private menuClassName: string;
|
||||
private menuAsChild?: boolean;
|
||||
@@ -243,7 +238,7 @@ export class DropdownMenu extends BaseDropdown {
|
||||
return this._menuOptions;
|
||||
}
|
||||
|
||||
private get actions(): ReadonlyArray<IAction> {
|
||||
private get actions(): IAction[] {
|
||||
if (this.actionProvider) {
|
||||
return this.actionProvider.getActions();
|
||||
}
|
||||
@@ -251,7 +246,7 @@ export class DropdownMenu extends BaseDropdown {
|
||||
return this._actions;
|
||||
}
|
||||
|
||||
private set actions(actions: ReadonlyArray<IAction>) {
|
||||
private set actions(actions: IAction[]) {
|
||||
this._actions = actions;
|
||||
}
|
||||
|
||||
@@ -283,106 +278,3 @@ export class DropdownMenu extends BaseDropdown {
|
||||
removeClass(this.element, 'active');
|
||||
}
|
||||
}
|
||||
|
||||
export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
private menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider;
|
||||
private dropdownMenu: DropdownMenu | undefined;
|
||||
private contextMenuProvider: IContextMenuProvider;
|
||||
private actionViewItemProvider?: IActionViewItemProvider;
|
||||
private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
|
||||
private clazz: string | undefined;
|
||||
private anchorAlignmentProvider: (() => AnchorAlignment) | undefined;
|
||||
private menuAsChild?: boolean;
|
||||
|
||||
private _onDidChangeVisibility = this._register(new Emitter<boolean>());
|
||||
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
|
||||
|
||||
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
|
||||
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
|
||||
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner | undefined, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean) {
|
||||
super(null, action);
|
||||
|
||||
this.menuActionsOrProvider = menuActionsOrProvider;
|
||||
this.contextMenuProvider = contextMenuProvider;
|
||||
this.actionViewItemProvider = actionViewItemProvider;
|
||||
if (actionRunner) {
|
||||
this.actionRunner = actionRunner;
|
||||
}
|
||||
this.keybindings = keybindings;
|
||||
this.clazz = clazz;
|
||||
this.anchorAlignmentProvider = anchorAlignmentProvider;
|
||||
this.menuAsChild = menuAsChild;
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
|
||||
this.element = append(el, $('a.action-label.codicon')); // todo@aeschli: remove codicon, should come through `this.clazz`
|
||||
if (this.clazz) {
|
||||
addClasses(this.element, this.clazz);
|
||||
}
|
||||
|
||||
this.element.tabIndex = 0;
|
||||
this.element.setAttribute('role', 'button');
|
||||
this.element.setAttribute('aria-haspopup', 'true');
|
||||
this.element.setAttribute('aria-expanded', 'false');
|
||||
this.element.title = this._action.label || '';
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const options: IDropdownMenuOptions = {
|
||||
contextMenuProvider: this.contextMenuProvider,
|
||||
labelRenderer: labelRenderer,
|
||||
menuAsChild: this.menuAsChild
|
||||
};
|
||||
|
||||
// Render the DropdownMenu around a simple action to toggle it
|
||||
if (Array.isArray(this.menuActionsOrProvider)) {
|
||||
options.actions = this.menuActionsOrProvider;
|
||||
} else {
|
||||
options.actionProvider = this.menuActionsOrProvider as IActionProvider;
|
||||
}
|
||||
|
||||
this.dropdownMenu = this._register(new DropdownMenu(container, options));
|
||||
this._register(this.dropdownMenu.onDidChangeVisibility(visible => {
|
||||
this.element?.setAttribute('aria-expanded', `${visible}`);
|
||||
this._onDidChangeVisibility.fire(visible);
|
||||
}));
|
||||
|
||||
this.dropdownMenu.menuOptions = {
|
||||
actionViewItemProvider: this.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
getKeyBinding: this.keybindings,
|
||||
context: this._context
|
||||
};
|
||||
|
||||
if (this.anchorAlignmentProvider) {
|
||||
const that = this;
|
||||
|
||||
this.dropdownMenu.menuOptions = {
|
||||
...this.dropdownMenu.menuOptions,
|
||||
get anchorAlignment(): AnchorAlignment {
|
||||
return that.anchorAlignmentProvider!();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
setActionContext(newContext: unknown): void {
|
||||
super.setActionContext(newContext);
|
||||
|
||||
if (this.dropdownMenu) {
|
||||
if (this.dropdownMenu.menuOptions) {
|
||||
this.dropdownMenu.menuOptions.context = newContext;
|
||||
} else {
|
||||
this.dropdownMenu.menuOptions = { context: newContext };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show(): void {
|
||||
if (this.dropdownMenu) {
|
||||
this.dropdownMenu.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
136
src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts
Normal file
136
src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./dropdown';
|
||||
import { IAction, IActionRunner, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { append, $, addClasses } from 'vs/base/browser/dom';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { BaseActionViewItem, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
|
||||
export interface IKeybindingProvider {
|
||||
(action: IAction): ResolvedKeybinding | undefined;
|
||||
}
|
||||
|
||||
export interface IAnchorAlignmentProvider {
|
||||
(): AnchorAlignment;
|
||||
}
|
||||
|
||||
export interface IDropdownMenuActionViewItemOptions extends IBaseActionViewItemOptions {
|
||||
readonly actionViewItemProvider?: IActionViewItemProvider;
|
||||
readonly keybindingProvider?: IKeybindingProvider;
|
||||
readonly actionRunner?: IActionRunner;
|
||||
readonly classNames?: string[] | string;
|
||||
readonly anchorAlignmentProvider?: IAnchorAlignmentProvider;
|
||||
readonly menuAsChild?: boolean;
|
||||
}
|
||||
|
||||
export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
private menuActionsOrProvider: readonly IAction[] | IActionProvider;
|
||||
private dropdownMenu: DropdownMenu | undefined;
|
||||
private contextMenuProvider: IContextMenuProvider;
|
||||
|
||||
private _onDidChangeVisibility = this._register(new Emitter<boolean>());
|
||||
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
|
||||
|
||||
constructor(
|
||||
action: IAction,
|
||||
menuActionsOrProvider: readonly IAction[] | IActionProvider,
|
||||
contextMenuProvider: IContextMenuProvider,
|
||||
protected options: IDropdownMenuActionViewItemOptions = {}
|
||||
) {
|
||||
super(null, action, options);
|
||||
|
||||
this.menuActionsOrProvider = menuActionsOrProvider;
|
||||
this.contextMenuProvider = contextMenuProvider;
|
||||
|
||||
if (this.options.actionRunner) {
|
||||
this.actionRunner = this.options.actionRunner;
|
||||
}
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
|
||||
this.element = append(el, $('a.action-label'));
|
||||
|
||||
const classNames = this.options.classNames ? asArray(this.options.classNames) : [];
|
||||
|
||||
// todo@aeschli: remove codicon, should come through `this.options.classNames`
|
||||
if (!classNames.find(c => c === 'icon')) {
|
||||
classNames.push('codicon');
|
||||
}
|
||||
|
||||
addClasses(this.element, ...classNames);
|
||||
|
||||
this.element.tabIndex = 0;
|
||||
this.element.setAttribute('role', 'button');
|
||||
this.element.setAttribute('aria-haspopup', 'true');
|
||||
this.element.setAttribute('aria-expanded', 'false');
|
||||
this.element.title = this._action.label || '';
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const options: IDropdownMenuOptions = {
|
||||
contextMenuProvider: this.contextMenuProvider,
|
||||
labelRenderer: labelRenderer,
|
||||
menuAsChild: this.options.menuAsChild
|
||||
};
|
||||
|
||||
// Render the DropdownMenu around a simple action to toggle it
|
||||
if (Array.isArray(this.menuActionsOrProvider)) {
|
||||
options.actions = this.menuActionsOrProvider;
|
||||
} else {
|
||||
options.actionProvider = this.menuActionsOrProvider as IActionProvider;
|
||||
}
|
||||
|
||||
this.dropdownMenu = this._register(new DropdownMenu(container, options));
|
||||
this._register(this.dropdownMenu.onDidChangeVisibility(visible => {
|
||||
this.element?.setAttribute('aria-expanded', `${visible}`);
|
||||
this._onDidChangeVisibility.fire(visible);
|
||||
}));
|
||||
|
||||
this.dropdownMenu.menuOptions = {
|
||||
actionViewItemProvider: this.options.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
getKeyBinding: this.options.keybindingProvider,
|
||||
context: this._context
|
||||
};
|
||||
|
||||
if (this.options.anchorAlignmentProvider) {
|
||||
const that = this;
|
||||
|
||||
this.dropdownMenu.menuOptions = {
|
||||
...this.dropdownMenu.menuOptions,
|
||||
get anchorAlignment(): AnchorAlignment {
|
||||
return that.options.anchorAlignmentProvider!();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
setActionContext(newContext: unknown): void {
|
||||
super.setActionContext(newContext);
|
||||
|
||||
if (this.dropdownMenu) {
|
||||
if (this.dropdownMenu.menuOptions) {
|
||||
this.dropdownMenu.menuOptions.context = newContext;
|
||||
} else {
|
||||
this.dropdownMenu.menuOptions = { context: newContext };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show(): void {
|
||||
if (this.dropdownMenu) {
|
||||
this.dropdownMenu.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
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, IActionViewItemProvider, ActionsOrientation, Separator, ActionViewItem, IActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IActionRunner, IAction, SubmenuAction, Separator, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } 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, clearNode, createStyleSheet, isInShadowDOM } from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -19,6 +19,7 @@ import { Event } from 'vs/base/common/event';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { Codicon, registerIcon, stripCodicons } from 'vs/base/common/codicons';
|
||||
import { BaseActionViewItem, ActionViewItem, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { formatRule } from 'vs/base/browser/ui/codicons/codiconStyles';
|
||||
|
||||
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
|
||||
@@ -42,6 +43,7 @@ export interface IMenuOptions {
|
||||
anchorAlignment?: AnchorAlignment;
|
||||
expandDirection?: Direction;
|
||||
useEventAsContext?: boolean;
|
||||
submenuIds?: Set<string>;
|
||||
}
|
||||
|
||||
export interface IMenuStyles {
|
||||
@@ -55,12 +57,6 @@ export interface IMenuStyles {
|
||||
separatorColor?: Color;
|
||||
}
|
||||
|
||||
export class SubmenuAction extends Action {
|
||||
constructor(label: string, public entries: ReadonlyArray<SubmenuAction | IAction>, cssClass?: string) {
|
||||
super(!!cssClass ? cssClass : 'submenu', label, '', true);
|
||||
}
|
||||
}
|
||||
|
||||
interface ISubMenuData {
|
||||
parent: Menu;
|
||||
submenu?: Menu;
|
||||
@@ -209,6 +205,15 @@ export class Menu extends ActionBar {
|
||||
|
||||
menuElement.style.maxHeight = `${Math.max(10, window.innerHeight - container.getBoundingClientRect().top - 30)}px`;
|
||||
|
||||
actions = actions.filter(a => {
|
||||
if (options.submenuIds?.has(a.id)) {
|
||||
console.warn(`Found submenu cycle: ${a.id}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.push(actions, { icon: true, label: true, isMenu: true });
|
||||
|
||||
container.appendChild(this.scrollableElement.getDomNode());
|
||||
@@ -317,7 +322,8 @@ export class Menu extends ActionBar {
|
||||
if (action instanceof Separator) {
|
||||
return new MenuSeparatorActionViewItem(options.context, action, { icon: true });
|
||||
} else if (action instanceof SubmenuAction) {
|
||||
const menuActionViewItem = new SubmenuMenuActionViewItem(action, action.entries, parentData, options);
|
||||
const actions = Array.isArray(action.actions) ? action.actions : action.actions();
|
||||
const menuActionViewItem = new SubmenuMenuActionViewItem(action, actions, parentData, { ...options, submenuIds: new Set([...(options.submenuIds || []), action.id]) });
|
||||
|
||||
if (options.enableMnemonics) {
|
||||
const mnemonic = menuActionViewItem.getMnemonic();
|
||||
|
||||
@@ -11,8 +11,8 @@ import * as nls from 'vs/nls';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { cleanMnemonic, IMenuOptions, Menu, MENU_ESCAPED_MNEMONIC_REGEX, MENU_MNEMONIC_REGEX, SubmenuAction, IMenuStyles, Direction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { cleanMnemonic, IMenuOptions, Menu, MENU_ESCAPED_MNEMONIC_REGEX, MENU_MNEMONIC_REGEX, IMenuStyles, Direction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { ActionRunner, IAction, IActionRunner, SubmenuAction, Separator } from 'vs/base/common/actions';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { KeyCode, ResolvedKeybinding, KeyMod } from 'vs/base/common/keyCodes';
|
||||
@@ -22,7 +22,6 @@ import { asArray } from 'vs/base/common/arrays';
|
||||
import { ScanCodeUtils, ScanCode } from 'vs/base/common/scanCode';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Codicon, registerIcon } from 'vs/base/common/codicons';
|
||||
|
||||
const $ = DOM.$;
|
||||
@@ -40,7 +39,7 @@ export interface IMenuBarOptions {
|
||||
}
|
||||
|
||||
export interface MenuBarMenu {
|
||||
actions: ReadonlyArray<IAction>;
|
||||
actions: IAction[];
|
||||
label: string;
|
||||
}
|
||||
|
||||
@@ -59,7 +58,7 @@ export class MenuBar extends Disposable {
|
||||
buttonElement: HTMLElement;
|
||||
titleElement: HTMLElement;
|
||||
label: string;
|
||||
actions?: ReadonlyArray<IAction>;
|
||||
actions?: IAction[];
|
||||
}[];
|
||||
|
||||
private overflowMenu!: {
|
||||
@@ -506,7 +505,7 @@ export class MenuBar extends Disposable {
|
||||
|
||||
this.overflowMenu.actions = [];
|
||||
for (let idx = this.numMenusShown; idx < this.menuCache.length; idx++) {
|
||||
this.overflowMenu.actions.push(new SubmenuAction(this.menuCache[idx].label, this.menuCache[idx].actions || []));
|
||||
this.overflowMenu.actions.push(new SubmenuAction(`menubar.submenu.${this.menuCache[idx].label}`, this.menuCache[idx].label, this.menuCache[idx].actions || []));
|
||||
}
|
||||
|
||||
if (this.overflowMenu.buttonElement.nextElementSibling !== this.menuCache[this.numMenusShown].buttonElement) {
|
||||
|
||||
@@ -5,17 +5,16 @@
|
||||
|
||||
import 'vs/css!./toolbar';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action, IActionRunner, IAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuProvider, DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { Action, IActionRunner, IAction, IActionViewItemProvider, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { Codicon, registerIcon } from 'vs/base/common/codicons';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export const CONTEXT = 'context.toolbar';
|
||||
import { EventMultiplexer } from 'vs/base/common/event';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
||||
|
||||
const toolBarMoreIcon = registerIcon('toolbar-more', Codicon.more);
|
||||
|
||||
@@ -37,12 +36,13 @@ export class ToolBar extends Disposable {
|
||||
private actionBar: ActionBar;
|
||||
private toggleMenuAction: ToggleMenuAction;
|
||||
private toggleMenuActionViewItem: DropdownMenuActionViewItem | undefined;
|
||||
private toggleMenuActionViewItemDisposable: IDisposable = Disposable.None;
|
||||
private submenuActionViewItems: DropdownMenuActionViewItem[] = [];
|
||||
private hasSecondaryActions: boolean = false;
|
||||
private lookupKeybindings: boolean;
|
||||
|
||||
private _onDidChangeDropdownVisibility = this._register(new Emitter<boolean>());
|
||||
private _onDidChangeDropdownVisibility = this._register(new EventMultiplexer<boolean>());
|
||||
readonly onDidChangeDropdownVisibility = this._onDidChangeDropdownVisibility.event;
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) {
|
||||
super();
|
||||
@@ -61,35 +61,57 @@ export class ToolBar extends Disposable {
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionRunner: options.actionRunner,
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
|
||||
// Return special action item for the toggle menu action
|
||||
if (action.id === ToggleMenuAction.ID) {
|
||||
|
||||
this.toggleMenuActionViewItemDisposable.dispose();
|
||||
|
||||
// Create new
|
||||
this.toggleMenuActionViewItem = new DropdownMenuActionViewItem(
|
||||
action,
|
||||
(<ToggleMenuAction>action).menuActions,
|
||||
contextMenuProvider,
|
||||
this.options.actionViewItemProvider,
|
||||
this.actionRunner,
|
||||
this.options.getKeyBinding,
|
||||
toolBarMoreIcon.classNames,
|
||||
this.options.anchorAlignmentProvider,
|
||||
true
|
||||
{
|
||||
actionViewItemProvider: this.options.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
keybindingProvider: this.options.getKeyBinding,
|
||||
classNames: toolBarMoreIcon.classNames,
|
||||
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
|
||||
menuAsChild: true
|
||||
}
|
||||
);
|
||||
this.toggleMenuActionViewItem.setActionContext(this.actionBar.context);
|
||||
|
||||
this.toggleMenuActionViewItemDisposable = combinedDisposable(
|
||||
this.toggleMenuActionViewItem,
|
||||
this.toggleMenuActionViewItem.onDidChangeVisibility(e => this._onDidChangeDropdownVisibility.fire(e))
|
||||
);
|
||||
this.disposables.add(this._onDidChangeDropdownVisibility.add(this.toggleMenuActionViewItem.onDidChangeVisibility));
|
||||
|
||||
return this.toggleMenuActionViewItem;
|
||||
}
|
||||
|
||||
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
|
||||
if (options.actionViewItemProvider) {
|
||||
const result = options.actionViewItemProvider(action);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (action instanceof SubmenuAction) {
|
||||
const actions = Array.isArray(action.actions) ? action.actions : action.actions();
|
||||
const result = new DropdownMenuActionViewItem(
|
||||
action,
|
||||
actions,
|
||||
contextMenuProvider,
|
||||
{
|
||||
actionViewItemProvider: this.options.actionViewItemProvider,
|
||||
actionRunner: this.actionRunner,
|
||||
keybindingProvider: this.options.getKeyBinding,
|
||||
classNames: action.class,
|
||||
anchorAlignmentProvider: this.options.anchorAlignmentProvider,
|
||||
menuAsChild: true
|
||||
}
|
||||
);
|
||||
result.setActionContext(this.actionBar.context);
|
||||
this.submenuActionViewItems.push(result);
|
||||
this.disposables.add(this._onDidChangeDropdownVisibility.add(result.onDidChangeVisibility));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -107,6 +129,9 @@ export class ToolBar extends Disposable {
|
||||
if (this.toggleMenuActionViewItem) {
|
||||
this.toggleMenuActionViewItem.setActionContext(context);
|
||||
}
|
||||
for (const actionViewItem of this.submenuActionViewItems) {
|
||||
actionViewItem.setActionContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
getContainer(): HTMLElement {
|
||||
@@ -126,6 +151,8 @@ export class ToolBar extends Disposable {
|
||||
}
|
||||
|
||||
setActions(primaryActions: ReadonlyArray<IAction>, secondaryActions?: ReadonlyArray<IAction>): void {
|
||||
this.clear();
|
||||
|
||||
let primaryActionsToSet = primaryActions ? primaryActions.slice(0) : [];
|
||||
|
||||
// Inject additional action to open secondary actions if present
|
||||
@@ -135,8 +162,6 @@ export class ToolBar extends Disposable {
|
||||
primaryActionsToSet.push(this.toggleMenuAction);
|
||||
}
|
||||
|
||||
this.actionBar.clear();
|
||||
|
||||
primaryActionsToSet.forEach(action => {
|
||||
this.actionBar.push(action, { icon: true, label: false, keybinding: this.getKeybindingLabel(action) });
|
||||
});
|
||||
@@ -148,25 +173,15 @@ export class ToolBar extends Disposable {
|
||||
return withNullAsUndefined(key?.getLabel());
|
||||
}
|
||||
|
||||
addPrimaryAction(primaryAction: IAction): () => void {
|
||||
return () => {
|
||||
|
||||
// Add after the "..." action if we have secondary actions
|
||||
if (this.hasSecondaryActions) {
|
||||
let itemCount = this.actionBar.length();
|
||||
this.actionBar.push(primaryAction, { icon: true, label: false, index: itemCount, keybinding: this.getKeybindingLabel(primaryAction) });
|
||||
}
|
||||
|
||||
// Otherwise just add to the end
|
||||
else {
|
||||
this.actionBar.push(primaryAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(primaryAction) });
|
||||
}
|
||||
};
|
||||
private clear(): void {
|
||||
this.submenuActionViewItems = [];
|
||||
this.disposables.clear();
|
||||
this.actionBar.clear();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.clear();
|
||||
super.dispose();
|
||||
this.toggleMenuActionViewItemDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +39,18 @@ export interface IActionRunner extends IDisposable {
|
||||
}
|
||||
|
||||
export interface IActionViewItem extends IDisposable {
|
||||
readonly actionRunner: IActionRunner;
|
||||
actionRunner: IActionRunner;
|
||||
setActionContext(context: any): void;
|
||||
render(element: any /* HTMLElement */): void;
|
||||
isEnabled(): boolean;
|
||||
focus(): void;
|
||||
focus(fromRight?: boolean): void; // TODO@isidorn what is this?
|
||||
blur(): void;
|
||||
}
|
||||
|
||||
export interface IActionViewItemProvider {
|
||||
(action: IAction): IActionViewItem | undefined;
|
||||
}
|
||||
|
||||
export interface IActionChangeEvent {
|
||||
readonly label?: string;
|
||||
readonly tooltip?: string;
|
||||
@@ -218,3 +222,22 @@ export class RadioGroup extends Disposable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Separator extends Action {
|
||||
|
||||
static readonly ID = 'vs.actions.separator';
|
||||
|
||||
constructor(label?: string) {
|
||||
super(Separator.ID, label, label ? 'separator text' : 'separator');
|
||||
this.checked = false;
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
export type SubmenuActions = IAction[] | (() => IAction[]);
|
||||
|
||||
export class SubmenuAction extends Action {
|
||||
constructor(id: string, label: string, readonly actions: SubmenuActions, cssClass?: string) {
|
||||
super(id, label, cssClass, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,11 +473,10 @@ export function range(arg: number, to?: number): number[] {
|
||||
}
|
||||
|
||||
export function index<T>(array: ReadonlyArray<T>, indexer: (t: T) => string): { [key: string]: T; };
|
||||
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, merger?: (t: T, r: R) => R): { [key: string]: R; };
|
||||
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, merger: (t: T, r: R) => R = t => t as any): { [key: string]: R; } {
|
||||
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, mapper: (t: T) => R): { [key: string]: R; };
|
||||
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, mapper?: (t: T) => R): { [key: string]: R; } {
|
||||
return array.reduce((r, t) => {
|
||||
const key = indexer(t);
|
||||
r[key] = merger(t, r[key]);
|
||||
r[indexer(t)] = mapper ? mapper(t) : t;
|
||||
return r;
|
||||
}, Object.create(null));
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Button, IButtonStyles } from 'vs/base/browser/ui/button/button';
|
||||
import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { equals } from 'vs/base/common/arrays';
|
||||
import { TimeoutTimer } from 'vs/base/common/async';
|
||||
@@ -28,6 +28,7 @@ import { List, IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWid
|
||||
import { IInputBoxStyles } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { registerIcon, Codicon } from 'vs/base/common/codicons';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export interface IQuickInputOptions {
|
||||
idPrefix: string;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Separator, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, Separator } from 'vs/base/common/actions';
|
||||
|
||||
suite('Actionbar', () => {
|
||||
|
||||
|
||||
@@ -22,9 +22,8 @@ exports.collectModules = function () {
|
||||
createModuleDescription('vs/code/electron-main/main', []),
|
||||
createModuleDescription('vs/code/node/cli', []),
|
||||
createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']),
|
||||
createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []),
|
||||
createModuleDescription('vs/code/electron-sandbox/issue/issueReporterMain', []),
|
||||
createModuleDescription('vs/code/electron-browser/sharedProcess/sharedProcessMain', []),
|
||||
createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []),
|
||||
createModuleDescription('vs/platform/driver/node/driver', []),
|
||||
createModuleDescription('vs/code/electron-sandbox/processExplorer/processExplorerMain', [])
|
||||
];
|
||||
|
||||
@@ -14,6 +14,6 @@ const bootstrapWindow = (() => {
|
||||
return window.MonacoBootstrapWindow;
|
||||
})();
|
||||
|
||||
bootstrapWindow.load(['vs/code/electron-browser/issue/issueReporterMain'], function (issueReporter, configuration) {
|
||||
bootstrapWindow.load(['vs/code/electron-sandbox/issue/issueReporterMain'], function (issueReporter, configuration) {
|
||||
issueReporter.startup(configuration);
|
||||
}, { forceEnableDeveloperKeybindings: true, disallowReloadKeybinding: true });
|
||||
@@ -5,9 +5,8 @@
|
||||
|
||||
import 'vs/css!./media/issueReporter';
|
||||
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
|
||||
import * as os from 'os';
|
||||
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { ipcRenderer, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
|
||||
import { $, windowOpenNoOpener, addClass } from 'vs/base/browser/dom';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
@@ -17,29 +16,15 @@ import { debounce } from 'vs/base/common/decorators';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { getDelayedChannel, createChannelSender } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
|
||||
import { IssueReporterData as IssueReporterModelData, IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
|
||||
import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage';
|
||||
import { IssueReporterData as IssueReporterModelData, IssueReporterModel } from 'vs/code/electron-sandbox/issue/issueReporterModel';
|
||||
import BaseHtml from 'vs/code/electron-sandbox/issue/issueReporterPage';
|
||||
import { localize } from 'vs/nls';
|
||||
import { isRemoteDiagnosticError, SystemInfo } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { EnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
|
||||
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
|
||||
import { ISettingsSearchIssueReporterData, IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue';
|
||||
import { getLogLevel, ILogService } from 'vs/platform/log/common/log';
|
||||
import { FollowerLogService, LoggerChannelClient } from 'vs/platform/log/common/logIpc';
|
||||
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { combinedAppender, LogAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
|
||||
import { INativeWindowConfiguration } from 'vs/platform/windows/node/window';
|
||||
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
|
||||
|
||||
const MAX_URL_LENGTH = 2045;
|
||||
|
||||
@@ -49,9 +34,23 @@ interface SearchResult {
|
||||
state?: string;
|
||||
}
|
||||
|
||||
export interface IssueReporterConfiguration extends INativeWindowConfiguration {
|
||||
export interface IssueReporterConfiguration extends IWindowConfiguration {
|
||||
windowId: number;
|
||||
disableExtensions: boolean;
|
||||
data: IssueReporterData;
|
||||
features: IssueReporterFeatures;
|
||||
os: {
|
||||
type: string;
|
||||
arch: string;
|
||||
release: string;
|
||||
},
|
||||
product: {
|
||||
nameShort: string;
|
||||
version: string;
|
||||
commit: string | undefined;
|
||||
date: string | undefined;
|
||||
reportIssueUrl: string | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function startup(configuration: IssueReporterConfiguration) {
|
||||
@@ -66,10 +65,7 @@ export function startup(configuration: IssueReporterConfiguration) {
|
||||
}
|
||||
|
||||
export class IssueReporter extends Disposable {
|
||||
private environmentService!: INativeEnvironmentService;
|
||||
private electronService!: IElectronService;
|
||||
private telemetryService!: ITelemetryService;
|
||||
private logService!: ILogService;
|
||||
private readonly issueReporterModel: IssueReporterModel;
|
||||
private numberOfSearchResultsDisplayed = 0;
|
||||
private receivedSystemInfo = false;
|
||||
@@ -79,7 +75,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
private readonly previewButton!: Button;
|
||||
|
||||
constructor(configuration: IssueReporterConfiguration) {
|
||||
constructor(private readonly configuration: IssueReporterConfiguration) {
|
||||
super();
|
||||
|
||||
this.initServices(configuration);
|
||||
@@ -90,10 +86,10 @@ export class IssueReporter extends Disposable {
|
||||
this.issueReporterModel = new IssueReporterModel({
|
||||
issueType: configuration.data.issueType || IssueType.Bug,
|
||||
versionInfo: {
|
||||
vscodeVersion: `${product.nameShort} ${product.version} (${product.commit || 'Commit unknown'}, ${product.date || 'Date unknown'})`,
|
||||
os: `${os.type()} ${os.arch()} ${os.release()}${isSnap ? ' snap' : ''}`
|
||||
vscodeVersion: `${configuration.product.nameShort} ${configuration.product.version} (${configuration.product.commit || 'Commit unknown'}, ${configuration.product.date || 'Date unknown'})`,
|
||||
os: `${this.configuration.os.type} ${this.configuration.os.arch} ${this.configuration.os.release}${isSnap ? ' snap' : ''}`
|
||||
},
|
||||
extensionsDisabled: !!this.environmentService.disableExtensions,
|
||||
extensionsDisabled: !!configuration.disableExtensions,
|
||||
fileOnExtension: configuration.data.extensionId ? !targetExtension?.isBuiltin : undefined,
|
||||
selectedExtension: targetExtension,
|
||||
});
|
||||
@@ -121,7 +117,6 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
|
||||
ipcRenderer.on('vscode:issuePerformanceInfoResponse', (_: unknown, info: Partial<IssueReporterData>) => {
|
||||
this.logService.trace('issueReporter: Received performance data');
|
||||
this.issueReporterModel.update(info);
|
||||
this.receivedPerformanceInfo = true;
|
||||
|
||||
@@ -132,7 +127,6 @@ export class IssueReporter extends Disposable {
|
||||
});
|
||||
|
||||
ipcRenderer.on('vscode:issueSystemInfoResponse', (_: unknown, info: SystemInfo) => {
|
||||
this.logService.trace('issueReporter: Received system data');
|
||||
this.issueReporterModel.update({ systemInfo: info });
|
||||
this.receivedSystemInfo = true;
|
||||
|
||||
@@ -144,7 +138,6 @@ export class IssueReporter extends Disposable {
|
||||
if (configuration.data.issueType === IssueType.PerformanceIssue) {
|
||||
ipcRenderer.send('vscode:issuePerformanceInfoRequest');
|
||||
}
|
||||
this.logService.trace('issueReporter: Sent data requests');
|
||||
|
||||
if (window.document.documentElement.lang !== 'en') {
|
||||
show(this.getElementById('english'));
|
||||
@@ -266,7 +259,7 @@ export class IssueReporter extends Disposable {
|
||||
this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: installedExtensions });
|
||||
this.updateExtensionTable(nonThemes, numberOfThemeExtesions);
|
||||
|
||||
if (this.environmentService.disableExtensions || installedExtensions.length === 0) {
|
||||
if (this.configuration.disableExtensions || installedExtensions.length === 0) {
|
||||
(<HTMLButtonElement>this.getElementById('disableExtensions')).disabled = true;
|
||||
}
|
||||
|
||||
@@ -314,40 +307,13 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private initServices(configuration: INativeWindowConfiguration): void {
|
||||
private initServices(configuration: IssueReporterConfiguration): void {
|
||||
const serviceCollection = new ServiceCollection();
|
||||
const mainProcessService = new MainProcessService(configuration.windowId);
|
||||
serviceCollection.set(IMainProcessService, mainProcessService);
|
||||
|
||||
this.electronService = new ElectronService(configuration.windowId, mainProcessService) as IElectronService;
|
||||
serviceCollection.set(IElectronService, this.electronService);
|
||||
|
||||
this.environmentService = new EnvironmentService(configuration, configuration.execPath);
|
||||
|
||||
const logService = new SpdLogService(`issuereporter${configuration.windowId}`, this.environmentService.logsPath, getLogLevel(this.environmentService));
|
||||
const loggerClient = new LoggerChannelClient(mainProcessService.getChannel('logger'));
|
||||
this.logService = new FollowerLogService(loggerClient, logService);
|
||||
|
||||
const sharedProcessService = createChannelSender<ISharedProcessService>(mainProcessService.getChannel('sharedProcess'));
|
||||
|
||||
const sharedProcess = sharedProcessService.whenSharedProcessReady()
|
||||
.then(() => connectNet(this.environmentService.sharedIPCHandle, `window:${configuration.windowId}`));
|
||||
|
||||
const instantiationService = new InstantiationService(serviceCollection, true);
|
||||
if (!this.environmentService.isExtensionDevelopment && !this.environmentService.args['disable-telemetry'] && !!product.enableTelemetry) {
|
||||
const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender')));
|
||||
const appender = combinedAppender(new TelemetryAppenderClient(channel), new LogAppender(logService));
|
||||
const commonProperties = resolveCommonProperties(product.commit || 'Commit unknown', product.version, configuration.machineId, product.msftInternalDomains, this.environmentService.installSourcePath);
|
||||
const piiPaths = this.environmentService.extensionsPath ? [this.environmentService.appRoot, this.environmentService.extensionsPath] : [this.environmentService.appRoot];
|
||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
const telemetryService = instantiationService.createInstance(TelemetryService, config);
|
||||
this._register(telemetryService);
|
||||
|
||||
this.telemetryService = telemetryService;
|
||||
} else {
|
||||
this.telemetryService = NullTelemetryService;
|
||||
}
|
||||
}
|
||||
|
||||
private setEventHandlers(): void {
|
||||
@@ -617,11 +583,11 @@ export class IssueReporter extends Disposable {
|
||||
}, timeToWait * 1000);
|
||||
}
|
||||
}
|
||||
}).catch(e => {
|
||||
this.logSearchError(e);
|
||||
}).catch(_ => {
|
||||
// Ignore
|
||||
});
|
||||
}).catch(e => {
|
||||
this.logSearchError(e);
|
||||
}).catch(_ => {
|
||||
// Ignore
|
||||
});
|
||||
}
|
||||
|
||||
@@ -648,11 +614,11 @@ export class IssueReporter extends Disposable {
|
||||
} else {
|
||||
throw new Error('Unexpected response, no candidates property');
|
||||
}
|
||||
}).catch((error) => {
|
||||
this.logSearchError(error);
|
||||
}).catch(_ => {
|
||||
// Ignore
|
||||
});
|
||||
}).catch((error) => {
|
||||
this.logSearchError(error);
|
||||
}).catch(_ => {
|
||||
// Ignore
|
||||
});
|
||||
}
|
||||
|
||||
@@ -705,18 +671,6 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private logSearchError(error: Error) {
|
||||
this.logService.warn('issueReporter#search ', error.message);
|
||||
type IssueReporterSearchErrorClassification = {
|
||||
message: { classification: 'CallstackOrException', purpose: 'PerformanceAndHealth' }
|
||||
};
|
||||
|
||||
type IssueReporterSearchError = {
|
||||
message: string;
|
||||
};
|
||||
this.telemetryService.publicLogError2<IssueReporterSearchError, IssueReporterSearchErrorClassification>('issueReporterSearchError', { message: error.message });
|
||||
}
|
||||
|
||||
private setUpTypes(): void {
|
||||
const makeOption = (issueType: IssueType, description: string) => `<option value="${issueType.valueOf()}">${escape(description)}</option>`;
|
||||
|
||||
@@ -910,15 +864,6 @@ export class IssueReporter extends Disposable {
|
||||
return false;
|
||||
}
|
||||
|
||||
type IssueReporterSubmitClassification = {
|
||||
issueType: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
numSimilarIssuesDisplayed: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
};
|
||||
type IssueReporterSubmitEvent = {
|
||||
issueType: any;
|
||||
numSimilarIssuesDisplayed: number;
|
||||
};
|
||||
this.telemetryService.publicLog2<IssueReporterSubmitEvent, IssueReporterSubmitClassification>('issueReporterSubmit', { issueType: this.issueReporterModel.getData().issueType, numSimilarIssuesDisplayed: this.numberOfSearchResultsDisplayed });
|
||||
this.hasBeenSubmitted = true;
|
||||
|
||||
const baseUrl = this.getIssueUrlWithTitle((<HTMLInputElement>this.getElementById('issue-title')).value);
|
||||
@@ -967,7 +912,7 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
|
||||
private getIssueUrlWithTitle(issueTitle: string): string {
|
||||
let repositoryUrl = product.reportIssueUrl;
|
||||
let repositoryUrl = this.configuration.product.reportIssueUrl;
|
||||
if (this.issueReporterModel.fileOnExtension()) {
|
||||
const extensionGitHubUrl = this.getExtensionGitHubUrl();
|
||||
if (extensionGitHubUrl) {
|
||||
@@ -975,7 +920,7 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
const queryStringPrefix = product.reportIssueUrl && product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&';
|
||||
const queryStringPrefix = this.configuration.product.reportIssueUrl && this.configuration.product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&';
|
||||
return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`;
|
||||
}
|
||||
|
||||
@@ -1136,7 +1081,7 @@ export class IssueReporter extends Disposable {
|
||||
private updateExtensionTable(extensions: IssueReporterExtensionData[], numThemeExtensions: number): void {
|
||||
const target = document.querySelector('.block-extensions .block-info');
|
||||
if (target) {
|
||||
if (this.environmentService.disableExtensions) {
|
||||
if (this.configuration.disableExtensions) {
|
||||
target.innerHTML = localize('disabledExtensions', "Extensions are disabled");
|
||||
return;
|
||||
}
|
||||
@@ -1193,7 +1138,6 @@ export class IssueReporter extends Disposable {
|
||||
// Exclude right click
|
||||
if (event.which < 3) {
|
||||
windowOpenNoOpener((<HTMLAnchorElement>event.target).href);
|
||||
this.telemetryService.publicLog2('issueReporterViewSimilarIssue');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/common/issue';
|
||||
import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
|
||||
@@ -49,7 +48,7 @@ export class IssueReporterModel {
|
||||
allExtensions: []
|
||||
};
|
||||
|
||||
this._data = initialData ? assign(defaultData, initialData) : defaultData;
|
||||
this._data = initialData ? Object.assign(defaultData, initialData) : defaultData;
|
||||
}
|
||||
|
||||
getData(): IssueReporterData {
|
||||
@@ -57,7 +56,7 @@ export class IssueReporterModel {
|
||||
}
|
||||
|
||||
update(newData: Partial<IssueReporterData>): void {
|
||||
assign(this._data, newData);
|
||||
Object.assign(this._data, newData);
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel';
|
||||
import { IssueReporterModel } from 'vs/code/electron-sandbox/issue/issueReporterModel';
|
||||
import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil';
|
||||
import { IssueType } from 'vs/platform/issue/common/issue';
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { Lazy } from 'vs/base/common/lazy';
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { KeyCode, KeyMod, ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -23,7 +22,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export class ContextMenuController implements IEditorContribution {
|
||||
|
||||
@@ -153,7 +152,7 @@ export class ContextMenuController implements IEditorContribution {
|
||||
if (action instanceof SubmenuItemAction) {
|
||||
const subActions = this._getMenuActions(model, action.item.submenu);
|
||||
if (subActions.length > 0) {
|
||||
result.push(new ContextSubMenu(action.label, subActions));
|
||||
result.push(new SubmenuAction(action.id, action.label, subActions));
|
||||
addedItems++;
|
||||
}
|
||||
} else {
|
||||
@@ -174,7 +173,7 @@ export class ContextMenuController implements IEditorContribution {
|
||||
return result;
|
||||
}
|
||||
|
||||
private _doShowContextMenu(actions: ReadonlyArray<IAction>, anchor: IAnchor | null = null): void {
|
||||
private _doShowContextMenu(actions: IAction[], anchor: IAnchor | null = null): void {
|
||||
if (!this._editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/action
|
||||
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
class MessageWidget {
|
||||
@@ -246,10 +246,10 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@IOpenerService private readonly _openerService: IOpenerService,
|
||||
@IMenuService private readonly _menuService: IMenuService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(editor, { showArrow: true, showFrame: true, isAccessible: true });
|
||||
super(editor, { showArrow: true, showFrame: true, isAccessible: true }, instantiationService);
|
||||
this._severity = MarkerSeverity.Warning;
|
||||
this._backgroundColor = Color.white;
|
||||
|
||||
@@ -311,8 +311,8 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
actionViewItemProvider: action => action instanceof MenuItemAction ? this._instantiationService.createInstance(MenuEntryActionViewItem, action) : undefined
|
||||
...super._getActionBarOptions(),
|
||||
orientation: ActionsOrientation.HORIZONTAL
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
||||
@ILabelService private readonly _uriLabel: ILabelService,
|
||||
@IUndoRedoService private readonly _undoRedoService: IUndoRedoService,
|
||||
) {
|
||||
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true });
|
||||
super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true }, _instantiationService);
|
||||
|
||||
this._applyTheme(themeService.getColorTheme());
|
||||
this._callOnDispose.add(themeService.onDidColorThemeChange(this._applyTheme.bind(this)));
|
||||
|
||||
@@ -18,7 +18,7 @@ import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeE
|
||||
import { IOptions, IStyles, ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget';
|
||||
import * as nls from 'vs/nls';
|
||||
import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServicesAccessor, createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -26,7 +26,8 @@ import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { registerColor, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
|
||||
import { MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
|
||||
export const IPeekViewService = createDecorator<IPeekViewService>('IPeekViewService');
|
||||
export interface IPeekViewService {
|
||||
@@ -115,7 +116,11 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
protected _actionbarWidget?: ActionBar;
|
||||
protected _bodyElement?: HTMLDivElement;
|
||||
|
||||
constructor(editor: ICodeEditor, options: IPeekViewOptions = {}) {
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
options: IPeekViewOptions,
|
||||
@IInstantiationService protected readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super(editor, options);
|
||||
objects.mixin(this.options, defaultOptions, false);
|
||||
}
|
||||
@@ -199,7 +204,17 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
}
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {};
|
||||
return {
|
||||
actionViewItemProvider: action => {
|
||||
if (action instanceof MenuItemAction) {
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected _onTitleClick(event: IMouseEvent): void {
|
||||
|
||||
@@ -43,9 +43,10 @@ import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { flatten, isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMenuService } from 'vs/platform/actions/common/actions';
|
||||
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, IActionViewItemProvider } from 'vs/base/common/actions';
|
||||
import { Codicon, registerIcon } from 'vs/base/common/codicons';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
const expandSuggestionDocsByDefault = false;
|
||||
|
||||
|
||||
@@ -552,6 +552,9 @@ export class StandaloneTelemetryService implements ITelemetryService {
|
||||
public setEnabled(value: boolean): void {
|
||||
}
|
||||
|
||||
public setExperimentProperty(name: string, value: string): void {
|
||||
}
|
||||
|
||||
public publicLog(eventName: string, data?: any): Promise<void> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
import { addClasses, createCSSRule, removeClasses, asCSSUrl } from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { IDisposable, toDisposable, MutableDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -17,6 +16,8 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
|
||||
// The alternative key on all platforms is alt. On windows we also support shift as an alternative key #44136
|
||||
class AlternativeKeyEmitter extends Emitter<boolean> {
|
||||
@@ -125,19 +126,11 @@ export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function createActionViewItem(action: IAction, keybindingService: IKeybindingService, notificationService: INotificationService, contextMenuService: IContextMenuService): ActionViewItem | undefined {
|
||||
if (action instanceof MenuItemAction) {
|
||||
return new MenuEntryActionViewItem(action, keybindingService, notificationService, contextMenuService);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const ids = new IdGenerator('menu-item-action-item-icon-');
|
||||
|
||||
export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>();
|
||||
|
||||
static readonly ICON_PATH_TO_CSS_RULES: Map<string /* path*/, string /* CSS rule */> = new Map<string, string>();
|
||||
export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
|
||||
private _wantsAltCommand: boolean = false;
|
||||
private readonly _itemClassDispose = this._register(new MutableDisposable());
|
||||
@@ -165,7 +158,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
this._altKey.suppressAltKeyUp();
|
||||
}
|
||||
|
||||
this.actionRunner.run(this._commandAction)
|
||||
this.actionRunner.run(this._commandAction, this._context)
|
||||
.then(undefined, err => this._notificationService.error(err));
|
||||
}
|
||||
|
||||
@@ -236,7 +229,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
_updateItemClass(item: ICommandAction): void {
|
||||
protected _updateItemClass(item: ICommandAction): void { // {{SQL CARBON EDIT}} make it overwritable
|
||||
this._itemClassDispose.value = undefined;
|
||||
|
||||
const icon = this._commandAction.checked && (item.toggled as { icon?: Icon })?.icon ? (item.toggled as { icon: Icon }).icon : item.icon;
|
||||
@@ -257,17 +250,17 @@ export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
// icon path
|
||||
let iconClass: string;
|
||||
|
||||
if (icon?.dark?.scheme) {
|
||||
if (icon.dark?.scheme) {
|
||||
|
||||
const iconPathMapKey = icon.dark.toString();
|
||||
|
||||
if (MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
|
||||
iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
|
||||
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
|
||||
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
|
||||
} else {
|
||||
iconClass = ids.nextId();
|
||||
createCSSRule(`.icon.${iconClass}`, `background-image: ${asCSSUrl(icon.light || icon.dark)}`);
|
||||
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: ${asCSSUrl(icon.dark)}`);
|
||||
MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
|
||||
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
|
||||
}
|
||||
|
||||
if (this.label) {
|
||||
@@ -284,17 +277,34 @@ export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
// Need to subclass MenuEntryActionViewItem in order to respect
|
||||
// the action context coming from any action bar, without breaking
|
||||
// existing users
|
||||
export class ContextAwareMenuEntryActionViewItem extends MenuEntryActionViewItem {
|
||||
export class SubmenuEntryActionViewItem extends DropdownMenuActionViewItem {
|
||||
|
||||
onClick(event: MouseEvent): void {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
constructor(
|
||||
action: SubmenuItemAction,
|
||||
@INotificationService _notificationService: INotificationService,
|
||||
@IContextMenuService _contextMenuService: IContextMenuService
|
||||
) {
|
||||
const classNames: string[] = [];
|
||||
|
||||
this.actionRunner.run(this._commandAction, this._context)
|
||||
.then(undefined, err => this._notificationService.error(err));
|
||||
if (action.item.icon) {
|
||||
if (ThemeIcon.isThemeIcon(action.item.icon)) {
|
||||
classNames.push(ThemeIcon.asClassName(action.item.icon)!);
|
||||
} else if (action.item.icon.dark?.scheme) {
|
||||
const iconPathMapKey = action.item.icon.dark.toString();
|
||||
|
||||
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
|
||||
classNames.push('icon', ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!);
|
||||
} else {
|
||||
const className = ids.nextId();
|
||||
classNames.push('icon', className);
|
||||
createCSSRule(`.icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.light || action.item.icon.dark)}`);
|
||||
createCSSRule(`.vs-dark .icon.${className}, .hc-black .icon.${className}`, `background-image: ${asCSSUrl(action.item.icon.dark)}`);
|
||||
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super(action, Array.isArray(action.actions) ? action.actions : action.actions(), _contextMenuService, { classNames });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +333,7 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
|
||||
|
||||
// Overwrite item class to ensure that we can pass in a CSS class that other items use
|
||||
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
|
||||
_updateItemClass(item: ICommandAction): void {
|
||||
protected _updateItemClass(item: ICommandAction): void {
|
||||
dispose(this._labeledItemClassDispose);
|
||||
this._labeledItemClassDispose = undefined;
|
||||
|
||||
@@ -336,13 +346,13 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
|
||||
if (item.icon?.dark?.scheme) {
|
||||
const iconPathMapKey = item.icon.dark.toString();
|
||||
|
||||
if (MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
|
||||
iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
|
||||
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
|
||||
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
|
||||
} else {
|
||||
iconClass = ids.nextId();
|
||||
createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
|
||||
createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)}`);
|
||||
MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
|
||||
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
|
||||
}
|
||||
|
||||
if (this.label) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { SyncDescriptor0, createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { IConstructorSignature2, createDecorator, BrandedService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindings, KeybindingsRegistry, IKeybindingRule } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
@@ -47,6 +47,7 @@ export interface IMenuItem {
|
||||
export interface ISubmenuItem {
|
||||
title: string | ILocalizedString;
|
||||
submenu: MenuId;
|
||||
icon?: Icon;
|
||||
when?: ContextKeyExpression;
|
||||
group?: 'navigation' | string;
|
||||
order?: number;
|
||||
@@ -302,12 +303,35 @@ export class ExecuteCommandAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class SubmenuItemAction extends Action {
|
||||
export class SubmenuItemAction extends SubmenuAction {
|
||||
|
||||
readonly item: ISubmenuItem;
|
||||
constructor(item: ISubmenuItem) {
|
||||
typeof item.title === 'string' ? super('', item.title, 'submenu') : super('', item.title.value, 'submenu');
|
||||
this.item = item;
|
||||
constructor(
|
||||
readonly item: ISubmenuItem,
|
||||
menuService: IMenuService,
|
||||
contextKeyService: IContextKeyService,
|
||||
options?: IMenuActionOptions
|
||||
) {
|
||||
super(`submenuitem.${item.submenu.id}`, typeof item.title === 'string' ? item.title : item.title.value, () => {
|
||||
const result: IAction[] = [];
|
||||
const menu = menuService.createMenu(item.submenu, contextKeyService);
|
||||
const groups = menu.getActions(options);
|
||||
menu.dispose();
|
||||
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
|
||||
if (actions.length > 0) {
|
||||
result.push(...actions);
|
||||
result.push(new Separator());
|
||||
}
|
||||
}
|
||||
|
||||
if (result.length) {
|
||||
result.pop(); // remove last separator
|
||||
}
|
||||
|
||||
return result;
|
||||
}, 'submenu');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export class MenuService implements IMenuService {
|
||||
}
|
||||
|
||||
createMenu(id: MenuId, contextKeyService: IContextKeyService): IMenu {
|
||||
return new Menu(id, this._commandService, contextKeyService);
|
||||
return new Menu(id, this._commandService, contextKeyService, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ class Menu implements IMenu {
|
||||
constructor(
|
||||
private readonly _id: MenuId,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IMenuService private readonly _menuService: IMenuService
|
||||
) {
|
||||
this._build();
|
||||
|
||||
@@ -114,7 +115,7 @@ class Menu implements IMenu {
|
||||
if (this._contextKeyService.contextMatchesRules(item.when)) {
|
||||
const action = isIMenuItem(item)
|
||||
? new MenuItemAction(item.command, item.alt, options, this._contextKeyService, this._commandService)
|
||||
: new SubmenuItemAction(item);
|
||||
: new SubmenuItemAction(item, this._menuService, this._contextKeyService, options);
|
||||
|
||||
activeActions.push(action);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CheckboxActionViewItem } from 'vs/base/browser/ui/checkbox/checkbox';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { attachCheckboxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export class ThemableCheckboxActionViewItem extends CheckboxActionViewItem {
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ class Query {
|
||||
withFilter(filterType: FilterType, ...values: string[]): Query {
|
||||
const criteria = [
|
||||
...this.state.criteria,
|
||||
...values.map(value => ({ filterType, value }))
|
||||
...values.length ? values.map(value => ({ filterType, value })) : [{ filterType }]
|
||||
];
|
||||
|
||||
return new Query(assign({}, this.state, { criteria }));
|
||||
@@ -494,6 +494,12 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
return '';
|
||||
});
|
||||
|
||||
// Use featured filter
|
||||
text = text.replace(/\bfeatured(\s+|\b|$)/g, () => {
|
||||
query = query.withFilter(FilterType.Featured);
|
||||
return '';
|
||||
});
|
||||
|
||||
text = text.trim();
|
||||
|
||||
if (text) {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import * as os from 'os';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { ICommonIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
|
||||
@@ -196,12 +198,23 @@ export class IssueMainService implements ICommonIssueService {
|
||||
backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR,
|
||||
webPreferences: {
|
||||
preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath,
|
||||
nodeIntegration: true,
|
||||
enableWebSQL: false,
|
||||
enableRemoteModule: false,
|
||||
spellcheck: false,
|
||||
nativeWindowOpen: true,
|
||||
zoomFactor: zoomLevelToZoomFactor(data.zoomLevel)
|
||||
zoomFactor: zoomLevelToZoomFactor(data.zoomLevel),
|
||||
...this.environmentService.sandbox ?
|
||||
|
||||
// Sandbox
|
||||
{
|
||||
sandbox: true,
|
||||
contextIsolation: true
|
||||
} :
|
||||
|
||||
// No Sandbox
|
||||
{
|
||||
nodeIntegration: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -408,10 +421,23 @@ export class IssueMainService implements ICommonIssueService {
|
||||
machineId: this.machineId,
|
||||
userEnv: this.userEnv,
|
||||
data,
|
||||
features
|
||||
features,
|
||||
disableExtensions: this.environmentService.disableExtensions,
|
||||
os: {
|
||||
type: os.type(),
|
||||
arch: os.arch(),
|
||||
release: os.release(),
|
||||
},
|
||||
product: {
|
||||
nameShort: product.nameShort,
|
||||
version: product.version,
|
||||
commit: product.commit,
|
||||
date: product.date,
|
||||
reportIssueUrl: product.reportIssueUrl
|
||||
}
|
||||
};
|
||||
|
||||
return toLauchUrl('vs/code/electron-browser/issue/issueReporter.html', windowConfiguration);
|
||||
return toLauchUrl('vs/code/electron-sandbox/issue/issueReporter.html', windowConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,13 @@ export interface IProductConfiguration {
|
||||
readonly settingsSearchBuildId?: number;
|
||||
readonly settingsSearchUrl?: string;
|
||||
|
||||
readonly tasConfig?: {
|
||||
endpoint: string;
|
||||
telemetryEventName: string;
|
||||
featuresTelemetryPropertyName: string;
|
||||
assignmentContextTelemetryPropertyName: string;
|
||||
};
|
||||
|
||||
readonly experimentsUrl?: string;
|
||||
|
||||
readonly extensionsGallery?: {
|
||||
|
||||
@@ -46,6 +46,8 @@ export interface ITelemetryService {
|
||||
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo>;
|
||||
|
||||
setExperimentProperty(name: string, value: string): void;
|
||||
|
||||
isOptedIn: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ export class TelemetryService implements ITelemetryService {
|
||||
|
||||
private _appender: ITelemetryAppender;
|
||||
private _commonProperties: Promise<{ [name: string]: any; }>;
|
||||
private _experimentProperties: { [name: string]: string } = {};
|
||||
private _piiPaths: string[];
|
||||
private _userOptIn: boolean;
|
||||
private _enabled: boolean;
|
||||
@@ -79,6 +80,10 @@ export class TelemetryService implements ITelemetryService {
|
||||
}
|
||||
}
|
||||
|
||||
setExperimentProperty(name: string, value: string): void {
|
||||
this._experimentProperties[name] = value;
|
||||
}
|
||||
|
||||
setEnabled(value: boolean): void {
|
||||
this._enabled = value;
|
||||
}
|
||||
@@ -119,6 +124,9 @@ export class TelemetryService implements ITelemetryService {
|
||||
// (first) add common properties
|
||||
data = mixin(data, values);
|
||||
|
||||
// (next) add experiment properties
|
||||
data = mixin(data, this._experimentProperties);
|
||||
|
||||
// (last) remove all PII from data
|
||||
data = cloneAndChange(data, value => {
|
||||
if (typeof value === 'string') {
|
||||
|
||||
@@ -28,6 +28,7 @@ export const NullTelemetryService = new class implements ITelemetryService {
|
||||
return this.publicLogError(eventName, data as ITelemetryData);
|
||||
}
|
||||
|
||||
setExperimentProperty() { }
|
||||
setEnabled() { }
|
||||
isOptedIn = true;
|
||||
getTelemetryInfo(): Promise<ITelemetryInfo> {
|
||||
|
||||
@@ -392,7 +392,7 @@ export const menuSeparatorBackground = registerColor('menu.separatorBackground',
|
||||
export const snippetTabstopHighlightBackground = registerColor('editor.snippetTabstopHighlightBackground', { dark: new Color(new RGBA(124, 124, 124, 0.3)), light: new Color(new RGBA(10, 50, 100, 0.2)), hc: new Color(new RGBA(124, 124, 124, 0.3)) }, nls.localize('snippetTabstopHighlightBackground', "Highlight background color of a snippet tabstop."));
|
||||
export const snippetTabstopHighlightBorder = registerColor('editor.snippetTabstopHighlightBorder', { dark: null, light: null, hc: null }, nls.localize('snippetTabstopHighlightBorder', "Highlight border color of a snippet tabstop."));
|
||||
export const snippetFinalTabstopHighlightBackground = registerColor('editor.snippetFinalTabstopHighlightBackground', { dark: null, light: null, hc: null }, nls.localize('snippetFinalTabstopHighlightBackground', "Highlight background color of the final tabstop of a snippet."));
|
||||
export const snippetFinalTabstopHighlightBorder = registerColor('editor.snippetFinalTabstopHighlightBorder', { dark: '#525252', light: new Color(new RGBA(10, 50, 100, 0.5)), hc: '#525252' }, nls.localize('snippetFinalTabstopHighlightBorder', "Highlight border color of the final stabstop of a snippet."));
|
||||
export const snippetFinalTabstopHighlightBorder = registerColor('editor.snippetFinalTabstopHighlightBorder', { dark: '#525252', light: new Color(new RGBA(10, 50, 100, 0.5)), hc: '#525252' }, nls.localize('snippetFinalTabstopHighlightBorder', "Highlight border color of the final tabstop of a snippet."));
|
||||
|
||||
/**
|
||||
* Breadcrumb colors
|
||||
|
||||
@@ -18,6 +18,7 @@ import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { Platform, platform } from 'vs/base/common/platform';
|
||||
|
||||
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline', 'vscode.github-browser'];
|
||||
|
||||
@@ -390,7 +391,11 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
|
||||
}
|
||||
|
||||
const remoteConnection = this.remoteAgentService.getConnection();
|
||||
if (remoteConnection && remoteConnection.remoteAuthority && remoteConnection.remoteAuthority.startsWith('vsonline') && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) {
|
||||
const isVSO = remoteConnection !== null
|
||||
? remoteConnection.remoteAuthority.startsWith('vsonline')
|
||||
: platform === Platform.Web;
|
||||
|
||||
if (isVSO && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) {
|
||||
addAccountUsage(this.storageService, providerId, accountName, extensionId, extensionName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -634,7 +634,7 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
return URI.parse(`${info.scheme}://${info.authority}${path}`);
|
||||
},
|
||||
context: this._extHostContext,
|
||||
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet, target: ConfigurationTarget): Promise<ResolvedVariables> => {
|
||||
resolveVariables: (workspaceFolder: IWorkspaceFolder, toResolve: ResolveSet, target: ConfigurationTarget): Promise<ResolvedVariables | undefined> => {
|
||||
const vars: string[] = [];
|
||||
toResolve.variables.forEach(item => vars.push(item));
|
||||
return Promise.resolve(this._proxy.$resolveVariables(workspaceFolder.uri, { process: toResolve.process, variables: vars })).then(values => {
|
||||
@@ -642,8 +642,12 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
forEach(values.variables, (entry) => {
|
||||
partiallyResolvedVars.push(entry.value);
|
||||
});
|
||||
return new Promise<ResolvedVariables>((resolve, reject) => {
|
||||
return new Promise<ResolvedVariables | undefined>((resolve, reject) => {
|
||||
this._configurationResolverService.resolveWithInteraction(workspaceFolder, partiallyResolvedVars, 'tasks', undefined, target).then(resolvedVars => {
|
||||
if (!resolvedVars) {
|
||||
resolve(undefined);
|
||||
}
|
||||
|
||||
const result: ResolvedVariables = {
|
||||
process: undefined,
|
||||
variables: new Map<string, string>()
|
||||
@@ -677,4 +681,9 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async $registerSupportedExecutions(custom?: boolean, shell?: boolean, process?: boolean): Promise<void> {
|
||||
return this._taskService.registerSupportedExecutions(custom, shell, process);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -791,6 +791,7 @@ export interface MainThreadTaskShape extends IDisposable {
|
||||
$terminateTask(id: string): Promise<void>;
|
||||
$registerTaskSystem(scheme: string, info: tasks.TaskSystemInfoDTO): void;
|
||||
$customExecutionComplete(id: string, result?: number): Promise<void>;
|
||||
$registerSupportedExecutions(custom?: boolean, shell?: boolean, process?: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadExtensionServiceShape extends IDisposable {
|
||||
|
||||
@@ -419,6 +419,7 @@ export abstract class ExtHostTaskBase implements ExtHostTaskShape, IExtHostTask
|
||||
this._activeCustomExecutions2 = new Map<string, types.CustomExecution>();
|
||||
this._logService = logService;
|
||||
this._deprecationService = deprecationService;
|
||||
this._proxy.$registerSupportedExecutions(true);
|
||||
}
|
||||
|
||||
public registerTaskProvider(extension: IExtensionDescription, type: string, provider: vscode.TaskProvider): vscode.Disposable {
|
||||
|
||||
@@ -10,14 +10,203 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { forEach } from 'vs/base/common/collections';
|
||||
import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem, ICommandAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem, ICommandAction, ISubmenuItem } from 'vs/platform/actions/common/actions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { index } from 'vs/base/common/arrays';
|
||||
|
||||
interface IAPIMenu {
|
||||
readonly key: string;
|
||||
readonly id: MenuId;
|
||||
readonly description: string;
|
||||
readonly proposed?: boolean; // defaults to false
|
||||
readonly supportsSubmenus?: boolean; // defaults to true
|
||||
}
|
||||
|
||||
const apiMenus: IAPIMenu[] = [
|
||||
{
|
||||
key: 'commandPalette',
|
||||
id: MenuId.CommandPalette,
|
||||
description: localize('menus.commandPalette', "The Command Palette"),
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'touchBar',
|
||||
id: MenuId.TouchBarContext,
|
||||
description: localize('menus.touchBar', "The touch bar (macOS only)"),
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'editor/title',
|
||||
id: MenuId.EditorTitle,
|
||||
description: localize('menus.editorTitle', "The editor title menu")
|
||||
},
|
||||
{
|
||||
key: 'editor/context',
|
||||
id: MenuId.EditorContext,
|
||||
description: localize('menus.editorContext', "The editor context menu")
|
||||
},
|
||||
{
|
||||
key: 'explorer/context',
|
||||
id: MenuId.ExplorerContext,
|
||||
description: localize('menus.explorerContext', "The file explorer context menu")
|
||||
},
|
||||
{
|
||||
key: 'editor/title/context',
|
||||
id: MenuId.EditorTitleContext,
|
||||
description: localize('menus.editorTabContext', "The editor tabs context menu")
|
||||
},
|
||||
{
|
||||
key: 'debug/callstack/context',
|
||||
id: MenuId.DebugCallStackContext,
|
||||
description: localize('menus.debugCallstackContext', "The debug callstack context menu")
|
||||
},
|
||||
{
|
||||
key: 'debug/toolBar',
|
||||
id: MenuId.DebugToolBar,
|
||||
description: localize('menus.debugToolBar', "The debug toolbar menu")
|
||||
},
|
||||
{
|
||||
key: 'menuBar/webNavigation',
|
||||
id: MenuId.MenubarWebNavigationMenu,
|
||||
description: localize('menus.webNavigation', "The top level navigational menu (web only)"),
|
||||
proposed: true,
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'scm/title',
|
||||
id: MenuId.SCMTitle,
|
||||
description: localize('menus.scmTitle', "The Source Control title menu")
|
||||
},
|
||||
{
|
||||
key: 'scm/sourceControl',
|
||||
id: MenuId.SCMSourceControl,
|
||||
description: localize('menus.scmSourceControl', "The Source Control menu")
|
||||
},
|
||||
{
|
||||
key: 'scm/resourceState/context',
|
||||
id: MenuId.SCMResourceContext,
|
||||
description: localize('menus.resourceGroupContext', "The Source Control resource group context menu")
|
||||
},
|
||||
{
|
||||
key: 'scm/resourceFolder/context',
|
||||
id: MenuId.SCMResourceFolderContext,
|
||||
description: localize('menus.resourceStateContext', "The Source Control resource state context menu")
|
||||
},
|
||||
{
|
||||
key: 'scm/resourceGroup/context',
|
||||
id: MenuId.SCMResourceGroupContext,
|
||||
description: localize('menus.resourceFolderContext', "The Source Control resource folder context menu")
|
||||
},
|
||||
{
|
||||
key: 'scm/change/title',
|
||||
id: MenuId.SCMChangeContext,
|
||||
description: localize('menus.changeTitle', "The Source Control inline change menu")
|
||||
},
|
||||
{
|
||||
key: 'statusBar/windowIndicator',
|
||||
id: MenuId.StatusBarWindowIndicatorMenu,
|
||||
description: localize('menus.statusBarWindowIndicator', "The window indicator menu in the status bar"),
|
||||
proposed: true,
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'view/title',
|
||||
id: MenuId.ViewTitle,
|
||||
description: localize('view.viewTitle', "The contributed view title menu")
|
||||
},
|
||||
{
|
||||
key: 'view/item/context',
|
||||
id: MenuId.ViewItemContext,
|
||||
description: localize('view.itemContext', "The contributed view item context menu")
|
||||
},
|
||||
{
|
||||
key: 'comments/commentThread/title',
|
||||
id: MenuId.CommentThreadTitle,
|
||||
description: localize('commentThread.title', "The contributed comment thread title menu")
|
||||
},
|
||||
{
|
||||
key: 'comments/commentThread/context',
|
||||
id: MenuId.CommentThreadActions,
|
||||
description: localize('commentThread.actions', "The contributed comment thread context menu, rendered as buttons below the comment editor"),
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'comments/comment/title',
|
||||
id: MenuId.CommentTitle,
|
||||
description: localize('comment.title', "The contributed comment title menu")
|
||||
},
|
||||
{
|
||||
key: 'comments/comment/context',
|
||||
id: MenuId.CommentActions,
|
||||
description: localize('comment.actions', "The contributed comment context menu, rendered as buttons below the comment editor"),
|
||||
supportsSubmenus: false
|
||||
},
|
||||
{
|
||||
key: 'notebook/cell/title',
|
||||
id: MenuId.NotebookCellTitle,
|
||||
description: localize('notebook.cell.title', "The contributed notebook cell title menu"),
|
||||
proposed: true
|
||||
},
|
||||
{
|
||||
key: 'extension/context',
|
||||
id: MenuId.ExtensionContext,
|
||||
description: localize('menus.extensionContext', "The extension context menu")
|
||||
},
|
||||
{
|
||||
key: 'timeline/title',
|
||||
id: MenuId.TimelineTitle,
|
||||
description: localize('view.timelineTitle', "The Timeline view title menu")
|
||||
},
|
||||
{
|
||||
key: 'timeline/item/context',
|
||||
id: MenuId.TimelineItemContext,
|
||||
description: localize('view.timelineContext', "The Timeline view item context menu")
|
||||
},
|
||||
// {{SQL CARBON EDIT}} start menu entries
|
||||
{
|
||||
key: 'dashboard/toolbar',
|
||||
id: MenuId.DashboardToolbar,
|
||||
description: localize('dashboard.toolbar', "The dashboard toolbar action menu")
|
||||
},
|
||||
{
|
||||
key: 'notebook/cell/title',
|
||||
id: MenuId.NotebookCellTitle,
|
||||
description: localize('notebook.cellTitle', "The notebook cell title menu")
|
||||
},
|
||||
{
|
||||
key: 'notebooks/title',
|
||||
id: MenuId.NotebookTitle,
|
||||
description: localize('notebook.title', "The notebook title menu")
|
||||
},
|
||||
{
|
||||
key: 'notebook/toolbar',
|
||||
id: MenuId.NotebookToolbar,
|
||||
description: localize('notebook.toolbar', "The notebook toolbar menu")
|
||||
},
|
||||
{
|
||||
key: 'dataExplorer/action',
|
||||
id: MenuId.DataExplorerAction,
|
||||
description: localize('dataExplorer.action', "The dataexplorer view container title action menu")
|
||||
},
|
||||
{
|
||||
key: 'dataExplorer/context',
|
||||
id: MenuId.DataExplorerContext,
|
||||
description: localize('dataExplorer.context', "The dataexplorer item context menu")
|
||||
},
|
||||
{
|
||||
key: 'objectExplorer/item/context',
|
||||
id: MenuId.DataExplorerContext,
|
||||
description: localize('objectExplorer.context', "The object explorer item context menu")
|
||||
},
|
||||
// {{SQL CARBON EDIT}} end menu entries
|
||||
];
|
||||
|
||||
namespace schema {
|
||||
|
||||
// --- menus contribution point
|
||||
// --- menus, submenus contribution point
|
||||
|
||||
export interface IUserFriendlyMenuItem {
|
||||
command: string;
|
||||
@@ -26,87 +215,102 @@ namespace schema {
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export function parseMenuId(value: string): MenuId | undefined {
|
||||
switch (value) {
|
||||
case 'commandPalette': return MenuId.CommandPalette;
|
||||
case 'touchBar': return MenuId.TouchBarContext;
|
||||
case 'editor/title': return MenuId.EditorTitle;
|
||||
case 'editor/context': return MenuId.EditorContext;
|
||||
case 'explorer/context': return MenuId.ExplorerContext;
|
||||
case 'editor/title/context': return MenuId.EditorTitleContext;
|
||||
case 'debug/callstack/context': return MenuId.DebugCallStackContext;
|
||||
case 'debug/toolbar': return MenuId.DebugToolBar;
|
||||
case 'debug/toolBar': return MenuId.DebugToolBar;
|
||||
case 'menuBar/webNavigation': return MenuId.MenubarWebNavigationMenu;
|
||||
case 'scm/title': return MenuId.SCMTitle;
|
||||
case 'scm/sourceControl': return MenuId.SCMSourceControl;
|
||||
case 'scm/resourceState/context': return MenuId.SCMResourceContext;
|
||||
case 'scm/resourceFolder/context': return MenuId.SCMResourceFolderContext;
|
||||
case 'scm/resourceGroup/context': return MenuId.SCMResourceGroupContext;
|
||||
case 'scm/change/title': return MenuId.SCMChangeContext;//
|
||||
case 'statusBar/windowIndicator': return MenuId.StatusBarWindowIndicatorMenu;
|
||||
case 'view/title': return MenuId.ViewTitle;
|
||||
case 'view/item/context': return MenuId.ViewItemContext;
|
||||
// {{SQL CARBON EDIT}}
|
||||
case 'objectExplorer/item/context': return MenuId.ObjectExplorerItemContext;
|
||||
case 'notebook/toolbar': return MenuId.NotebookToolbar;
|
||||
case 'dataExplorer/context': return MenuId.DataExplorerContext;
|
||||
case 'dataExplorer/action': return MenuId.DataExplorerAction;
|
||||
case 'notebooks/title': return MenuId.NotebookTitle;
|
||||
case 'comments/commentThread/title': return MenuId.CommentThreadTitle;
|
||||
case 'comments/commentThread/context': return MenuId.CommentThreadActions;
|
||||
case 'comments/comment/title': return MenuId.CommentTitle;
|
||||
case 'comments/comment/context': return MenuId.CommentActions;
|
||||
case 'notebook/cell/title': return MenuId.NotebookCellTitle;
|
||||
case 'extension/context': return MenuId.ExtensionContext;
|
||||
case 'dashboard/toolbar': return MenuId.DashboardToolbar;
|
||||
case 'timeline/title': return MenuId.TimelineTitle;
|
||||
case 'timeline/item/context': return MenuId.TimelineItemContext;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
export interface IUserFriendlySubmenuItem {
|
||||
submenu: string;
|
||||
when?: string;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export function isProposedAPI(menuId: MenuId): boolean {
|
||||
switch (menuId) {
|
||||
case MenuId.StatusBarWindowIndicatorMenu:
|
||||
case MenuId.MenubarWebNavigationMenu:
|
||||
case MenuId.NotebookCellTitle:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
export interface IUserFriendlySubmenu {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: IUserFriendlyIcon;
|
||||
}
|
||||
|
||||
export function isValidMenuItems(menu: IUserFriendlyMenuItem[], collector: ExtensionMessageCollector): boolean {
|
||||
if (!Array.isArray(menu)) {
|
||||
collector.error(localize('requirearray', "menu items must be an array"));
|
||||
export function isMenuItem(item: IUserFriendlyMenuItem | IUserFriendlySubmenuItem): item is IUserFriendlyMenuItem {
|
||||
return typeof (item as IUserFriendlyMenuItem).command === 'string';
|
||||
}
|
||||
|
||||
export function isValidMenuItem(item: IUserFriendlyMenuItem, collector: ExtensionMessageCollector): boolean {
|
||||
if (typeof item.command !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
|
||||
return false;
|
||||
}
|
||||
if (item.alt && typeof item.alt !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'alt'));
|
||||
return false;
|
||||
}
|
||||
if (item.when && typeof item.when !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
if (item.group && typeof item.group !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'group'));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let item of menu) {
|
||||
if (typeof item.command !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
|
||||
return false;
|
||||
}
|
||||
if (item.alt && typeof item.alt !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'alt'));
|
||||
return false;
|
||||
}
|
||||
if (item.when && typeof item.when !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
if (item.group && typeof item.group !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'group'));
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isValidSubmenuItem(item: IUserFriendlySubmenuItem, collector: ExtensionMessageCollector): boolean {
|
||||
if (typeof item.submenu !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'submenu'));
|
||||
return false;
|
||||
}
|
||||
if (item.when && typeof item.when !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
|
||||
return false;
|
||||
}
|
||||
if (item.group && typeof item.group !== 'string') {
|
||||
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'group'));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isValidItems(items: (IUserFriendlyMenuItem | IUserFriendlySubmenuItem)[], collector: ExtensionMessageCollector): boolean {
|
||||
if (!Array.isArray(items)) {
|
||||
collector.error(localize('requirearray', "submenu items must be an array"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let item of items) {
|
||||
if (isMenuItem(item)) {
|
||||
if (!isValidMenuItem(item, collector)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!isValidSubmenuItem(item, collector)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isValidSubmenu(submenu: IUserFriendlySubmenu, collector: ExtensionMessageCollector): boolean {
|
||||
if (typeof submenu !== 'object') {
|
||||
collector.error(localize('require', "submenu items must be an object"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof submenu.id !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'id'));
|
||||
return false;
|
||||
}
|
||||
if (typeof submenu.label !== 'string') {
|
||||
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'label'));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const menuItem: IJSONSchema = {
|
||||
type: 'object',
|
||||
required: ['command'],
|
||||
properties: {
|
||||
command: {
|
||||
description: localize('vscode.extension.contributes.menuItem.command', 'Identifier of the command to execute. The command must be declared in the \'commands\'-section'),
|
||||
@@ -127,136 +331,73 @@ namespace schema {
|
||||
}
|
||||
};
|
||||
|
||||
const submenuItem: IJSONSchema = {
|
||||
type: 'object',
|
||||
required: ['submenu'],
|
||||
properties: {
|
||||
submenu: {
|
||||
description: localize('vscode.extension.contributes.menuItem.submenu', 'Identifier of the submenu to display in this item.'),
|
||||
type: 'string'
|
||||
},
|
||||
when: {
|
||||
description: localize('vscode.extension.contributes.menuItem.when', 'Condition which must be true to show this item'),
|
||||
type: 'string'
|
||||
},
|
||||
group: {
|
||||
description: localize('vscode.extension.contributes.menuItem.group', 'Group into which this command belongs'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const submenu: IJSONSchema = {
|
||||
type: 'object',
|
||||
required: ['id', 'label'],
|
||||
properties: {
|
||||
id: {
|
||||
description: localize('vscode.extension.contributes.submenu.id', 'Identifier of the menu to display as a submenu.'),
|
||||
type: 'string'
|
||||
},
|
||||
label: {
|
||||
description: localize('vscode.extension.contributes.submenu.label', 'The label of the menu item which leads to this submenu.'),
|
||||
type: 'string'
|
||||
},
|
||||
icon: {
|
||||
description: localize('vscode.extension.contributes.submenu.icon', '(Optional) Icon which is used to represent the submenu in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\\$(zap)`'),
|
||||
anyOf: [{
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
light: {
|
||||
description: localize('vscode.extension.contributes.submenu.icon.light', 'Icon path when a light theme is used'),
|
||||
type: 'string'
|
||||
},
|
||||
dark: {
|
||||
description: localize('vscode.extension.contributes.submenu.icon.dark', 'Icon path when a dark theme is used'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const menusContribution: IJSONSchema = {
|
||||
description: localize('vscode.extension.contributes.menus', "Contributes menu items to the editor"),
|
||||
type: 'object',
|
||||
properties: {
|
||||
'commandPalette': {
|
||||
description: localize('menus.commandPalette', "The Command Palette"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'touchBar': {
|
||||
description: localize('menus.touchBar', "The touch bar (macOS only)"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'editor/title': {
|
||||
description: localize('menus.editorTitle', "The editor title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'editor/context': {
|
||||
description: localize('menus.editorContext', "The editor context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'explorer/context': {
|
||||
description: localize('menus.explorerContext', "The file explorer context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'editor/title/context': {
|
||||
description: localize('menus.editorTabContext', "The editor tabs context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'debug/callstack/context': {
|
||||
description: localize('menus.debugCallstackContext', "The debug callstack context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'debug/toolBar': {
|
||||
description: localize('menus.debugToolBar', "The debug toolbar menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'menuBar/webNavigation': {
|
||||
description: localize('menus.webNavigation', "The top level navigational menu (web only)"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/title': {
|
||||
description: localize('menus.scmTitle', "The Source Control title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/sourceControl': {
|
||||
description: localize('menus.scmSourceControl', "The Source Control menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/resourceGroup/context': {
|
||||
description: localize('menus.resourceGroupContext', "The Source Control resource group context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/resourceState/context': {
|
||||
description: localize('menus.resourceStateContext', "The Source Control resource state context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/resourceFolder/context': {
|
||||
description: localize('menus.resourceFolderContext', "The Source Control resource folder context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'scm/change/title': {
|
||||
description: localize('menus.changeTitle', "The Source Control inline change menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'view/title': {
|
||||
description: localize('view.viewTitle', "The contributed view title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'view/item/context': {
|
||||
description: localize('view.itemContext', "The contributed view item context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/commentThread/title': {
|
||||
description: localize('commentThread.title', "The contributed comment thread title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/commentThread/context': {
|
||||
description: localize('commentThread.actions', "The contributed comment thread context menu, rendered as buttons below the comment editor"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/comment/title': {
|
||||
description: localize('comment.title', "The contributed comment title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'comments/comment/context': {
|
||||
description: localize('comment.actions', "The contributed comment context menu, rendered as buttons below the comment editor"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'notebook/cell/title': {
|
||||
description: localize('notebook.cell.title', "The contributed notebook cell title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'extension/context': {
|
||||
description: localize('menus.extensionContext', "The extension context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'timeline/title': {
|
||||
description: localize('view.timelineTitle', "The Timeline view title menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'timeline/item/context': {
|
||||
description: localize('view.timelineContext', "The Timeline view item context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
}
|
||||
properties: index(apiMenus, menu => menu.key, menu => ({
|
||||
description: menu.proposed ? `(${localize('proposed', "Proposed API")}) ${menu.description}` : menu.description,
|
||||
type: 'array',
|
||||
items: menu.supportsSubmenus === false ? menuItem : { oneOf: [menuItem, submenuItem] }
|
||||
}))
|
||||
};
|
||||
|
||||
export const submenusContribution: IJSONSchema = {
|
||||
description: localize('vscode.extension.contributes.submenus', "(Proposed API) Contributes submenu items to the editor"),
|
||||
type: 'array',
|
||||
items: submenu
|
||||
};
|
||||
|
||||
// --- commands contribution point
|
||||
@@ -437,74 +578,175 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
_commandRegistrations.add(MenuRegistry.addCommands(newCommands));
|
||||
});
|
||||
|
||||
const _menuRegistrations = new DisposableStore();
|
||||
interface IRegisteredSubmenu {
|
||||
readonly id: MenuId;
|
||||
readonly label: string;
|
||||
readonly icon?: { dark: URI; light?: URI; } | ThemeIcon;
|
||||
}
|
||||
|
||||
ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyMenuItem[] }>({
|
||||
extensionPoint: 'menus',
|
||||
jsonSchema: schema.menusContribution
|
||||
}).setHandler(extensions => {
|
||||
const _submenus = new Map<string, IRegisteredSubmenu>();
|
||||
|
||||
// remove all previous menu registrations
|
||||
_menuRegistrations.clear();
|
||||
const submenusExtensionPoint = ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlySubmenu[]>({
|
||||
extensionPoint: 'submenus',
|
||||
jsonSchema: schema.submenusContribution
|
||||
});
|
||||
|
||||
const items: { id: MenuId, item: IMenuItem }[] = [];
|
||||
submenusExtensionPoint.setHandler(extensions => {
|
||||
|
||||
_submenus.clear();
|
||||
|
||||
for (let extension of extensions) {
|
||||
const { value, collector } = extension;
|
||||
|
||||
forEach(value, entry => {
|
||||
if (!schema.isValidMenuItems(entry.value, collector)) {
|
||||
if (!schema.isValidSubmenu(entry.value, collector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const menu = schema.parseMenuId(entry.key);
|
||||
if (typeof menu === 'undefined') {
|
||||
if (!entry.value.id) {
|
||||
collector.warn(localize('submenuId.invalid.id', "`{0}` is not a valid submenu identifier", entry.value.id));
|
||||
return;
|
||||
}
|
||||
if (!entry.value.label) {
|
||||
collector.warn(localize('submenuId.invalid.label', "`{0}` is not a valid submenu label", entry.value.label));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!extension.description.enableProposedApi) {
|
||||
collector.error(localize('submenu.proposedAPI.invalid', "Submenus are proposed API and are only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", extension.description.identifier.value));
|
||||
return;
|
||||
}
|
||||
|
||||
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
|
||||
if (entry.value.icon) {
|
||||
if (typeof entry.value.icon === 'string') {
|
||||
absoluteIcon = ThemeIcon.fromString(entry.value.icon) || { dark: resources.joinPath(extension.description.extensionLocation, entry.value.icon) };
|
||||
} else {
|
||||
absoluteIcon = {
|
||||
dark: resources.joinPath(extension.description.extensionLocation, entry.value.icon.dark),
|
||||
light: resources.joinPath(extension.description.extensionLocation, entry.value.icon.light)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const item: IRegisteredSubmenu = {
|
||||
id: new MenuId(`api:${entry.value.id}`),
|
||||
label: entry.value.label,
|
||||
icon: absoluteIcon
|
||||
};
|
||||
|
||||
_submenus.set(entry.value.id, item);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const _apiMenusByKey = new Map(Iterable.map(Iterable.from(apiMenus), menu => ([menu.key, menu])));
|
||||
const _menuRegistrations = new DisposableStore();
|
||||
|
||||
const menusExtensionPoint = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: (schema.IUserFriendlyMenuItem | schema.IUserFriendlySubmenuItem)[] }>({
|
||||
extensionPoint: 'menus',
|
||||
jsonSchema: schema.menusContribution,
|
||||
deps: [submenusExtensionPoint]
|
||||
});
|
||||
|
||||
menusExtensionPoint.setHandler(extensions => {
|
||||
|
||||
// remove all previous menu registrations
|
||||
_menuRegistrations.clear();
|
||||
|
||||
const items: { id: MenuId, item: IMenuItem | ISubmenuItem }[] = [];
|
||||
|
||||
for (let extension of extensions) {
|
||||
const { value, collector } = extension;
|
||||
|
||||
forEach(value, entry => {
|
||||
if (!schema.isValidItems(entry.value, collector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let menu = _apiMenusByKey.get(entry.key);
|
||||
let isSubmenu = false;
|
||||
|
||||
if (!menu) {
|
||||
const submenu = _submenus.get(entry.key);
|
||||
|
||||
if (submenu) {
|
||||
menu = {
|
||||
key: entry.key,
|
||||
id: submenu.id,
|
||||
description: ''
|
||||
};
|
||||
isSubmenu = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!menu) {
|
||||
collector.warn(localize('menuId.invalid', "`{0}` is not a valid menu identifier", entry.key));
|
||||
return;
|
||||
}
|
||||
|
||||
if (schema.isProposedAPI(menu) && !extension.description.enableProposedApi) {
|
||||
if (menu.proposed && !extension.description.enableProposedApi) {
|
||||
collector.error(localize('proposedAPI.invalid', "{0} is a proposed menu identifier and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", entry.key, extension.description.identifier.value));
|
||||
return;
|
||||
}
|
||||
|
||||
for (let item of entry.value) {
|
||||
let command = MenuRegistry.getCommand(item.command);
|
||||
let alt = item.alt && MenuRegistry.getCommand(item.alt) || undefined;
|
||||
if (isSubmenu && !extension.description.enableProposedApi) {
|
||||
collector.error(localize('proposedAPI.invalid.submenu', "{0} is a submenu identifier and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", entry.key, extension.description.identifier.value));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!command) {
|
||||
collector.error(localize('missing.command', "Menu item references a command `{0}` which is not defined in the 'commands' section.", item.command));
|
||||
continue;
|
||||
}
|
||||
if (item.alt && !alt) {
|
||||
collector.warn(localize('missing.altCommand', "Menu item references an alt-command `{0}` which is not defined in the 'commands' section.", item.alt));
|
||||
}
|
||||
if (item.command === item.alt) {
|
||||
collector.info(localize('dupe.command', "Menu item references the same command as default and alt-command"));
|
||||
for (const menuItem of entry.value) {
|
||||
let item: IMenuItem | ISubmenuItem;
|
||||
|
||||
if (schema.isMenuItem(menuItem)) {
|
||||
const command = MenuRegistry.getCommand(menuItem.command);
|
||||
const alt = menuItem.alt && MenuRegistry.getCommand(menuItem.alt) || undefined;
|
||||
|
||||
if (!command) {
|
||||
collector.error(localize('missing.command', "Menu item references a command `{0}` which is not defined in the 'commands' section.", menuItem.command));
|
||||
continue;
|
||||
}
|
||||
if (menuItem.alt && !alt) {
|
||||
collector.warn(localize('missing.altCommand', "Menu item references an alt-command `{0}` which is not defined in the 'commands' section.", menuItem.alt));
|
||||
}
|
||||
if (menuItem.command === menuItem.alt) {
|
||||
collector.info(localize('dupe.command', "Menu item references the same command as default and alt-command"));
|
||||
}
|
||||
|
||||
item = { command, alt, group: undefined, order: undefined, when: undefined };
|
||||
} else {
|
||||
if (!extension.description.enableProposedApi) {
|
||||
collector.error(localize('proposedAPI.invalid.submenureference', "Menu item references a submenu which is only available when running out of dev or with the following command line switch: --enable-proposed-api {0}", extension.description.identifier.value));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (menu.supportsSubmenus === false) {
|
||||
collector.error(localize('proposedAPI.unsupported.submenureference', "Menu item references a submenu for a menu which doesn't have submenu support."));
|
||||
continue;
|
||||
}
|
||||
|
||||
const submenu = _submenus.get(menuItem.submenu);
|
||||
|
||||
if (!submenu) {
|
||||
collector.error(localize('missing.submenu', "Menu item references a submenu `{0}` which is not defined in the 'submenus' section.", menuItem.submenu));
|
||||
continue;
|
||||
}
|
||||
|
||||
item = { submenu: submenu.id, icon: submenu.icon, title: submenu.label, group: undefined, order: undefined, when: undefined };
|
||||
}
|
||||
|
||||
let group: string | undefined;
|
||||
let order: number | undefined;
|
||||
if (item.group) {
|
||||
const idx = item.group.lastIndexOf('@');
|
||||
if (menuItem.group) {
|
||||
const idx = menuItem.group.lastIndexOf('@');
|
||||
if (idx > 0) {
|
||||
group = item.group.substr(0, idx);
|
||||
order = Number(item.group.substr(idx + 1)) || undefined;
|
||||
item.group = menuItem.group.substr(0, idx);
|
||||
item.order = Number(menuItem.group.substr(idx + 1)) || undefined;
|
||||
} else {
|
||||
group = item.group;
|
||||
item.group = menuItem.group;
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
id: menu,
|
||||
item: {
|
||||
command,
|
||||
alt,
|
||||
group,
|
||||
order,
|
||||
when: ContextKeyExpr.deserialize(item.when)
|
||||
}
|
||||
});
|
||||
item.when = ContextKeyExpr.deserialize(menuItem.when);
|
||||
items.push({ id: menu.id, item });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ export class ExtHostTask extends ExtHostTaskBase {
|
||||
platform: process.platform
|
||||
});
|
||||
}
|
||||
this._proxy.$registerSupportedExecutions(true, true, true);
|
||||
}
|
||||
|
||||
public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution> {
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, Separator } from 'vs/base/common/actions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, IActionRunner, ActionRunner, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { Component } from 'vs/workbench/common/component';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IComposite, ICompositeControl } from 'vs/workbench/common/composite';
|
||||
|
||||
@@ -15,10 +15,9 @@ import { Composite } from 'vs/workbench/browser/composite';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { ViewPaneContainer } from './parts/views/viewPaneContainer';
|
||||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem, Separator } from 'vs/base/common/actions';
|
||||
import { ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
||||
import { MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
|
||||
export class PaneComposite extends Composite implements IPaneComposite {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { SyncActionDescriptor, IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions';
|
||||
@@ -27,12 +27,11 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import { AuthenticationSession } from 'vs/editor/common/modes';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class ViewContainerActivityAction extends ActivityAction {
|
||||
@@ -163,7 +162,7 @@ export class AccountsActionViewItem extends ActivityActionViewItem {
|
||||
});
|
||||
|
||||
const result = await Promise.all(allSessions);
|
||||
let menus: (IAction | ContextSubMenu)[] = [];
|
||||
let menus: IAction[] = [];
|
||||
result.forEach(sessionInfo => {
|
||||
const providerDisplayName = this.authenticationService.getLabel(sessionInfo.providerId);
|
||||
Object.keys(sessionInfo.sessions).forEach(accountName => {
|
||||
@@ -177,7 +176,7 @@ export class AccountsActionViewItem extends ActivityActionViewItem {
|
||||
|
||||
const actions = hasEmbedderAccountSession ? [manageExtensionsAction] : [manageExtensionsAction, signOutAction];
|
||||
|
||||
const menu = new ContextSubMenu(`${accountName} (${providerDisplayName})`, actions);
|
||||
const menu = new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, actions);
|
||||
menus.push(menu);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/activitybarpart';
|
||||
import * as nls from 'vs/nls';
|
||||
import { ActionsOrientation, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { GLOBAL_ACTIVITY_ID, IActivity, ACCOUNTS_ACTIIVTY_ID } from 'vs/workbench/common/activity';
|
||||
import { Part } from 'vs/workbench/browser/part';
|
||||
import { GlobalActivityActionViewItem, ViewContainerActivityAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewContainerActivityAction, HomeAction, HomeActionViewItem, ACCOUNTS_VISIBILITY_PREFERENCE_KEY } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
|
||||
@@ -37,7 +37,7 @@ import { isWeb } from 'vs/base/common/platform';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { Before2D } from 'vs/workbench/browser/dnd';
|
||||
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Action, Separator } from 'vs/base/common/actions';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { Dimension, $, addDisposableListener, EventType, EventHelper, toggleClass, isAncestor } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
@@ -629,7 +629,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
});
|
||||
}
|
||||
|
||||
private getContextMenuActions(): ReadonlyArray<IAction> {
|
||||
private getContextMenuActions(): IAction[] {
|
||||
const actions: IAction[] = this.model.visibleItems
|
||||
.map(({ id, name, activityAction }) => (<IAction>{
|
||||
id,
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Action, Separator } from 'vs/base/common/actions';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { BaseActionViewItem, IBaseActionViewItemOptions, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { dispose, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
@@ -21,6 +20,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D, toggleDropEffect } from 'vs/workbench/browser/dnd';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { IBaseActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export interface ICompositeActivity {
|
||||
badge: IBadge;
|
||||
|
||||
@@ -11,9 +11,9 @@ import * as strings from 'vs/base/common/strings';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IActionViewItem, ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { Part, IPartOptions } from 'vs/workbench/browser/part';
|
||||
import { Composite, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
import { IComposite } from 'vs/workbench/common/composite';
|
||||
|
||||
@@ -7,16 +7,16 @@ import 'vs/css!./media/titlecontrol';
|
||||
import { applyDragImage, DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, IActionViewItem } from 'vs/base/common/actions';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { getCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { localize } from 'vs/nls';
|
||||
import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { ExecuteCommandAction, IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { createAndFillInActionBarActions, createAndFillInContextMenuActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { ExecuteCommandAction, IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
@@ -164,17 +164,22 @@ export abstract class TitleControl extends Themable {
|
||||
const activeEditorPane = this.group.activeEditorPane;
|
||||
|
||||
// Check Active Editor
|
||||
let actionViewItem: IActionViewItem | undefined = undefined;
|
||||
if (activeEditorPane instanceof BaseEditor) {
|
||||
actionViewItem = activeEditorPane.getActionViewItem(action);
|
||||
const result = activeEditorPane.getActionViewItem(action);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Check extensions
|
||||
if (!actionViewItem) {
|
||||
actionViewItem = createActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
if (action instanceof MenuItemAction) {
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return actionViewItem;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected updateEditorActionsToolbar(): void {
|
||||
|
||||
@@ -16,7 +16,6 @@ import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { dispose, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { INotificationViewItem, NotificationViewItem, NotificationViewItemContentChangeKind, INotificationMessage, ChoiceAction } from 'vs/workbench/common/notifications';
|
||||
import { ClearNotificationAction, ExpandNotificationAction, CollapseNotificationAction, ConfigureNotificationAction } from 'vs/workbench/browser/parts/notifications/notificationsActions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -24,6 +23,7 @@ import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { Severity } from 'vs/platform/notification/common/notification';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
|
||||
export class NotificationsListDelegate implements IListVirtualDelegate<INotificationViewItem> {
|
||||
|
||||
@@ -211,7 +211,7 @@ export class NotificationRenderer implements IListRenderer<INotificationViewItem
|
||||
ariaLabel: localize('notificationActions', "Notification Actions"),
|
||||
actionViewItemProvider: action => {
|
||||
if (action && action instanceof ConfigureNotificationAction) {
|
||||
const item = new DropdownMenuActionViewItem(action, action.configurationActions, this.contextMenuService, undefined, this.actionRunner, undefined, action.class);
|
||||
const item = new DropdownMenuActionViewItem(action, action.configurationActions, this.contextMenuService, { actionRunner: this.actionRunner, classNames: action.class });
|
||||
data.toDispose.add(item);
|
||||
|
||||
return item;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions';
|
||||
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
|
||||
import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -29,7 +29,6 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Command } from 'vs/editor/common/modes';
|
||||
|
||||
@@ -8,8 +8,7 @@ import { IMenuService, MenuId, IMenu, SubmenuItemAction, registerAction2, Action
|
||||
import { registerThemingParticipant, IColorTheme, ICssStyleCollector, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { MenuBarVisibility, getTitleBarStyle, IWindowOpenable, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, Action, SubmenuAction, Separator } from 'vs/base/common/actions';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { isMacintosh, isWeb, isIOS } from 'vs/base/common/platform';
|
||||
@@ -27,7 +26,7 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { MenuBar, IMenuBarOptions } from 'vs/base/browser/ui/menu/menubar';
|
||||
import { SubmenuAction, Direction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { Direction } from 'vs/base/browser/ui/menu/menu';
|
||||
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
|
||||
import { mnemonicMenuLabel, unmnemonicLabel } from 'vs/base/common/labels';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
@@ -600,7 +599,7 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
|
||||
const submenuActions: SubmenuAction[] = [];
|
||||
updateActions(submenu, submenuActions, topLevelTitle);
|
||||
target.push(new SubmenuAction(mnemonicMenuLabel(action.label), submenuActions));
|
||||
target.push(new SubmenuAction(action.id, mnemonicMenuLabel(action.label), submenuActions));
|
||||
} else {
|
||||
action.label = mnemonicMenuLabel(this.calculateActionLabel(action));
|
||||
target.push(action);
|
||||
|
||||
@@ -12,8 +12,8 @@ import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND,
|
||||
import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom';
|
||||
import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IActionViewItem, ActionsOrientation, Separator, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -33,8 +33,8 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { Component } from 'vs/workbench/common/component';
|
||||
import { MenuId, MenuItemAction, registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { MenuId, MenuItemAction, registerAction2, Action2, IAction2Options, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
||||
import { parseLinkedText } from 'vs/base/common/linkedText';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
@@ -482,7 +482,9 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
|
||||
getActionViewItem(action: IAction): IActionViewItem | undefined {
|
||||
if (action instanceof MenuItemAction) {
|
||||
return this.instantiationService.createInstance(ContextAwareMenuEntryActionViewItem, action);
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
@@ -26,8 +26,6 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { PaneComposite } from 'vs/workbench/browser/panecomposite';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
||||
export abstract class Viewlet extends PaneComposite implements IViewlet {
|
||||
@@ -79,7 +77,7 @@ export abstract class Viewlet extends PaneComposite implements IViewlet {
|
||||
}
|
||||
|
||||
return [
|
||||
new ContextSubMenu(nls.localize('views', "Views"), viewVisibilityActions),
|
||||
new SubmenuAction('workbench.views', nls.localize('views', "Views"), viewVisibilityActions),
|
||||
new Separator(),
|
||||
...secondaryActions
|
||||
];
|
||||
|
||||
@@ -32,9 +32,9 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { TreeMouseEventTarget, ITreeNode } from 'vs/base/browser/ui/tree/tree';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
|
||||
const enum State {
|
||||
Loading = 'loading',
|
||||
@@ -94,7 +94,7 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
super(editor, { showFrame: true, showArrow: true, isResizeable: true, isAccessible: true });
|
||||
super(editor, { showFrame: true, showArrow: true, isResizeable: true, isAccessible: true }, _instantiationService);
|
||||
this.create();
|
||||
this._peekViewService.addExclusiveWidget(editor, this);
|
||||
this._applyTheme(themeService.getColorTheme());
|
||||
@@ -142,8 +142,8 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
|
||||
|
||||
protected _getActionBarOptions(): IActionBarOptions {
|
||||
return {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
actionViewItemProvider: action => action instanceof MenuItemAction ? this._instantiationService.createInstance(MenuEntryActionViewItem, action) : undefined
|
||||
...super._getActionBarOptions(),
|
||||
orientation: ActionsOrientation.HORIZONTAL
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ActionsOrientation, ActionViewItem, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IActionRunner, IAction } from 'vs/base/common/actions';
|
||||
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IActionRunner, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -23,17 +23,17 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { ToggleReactionsAction, ReactionAction, ReactionActionViewItem } from './reactionsAction';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget';
|
||||
import { MenuItemAction, SubmenuItemAction, IMenu } from 'vs/platform/actions/common/actions';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commentFormActions';
|
||||
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
|
||||
export class CommentNode extends Disposable {
|
||||
private _domNode: HTMLElement;
|
||||
@@ -79,7 +79,6 @@ export class CommentNode extends Disposable {
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
@@ -154,13 +153,12 @@ export class CommentNode extends Disposable {
|
||||
action,
|
||||
(<ToggleReactionsAction>action).menuActions,
|
||||
this.contextMenuService,
|
||||
action => {
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
},
|
||||
this.actionRunner!,
|
||||
undefined,
|
||||
'toolbar-toggle-pickReactions codicon codicon-reactions',
|
||||
() => { return AnchorAlignment.RIGHT; }
|
||||
{
|
||||
actionViewItemProvider: action => this.actionViewItemProvider(action as Action),
|
||||
actionRunner: this.actionRunner,
|
||||
classNames: ['toolbar-toggle-pickReactions', 'codicon', 'codicon-reactions'],
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
}
|
||||
);
|
||||
}
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
@@ -221,8 +219,9 @@ export class CommentNode extends Disposable {
|
||||
let item = new ReactionActionViewItem(action);
|
||||
return item;
|
||||
} else if (action instanceof MenuItemAction) {
|
||||
let item = new ContextAwareMenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
return item;
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
} else {
|
||||
let item = new ActionViewItem({}, action, options);
|
||||
return item;
|
||||
@@ -259,16 +258,17 @@ export class CommentNode extends Disposable {
|
||||
toggleReactionAction,
|
||||
(<ToggleReactionsAction>toggleReactionAction).menuActions,
|
||||
this.contextMenuService,
|
||||
action => {
|
||||
if (action.id === ToggleReactionsAction.ID) {
|
||||
return toggleReactionActionViewItem;
|
||||
}
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
},
|
||||
this.actionRunner!,
|
||||
undefined,
|
||||
'toolbar-toggle-pickReactions',
|
||||
() => { return AnchorAlignment.RIGHT; }
|
||||
{
|
||||
actionViewItemProvider: action => {
|
||||
if (action.id === ToggleReactionsAction.ID) {
|
||||
return toggleReactionActionViewItem;
|
||||
}
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
},
|
||||
actionRunner: this.actionRunner,
|
||||
classNames: 'toolbar-toggle-pickReactions',
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
}
|
||||
);
|
||||
|
||||
return toggleReactionAction;
|
||||
@@ -283,13 +283,12 @@ export class CommentNode extends Disposable {
|
||||
action,
|
||||
(<ToggleReactionsAction>action).menuActions,
|
||||
this.contextMenuService,
|
||||
action => {
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
},
|
||||
this.actionRunner!,
|
||||
undefined,
|
||||
'toolbar-toggle-pickReactions',
|
||||
() => { return AnchorAlignment.RIGHT; }
|
||||
{
|
||||
actionViewItemProvider: action => this.actionViewItemProvider(action as Action),
|
||||
actionRunner: this.actionRunner,
|
||||
classNames: 'toolbar-toggle-pickReactions',
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
}
|
||||
);
|
||||
}
|
||||
return this.actionViewItemProvider(action as Action);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
@@ -26,13 +26,10 @@ import { MarkdownRenderer } from 'vs/editor/contrib/markdown/markdownRenderer';
|
||||
import { peekViewBorder } from 'vs/editor/contrib/peekView/peekView';
|
||||
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/zoneWidget';
|
||||
import * as nls from 'vs/nls';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenu, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { contrastBorder, editorForeground, focusBorder, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
@@ -49,6 +46,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
|
||||
const COLLAPSE_ACTION_CLASS = 'expand-review-action codicon-chevron-up';
|
||||
@@ -109,15 +107,12 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
private _owner: string,
|
||||
private _commentThread: modes.CommentThread,
|
||||
private _pendingComment: string | null,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IThemeService private themeService: IThemeService,
|
||||
@ICommentService private commentService: ICommentService,
|
||||
@IOpenerService private openerService: IOpenerService,
|
||||
@IKeybindingService private keybindingService: IKeybindingService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
) {
|
||||
super(editor, { keepEditorSelection: true });
|
||||
@@ -239,11 +234,11 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, {
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action instanceof MenuItemAction) {
|
||||
let item = new ContextAwareMenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
return item;
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
} else {
|
||||
let item = new ActionViewItem({}, action, { label: false, icon: true });
|
||||
return item;
|
||||
return new ActionViewItem({}, action, { label: false, icon: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { $ } from 'vs/base/browser/dom';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { coalesce, findFirstInSorted } from 'vs/base/common/arrays';
|
||||
@@ -547,8 +546,8 @@ export class CommentController implements IEditorContribution {
|
||||
return picks;
|
||||
}
|
||||
|
||||
private getContextMenuActions(commentInfos: { ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges }[], lineNumber: number): (IAction | ContextSubMenu)[] {
|
||||
const actions: (IAction | ContextSubMenu)[] = [];
|
||||
private getContextMenuActions(commentInfos: { ownerId: string, extensionId: string | undefined, label: string | undefined, commentingRangesInfo: modes.CommentingRanges }[], lineNumber: number): IAction[] {
|
||||
const actions: IAction[] = [];
|
||||
|
||||
commentInfos.forEach(commentInfo => {
|
||||
const { ownerId, extensionId, label } = commentInfo;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export class ToggleReactionsAction extends Action {
|
||||
static readonly ID = 'toolbar.toggle.pickReactions';
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as env from 'vs/base/common/platform';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import severity from 'vs/base/common/severity';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ICodeEditor, IEditorMouseEvent, MouseTargetType, IContentWidget, IActiveCodeEditor, IContentWidgetPosition, ContentWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
|
||||
import { IModelDecorationOptions, IModelDeltaDecoration, TrackedRangeStickiness, ITextModel, OverviewRulerLane, IModelDecorationOverviewRulerOptions } from 'vs/editor/common/model';
|
||||
@@ -18,7 +18,6 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
||||
import { RemoveBreakpointAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, BreakpointWidgetContext, IBreakpointEditorContribution, IBreakpointUpdateData, IDebugConfiguration, State, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { BreakpointWidget } from 'vs/workbench/contrib/debug/browser/breakpointWidget';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -288,8 +287,8 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
|
||||
}));
|
||||
}
|
||||
|
||||
private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: URI, lineNumber: number, column?: number): Array<IAction | ContextSubMenu> {
|
||||
const actions: Array<IAction | ContextSubMenu> = [];
|
||||
private getContextMenuActions(breakpoints: ReadonlyArray<IBreakpoint>, uri: URI, lineNumber: number, column?: number): IAction[] {
|
||||
const actions: IAction[] = [];
|
||||
if (breakpoints.length === 1) {
|
||||
const breakpointType = breakpoints[0].logMessage ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint");
|
||||
actions.push(new RemoveBreakpointAction(RemoveBreakpointAction.ID, nls.localize('removeBreakpoint', "Remove {0}", breakpointType), this.debugService));
|
||||
@@ -310,7 +309,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
|
||||
));
|
||||
} else if (breakpoints.length > 1) {
|
||||
const sorted = breakpoints.slice().sort((first, second) => (first.column && second.column) ? first.column - second.column : 1);
|
||||
actions.push(new ContextSubMenu(nls.localize('removeBreakpoints', "Remove Breakpoints"), sorted.map(bp => new Action(
|
||||
actions.push(new SubmenuAction('debug.removeBreakpoints', nls.localize('removeBreakpoints', "Remove Breakpoints"), sorted.map(bp => new Action(
|
||||
'removeInlineBreakpoint',
|
||||
bp.column ? nls.localize('removeInlineBreakpointOnColumn', "Remove Inline Breakpoint on Column {0}", bp.column) : nls.localize('removeLineBreakpoint', "Remove Line Breakpoint"),
|
||||
undefined,
|
||||
@@ -318,7 +317,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
|
||||
() => this.debugService.removeBreakpoints(bp.getId())
|
||||
))));
|
||||
|
||||
actions.push(new ContextSubMenu(nls.localize('editBreakpoints', "Edit Breakpoints"), sorted.map(bp =>
|
||||
actions.push(new SubmenuAction('debug.editBReakpoints', nls.localize('editBreakpoints', "Edit Breakpoints"), sorted.map(bp =>
|
||||
new Action('editBreakpoint',
|
||||
bp.column ? nls.localize('editInlineBreakpointOnColumn', "Edit Inline Breakpoint on Column {0}", bp.column) : nls.localize('editLineBrekapoint', "Edit Line Breakpoint"),
|
||||
undefined,
|
||||
@@ -327,7 +326,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
|
||||
)
|
||||
)));
|
||||
|
||||
actions.push(new ContextSubMenu(nls.localize('enableDisableBreakpoints', "Enable/Disable Breakpoints"), sorted.map(bp => new Action(
|
||||
actions.push(new SubmenuAction('debug.enableDisableBreakpoints', nls.localize('enableDisableBreakpoints', "Enable/Disable Breakpoints"), sorted.map(bp => new Action(
|
||||
bp.enabled ? 'disableColumnBreakpoint' : 'enableColumnBreakpoint',
|
||||
bp.enabled ? (bp.column ? nls.localize('disableInlineColumnBreakpoint', "Disable Inline Breakpoint on Column {0}", bp.column) : nls.localize('disableBreakpointOnLine', "Disable Line Breakpoint"))
|
||||
: (bp.column ? nls.localize('enableBreakpoints', "Enable Inline Breakpoint on Column {0}", bp.column) : nls.localize('enableBreakpointOnLine', "Enable Line Breakpoint")),
|
||||
@@ -548,7 +547,7 @@ class InlineBreakpointWidget implements IContentWidget, IDisposable {
|
||||
private readonly breakpoint: IBreakpoint | undefined,
|
||||
private readonly debugService: IDebugService,
|
||||
private readonly contextMenuService: IContextMenuService,
|
||||
private readonly getContextMenuActions: () => ReadonlyArray<IAction | ContextSubMenu>
|
||||
private readonly getContextMenuActions: () => IAction[]
|
||||
) {
|
||||
this.range = this.editor.getModel().getDecorationRange(decorationId);
|
||||
this.toDispose.push(this.editor.onDidChangeModelDecorations(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, Separator } from 'vs/base/common/actions';
|
||||
import { IDebugService, IBreakpoint, CONTEXT_BREAKPOINTS_FOCUSED, State, DEBUG_SCHEME, IFunctionBreakpoint, IExceptionBreakpoint, IEnablement, BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution, IDebugModel, IDataBreakpoint } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, DataBreakpoint } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { AddFunctionBreakpointAction, ToggleBreakpointsActivatedAction, RemoveAllBreakpointsAction, RemoveBreakpointAction, EnableAllBreakpointsAction, DisableAllBreakpointsAction, ReapplyBreakpointsAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
@@ -16,7 +16,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IListVirtualDelegate, IListContextMenuEvent, IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IDebugService, State, IStackFrame, IDebugSession, IThread, CONTEXT_CALL
|
||||
import { Thread, StackFrame, ThreadAndSessionIds } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { MenuId, IMenu, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { MenuId, IMenu, IMenuService, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { renderViewTree } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
@@ -21,7 +21,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
|
||||
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { createAndFillInContextMenuActions, createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { ITreeNode, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||
import { WorkbenchCompressibleAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
@@ -489,10 +489,7 @@ class SessionsRenderer implements ICompressibleTreeRenderer<IDebugSession, Fuzzy
|
||||
constructor(
|
||||
private menu: IMenu,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IDebugService private readonly debugService: IDebugService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService
|
||||
@IDebugService private readonly debugService: IDebugService
|
||||
) { }
|
||||
|
||||
get templateId(): string {
|
||||
@@ -509,8 +506,9 @@ class SessionsRenderer implements ICompressibleTreeRenderer<IDebugSession, Fuzzy
|
||||
const actionBar = new ActionBar(session, {
|
||||
actionViewItemProvider: action => {
|
||||
if (action instanceof MenuItemAction) {
|
||||
// We need the MenuEntryActionViewItem so the icon would get rendered
|
||||
return new MenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { IAction, IActionRunner, IActionViewItem } from 'vs/base/common/actions';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { SelectBox, ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { SelectActionViewItem, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch } from 'vs/workbench/contrib/debug/common/debug';
|
||||
@@ -20,6 +19,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ADD_CONFIGURATION_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import * as browser from 'vs/base/browser/browser';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions';
|
||||
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/contrib/debug/common/debug';
|
||||
@@ -21,13 +21,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { registerThemingParticipant, IThemeService, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { registerColor, contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { createAndFillInActionBarActions, MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenu, IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -57,7 +56,6 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IMenuService menuService: IMenuService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@@ -80,9 +78,10 @@ export class DebugToolBar extends Themable implements IWorkbenchContribution {
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action.id === FocusSessionAction.ID) {
|
||||
return this.instantiationService.createInstance(FocusSessionActionViewItem, action);
|
||||
}
|
||||
if (action instanceof MenuItemAction) {
|
||||
return new MenuEntryActionViewItem(action, this.keybindingService, this.notificationService, contextMenuService);
|
||||
} else if (action instanceof MenuItemAction) {
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
|
||||
import 'vs/css!./media/debugViewlet';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IDebugService, VIEWLET_ID, State, BREAKPOINTS_VIEW_ID, IDebugConfiguration, CONTEXT_DEBUG_UX, CONTEXT_DEBUG_UX_KEY, REPL_VIEW_ID } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { StartAction, ConfigureAction, SelectAndStartAction, FocusSessionAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems';
|
||||
@@ -24,12 +23,10 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IMenu, MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IMenu, MenuId, IMenuService, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views';
|
||||
import { WelcomeView } from 'vs/workbench/contrib/debug/browser/welcomeView';
|
||||
import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
@@ -55,11 +52,9 @@ export class DebugViewPaneContainer extends ViewPaneContainer {
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService
|
||||
) {
|
||||
super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
|
||||
@@ -165,7 +160,9 @@ export class DebugViewPaneContainer extends ViewPaneContainer {
|
||||
return new FocusSessionActionViewItem(action, this.debugService, this.themeService, this.contextViewService, this.configurationService);
|
||||
}
|
||||
if (action instanceof MenuItemAction) {
|
||||
return new MenuEntryActionViewItem(action, this.keybindingService, this.notificationService, this.contextMenuService);
|
||||
return this.instantiationService.createInstance(MenuEntryActionViewItem, action);
|
||||
} else if (action instanceof SubmenuItemAction) {
|
||||
return this.instantiationService.createInstance(SubmenuEntryActionViewItem, action);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.monaco-workbench .debug-toolbar .monaco-action-bar .action-item > .action-label {
|
||||
.monaco-workbench .debug-toolbar .monaco-action-bar .action-item .action-label {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 0;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/repl';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { IAction, IActionViewItem, Action } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem, Action, Separator } from 'vs/base/common/actions';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -41,7 +41,6 @@ import { first } from 'vs/base/common/arrays';
|
||||
import { ITreeNode, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { LinkDetector } from 'vs/workbench/contrib/debug/browser/linkDetector';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { removeAnsiEscapeCodes } from 'vs/base/common/strings';
|
||||
import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
@@ -440,7 +439,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
return this.instantiationService.createInstance(SelectReplActionViewItem, this.selectReplAction);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return super.getActionViewItem(action);
|
||||
}
|
||||
|
||||
getActions(): IAction[] {
|
||||
|
||||
@@ -13,9 +13,8 @@ import { Variable, Scope, ErrorScope, StackFrame } from 'vs/workbench/contrib/de
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { renderViewTree, renderVariable, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, Separator } from 'vs/base/common/actions';
|
||||
import { CopyValueAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
|
||||
@@ -14,8 +14,7 @@ import { AddWatchExpressionAction, RemoveAllWatchExpressionsAction, CopyValueAct
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, Action, Separator } from 'vs/base/common/actions';
|
||||
import { renderExpressionValue, renderViewTree, IInputBoxOptions, AbstractExpressionsRenderer, IExpressionTemplateData } from 'vs/workbench/contrib/debug/browser/baseDebugView';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
import 'vs/css!./media/extensionActions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { ActionViewItem, Separator, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, AutoUpdateConfigurationKey, IExtensionContainer, EXTENSIONS_CONFIG, TOGGLE_IGNORE_EXTENSION_ACTION_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
@@ -61,6 +60,7 @@ import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/d
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { IActionViewItemOptions, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; // {{SQL CARBON EDIT}}
|
||||
import product from 'vs/platform/product/common/product';
|
||||
@@ -729,7 +729,7 @@ export class DropDownMenuActionViewItem extends ExtensionActionViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
export function getContextMenuActions(menuService: IMenuService, contextKeyService: IContextKeyService, instantiationService: IInstantiationService, extension: IExtension | undefined | null): ExtensionAction[][] {
|
||||
export function getContextMenuActions(menuService: IMenuService, contextKeyService: IContextKeyService, instantiationService: IInstantiationService, extension: IExtension | undefined | null): IAction[][] {
|
||||
const scopedContextKeyService = contextKeyService.createScoped();
|
||||
if (extension) {
|
||||
scopedContextKeyService.createKey<string>('extension', extension.identifier.id);
|
||||
@@ -740,9 +740,14 @@ export function getContextMenuActions(menuService: IMenuService, contextKeyServi
|
||||
}
|
||||
}
|
||||
|
||||
const groups: ExtensionAction[][] = [];
|
||||
const groups: IAction[][] = [];
|
||||
const menu = menuService.createMenu(MenuId.ExtensionContext, scopedContextKeyService);
|
||||
menu.getActions({ shouldForwardArgs: true }).forEach(([, actions]) => groups.push(actions.map(action => instantiationService.createInstance(MenuItemExtensionAction, action))));
|
||||
menu.getActions({ shouldForwardArgs: true }).forEach(([, actions]) => groups.push(actions.map(action => {
|
||||
if (action instanceof SubmenuAction) {
|
||||
return action;
|
||||
}
|
||||
return instantiationService.createInstance(MenuItemExtensionAction, action);
|
||||
})));
|
||||
menu.dispose();
|
||||
|
||||
return groups;
|
||||
@@ -771,7 +776,7 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
|
||||
}
|
||||
|
||||
async getActionGroups(runningExtensions: IExtensionDescription[]): Promise<IAction[][]> {
|
||||
const groups: ExtensionAction[][] = [];
|
||||
const groups: IAction[][] = [];
|
||||
if (this.extension) {
|
||||
const actions = await Promise.all([
|
||||
SetColorThemeAction.create(this.workbenchThemeService, this.instantiationService, this.extension),
|
||||
@@ -802,7 +807,11 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
|
||||
|
||||
getContextMenuActions(this.menuService, this.contextKeyService, this.instantiationService, this.extension).forEach(actions => groups.push(actions));
|
||||
|
||||
groups.forEach(group => group.forEach(extensionAction => extensionAction.extension = this.extension));
|
||||
groups.forEach(group => group.forEach(extensionAction => {
|
||||
if (extensionAction instanceof ExtensionAction) {
|
||||
extensionAction.extension = this.extension;
|
||||
}
|
||||
}));
|
||||
|
||||
return groups;
|
||||
}
|
||||
@@ -1769,7 +1778,28 @@ export class ShowPopularExtensionsAction extends Action {
|
||||
return this.viewletService.openViewlet(VIEWLET_ID, true)
|
||||
.then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)
|
||||
.then(viewlet => {
|
||||
viewlet.search('@sort:installs ');
|
||||
viewlet.search('@popular ');
|
||||
viewlet.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class PredefinedExtensionFilterAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private readonly filter: string,
|
||||
@IViewletService private readonly viewletService: IViewletService
|
||||
) {
|
||||
super(id, label, undefined, true);
|
||||
}
|
||||
|
||||
run(): Promise<void> {
|
||||
return this.viewletService.openViewlet(VIEWLET_ID, true)
|
||||
.then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer)
|
||||
.then(viewlet => {
|
||||
viewlet.search(`${this.filter} `);
|
||||
viewlet.focus();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event as EventOf, Emitter } from 'vs/base/common/event';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { Separator, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, Action, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { append, $, addClass, toggleClass, Dimension, hide, show } from 'vs/base/browser/dom';
|
||||
@@ -20,11 +19,12 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, AutoUpdateConfigurationKey, CloseExtensionDetailsOnViewChangeKey } from '../common/extensions';
|
||||
import {
|
||||
ShowRecommendedExtensionsAction, /*ShowPopularExtensionsAction,*/
|
||||
ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, SearchCategoryAction, /*RecentlyPublishedExtensionsAction, */ShowInstalledExtensionsAction, ShowOutdatedExtensionsAction, ShowDisabledExtensionsAction, ShowEnabledExtensionsAction
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, SearchCategoryAction,
|
||||
/*RecentlyPublishedExtensionsAction, */ShowInstalledExtensionsAction, ShowOutdatedExtensionsAction, ShowDisabledExtensionsAction,
|
||||
ShowEnabledExtensionsAction, PredefinedExtensionFilterAction
|
||||
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInFeatureExtensionsView, BuiltInThemesExtensionsView, BuiltInProgrammingLanguageExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView, OutdatedExtensionsView, InstalledExtensionsView, SearchBuiltInExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
@@ -59,8 +59,6 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr
|
||||
import { DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
|
||||
const NonEmptyWorkspaceContext = new RawContextKey<boolean>('nonEmptyWorkspace', false);
|
||||
const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
|
||||
@@ -347,6 +345,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@@ -497,41 +496,43 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
}
|
||||
|
||||
getActions(): IAction[] {
|
||||
const filterActions: IAction[] = [];
|
||||
|
||||
// Local extensions filters
|
||||
filterActions.push(...[
|
||||
this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, localize('builtin filter', "Built-in")),
|
||||
this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, localize('installed filter', "Installed")),
|
||||
this.instantiationService.createInstance(ShowEnabledExtensionsAction, ShowEnabledExtensionsAction.ID, localize('enabled filter', "Enabled")),
|
||||
this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, localize('disabled filter', "Disabled")),
|
||||
this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, localize('outdated filter', "Outdated")),
|
||||
]);
|
||||
|
||||
if (this.extensionGalleryService.isEnabled()) {
|
||||
filterActions.splice(0, 0, ...[
|
||||
// this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.featured', localize('featured filter', "Featured"), '@featured'), // {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.popular', localize('most popular filter', "Most Popular"), '@popular'), // {{SQL CARBON EDIT}}
|
||||
this.instantiationService.createInstance(PredefinedExtensionFilterAction, 'extensions.filter.recommended', localize('most popular recommended', "Recommended"), '@recommended'),
|
||||
// this.instantiationService.createInstance(RecentlyPublishedExtensionsAction, RecentlyPublishedExtensionsAction.ID, localize('recently published filter', "Recently Published")), // {{SQL CARBON EDIT}}
|
||||
new SubmenuAction('workbench.extensions.action.filterExtensionsByCategory', localize('filter by category', "Category"), EXTENSION_CATEGORIES.map(category => this.instantiationService.createInstance(SearchCategoryAction, `extensions.actions.searchByCategory.${category}`, category, category))),
|
||||
new Separator(),
|
||||
]);
|
||||
filterActions.push(...[
|
||||
new Separator(),
|
||||
new SubmenuAction('workbench.extensions.action.sortBy', localize('sorty by', "Sort By"), [
|
||||
// this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install', localize('sort by installs', "Install Count"), this.onSearchChange, 'installs'), // {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.rating', localize('sort by rating', "Rating"), this.onSearchChange, 'rating'), // {{SQL CARBON EDIT}}
|
||||
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.name', localize('sort by name', "Name"), this.onSearchChange, 'name'),
|
||||
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.publishedDate', localize('sort by date', "Published Date"), this.onSearchChange, 'publishedDate'),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
new Action('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), 'codicon-filter', true),
|
||||
new SubmenuAction('workbench.extensions.action.filterExtensions', localize('filterExtensions', "Filter Extensions..."), filterActions, 'codicon-filter'),
|
||||
this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, this.searchBox ? this.searchBox.getValue() : ''),
|
||||
];
|
||||
}
|
||||
|
||||
getActionViewItem(action: IAction): IActionViewItem | undefined {
|
||||
if (action.id === 'workbench.extensions.action.filterExtensions') {
|
||||
return new DropdownMenuActionViewItem(action,
|
||||
[
|
||||
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, localize('most popular filter', "Most Popular")), // {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(RecentlyPublishedExtensionsAction, RecentlyPublishedExtensionsAction.ID, localize('recently published filter', "Recently Published")), // {{SQL CARBON EDIT}}
|
||||
this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('recomended filter', "Recommended")),
|
||||
new ContextSubMenu(localize('filter by category', "Category"), EXTENSION_CATEGORIES.map(category => this.instantiationService.createInstance(SearchCategoryAction, `extensions.actions.searchByCategory.${category}`, category, category))),
|
||||
|
||||
new Separator(),
|
||||
this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, localize('builtin filter', "Built-in")),
|
||||
this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, localize('installed filter', "Installed")),
|
||||
this.instantiationService.createInstance(ShowEnabledExtensionsAction, ShowEnabledExtensionsAction.ID, localize('enabled filter', "Enabled")),
|
||||
this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, localize('disabled filter', "Disabled")),
|
||||
this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, localize('outdated filter', "Outdated")),
|
||||
|
||||
new Separator(),
|
||||
new ContextSubMenu(localize('sorty by', "Sort By"), [
|
||||
// this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install', localize('sort by installs', "Install Count"), this.onSearchChange, 'installs'), // {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.rating', localize('sort by rating', "Rating"), this.onSearchChange, 'rating'), // {{SQL CARBON EDIT}}
|
||||
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.name', localize('sort by name', "Name"), this.onSearchChange, 'name'),
|
||||
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.publishedDate', localize('sort by date', "Published Date"), this.onSearchChange, 'publishedDate'),
|
||||
]),
|
||||
],
|
||||
this.contextMenuService, undefined, undefined, undefined, 'codicon-filter', undefined, true);
|
||||
}
|
||||
return super.getActionViewItem(action);
|
||||
}
|
||||
|
||||
getSecondaryActions(): IAction[] {
|
||||
const actions: IAction[] = [];
|
||||
|
||||
@@ -541,11 +542,13 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
} else {
|
||||
actions.push(this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL));
|
||||
}
|
||||
actions.push(this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL));
|
||||
|
||||
actions.push(new Separator());
|
||||
actions.push(this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL));
|
||||
actions.push(this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL));
|
||||
actions.push(this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL));
|
||||
|
||||
actions.push(new Separator());
|
||||
actions.push(this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL));
|
||||
|
||||
return actions;
|
||||
}
|
||||
@@ -565,7 +568,14 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
}
|
||||
|
||||
private normalizedQuery(): string {
|
||||
return this.searchBox ? this.searchBox.getValue().replace(/@category/g, 'category').replace(/@tag:/g, 'tag:').replace(/@ext:/g, 'ext:') : '';
|
||||
return this.searchBox
|
||||
? this.searchBox.getValue()
|
||||
.replace(/@category/g, 'category')
|
||||
.replace(/@tag:/g, 'tag:')
|
||||
.replace(/@ext:/g, 'ext:')
|
||||
.replace(/@featured/g, 'featured')
|
||||
.replace(/@popular/g, '@sort:installs')
|
||||
: '';
|
||||
}
|
||||
|
||||
saveState(): void {
|
||||
|
||||
@@ -25,8 +25,7 @@ import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction, InstallLocalExtensionsInRemoteAction, getContextMenuActions } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction, InstallLocalExtensionsInRemoteAction, getContextMenuActions, ExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { WorkbenchPagedList, ListResourceNavigator } from 'vs/platform/list/browser/listService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
@@ -38,7 +37,7 @@ import { alert } from 'vs/base/browser/ui/aria/aria';
|
||||
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
|
||||
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IAction, Action, Separator } from 'vs/base/common/actions';
|
||||
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
@@ -248,7 +247,11 @@ export class ExtensionsListView extends ViewPane {
|
||||
});
|
||||
} else if (e.element) {
|
||||
const groups = getContextMenuActions(this.menuService, this.contextKeyService.createScoped(), this.instantiationService, e.element);
|
||||
groups.forEach(group => group.forEach(extensionAction => extensionAction.extension = e.element!));
|
||||
groups.forEach(group => group.forEach(extensionAction => {
|
||||
if (extensionAction instanceof ExtensionAction) {
|
||||
extensionAction.extension = e.element!;
|
||||
}
|
||||
}));
|
||||
let actions: IAction[] = [];
|
||||
for (const menuActions of groups) {
|
||||
actions = [...actions, ...menuActions, new Separator()];
|
||||
|
||||
@@ -40,6 +40,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { asDomUri } from 'vs/base/browser/dom';
|
||||
import { getIgnoredExtensions } from 'vs/platform/userDataSync/common/extensionsMerge';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { getExtensionKind } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
|
||||
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator'; // {{SQL CARBON EDIT}}
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener'; // {{SQL CARBON EDIT}}
|
||||
@@ -686,14 +687,79 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
if (extensions.length === 1) {
|
||||
return extensions[0];
|
||||
}
|
||||
|
||||
const enabledExtensions = extensions.filter(e => e.local && this.extensionEnablementService.isEnabled(e.local));
|
||||
if (enabledExtensions.length === 0) {
|
||||
return extensions[0];
|
||||
}
|
||||
if (enabledExtensions.length === 1) {
|
||||
return enabledExtensions[0];
|
||||
}
|
||||
return enabledExtensions.find(e => e.server === this.extensionManagementServerService.remoteExtensionManagementServer) || enabledExtensions[0];
|
||||
|
||||
const extensionsToChoose = enabledExtensions.length ? enabledExtensions : extensions;
|
||||
|
||||
let extension = extensionsToChoose.find(extension => {
|
||||
for (const extensionKind of getExtensionKind(extension.local!.manifest, this.productService, this.configurationService)) {
|
||||
switch (extensionKind) {
|
||||
case 'ui':
|
||||
/* UI extension is chosen only if it is installed locally */
|
||||
if (extension.server === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'workspace':
|
||||
/* Choose remote workspace extension if exists */
|
||||
if (extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'web':
|
||||
/* Choose web extension if exists */
|
||||
if (extension.server === this.extensionManagementServerService.webExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!extension && this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
extension = extensionsToChoose.find(extension => {
|
||||
for (const extensionKind of getExtensionKind(extension.local!.manifest, this.productService, this.configurationService)) {
|
||||
switch (extensionKind) {
|
||||
case 'workspace':
|
||||
/* Choose local workspace extension if exists */
|
||||
if (extension.server === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'web':
|
||||
/* Choose local web extension if exists */
|
||||
if (extension.server === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (!extension && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
extension = extensionsToChoose.find(extension => {
|
||||
for (const extensionKind of getExtensionKind(extension.local!.manifest, this.productService, this.configurationService)) {
|
||||
switch (extensionKind) {
|
||||
case 'web':
|
||||
/* Choose remote web extension if exists */
|
||||
if (extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return extension || extensions[0];
|
||||
}
|
||||
|
||||
private fromGallery(gallery: IGalleryExtension, maliciousExtensionSet: Set<string>): IExtension {
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'vs/css!./media/runtimeExtensionsEditor';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as os from 'os';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -18,7 +18,7 @@ import { IExtensionService, IExtensionsStatus, IExtensionHostProfile } from 'vs/
|
||||
import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
import { WorkbenchList } from 'vs/platform/list/browser/listService';
|
||||
import { append, $, addClass, toggleClass, Dimension, clearNode } from 'vs/base/browser/dom';
|
||||
import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
@@ -164,16 +164,17 @@ export class RuntimeExtensionsEditor extends BaseEditor {
|
||||
this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule()));
|
||||
}
|
||||
|
||||
private _updateExtensions(): void {
|
||||
this._elements = this._resolveExtensions();
|
||||
private async _updateExtensions(): Promise<void> {
|
||||
this._elements = await this._resolveExtensions();
|
||||
if (this._list) {
|
||||
this._list.splice(0, this._list.length, this._elements);
|
||||
}
|
||||
}
|
||||
|
||||
private _resolveExtensions(): IRuntimeExtension[] {
|
||||
private async _resolveExtensions(): Promise<IRuntimeExtension[]> {
|
||||
let marketplaceMap: { [id: string]: IExtension; } = Object.create(null);
|
||||
for (let extension of this._extensionsWorkbenchService.local) {
|
||||
const marketPlaceExtensions = await this._extensionsWorkbenchService.queryLocal();
|
||||
for (let extension of marketPlaceExtensions) {
|
||||
marketplaceMap[ExtensionIdentifier.toKey(extension.identifier.id)] = extension;
|
||||
}
|
||||
|
||||
@@ -328,7 +329,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
|
||||
} else {
|
||||
data.icon.style.visibility = 'inherit';
|
||||
}
|
||||
data.name.textContent = element.marketplaceInfo ? element.marketplaceInfo.displayName : element.description.displayName || '';
|
||||
data.name.textContent = element.marketplaceInfo.displayName;
|
||||
data.version.textContent = element.description.version;
|
||||
|
||||
const activationTimes = element.status.activationTimes!;
|
||||
@@ -462,11 +463,10 @@ export class RuntimeExtensionsEditor extends BaseEditor {
|
||||
actions.push(new ReportExtensionIssueAction(e.element, this._openerService, this._clipboardService, this._productService));
|
||||
actions.push(new Separator());
|
||||
|
||||
if (e.element.marketplaceInfo) {
|
||||
actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace)));
|
||||
actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally)));
|
||||
actions.push(new Separator());
|
||||
}
|
||||
actions.push(new Action('runtimeExtensionsEditor.action.disableWorkspace', nls.localize('disable workspace', "Disable (Workspace)"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledWorkspace)));
|
||||
actions.push(new Action('runtimeExtensionsEditor.action.disable', nls.localize('disable', "Disable"), undefined, true, () => this._extensionsWorkbenchService.setEnablement(e.element!.marketplaceInfo, EnablementState.DisabledGlobally)));
|
||||
actions.push(new Separator());
|
||||
|
||||
const state = this._extensionHostProfileService.state;
|
||||
if (state === ProfileSessionState.Running) {
|
||||
actions.push(this._instantiationService.createInstance(StopExtensionHostProfileAction, StopExtensionHostProfileAction.ID, StopExtensionHostProfileAction.LABEL));
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension,
|
||||
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IGalleryExtensionAssets, IExtensionIdentifier, InstallOperation, IExtensionTipsService, IGalleryMetadata
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionRecommendationsService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
|
||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||
@@ -34,7 +34,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { NativeURLService } from 'vs/platform/url/common/urlService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionType, IExtension, ExtensionKind } from 'vs/platform/extensions/common/extensions';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
|
||||
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
|
||||
@@ -46,6 +46,8 @@ import { TestLifecycleService } from 'vs/workbench/test/browser/workbenchTestSer
|
||||
import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
|
||||
import { ExtensionTipsService } from 'vs/platform/extensionManagement/node/extensionTipsService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
suite('ExtensionsWorkbenchServiceTest', () => {
|
||||
|
||||
@@ -981,6 +983,384 @@ suite('ExtensionsWorkbenchServiceTest', () => {
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledWorkspace);
|
||||
});
|
||||
|
||||
test('test user extension is preferred when the same extension exists as system and user extension', async () => {
|
||||
testObject = await aWorkbenchService();
|
||||
const userExtension = aLocalExtension('pub.a');
|
||||
const systemExtension = aLocalExtension('pub.a', {}, { type: ExtensionType.System });
|
||||
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [systemExtension, userExtension]);
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, userExtension);
|
||||
});
|
||||
|
||||
test('test user extension is disabled when the same extension exists as system and user extension and system extension is disabled', async () => {
|
||||
testObject = await aWorkbenchService();
|
||||
const systemExtension = aLocalExtension('pub.a', {}, { type: ExtensionType.System });
|
||||
await instantiationService.get(IWorkbenchExtensionEnablementService).setEnablement([systemExtension], EnablementState.DisabledGlobally);
|
||||
const userExtension = aLocalExtension('pub.a');
|
||||
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [systemExtension, userExtension]);
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, userExtension);
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledGlobally);
|
||||
});
|
||||
|
||||
test('Test local ui extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local workspace extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local web extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['web'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local ui,workspace extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local workspace,ui extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace', 'ui'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local ui,workspace,web extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'workspace', 'web'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local ui,web,workspace extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'web', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local web,ui,workspace extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['web', 'ui', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local web,workspace,ui extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['web', 'workspace', 'ui'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local workspace,web,ui extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace', 'web', 'ui'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local workspace,ui,web extension is chosen if it exists only in local server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace', 'ui', 'web'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local UI extension is chosen if it exists in both servers', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test local ui,workspace extension is chosen if it exists in both servers', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test remote workspace extension is chosen if it exists in remote server', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace'];
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, remoteExtension);
|
||||
});
|
||||
|
||||
test('Test remote workspace extension is chosen if it exists in both servers', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, remoteExtension);
|
||||
});
|
||||
|
||||
test('Test remote workspace extension is chosen if it exists in both servers and local is disabled', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
await instantiationService.get(IWorkbenchExtensionEnablementService).setEnablement([localExtension], EnablementState.DisabledGlobally);
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, remoteExtension);
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledGlobally);
|
||||
});
|
||||
|
||||
test('Test remote workspace extension is chosen if it exists in both servers and remote is disabled in workspace', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
await instantiationService.get(IWorkbenchExtensionEnablementService).setEnablement([remoteExtension], EnablementState.DisabledWorkspace);
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, remoteExtension);
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledWorkspace);
|
||||
});
|
||||
|
||||
test('Test local ui, workspace extension is chosen if it exists in both servers and local is disabled', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
await instantiationService.get(IWorkbenchExtensionEnablementService).setEnablement([localExtension], EnablementState.DisabledGlobally);
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledGlobally);
|
||||
});
|
||||
|
||||
test('Test local ui, workspace extension is chosen if it exists in both servers and local is disabled in workspace', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['ui', 'workspace'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
await instantiationService.get(IWorkbenchExtensionEnablementService).setEnablement([localExtension], EnablementState.DisabledWorkspace);
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
assert.equal(actual[0].enablementState, EnablementState.DisabledWorkspace);
|
||||
});
|
||||
|
||||
test('Test local web extension is chosen if it exists in both servers', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['web'];
|
||||
const localExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`) });
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([localExtension]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, localExtension);
|
||||
});
|
||||
|
||||
test('Test remote web extension is chosen if it exists only in remote', async () => {
|
||||
// multi server setup
|
||||
const extensionKind: ExtensionKind[] = ['web'];
|
||||
const remoteExtension = aLocalExtension('a', { extensionKind }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
|
||||
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService([]), createExtensionManagementService([remoteExtension]));
|
||||
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
|
||||
instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
|
||||
testObject = await aWorkbenchService();
|
||||
|
||||
const actual = await testObject.queryLocal();
|
||||
|
||||
assert.equal(actual.length, 1);
|
||||
assert.equal(actual[0].local, remoteExtension);
|
||||
});
|
||||
|
||||
async function aWorkbenchService(): Promise<ExtensionsWorkbenchService> {
|
||||
const workbenchService: ExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
|
||||
await workbenchService.queryLocal();
|
||||
@@ -1031,4 +1411,49 @@ suite('ExtensionsWorkbenchServiceTest', () => {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function aMultiExtensionManagementServerService(instantiationService: TestInstantiationService, localExtensionManagementService?: IExtensionManagementService, remoteExtensionManagementService?: IExtensionManagementService): IExtensionManagementServerService {
|
||||
const localExtensionManagementServer: IExtensionManagementServer = {
|
||||
id: 'vscode-local',
|
||||
label: 'local',
|
||||
extensionManagementService: localExtensionManagementService || createExtensionManagementService()
|
||||
};
|
||||
const remoteExtensionManagementServer: IExtensionManagementServer = {
|
||||
id: 'vscode-remote',
|
||||
label: 'remote',
|
||||
extensionManagementService: remoteExtensionManagementService || createExtensionManagementService()
|
||||
};
|
||||
return {
|
||||
_serviceBrand: undefined,
|
||||
localExtensionManagementServer,
|
||||
remoteExtensionManagementServer,
|
||||
webExtensionManagementServer: null,
|
||||
getExtensionManagementServer: (extension: IExtension) => {
|
||||
if (extension.location.scheme === Schemas.file) {
|
||||
return localExtensionManagementServer;
|
||||
}
|
||||
if (extension.location.scheme === REMOTE_HOST_SCHEME) {
|
||||
return remoteExtensionManagementServer;
|
||||
}
|
||||
throw new Error('');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createExtensionManagementService(installed: ILocalExtension[] = []): IExtensionManagementService {
|
||||
return <IExtensionManagementService>{
|
||||
onInstallExtension: Event.None,
|
||||
onDidInstallExtension: Event.None,
|
||||
onUninstallExtension: Event.None,
|
||||
onDidUninstallExtension: Event.None,
|
||||
getInstalled: () => Promise.resolve<ILocalExtension[]>(installed),
|
||||
installFromGallery: (extension: IGalleryExtension) => Promise.reject(new Error('not supported')),
|
||||
updateMetadata: async (local: ILocalExtension, metadata: IGalleryMetadata) => {
|
||||
local.identifier.uuid = metadata.id;
|
||||
local.publisherDisplayName = metadata.publisherDisplayName;
|
||||
local.publisherId = metadata.publisherId;
|
||||
return local;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { QuickFixAction, QuickFixActionViewItem } from 'vs/workbench/contrib/markers/browser/markersViewActions';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { dirname, basename, isEqual } from 'vs/base/common/resources';
|
||||
@@ -52,6 +52,7 @@ import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
export type TreeElement = ResourceMarkers | Marker | RelatedInformation;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'vs/css!./media/markers';
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IAction, IActionViewItem, Action } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem, Action, Separator } from 'vs/base/common/actions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import Constants from 'vs/workbench/contrib/markers/browser/constants';
|
||||
@@ -33,7 +33,7 @@ import { deepClone } from 'vs/base/common/objects';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { FilterData, Filter, VirtualDelegate, ResourceMarkersRenderer, MarkerRenderer, RelatedInformationRenderer, TreeElement, MarkersTreeAccessibilityProvider, MarkersViewModel, ResourceDragAndDrop } from 'vs/workbench/contrib/markers/browser/markersTreeViewer';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Separator, ActionViewItem, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IMenuService, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -50,6 +50,7 @@ import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/vie
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
|
||||
function createResourceMarkersIterator(resourceMarkers: ResourceMarkers): Iterable<ITreeElement<TreeElement>> {
|
||||
return Iterable.map(resourceMarkers.markers, m => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { Action, IAction, IActionRunner, Separator } from 'vs/base/common/actions';
|
||||
import { HistoryInputBox } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -15,7 +15,7 @@ import Constants from 'vs/workbench/contrib/markers/browser/constants';
|
||||
import { IThemeService, registerThemingParticipant, ICssStyleCollector, IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||
import { attachInputBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
|
||||
import { toDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { BaseActionViewItem, ActionViewItem, ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { badgeBackground, badgeForeground, contrastBorder, inputActiveOptionBorder, inputActiveOptionBackground, inputActiveOptionForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -23,10 +23,11 @@ import { ContextScopedHistoryInputBox } from 'vs/platform/browser/contextScopedH
|
||||
import { Marker } from 'vs/workbench/contrib/markers/browser/markersModel';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { BaseActionViewItem, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
|
||||
|
||||
export class ShowProblemsPanelAction extends Action {
|
||||
|
||||
@@ -179,11 +180,12 @@ class FiltersDropdownMenuActionViewItem extends DropdownMenuActionViewItem {
|
||||
super(action,
|
||||
{ getActions: () => this.getActions() },
|
||||
contextMenuService,
|
||||
action => undefined,
|
||||
actionRunner!,
|
||||
undefined,
|
||||
action.class,
|
||||
() => { return AnchorAlignment.RIGHT; });
|
||||
{
|
||||
actionRunner,
|
||||
classNames: action.class,
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
|
||||
@@ -18,7 +18,7 @@ export const BOTTOM_CELL_TOOLBAR_OFFSET = 12;
|
||||
export const CELL_STATUSBAR_HEIGHT = 22;
|
||||
|
||||
// Margin above editor
|
||||
export const EDITOR_TOP_MARGIN = 6;
|
||||
export const CELL_TOP_MARGIN = 6;
|
||||
export const CELL_BOTTOM_MARGIN = 6;
|
||||
|
||||
// Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight`
|
||||
@@ -26,3 +26,5 @@ export const EDITOR_TOP_PADDING = 12;
|
||||
export const EDITOR_BOTTOM_PADDING = 4;
|
||||
|
||||
export const CELL_OUTPUT_PADDING = 14;
|
||||
|
||||
export const COLLAPSED_INDICATOR_HEIGHT = 24;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user