mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 1fbacccbc900bb59ba8a8f26a4128d48a1c97842
This commit is contained in:
@@ -238,9 +238,12 @@ export class ResourcesDropHandler {
|
||||
|
||||
private async handleDirtyEditorDrop(droppedDirtyEditor: IDraggedEditor): Promise<boolean> {
|
||||
|
||||
// Untitled: always ensure that we open a new untitled for each file we drop
|
||||
// Untitled: always ensure that we open a new untitled editor for each file we drop
|
||||
if (droppedDirtyEditor.resource.scheme === Schemas.untitled) {
|
||||
droppedDirtyEditor.resource = this.textFileService.untitled.create({ mode: droppedDirtyEditor.mode, encoding: droppedDirtyEditor.encoding }).getResource();
|
||||
const untitledEditorResource = this.editorService.createInput({ mode: droppedDirtyEditor.mode, encoding: droppedDirtyEditor.encoding, forceUntitled: true }).getResource();
|
||||
if (untitledEditorResource) {
|
||||
droppedDirtyEditor.resource = untitledEditorResource;
|
||||
}
|
||||
}
|
||||
|
||||
// File: ensure the file is not dirty or opened already
|
||||
|
||||
@@ -105,8 +105,7 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
);
|
||||
|
||||
interface ISerializedUntitledTextEditorInput {
|
||||
resource: string;
|
||||
resourceJSON: object;
|
||||
resourceJSON: UriComponents;
|
||||
modeId: string | undefined;
|
||||
encoding: string | undefined;
|
||||
}
|
||||
@@ -131,12 +130,11 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
|
||||
const untitledTextEditorInput = <UntitledTextEditorInput>editorInput;
|
||||
|
||||
let resource = untitledTextEditorInput.getResource();
|
||||
if (untitledTextEditorInput.hasAssociatedFilePath) {
|
||||
if (untitledTextEditorInput.model.hasAssociatedFilePath) {
|
||||
resource = toLocalResource(resource, this.environmentService.configuration.remoteAuthority); // untitled with associated file path use the local schema
|
||||
}
|
||||
|
||||
const serialized: ISerializedUntitledTextEditorInput = {
|
||||
resource: resource.toString(), // Keep for backwards compatibility
|
||||
resourceJSON: resource.toJSON(),
|
||||
modeId: untitledTextEditorInput.getMode(),
|
||||
encoding: untitledTextEditorInput.getEncoding()
|
||||
@@ -148,7 +146,7 @@ class UntitledTextEditorInputFactory implements IEditorInputFactory {
|
||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): UntitledTextEditorInput {
|
||||
return instantiationService.invokeFunction<UntitledTextEditorInput>(accessor => {
|
||||
const deserialized: ISerializedUntitledTextEditorInput = JSON.parse(serializedEditorInput);
|
||||
const resource = !!deserialized.resourceJSON ? URI.revive(<UriComponents>deserialized.resourceJSON) : URI.parse(deserialized.resource);
|
||||
const resource = URI.revive(deserialized.resourceJSON);
|
||||
const mode = deserialized.modeId;
|
||||
const encoding = deserialized.encoding;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor';
|
||||
import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditor, IEditorPartOptions, IEditorPartOptionsChangeEvent, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorGroup } from 'vs/workbench/common/editor/editorGroup';
|
||||
import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -14,7 +14,7 @@ import { IConfigurationChangeEvent } from 'vs/platform/configuration/common/conf
|
||||
import { ISerializableView } from 'vs/base/browser/ui/grid/grid';
|
||||
import { getCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export const EDITOR_TITLE_HEIGHT = 35;
|
||||
|
||||
@@ -156,4 +156,9 @@ export interface EditorServiceImpl extends IEditorService {
|
||||
* Emitted when the list of most recently active editors change.
|
||||
*/
|
||||
readonly onDidMostRecentlyActiveEditorsChange: Event<void>;
|
||||
|
||||
/**
|
||||
* Override to return a typed `EditorInput`.
|
||||
*/
|
||||
createInput(input: IResourceEditor): EditorInput;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
interface IDropOperation {
|
||||
splitDirection?: GroupDirection;
|
||||
@@ -48,8 +48,8 @@ class DropOverlay extends Themable {
|
||||
private groupView: IEditorGroupView,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@ITextFileService private textFileService: ITextFileService,
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -308,8 +308,11 @@ class DropOverlay extends Themable {
|
||||
}
|
||||
|
||||
// Open as untitled file with the provided contents
|
||||
const contents = VSBuffer.wrap(new Uint8Array(event.target.result)).toString();
|
||||
const untitledEditor = this.textFileService.untitled.create({ associatedResource: proposedFilePath, initialValue: contents });
|
||||
const untitledEditor = this.editorService.createInput({
|
||||
resource: proposedFilePath,
|
||||
forceUntitled: true,
|
||||
contents: VSBuffer.wrap(new Uint8Array(event.target.result)).toString()
|
||||
});
|
||||
|
||||
if (!targetGroup) {
|
||||
targetGroup = ensureTargetGroup();
|
||||
|
||||
@@ -31,8 +31,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { RunOnceWorker } from 'vs/base/common/async';
|
||||
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, getActiveTextEditorOptions, IEditorOpeningEvent } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, getActiveTextEditorOptions, IEditorOpeningEvent, EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ActionRunner, IAction, Action } from 'vs/base/common/actions';
|
||||
@@ -43,7 +42,7 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { isErrorWithActions, IErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { IVisibleEditor } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IVisibleEditor, IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { guessMimeTypes } from 'vs/base/common/mime';
|
||||
@@ -129,12 +128,12 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IEditorService private readonly editorService: EditorServiceImpl
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -256,7 +255,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
if (this.isEmpty) {
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.openEditor(this.textFileService.untitled.create(), EditorOptions.create({ pinned: true }));
|
||||
this.openEditor(this.editorService.createInput({ forceUntitled: true }), EditorOptions.create({ pinned: true }));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/bro
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { MementoObject } from 'vs/workbench/common/memento';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { IBoundarySashes } from 'vs/base/browser/ui/grid/gridview';
|
||||
|
||||
interface IEditorPartUIState {
|
||||
serializedGrid: ISerializedGrid;
|
||||
@@ -947,11 +948,15 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
|
||||
}
|
||||
|
||||
private doSetGridWidget(gridWidget: SerializableGrid<IEditorGroupView>): void {
|
||||
let boundarySashes: IBoundarySashes = {};
|
||||
|
||||
if (this.gridWidget) {
|
||||
boundarySashes = this.gridWidget.boundarySashes;
|
||||
this.gridWidget.dispose();
|
||||
}
|
||||
|
||||
this.gridWidget = gridWidget;
|
||||
this.gridWidget.boundarySashes = boundarySashes;
|
||||
this.gridWidgetView.gridWidget = gridWidget;
|
||||
|
||||
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
|
||||
@@ -972,6 +977,11 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
|
||||
return this.groupViews.size === 1 && this._activeGroup.isEmpty;
|
||||
}
|
||||
|
||||
setBoundarySashes(sashes: IBoundarySashes): void {
|
||||
this.gridWidget.boundarySashes = sashes;
|
||||
this.centeredLayoutWidget.boundarySashes = sashes;
|
||||
}
|
||||
|
||||
layout(width: number, height: number): void {
|
||||
|
||||
// Layout contents
|
||||
|
||||
@@ -34,14 +34,14 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
||||
import { MergeGroupMode, IMergeGroupOptions, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { addClass, addDisposableListener, hasClass, EventType, EventHelper, removeClass, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode } from 'vs/base/browser/dom';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { withNullAsUndefined, assertAllDefined, assertIsDefined } from 'vs/base/common/types';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { basenameOrAuthority } from 'vs/base/common/resources';
|
||||
|
||||
// {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
@@ -80,7 +80,6 @@ export class TabsTitleControl extends TitleControl {
|
||||
group: IEditorGroupView,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ITextFileService private readonly textFileService: ITextFileService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@@ -91,7 +90,8 @@ export class TabsTitleControl extends TitleControl {
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IFileService fileService: IFileService,
|
||||
@ILabelService labelService: ILabelService
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IEditorService private readonly editorService: EditorServiceImpl
|
||||
) {
|
||||
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickOpenService, themeService, extensionService, configurationService, fileService, labelService);
|
||||
|
||||
@@ -198,7 +198,13 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
EventHelper.stop(e);
|
||||
|
||||
this.group.openEditor(this.textFileService.untitled.create(), { pinned: true /* untitled is always pinned */, index: this.group.count /* always at the end */ });
|
||||
this.group.openEditor(this.editorService.createInput({
|
||||
forceUntitled: true,
|
||||
options: {
|
||||
pinned: true, // untitled is always pinned
|
||||
index: this.group.count // always at the end
|
||||
}
|
||||
}));
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ export class TextResourceEditor extends AbstractTextResourceEditor {
|
||||
}
|
||||
|
||||
private onDidEditorPaste(e: IPasteEvent, codeEditor: ICodeEditor): void {
|
||||
if (e.range.startLineNumber !== 1 && e.range.startColumn !== 1) {
|
||||
if (e.range.startLineNumber !== 1 || e.range.startColumn !== 1) {
|
||||
return; // only when pasting into first line, first column (= empty document)
|
||||
}
|
||||
|
||||
|
||||
@@ -156,14 +156,14 @@ export abstract class MenubarControl extends Disposable {
|
||||
return label;
|
||||
}
|
||||
|
||||
protected getOpenRecentActions(): IAction[] {
|
||||
protected getOpenRecentActions(): (Separator | IAction & { uri: URI })[] {
|
||||
if (!this.recentlyOpened) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaces, files } = this.recentlyOpened;
|
||||
|
||||
const result: IAction[] = [];
|
||||
const result = [];
|
||||
|
||||
if (workspaces.length > 0) {
|
||||
for (let i = 0; i < MenubarControl.MAX_MENU_RECENT_ENTRIES && i < workspaces.length; i++) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import { ResourceLabels, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
import { ActionBar, IActionViewItemProvider, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { dirname, basename } from 'vs/base/common/resources';
|
||||
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, ThemeIcon, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { FileKind } from 'vs/platform/files/common/files';
|
||||
import { WorkbenchAsyncDataTree, TreeResourceNavigator } from 'vs/platform/list/browser/listService';
|
||||
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
@@ -42,6 +42,7 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters';
|
||||
import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { SIDE_BAR_BACKGROUND, PANEL_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
export class CustomTreeViewPane extends ViewPane {
|
||||
|
||||
@@ -56,8 +57,10 @@ export class CustomTreeViewPane extends ViewPane {
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
) {
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title, titleMenuId: MenuId.ViewTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService);
|
||||
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title, titleMenuId: MenuId.ViewTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService);
|
||||
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
|
||||
this.treeView = treeView;
|
||||
this._register(this.treeView.onDidChangeActions(() => this.updateActions(), this));
|
||||
@@ -73,6 +76,8 @@ export class CustomTreeViewPane extends ViewPane {
|
||||
}
|
||||
|
||||
renderBody(container: HTMLElement): void {
|
||||
super.renderBody(container);
|
||||
|
||||
if (this.treeView instanceof CustomTreeView) {
|
||||
this.treeView.show(container);
|
||||
}
|
||||
@@ -113,6 +118,8 @@ class Root implements ITreeItem {
|
||||
|
||||
const noDataProviderMessage = localize('no-dataprovider', "There is no data provider registered that can provide view data.");
|
||||
|
||||
class CustomTree extends WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore> { }
|
||||
|
||||
export class CustomTreeView extends Disposable implements ITreeView {
|
||||
|
||||
private isVisible: boolean = false;
|
||||
@@ -127,7 +134,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
private _messageValue: string | undefined;
|
||||
private _canSelectMany: boolean = false;
|
||||
private messageElement!: HTMLDivElement;
|
||||
private tree: WorkbenchAsyncDataTree<ITreeItem, ITreeItem, FuzzyScore> | undefined;
|
||||
private tree: CustomTree | undefined;
|
||||
private treeLabels: ResourceLabels | undefined;
|
||||
|
||||
private root: ITreeItem;
|
||||
@@ -351,7 +358,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
|
||||
const aligner = new Aligner(this.themeService);
|
||||
const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, treeMenus, this.treeLabels, actionViewItemProvider, aligner);
|
||||
|
||||
this.tree = this._register(this.instantiationService.createInstance(WorkbenchAsyncDataTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer],
|
||||
this.tree = this._register(this.instantiationService.createInstance(CustomTree, 'CustomView', this.treeContainer, new CustomTreeDelegate(), [renderer],
|
||||
dataSource, {
|
||||
identityProvider: new CustomViewIdentityProvider(),
|
||||
accessibilityProvider: {
|
||||
|
||||
@@ -71,6 +71,26 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body > .empty-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 20px 0 20px;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body:not(.empty) > .empty-view,
|
||||
.monaco-workbench .pane > .pane-body.empty > :not(.empty-view) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body > .empty-view .monaco-button {
|
||||
max-width: 260px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.customview-tree .monaco-list-row .monaco-tl-contents.align-icon-with-twisty::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import 'vs/css!./media/paneviewlet';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachStyler, IColorMapping } from 'vs/platform/theme/common/styler';
|
||||
import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler } from 'vs/platform/theme/common/styler';
|
||||
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { IDisposable, combinedDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass } from 'vs/base/browser/dom';
|
||||
import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { IAction, IActionRunner, ActionRunner } from 'vs/base/common/actions';
|
||||
import { IActionViewItem, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
@@ -25,7 +25,7 @@ import { PaneView, IPaneViewOptions, IPaneOptions, Pane, DefaultPaneDndControlle
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer } from 'vs/workbench/common/views';
|
||||
import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry } from 'vs/workbench/common/views';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
@@ -38,6 +38,10 @@ import { Component } from 'vs/workbench/common/component';
|
||||
import { MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
||||
import { parseLinkedText } from 'vs/base/browser/linkedText';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { Link } from 'vs/platform/opener/browser/link';
|
||||
|
||||
export interface IPaneColors extends IColorMapping {
|
||||
dropBackground?: ColorIdentifier;
|
||||
@@ -54,6 +58,8 @@ export interface IViewPaneOptions extends IPaneOptions {
|
||||
titleMenuId?: MenuId;
|
||||
}
|
||||
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
|
||||
|
||||
export abstract class ViewPane extends Pane implements IView {
|
||||
|
||||
private static readonly AlwaysShowActionsConfig = 'workbench.view.alwaysShowHeaderActions';
|
||||
@@ -70,6 +76,9 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
protected _onDidChangeTitleArea = this._register(new Emitter<void>());
|
||||
readonly onDidChangeTitleArea: Event<void> = this._onDidChangeTitleArea.event;
|
||||
|
||||
protected _onDidChangeEmptyState = this._register(new Emitter<void>());
|
||||
readonly onDidChangeEmptyState: Event<void> = this._onDidChangeEmptyState.event;
|
||||
|
||||
private focusedViewContextKey: IContextKey<string>;
|
||||
|
||||
private _isVisible: boolean = false;
|
||||
@@ -79,12 +88,16 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
private readonly menuActions: ViewMenuActions;
|
||||
|
||||
protected actionRunner?: IActionRunner;
|
||||
protected toolbar?: ToolBar;
|
||||
private toolbar?: ToolBar;
|
||||
private readonly showActionsAlways: boolean = false;
|
||||
private headerContainer?: HTMLElement;
|
||||
private titleContainer?: HTMLElement;
|
||||
protected twistiesContainer?: HTMLElement;
|
||||
|
||||
private bodyContainer!: HTMLElement;
|
||||
private emptyViewContainer!: HTMLElement;
|
||||
private emptyViewDisposable: IDisposable = Disposable.None;
|
||||
|
||||
constructor(
|
||||
options: IViewPaneOptions,
|
||||
@IKeybindingService protected keybindingService: IKeybindingService,
|
||||
@@ -93,6 +106,8 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IViewDescriptorService protected viewDescriptorService: IViewDescriptorService,
|
||||
@IInstantiationService protected instantiationService: IInstantiationService,
|
||||
@IOpenerService protected openerService: IOpenerService,
|
||||
@IThemeService protected themeService: IThemeService,
|
||||
) {
|
||||
super(options);
|
||||
|
||||
@@ -189,6 +204,22 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
this._onDidChangeTitleArea.fire();
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
this.bodyContainer = container;
|
||||
this.emptyViewContainer = append(container, $('.empty-view', { tabIndex: 0 }));
|
||||
|
||||
// we should update our empty state whenever
|
||||
const onEmptyViewContentChange = Event.any(
|
||||
// the registry changes
|
||||
Event.map(Event.filter(viewsRegistry.onDidChangeEmptyViewContent, id => id === this.id), () => this.isEmpty()),
|
||||
// or the view's empty state changes
|
||||
Event.latch(Event.map(this.onDidChangeEmptyState, () => this.isEmpty()))
|
||||
);
|
||||
|
||||
this._register(onEmptyViewContentChange(this.updateEmptyState, this));
|
||||
this.updateEmptyState(this.isEmpty());
|
||||
}
|
||||
|
||||
protected getProgressLocation(): string {
|
||||
return this.viewDescriptorService.getViewContainer(this.id)!.id;
|
||||
}
|
||||
@@ -254,6 +285,66 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
saveState(): void {
|
||||
// Subclasses to implement for saving state
|
||||
}
|
||||
|
||||
private updateEmptyState(isEmpty: boolean): void {
|
||||
this.emptyViewDisposable.dispose();
|
||||
|
||||
if (!isEmpty) {
|
||||
removeClass(this.bodyContainer, 'empty');
|
||||
this.emptyViewContainer.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const contents = viewsRegistry.getEmptyViewContent(this.id);
|
||||
|
||||
if (contents.length === 0) {
|
||||
removeClass(this.bodyContainer, 'empty');
|
||||
this.emptyViewContainer.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
addClass(this.bodyContainer, 'empty');
|
||||
this.emptyViewContainer.innerHTML = '';
|
||||
|
||||
for (const { content } of contents) {
|
||||
const lines = content.split('\n');
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim();
|
||||
|
||||
if (!line) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const p = append(this.emptyViewContainer, $('p'));
|
||||
const linkedText = parseLinkedText(line);
|
||||
|
||||
for (const node of linkedText) {
|
||||
if (typeof node === 'string') {
|
||||
append(p, document.createTextNode(node));
|
||||
} else if (linkedText.length === 1) {
|
||||
const button = new Button(p, { title: node.title });
|
||||
button.label = node.label;
|
||||
button.onDidClick(_ => this.openerService.open(node.href), null, disposables);
|
||||
disposables.add(button);
|
||||
disposables.add(attachButtonStyler(button, this.themeService));
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
append(p, link.el);
|
||||
disposables.add(link);
|
||||
disposables.add(attachLinkStyler(link, this.themeService));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.emptyViewDisposable = disposables;
|
||||
}
|
||||
|
||||
isEmpty(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IViewPaneContainerOptions extends IPaneViewOptions {
|
||||
|
||||
@@ -191,7 +191,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
|
||||
'type': 'string',
|
||||
'enum': ['left', 'bottom', 'right'],
|
||||
'default': 'bottom',
|
||||
'description': nls.localize('panelDefaultLocation', "Controls the default location of the panel (terminal, debug console, output, problems). It can either show at the bottom or on the right of the workbench.")
|
||||
'description': nls.localize('panelDefaultLocation', "Controls the default location of the panel (terminal, debug console, output, problems). It can either show at the bottom, right, or left of the workbench.")
|
||||
},
|
||||
'workbench.statusBar.visible': {
|
||||
'type': 'boolean',
|
||||
@@ -210,7 +210,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
|
||||
},
|
||||
'workbench.view.experimental.allowMovingToNewContainer': {
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'default': true,
|
||||
'description': nls.localize('movingViewContainer', "Controls whether specific views will have a context menu entry allowing them to be moved to a new container. Currently, this setting only affects the outline view and views contributed by extensions.")
|
||||
},
|
||||
'workbench.fontAliasing': {
|
||||
|
||||
Reference in New Issue
Block a user