diff --git a/.vscode/launch.json b/.vscode/launch.json index e67212baab..224f940153 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,7 +20,10 @@ "restart": true, "outFiles": [ "${workspaceFolder}/out/**/*.js" - ] + ], + "presentation": { + "hidden": true, + } }, { "type": "chrome", @@ -36,7 +39,10 @@ "port": 5876, "outFiles": [ "${workspaceFolder}/out/**/*.js" - ] + ], + "presentation": { + "hidden": true, + } }, { "type": "node", @@ -54,13 +60,19 @@ "port": 5875, "outFiles": [ "${workspaceFolder}/out/**/*.js" - ] + ], + "presentation": { + "hidden": true, + } }, { "type": "chrome", "request": "attach", "name": "Attach to azuredatastudio", - "port": 9222 + "port": 9222, + "presentation": { + "hidden": true + } }, { "type": "chrome", @@ -86,7 +98,10 @@ "--inspect=5875", "--no-cached-data" ], - "webRoot": "${workspaceFolder}" + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": true + } }, { "type": "node", @@ -101,7 +116,11 @@ ], "outFiles": [ "${workspaceFolder}/out/**/*.js" - ] + ], + "presentation": { + "group": "2_launch", + "order": 1 + } }, { "type": "chrome", @@ -135,13 +154,21 @@ "runtimeArgs": [ "web" ], + "presentation": { + "group": "2_launch", + "order": 2 + } }, { "type": "chrome", "request": "launch", "name": "Launch ADS (Web, Chrome) (TBD)", "url": "http://localhost:8080", - "preLaunchTask": "Run web" + "preLaunchTask": "Run web", + "presentation": { + "group": "2_launch", + "order": 3 + } }, { "type": "node", @@ -152,16 +179,11 @@ "cwd": "${workspaceFolder}/extensions/git", "outFiles": [ "${workspaceFolder}/extensions/git/out/**/*.js" - ] - }, - { - "name": "Launch Built-in Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - "--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch" - ] + ], + "presentation": { + "group": "5_tests", + "order": 10 + } }, { "type": "node", @@ -171,6 +193,10 @@ "cwd": "${workspaceFolder}/test/smoke", "env": { "BUILD_ARTIFACTSTAGINGDIRECTORY": "${workspaceFolder}" + }, + "presentation": { + "group": "5_tests", + "order": 8 } }, { @@ -195,6 +221,9 @@ ], "env": { "MOCHA_COLORS": "true" + }, + "presentation": { + "hidden": true } }, { @@ -245,19 +274,16 @@ "Run Extension Unit Tests" ] }, - { - "name": "Debug Extension Integration Tests", - "configurations": [ - "Attach to Extension Host", - "Run Extension Integration Tests" - ] - }, { "name": "Debug azuredatastudio Main and Renderer", "configurations": [ "Launch azuredatastudio", "Attach to Main Process" - ] + ], + "presentation": { + "group": "1_vscode", + "order": 1 + } }, { "name": "Debug azuredatastudio Main, Renderer & Extension Host", @@ -265,28 +291,33 @@ "Launch azuredatastudio", "Attach to Main Process", "Attach to Extension Host" - ] - }, - { - "name": "Debug Renderer and search processes", - "configurations": [ - "Launch azuredatastudio", - "Attach to Search Process" - ] + ], + "presentation": { + "group": "1_vscode", + "order": 3 + } }, { "name": "Debug Renderer and Extension Host processes", "configurations": [ "Launch azuredatastudio", "Attach to Extension Host" - ] + ], + "presentation": { + "group": "1_vscode", + "order": 2 + } }, { "name": "Attach Renderer and Extension Host", "configurations": [ "Attach to azuredatastudio", "Attach to Extension Host" - ] + ], + "presentation": { + "group": "1_vscode", + "order": 2 + } } ] } diff --git a/extensions/markdown-basics/test/colorize-results/test_md.json b/extensions/markdown-basics/test/colorize-results/test_md.json index 9bc9aa7595..6963f66e79 100644 --- a/extensions/markdown-basics/test/colorize-results/test_md.json +++ b/extensions/markdown-basics/test/colorize-results/test_md.json @@ -1134,7 +1134,7 @@ }, { "c": "<", - "t": "text.html.markdown meta.embedded.block.html meta.tag.metadata.style.end.html punctuation.definition.tag.begin.html source.css", + "t": "text.html.markdown meta.embedded.block.html meta.tag.metadata.style.end.html punctuation.definition.tag.begin.html source.css-ignored-vscode", "r": { "dark_plus": "punctuation.definition.tag: #808080", "light_plus": "punctuation.definition.tag: #800000", diff --git a/extensions/python/package.json b/extensions/python/package.json index 645cba2bae..c500b586f4 100644 --- a/extensions/python/package.json +++ b/extensions/python/package.json @@ -14,7 +14,7 @@ "extensions": [ ".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi", ".pyi", ".ipy"], "aliases": [ "Python", "py" ], "filenames": [ "Snakefile" ], - "firstLine": "^#!\\s*/.*\\bpython[0-9.-]*\\b", + "firstLine": "^#!\\s*/?.*\\bpython[0-9.-]*\\b", "configuration": "./language-configuration.json" }], "grammars": [{ diff --git a/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts b/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts index d80082f2c1..c124c16bea 100644 --- a/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts +++ b/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts @@ -46,8 +46,6 @@ export class OpenDataExplorerViewletAction extends ShowViewletAction { } } -export const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('dataexplorer.name', "Connections") }, ViewContainerLocation.Sidebar); - export class DataExplorerViewletViewsContribution implements IWorkbenchContribution { constructor() { @@ -157,3 +155,9 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer { return viewletPanel; } } + +export const VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: localize('dataexplorer.name', "Connections"), + ctorDescriptor: { ctor: DataExplorerViewPaneContainer } +}, ViewContainerLocation.Sidebar); diff --git a/src/sql/workbench/contrib/extensions/browser/extensionsActions.ts b/src/sql/workbench/contrib/extensions/browser/extensionsActions.ts index f73c9a06d4..5c061523c7 100644 --- a/src/sql/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/sql/workbench/contrib/extensions/browser/extensionsActions.ts @@ -6,11 +6,10 @@ import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { IExtensionsWorkbenchService, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/common/extensions'; import { IExtensionRecommendation } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { CancellationToken } from 'vs/base/common/cancellation'; import { PagedModel } from 'vs/base/common/paging'; -import { ExtensionsViewlet, ExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; function getScenarioID(scenarioType: string) { return 'workbench.extensions.action.show' + scenarioType; @@ -26,8 +25,9 @@ export class ShowRecommendedExtensionsByScenarioAction extends Action { run(): Promise { return this.viewletService.openViewlet(VIEWLET_ID, true) - .then((viewlet: ExtensionsViewlet) => { - (viewlet.getViewPaneContainer() as ExtensionsViewPaneContainer).search('@' + this.scenarioType); + .then(viewlet => viewlet?.getViewPaneContainer()) + .then((viewlet: IExtensionsViewPaneContainer) => { + viewlet.search('@' + this.scenarioType); viewlet.focus(); }); } @@ -51,8 +51,9 @@ export class InstallRecommendedExtensionsByScenarioAction extends Action { run(): Promise { if (!this.recommendations.length) { return Promise.resolve(); } return this.viewletService.openViewlet(VIEWLET_ID, true) - .then((viewlet: ExtensionsViewlet) => { - (viewlet.getViewPaneContainer() as ExtensionsViewPaneContainer).search('@' + this.scenarioType); + .then(viewlet => viewlet?.getViewPaneContainer()) + .then((viewlet: IExtensionsViewPaneContainer) => { + viewlet.search('@' + this.scenarioType); viewlet.focus(); const names = this.recommendations.map(({ extensionId }) => extensionId); return this.extensionWorkbenchService.queryGallery({ names, source: 'install-' + this.scenarioType }, CancellationToken.None).then(pager => { diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts index 31cd5f4266..ffe91c3d9d 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts @@ -37,7 +37,7 @@ import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHos import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; import { CellMagicMapper } from 'sql/workbench/contrib/notebook/browser/models/cellMagicMapper'; -import { VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; +import { VIEWLET_ID, IExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/common/extensions'; import { CellModel } from 'sql/workbench/contrib/notebook/browser/models/cell'; import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { isValidBasename } from 'vs/base/common/extpath'; @@ -56,7 +56,6 @@ import { find, firstIndex } from 'vs/base/common/arrays'; import { CodeCellComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/codeCell.component'; import { TextCellComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/textCell.component'; import { NotebookRange } from 'sql/workbench/contrib/notebook/find/notebookFindDecorations'; -import { ExtensionsViewlet, ExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; export const NOTEBOOK_SELECTOR: string = 'notebook-component'; @@ -354,8 +353,8 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe private async openExtensionGallery(): Promise { try { - let viewlet = await this.viewletService.openViewlet(VIEWLET_ID, true) as ExtensionsViewlet; - (viewlet.getViewPaneContainer() as ExtensionsViewPaneContainer).search('sql-vnext'); + let viewlet = await this.viewletService.openViewlet(VIEWLET_ID, true); + (viewlet.getViewPaneContainer() as IExtensionsViewPaneContainer).search('sql-vnext'); viewlet.focus(); } catch (error) { this.notificationService.error(error.message); diff --git a/src/vs/editor/contrib/codelens/codelensWidget.css b/src/vs/editor/contrib/codelens/codelensWidget.css index 89a07a31c1..df30d79470 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.css +++ b/src/vs/editor/contrib/codelens/codelensWidget.css @@ -23,17 +23,16 @@ } .monaco-editor .codelens-decoration > a:hover { - text-decoration: underline; cursor: pointer; } .monaco-editor .codelens-decoration .codicon { line-height: inherit; - font-size: inherit; + font-size: 110%; + vertical-align: inherit; } .monaco-editor .codelens-decoration > a:hover .codicon::before { - text-decoration: underline; cursor: pointer; } diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index ff26dcf0c9..3eb92d6220 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -32,7 +32,6 @@ import { InitializingRangeProvider, ID_INIT_PROVIDER } from 'vs/editor/contrib/f import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { onUnexpectedError } from 'vs/base/common/errors'; import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IMouseEvent } from 'vs/base/browser/mouseEvent'; const CONTEXT_FOLDING_ENABLED = new RawContextKey('foldingEnabled', false); @@ -423,12 +422,17 @@ export class FoldingController extends Disposable implements IEditorContribution let isCollapsed = region.isCollapsed; if (iconClicked || isCollapsed) { let toToggle = []; - let considerRegionsInside = this.shouldConsiderRegionsInside(e.event); - if (isCollapsed || (!isCollapsed && !considerRegionsInside)) { - toToggle.push(region); + let recursive = e.event.middleButton || e.event.shiftKey; + if (recursive) { + for (const r of foldingModel.getRegionsInside(region)) { + if (r.isCollapsed === isCollapsed) { + toToggle.push(r); + } + } } - if (considerRegionsInside) { - toToggle.push(...foldingModel.getRegionsInside(region, (r: FoldingRegion) => r.isCollapsed === isCollapsed)); + // when recursive, first only collapse all children. If all are already folded or there are no children, also fold parent. + if (isCollapsed || !recursive || toToggle.length === 0) { + toToggle.push(region); } foldingModel.toggleCollapseState(toToggle); this.reveal({ lineNumber, column: 1 }); @@ -438,10 +442,6 @@ export class FoldingController extends Disposable implements IEditorContribution }).then(undefined, onUnexpectedError); } - private shouldConsiderRegionsInside(event: IMouseEvent): boolean { - return event.middleButton || event.shiftKey; - } - public reveal(position: IPosition): void { this.editor.revealPositionInCenterIfOutsideViewport(position, ScrollType.Smooth); } diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index 229540e08c..3ca8f0a5d1 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -22,14 +22,13 @@ import { VIEWLET_ID as DEBUG } from 'vs/workbench/contrib/debug/common/debug'; import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/common/remote.contribution'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction, Viewlet } from 'vs/workbench/browser/viewlet'; +import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -313,7 +312,6 @@ class ViewsExtensionHandler implements IWorkbenchContribution { if (!viewContainer) { - viewContainer = this.viewContainersRegistry.registerViewContainer({ id, hideIfEmpty: true, name: title, extensionId }, ViewContainerLocation.Sidebar); class CustomViewPaneContainer extends ViewPaneContainer { constructor( @@ -331,34 +329,13 @@ class ViewsExtensionHandler implements IWorkbenchContribution { } } - // Register a viewlet - class CustomViewlet extends Viewlet { - constructor( - @IConfigurationService configurationService: IConfigurationService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @ITelemetryService telemetryService: ITelemetryService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @IStorageService storageService: IStorageService, - @IEditorService editorService: IEditorService, - @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService contextMenuService: IContextMenuService, - @IExtensionService extensionService: IExtensionService - ) { - super(id, instantiationService.createInstance(CustomViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } - } - - const viewletDescriptor = ViewletDescriptor.create( - CustomViewlet, + viewContainer = this.viewContainersRegistry.registerViewContainer({ id, - title, - undefined, - order, - icon - ); - - Registry.as(ViewletExtensions.Viewlets).registerViewlet(viewletDescriptor); + name: title, extensionId, + ctorDescriptor: { ctor: CustomViewPaneContainer }, + hideIfEmpty: true, + icon, + }, ViewContainerLocation.Sidebar); // Register Action to Open Viewlet class OpenCustomViewletAction extends ShowViewletAction { @@ -432,8 +409,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution { const order = ExtensionIdentifier.equals(extension.description.identifier, container.extensionId) ? index + 1 - : container.orderDelegate - ? container.orderDelegate.getOrder(item.group) + : container.viewOrderDelegate + ? container.viewOrderDelegate.getOrder(item.group) : undefined; const viewDescriptor = { diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index defa775894..44357208d8 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -156,9 +156,4 @@ export interface EditorServiceImpl extends IEditorService { * Emitted when the list of most recently active editors change. */ readonly onDidMostRecentlyActiveEditorsChange: Event; - - /** - * Access to the list of most recently active editors. - */ - readonly mostRecentlyActiveEditors: ReadonlyArray; } diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 2b9fb9a4ad..e2b791673f 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { mixin } from 'vs/base/common/objects'; -import { IEditorInput, EditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason } from 'vs/workbench/common/editor'; +import { IEditorInput, EditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder } from 'vs/workbench/common/editor'; import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; @@ -16,7 +16,7 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { CLOSE_EDITOR_COMMAND_ID, NAVIGATE_ALL_EDITORS_BY_APPEARANCE_PREFIX, MOVE_ACTIVE_EDITOR_COMMAND_ID, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX } from 'vs/workbench/browser/parts/editor/editorCommands'; -import { IEditorGroupsService, IEditorGroup, GroupsArrangement, EditorsOrder, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { DisposableStore } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index dbcd594aea..9cec4c8211 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor, EditorGroupEditorsCountContext, toResource, SideBySideEditor, SaveReason, SaveContext, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor, EditorGroupEditorsCountContext, toResource, SideBySideEditor, SaveReason, SaveContext, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -17,7 +17,7 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { Themable, EDITOR_GROUP_HEADER_TABS_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND, EDITOR_GROUP_EMPTY_BACKGROUND, EDITOR_GROUP_FOCUSED_EMPTY_BORDER } from 'vs/workbench/common/theme'; -import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, EditorsOrder, GroupsOrder, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, GroupsOrder, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl'; import { EditorControl } from 'vs/workbench/browser/parts/editor/editorControl'; import { IEditorProgressService } from 'vs/platform/progress/common/progress'; @@ -725,7 +725,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } get editors(): EditorInput[] { - return this._group.getEditors(); + return this._group.getEditors(EditorsOrder.SEQUENTIAL); } get count(): number { @@ -752,12 +752,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return this._group.isActive(editor); } - getEditors(order?: EditorsOrder): EditorInput[] { - if (order === EditorsOrder.MOST_RECENTLY_ACTIVE) { - return this._group.getEditors(true); - } - - return this.editors; + getEditors(order: EditorsOrder): EditorInput[] { + return this._group.getEditors(order); } getEditorByIndex(index: number): EditorInput | undefined { @@ -1021,7 +1017,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Use the first editor as active editor const { editor, options } = editors.shift()!; - let firstOpenedEditor = await this.openEditor(editor, options); + await this.openEditor(editor, options); // Open the other ones inactive const startingIndex = this.getIndexOfEditor(editor) + 1; @@ -1031,13 +1027,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView { adjustedEditorOptions.pinned = true; adjustedEditorOptions.index = startingIndex + index; - const openedEditor = await this.openEditor(editor, adjustedEditorOptions); - if (!firstOpenedEditor) { - firstOpenedEditor = openedEditor; // only take if the first editor opening failed - } + await this.openEditor(editor, adjustedEditorOptions); })); - return firstOpenedEditor; + // Opening many editors at once can put any editor to be + // the active one depending on options. As such, we simply + // return the active control after this operation. + return this.editorControl.activeControl; } //#endregion @@ -1373,7 +1369,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { const filter = editors; const hasDirection = typeof filter.direction === 'number'; - let editorsToClose = this._group.getEditors(!hasDirection /* in MRU order only if direction is not specified */); + let editorsToClose = this._group.getEditors(hasDirection ? EditorsOrder.SEQUENTIAL : EditorsOrder.MOST_RECENTLY_ACTIVE); // in MRU order only if direction is not specified // Filter: saved only if (filter.savedOnly) { @@ -1434,7 +1430,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } // Check for dirty and veto - const editors = this._group.getEditors(true); + const editors = this._group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); const veto = await this.handleDirtyClosing(editors.slice(0)); if (veto) { return; @@ -1528,8 +1524,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#endregion - //#endregion - //#region Themable protected updateStyles(): void { diff --git a/src/vs/workbench/browser/parts/editor/editorPicker.ts b/src/vs/workbench/browser/parts/editor/editorPicker.ts index 755cca1b2b..a66789fcf6 100644 --- a/src/vs/workbench/browser/parts/editor/editorPicker.ts +++ b/src/vs/workbench/browser/parts/editor/editorPicker.ts @@ -13,12 +13,11 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { IModelService } from 'vs/editor/common/services/modelService'; import { QuickOpenHandler } from 'vs/workbench/browser/quickopen'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IEditorGroupsService, IEditorGroup, EditorsOrder, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { toResource, SideBySideEditor, IEditorInput } from 'vs/workbench/common/editor'; +import { toResource, SideBySideEditor, IEditorInput, EditorsOrder } from 'vs/workbench/common/editor'; import { compareItemsByScore, scoreItem, ScorerCache, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IHistoryService } from 'vs/workbench/services/history/common/history'; export class EditorPickerEntry extends QuickOpenEntryGroup { @@ -209,14 +208,13 @@ export abstract class BaseAllEditorsPicker extends BaseEditorPicker { constructor( @IInstantiationService instantiationService: IInstantiationService, @IEditorService editorService: IEditorService, - @IEditorGroupsService editorGroupService: IEditorGroupsService, - @IHistoryService protected historyService: IHistoryService + @IEditorGroupsService editorGroupService: IEditorGroupsService ) { super(instantiationService, editorService, editorGroupService); } protected count(): number { - return this.historyService.getMostRecentlyUsedOpenEditors().length; + return this.editorService.count; } getEmptyLabel(searchString: string): string { @@ -262,7 +260,7 @@ export class AllEditorsByMostRecentlyUsedPicker extends BaseAllEditorsPicker { protected getEditorEntries(): EditorPickerEntry[] { const entries: EditorPickerEntry[] = []; - for (const { editor, groupId } of this.historyService.getMostRecentlyUsedOpenEditors()) { + for (const { editor, groupId } of this.editorService.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { entries.push(this.instantiationService.createInstance(EditorPickerEntry, editor, this.editorGroupService.getGroup(groupId)!)); } diff --git a/src/vs/workbench/browser/parts/editor/editorsObserver.ts b/src/vs/workbench/browser/parts/editor/editorsObserver.ts index beeb1d72d2..6db8be0701 100644 --- a/src/vs/workbench/browser/parts/editor/editorsObserver.ts +++ b/src/vs/workbench/browser/parts/editor/editorsObserver.ts @@ -3,12 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, Extensions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, Extensions, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; import { Event, Emitter } from 'vs/base/common/event'; -import { IEditorGroupsService, IEditorGroup, EditorsOrder, GroupChangeKind, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { coalesce } from 'vs/base/common/arrays'; import { LinkedMap, Touch } from 'vs/base/common/map'; import { equals } from 'vs/base/common/objects'; @@ -41,6 +41,10 @@ export class EditorsObserver extends Disposable { private readonly _onDidChange = this._register(new Emitter()); readonly onDidChange = this._onDidChange.event; + get count(): number { + return this.mostRecentEditorsMap.size; + } + get editors(): IEditorIdentifier[] { return this.mostRecentEditorsMap.values(); } @@ -231,7 +235,7 @@ export class EditorsObserver extends Disposable { if (typeof groupId === 'number') { const group = this.editorGroupsService.getGroup(groupId); if (group) { - this.doEnsureOpenedEditorsLimit(limit, group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).map(editor => ({ editor, groupId })), exclude); + await this.doEnsureOpenedEditorsLimit(limit, group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).map(editor => ({ editor, groupId })), exclude); } } @@ -245,7 +249,7 @@ export class EditorsObserver extends Disposable { // Across all editor groups else { - this.doEnsureOpenedEditorsLimit(limit, this.mostRecentEditorsMap.values(), exclude); + await this.doEnsureOpenedEditorsLimit(limit, this.mostRecentEditorsMap.values(), exclude); } } diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts index 08f903869d..4928f37c94 100644 --- a/src/vs/workbench/browser/parts/panel/panelActions.ts +++ b/src/vs/workbench/browser/parts/panel/panelActions.ts @@ -13,7 +13,7 @@ import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/ import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/actions'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; -import { ActivityAction } from 'vs/workbench/browser/parts/compositeBarActions'; +import { ActivityAction, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositeBarActions'; import { IActivity } from 'vs/workbench/common/activity'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ActivePanelContext, PanelPositionContext } from 'vs/workbench/common/panel'; @@ -149,7 +149,7 @@ function createPositionPanelActionConfig(id: string, alias: string, label: strin }; } -export const PositionPanelActionConfigs = [ +export const PositionPanelActionConfigs: PanelActionConfig[] = [ createPositionPanelActionConfig(PositionPanelActionId.LEFT, 'View: Panel Position Left', nls.localize('positionPanelLeft', 'Move Panel Left'), Position.LEFT), createPositionPanelActionConfig(PositionPanelActionId.RIGHT, 'View: Panel Position Right', nls.localize('positionPanelRight', 'Move Panel Right'), Position.RIGHT), createPositionPanelActionConfig(PositionPanelActionId.BOTTOM, 'View: Panel Position Bottom', nls.localize('positionPanelBottom', 'Move Panel To Bottom'), Position.BOTTOM), @@ -187,8 +187,34 @@ export class PanelActivityAction extends ActivityAction { this.activate(); return Promise.resolve(); } + + setActivity(activity: IActivity): void { + this.activity = activity; + } } +export class PlaceHolderPanelActivityAction extends PanelActivityAction { + + constructor( + id: string, + @IPanelService panelService: IPanelService + ) { + super({ id, name: id }, panelService); + } +} + +export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinnedAction { + + constructor(id: string, compositeBar: ICompositeBar) { + super({ id, name: id, cssClass: undefined }, compositeBar); + } + + setActivity(activity: IActivity): void { + this.label = activity.name; + } +} + + export class SwitchPanelViewAction extends Action { constructor( diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index efcf83a155..4c3ec0f4e8 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/panelpart'; -import { IAction } from 'vs/base/common/actions'; +import { IAction, Action } from 'vs/base/common/actions'; import { Event } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -18,7 +18,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ClosePanelAction, PanelActivityAction, ToggleMaximizedPanelAction, TogglePanelAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions'; +import { ClosePanelAction, PanelActivityAction, ToggleMaximizedPanelAction, TogglePanelAction, PlaceHolderPanelActivityAction, PlaceHolderToggleCompositePinnedAction, PositionPanelActionConfigs, SetPanelPositionAction } from 'vs/workbench/browser/parts/panel/panelActions'; import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BACKGROUND, PANEL_INPUT_BORDER } from 'vs/workbench/common/theme'; import { activeContrastBorder, focusBorder, contrastBorder, editorBackground, badgeBackground, badgeForeground } from 'vs/platform/theme/common/colorRegistry'; @@ -28,17 +28,19 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { Dimension, trackFocus } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; -import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewsService, IViewDescriptorCollection } from 'vs/workbench/common/views'; interface ICachedPanel { id: string; pinned: boolean; order?: number; visible: boolean; + views?: { when?: string }[]; } export class PanelPart extends CompositePart implements IPanelService { @@ -80,9 +82,13 @@ export class PanelPart extends CompositePart implements IPanelService { private compositeBar: CompositeBar; private compositeActions: Map = new Map(); + private readonly panelDisposables: Map = new Map(); + private blockOpeningPanel = false; private _contentDimension: Dimension | undefined; + private panelRegistry: PanelRegistry; + constructor( @INotificationService notificationService: INotificationService, @IStorageService storageService: IStorageService, @@ -92,8 +98,9 @@ export class PanelPart extends CompositePart implements IPanelService { @IKeybindingService keybindingService: IKeybindingService, @IInstantiationService instantiationService: IInstantiationService, @IThemeService themeService: IThemeService, - @IContextKeyService contextKeyService: IContextKeyService, - @ILifecycleService private readonly lifecycleService: ILifecycleService + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IExtensionService private readonly extensionService: IExtensionService, + @IViewsService private readonly viewsService: IViewsService, ) { super( notificationService, @@ -114,6 +121,8 @@ export class PanelPart extends CompositePart implements IPanelService { { hasTitle: true } ); + this.panelRegistry = Registry.as(PanelExtensions.Panels); + this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, this.getCachedPanels(), { icon: false, orientation: ActionsOrientation.HORIZONTAL, @@ -127,8 +136,8 @@ export class PanelPart extends CompositePart implements IPanelService { .filter(({ when }) => contextKeyService.contextMatchesRules(when)) .map(({ id, label }) => this.instantiationService.createInstance(SetPanelPositionAction, id, label)), this.instantiationService.createInstance(TogglePanelAction, TogglePanelAction.ID, localize('hidePanel', "Hide Panel")) - ], - getDefaultCompositeId: () => Registry.as(PanelExtensions.Panels).getDefaultPanelId(), + ] as Action[], + getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(), hidePart: () => this.layoutService.setPanelHidden(true), compositeSize: 0, overflowActionSize: 44, @@ -144,47 +153,156 @@ export class PanelPart extends CompositePart implements IPanelService { }) })); - for (const panel of this.getPanels()) { - this.compositeBar.addComposite(panel); - } - this.activePanelContextKey = ActivePanelContext.bindTo(contextKeyService); this.panelFocusContextKey = PanelFocusContext.bindTo(contextKeyService); this.registerListeners(); + this.onDidRegisterPanels([...this.getPanels()]); + } + + private onDidRegisterPanels(panels: PanelDescriptor[]): void { + for (const panel of panels) { + const cachedPanel = this.getCachedPanels().filter(({ id }) => id === panel.id)[0]; + const activePanel = this.getActivePanel(); + const isActive = activePanel?.getId() === panel.id; + + if (isActive || !this.shouldBeHidden(panel.id, cachedPanel)) { + this.compositeBar.addComposite(panel); + + // Pin it by default if it is new + if (!cachedPanel) { + this.compositeBar.pin(panel.id); + } + + if (isActive) { + this.compositeBar.activateComposite(panel.id); + } + } + } + + for (const panel of panels) { + this.enableCompositeActions(panel); + const viewContainer = this.getViewContainer(panel.id); + if (viewContainer?.hideIfEmpty) { + const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer); + if (viewDescriptors) { + this.onDidChangeActiveViews(panel, viewDescriptors); + this.panelDisposables.set(panel.id, viewDescriptors.onDidChangeActiveViews(() => this.onDidChangeActiveViews(panel, viewDescriptors))); + } + } + } + } + + private onDidDeregisterPanel(panelId: string): void { + const disposable = this.panelDisposables.get(panelId); + if (disposable) { + disposable.dispose(); + } + + this.panelDisposables.delete(panelId); + this.hideComposite(panelId); + } + + private enableCompositeActions(panel: PanelDescriptor): void { + const { activityAction, pinnedAction } = this.getCompositeActions(panel.id); + if (activityAction instanceof PlaceHolderPanelActivityAction) { + activityAction.setActivity(panel); + } + + if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) { + pinnedAction.setActivity(panel); + } + } + + private onDidChangeActiveViews(panel: PanelDescriptor, viewDescriptors: IViewDescriptorCollection): void { + if (viewDescriptors.activeViewDescriptors.length) { + this.compositeBar.addComposite(panel); + } else { + this.hideComposite(panel.id); + } + } + + private shouldBeHidden(panelId: string, cachedPanel?: ICachedPanel): boolean { + const viewContainer = this.getViewContainer(panelId); + if (!viewContainer || !viewContainer.hideIfEmpty) { + return false; + } + + return cachedPanel?.views && cachedPanel.views.length + ? cachedPanel.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when))) + : false; } private registerListeners(): void { + // Panel registration + this._register(this.registry.onDidRegister(panel => this.onDidRegisterPanels([panel]))); + this._register(this.registry.onDidDeregister(panel => this.onDidDeregisterPanel(panel.id))); - // Panel open/close + // Activate on panel open this._register(this.onDidPanelOpen(({ panel }) => this.onPanelOpen(panel))); + + // Deactivate on panel close this._register(this.onDidPanelClose(this.onPanelClose, this)); - // Panel register/deregister - this._register(this.registry.onDidRegister(panelDescriptor => this.compositeBar.addComposite(panelDescriptor))); - this._register(this.registry.onDidDeregister(panelDescriptor => { - this.compositeBar.hideComposite(panelDescriptor.id); - this.removeComposite(panelDescriptor.id); + // Extension registration + let disposables = this._register(new DisposableStore()); + this._register(this.extensionService.onDidRegisterExtensions(() => { + disposables.clear(); + this.onDidRegisterExtensions(); + this.compositeBar.onDidChange(() => this.saveCachedPanels(), this, disposables); + this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables); })); + } - // Activate panel action on opening of a panel - this._register(this.onDidPanelOpen(({ panel }) => { - this.compositeBar.activateComposite(panel.getId()); - this.layoutCompositeBar(); // Need to relayout composite bar since different panels have different action bar width - })); + private onDidRegisterExtensions(): void { + this.removeNotExistingComposites(); - // Deactivate panel action on close - this._register(this.onDidPanelClose(panel => this.compositeBar.deactivateComposite(panel.getId()))); + this.saveCachedPanels(); + } - // State - this.lifecycleService.when(LifecyclePhase.Eventually).then(() => { - this._register(this.compositeBar.onDidChange(() => this.saveCachedPanels())); - this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); - }); + private removeNotExistingComposites(): void { + const panels = this.getPanels(); + for (const { id } of this.getCachedPanels()) { // should this value match viewlet (load on ctor) + if (panels.every(panel => panel.id !== id)) { + this.hideComposite(id); + } + } + } + + private hideComposite(compositeId: string): void { + this.compositeBar.hideComposite(compositeId); + + const compositeActions = this.compositeActions.get(compositeId); + if (compositeActions) { + compositeActions.activityAction.dispose(); + compositeActions.pinnedAction.dispose(); + this.compositeActions.delete(compositeId); + } } private onPanelOpen(panel: IPanel): void { this.activePanelContextKey.set(panel.getId()); + + const foundPanel = this.panelRegistry.getPanel(panel.getId()); + if (foundPanel) { + this.compositeBar.addComposite(foundPanel); + } + + // Activate composite when opened + this.compositeBar.activateComposite(panel.getId()); + + const panelDescriptor = this.panelRegistry.getPanel(panel.getId()); + if (panelDescriptor) { + const viewContainer = this.getViewContainer(panelDescriptor.id); + if (viewContainer?.hideIfEmpty) { + const viewDescriptors = this.viewsService.getViewDescriptors(viewContainer); + if (viewDescriptors?.activeViewDescriptors.length === 0) { + this.hideComposite(panelDescriptor.id); // Update the composite bar by hiding + } + } + } + + this.layoutCompositeBar(); // Need to relayout composite bar since different panels have different action bar width } private onPanelClose(panel: IPanel): void { @@ -193,6 +311,8 @@ export class PanelPart extends CompositePart implements IPanelService { if (this.activePanelContextKey.get() === id) { this.activePanelContextKey.reset(); } + + this.compositeBar.deactivateComposite(panel.getId()); } create(parent: HTMLElement): void { @@ -243,11 +363,11 @@ export class PanelPart extends CompositePart implements IPanelService { } getPanel(panelId: string): IPanelIdentifier | undefined { - return Registry.as(PanelExtensions.Panels).getPanel(panelId); + return this.panelRegistry.getPanel(panelId); } getPanels(): readonly PanelDescriptor[] { - return Registry.as(PanelExtensions.Panels).getPanels() + return this.panelRegistry.getPanels() .sort((v1, v2) => typeof v1.order === 'number' && typeof v2.order === 'number' ? v1.order - v2.order : NaN); } @@ -331,10 +451,18 @@ export class PanelPart extends CompositePart implements IPanelService { private getCompositeActions(compositeId: string): { activityAction: PanelActivityAction, pinnedAction: ToggleCompositePinnedAction; } { let compositeActions = this.compositeActions.get(compositeId); if (!compositeActions) { - compositeActions = { - activityAction: this.instantiationService.createInstance(PanelActivityAction, assertIsDefined(this.getPanel(compositeId))), - pinnedAction: new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar) - }; + const panel = this.getPanel(compositeId); + if (panel) { + compositeActions = { + activityAction: new PanelActivityAction(assertIsDefined(this.getPanel(compositeId)), this), + pinnedAction: new ToggleCompositePinnedAction(this.getPanel(compositeId), this.compositeBar) + }; + } else { + compositeActions = { + activityAction: new PlaceHolderPanelActivityAction(compositeId, this), + pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar) + }; + } this.compositeActions.set(compositeId, compositeActions); } @@ -448,6 +576,11 @@ export class PanelPart extends CompositePart implements IPanelService { this.storageService.store(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL); } + private getViewContainer(panelId: string): ViewContainer | undefined { + const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); + return viewContainerRegistry.get(panelId); + } + toJSON(): object { return { type: Parts.PANEL_PART diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index f4e235c1c5..5c71f33d03 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -495,14 +495,12 @@ export class CustomTreeView extends Disposable implements ITreeView { private showMessage(message: string): void { DOM.removeClass(this.messageElement, 'hide'); - if (this._messageValue !== message) { - this.resetMessageElement(); - this._messageValue = message; - if (!isFalsyOrWhitespace(this._message)) { - this.messageElement.textContent = this._messageValue; - } - this.layout(this._height, this._width); + this.resetMessageElement(); + this._messageValue = message; + if (!isFalsyOrWhitespace(this._message)) { + this.messageElement.textContent = this._messageValue; } + this.layout(this._height, this._width); } private hideMessage(): void { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 140d1bfb5c..b004a4a0da 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -243,7 +243,7 @@ interface IViewPaneItem { export class ViewPaneContainer extends Component implements IViewPaneContainer { - private readonly viewContainer: ViewContainer; + readonly viewContainer: ViewContainer; private lastFocusedPane: ViewPane | undefined; private paneItems: IViewPaneItem[] = []; private paneview?: PaneView; diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index eff4d38dde..779bfce549 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -8,6 +8,21 @@ import * as nls from 'vs/nls'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { isMacintosh, isWindows, isLinux, isWeb, isNative } from 'vs/base/common/platform'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; +import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor, PaneCompositePanel } from 'vs/workbench/browser/panel'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation } from 'vs/workbench/common/views'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { Viewlet, ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { isString } from 'vs/base/common/types'; +import { URI } from 'vs/base/common/uri'; // Configuration (function registerConfiguration(): void { @@ -373,3 +388,74 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio } }); })(); + +// Viewlets & Panels +(function registerViewletsAndPanels(): void { + const registerPanel = (viewContainer: ViewContainer): void => { + class PaneContainerPanel extends PaneCompositePanel { + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IStorageService storageService: IStorageService, + @IInstantiationService instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService, + @IWorkspaceContextService contextService: IWorkspaceContextService + ) { + super(viewContainer.id, (instantiationService as any).createInstance(viewContainer.ctorDescriptor!.ctor, ...(viewContainer.ctorDescriptor!.arguments || [])), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService); + } + } + Registry.as(PanelExtensions.Panels).registerPanel(PanelDescriptor.create( + PaneContainerPanel, + viewContainer.id, + viewContainer.name, + isString(viewContainer.icon) ? viewContainer.icon : undefined, + viewContainer.order, + viewContainer.focusCommand?.id, + )); + }; + + const registerViewlet = (viewContainer: ViewContainer): void => { + class PaneContainerViewlet extends Viewlet { + constructor( + @IConfigurationService configurationService: IConfigurationService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @ITelemetryService telemetryService: ITelemetryService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IStorageService storageService: IStorageService, + @IEditorService editorService: IEditorService, + @IInstantiationService instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService + ) { + super(viewContainer.id, (instantiationService as any).createInstance(viewContainer.ctorDescriptor!.ctor, ...(viewContainer.ctorDescriptor!.arguments || [])), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); + } + } + const viewletDescriptor = ViewletDescriptor.create( + PaneContainerViewlet, + viewContainer.id, + viewContainer.name, + isString(viewContainer.icon) ? viewContainer.icon : undefined, + viewContainer.order, + viewContainer.icon instanceof URI ? viewContainer.icon : undefined + ); + + Registry.as(ViewletExtensions.Viewlets).registerViewlet(viewletDescriptor); + }; + + const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); + viewContainerRegistry.getViewContainers(ViewContainerLocation.Panel).forEach(viewContainer => registerPanel(viewContainer)); + viewContainerRegistry.onDidRegister(({ viewContainer, viewContainerLocation }) => { + switch (viewContainerLocation) { + case ViewContainerLocation.Panel: + registerPanel(viewContainer); + return; + case ViewContainerLocation.Sidebar: + if (viewContainer.ctorDescriptor) { + registerViewlet(viewContainer); + } + return; + } + }); +})(); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 9db7e6564f..c37abb750b 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -1327,3 +1327,16 @@ export async function pathsToEditors(paths: IPathData[] | undefined, fileService return coalesce(editors); } + +export const enum EditorsOrder { + + /** + * Editors sorted by most recent activity (most recent active first) + */ + MOST_RECENTLY_ACTIVE, + + /** + * Editors sorted by sequential order + */ + SEQUENTIAL +} diff --git a/src/vs/workbench/common/editor/editorGroup.ts b/src/vs/workbench/common/editor/editorGroup.ts index 2c02ddfd7a..73573537eb 100644 --- a/src/vs/workbench/common/editor/editorGroup.ts +++ b/src/vs/workbench/common/editor/editorGroup.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { Extensions, IEditorInputFactoryRegistry, EditorInput, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, CloseDirection, SideBySideEditorInput, IEditorInput } from 'vs/workbench/common/editor'; +import { Extensions, IEditorInputFactoryRegistry, EditorInput, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, CloseDirection, SideBySideEditorInput, IEditorInput, EditorsOrder } from 'vs/workbench/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; @@ -136,8 +136,8 @@ export class EditorGroup extends Disposable { return this.editors.length; } - getEditors(mru?: boolean): EditorInput[] { - return mru ? this.mru.slice(0) : this.editors.slice(0); + getEditors(order: EditorsOrder): EditorInput[] { + return order === EditorsOrder.MOST_RECENTLY_ACTIVE ? this.mru.slice(0) : this.editors.slice(0); } getEditorByIndex(index: number): EditorInput | undefined { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index a4217b1e2c..5267999cd9 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Command } from 'vs/editor/common/modes'; -import { UriComponents } from 'vs/base/common/uri'; +import { UriComponents, URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { localize } from 'vs/nls'; @@ -18,6 +18,7 @@ import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry' import { IAction } from 'vs/base/common/actions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { flatten } from 'vs/base/common/arrays'; +import { IViewPaneContainer } from 'vs/workbench/common/viewPaneContainer'; export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test'; export const FocusedViewContext = new RawContextKey('focusedView', ''); @@ -38,6 +39,14 @@ export interface IViewContainerDescriptor { readonly name: string; + readonly ctorDescriptor: { ctor: new (...args: any[]) => IViewPaneContainer, arguments?: any[] }; + + readonly icon?: string | URI; + + readonly order?: number; + + readonly focusCommand?: { id: string, keybindings?: IKeybindings }; + readonly viewOrderDelegate?: ViewOrderDelegate; readonly hideIfEmpty?: boolean; @@ -96,16 +105,7 @@ interface ViewOrderDelegate { getOrder(group?: string): number | undefined; } -export class ViewContainer { - - protected constructor(private readonly descriptor: IViewContainerDescriptor) { } - - readonly id: string = this.descriptor.id; - readonly name: string = this.descriptor.name; - readonly hideIfEmpty: boolean = !!this.descriptor.hideIfEmpty; - readonly extensionId: ExtensionIdentifier | undefined = this.descriptor.extensionId; - readonly orderDelegate: ViewOrderDelegate | undefined = this.descriptor.viewOrderDelegate; -} +export interface ViewContainer extends IViewContainerDescriptor { } class ViewContainersRegistryImpl extends Disposable implements IViewContainersRegistry { @@ -127,11 +127,7 @@ class ViewContainersRegistryImpl extends Disposable implements IViewContainersRe return existing; } - const viewContainer = new class extends ViewContainer { - constructor() { - super(viewContainerDescriptor); - } - }; + const viewContainer: ViewContainer = { ...viewContainerDescriptor }; const viewContainers = getOrSet(this.viewContainers, viewContainerLocation, []); viewContainers.push(viewContainer); this._onDidRegister.fire({ viewContainer, viewContainerLocation }); diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index 91974639e9..bda7e12073 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -122,7 +122,7 @@ suite.skip('BackupModelRestorer', () => { // {{SQL CARBON EDIT}} TODO @anthonydr // Verify backups restored and opened as dirty await restorer.doRestoreBackups(); - assert.equal(editorService.editors.length, 4); + assert.equal(editorService.count, 4); assert.ok(editorService.editors.every(editor => editor.isDirty())); let counter = 0; diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 880bb9696f..7f320cbe92 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -13,14 +13,14 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actions'; -import { ShowViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; +import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { TogglePanelAction, Extensions as PanelExtensions, PanelRegistry, PanelDescriptor } from 'vs/workbench/browser/panel'; import { BreakpointsView } from 'vs/workbench/contrib/debug/browser/breakpointsView'; import { CallStackView } from 'vs/workbench/contrib/debug/browser/callStackView'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IDebugService, VIEWLET_ID, REPL_ID, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA, - CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, VIEW_CONTAINER, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, + CONTEXT_DEBUG_STATE, VARIABLES_VIEW_ID, CALLSTACK_VIEW_ID, WATCH_VIEW_ID, BREAKPOINTS_VIEW_ID, LOADED_SCRIPTS_VIEW_ID, CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_FOCUSED_SESSION_IS_ATTACH, CONTEXT_STEP_BACK_SUPPORTED, CONTEXT_CALLSTACK_ITEM_TYPE, CONTEXT_RESTART_FRAME_SUPPORTED, CONTEXT_JUMP_TO_CURSOR_SUPPORTED, CONTEXT_DEBUG_UX, } from 'vs/workbench/contrib/debug/common/debug'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -31,7 +31,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID, RESTART_LABEL, STEP_INTO_LABEL, STEP_OVER_LABEL, STEP_OUT_LABEL, PAUSE_LABEL, DISCONNECT_LABEL, STOP_LABEL, CONTINUE_LABEL } from 'vs/workbench/contrib/debug/browser/debugCommands'; import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { StatusBarColorProvider } from 'vs/workbench/contrib/debug/browser/statusbarColorProvider'; -import { IViewsRegistry, Extensions as ViewExtensions } from 'vs/workbench/common/views'; +import { IViewsRegistry, Extensions as ViewExtensions, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; import { isMacintosh } from 'vs/base/common/platform'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { URI } from 'vs/base/common/uri'; @@ -46,9 +46,9 @@ import { WatchExpressionsView } from 'vs/workbench/contrib/debug/browser/watchEx import { VariablesView } from 'vs/workbench/contrib/debug/browser/variablesView'; import { ClearReplAction, Repl } from 'vs/workbench/contrib/debug/browser/repl'; import { DebugContentProvider } from 'vs/workbench/contrib/debug/common/debugContentProvider'; -import { DebugViewlet } from 'vs/workbench/contrib/debug/browser/debugViewlet'; import { StartView } from 'vs/workbench/contrib/debug/browser/startView'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { DebugViewPaneContainer } from 'vs/workbench/contrib/debug/browser/debugViewlet'; class OpenDebugViewletAction extends ShowViewletAction { public static readonly ID = VIEWLET_ID; @@ -79,14 +79,13 @@ class OpenDebugPanelAction extends TogglePanelAction { } } -// register viewlet -Registry.as(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create( - DebugViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-debug-alt', - 13 // {{SQL CARBON EDIT}} -)); +const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: nls.localize('debugAndRun', "Debug and Run"), + ctorDescriptor: { ctor: DebugViewPaneContainer }, + icon: 'codicon-debug-alt', + order: 13 // {{SQL CARBON EDIT}} +}, ViewContainerLocation.Sidebar); const openViewletKb: IKeybindings = { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_D @@ -107,12 +106,12 @@ Registry.as(PanelExtensions.Panels).registerPanel(PanelDescriptor // Register default debug views const viewsRegistry = Registry.as(ViewExtensions.ViewsRegistry); -viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), ctorDescriptor: { ctor: VariablesView }, order: 10, weight: 40, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], VIEW_CONTAINER); -viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctorDescriptor: { ctor: WatchExpressionsView }, order: 20, weight: 10, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], VIEW_CONTAINER); -viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctorDescriptor: { ctor: CallStackView }, order: 30, weight: 30, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], VIEW_CONTAINER); -viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: { ctor: BreakpointsView }, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], VIEW_CONTAINER); -viewsRegistry.registerViews([{ id: StartView.ID, name: StartView.LABEL, ctorDescriptor: { ctor: StartView }, order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], VIEW_CONTAINER); -viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: { ctor: LoadedScriptsView }, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], VIEW_CONTAINER); +viewsRegistry.registerViews([{ id: VARIABLES_VIEW_ID, name: nls.localize('variables', "Variables"), ctorDescriptor: { ctor: VariablesView }, order: 10, weight: 40, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusVariablesView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); +viewsRegistry.registerViews([{ id: WATCH_VIEW_ID, name: nls.localize('watch', "Watch"), ctorDescriptor: { ctor: WatchExpressionsView }, order: 20, weight: 10, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusWatchView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); +viewsRegistry.registerViews([{ id: CALLSTACK_VIEW_ID, name: nls.localize('callStack', "Call Stack"), ctorDescriptor: { ctor: CallStackView }, order: 30, weight: 30, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusCallStackView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); +viewsRegistry.registerViews([{ id: BREAKPOINTS_VIEW_ID, name: nls.localize('breakpoints', "Breakpoints"), ctorDescriptor: { ctor: BreakpointsView }, order: 40, weight: 20, canToggleVisibility: true, focusCommand: { id: 'workbench.debug.action.focusBreakpointsView' }, when: CONTEXT_DEBUG_UX.isEqualTo('default') }], viewContainer); +viewsRegistry.registerViews([{ id: StartView.ID, name: StartView.LABEL, ctorDescriptor: { ctor: StartView }, order: 10, weight: 40, canToggleVisibility: true, when: CONTEXT_DEBUG_UX.isEqualTo('simple') }], viewContainer); +viewsRegistry.registerViews([{ id: LOADED_SCRIPTS_VIEW_ID, name: nls.localize('loadedScripts', "Loaded Scripts"), ctorDescriptor: { ctor: LoadedScriptsView }, order: 35, weight: 5, canToggleVisibility: true, collapsed: true, when: ContextKeyExpr.and(CONTEXT_LOADED_SCRIPTS_SUPPORTED, CONTEXT_DEBUG_UX.isEqualTo('default')) }], viewContainer); registerCommands(); diff --git a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts index 15cf1e1218..ff5919768d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts @@ -157,25 +157,33 @@ export class StartDebugActionViewItem implements IActionViewItem { this.selected = 0; this.options = []; const manager = this.debugService.getConfigurationManager(); - const launches = manager.getLaunches(); const inWorkspace = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE; - launches.forEach(launch => - launch.getConfigurationNames().forEach(name => { - if (name === manager.selectedConfiguration.name && launch === manager.selectedConfiguration.launch) { - this.selected = this.options.length; + let lastGroup: string | undefined; + const disabledIdxs: number[] = []; + manager.getAllConfigurations().forEach(({ launch, name, presentation }) => { + if (name === manager.selectedConfiguration.name && launch === manager.selectedConfiguration.launch) { + this.selected = this.options.length; + } + if (lastGroup !== presentation?.group) { + lastGroup = presentation?.group; + if (this.options.length) { + this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: undefined }); + disabledIdxs.push(this.options.length - 1); } - const label = inWorkspace ? `${name} (${launch.name})` : name; - this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } }); - })); + } + + const label = inWorkspace ? `${name} (${launch.name})` : name; + this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } }); + }); if (this.options.length === 0) { this.options.push({ label: nls.localize('noConfigurations', "No Configurations"), handler: () => false }); } else { this.options.push({ label: StartDebugActionViewItem.SEPARATOR, handler: undefined }); + disabledIdxs.push(this.options.length - 1); } - const disabledIdx = this.options.length - 1; - launches.filter(l => !l.hidden).forEach(l => { + manager.getLaunches().filter(l => !l.hidden).forEach(l => { const label = inWorkspace ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration..."); this.options.push({ label, handler: () => { @@ -185,7 +193,7 @@ export class StartDebugActionViewItem implements IActionViewItem { }); }); - this.selectBox.setOptions(this.options.map((data, index) => { text: data.label, isDisabled: (index === disabledIdx ? true : undefined) }), this.selected); + this.selectBox.setOptions(this.options.map((data, index) => { text: data.label, isDisabled: disabledIdxs.indexOf(index) !== -1 }), this.selected); } } diff --git a/src/vs/workbench/contrib/debug/browser/debugActions.ts b/src/vs/workbench/contrib/debug/browser/debugActions.ts index c0d461ae45..e7759579e8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActions.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActions.ts @@ -79,8 +79,7 @@ export class ConfigureAction extends AbstractDebugAction { private updateClass(): void { const configurationManager = this.debugService.getConfigurationManager(); - const configurationCount = configurationManager.getLaunches().map(l => l.getConfigurationNames().length).reduce((sum, current) => sum + current); - this.class = configurationCount > 0 ? 'debug-action codicon codicon-gear' : 'debug-action codicon codicon-gear notification'; + this.class = configurationManager.selectedConfiguration.name ? 'debug-action codicon codicon-gear' : 'debug-action codicon codicon-gear notification'; } async run(event?: any): Promise { @@ -145,7 +144,7 @@ export class StartAction extends AbstractDebugAction { if (debugService.state === State.Initializing) { return false; } - if ((sessions.length > 0) && debugService.getConfigurationManager().getLaunches().every(l => l.getConfigurationNames().length === 0)) { + if ((sessions.length > 0) && !debugService.getConfigurationManager().selectedConfiguration.name) { // There is already a debug session running and we do not have any launch configuration selected return false; } diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index d20fe62d1e..59d93cd00f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -21,7 +21,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IConfigPresentation } from 'vs/workbench/contrib/debug/common/debug'; import { Debugger } from 'vs/workbench/contrib/debug/common/debugger'; import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; @@ -214,6 +214,43 @@ export class ConfigurationManager implements IConfigurationManager { return results.reduce((first, second) => first.concat(second), []); } + getAllConfigurations(): { launch: ILaunch; name: string; presentation?: IConfigPresentation }[] { + const all: { launch: ILaunch, name: string, presentation?: IConfigPresentation }[] = []; + for (let l of this.launches) { + for (let name of l.getConfigurationNames()) { + const config = l.getConfiguration(name) || l.getCompound(name); + if (config && !config.presentation?.hidden) { + all.push({ launch: l, name, presentation: config.presentation }); + } + } + } + + return all.sort((first, second) => { + if (!first.presentation) { + return 1; + } + if (!second.presentation) { + return -1; + } + if (!first.presentation.group) { + return 1; + } + if (!second.presentation.group) { + return -1; + } + if (first.presentation.group !== second.presentation.group) { + return first.presentation.group.localeCompare(second.presentation.group); + } + if (typeof first.presentation.order !== 'number') { + return 1; + } + if (typeof second.presentation.order !== 'number') { + return -1; + } + return first.presentation.order - second.presentation.order; + }); + } + private registerListeners(): void { debuggersExtPoint.setHandler((extensions, delta) => { delta.added.forEach(added => { diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickOpen.ts b/src/vs/workbench/contrib/debug/browser/debugQuickOpen.ts index 030944a046..514650787d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickOpen.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickOpen.ts @@ -96,18 +96,24 @@ export class DebugQuickOpenHandler extends QuickOpenHandler { const configurations: QuickOpenEntry[] = []; const configManager = this.debugService.getConfigurationManager(); - const launches = configManager.getLaunches(); - for (let launch of launches) { - launch.getConfigurationNames().map(config => ({ config: config, highlights: matchesFuzzy(input, config, true) || undefined })) - .filter(({ highlights }) => !!highlights) - .forEach(({ config, highlights }) => { - if (launch === configManager.selectedConfiguration.launch && config === configManager.selectedConfiguration.name) { - this.autoFocusIndex = configurations.length; - } - configurations.push(new StartDebugEntry(this.debugService, this.contextService, this.notificationService, launch, config, highlights)); - }); + const allConfigurations = configManager.getAllConfigurations(); + let lastGroup: string | undefined; + for (let config of allConfigurations) { + const highlights = matchesFuzzy(input, config.name, true); + if (highlights) { + if (config.launch === configManager.selectedConfiguration.launch && config.name === configManager.selectedConfiguration.name) { + this.autoFocusIndex = configurations.length; + } + let entry: QuickOpenEntry = new StartDebugEntry(this.debugService, this.contextService, this.notificationService, config.launch, config.name, highlights); + if (lastGroup !== config.presentation?.group) { + entry = new QuickOpenEntryGroup(entry, undefined, true); + lastGroup = config.presentation?.group; + } + configurations.push(entry); + } } - launches.filter(l => !l.hidden).forEach((l, index) => { + + configManager.getLaunches().filter(l => !l.hidden).forEach((l, index) => { const label = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration..."); const entry = new AddConfigEntry(label, l, this.commandService, this.contextService, matchesFuzzy(input, label, true) || undefined); diff --git a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts index 96383899ef..48e864a687 100644 --- a/src/vs/workbench/contrib/debug/browser/debugViewlet.ts +++ b/src/vs/workbench/contrib/debug/browser/debugViewlet.ts @@ -32,26 +32,8 @@ import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryAc import { INotificationService } from 'vs/platform/notification/common/notification'; import { TogglePanelAction } from 'vs/workbench/browser/panel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { Viewlet } from 'vs/workbench/browser/viewlet'; import { StartView } from 'vs/workbench/contrib/debug/browser/startView'; -// Register a lightweight viewlet responsible for making the container -export class DebugViewlet extends Viewlet { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService - ) { - super(VIEWLET_ID, instantiationService.createInstance(DebugViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } -} - export class DebugViewPaneContainer extends ViewPaneContainer { private startDebugActionViewItem: StartDebugActionViewItem | undefined; diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index dfc87fd7a1..b064c72f55 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -24,11 +24,8 @@ import { TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { Extensions as ViewContainerExtensions, IViewContainersRegistry, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views'; -import { Registry } from 'vs/platform/registry/common/platform'; export const VIEWLET_ID = 'workbench.view.debug'; -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: nls.localize('debugAndRun', "Debug and Run") }, ViewContainerLocation.Sidebar); export const VARIABLES_VIEW_ID = 'workbench.debug.variablesView'; export const WATCH_VIEW_ID = 'workbench.debug.watchExpressionsView'; @@ -487,13 +484,19 @@ export interface IEnvConfig { noDebug?: boolean; } +export interface IConfigPresentation { + hidden?: boolean; + group?: string; + order?: number; +} + export interface IConfig extends IEnvConfig { // fundamental attributes type: string; request: string; name: string; - + presentation?: IConfigPresentation; // platform specifics windows?: IEnvConfig; osx?: IEnvConfig; @@ -510,6 +513,7 @@ export interface ICompound { name: string; preLaunchTask?: string | TaskIdentifier; configurations: (string | { name: string, folder: string })[]; + presentation?: IConfigPresentation; } export interface IDebugAdapter extends IDisposable { @@ -631,6 +635,8 @@ export interface IConfigurationManager { getLaunch(workspaceUri: uri | undefined): ILaunch | undefined; + getAllConfigurations(): { launch: ILaunch, name: string, presentation?: IConfigPresentation }[]; + /** * Allows to register on change of selected debug configuration. */ diff --git a/src/vs/workbench/contrib/debug/common/debugSchemas.ts b/src/vs/workbench/contrib/debug/common/debugSchemas.ts index 7d401c4a09..c60e484ef4 100644 --- a/src/vs/workbench/contrib/debug/common/debugSchemas.ts +++ b/src/vs/workbench/contrib/debug/common/debugSchemas.ts @@ -132,6 +132,33 @@ export const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registe }); // debug general schema + +export const presentationSchema: IJSONSchema = { + type: 'object', + description: nls.localize('presentation', "Presentation options on how to show this configuration in the debug configuration dropdown and the command palette."), + properties: { + hidden: { + type: 'boolean', + default: false, + description: nls.localize('presentation.hidden', "Controls if this configuration should be shown in the configuration dropdown and the command palette.") + }, + group: { + type: 'string', + default: '', + description: nls.localize('presentation.group', "Group that this configuration belongs to. Used for grouping and sorting in the configuration dropdown and the command palette.") + }, + order: { + type: 'number', + default: 1, + description: nls.localize('presentation.order', "Order of this configuration within a group. Used for grouping and sorting in the configuration dropdown and the command palette.") + } + }, + default: { + hidden: false, + group: '', + order: 1 + } +}; const defaultCompound: ICompound = { name: 'Compound', configurations: [] }; export const launchSchema: IJSONSchema = { id: launchSchemaId, @@ -167,6 +194,7 @@ export const launchSchema: IJSONSchema = { type: 'string', description: nls.localize('app.launch.json.compound.name', "Name of compound. Appears in the launch configuration drop down menu.") }, + presentation: presentationSchema, configurations: { type: 'array', default: [], diff --git a/src/vs/workbench/contrib/debug/common/debugger.ts b/src/vs/workbench/contrib/debug/common/debugger.ts index 8d44cf3b44..482ec4678f 100644 --- a/src/vs/workbench/contrib/debug/common/debugger.ts +++ b/src/vs/workbench/contrib/debug/common/debugger.ts @@ -22,6 +22,7 @@ import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; +import { presentationSchema } from 'vs/workbench/contrib/debug/common/debugSchemas'; export class Debugger implements IDebugger { @@ -222,7 +223,7 @@ export class Debugger implements IDebugger { }; properties['name'] = { type: 'string', - description: nls.localize('debugName', "Name of configuration; appears in the launch configuration drop down menu."), + description: nls.localize('debugName', "Name of configuration; appears in the launch configuration dropdown menu."), default: 'Launch' }; properties['request'] = { @@ -250,6 +251,7 @@ export class Debugger implements IDebugger { defaultSnippets: [{ body: { task: '', type: '' } }], description: nls.localize('debugPostDebugTask', "Task to run after debug session ends.") }; + properties['presentation'] = presentationSchema; properties['internalConsoleOptions'] = INTERNAL_CONSOLE_OPTIONS_SCHEMA; // Clear out windows, linux and osx fields to not have cycles inside the properties object delete properties['windows']; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 7de3448014..0a069e6af6 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -61,7 +61,6 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { TokenizationRegistry } from 'vs/editor/common/modes'; import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization'; import { editorBackground } from 'vs/platform/theme/common/colorRegistry'; -import { ExtensionsViewlet, ExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; function removeEmbeddedSVGs(documentContent: string): string { const newDocument = new DOMParser().parseFromString(documentContent, 'text/html'); @@ -393,7 +392,10 @@ export class ExtensionEditor extends BaseEditor { } this.transientDisposables.add(this.onClick(template.publisher, () => { this.viewletService.openViewlet(VIEWLET_ID, true) - .then((viewlet: ExtensionsViewlet) => (viewlet.getViewPaneContainer() as ExtensionsViewPaneContainer).search(`publisher:"${extension.publisherDisplayName}"`)); + .then(viewlet => viewlet?.getViewPaneContainer()) + .then((viewlet: IExtensionsViewPaneContainer) => { + viewlet.search(`publisher:"${extension.publisherDisplayName}"`); + }); })); } // {{SQL CARBON EDIT}} - End diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index b273a387c4..ddc26ef558 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -14,7 +14,7 @@ import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } fro import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/services/output/common/output'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { VIEWLET_ID, IExtensionsWorkbenchService, VIEW_CONTAINER } from 'vs/workbench/contrib/extensions/common/extensions'; +import { VIEWLET_ID, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; import { OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction, @@ -22,9 +22,8 @@ import { EnableAllAction, EnableAllWorkspaceAction, DisableAllAction, DisableAllWorkspaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor'; -import { StatusUpdater, MaliciousExtensionChecker, ExtensionsViewletViewsContribution, ExtensionsViewlet } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; +import { StatusUpdater, MaliciousExtensionChecker, ExtensionsViewletViewsContribution, ExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import * as jsonContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; @@ -44,6 +43,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionType, ExtensionsPolicy } from 'vs/platform/extensions/common/extensions'; // {{SQL CARBON EDIT}} import { RemoteExtensionsInstaller } from 'vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller'; import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/browser/extensionTipsService'; +import { IViewContainersRegistry, ViewContainerLocation, Extensions as ViewContainerExtensions } from 'vs/workbench/common/views'; // Singletons registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); @@ -75,17 +75,15 @@ Registry.as(EditorExtensions.Editors).registerEditor( new SyncDescriptor(ExtensionsInput) ]); -// Viewlet -const viewletDescriptor = ViewletDescriptor.create( - ExtensionsViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-extensions', - 14 // {{SQL CARBON EDIT}} -); +Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( + { + id: VIEWLET_ID, + name: localize('extensions', "Extensions"), + ctorDescriptor: { ctor: ExtensionsViewPaneContainer }, + icon: 'codicon-extensions', + order: 14 // {{SQL CARBON EDIT}} + }, ViewContainerLocation.Sidebar); -Registry.as(ViewletExtensions.Viewlets) - .registerViewlet(viewletDescriptor); // Global actions const actionRegistry = Registry.as(WorkbenchActionExtensions.WorkbenchActions); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index aaec474707..001ac5e266 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -18,7 +18,7 @@ import { append, $, addClass, toggleClass, Dimension } from 'vs/base/browser/dom import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, AutoUpdateConfigurationKey, ShowRecommendationsOnlyOnDemandKey, CloseExtensionDetailsOnViewChangeKey, VIEW_CONTAINER } from '../common/extensions'; +import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, AutoUpdateConfigurationKey, ShowRecommendationsOnlyOnDemandKey, CloseExtensionDetailsOnViewChangeKey } from '../common/extensions'; import { ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, /*ShowPopularExtensionsAction,*/ ShowDisabledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction, @@ -35,7 +35,7 @@ import Severity from 'vs/base/common/severity'; import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IViewsRegistry, IViewDescriptor, Extensions } from 'vs/workbench/common/views'; +import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry } from 'vs/workbench/common/views'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IContextKeyService, ContextKeyExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -57,7 +57,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { RemoteNameContext } from 'vs/workbench/browser/contextkeys'; import { ILabelService } from 'vs/platform/label/common/label'; import { MementoObject } from 'vs/workbench/common/memento'; -import { Viewlet } from 'vs/workbench/browser/viewlet'; const NonEmptyWorkspaceContext = new RawContextKey('nonEmptyWorkspace', false); const DefaultViewsContext = new RawContextKey('defaultExtensionViews', true); @@ -89,10 +88,13 @@ const viewIdNameMappings: { [id: string]: string } = { export class ExtensionsViewletViewsContribution implements IWorkbenchContribution { + private readonly container: ViewContainer; + constructor( @IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService, @ILabelService private readonly labelService: ILabelService, ) { + this.container = Registry.as(Extensions.ViewContainersRegistry).get(VIEWLET_ID)!; this.registerViews(); } @@ -119,7 +121,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(this.extensionManagementServerService.remoteExtensionManagementServer)); } - Registry.as(Extensions.ViewsRegistry).registerViews(viewDescriptors, VIEW_CONTAINER); + Registry.as(Extensions.ViewsRegistry).registerViews(viewDescriptors, this.container); } // View used for any kind of searching @@ -318,22 +320,6 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio } -export class ExtensionsViewlet extends Viewlet { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService - ) { - super(VIEWLET_ID, instantiationService.createInstance(ExtensionsViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } -} - export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IExtensionsViewPaneContainer { private readonly _onSearchChange: Emitter = this._register(new Emitter()); diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index cc39f873e5..60ddf618ff 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -14,12 +14,9 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { IViewPaneContainer } from 'vs/workbench/common/viewPaneContainer'; -import { Extensions as ViewContainerExtensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { localize } from 'vs/nls'; +import { IAction } from 'vs/base/common/actions'; export const VIEWLET_ID = 'workbench.view.extensions'; -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('extensions', "Extensions") }, ViewContainerLocation.Sidebar); export const EXTENSIONS_CONFIG = '.azuredatastudio/extensions.json'; @@ -148,3 +145,12 @@ export class ExtensionContainers extends Disposable { } } } + +export interface IExtensionMenuAction extends IAction { + run(context: IExtensionMenuActionContext): Promise; +} + +export interface IExtensionMenuActionContext { + id: string; + packageJSON: IExtensionManifest; +} diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index ecbb26fce8..9e4cd8d01f 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/explorerviewlet'; import { localize } from 'vs/nls'; import * as DOM from 'vs/base/browser/dom'; -import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration, OpenEditorsVisibleContext, VIEW_CONTAINER } from 'vs/workbench/contrib/files/common/files'; +import { VIEWLET_ID, ExplorerViewletVisibleContext, IFilesConfiguration, OpenEditorsVisibleContext } from 'vs/workbench/contrib/files/common/files'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { ExplorerView } from 'vs/workbench/contrib/files/browser/views/explorerView'; @@ -20,7 +20,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IViewsRegistry, IViewDescriptor, Extensions } from 'vs/workbench/common/views'; +import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -33,7 +33,6 @@ import { ViewPane, ViewPaneContainer } from 'vs/workbench/browser/parts/views/vi import { KeyChord, KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Registry } from 'vs/platform/registry/common/platform'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; -import { Viewlet } from 'vs/workbench/browser/viewlet'; export class ExplorerViewletViewsContribution extends Disposable implements IWorkbenchContribution { @@ -146,22 +145,6 @@ export class ExplorerViewletViewsContribution extends Disposable implements IWor } } -export class ExplorerViewlet extends Viewlet { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService - ) { - super(VIEWLET_ID, instantiationService.createInstance(ExplorerViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } -} - export class ExplorerViewPaneContainer extends ViewPaneContainer { private static readonly EXPLORER_VIEWS_STATE = 'workbench.explorer.views.state'; @@ -257,3 +240,14 @@ export class ExplorerViewPaneContainer extends ViewPaneContainer { } } } + +/** + * Explorer viewlet container. + */ +export const VIEW_CONTAINER: ViewContainer = Registry.as(Extensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: localize('explore', "Explorer"), + ctorDescriptor: { ctor: ExplorerViewPaneContainer }, + icon: 'codicon-files', + order: 10 // {{SQL CARBON EDIT}} +}, ViewContainerLocation.Sidebar); diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 5b745dd64f..fc52beeb8a 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput, EditorsOrder } from 'vs/workbench/common/editor'; import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -30,7 +30,7 @@ import { Schemas } from 'vs/base/common/network'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IEditorService, SIDE_GROUP, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; -import { IEditorGroupsService, GroupsOrder, EditorsOrder, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, GroupsOrder, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ILabelService } from 'vs/platform/label/common/label'; import { basename, joinPath, isEqual } from 'vs/base/common/resources'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index 02c7372d4f..1fc9899d8d 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI, UriComponents } from 'vs/base/common/uri'; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction } from 'vs/workbench/browser/viewlet'; +import { /*ViewletRegistry, Extensions as ViewletExtensions,*/ ShowViewletAction } from 'vs/workbench/browser/viewlet'; import * as nls from 'vs/nls'; import { sep } from 'vs/base/common/path'; import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; @@ -14,7 +14,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IEditorInputFactory, EditorInput, IFileEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions } from 'vs/workbench/common/editor'; import { AutoSaveConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files'; -import { VIEWLET_ID, VIEW_CONTAINER, SortOrder, FILE_EDITOR_INPUT_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files'; +import { VIEWLET_ID, SortOrder, FILE_EDITOR_INPUT_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { FileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/fileEditorTracker'; import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; @@ -25,7 +25,7 @@ import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry' import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import * as platform from 'vs/base/common/platform'; -import { ExplorerViewletViewsContribution, ExplorerViewlet } from 'vs/workbench/contrib/files/browser/explorerViewlet'; +import { ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -73,15 +73,6 @@ class FileUriLabelContribution implements IWorkbenchContribution { } } -// Register Viewlet -Registry.as(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create( - ExplorerViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-files', - 10 // {{SQL CARBON EDIT}} -)); - registerSingleton(IExplorerService, ExplorerService, true); // {{SQL CARBON EDIT}} diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 12da3f0898..dfafed08ce 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -16,26 +16,19 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService, ILanguageSelection } from 'vs/editor/common/services/modeService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkeys'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainer, IEditableData, ViewContainerLocation } from 'vs/workbench/common/views'; +import { IEditableData } from 'vs/workbench/common/views'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { once } from 'vs/base/common/functional'; import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { localize } from 'vs/nls'; /** * Explorer viewlet id. */ export const VIEWLET_ID = 'workbench.view.explorer'; -/** - * Explorer viewlet container. - */ -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('explore', "Explorer") }, ViewContainerLocation.Sidebar); - export interface IExplorerService { _serviceBrand: undefined; readonly roots: ExplorerItem[]; diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index 3dc7d87b59..61fd46e5e4 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -14,7 +14,7 @@ import { localize } from 'vs/nls'; import { Marker, RelatedInformation } from 'vs/workbench/contrib/markers/browser/markersModel'; import { MarkersView, getMarkersView } from 'vs/workbench/contrib/markers/browser/markersView'; import { MenuId, MenuRegistry, SyncActionDescriptor, registerAction } from 'vs/platform/actions/common/actions'; -import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor, PaneCompositePanel, TogglePanelAction } from 'vs/workbench/browser/panel'; +import { TogglePanelAction } from 'vs/workbench/browser/panel'; import { Registry } from 'vs/platform/registry/common/platform'; import { ShowProblemsPanelAction } from 'vs/workbench/contrib/markers/browser/markersViewActions'; import Constants from 'vs/workbench/contrib/markers/browser/constants'; @@ -30,13 +30,6 @@ import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment, IStatus import { IMarkerService, MarkerStatistics } from 'vs/platform/markers/common/markers'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewsRegistry } from 'vs/workbench/common/views'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -100,30 +93,6 @@ Registry.as(Extensions.Configuration).registerConfigurat } }); - -// markers view container -const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: Constants.MARKERS_PANEL_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS }, ViewContainerLocation.Panel); -Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ - id: Constants.MARKERS_VIEW_ID, - name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, - canToggleVisibility: false, - ctorDescriptor: { ctor: MarkersView }, -}], VIEW_CONTAINER); - -// markers panel -class MarkersPanel extends PaneCompositePanel { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService storageService: IStorageService, - @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService contextMenuService: IContextMenuService, - @IExtensionService extensionService: IExtensionService, - @IWorkspaceContextService contextService: IWorkspaceContextService) { - super(Constants.MARKERS_PANEL_ID, instantiationService.createInstance(ViewPaneContainer, Constants.MARKERS_PANEL_ID, Constants.MARKERS_PANEL_STORAGE_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }), - telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService); - } -} class ToggleMarkersPanelAction extends TogglePanelAction { public static readonly ID = 'workbench.actions.view.problems'; @@ -136,14 +105,25 @@ class ToggleMarkersPanelAction extends TogglePanelAction { super(id, label, Constants.MARKERS_PANEL_ID, panelService, layoutService); } } -Registry.as(PanelExtensions.Panels).registerPanel(PanelDescriptor.create( - MarkersPanel, - Constants.MARKERS_PANEL_ID, - VIEW_CONTAINER.name, - 'markersPanel', - 10, - ToggleMarkersPanelAction.ID -)); + +// markers view container +const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ + id: Constants.MARKERS_PANEL_ID, + name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, + ctorDescriptor: { ctor: ViewPaneContainer, arguments: [Constants.MARKERS_PANEL_ID, Constants.MARKERS_PANEL_STORAGE_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }] }, + focusCommand: { + id: ToggleMarkersPanelAction.ID, keybindings: { + primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_M + } + } +}, ViewContainerLocation.Panel); + +Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([{ + id: Constants.MARKERS_VIEW_ID, + name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, + canToggleVisibility: false, + ctorDescriptor: { ctor: MarkersView }, +}], VIEW_CONTAINER); // workbench const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); diff --git a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts index 1e8f8b46a8..bea35a1970 100644 --- a/src/vs/workbench/contrib/outline/browser/outline.contribution.ts +++ b/src/vs/workbench/contrib/outline/browser/outline.contribution.ts @@ -6,10 +6,10 @@ import { localize } from 'vs/nls'; import { IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions } from 'vs/workbench/common/views'; import { OutlinePane } from './outlinePane'; -import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/common/files'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { OutlineConfigKeys, OutlineViewId } from 'vs/editor/contrib/documentSymbols/outline'; +import { VIEW_CONTAINER } from 'vs/workbench/contrib/files/browser/explorerViewlet'; // import './outlineNavigation'; diff --git a/src/vs/workbench/contrib/output/browser/outputActions.ts b/src/vs/workbench/contrib/output/browser/outputActions.ts index fb4806a3db..6bbf67b15b 100644 --- a/src/vs/workbench/contrib/output/browser/outputActions.ts +++ b/src/vs/workbench/contrib/output/browser/outputActions.ts @@ -173,7 +173,7 @@ export class SwitchOutputActionViewItem extends SelectActionViewItem { selected = logChannelIndex !== -1 ? separatorIndex + 1 + logChannelIndex : 0; } } - this.setOptions(options.map((label, index) => { text: label, isDisabled: (index === separatorIndex ? true : undefined) }), Math.max(0, selected)); + this.setOptions(options.map((label, index) => { text: label, isDisabled: (index === separatorIndex ? true : false) }), Math.max(0, selected)); } } diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 20e2fc0776..012c3275f2 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -5,6 +5,7 @@ import 'vs/css!./remoteViewlet'; import * as nls from 'vs/nls'; +import * as dom from 'vs/base/browser/dom'; import { URI } from 'vs/base/common/uri'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -16,15 +17,15 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet'; -import { VIEWLET_ID, VIEW_CONTAINER } from 'vs/workbench/contrib/remote/common/remote.contribution'; +import { VIEWLET_ID } from 'vs/workbench/contrib/remote/common/remote.contribution'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IViewDescriptor, IViewsRegistry, Extensions } from 'vs/workbench/common/views'; +import { IViewDescriptor, IViewsRegistry, Extensions, ViewContainerLocation, IViewContainersRegistry } from 'vs/workbench/common/views'; import { Registry } from 'vs/platform/registry/common/platform'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction, Viewlet } from 'vs/workbench/browser/viewlet'; +import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions'; @@ -41,17 +42,124 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { SwitchRemoteViewItem, SwitchRemoteAction } from 'vs/workbench/contrib/remote/browser/explorerViewItems'; import { Action, IActionViewItem, IAction } from 'vs/base/common/actions'; import { isStringArray } from 'vs/base/common/types'; -import { IRemoteExplorerService, HelpInformation } from 'vs/workbench/services/remote/common/remoteExplorerService'; +import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { startsWith } from 'vs/base/common/strings'; import { TunnelPanelDescriptor, TunnelViewModel, forwardedPortsViewEnabled } from 'vs/workbench/contrib/remote/browser/tunnelView'; import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views'; -import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { ITreeRenderer, ITreeNode, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree'; +import { WorkbenchAsyncDataTree, TreeResourceNavigator2 } from 'vs/platform/list/browser/listService'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { Event } from 'vs/base/common/event'; +import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; + +export interface HelpInformation { + extensionDescription: IExtensionDescription; + getStarted?: string; + documentation?: string; + feedback?: string; + issues?: string; + remoteName?: string[] | string; +} + +const remoteHelpExtPoint = ExtensionsRegistry.registerExtensionPoint({ + extensionPoint: 'remoteHelp', + jsonSchema: { + description: nls.localize('RemoteHelpInformationExtPoint', 'Contributes help information for Remote'), + type: 'object', + properties: { + 'getStarted': { + description: nls.localize('RemoteHelpInformationExtPoint.getStarted', "The url to your project's Getting Started page"), + type: 'string' + }, + 'documentation': { + description: nls.localize('RemoteHelpInformationExtPoint.documentation', "The url to your project's documentation page"), + type: 'string' + }, + 'feedback': { + description: nls.localize('RemoteHelpInformationExtPoint.feedback', "The url to your project's feedback reporter"), + type: 'string' + }, + 'issues': { + description: nls.localize('RemoteHelpInformationExtPoint.issues', "The url to your project's issues list"), + type: 'string' + } + } + } +}); + +interface IViewModel { + helpInformation: HelpInformation[]; +} + +class HelpTreeVirtualDelegate implements IListVirtualDelegate { + getHeight(element: IHelpItem): number { + return 22; + } + + getTemplateId(element: IHelpItem): string { + return 'HelpItemTemplate'; + } +} + +interface IHelpItemTemplateData { + parent: HTMLElement; + icon: HTMLElement; +} + +class HelpTreeRenderer implements ITreeRenderer { + templateId: string = 'HelpItemTemplate'; + + renderTemplate(container: HTMLElement): IHelpItemTemplateData { + dom.addClass(container, 'remote-help-tree-node-item'); + const icon = dom.append(container, dom.$('.remote-help-tree-node-item-icon')); + const data = Object.create(null); + data.parent = container; + data.icon = icon; + return data; + } + + renderElement(element: ITreeNode, index: number, templateData: IHelpItemTemplateData, height: number | undefined): void { + const container = templateData.parent; + dom.append(container, templateData.icon); + dom.addClasses(templateData.icon, ...element.element.iconClasses); + const labelContainer = dom.append(container, dom.$('.help-item-label')); + labelContainer.innerText = element.element.label; + } + + disposeTemplate(templateData: IHelpItemTemplateData): void { + + } +} + +class HelpDataSource implements IAsyncDataSource { + hasChildren(element: any) { + return element instanceof HelpModel; + } + + getChildren(element: any) { + if (element instanceof HelpModel && element.items) { + return element.items; + } + + return []; + } +} + +interface IHelpItem { + key: string; + iconClasses: string[]; + label: string; + handleClick(): Promise; +} class HelpModel { items: IHelpItem[] | undefined; constructor( + viewModel: IViewModel, openerService: IOpenerService, quickInputService: IQuickInputService, commandService: ICommandService, @@ -59,12 +167,12 @@ class HelpModel { environmentService: IWorkbenchEnvironmentService ) { let helpItems: IHelpItem[] = []; - const getStarted = remoteExplorerService.helpInformation.filter(info => info.getStarted); + const getStarted = viewModel.helpInformation.filter(info => info.getStarted); if (getStarted.length) { helpItems.push(new HelpItem( - ['getStarted'], - nls.localize('remote.help.getStarted', "$(star) Get Started"), + 'star', + nls.localize('remote.help.getStarted', "Get Started"), getStarted.map((info: HelpInformation) => ({ extensionDescription: info.extensionDescription, url: info.getStarted!, @@ -77,12 +185,12 @@ class HelpModel { )); } - const documentation = remoteExplorerService.helpInformation.filter(info => info.documentation); + const documentation = viewModel.helpInformation.filter(info => info.documentation); if (documentation.length) { helpItems.push(new HelpItem( - ['documentation'], - nls.localize('remote.help.documentation', "$(book) Read Documentation"), + 'book', + nls.localize('remote.help.documentation', "Read Documentation"), documentation.map((info: HelpInformation) => ({ extensionDescription: info.extensionDescription, url: info.documentation!, @@ -95,12 +203,12 @@ class HelpModel { )); } - const feedback = remoteExplorerService.helpInformation.filter(info => info.feedback); + const feedback = viewModel.helpInformation.filter(info => info.feedback); if (feedback.length) { helpItems.push(new HelpItem( - ['feedback'], - nls.localize('remote.help.feedback', "$(twitter) Provide Feedback"), + 'twitter', + nls.localize('remote.help.feedback', "Provide Feedback"), feedback.map((info: HelpInformation) => ({ extensionDescription: info.extensionDescription, url: info.feedback!, @@ -113,12 +221,12 @@ class HelpModel { )); } - const issues = remoteExplorerService.helpInformation.filter(info => info.issues); + const issues = viewModel.helpInformation.filter(info => info.issues); if (issues.length) { helpItems.push(new HelpItem( - ['issues'], - nls.localize('remote.help.issues', "$(issues) Review Issues"), + 'issues', + nls.localize('remote.help.issues', "Review Issues"), issues.map((info: HelpInformation) => ({ extensionDescription: info.extensionDescription, url: info.issues!, @@ -133,9 +241,9 @@ class HelpModel { if (helpItems.length) { helpItems.push(new IssueReporterItem( - ['issueReporter'], - nls.localize('remote.help.report', "$(comment) Report Issue"), - remoteExplorerService.helpInformation.map(info => ({ + 'comment', + nls.localize('remote.help.report', "Report Issue"), + viewModel.helpInformation.map(info => ({ extensionDescription: info.extensionDescription, remoteAuthority: (typeof info.remoteName === 'string') ? [info.remoteName] : info.remoteName })), @@ -152,21 +260,19 @@ class HelpModel { } } -interface IHelpItem extends IQuickPickItem { - label: string; - handleClick(): Promise; -} - abstract class HelpItemBase implements IHelpItem { + public iconClasses: string[] = []; constructor( - public iconClasses: string[], + public key: string, public label: string, public values: { extensionDescription: IExtensionDescription, url?: string, remoteAuthority: string[] | undefined }[], private quickInputService: IQuickInputService, private environmentService: IWorkbenchEnvironmentService, private remoteExplorerService: IRemoteExplorerService ) { - iconClasses.push('remote-help-tree-node-item-icon'); + this.iconClasses.push(`codicon-${key}`); + this.iconClasses.push('remote-help-tree-node-item-icon'); + this.iconClasses.push('codicon'); } async handleClick() { @@ -208,7 +314,7 @@ abstract class HelpItemBase implements IHelpItem { class HelpItem extends HelpItemBase { constructor( - iconClasses: string[], + key: string, label: string, values: { extensionDescription: IExtensionDescription; url: string, remoteAuthority: string[] | undefined }[], quickInputService: IQuickInputService, @@ -216,7 +322,7 @@ class HelpItem extends HelpItemBase { private openerService: IOpenerService, remoteExplorerService: IRemoteExplorerService ) { - super(iconClasses, label, values, quickInputService, environmentService, remoteExplorerService); + super(key, label, values, quickInputService, environmentService, remoteExplorerService); } protected async takeAction(extensionDescription: IExtensionDescription, url: string): Promise { @@ -226,7 +332,7 @@ class HelpItem extends HelpItemBase { class IssueReporterItem extends HelpItemBase { constructor( - iconClasses: string[], + key: string, label: string, values: { extensionDescription: IExtensionDescription; remoteAuthority: string[] | undefined }[], quickInputService: IQuickInputService, @@ -234,7 +340,7 @@ class IssueReporterItem extends HelpItemBase { private commandService: ICommandService, remoteExplorerService: IRemoteExplorerService ) { - super(iconClasses, label, values, quickInputService, environmentService, remoteExplorerService); + super(key, label, values, quickInputService, environmentService, remoteExplorerService); } protected async takeAction(extensionDescription: IExtensionDescription): Promise { @@ -242,53 +348,77 @@ class IssueReporterItem extends HelpItemBase { } } -class HelpAction extends Action { - static readonly ID = 'remote.explorer.help'; - static readonly LABEL = nls.localize('remote.explorer.help', "Help, Documentation, and Feedback"); - private helpModel: HelpModel; +class HelpPanel extends ViewPane { + static readonly ID = '~remote.helpPanel'; + static readonly TITLE = nls.localize('remote.help', "Help and feedback"); + private tree!: WorkbenchAsyncDataTree; - constructor(id: string, - label: string, - @IOpenerService private readonly openerService: IOpenerService, - @IQuickInputService private readonly quickInputService: IQuickInputService, - @ICommandService private readonly commandService: ICommandService, - @IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService, - @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService - ) { - super(id, label, 'codicon codicon-question'); - this.helpModel = new HelpModel(openerService, quickInputService, commandService, remoteExplorerService, environmentService); - } - - async run(event?: any): Promise { - if (!this.helpModel.items) { - this.helpModel = new HelpModel(this.openerService, this.quickInputService, this.commandService, this.remoteExplorerService, this.environmentService); - } - if (this.helpModel.items) { - const selection = await this.quickInputService.pick(this.helpModel.items, { placeHolder: nls.localize('remote.explorer.helpPlaceholder', "Help and Feedback") }); - if (selection) { - return selection.handleClick(); - } - } - } -} - -export class RemoteViewlet extends Viewlet { constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, + protected viewModel: IViewModel, + options: IViewPaneOptions, + @IKeybindingService protected keybindingService: IKeybindingService, @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService + @IContextKeyService protected contextKeyService: IContextKeyService, + @IConfigurationService protected configurationService: IConfigurationService, + @IInstantiationService protected readonly instantiationService: IInstantiationService, + @IOpenerService protected openerService: IOpenerService, + @IQuickInputService protected quickInputService: IQuickInputService, + @ICommandService protected commandService: ICommandService, + @IRemoteExplorerService protected readonly remoteExplorerService: IRemoteExplorerService, + @IWorkbenchEnvironmentService protected readonly workbenchEnvironmentService: IWorkbenchEnvironmentService ) { - super(VIEWLET_ID, instantiationService.createInstance(RemoteViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); + super(options, keybindingService, contextMenuService, configurationService, contextKeyService); + } + + protected renderBody(container: HTMLElement): void { + dom.addClass(container, 'remote-help'); + const treeContainer = document.createElement('div'); + dom.addClass(treeContainer, 'remote-help-content'); + container.appendChild(treeContainer); + + this.tree = this.instantiationService.createInstance(WorkbenchAsyncDataTree, + 'RemoteHelp', + treeContainer, + new HelpTreeVirtualDelegate(), + [new HelpTreeRenderer()], + new HelpDataSource(), + { + keyboardSupport: true, + } + ); + + const model = new HelpModel(this.viewModel, this.openerService, this.quickInputService, this.commandService, this.remoteExplorerService, this.workbenchEnvironmentService); + + this.tree.setInput(model); + + const helpItemNavigator = this._register(new TreeResourceNavigator2(this.tree, { openOnFocus: false, openOnSelection: false })); + + this._register(Event.debounce(helpItemNavigator.onDidOpenResource, (last, event) => event, 75, true)(e => { + e.element.handleClick(); + })); + } + + protected layoutBody(height: number, width: number): void { + this.tree.layout(height, width); } } -export class RemoteViewPaneContainer extends FilterViewPaneContainer { +class HelpPanelDescriptor implements IViewDescriptor { + readonly id = HelpPanel.ID; + readonly name = HelpPanel.TITLE; + readonly ctorDescriptor: { ctor: any, arguments?: any[] }; + readonly canToggleVisibility = true; + readonly hideByDefault = false; + readonly workspace = true; + + constructor(viewModel: IViewModel) { + this.ctorDescriptor = { ctor: HelpPanel, arguments: [viewModel] }; + } +} + +export class RemoteViewPaneContainer extends FilterViewPaneContainer implements IViewModel { + private helpPanelDescriptor = new HelpPanelDescriptor(this); + helpInformation: HelpInformation[] = []; private actions: IAction[] | undefined; private tunnelPanelDescriptor: TunnelPanelDescriptor | undefined; @@ -307,6 +437,41 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer { @IContextKeyService private readonly contextKeyService: IContextKeyService ) { super(VIEWLET_ID, remoteExplorerService.onDidChangeTargetType, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService); + this.addConstantViewDescriptors([this.helpPanelDescriptor]); + remoteHelpExtPoint.setHandler((extensions) => { + let helpInformation: HelpInformation[] = []; + for (let extension of extensions) { + this._handleRemoteInfoExtensionPoint(extension, helpInformation); + } + + this.helpInformation = helpInformation; + + const viewsRegistry = Registry.as(Extensions.ViewsRegistry); + if (this.helpInformation.length) { + viewsRegistry.registerViews([this.helpPanelDescriptor], this.viewContainer); + } else { + viewsRegistry.deregisterViews([this.helpPanelDescriptor], this.viewContainer); + } + }); + } + + private _handleRemoteInfoExtensionPoint(extension: IExtensionPointUser, helpInformation: HelpInformation[]) { + if (!extension.description.enableProposedApi) { + return; + } + + if (!extension.value.documentation && !extension.value.feedback && !extension.value.getStarted && !extension.value.issues) { + return; + } + + helpInformation.push({ + extensionDescription: extension.description, + getStarted: extension.value.getStarted, + documentation: extension.value.documentation, + feedback: extension.value.feedback, + issues: extension.value.issues, + remoteName: extension.value.remoteName + }); } protected getFilterOn(viewDescriptor: IViewDescriptor): string | undefined { @@ -315,7 +480,7 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer { public getActionViewItem(action: Action): IActionViewItem | undefined { if (action.id === SwitchRemoteAction.ID) { - return this.instantiationService.createInstance(SwitchRemoteViewItem, action, SwitchRemoteViewItem.createOptionItems(Registry.as(Extensions.ViewsRegistry).getViews(VIEW_CONTAINER), this.contextKeyService)); + return this.instantiationService.createInstance(SwitchRemoteViewItem, action, SwitchRemoteViewItem.createOptionItems(Registry.as(Extensions.ViewsRegistry).getViews(this.viewContainer), this.contextKeyService)); } return super.getActionViewItem(action); @@ -324,8 +489,7 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer { public getActions(): IAction[] { if (!this.actions) { this.actions = [ - this.instantiationService.createInstance(SwitchRemoteAction, SwitchRemoteAction.ID, SwitchRemoteAction.LABEL), - this.instantiationService.createInstance(HelpAction, HelpAction.ID, HelpAction.LABEL) + this.instantiationService.createInstance(SwitchRemoteAction, SwitchRemoteAction.ID, SwitchRemoteAction.LABEL) ]; this.actions.forEach(a => { this._register(a); @@ -347,19 +511,41 @@ export class RemoteViewPaneContainer extends FilterViewPaneContainer { if (this.environmentService.configuration.remoteAuthority && !this.tunnelPanelDescriptor && viewEnabled) { this.tunnelPanelDescriptor = new TunnelPanelDescriptor(new TunnelViewModel(this.remoteExplorerService), this.environmentService); const viewsRegistry = Registry.as(Extensions.ViewsRegistry); - viewsRegistry.registerViews([this.tunnelPanelDescriptor!], VIEW_CONTAINER); + viewsRegistry.registerViews([this.tunnelPanelDescriptor!], this.viewContainer); } return panels; } } -Registry.as(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create( - RemoteViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-remote-explorer', - 4 -)); +Registry.as(Extensions.ViewContainersRegistry).registerViewContainer( + { + id: VIEWLET_ID, + name: nls.localize('remote.explorer', "Remote Explorer"), + ctorDescriptor: { ctor: RemoteViewPaneContainer }, + hideIfEmpty: true, + viewOrderDelegate: { + getOrder: (group?: string) => { + if (!group) { + return undefined; // {{SQL CARBON EDIT}} strict-null-check + } + + let matches = /^targets@(\d+)$/.exec(group); + if (matches) { + return -1000; + } + + matches = /^details(@(\d+))?$/.exec(group); + + if (matches) { + return -500; + } + + return undefined; // {{SQL CARBON EDIT}} strict-null-check; + } + }, + icon: 'codicon-remote-explorer', + order: 4 + }, ViewContainerLocation.Sidebar); class OpenRemoteViewletAction extends ShowViewletAction { diff --git a/src/vs/workbench/contrib/remote/browser/remoteViewlet.css b/src/vs/workbench/contrib/remote/browser/remoteViewlet.css index d287b989be..b4eef10c91 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteViewlet.css +++ b/src/vs/workbench/contrib/remote/browser/remoteViewlet.css @@ -3,14 +3,32 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -.remote-help-tree-node-item-icon { +.remote-help-content .monaco-list .monaco-list-row .remote-help-tree-node-item { + display: flex; + height: 22px; + line-height: 22px; + flex: 1; + text-overflow: ellipsis; + overflow: hidden; + flex-wrap: nowrap; +} + +.remote-help-content .monaco-list .monaco-list-row .remote-help-tree-node-item>.remote-help-tree-node-item-icon { background-size: 16px; background-position: left center; background-repeat: no-repeat; + padding-right: 6px; + padding-top: 3px; + width: 16px; + height: 22px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } +.remote-help-content .monaco-list .monaco-list-row .monaco-tl-twistie { + width: 0px !important; +} + .remote-help-tree-node-item-icon .monaco-icon-label-description-container { padding-left: 22px; } diff --git a/src/vs/workbench/contrib/remote/common/remote.contribution.ts b/src/vs/workbench/contrib/remote/common/remote.contribution.ts index 7553d0912e..86d8721e33 100644 --- a/src/vs/workbench/contrib/remote/common/remote.contribution.ts +++ b/src/vs/workbench/contrib/remote/common/remote.contribution.ts @@ -16,35 +16,8 @@ import { IOutputChannelRegistry, Extensions as OutputExt, } from 'vs/workbench/s import { localize } from 'vs/nls'; import { joinPath } from 'vs/base/common/resources'; import { Disposable } from 'vs/base/common/lifecycle'; -import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation } from 'vs/workbench/common/views'; export const VIEWLET_ID = 'workbench.view.remote'; -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer( - { - id: VIEWLET_ID, - name: localize('remote.explorer', "Remote Explorer"), - hideIfEmpty: true, - viewOrderDelegate: { - getOrder: (group?: string) => { - if (!group) { - return undefined; // {{SQL CARBON EDIT}} strict-null-checks - } - - let matches = /^targets@(\d+)$/.exec(group); - if (matches) { - return -1000; - } - - matches = /^details(@(\d+))?$/.exec(group); - - if (matches) { - return -500; - } - - return undefined; // {{SQL CARBON EDIT}} strict-null-checks - } - } - }, ViewContainerLocation.Sidebar); export class LabelContribution implements IWorkbenchContribution { constructor( diff --git a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts index b2f4478c9b..bf2440ba50 100644 --- a/src/vs/workbench/contrib/scm/browser/scm.contribution.ts +++ b/src/vs/workbench/contrib/scm/browser/scm.contribution.ts @@ -7,14 +7,13 @@ import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { DirtyDiffWorkbenchController } from './dirtydiffDecorator'; -import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction } from 'vs/workbench/browser/viewlet'; -import { VIEWLET_ID, VIEW_CONTAINER, ISCMRepository, ISCMService } from 'vs/workbench/contrib/scm/common/scm'; +import { ShowViewletAction } from 'vs/workbench/browser/viewlet'; +import { VIEWLET_ID, ISCMRepository, ISCMService } from 'vs/workbench/contrib/scm/common/scm'; import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { SCMStatusController } from './activity'; -import { SCMViewlet } from 'vs/workbench/contrib/scm/browser/scmViewlet'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -24,6 +23,8 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { SCMService } from 'vs/workbench/contrib/scm/common/scmService'; +import { IViewContainersRegistry, ViewContainerLocation, Extensions as ViewContainerExtensions } from 'vs/workbench/common/views'; +import { SCMViewPaneContainer } from 'vs/workbench/contrib/scm/browser/scmViewlet'; class OpenSCMViewletAction extends ShowViewletAction { @@ -38,13 +39,13 @@ class OpenSCMViewletAction extends ShowViewletAction { Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(DirtyDiffWorkbenchController, LifecyclePhase.Restored); -Registry.as(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create( - SCMViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-source-control', - 12 // {{SQL CARBON EDIT}} -)); +Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: localize('source control', "Source Control"), + ctorDescriptor: { ctor: SCMViewPaneContainer }, + icon: 'codicon-source-control', + order: 12 // {{SQL CARBON EDIT}} +}, ViewContainerLocation.Sidebar); Registry.as(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(SCMStatusController, LifecyclePhase.Restored); diff --git a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts index 14e8145edc..252515dc71 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { append, $, toggleClass, addClasses } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { VIEWLET_ID, ISCMService, ISCMRepository, VIEW_CONTAINER } from 'vs/workbench/contrib/scm/common/scm'; +import { VIEWLET_ID, ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -31,7 +31,6 @@ import { nextTick } from 'vs/base/common/process'; import { RepositoryPane, RepositoryViewDescriptor } from 'vs/workbench/contrib/scm/browser/repositoryPane'; import { MainPaneDescriptor, MainPane } from 'vs/workbench/contrib/scm/browser/mainPane'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -import { Viewlet } from 'vs/workbench/browser/viewlet'; export interface ISpliceEvent { index: number; @@ -51,22 +50,6 @@ export interface IViewModel { readonly onDidChangeVisibility: Event; } -export class SCMViewlet extends Viewlet { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService - ) { - super(VIEWLET_ID, instantiationService.createInstance(SCMViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } -} - export class SCMViewPaneContainer extends ViewPaneContainer implements IViewModel { private static readonly STATE_KEY = 'workbench.scm.views.state'; @@ -124,7 +107,7 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode this.message = $('.empty-message', { tabIndex: 0 }, localize('no open repo', "No source control providers registered.")); const viewsRegistry = Registry.as(Extensions.ViewsRegistry); - viewsRegistry.registerViews([new MainPaneDescriptor(this)], VIEW_CONTAINER); + viewsRegistry.registerViews([new MainPaneDescriptor(this)], this.viewContainer); this._register(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('scm.alwaysShowProviders') && configurationService.getValue('scm.alwaysShowProviders')) { @@ -153,7 +136,7 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode this._repositories.push(repository); const viewDescriptor = new RepositoryViewDescriptor(repository, false); - Registry.as(Extensions.ViewsRegistry).registerViews([viewDescriptor], VIEW_CONTAINER); + Registry.as(Extensions.ViewsRegistry).registerViews([viewDescriptor], this.viewContainer); this.viewDescriptors.push(viewDescriptor); this._onDidSplice.fire({ index, deleteCount: 0, elements: [repository] }); @@ -169,7 +152,7 @@ export class SCMViewPaneContainer extends ViewPaneContainer implements IViewMode return; } - Registry.as(Extensions.ViewsRegistry).deregisterViews([this.viewDescriptors[index]], VIEW_CONTAINER); + Registry.as(Extensions.ViewsRegistry).deregisterViews([this.viewDescriptors[index]], this.viewContainer); this._repositories.splice(index, 1); this.viewDescriptors.splice(index, 1); diff --git a/src/vs/workbench/contrib/scm/common/scm.ts b/src/vs/workbench/contrib/scm/common/scm.ts index de9e2a2add..704bf485a2 100644 --- a/src/vs/workbench/contrib/scm/common/scm.ts +++ b/src/vs/workbench/contrib/scm/common/scm.ts @@ -9,12 +9,8 @@ import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Command } from 'vs/editor/common/modes'; import { ISequence } from 'vs/base/common/sequence'; -import { Extensions as ViewContainerExtensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { localize } from 'vs/nls'; export const VIEWLET_ID = 'workbench.view.scm'; -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('source control', "Source Control"), }, ViewContainerLocation.Sidebar); export interface IBaselineResourceProvider { getBaselineResource(resource: URI): Promise; diff --git a/src/vs/workbench/contrib/search/browser/search.contribution.ts b/src/vs/workbench/contrib/search/browser/search.contribution.ts index 0e795f76f8..1233558354 100644 --- a/src/vs/workbench/contrib/search/browser/search.contribution.ts +++ b/src/vs/workbench/contrib/search/browser/search.contribution.ts @@ -31,10 +31,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as PanelExtensions, PanelDescriptor, PanelRegistry } from 'vs/workbench/browser/panel'; import { defaultQuickOpenContextKey } from 'vs/workbench/browser/parts/quickopen/quickopen'; import { Extensions as QuickOpenExtensions, IQuickOpenRegistry, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; -import { Extensions as ViewletExtensions, ViewletDescriptor, ViewletRegistry } from 'vs/workbench/browser/viewlet'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { Extensions as ViewExtensions, IViewsRegistry } from 'vs/workbench/common/views'; +import { Extensions as ViewExtensions, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; import { ExplorerFolderContext, ExplorerRootContext, FilesExplorerFocusCondition, IExplorerService, VIEWLET_ID as VIEWLET_ID_FILES } from 'vs/workbench/contrib/files/common/files'; import { OpenAnythingHandler } from 'vs/workbench/contrib/search/browser/openAnythingHandler'; @@ -43,7 +42,6 @@ import { registerContributions as replaceContributions } from 'vs/workbench/cont import { clearHistoryCommand, ClearSearchResultsAction, CloseReplaceAction, CollapseDeepestExpandedLevelAction, copyAllCommand, copyMatchCommand, copyPathCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, RefreshAction, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, toggleRegexCommand, toggleWholeWordCommand, FindInFilesCommand, ToggleSearchOnTypeAction, OpenResultsInEditorAction, RerunEditorSearchAction, RerunEditorSearchWithContextAction, ExpandAllAction } from 'vs/workbench/contrib/search/browser/searchActions'; import { SearchPanel } from 'vs/workbench/contrib/search/browser/searchPanel'; import { SearchView, SearchViewPosition } from 'vs/workbench/contrib/search/browser/searchView'; -import { SearchViewlet } from 'vs/workbench/contrib/search/browser/searchViewlet'; import { registerContributions as searchWidgetContributions } from 'vs/workbench/contrib/search/browser/searchWidget'; import * as Constants from 'vs/workbench/contrib/search/common/constants'; import { getWorkspaceSymbols } from 'vs/workbench/contrib/search/common/search'; @@ -51,12 +49,13 @@ import { ISearchHistoryService, SearchHistoryService } from 'vs/workbench/contri import { FileMatchOrMatch, ISearchWorkbenchService, RenderableMatch, SearchWorkbenchService, FileMatch, Match, FolderMatch } from 'vs/workbench/contrib/search/common/searchModel'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { ISearchConfiguration, ISearchConfigurationProperties, PANEL_ID, VIEWLET_ID, VIEW_ID, VIEW_CONTAINER, SearchSortOrder } from 'vs/workbench/services/search/common/search'; +import { ISearchConfiguration, ISearchConfigurationProperties, PANEL_ID, VIEWLET_ID, VIEW_ID, SearchSortOrder } from 'vs/workbench/services/search/common/search'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { assertType } from 'vs/base/common/types'; +import { SearchViewPaneContainer } from 'vs/workbench/contrib/search/browser/searchViewlet'; registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true); registerSingleton(ISearchHistoryService, SearchHistoryService, true); @@ -505,13 +504,14 @@ class ShowAllSymbolsAction extends Action { } } -Registry.as(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create( - SearchViewlet, - VIEWLET_ID, - VIEW_CONTAINER.name, - 'codicon-search', - 1 -)); +const viewContainer = Registry.as(ViewExtensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: nls.localize('name', "Search"), + ctorDescriptor: { ctor: SearchViewPaneContainer }, + hideIfEmpty: true, + icon: 'codicon-search', + order: 1 +}, ViewContainerLocation.Sidebar); Registry.as(PanelExtensions.Panels).registerPanel(PanelDescriptor.create( SearchPanel, @@ -532,7 +532,7 @@ class RegisterSearchViewContribution implements IWorkbenchContribution { const updateSearchViewLocation = (open: boolean) => { const config = configurationService.getValue(); if (config.search.location === 'panel') { - viewsRegistry.deregisterViews(viewsRegistry.getViews(VIEW_CONTAINER), VIEW_CONTAINER); + viewsRegistry.deregisterViews(viewsRegistry.getViews(viewContainer), viewContainer); Registry.as(PanelExtensions.Panels).registerPanel(PanelDescriptor.create( SearchPanel, PANEL_ID, @@ -545,7 +545,7 @@ class RegisterSearchViewContribution implements IWorkbenchContribution { } } else { Registry.as(PanelExtensions.Panels).deregisterPanel(PANEL_ID); - viewsRegistry.registerViews([{ id: VIEW_ID, name: nls.localize('search', "Search"), ctorDescriptor: { ctor: SearchView, arguments: [SearchViewPosition.SideBar] }, canToggleVisibility: false }], VIEW_CONTAINER); + viewsRegistry.registerViews([{ id: VIEW_ID, name: nls.localize('search', "Search"), ctorDescriptor: { ctor: SearchView, arguments: [SearchViewPosition.SideBar] }, canToggleVisibility: false }], viewContainer); if (open) { viewletService.openViewlet(VIEWLET_ID); } diff --git a/src/vs/workbench/contrib/search/browser/searchViewlet.ts b/src/vs/workbench/contrib/search/browser/searchViewlet.ts index 50d3ab2617..274d173224 100644 --- a/src/vs/workbench/contrib/search/browser/searchViewlet.ts +++ b/src/vs/workbench/contrib/search/browser/searchViewlet.ts @@ -14,26 +14,9 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { VIEWLET_ID, VIEW_ID } from 'vs/workbench/services/search/common/search'; import { SearchView } from 'vs/workbench/contrib/search/browser/searchView'; -import { Viewlet } from 'vs/workbench/browser/viewlet'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; -export class SearchViewlet extends Viewlet { - constructor( - @ITelemetryService telemetryService: ITelemetryService, - @IStorageService protected storageService: IStorageService, - @IInstantiationService protected instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService protected contextMenuService: IContextMenuService, - @IExtensionService protected extensionService: IExtensionService, - @IWorkspaceContextService protected contextService: IWorkspaceContextService, - @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, - @IConfigurationService protected configurationService: IConfigurationService - ) { - super(VIEWLET_ID, instantiationService.createInstance(SearchViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); - } -} - export class SearchViewPaneContainer extends ViewPaneContainer { constructor( diff --git a/src/vs/workbench/contrib/webview/common/resourceLoader.ts b/src/vs/workbench/contrib/webview/common/resourceLoader.ts index a7a7a28ef2..996be332e3 100644 --- a/src/vs/workbench/contrib/webview/common/resourceLoader.ts +++ b/src/vs/workbench/contrib/webview/common/resourceLoader.ts @@ -104,5 +104,5 @@ function containsResource(root: URI, resource: URI): boolean { resourceFsPath = resourceFsPath.toLowerCase(); } - return startsWith(resource.fsPath, rootPath); + return startsWith(resourceFsPath, rootPath); } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 90abb4533e..625e4d9e15 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IResourceInput, ITextEditorOptions, IEditorOptions, EditorActivation } from 'vs/platform/editor/common/editor'; -import { IEditorInput, IEditor, GroupIdentifier, IFileEditorInput, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInputFactoryRegistry, Extensions as EditorExtensions, IFileInputFactory, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditor, ITextDiffEditor, ITextSideBySideEditor, toResource, SideBySideEditor, IRevertOptions, SaveReason } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditor, GroupIdentifier, IFileEditorInput, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInputFactoryRegistry, Extensions as EditorExtensions, IFileInputFactory, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditor, ITextDiffEditor, ITextSideBySideEditor, toResource, SideBySideEditor, IRevertOptions, SaveReason, EditorsOrder } from 'vs/workbench/common/editor'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { Registry } from 'vs/platform/registry/common/platform'; import { ResourceMap } from 'vs/base/common/map'; @@ -17,7 +17,7 @@ import { URI } from 'vs/base/common/uri'; import { basename, isEqual } from 'vs/base/common/resources'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { localize } from 'vs/nls'; -import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection, EditorsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IResourceEditor, SIDE_GROUP, IResourceEditorReplacement, IOpenEditorOverrideHandler, IVisibleEditor, IEditorService, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { Disposable, IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; @@ -186,19 +186,28 @@ export class EditorService extends Disposable implements EditorServiceImpl { return undefined; } + get count(): number { + return this.editorsObserver.count; + } + get editors(): IEditorInput[] { - const editors: IEditorInput[] = []; - this.editorGroupService.groups.forEach(group => { - editors.push(...group.editors); + return this.getEditors(EditorsOrder.SEQUENTIAL).map(({ editor }) => editor); + } + + getEditors(order: EditorsOrder): ReadonlyArray { + if (order === EditorsOrder.MOST_RECENTLY_ACTIVE) { + return this.editorsObserver.editors; + } + + const editors: IEditorIdentifier[] = []; + + this.editorGroupService.getGroups(GroupsOrder.GRID_APPEARANCE).forEach(group => { + editors.push(...group.getEditors(EditorsOrder.SEQUENTIAL).map(editor => ({ editor, groupId: group.id }))); }); return editors; } - get mostRecentlyActiveEditors(): IEditorIdentifier[] { - return this.editorsObserver.editors; - } - get activeEditor(): IEditorInput | undefined { const activeGroup = this.editorGroupService.activeGroup; @@ -834,6 +843,9 @@ export class DelegatingEditorService implements IEditorService { get visibleControls(): ReadonlyArray { return this.editorService.visibleControls; } get visibleTextEditorWidgets(): ReadonlyArray { return this.editorService.visibleTextEditorWidgets; } get editors(): ReadonlyArray { return this.editorService.editors; } + get count(): number { return this.editorService.count; } + + getEditors(order: EditorsOrder): ReadonlyArray { return this.editorService.getEditors(order); } openEditors(editors: IEditorInputWithOptions[], group?: OpenInEditorGroup): Promise; openEditors(editors: IResourceEditor[], group?: OpenInEditorGroup): Promise; diff --git a/src/vs/workbench/services/editor/common/editorGroupsService.ts b/src/vs/workbench/services/editor/common/editorGroupsService.ts index 48d937b026..dd3145ca17 100644 --- a/src/vs/workbench/services/editor/common/editorGroupsService.ts +++ b/src/vs/workbench/services/editor/common/editorGroupsService.ts @@ -5,7 +5,7 @@ import { Event } from 'vs/base/common/event'; import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, CloseDirection, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, CloseDirection, IEditorPartOptions, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorOptions, ITextEditorOptions, IResourceInput } from 'vs/platform/editor/common/editor'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IVisibleEditor } from 'vs/workbench/services/editor/common/editorService'; @@ -134,19 +134,6 @@ export const enum GroupsOrder { GRID_APPEARANCE } -export const enum EditorsOrder { - - /** - * Editors sorted by most recent activity (most recent active first) - */ - MOST_RECENTLY_ACTIVE, - - /** - * Editors sorted by sequential order - */ - SEQUENTIAL -} - export interface IEditorGroupsService { _serviceBrand: undefined; @@ -224,11 +211,11 @@ export interface IEditorGroupsService { readonly willRestoreEditors: boolean; /** - * Get all groups that are currently visible in the editor area optionally - * sorted by being most recent active or grid order. Will sort by creation - * time by default (oldest group first). + * Get all groups that are currently visible in the editor area. + * + * @param order the order of the editors to use */ - getGroups(order?: GroupsOrder): ReadonlyArray; + getGroups(order: GroupsOrder): ReadonlyArray; /** * Allows to convert a group identifier to a group. @@ -433,16 +420,16 @@ export interface IEditorGroup { readonly count: number; /** - * All opened editors in the group. There can only be one editor active. + * All opened editors in the group in sequential order of their appearance. */ readonly editors: ReadonlyArray; /** - * Get all editors that are currently opened in the group optionally - * sorted by being most recent active. Will sort by sequential appearance - * by default (from left to right). + * Get all editors that are currently opened in the group. + * + * @param order the order of the editors to use */ - getEditors(order?: EditorsOrder): ReadonlyArray; + getEditors(order: EditorsOrder): ReadonlyArray; /** * Returns the editor at a specific index of the group. diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index ebe14b4c29..bb458b1522 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -5,7 +5,7 @@ import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IResourceInput, IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; -import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, ITextEditor, ITextDiffEditor, ITextSideBySideEditor, IEditorIdentifier, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, ITextEditor, ITextDiffEditor, ITextSideBySideEditor, IEditorIdentifier, ISaveOptions, IRevertOptions, EditorsOrder } from 'vs/workbench/common/editor'; import { Event } from 'vs/base/common/event'; import { IEditor as ICodeEditor, IDiffEditor } from 'vs/editor/common/editorCommon'; import { IEditorGroup, IEditorReplacement } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -123,11 +123,26 @@ export interface IEditorService { readonly visibleTextEditorWidgets: ReadonlyArray; /** - * All editors that are opened across all editor groups. This includes active as well as inactive - * editors in each editor group. + * All editors that are opened across all editor groups in sequential order + * of appearance. + * + * This includes active as well as inactive editors in each editor group. */ readonly editors: ReadonlyArray; + /** + * The total number of editors that are opened either inactive or active. + */ + readonly count: number; + + /** + * All editors that are opened across all editor groups with their group + * identifier. + * + * @param order the order of the editors to use + */ + getEditors(order: EditorsOrder): ReadonlyArray; + /** * Open an editor in an editor group. * diff --git a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts index 293dd192fc..9a25cba411 100644 --- a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts @@ -6,9 +6,9 @@ import * as assert from 'assert'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; import { workbenchInstantiationService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; -import { GroupDirection, GroupsOrder, MergeGroupMode, GroupOrientation, GroupChangeKind, EditorsOrder, GroupLocation } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { GroupDirection, GroupsOrder, MergeGroupMode, GroupOrientation, GroupChangeKind, GroupLocation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EditorInput, IFileEditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorExtensions, EditorOptions, CloseDirection, IEditorPartOptions } from 'vs/workbench/common/editor'; +import { EditorInput, IFileEditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorExtensions, EditorOptions, CloseDirection, IEditorPartOptions, EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { URI } from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -468,7 +468,7 @@ suite.skip('EditorGroupsService', () => { // {{SQL CARBON EDIT}} skip suite assert.equal(group.activeEditor, input); assert.ok(group.activeControl instanceof TestEditorControl); - assert.equal(group.editors.length, 2); + assert.equal(group.count, 2); const mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input); diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 550de75d0a..058afe021d 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { EditorActivation, IEditorModel } from 'vs/platform/editor/common/editor'; import { URI } from 'vs/base/common/uri'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; -import { EditorInput, EditorOptions, IFileEditorInput, GroupIdentifier, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, IFileEditorInput, GroupIdentifier, ISaveOptions, IRevertOptions, EditorsOrder } from 'vs/workbench/common/editor'; import { workbenchInstantiationService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; @@ -156,6 +156,9 @@ suite.skip('EditorService', () => { // {{SQL CARBON EDIT}} skip suite assert.ok(editor instanceof TestEditorControl); assert.equal(editor, service.activeControl); + assert.equal(1, service.count); + assert.equal(input, service.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].editor); + assert.equal(input, service.getEditors(EditorsOrder.SEQUENTIAL)[0].editor); assert.equal(input, service.activeEditor); assert.equal(service.visibleControls.length, 1); assert.equal(service.visibleControls[0], editor); @@ -169,6 +172,9 @@ suite.skip('EditorService', () => { // {{SQL CARBON EDIT}} skip suite // Close input await editor!.group!.closeEditor(input); + assert.equal(0, service.count); + assert.equal(0, service.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length); + assert.equal(0, service.getEditors(EditorsOrder.SEQUENTIAL).length); assert.equal(didCloseEditorListenerCounter, 1); assert.equal(activeEditorChangeEventCounter, 2); assert.equal(visibleEditorChangeEventCounter, 2); @@ -178,6 +184,11 @@ suite.skip('EditorService', () => { // {{SQL CARBON EDIT}} skip suite await service.openEditor(input, { pinned: true }); editor = await service.openEditor(otherInput, { pinned: true }); + assert.equal(2, service.count); + assert.equal(otherInput, service.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].editor); + assert.equal(input, service.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].editor); + assert.equal(input, service.getEditors(EditorsOrder.SEQUENTIAL)[0].editor); + assert.equal(otherInput, service.getEditors(EditorsOrder.SEQUENTIAL)[1].editor); assert.equal(service.visibleControls.length, 1); assert.equal(service.isOpen(input), true); assert.equal(service.isOpen(otherInput), true); diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 5b50e769cf..0e2ff7ce8f 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -7,7 +7,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IEditor } from 'vs/editor/common/editorCommon'; import { ITextEditorOptions, IResourceInput, ITextEditorSelection } from 'vs/platform/editor/common/editor'; -import { IEditorInput, IEditor as IBaseEditor, Extensions as EditorExtensions, EditorInput, IEditorCloseEvent, IEditorInputFactoryRegistry, toResource, IEditorIdentifier, GroupIdentifier } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditor as IBaseEditor, Extensions as EditorExtensions, EditorInput, IEditorCloseEvent, IEditorInputFactoryRegistry, toResource, IEditorIdentifier, GroupIdentifier, EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { FileChangesEvent, IFileService, FileChangeType, FILES_EXCLUDE_CONFIG } from 'vs/platform/files/common/files'; @@ -18,7 +18,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { Registry } from 'vs/platform/registry/common/platform'; import { Event } from 'vs/base/common/event'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; -import { IEditorGroupsService, EditorsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { getExcludes, ISearchConfiguration } from 'vs/workbench/services/search/common/search'; import { IExpression } from 'vs/base/common/glob'; @@ -1023,7 +1023,7 @@ export class HistoryService extends Disposable implements IHistoryService { // Across groups if (!group) { - editors = this.recentlyUsedEditorsStack || this.editorService.mostRecentlyActiveEditors; + editors = this.recentlyUsedEditorsStack || this.editorService.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); index = this.recentlyUsedEditorsStackIndex; } @@ -1068,10 +1068,6 @@ export class HistoryService extends Disposable implements IHistoryService { } } - getMostRecentlyUsedOpenEditors(): ReadonlyArray { - return this.editorService.mostRecentlyActiveEditors; - } - //#endregion } diff --git a/src/vs/workbench/services/history/common/history.ts b/src/vs/workbench/services/history/common/history.ts index d2c1534d35..d05ed54d1a 100644 --- a/src/vs/workbench/services/history/common/history.ts +++ b/src/vs/workbench/services/history/common/history.ts @@ -5,7 +5,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IResourceInput } from 'vs/platform/editor/common/editor'; -import { IEditorInput, IEditorIdentifier, GroupIdentifier } from 'vs/workbench/common/editor'; +import { IEditorInput, GroupIdentifier } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; export const IHistoryService = createDecorator('historyService'); @@ -87,9 +87,4 @@ export interface IHistoryService { * @param group optional indicator to scope to a specific group. */ openPreviouslyUsedEditor(group?: GroupIdentifier): void; - - /** - * Get a list of most recently used editors that are open. - */ - getMostRecentlyUsedOpenEditors(): ReadonlyArray; } diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts index 3177748659..a0c1e0f508 100644 --- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts +++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts @@ -3,13 +3,10 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel'; import { Disposable } from 'vs/base/common/lifecycle'; import { IEditableData } from 'vs/workbench/common/views'; @@ -208,7 +205,6 @@ export interface IRemoteExplorerService { _serviceBrand: undefined; onDidChangeTargetType: Event; targetType: string; - readonly helpInformation: HelpInformation[]; readonly tunnelModel: TunnelModel; onDidChangeEditable: Event; setEditable(tunnelItem: ITunnelItem | undefined, data: IEditableData | null): void; @@ -220,47 +216,11 @@ export interface IRemoteExplorerService { refresh(): Promise; } -export interface HelpInformation { - extensionDescription: IExtensionDescription; - getStarted?: string; - documentation?: string; - feedback?: string; - issues?: string; - remoteName?: string[] | string; -} - -const remoteHelpExtPoint = ExtensionsRegistry.registerExtensionPoint({ - extensionPoint: 'remoteHelp', - jsonSchema: { - description: nls.localize('RemoteHelpInformationExtPoint', 'Contributes help information for Remote'), - type: 'object', - properties: { - 'getStarted': { - description: nls.localize('RemoteHelpInformationExtPoint.getStarted', "The url to your project's Getting Started page"), - type: 'string' - }, - 'documentation': { - description: nls.localize('RemoteHelpInformationExtPoint.documentation', "The url to your project's documentation page"), - type: 'string' - }, - 'feedback': { - description: nls.localize('RemoteHelpInformationExtPoint.feedback', "The url to your project's feedback reporter"), - type: 'string' - }, - 'issues': { - description: nls.localize('RemoteHelpInformationExtPoint.issues', "The url to your project's issues list"), - type: 'string' - } - } - } -}); - class RemoteExplorerService implements IRemoteExplorerService { public _serviceBrand: undefined; private _targetType: string = ''; private readonly _onDidChangeTargetType: Emitter = new Emitter(); public readonly onDidChangeTargetType: Event = this._onDidChangeTargetType.event; - private _helpInformation: HelpInformation[] = []; private _tunnelModel: TunnelModel; private _editable: { tunnelItem: ITunnelItem | undefined, data: IEditableData } | undefined; private readonly _onDidChangeEditable: Emitter = new Emitter(); @@ -272,14 +232,6 @@ class RemoteExplorerService implements IRemoteExplorerService { @IConfigurationService configurationService: IConfigurationService ) { this._tunnelModel = new TunnelModel(tunnelService, storageService, configurationService); - remoteHelpExtPoint.setHandler((extensions) => { - let helpInformation: HelpInformation[] = []; - for (let extension of extensions) { - this._handleRemoteInfoExtensionPoint(extension, helpInformation); - } - - this._helpInformation = helpInformation; - }); } set targetType(name: string) { @@ -294,29 +246,6 @@ class RemoteExplorerService implements IRemoteExplorerService { return this._targetType; } - private _handleRemoteInfoExtensionPoint(extension: IExtensionPointUser, helpInformation: HelpInformation[]) { - if (!extension.description.enableProposedApi) { - return; - } - - if (!extension.value.documentation && !extension.value.feedback && !extension.value.getStarted && !extension.value.issues) { - return; - } - - helpInformation.push({ - extensionDescription: extension.description, - getStarted: extension.value.getStarted, - documentation: extension.value.documentation, - feedback: extension.value.feedback, - issues: extension.value.issues, - remoteName: extension.value.remoteName - }); - } - - get helpInformation(): HelpInformation[] { - return this._helpInformation; - } - get tunnelModel(): TunnelModel { return this._tunnelModel; } diff --git a/src/vs/workbench/services/search/common/search.ts b/src/vs/workbench/services/search/common/search.ts index 0997bbd794..35b75a65db 100644 --- a/src/vs/workbench/services/search/common/search.ts +++ b/src/vs/workbench/services/search/common/search.ts @@ -16,17 +16,10 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { Event } from 'vs/base/common/event'; import { relative } from 'vs/base/common/path'; -import { Extensions as ViewContainerExtensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation } from 'vs/workbench/common/views'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { localize } from 'vs/nls'; export const VIEWLET_ID = 'workbench.view.search'; export const PANEL_ID = 'workbench.view.search'; export const VIEW_ID = 'workbench.view.search'; -/** - * Search viewlet container. - */ -export const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: VIEWLET_ID, name: localize('name', "Search"), hideIfEmpty: true }, ViewContainerLocation.Sidebar); export const ISearchService = createDecorator('searchService'); diff --git a/src/vs/workbench/test/browser/parts/views/views.test.ts b/src/vs/workbench/test/browser/parts/views/views.test.ts index 6036c87139..8d5cbc0a64 100644 --- a/src/vs/workbench/test/browser/parts/views/views.test.ts +++ b/src/vs/workbench/test/browser/parts/views/views.test.ts @@ -15,7 +15,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; import sinon = require('sinon'); -const container = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: 'test', name: 'test' }, ViewContainerLocation.Sidebar); +const container = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: 'test', name: 'test', ctorDescriptor: { ctor: {} } }, ViewContainerLocation.Sidebar); const ViewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); class ViewDescriptorSequence { diff --git a/src/vs/workbench/test/common/editor/editorGroups.test.ts b/src/vs/workbench/test/common/editor/editorGroups.test.ts index bc4ee57ec5..357573ff40 100644 --- a/src/vs/workbench/test/common/editor/editorGroups.test.ts +++ b/src/vs/workbench/test/common/editor/editorGroups.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { EditorGroup, ISerializedEditorGroup, EditorCloseEvent } from 'vs/workbench/common/editor/editorGroup'; -import { Extensions as EditorExtensions, IEditorInputFactoryRegistry, EditorInput, IFileEditorInput, IEditorInputFactory, CloseDirection } from 'vs/workbench/common/editor'; +import { Extensions as EditorExtensions, IEditorInputFactoryRegistry, EditorInput, IFileEditorInput, IEditorInputFactory, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { TestLifecycleService, TestContextService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; @@ -307,7 +307,7 @@ suite('Workbench editor groups', () => { const events = groupListener(group); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); // Active && Pinned const input1 = input(); @@ -315,7 +315,7 @@ suite('Workbench editor groups', () => { assert.equal(openedEditor, input1); assert.equal(group.count, 1); - assert.equal(group.getEditors(true).length, 1); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 1); assert.equal(group.activeEditor, input1); assert.equal(group.isActive(input1), true); assert.equal(group.isPreview(input1), false); @@ -328,7 +328,7 @@ suite('Workbench editor groups', () => { let editor = group.closeEditor(input1); assert.equal(editor, input1); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[0].editor, input1); assert.equal(events.closed[0].index, 0); @@ -339,7 +339,7 @@ suite('Workbench editor groups', () => { group.openEditor(input2, { active: true, pinned: false }); assert.equal(group.count, 1); - assert.equal(group.getEditors(true).length, 1); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 1); assert.equal(group.activeEditor, input2); assert.equal(group.isActive(input2), true); assert.equal(group.isPreview(input2), true); @@ -351,7 +351,7 @@ suite('Workbench editor groups', () => { group.closeEditor(input2); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[1].editor, input2); assert.equal(events.closed[1].index, 0); @@ -360,7 +360,7 @@ suite('Workbench editor groups', () => { editor = group.closeEditor(input2); assert.ok(!editor); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[1].editor, input2); @@ -369,7 +369,7 @@ suite('Workbench editor groups', () => { group.openEditor(input3, { active: false, pinned: true }); assert.equal(group.count, 1); - assert.equal(group.getEditors(true).length, 1); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 1); assert.equal(group.activeEditor, input3); assert.equal(group.isActive(input3), true); assert.equal(group.isPreview(input3), false); @@ -381,7 +381,7 @@ suite('Workbench editor groups', () => { group.closeEditor(input3); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[2].editor, input3); @@ -390,7 +390,7 @@ suite('Workbench editor groups', () => { group.closeEditor(input3); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[2].editor, input3); @@ -399,7 +399,7 @@ suite('Workbench editor groups', () => { group.openEditor(input4); assert.equal(group.count, 1); - assert.equal(group.getEditors(true).length, 1); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 1); assert.equal(group.activeEditor, input4); assert.equal(group.isActive(input4), true); assert.equal(group.isPreview(input4), true); @@ -411,7 +411,7 @@ suite('Workbench editor groups', () => { group.closeEditor(input4); assert.equal(group.count, 0); - assert.equal(group.getEditors(true).length, 0); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 0); assert.equal(group.activeEditor, undefined); assert.equal(events.closed[3].editor, input4); }); @@ -436,7 +436,7 @@ suite('Workbench editor groups', () => { group.openEditor(input3, { pinned: true, active: true }); assert.equal(group.count, 3); - assert.equal(group.getEditors(true).length, 3); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 3); assert.equal(group.activeEditor, input3); assert.equal(group.isActive(input1), false); assert.equal(group.isPinned(input1), true); @@ -456,7 +456,7 @@ suite('Workbench editor groups', () => { assert.equal(events.activated[1], input2); assert.equal(events.activated[2], input3); - const mru = group.getEditors(true); + const mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input3); assert.equal(mru[1], input2); assert.equal(mru[2], input1); @@ -496,12 +496,12 @@ suite('Workbench editor groups', () => { group.openEditor(input2, { pinned: true, active: true }); group.openEditor(input3, { pinned: true, active: true }); - assert.equal(input3, group.getEditors()[2]); + assert.equal(input3, group.getEditors(EditorsOrder.SEQUENTIAL)[2]); const input4 = input(); group.openEditor(input4, { pinned: false, active: true }); // this should cause the preview editor to move after input3 - assert.equal(input4, group.getEditors()[2]); + assert.equal(input4, group.getEditors(EditorsOrder.SEQUENTIAL)[2]); }); test('Multiple Editors - Pinned and Active (DEFAULT_OPEN_EDITOR_DIRECTION = Direction.LEFT)', function () { @@ -528,9 +528,9 @@ suite('Workbench editor groups', () => { group.openEditor(input2, { pinned: true, active: true }); group.openEditor(input3, { pinned: true, active: true }); - assert.equal(group.getEditors()[0], input3); - assert.equal(group.getEditors()[1], input2); - assert.equal(group.getEditors()[2], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input1); group.closeAllEditors(); @@ -551,7 +551,7 @@ suite('Workbench editor groups', () => { group.openEditor(input3, { pinned: true }); assert.equal(group.count, 3); - assert.equal(group.getEditors(true).length, 3); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 3); assert.equal(group.activeEditor, input1); assert.equal(group.isActive(input1), true); assert.equal(group.isPinned(input1), true); @@ -566,7 +566,7 @@ suite('Workbench editor groups', () => { assert.equal(group.isPinned(2), true); assert.equal(group.isPreview(input3), false); - const mru = group.getEditors(true); + const mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input1); assert.equal(mru[1], input3); assert.equal(mru[2], input2); @@ -586,7 +586,7 @@ suite('Workbench editor groups', () => { group.openEditor(input3); // overwrites preview assert.equal(group.count, 1); - assert.equal(group.getEditors(true).length, 1); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).length, 1); assert.equal(group.activeEditor, input3); assert.equal(group.isActive(input3), true); assert.equal(group.isPinned(input3), false); @@ -600,7 +600,7 @@ suite('Workbench editor groups', () => { assert.equal(events.closed[0].replaced, true); assert.equal(events.closed[1].replaced, true); - const mru = group.getEditors(true); + const mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input3); assert.equal(mru.length, 1); }); @@ -619,7 +619,7 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor, input3); - let mru = group.getEditors(true); + let mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input3); assert.equal(mru[1], input2); assert.equal(mru[2], input1); @@ -634,7 +634,7 @@ suite('Workbench editor groups', () => { assert.equal(group.isActive(input2), false); assert.equal(group.isActive(input3), false); - mru = group.getEditors(true); + mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); assert.equal(mru[0], input1); assert.equal(mru[1], input3); assert.equal(mru[2], input2); @@ -677,8 +677,8 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor, input3); assert.equal(group.count, 2); // 2 previews got merged into one - assert.equal(group.getEditors()[0], input2); - assert.equal(group.getEditors()[1], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input3); assert.equal(events.closed[0].editor, input1); assert.equal(group.count, 2); @@ -686,7 +686,7 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor, input3); assert.equal(group.count, 1); // pinning replaced the preview - assert.equal(group.getEditors()[0], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input3); assert.equal(events.closed[1].editor, input2); assert.equal(group.count, 1); }); @@ -708,7 +708,7 @@ suite('Workbench editor groups', () => { group.openEditor(input5, { pinned: true, active: true }); assert.equal(group.activeEditor, input5); - assert.equal(group.getEditors(true)[0], input5); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0], input5); assert.equal(group.count, 5); group.closeEditor(input5); @@ -767,7 +767,7 @@ suite('Workbench editor groups', () => { group.openEditor(input5, { pinned: true, active: true }); assert.equal(group.activeEditor, input5); - assert.equal(group.getEditors(true)[0], input5); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0], input5); assert.equal(group.count, 5); group.closeEditor(input5); @@ -814,8 +814,8 @@ suite('Workbench editor groups', () => { group.moveEditor(input1, 1); assert.equal(events.moved[0], input1); - assert.equal(group.getEditors()[0], input2); - assert.equal(group.getEditors()[1], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input1); group.setActive(input1); group.openEditor(input3, { pinned: true, active: true }); @@ -825,20 +825,20 @@ suite('Workbench editor groups', () => { group.moveEditor(input4, 0); assert.equal(events.moved[1], input4); - assert.equal(group.getEditors()[0], input4); - assert.equal(group.getEditors()[1], input2); - assert.equal(group.getEditors()[2], input1); - assert.equal(group.getEditors()[3], input3); - assert.equal(group.getEditors()[4], input5); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input4); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[3], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[4], input5); group.moveEditor(input4, 3); group.moveEditor(input2, 1); - assert.equal(group.getEditors()[0], input1); - assert.equal(group.getEditors()[1], input2); - assert.equal(group.getEditors()[2], input3); - assert.equal(group.getEditors()[3], input4); - assert.equal(group.getEditors()[4], input5); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[3], input4); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[4], input5); }); test('Multiple Editors - move editor across groups', function () { @@ -858,9 +858,9 @@ suite('Workbench editor groups', () => { group1.openEditor(g2_input1, { active: true, pinned: true, index: 1 }); assert.equal(group1.count, 3); - assert.equal(group1.getEditors()[0], g1_input1); - assert.equal(group1.getEditors()[1], g2_input1); - assert.equal(group1.getEditors()[2], g1_input2); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[0], g1_input1); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[1], g2_input1); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[2], g1_input2); }); test('Multiple Editors - move editor across groups (input already exists in group 1)', function () { @@ -882,9 +882,9 @@ suite('Workbench editor groups', () => { group1.openEditor(g2_input1, { active: true, pinned: true, index: 0 }); assert.equal(group1.count, 3); - assert.equal(group1.getEditors()[0], g1_input2); - assert.equal(group1.getEditors()[1], g1_input1); - assert.equal(group1.getEditors()[2], g1_input3); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[0], g1_input2); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[1], g1_input1); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[2], g1_input3); }); test('Multiple Editors - Pinned & Non Active', function () { @@ -894,24 +894,24 @@ suite('Workbench editor groups', () => { group.openEditor(input1); assert.equal(group.activeEditor, input1); assert.equal(group.previewEditor, input1); - assert.equal(group.getEditors()[0], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input1); assert.equal(group.count, 1); const input2 = input(); group.openEditor(input2, { pinned: true, active: false }); assert.equal(group.activeEditor, input1); assert.equal(group.previewEditor, input1); - assert.equal(group.getEditors()[0], input1); - assert.equal(group.getEditors()[1], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input2); assert.equal(group.count, 2); const input3 = input(); group.openEditor(input3, { pinned: true, active: false }); assert.equal(group.activeEditor, input1); assert.equal(group.previewEditor, input1); - assert.equal(group.getEditors()[0], input1); - assert.equal(group.getEditors()[1], input3); - assert.equal(group.getEditors()[2], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input2); assert.equal(group.isPinned(input1), false); assert.equal(group.isPinned(input2), true); assert.equal(group.isPinned(input3), true); @@ -951,9 +951,9 @@ suite('Workbench editor groups', () => { group.closeEditors(group.activeEditor!, CloseDirection.LEFT); assert.equal(group.activeEditor, input3); assert.equal(group.count, 3); - assert.equal(group.getEditors()[0], input3); - assert.equal(group.getEditors()[1], input4); - assert.equal(group.getEditors()[2], input5); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input4); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input5); group.closeAllEditors(); group.openEditor(input1, { active: true, pinned: true }); @@ -968,9 +968,9 @@ suite('Workbench editor groups', () => { group.closeEditors(group.activeEditor!, CloseDirection.RIGHT); assert.equal(group.activeEditor, input3); assert.equal(group.count, 3); - assert.equal(group.getEditors()[0], input1); - assert.equal(group.getEditors()[1], input2); - assert.equal(group.getEditors()[2], input3); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], input1); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], input2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[2], input3); }); test('Multiple Editors - real user example', function () { @@ -982,7 +982,7 @@ suite('Workbench editor groups', () => { assert.equal(openedEditor, indexHtml); assert.equal(group.activeEditor, indexHtml); assert.equal(group.previewEditor, indexHtml); - assert.equal(group.getEditors()[0], indexHtml); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], indexHtml); assert.equal(group.count, 1); // /index.html/ -> /index.html/ @@ -991,7 +991,7 @@ suite('Workbench editor groups', () => { assert.equal(openedEditor, indexHtml); assert.equal(group.activeEditor, indexHtml); assert.equal(group.previewEditor, indexHtml); - assert.equal(group.getEditors()[0], indexHtml); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], indexHtml); assert.equal(group.count, 1); // /index.html/ -> /style.css/ @@ -1000,7 +1000,7 @@ suite('Workbench editor groups', () => { assert.equal(openedEditor, styleCss); assert.equal(group.activeEditor, styleCss); assert.equal(group.previewEditor, styleCss); - assert.equal(group.getEditors()[0], styleCss); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], styleCss); assert.equal(group.count, 1); // /style.css/ -> [/style.css/, test.js] @@ -1011,8 +1011,8 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor, testJs); assert.equal(group.isPreview(styleCss), true); assert.equal(group.isPinned(testJs), true); - assert.equal(group.getEditors()[0], styleCss); - assert.equal(group.getEditors()[1], testJs); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], styleCss); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], testJs); assert.equal(group.count, 2); // [/style.css/, test.js] -> [test.js, /index.html/] @@ -1022,8 +1022,8 @@ suite('Workbench editor groups', () => { assert.equal(group.previewEditor, indexHtml2); assert.equal(group.isPreview(indexHtml2), true); assert.equal(group.isPinned(testJs), true); - assert.equal(group.getEditors()[0], testJs); - assert.equal(group.getEditors()[1], indexHtml2); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[0], testJs); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], indexHtml2); assert.equal(group.count, 2); // make test.js active @@ -1060,9 +1060,9 @@ suite('Workbench editor groups', () => { group.openEditor(otherTs, { active: true }); assert.equal(group.count, 3); assert.equal(group.activeEditor, otherTs); - assert.ok(group.getEditors()[0].matches(testJs)); - assert.equal(group.getEditors()[1], otherTs); - assert.ok(group.getEditors()[2].matches(indexHtml)); + assert.ok(group.getEditors(EditorsOrder.SEQUENTIAL)[0].matches(testJs)); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], otherTs); + assert.ok(group.getEditors(EditorsOrder.SEQUENTIAL)[2].matches(indexHtml)); // make index.html active const indexHtml4 = input('index.html'); @@ -1073,20 +1073,20 @@ suite('Workbench editor groups', () => { group.closeEditor(indexHtml); assert.equal(group.count, 2); assert.equal(group.activeEditor, otherTs); - assert.ok(group.getEditors()[0].matches(testJs)); - assert.equal(group.getEditors()[1], otherTs); + assert.ok(group.getEditors(EditorsOrder.SEQUENTIAL)[0].matches(testJs)); + assert.equal(group.getEditors(EditorsOrder.SEQUENTIAL)[1], otherTs); // [test.js, /other.ts/] -> [test.js] group.closeEditor(otherTs); assert.equal(group.count, 1); assert.equal(group.activeEditor, testJs); - assert.ok(group.getEditors()[0].matches(testJs)); + assert.ok(group.getEditors(EditorsOrder.SEQUENTIAL)[0].matches(testJs)); // [test.js] -> /test.js/ group.unpin(testJs); assert.equal(group.count, 1); assert.equal(group.activeEditor, testJs); - assert.ok(group.getEditors()[0].matches(testJs)); + assert.ok(group.getEditors(EditorsOrder.SEQUENTIAL)[0].matches(testJs)); assert.equal(group.isPinned(testJs), false); assert.equal(group.isPreview(testJs), true); @@ -1173,13 +1173,13 @@ suite('Workbench editor groups', () => { assert.equal(group1.previewEditor!.matches(g1_input2), true); assert.equal(group2.previewEditor!.matches(g2_input2), true); - assert.equal(group1.getEditors(true)[0].matches(g1_input2), true); - assert.equal(group1.getEditors(true)[1].matches(g1_input3), true); - assert.equal(group1.getEditors(true)[2].matches(g1_input1), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(g1_input2), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(g1_input3), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[2].matches(g1_input1), true); - assert.equal(group2.getEditors(true)[0].matches(g2_input1), true); - assert.equal(group2.getEditors(true)[1].matches(g2_input3), true); - assert.equal(group2.getEditors(true)[2].matches(g2_input2), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(g2_input1), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(g2_input3), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[2].matches(g2_input2), true); // Create model again - should load from storage group1 = inst.createInstance(EditorGroup, group1.serialize()); @@ -1192,13 +1192,13 @@ suite('Workbench editor groups', () => { assert.equal(group1.previewEditor!.matches(g1_input2), true); assert.equal(group2.previewEditor!.matches(g2_input2), true); - assert.equal(group1.getEditors(true)[0].matches(g1_input2), true); - assert.equal(group1.getEditors(true)[1].matches(g1_input3), true); - assert.equal(group1.getEditors(true)[2].matches(g1_input1), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(g1_input2), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(g1_input3), true); + assert.equal(group1.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[2].matches(g1_input1), true); - assert.equal(group2.getEditors(true)[0].matches(g2_input1), true); - assert.equal(group2.getEditors(true)[1].matches(g2_input3), true); - assert.equal(group2.getEditors(true)[2].matches(g2_input2), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(g2_input1), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(g2_input3), true); + assert.equal(group2.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[2].matches(g2_input2), true); }); test('Single group, multiple editors - persist (some not persistable)', function () { @@ -1230,9 +1230,9 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor!.matches(nonSerializableInput2), true); assert.equal(group.previewEditor!.matches(nonSerializableInput2), true); - assert.equal(group.getEditors(true)[0].matches(nonSerializableInput2), true); - assert.equal(group.getEditors(true)[1].matches(serializableInput2), true); - assert.equal(group.getEditors(true)[2].matches(serializableInput1), true); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(nonSerializableInput2), true); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(serializableInput2), true); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[2].matches(serializableInput1), true); // Create model again - should load from storage group = inst.createInstance(EditorGroup, group.serialize()); @@ -1241,8 +1241,8 @@ suite('Workbench editor groups', () => { assert.equal(group.activeEditor!.matches(serializableInput2), true); assert.equal(group.previewEditor, null); - assert.equal(group.getEditors(true)[0].matches(serializableInput2), true); - assert.equal(group.getEditors(true)[1].matches(serializableInput1), true); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[0].matches(serializableInput2), true); + assert.equal(group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)[1].matches(serializableInput1), true); }); test('Multiple groups, multiple editors - persist (some not persistable, causes empty group)', function () { @@ -1277,8 +1277,8 @@ suite('Workbench editor groups', () => { group2 = inst.createInstance(EditorGroup, group2.serialize()); assert.equal(group1.count, 2); - assert.equal(group1.getEditors()[0].matches(serializableInput1), true); - assert.equal(group1.getEditors()[1].matches(serializableInput2), true); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[0].matches(serializableInput1), true); + assert.equal(group1.getEditors(EditorsOrder.SEQUENTIAL)[1].matches(serializableInput2), true); }); test('Multiple Editors - Editor Dispose', function () { diff --git a/src/vs/workbench/test/workbenchTestServices.ts b/src/vs/workbench/test/workbenchTestServices.ts index 160409c59a..3223a1206e 100644 --- a/src/vs/workbench/test/workbenchTestServices.ts +++ b/src/vs/workbench/test/workbenchTestServices.ts @@ -11,7 +11,7 @@ import * as resources from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { IEditorInputWithOptions, CloseDirection, IEditorIdentifier, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInput, IEditor, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { IEditorInputWithOptions, CloseDirection, IEditorIdentifier, IUntitledTextResourceInput, IResourceDiffInput, IResourceSideBySideInput, IEditorInput, IEditor, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions, EditorsOrder } from 'vs/workbench/common/editor'; import { IEditorOpeningEvent, EditorServiceImpl, IEditorGroupView, IEditorGroupsAccessor } from 'vs/workbench/browser/parts/editor/editor'; import { Event, Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; @@ -56,7 +56,7 @@ import { IExtensionService, NullExtensionService } from 'vs/workbench/services/e import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IDecorationsService, IResourceDecorationChangeEvent, IDecoration, IDecorationData, IDecorationsProvider } from 'vs/workbench/services/decorations/browser/decorations'; import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupsArrangement, GroupDirection, IAddGroupOptions, IMergeGroupOptions, IMoveEditorOptions, ICopyEditorOptions, IEditorReplacement, IGroupChangeEvent, EditorsOrder, IFindGroupScope, EditorGroupLayout, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupsArrangement, GroupDirection, IAddGroupOptions, IMergeGroupOptions, IMoveEditorOptions, ICopyEditorOptions, IEditorReplacement, IGroupChangeEvent, IFindGroupScope, EditorGroupLayout, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, IOpenEditorOverrideHandler, IVisibleEditor, ISaveEditorsOptions, IRevertAllEditorsOptions, IResourceEditor } from 'vs/workbench/services/editor/common/editorService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; @@ -377,7 +377,6 @@ export class TestHistoryService implements IHistoryService { getHistory(): ReadonlyArray { return []; } openNextRecentlyUsedEditor(group?: GroupIdentifier): void { } openPreviouslyUsedEditor(group?: GroupIdentifier): void { } - getMostRecentlyUsedOpenEditors(): Array { return []; } getLastActiveWorkspaceRoot(_schemeFilter: string): URI | undefined { return this.root; } getLastActiveFile(_schemeFilter: string): URI | undefined { return undefined; } openLastEditLocation(): void { } @@ -912,9 +911,12 @@ export class TestEditorService implements EditorServiceImpl { visibleControls: ReadonlyArray = []; visibleTextEditorWidgets = []; visibleEditors: ReadonlyArray = []; + count = this.editors.length; constructor(private editorGroupService?: IEditorGroupsService) { } + getEditors() { return []; } + overrideOpenEditor(_handler: IOpenEditorOverrideHandler): IDisposable { return toDisposable(() => undefined); }