mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 6fded8a497cd0142de3a1c607649a5423a091a25
This commit is contained in:
@@ -504,6 +504,37 @@ export class ResetViewLocationsAction extends Action {
|
||||
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ResetViewLocationsAction, ResetViewLocationsAction.ID, ResetViewLocationsAction.LABEL), 'View: Reset View Locations', viewCategory);
|
||||
|
||||
// --- Toggle View with Command
|
||||
export abstract class ToggleViewAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private readonly viewId: string,
|
||||
protected viewsService: IViewsService,
|
||||
protected viewDescriptorService: IViewDescriptorService,
|
||||
protected contextKeyService: IContextKeyService,
|
||||
private layoutService: IWorkbenchLayoutService,
|
||||
cssClass?: string
|
||||
) {
|
||||
super(id, label, cssClass);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
const focusedViewId = FocusedViewContext.getValue(this.contextKeyService);
|
||||
|
||||
if (focusedViewId === this.viewId) {
|
||||
if (this.viewDescriptorService.getViewLocation(this.viewId) === ViewContainerLocation.Sidebar) {
|
||||
this.layoutService.setSideBarHidden(true);
|
||||
} else {
|
||||
this.layoutService.setPanelHidden(true);
|
||||
}
|
||||
} else {
|
||||
this.viewsService.openView(this.viewId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Move View with Command
|
||||
export class MoveFocusedViewAction extends Action {
|
||||
static readonly ID = 'workbench.action.moveFocusedView';
|
||||
@@ -541,6 +572,7 @@ export class MoveFocusedViewAction extends Action {
|
||||
|
||||
const quickPick = this.quickInputService.createQuickPick();
|
||||
quickPick.placeholder = nls.localize('moveFocusedView.selectDestination', "Select a Destination for the View");
|
||||
quickPick.title = nls.localize('moveFocusedView.title', "View: Move {0}", viewDescriptor.name);
|
||||
|
||||
const items: Array<IQuickPickItem | IQuickPickSeparator> = [];
|
||||
|
||||
@@ -549,10 +581,16 @@ export class MoveFocusedViewAction extends Action {
|
||||
label: nls.localize('sidebar', "Side Bar")
|
||||
});
|
||||
|
||||
items.push({
|
||||
id: '_.sidebar.newcontainer',
|
||||
label: nls.localize('moveFocusedView.newContainerInSidebar', "New Container in Side Bar")
|
||||
});
|
||||
const currentContainer = this.viewDescriptorService.getViewContainer(focusedViewId)!;
|
||||
const currentLocation = this.viewDescriptorService.getViewLocation(focusedViewId)!;
|
||||
const isViewSolo = this.viewDescriptorService.getViewDescriptors(currentContainer).allViewDescriptors.length === 1;
|
||||
|
||||
if (!(isViewSolo && currentLocation === ViewContainerLocation.Sidebar)) {
|
||||
items.push({
|
||||
id: '_.sidebar.newcontainer',
|
||||
label: nls.localize('moveFocusedView.newContainerInSidebar', "New Container in Side Bar")
|
||||
});
|
||||
}
|
||||
|
||||
const pinnedViewlets = this.activityBarService.getPinnedViewletIds();
|
||||
items.push(...pinnedViewlets
|
||||
@@ -574,10 +612,13 @@ export class MoveFocusedViewAction extends Action {
|
||||
type: 'separator',
|
||||
label: nls.localize('panel', "Panel")
|
||||
});
|
||||
items.push({
|
||||
id: '_.panel.newcontainer',
|
||||
label: nls.localize('moveFocusedView.newContainerInPanel', "New Container in Panel"),
|
||||
});
|
||||
|
||||
if (!(isViewSolo && currentLocation === ViewContainerLocation.Panel)) {
|
||||
items.push({
|
||||
id: '_.panel.newcontainer',
|
||||
label: nls.localize('moveFocusedView.newContainerInPanel', "New Container in Panel"),
|
||||
});
|
||||
}
|
||||
|
||||
const pinnedPanels = this.panelService.getPinnedPanels();
|
||||
items.push(...pinnedPanels
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
const pick = await this.quickInputService.pick(picks, {
|
||||
contextKey: inRecentFilesPickerContextKey,
|
||||
activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0],
|
||||
placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"),
|
||||
placeHolder: isMacintosh ? nls.localize('openRecentPlaceholderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceholder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"),
|
||||
matchOnDescription: true,
|
||||
onKeyMods: mods => keyMods = mods,
|
||||
quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined,
|
||||
@@ -196,6 +196,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
return {
|
||||
iconClasses,
|
||||
label: name,
|
||||
ariaLabel: isDirty ? nls.localize('recentDirtyAriaLabel', "{0}, dirty workspace", name) : name,
|
||||
description: parentPath,
|
||||
buttons: isDirty ? [this.dirtyRecentlyOpened] : [this.removeFromRecentlyOpened],
|
||||
openable,
|
||||
|
||||
@@ -509,8 +509,10 @@ export function containsDragType(event: DragEvent, ...dragTypesToFind: string[])
|
||||
return false;
|
||||
}
|
||||
|
||||
export type Before2D = { verticallyBefore: boolean; horizontallyBefore: boolean; };
|
||||
|
||||
export interface ICompositeDragAndDrop {
|
||||
drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: boolean): void;
|
||||
drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: Before2D): void;
|
||||
onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||
onDragEnter(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IPanel } from 'vs/workbench/common/panel';
|
||||
import { Composite, CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IConstructorSignature0, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isAncestor } from 'vs/base/browser/dom';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { PaneComposite } from 'vs/workbench/browser/panecomposite';
|
||||
|
||||
@@ -85,44 +81,6 @@ export class PanelRegistry extends CompositeRegistry<Panel> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A reusable action to toggle a panel with a specific id depending on focus.
|
||||
*/
|
||||
export abstract class TogglePanelAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
private readonly panelId: string,
|
||||
protected panelService: IPanelService,
|
||||
private layoutService: IWorkbenchLayoutService,
|
||||
cssClass?: string
|
||||
) {
|
||||
super(id, label, cssClass);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
if (this.isPanelFocused()) {
|
||||
this.layoutService.setPanelHidden(true);
|
||||
} else {
|
||||
await this.panelService.openPanel(this.panelId, true);
|
||||
}
|
||||
}
|
||||
|
||||
private isPanelActive(): boolean {
|
||||
const activePanel = this.panelService.getActivePanel();
|
||||
|
||||
return activePanel?.getId() === this.panelId;
|
||||
}
|
||||
|
||||
private isPanelFocused(): boolean {
|
||||
const activeElement = document.activeElement;
|
||||
const panelPart = this.layoutService.getContainer(Parts.PANEL_PART);
|
||||
|
||||
return !!(this.isPanelActive() && activeElement && panelPart && isAncestor(activeElement, panelPart));
|
||||
}
|
||||
}
|
||||
|
||||
export const Extensions = {
|
||||
Panels: 'workbench.contributions.panels'
|
||||
};
|
||||
|
||||
@@ -42,6 +42,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Before2D } from 'vs/workbench/browser/dnd';
|
||||
|
||||
interface IPlaceholderViewlet {
|
||||
id: string;
|
||||
@@ -152,7 +153,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
||||
hidePart: () => this.layoutService.setSideBarHidden(true),
|
||||
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar,
|
||||
(id: string, focus?: boolean) => this.viewletService.openViewlet(id, focus),
|
||||
(from: string, to: string, before?: boolean) => this.compositeBar.move(from, to, before)
|
||||
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore)
|
||||
),
|
||||
compositeSize: 50,
|
||||
colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme),
|
||||
|
||||
@@ -23,7 +23,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
import { IComposite } from 'vs/workbench/common/composite';
|
||||
import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd';
|
||||
import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd';
|
||||
|
||||
export interface ICompositeBarItem {
|
||||
id: string;
|
||||
@@ -39,9 +39,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
private viewDescriptorService: IViewDescriptorService,
|
||||
private targetContainerLocation: ViewContainerLocation,
|
||||
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | undefined>,
|
||||
private moveComposite: (from: string, to: string, before?: boolean) => void,
|
||||
private moveComposite: (from: string, to: string, before?: Before2D) => void,
|
||||
) { }
|
||||
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: boolean): void {
|
||||
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: Before2D): void {
|
||||
const dragData = data.getData();
|
||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
|
||||
@@ -255,7 +255,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
},
|
||||
onDrop: (e: IDraggedCompositeData) => {
|
||||
const pinnedItems = this.getPinnedComposites();
|
||||
this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, false);
|
||||
this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, { horizontallyBefore: false, verticallyBefore: false });
|
||||
toggleClass(parent, 'dragged-over', false);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -18,7 +18,7 @@ import { DelayedDragHandler } from 'vs/base/browser/dnd';
|
||||
import { IActivity } from 'vs/workbench/common/activity';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd';
|
||||
import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
|
||||
export interface ICompositeActivity {
|
||||
@@ -516,7 +516,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
this.showContextMenu(container);
|
||||
}));
|
||||
|
||||
let insertDropBefore: boolean | undefined = undefined;
|
||||
let insertDropBefore: Before2D | undefined = undefined;
|
||||
// Allow to drag
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, () => { return { type: 'composite', id: this.activity.id }; }, {
|
||||
onDragOver: e => {
|
||||
@@ -534,7 +534,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
|
||||
onDrop: e => {
|
||||
dom.EventHelper.stop(e.eventData, true);
|
||||
this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, !!insertDropBefore);
|
||||
this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, insertDropBefore);
|
||||
insertDropBefore = this.updateFromDragging(container, false, e.eventData);
|
||||
},
|
||||
onDragStart: e => {
|
||||
@@ -563,7 +563,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
this.updateStyles();
|
||||
}
|
||||
|
||||
private updateFromDragging(element: HTMLElement, showFeedback: boolean, event: DragEvent): boolean | undefined {
|
||||
private updateFromDragging(element: HTMLElement, showFeedback: boolean, event: DragEvent): Before2D | undefined {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const posX = event.clientX;
|
||||
const posY = event.clientY;
|
||||
@@ -598,7 +598,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return top || left;
|
||||
return { verticallyBefore: top, horizontallyBefore: left };
|
||||
}
|
||||
|
||||
private showContextMenu(container: HTMLElement): void {
|
||||
|
||||
@@ -8,22 +8,24 @@ import { localize } from 'vs/nls';
|
||||
import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { IEditorGroupsService, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor, GroupIdentifier } from 'vs/workbench/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { prepareQuery, scoreItem, compareItemsByScore, ScorerCache } from 'vs/base/common/fuzzyScorer';
|
||||
import { prepareQuery, scoreItemFuzzy, compareItemsByFuzzyScore, FuzzyScorerCache } from 'vs/base/common/fuzzyScorer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
interface IEditorQuickPickItem extends IQuickPickItemWithResource, IEditorIdentifier, IPickerQuickAccessItem { }
|
||||
interface IEditorQuickPickItem extends IQuickPickItemWithResource, IPickerQuickAccessItem {
|
||||
groupId: GroupIdentifier;
|
||||
}
|
||||
|
||||
export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessProvider<IEditorQuickPickItem> {
|
||||
|
||||
private readonly pickState = new class {
|
||||
|
||||
scorerCache: ScorerCache = Object.create(null);
|
||||
scorerCache: FuzzyScorerCache = Object.create(null);
|
||||
isQuickNavigating: boolean | undefined = undefined;
|
||||
|
||||
reset(isQuickNavigating: boolean): void {
|
||||
@@ -45,7 +47,15 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService
|
||||
) {
|
||||
super(prefix, { canAcceptInBackground: true });
|
||||
super(prefix,
|
||||
{
|
||||
canAcceptInBackground: true,
|
||||
noResultsPick: {
|
||||
label: localize('noViewResults', "No matching editors"),
|
||||
groupId: -1
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
provide(picker: IQuickPick<IEditorQuickPickItem>, token: CancellationToken): IDisposable {
|
||||
@@ -67,7 +77,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
}
|
||||
|
||||
// Score on label and description
|
||||
const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
|
||||
const itemScore = scoreItemFuzzy(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
|
||||
if (!itemScore.score) {
|
||||
return false;
|
||||
}
|
||||
@@ -86,7 +96,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
return groups.indexOf(entryA.groupId) - groups.indexOf(entryB.groupId); // older groups first
|
||||
}
|
||||
|
||||
return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
|
||||
return compareItemsByFuzzyScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -113,16 +123,35 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
}
|
||||
|
||||
private doGetEditorPickItems(): Array<IEditorQuickPickItem> {
|
||||
const editors = this.doGetEditors();
|
||||
|
||||
const mapGroupIdToGroupAriaLabel = new Map<GroupIdentifier, string>();
|
||||
for (const { groupId } of editors) {
|
||||
if (!mapGroupIdToGroupAriaLabel.has(groupId)) {
|
||||
const group = this.editorGroupService.getGroup(groupId);
|
||||
if (group) {
|
||||
mapGroupIdToGroupAriaLabel.set(groupId, group.ariaLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.doGetEditors().map(({ editor, groupId }): IEditorQuickPickItem => {
|
||||
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
const isDirty = editor.isDirty() && !editor.isSaving();
|
||||
|
||||
return {
|
||||
editor,
|
||||
groupId,
|
||||
resource,
|
||||
label: editor.getName(),
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, editors picker", editor.getName()),
|
||||
ariaLabel: (() => {
|
||||
if (mapGroupIdToGroupAriaLabel.size > 1) {
|
||||
return isDirty ?
|
||||
localize('entryAriaLabelWithGroupDirty', "{0}, dirty, {1}", editor.getName(), mapGroupIdToGroupAriaLabel.get(groupId)) :
|
||||
localize('entryAriaLabelWithGroup', "{0}, {1}", editor.getName(), mapGroupIdToGroupAriaLabel.get(groupId));
|
||||
}
|
||||
|
||||
return isDirty ? localize('entryAriaLabelDirty', "{0}, dirty", editor.getName()) : editor.getName();
|
||||
})(),
|
||||
description: editor.getDescription(),
|
||||
iconClasses: getIconClasses(this.modelService, this.modeService, resource),
|
||||
italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor),
|
||||
|
||||
@@ -38,6 +38,7 @@ import { MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions';
|
||||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { Before2D } from 'vs/workbench/browser/dnd';
|
||||
|
||||
interface ICachedPanel {
|
||||
id: string;
|
||||
@@ -147,8 +148,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(),
|
||||
hidePart: () => this.layoutService.setPanelHidden(true),
|
||||
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel,
|
||||
(id: string, focus?: boolean) => <unknown>this.openPanel(id, focus) as Promise<IPaneComposite | undefined>, // {{SQL CARBON EDIT}} strict-null-checks
|
||||
(from: string, to: string, before?: boolean) => this.compositeBar.move(from, to, before)
|
||||
(id: string, focus?: boolean) => <unknown>this.openPanel(id, focus) as Promise<IPaneComposite | undefined>, // {{SQL CARBON EDIT}} strict-null-checks
|
||||
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.horizontallyBefore)
|
||||
),
|
||||
compositeSize: 0,
|
||||
overflowActionSize: 44,
|
||||
|
||||
@@ -428,7 +428,7 @@ export class CustomMenubarControl extends MenubarControl {
|
||||
return new Action('update.checking', nls.localize('checkingForUpdates', "Checking for Updates..."), undefined, false);
|
||||
|
||||
case StateType.AvailableForDownload:
|
||||
return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Now"), undefined, true, () =>
|
||||
return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Update"), undefined, true, () =>
|
||||
this.updateService.downloadUpdate());
|
||||
|
||||
case StateType.Downloading:
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
.monaco-pane-view .split-view-view:first-of-type > .pane > .pane-header {
|
||||
border-top: none !important; /* less clutter: do not show any border for first views in a pane */
|
||||
}
|
||||
.monaco-pane-view .split-view-view:first-of-type > .pane {
|
||||
border-left: none !important; /* less clutter: do not show any border for first views in a pane */
|
||||
}
|
||||
|
||||
.monaco-pane-view .pane > .pane-header {
|
||||
position: relative;
|
||||
@@ -24,10 +27,6 @@
|
||||
-webkit-margin-after: 0;
|
||||
}
|
||||
|
||||
.monaco-pane-view .pane > .pane-header h3.title:first-child {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
.monaco-pane-view .pane .monaco-progress-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
.monaco-workbench .pane > .pane-body > .welcome-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 20px 0 20px;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body:not(.welcome) > .welcome-view,
|
||||
@@ -69,6 +69,15 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body .welcome-view-content {
|
||||
padding: 0 20px 0 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane > .pane-body .welcome-view-content > *:last-child {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.customview-tree .monaco-list-row .monaco-tl-contents.align-icon-with-twisty::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ColorIdentifier, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, attachProgressBarStyler } 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, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
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, EDITOR_DRAG_AND_DROP_BACKGROUND, PANEL_BORDER } from 'vs/workbench/common/theme';
|
||||
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';
|
||||
@@ -47,12 +47,15 @@ import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { CompositeProgressIndicator } from 'vs/workbench/services/progress/browser/progressIndicator';
|
||||
import { IProgressIndicator } from 'vs/platform/progress/common/progress';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
|
||||
export interface IPaneColors extends IColorMapping {
|
||||
dropBackground?: ColorIdentifier;
|
||||
headerForeground?: ColorIdentifier;
|
||||
headerBackground?: ColorIdentifier;
|
||||
headerBorder?: ColorIdentifier;
|
||||
leftBorder?: ColorIdentifier;
|
||||
}
|
||||
|
||||
export interface IViewPaneOptions extends IPaneOptions {
|
||||
@@ -309,9 +312,20 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
this._onDidChangeTitleArea.fire();
|
||||
}
|
||||
|
||||
private scrollableElement!: DomScrollableElement;
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
this.bodyContainer = container;
|
||||
this.viewWelcomeContainer = append(container, $('.welcome-view', { tabIndex: 0 }));
|
||||
|
||||
const viewWelcomeContainer = append(container, $('.welcome-view'));
|
||||
this.viewWelcomeContainer = $('.welcome-view-content', { tabIndex: 0 });
|
||||
this.scrollableElement = this._register(new DomScrollableElement(this.viewWelcomeContainer, {
|
||||
alwaysConsumeMouseWheel: true,
|
||||
horizontal: ScrollbarVisibility.Hidden,
|
||||
vertical: ScrollbarVisibility.Visible,
|
||||
}));
|
||||
|
||||
append(viewWelcomeContainer, this.scrollableElement.getDomNode());
|
||||
|
||||
const onViewWelcomeChange = Event.any(this.viewWelcomeController.onDidChange, this.onDidChangeViewWelcomeState);
|
||||
this._register(onViewWelcomeChange(this.updateViewWelcome, this));
|
||||
@@ -319,7 +333,9 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
}
|
||||
|
||||
protected layoutBody(height: number, width: number): void {
|
||||
// noop
|
||||
this.viewWelcomeContainer.style.height = `${height}px`;
|
||||
this.viewWelcomeContainer.style.width = `${width}px`;
|
||||
this.scrollableElement.scanDomNode();
|
||||
}
|
||||
|
||||
getProgressIndicator() {
|
||||
@@ -410,6 +426,7 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
if (!this.shouldShowWelcome()) {
|
||||
removeClass(this.bodyContainer, 'welcome');
|
||||
this.viewWelcomeContainer.innerHTML = '';
|
||||
this.scrollableElement.scanDomNode();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -418,6 +435,7 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
if (contents.length === 0) {
|
||||
removeClass(this.bodyContainer, 'welcome');
|
||||
this.viewWelcomeContainer.innerHTML = '';
|
||||
this.scrollableElement.scanDomNode();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -437,47 +455,52 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
continue;
|
||||
}
|
||||
|
||||
const p = append(this.viewWelcomeContainer, $('p'));
|
||||
const linkedText = parseLinkedText(line);
|
||||
|
||||
for (const node of linkedText.nodes) {
|
||||
if (typeof node === 'string') {
|
||||
append(p, document.createTextNode(node));
|
||||
} else if (linkedText.nodes.length === 1) {
|
||||
const button = new Button(p, { title: node.title });
|
||||
button.label = node.label;
|
||||
button.onDidClick(_ => {
|
||||
this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href });
|
||||
this.openerService.open(node.href);
|
||||
}, null, disposables);
|
||||
disposables.add(button);
|
||||
disposables.add(attachButtonStyler(button, this.themeService));
|
||||
if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') {
|
||||
const node = linkedText.nodes[0];
|
||||
const button = new Button(this.viewWelcomeContainer, { title: node.title });
|
||||
button.label = node.label;
|
||||
button.onDidClick(_ => {
|
||||
this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href });
|
||||
this.openerService.open(node.href);
|
||||
}, null, disposables);
|
||||
disposables.add(button);
|
||||
disposables.add(attachButtonStyler(button, this.themeService));
|
||||
|
||||
if (preconditions) {
|
||||
const precondition = preconditions[buttonIndex];
|
||||
if (preconditions) {
|
||||
const precondition = preconditions[buttonIndex];
|
||||
|
||||
if (precondition) {
|
||||
const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition);
|
||||
updateEnablement();
|
||||
if (precondition) {
|
||||
const updateEnablement = () => button.enabled = this.contextKeyService.contextMatchesRules(precondition);
|
||||
updateEnablement();
|
||||
|
||||
const keys = new Set();
|
||||
precondition.keys().forEach(key => keys.add(key));
|
||||
const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys));
|
||||
onDidChangeContext(updateEnablement, null, disposables);
|
||||
}
|
||||
const keys = new Set();
|
||||
precondition.keys().forEach(key => keys.add(key));
|
||||
const onDidChangeContext = Event.filter(this.contextKeyService.onDidChangeContext, e => e.affectsSome(keys));
|
||||
onDidChangeContext(updateEnablement, null, disposables);
|
||||
}
|
||||
}
|
||||
|
||||
buttonIndex++;
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
append(p, link.el);
|
||||
disposables.add(link);
|
||||
disposables.add(attachLinkStyler(link, this.themeService));
|
||||
buttonIndex++;
|
||||
} else {
|
||||
const p = append(this.viewWelcomeContainer, $('p'));
|
||||
|
||||
for (const node of linkedText.nodes) {
|
||||
if (typeof node === 'string') {
|
||||
append(p, document.createTextNode(node));
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
append(p, link.el);
|
||||
disposables.add(link);
|
||||
disposables.add(attachLinkStyler(link, this.themeService));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.scrollableElement.scanDomNode();
|
||||
this.viewWelcomeDisposable = disposables;
|
||||
}
|
||||
|
||||
@@ -523,7 +546,7 @@ class ViewPaneDropOverlay extends Themable {
|
||||
|
||||
constructor(
|
||||
private paneElement: HTMLElement,
|
||||
private orientation: Orientation,
|
||||
private orientation: Orientation | undefined,
|
||||
protected themeService: IThemeService
|
||||
) {
|
||||
super(themeService);
|
||||
@@ -540,6 +563,7 @@ class ViewPaneDropOverlay extends Themable {
|
||||
// Container
|
||||
this.container = document.createElement('div');
|
||||
this.container.id = ViewPaneDropOverlay.OVERLAY_ID;
|
||||
this.container.style.top = '0px';
|
||||
|
||||
// Parent
|
||||
this.paneElement.appendChild(this.container);
|
||||
@@ -575,6 +599,7 @@ class ViewPaneDropOverlay extends Themable {
|
||||
|
||||
this.overlay.style.borderColor = activeContrastBorderColor || '';
|
||||
this.overlay.style.borderStyle = 'solid' || '';
|
||||
this.overlay.style.borderWidth = '0px';
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
@@ -629,7 +654,7 @@ class ViewPaneDropOverlay extends Themable {
|
||||
} else if (mousePosY >= splitHeightThreshold) {
|
||||
dropDirection = DropDirection.DOWN;
|
||||
}
|
||||
} else {
|
||||
} else if (this.orientation === Orientation.HORIZONTAL) {
|
||||
if (mousePosX < splitWidthThreshold) {
|
||||
dropDirection = DropDirection.LEFT;
|
||||
} else if (mousePosX >= splitWidthThreshold) {
|
||||
@@ -655,7 +680,12 @@ class ViewPaneDropOverlay extends Themable {
|
||||
this.doPositionOverlay({ top: '0', left: '0', width: '100%', height: '100%' });
|
||||
}
|
||||
|
||||
this.doUpdateOverlayBorder(dropDirection);
|
||||
if ((this.orientation === Orientation.VERTICAL && paneHeight <= 25) ||
|
||||
(this.orientation === Orientation.HORIZONTAL && paneWidth <= 25)) {
|
||||
this.doUpdateOverlayBorder(dropDirection);
|
||||
} else {
|
||||
this.doUpdateOverlayBorder(undefined);
|
||||
}
|
||||
|
||||
// Make sure the overlay is visible now
|
||||
this.overlay.style.opacity = '1';
|
||||
@@ -788,6 +818,71 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane)));
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e))));
|
||||
|
||||
let overlay: ViewPaneDropOverlay | undefined;
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {
|
||||
onDragEnter: (e) => {
|
||||
if (!overlay && this.panes.length === 0) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view') {
|
||||
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainer(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dropData.id);
|
||||
|
||||
if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay = new ViewPaneDropOverlay(parent, undefined, this.themeService);
|
||||
}
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
|
||||
const container = viewContainerRegistry.get(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
|
||||
|
||||
if (viewsToMove.length === 1 && viewsToMove[0].canMoveView) {
|
||||
overlay = new ViewPaneDropOverlay(parent, undefined, this.themeService);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
|
||||
const container = viewContainerRegistry.get(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewDescriptors(container).allViewDescriptors;
|
||||
|
||||
if (viewsToMove.length === 1 && viewsToMove[0].canMoveView) {
|
||||
dropData.type = 'view';
|
||||
dropData.id = viewsToMove[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
if (dropData.type === 'view') {
|
||||
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainer(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dropData.id);
|
||||
if (oldViewContainer !== this.viewContainer && viewDescriptor && viewDescriptor.canMoveView) {
|
||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], this.viewContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.onDidSashChange(() => this.saveViewSizes()));
|
||||
this.viewsModel.onDidAdd(added => this.onDidAddViewDescriptors(added));
|
||||
this.viewsModel.onDidRemove(removed => this.onDidRemoveViewDescriptors(removed));
|
||||
@@ -1143,6 +1238,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND,
|
||||
headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND,
|
||||
headerBorder: SIDE_BAR_SECTION_HEADER_BORDER,
|
||||
leftBorder: PANEL_BORDER,
|
||||
dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND
|
||||
}, pane);
|
||||
const disposable = combinedDisposable(onDidFocus, onDidChangeTitleArea, paneStyler, onDidChange, onDidChangeVisibility);
|
||||
|
||||
Reference in New Issue
Block a user