mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-14 23:18:36 +00:00
- support hiding title in a part (#294970)
* - support hiding title in a part - support can move views in workbench - support globalLeftToolbar in pane composite part * clean up * chat feedback * fix compilation
This commit is contained in:
committed by
GitHub
parent
14b8c701f1
commit
27abe96390
@@ -50,7 +50,7 @@ export abstract class Part<MementoType extends object = object> extends Componen
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
private options: IPartOptions,
|
||||
protected options: IPartOptions,
|
||||
themeService: IThemeService,
|
||||
storageService: IStorageService,
|
||||
protected readonly layoutService: IWorkbenchLayoutService
|
||||
|
||||
@@ -68,6 +68,7 @@ export class ActivitybarPart extends Part {
|
||||
private _isCompact: boolean;
|
||||
|
||||
constructor(
|
||||
private readonly location: ViewContainerLocation,
|
||||
private readonly paneCompositePart: IPaneCompositePart,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@@ -117,7 +118,7 @@ export class ActivitybarPart extends Part {
|
||||
const actionHeight = this._isCompact ? ActivitybarPart.COMPACT_ACTION_HEIGHT : ActivitybarPart.ACTION_HEIGHT;
|
||||
const iconSize = this._isCompact ? ActivitybarPart.COMPACT_ICON_SIZE : ActivitybarPart.ICON_SIZE;
|
||||
|
||||
return this.instantiationService.createInstance(ActivityBarCompositeBar, {
|
||||
return this.instantiationService.createInstance(ActivityBarCompositeBar, this.location, {
|
||||
partContainerClass: 'activitybar',
|
||||
pinnedViewContainersKey: ActivitybarPart.pinnedViewContainersKey,
|
||||
placeholderViewContainersKey: ActivitybarPart.placeholderViewContainersKey,
|
||||
@@ -251,6 +252,7 @@ export class ActivityBarCompositeBar extends PaneCompositeBar {
|
||||
private readonly keyboardNavigationDisposables = this._register(new DisposableStore());
|
||||
|
||||
constructor(
|
||||
location: ViewContainerLocation,
|
||||
options: IPaneCompositeBarOptions,
|
||||
part: Parts,
|
||||
paneCompositePart: IPaneCompositePart,
|
||||
@@ -266,13 +268,14 @@ export class ActivityBarCompositeBar extends PaneCompositeBar {
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
) {
|
||||
super({
|
||||
...options,
|
||||
fillExtraContextMenuActions: (actions, e) => {
|
||||
options.fillExtraContextMenuActions(actions, e);
|
||||
this.fillContextMenuActions(actions, e);
|
||||
}
|
||||
}, part, paneCompositePart, instantiationService, storageService, extensionService, viewDescriptorService, viewService, contextKeyService, environmentService, layoutService);
|
||||
super(location,
|
||||
{
|
||||
...options,
|
||||
fillExtraContextMenuActions: (actions, e) => {
|
||||
options.fillExtraContextMenuActions(actions, e);
|
||||
this.fillContextMenuActions(actions, e);
|
||||
}
|
||||
}, part, paneCompositePart, instantiationService, storageService, extensionService, viewDescriptorService, viewService, contextKeyService, environmentService, layoutService);
|
||||
|
||||
if (showGlobalActivities) {
|
||||
this.globalCompositeBar = this._register(instantiationService.createInstance(GlobalCompositeBar, () => this.getContextMenuActions(), (theme: IColorTheme) => this.options.colors(theme), this.options.activityHoverOptions));
|
||||
|
||||
@@ -33,6 +33,7 @@ import { IConfigurationService } from '../../../../platform/configuration/common
|
||||
import { getContextMenuActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { VisibleViewContainersTracker } from '../visibleViewContainersTracker.js';
|
||||
import { Extensions } from '../../panecomposite.js';
|
||||
|
||||
interface IAuxiliaryBarPartConfiguration {
|
||||
position: ActivityBarPosition;
|
||||
@@ -110,6 +111,9 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
|
||||
'auxiliarybar',
|
||||
undefined,
|
||||
SIDE_BAR_TITLE_BORDER,
|
||||
ViewContainerLocation.AuxiliaryBar,
|
||||
Extensions.Auxiliary,
|
||||
MenuId.AuxiliaryBarTitle,
|
||||
notificationService,
|
||||
storageService,
|
||||
contextMenuService,
|
||||
|
||||
@@ -257,8 +257,9 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
show(compositeContainer);
|
||||
|
||||
// Setup action runner
|
||||
const toolBar = assertReturnsDefined(this.toolBar);
|
||||
toolBar.actionRunner = composite.getActionRunner();
|
||||
if (this.toolBar) {
|
||||
this.toolBar.actionRunner = composite.getActionRunner();
|
||||
}
|
||||
|
||||
// Update title with composite title if it differs from descriptor
|
||||
const descriptor = this.registry.getComposite(composite.getId());
|
||||
@@ -275,13 +276,15 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
actionsBinding();
|
||||
|
||||
// Action Run Handling
|
||||
this.actionsListener.value = toolBar.actionRunner.onDidRun(e => {
|
||||
if (this.toolBar) {
|
||||
this.actionsListener.value = this.toolBar.actionRunner.onDidRun(e => {
|
||||
|
||||
// Check for Error
|
||||
if (e.error && !isCancellationError(e.error)) {
|
||||
this.notificationService.error(e.error);
|
||||
}
|
||||
});
|
||||
// Check for Error
|
||||
if (e.error && !isCancellationError(e.error)) {
|
||||
this.notificationService.error(e.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Indicate to composite that it is now visible
|
||||
composite.setVisible(true);
|
||||
@@ -338,8 +341,7 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
|
||||
this.titleLabel.updateTitle(compositeId, compositeTitle, keybinding?.getLabel() ?? undefined);
|
||||
|
||||
const toolBar = assertReturnsDefined(this.toolBar);
|
||||
toolBar.setAriaLabel(localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle));
|
||||
this.toolBar?.setAriaLabel(localize('ariaCompositeToolbarLabel', "{0} actions", compositeTitle));
|
||||
}
|
||||
|
||||
private collectCompositeActions(composite?: Composite): () => void {
|
||||
@@ -350,12 +352,13 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
const secondaryActions: IAction[] = composite?.getSecondaryActions().slice(0) || [];
|
||||
|
||||
// Update context
|
||||
const toolBar = assertReturnsDefined(this.toolBar);
|
||||
toolBar.context = this.actionsContextProvider();
|
||||
if (this.toolBar) {
|
||||
this.toolBar.context = this.actionsContextProvider();
|
||||
}
|
||||
|
||||
// Return fn to set into toolbar
|
||||
return () => {
|
||||
toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions), menuIds);
|
||||
this.toolBar?.setActions(prepareActions(primaryActions), prepareActions(secondaryActions), menuIds);
|
||||
this.titleArea?.classList.toggle('has-actions', primaryActions.length > 0 || secondaryActions.length > 0);
|
||||
};
|
||||
}
|
||||
@@ -399,7 +402,10 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
return composite;
|
||||
}
|
||||
|
||||
protected override createTitleArea(parent: HTMLElement): HTMLElement {
|
||||
protected override createTitleArea(parent: HTMLElement): HTMLElement | undefined {
|
||||
if (!this.options.hasTitle) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Title Area Container
|
||||
const titleArea = append(parent, $('.composite'));
|
||||
@@ -463,9 +469,8 @@ export abstract class CompositePart<T extends Composite, MementoType extends obj
|
||||
override updateStyles(): void {
|
||||
super.updateStyles();
|
||||
|
||||
// Forward to title label
|
||||
const titleLabel = assertReturnsDefined(this.titleLabel);
|
||||
titleLabel.updateStyles();
|
||||
// Forward to title label if present
|
||||
this.titleLabel?.updateStyles();
|
||||
}
|
||||
|
||||
protected actionViewItemProvider(action: IAction, options: IBaseActionViewItemOptions): IActionViewItem | undefined {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .pane-composite-part > .title.has-composite-bar > .title-actions .monaco-action-bar .action-item,
|
||||
.monaco-workbench .pane-composite-part > .title.has-composite-bar > .global-actions .monaco-action-bar .action-item {
|
||||
.monaco-workbench .pane-composite-part > .title.has-composite-bar > .global-actions .monaco-action-bar .action-item,
|
||||
.monaco-workbench .pane-composite-part > .title.has-composite-bar > .global-actions-left .monaco-action-bar .action-item {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
@@ -16,6 +17,13 @@
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* Global left actions toolbar: rendered first visually via CSS order */
|
||||
.monaco-workbench .pane-composite-part > .title > .global-actions-left {
|
||||
order: -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monaco-workbench .pane-composite-part > .title.has-composite-bar > .title-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ export interface IPaneCompositeBarOptions {
|
||||
export class PaneCompositeBar extends Disposable {
|
||||
|
||||
private readonly viewContainerDisposables = this._register(new DisposableMap<string, IDisposable>());
|
||||
private readonly location: ViewContainerLocation;
|
||||
|
||||
private readonly compositeBar: CompositeBar;
|
||||
readonly dndHandler: ICompositeDragAndDrop;
|
||||
@@ -97,6 +96,7 @@ export class PaneCompositeBar extends Disposable {
|
||||
private hasExtensionsRegistered: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly location: ViewContainerLocation,
|
||||
protected readonly options: IPaneCompositeBarOptions,
|
||||
protected readonly part: Parts,
|
||||
private readonly paneCompositePart: IPaneCompositePart,
|
||||
@@ -111,10 +111,6 @@ export class PaneCompositeBar extends Disposable {
|
||||
) {
|
||||
super();
|
||||
|
||||
this.location = paneCompositePart.partId === Parts.PANEL_PART
|
||||
? ViewContainerLocation.Panel : paneCompositePart.partId === Parts.AUXILIARYBAR_PART
|
||||
? ViewContainerLocation.AuxiliaryBar : ViewContainerLocation.Sidebar;
|
||||
|
||||
this.dndHandler = new CompositeDragAndDrop(this.viewDescriptorService, this.location, this.options.orientation,
|
||||
async (id: string, focus?: boolean) => { return await this.paneCompositePart.openPaneComposite(id, focus) ?? null; },
|
||||
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, this.options.orientation === ActionsOrientation.VERTICAL ? before?.verticallyBefore : before?.horizontallyBefore),
|
||||
|
||||
@@ -7,7 +7,7 @@ import './media/paneCompositePart.css';
|
||||
import { Event } from '../../../base/common/event.js';
|
||||
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
|
||||
import { IProgressIndicator } from '../../../platform/progress/common/progress.js';
|
||||
import { Extensions, PaneComposite, PaneCompositeDescriptor, PaneCompositeRegistry } from '../panecomposite.js';
|
||||
import { PaneComposite, PaneCompositeDescriptor, PaneCompositeRegistry } from '../panecomposite.js';
|
||||
import { IPaneComposite } from '../../common/panecomposite.js';
|
||||
import { IViewDescriptorService, ViewContainerLocation } from '../../common/views.js';
|
||||
import { DisposableStore, MutableDisposable } from '../../../base/common/lifecycle.js';
|
||||
@@ -117,7 +117,6 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
get onDidPaneCompositeOpen(): Event<IPaneComposite> { return Event.map(this.onDidCompositeOpen.event, compositeEvent => <IPaneComposite>compositeEvent.composite); }
|
||||
readonly onDidPaneCompositeClose = this.onDidCompositeClose.event as Event<IPaneComposite>;
|
||||
|
||||
private readonly location: ViewContainerLocation;
|
||||
private titleContainer: HTMLElement | undefined;
|
||||
private headerFooterCompositeBarContainer: HTMLElement | undefined;
|
||||
protected readonly headerFooterCompositeBarDispoables = this._register(new DisposableStore());
|
||||
@@ -126,8 +125,8 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
private compositeBarPosition: CompositeBarPosition | undefined = undefined;
|
||||
private emptyPaneMessageElement: HTMLElement | undefined;
|
||||
|
||||
private readonly globalActionsMenuId: MenuId;
|
||||
private globalToolBar: MenuWorkbenchToolBar | undefined;
|
||||
private globalLeftToolBar: MenuWorkbenchToolBar | undefined;
|
||||
|
||||
private blockOpening: DeferredPromise<PaneComposite | undefined> | undefined = undefined;
|
||||
protected contentDimension: Dimension | undefined;
|
||||
@@ -142,6 +141,9 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
compositeCSSClass: string,
|
||||
titleForegroundColor: string | undefined,
|
||||
titleBorderColor: string | undefined,
|
||||
protected readonly location: ViewContainerLocation,
|
||||
registryId: string,
|
||||
private readonly globalActionsMenuId: MenuId,
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@@ -155,18 +157,6 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IMenuService protected readonly menuService: IMenuService,
|
||||
) {
|
||||
let location = ViewContainerLocation.Sidebar;
|
||||
let registryId = Extensions.Viewlets;
|
||||
let globalActionsMenuId = MenuId.SidebarTitle;
|
||||
if (partId === Parts.PANEL_PART) {
|
||||
location = ViewContainerLocation.Panel;
|
||||
registryId = Extensions.Panels;
|
||||
globalActionsMenuId = MenuId.PanelTitle;
|
||||
} else if (partId === Parts.AUXILIARYBAR_PART) {
|
||||
location = ViewContainerLocation.AuxiliaryBar;
|
||||
registryId = Extensions.Auxiliary;
|
||||
globalActionsMenuId = MenuId.AuxiliaryBarTitle;
|
||||
}
|
||||
super(
|
||||
notificationService,
|
||||
storageService,
|
||||
@@ -186,9 +176,6 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
partId,
|
||||
partOptions
|
||||
);
|
||||
|
||||
this.location = location;
|
||||
this.globalActionsMenuId = globalActionsMenuId;
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
@@ -283,63 +270,68 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
this.emptyPaneMessageElement!.style.backgroundColor = backgroundColor;
|
||||
};
|
||||
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(this.element, {
|
||||
onDragOver: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
if (this.paneCompositeBar.value) {
|
||||
const validDropTarget = this.paneCompositeBar.value.dndHandler.onDragEnter(e.dragAndDropData, undefined, e.eventData);
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', validDropTarget);
|
||||
}
|
||||
},
|
||||
onDragEnter: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
if (this.paneCompositeBar.value) {
|
||||
const validDropTarget = this.paneCompositeBar.value.dndHandler.onDragEnter(e.dragAndDropData, undefined, e.eventData);
|
||||
setDropBackgroundFeedback(validDropTarget);
|
||||
}
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
},
|
||||
onDragEnd: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
},
|
||||
onDrop: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
if (this.paneCompositeBar.value) {
|
||||
this.paneCompositeBar.value.dndHandler.drop(e.dragAndDropData, undefined, e.eventData);
|
||||
} else {
|
||||
// Allow opening views/composites if the composite bar is hidden
|
||||
const dragData = e.dragAndDropData.getData();
|
||||
|
||||
if (dragData.type === 'composite') {
|
||||
const currentContainer = this.viewDescriptorService.getViewContainerById(dragData.id)!;
|
||||
this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.location, undefined, 'dnd');
|
||||
this.openPaneComposite(currentContainer.id, true);
|
||||
if (this.viewDescriptorService.canMoveViews()) {
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(this.element, {
|
||||
onDragOver: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
if (this.paneCompositeBar.value) {
|
||||
const validDropTarget = this.paneCompositeBar.value.dndHandler.onDragEnter(e.dragAndDropData, undefined, e.eventData);
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', validDropTarget);
|
||||
}
|
||||
},
|
||||
onDragEnter: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
if (this.paneCompositeBar.value) {
|
||||
const validDropTarget = this.paneCompositeBar.value.dndHandler.onDragEnter(e.dragAndDropData, undefined, e.eventData);
|
||||
setDropBackgroundFeedback(validDropTarget);
|
||||
}
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
},
|
||||
onDragEnd: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
},
|
||||
onDrop: (e) => {
|
||||
EventHelper.stop(e.eventData, true);
|
||||
setDropBackgroundFeedback(false);
|
||||
if (this.paneCompositeBar.value) {
|
||||
this.paneCompositeBar.value.dndHandler.drop(e.dragAndDropData, undefined, e.eventData);
|
||||
} else {
|
||||
// Allow opening views/composites if the composite bar is hidden
|
||||
const dragData = e.dragAndDropData.getData();
|
||||
|
||||
else if (dragData.type === 'view') {
|
||||
const viewToMove = this.viewDescriptorService.getViewDescriptorById(dragData.id)!;
|
||||
if (viewToMove.canMoveView) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewToMove, this.location, 'dnd');
|
||||
if (dragData.type === 'composite') {
|
||||
const currentContainer = this.viewDescriptorService.getViewContainerById(dragData.id)!;
|
||||
this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.location, undefined, 'dnd');
|
||||
this.openPaneComposite(currentContainer.id, true);
|
||||
}
|
||||
|
||||
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
|
||||
else if (dragData.type === 'view') {
|
||||
const viewToMove = this.viewDescriptorService.getViewDescriptorById(dragData.id)!;
|
||||
if (viewToMove.canMoveView) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewToMove, this.location, 'dnd');
|
||||
|
||||
this.openPaneComposite(newContainer.id, true).then(composite => {
|
||||
composite?.openView(viewToMove.id, true);
|
||||
});
|
||||
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
|
||||
|
||||
this.openPaneComposite(newContainer.id, true).then(composite => {
|
||||
composite?.openView(viewToMove.id, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}));
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
protected override createTitleArea(parent: HTMLElement): HTMLElement {
|
||||
protected override createTitleArea(parent: HTMLElement): HTMLElement | undefined {
|
||||
const titleArea = super.createTitleArea(parent);
|
||||
if (!titleArea) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this._register(addDisposableListener(titleArea, EventType.CONTEXT_MENU, e => {
|
||||
this.onTitleAreaContextMenu(new StandardMouseEvent(getWindow(titleArea), e));
|
||||
@@ -349,6 +341,26 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
this.onTitleAreaContextMenu(new StandardMouseEvent(getWindow(titleArea), e));
|
||||
}));
|
||||
|
||||
// Global Left Actions Toolbar (optional, subclasses provide a menu ID)
|
||||
const globalLeftActionsMenuId = this.getGlobalLeftActionsMenuId();
|
||||
if (globalLeftActionsMenuId) {
|
||||
const globalLeftTitleActionsContainer = titleArea.appendChild($('.global-actions-left'));
|
||||
this.globalLeftToolBar = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar,
|
||||
globalLeftTitleActionsContainer,
|
||||
globalLeftActionsMenuId,
|
||||
{
|
||||
actionViewItemProvider: (action, options) => this.actionViewItemProvider(action, options),
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
|
||||
anchorAlignmentProvider: () => this.getTitleAreaDropDownAnchorAlignment(),
|
||||
hoverDelegate: this.toolbarHoverDelegate,
|
||||
hiddenItemStrategy: HiddenItemStrategy.NoHide,
|
||||
highlightToggledItems: false,
|
||||
telemetrySource: this.nameForTelemetry
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
const globalTitleActionsContainer = titleArea.appendChild($('.global-actions'));
|
||||
|
||||
// Global Actions Toolbar
|
||||
@@ -375,7 +387,7 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
this.titleContainer = parent;
|
||||
|
||||
const titleLabel = super.createTitleLabel(parent);
|
||||
this.titleLabelElement!.draggable = true;
|
||||
this.titleLabelElement!.draggable = this.viewDescriptorService.canMoveViews();
|
||||
const draggedItemProvider = (): { type: 'view' | 'composite'; id: string } => {
|
||||
const activeViewlet = this.getActivePaneComposite()!;
|
||||
return { type: 'composite', id: activeViewlet.getId() };
|
||||
@@ -489,7 +501,7 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
}
|
||||
|
||||
protected createCompositeBar(): PaneCompositeBar {
|
||||
return this.instantiationService.createInstance(PaneCompositeBar, this.getCompositeBarOptions(), this.partId, this);
|
||||
return this.instantiationService.createInstance(PaneCompositeBar, this.location, this.getCompositeBarOptions(), this.partId, this);
|
||||
}
|
||||
|
||||
protected override onTitleAreaUpdate(compositeId: string): void {
|
||||
@@ -642,7 +654,8 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
// Each toolbar item has 4px margin
|
||||
const toolBarWidth = this.toolBar.getItemsWidth() + this.toolBar.getItemsLength() * 4;
|
||||
const globalToolBarWidth = this.globalToolBar ? this.globalToolBar.getItemsWidth() + this.globalToolBar.getItemsLength() * 4 : 0;
|
||||
return toolBarWidth + globalToolBarWidth + 8; // 8px padding left
|
||||
const globalLeftToolBarWidth = this.globalLeftToolBar ? this.globalLeftToolBar.getItemsWidth() + this.globalLeftToolBar.getItemsLength() * 4 : 0;
|
||||
return toolBarWidth + globalToolBarWidth + globalLeftToolBarWidth + 8; // 8px padding left
|
||||
}
|
||||
|
||||
private onTitleAreaContextMenu(event: StandardMouseEvent): void {
|
||||
@@ -694,6 +707,14 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override in subclasses to provide a menu ID for a global toolbar on the left side
|
||||
* of the composite bar / title area. Returns `undefined` by default (no left toolbar).
|
||||
*/
|
||||
protected getGlobalLeftActionsMenuId(): MenuId | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
protected abstract shouldShowCompositeBar(): boolean;
|
||||
protected abstract getCompositeBarOptions(): IPaneCompositeBarOptions;
|
||||
protected abstract getCompositeBarPosition(): CompositeBarPosition;
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Dimension } from '../../../../base/browser/dom.js';
|
||||
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { assertReturnsDefined } from '../../../../base/common/types.js';
|
||||
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
|
||||
import { IViewDescriptorService } from '../../../common/views.js';
|
||||
import { IViewDescriptorService, ViewContainerLocation } from '../../../common/views.js';
|
||||
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
|
||||
import { IMenuService, MenuId } from '../../../../platform/actions/common/actions.js';
|
||||
import { AbstractPaneCompositePart, CompositeBarPosition } from '../paneCompositePart.js';
|
||||
@@ -31,6 +31,7 @@ import { getContextMenuActions } from '../../../../platform/actions/browser/menu
|
||||
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { Extensions } from '../../panecomposite.js';
|
||||
|
||||
export class PanelPart extends AbstractPaneCompositePart {
|
||||
|
||||
@@ -92,6 +93,9 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
'panel',
|
||||
undefined,
|
||||
PANEL_TITLE_BORDER,
|
||||
ViewContainerLocation.Panel,
|
||||
Extensions.Panels,
|
||||
MenuId.PanelTitle,
|
||||
notificationService,
|
||||
storageService,
|
||||
contextMenuService,
|
||||
|
||||
@@ -27,12 +27,13 @@ import { ActionsOrientation } from '../../../../base/browser/ui/actionbar/action
|
||||
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
|
||||
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { Action2, IMenuService, registerAction2 } from '../../../../platform/actions/common/actions.js';
|
||||
import { Action2, IMenuService, MenuId, registerAction2 } from '../../../../platform/actions/common/actions.js';
|
||||
import { Separator } from '../../../../base/common/actions.js';
|
||||
import { ToggleActivityBarVisibilityActionId } from '../../actions/layoutActions.js';
|
||||
import { localize2 } from '../../../../nls.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { VisibleViewContainersTracker } from '../visibleViewContainersTracker.js';
|
||||
import { Extensions } from '../../panecomposite.js';
|
||||
|
||||
export class SidebarPart extends AbstractPaneCompositePart {
|
||||
|
||||
@@ -63,7 +64,7 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
return Math.max(width, 300);
|
||||
}
|
||||
|
||||
private readonly activityBarPart = this._register(this.instantiationService.createInstance(ActivitybarPart, this));
|
||||
private readonly activityBarPart = this._register(this.instantiationService.createInstance(ActivitybarPart, this.location, this));
|
||||
private readonly visibleViewContainersTracker: VisibleViewContainersTracker;
|
||||
|
||||
//#endregion
|
||||
@@ -93,6 +94,9 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
'viewlet',
|
||||
SIDE_BAR_TITLE_FOREGROUND,
|
||||
SIDE_BAR_TITLE_BORDER,
|
||||
ViewContainerLocation.Sidebar,
|
||||
Extensions.Viewlets,
|
||||
MenuId.SidebarTitle,
|
||||
notificationService,
|
||||
storageService,
|
||||
contextMenuService,
|
||||
@@ -186,7 +190,7 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
}
|
||||
|
||||
protected override createCompositeBar(): ActivityBarCompositeBar {
|
||||
return this.instantiationService.createInstance(ActivityBarCompositeBar, this.getCompositeBarOptions(), this.partId, this, false);
|
||||
return this.instantiationService.createInstance(ActivityBarCompositeBar, ViewContainerLocation.Sidebar, this.getCompositeBarOptions(), this.partId, this, false);
|
||||
}
|
||||
|
||||
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
|
||||
|
||||
@@ -421,94 +421,96 @@ export class ViewPaneContainer<MementoType extends object = object> extends Comp
|
||||
|
||||
let bounds: BoundingRect;
|
||||
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {
|
||||
onDragEnter: (e) => {
|
||||
bounds = getOverlayBounds();
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
if (!overlay && inBounds(bounds, e.eventData)) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view') {
|
||||
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
|
||||
if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView || this.viewContainer.rejectAddedViews)) {
|
||||
return;
|
||||
}
|
||||
|
||||
overlay = new ViewPaneDropOverlay(parent, undefined, bounds, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
if (this.viewDescriptorService.canMoveViews()) {
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {
|
||||
onDragEnter: (e) => {
|
||||
bounds = getOverlayBounds();
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
if (!overlay && inBounds(bounds, e.eventData)) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view') {
|
||||
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
|
||||
if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView || this.viewContainer.rejectAddedViews)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!viewsToMove.some(v => !v.canMoveView) && viewsToMove.length > 0) {
|
||||
overlay = new ViewPaneDropOverlay(parent, undefined, bounds, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragOver: (e) => {
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
if (overlay && !inBounds(bounds, e.eventData)) {
|
||||
overlay.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
|
||||
if (inBounds(bounds, e.eventData)) {
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', overlay !== undefined);
|
||||
}
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
const viewsToMove: IViewDescriptor[] = [];
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
if (!allViews.some(v => !v.canMoveView)) {
|
||||
viewsToMove.push(...allViews);
|
||||
}
|
||||
} else if (dropData.type === 'view') {
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
if (oldViewContainer !== this.viewContainer && viewDescriptor?.canMoveView) {
|
||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
}
|
||||
|
||||
const paneCount = this.panes.length;
|
||||
|
||||
if (viewsToMove.length > 0) {
|
||||
this.viewDescriptorService.moveViewsToContainer(viewsToMove, this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
|
||||
if (paneCount > 0) {
|
||||
for (const view of viewsToMove) {
|
||||
const paneToMove = this.panes.find(p => p.id === view.id);
|
||||
if (paneToMove) {
|
||||
this.movePane(paneToMove, this.panes[this.panes.length - 1]);
|
||||
if (!viewsToMove.some(v => !v.canMoveView) && viewsToMove.length > 0) {
|
||||
overlay = new ViewPaneDropOverlay(parent, undefined, bounds, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragOver: (e) => {
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
if (overlay && !inBounds(bounds, e.eventData)) {
|
||||
overlay.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
if (inBounds(bounds, e.eventData)) {
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', overlay !== undefined);
|
||||
}
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
const viewsToMove: IViewDescriptor[] = [];
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
if (!allViews.some(v => !v.canMoveView)) {
|
||||
viewsToMove.push(...allViews);
|
||||
}
|
||||
} else if (dropData.type === 'view') {
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
if (oldViewContainer !== this.viewContainer && viewDescriptor?.canMoveView) {
|
||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
}
|
||||
|
||||
const paneCount = this.panes.length;
|
||||
|
||||
if (viewsToMove.length > 0) {
|
||||
this.viewDescriptorService.moveViewsToContainer(viewsToMove, this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
|
||||
if (paneCount > 0) {
|
||||
for (const view of viewsToMove) {
|
||||
const paneToMove = this.panes.find(p => p.id === view.id);
|
||||
if (paneToMove) {
|
||||
this.movePane(paneToMove, this.panes[this.panes.length - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(this.onDidSashChange(() => this.saveViewSizes()));
|
||||
this._register(this.viewContainerModel.onDidAddVisibleViewDescriptors(added => this.onDidAddViewDescriptors(added)));
|
||||
@@ -874,111 +876,82 @@ export class ViewPaneContainer<MementoType extends object = object> extends Comp
|
||||
|
||||
let overlay: ViewPaneDropOverlay | undefined;
|
||||
|
||||
if (pane.draggableElement) {
|
||||
store.add(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, () => { return { type: 'view', id: pane.id }; }, {}));
|
||||
}
|
||||
if (this.viewDescriptorService.canMoveViews()) {
|
||||
|
||||
store.add(CompositeDragAndDropObserver.INSTANCE.registerTarget(pane.dropTargetElement, {
|
||||
onDragEnter: (e) => {
|
||||
if (!overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view' && dropData.id !== pane.id) {
|
||||
if (pane.draggableElement) {
|
||||
store.add(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, () => { return { type: 'view', id: pane.id }; }, {}));
|
||||
}
|
||||
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
store.add(CompositeDragAndDropObserver.INSTANCE.registerTarget(pane.dropTargetElement, {
|
||||
onDragEnter: (e) => {
|
||||
if (!overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view' && dropData.id !== pane.id) {
|
||||
|
||||
if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView || this.viewContainer.rejectAddedViews)) {
|
||||
return;
|
||||
}
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
|
||||
overlay = new ViewPaneDropOverlay(pane.dropTargetElement, this.orientation ?? Orientation.VERTICAL, undefined, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
}
|
||||
if (oldViewContainer !== this.viewContainer && (!viewDescriptor || !viewDescriptor.canMoveView || this.viewContainer.rejectAddedViews)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id && !this.viewContainer.rejectAddedViews) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
|
||||
if (!viewsToMove.some(v => !v.canMoveView) && viewsToMove.length > 0) {
|
||||
overlay = new ViewPaneDropOverlay(pane.dropTargetElement, this.orientation ?? Orientation.VERTICAL, undefined, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragOver: (e) => {
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', overlay !== undefined);
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
const viewsToMove: IViewDescriptor[] = [];
|
||||
let anchorView: IViewDescriptor | undefined;
|
||||
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id && !this.viewContainer.rejectAddedViews) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id && !this.viewContainer.rejectAddedViews) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const viewsToMove = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
|
||||
if (allViews.length > 0 && !allViews.some(v => !v.canMoveView)) {
|
||||
viewsToMove.push(...allViews);
|
||||
anchorView = allViews[0];
|
||||
}
|
||||
} else if (dropData.type === 'view') {
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
if (oldViewContainer !== this.viewContainer && viewDescriptor && viewDescriptor.canMoveView && !this.viewContainer.rejectAddedViews) {
|
||||
viewsToMove.push(viewDescriptor);
|
||||
}
|
||||
|
||||
if (viewDescriptor) {
|
||||
anchorView = viewDescriptor;
|
||||
if (!viewsToMove.some(v => !v.canMoveView) && viewsToMove.length > 0) {
|
||||
overlay = new ViewPaneDropOverlay(pane.dropTargetElement, this.orientation ?? Orientation.VERTICAL, undefined, this.viewDescriptorService.getViewContainerLocation(this.viewContainer)!, this.themeService);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragOver: (e) => {
|
||||
toggleDropEffect(e.eventData.dataTransfer, 'move', overlay !== undefined);
|
||||
},
|
||||
onDragLeave: (e) => {
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
},
|
||||
onDrop: (e) => {
|
||||
if (overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
const viewsToMove: IViewDescriptor[] = [];
|
||||
let anchorView: IViewDescriptor | undefined;
|
||||
|
||||
if (viewsToMove) {
|
||||
this.viewDescriptorService.moveViewsToContainer(viewsToMove, this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
if (dropData.type === 'composite' && dropData.id !== this.viewContainer.id && !this.viewContainer.rejectAddedViews) {
|
||||
const container = this.viewDescriptorService.getViewContainerById(dropData.id)!;
|
||||
const allViews = this.viewDescriptorService.getViewContainerModel(container).allViewDescriptors;
|
||||
|
||||
if (anchorView) {
|
||||
if (overlay.currentDropOperation === DropDirection.DOWN ||
|
||||
overlay.currentDropOperation === DropDirection.RIGHT) {
|
||||
if (allViews.length > 0 && !allViews.some(v => !v.canMoveView)) {
|
||||
viewsToMove.push(...allViews);
|
||||
anchorView = allViews[0];
|
||||
}
|
||||
} else if (dropData.type === 'view') {
|
||||
const oldViewContainer = this.viewDescriptorService.getViewContainerByViewId(dropData.id);
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(dropData.id);
|
||||
if (oldViewContainer !== this.viewContainer && viewDescriptor && viewDescriptor.canMoveView && !this.viewContainer.rejectAddedViews) {
|
||||
viewsToMove.push(viewDescriptor);
|
||||
}
|
||||
|
||||
const fromIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
let toIndex = this.panes.findIndex(p => p.id === pane.id);
|
||||
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (fromIndex > toIndex) {
|
||||
toIndex++;
|
||||
}
|
||||
|
||||
if (toIndex < this.panes.length && toIndex !== fromIndex) {
|
||||
this.movePane(this.panes[fromIndex], this.panes[toIndex]);
|
||||
}
|
||||
if (viewDescriptor) {
|
||||
anchorView = viewDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlay.currentDropOperation === DropDirection.UP ||
|
||||
overlay.currentDropOperation === DropDirection.LEFT) {
|
||||
const fromIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
let toIndex = this.panes.findIndex(p => p.id === pane.id);
|
||||
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (fromIndex < toIndex) {
|
||||
toIndex--;
|
||||
}
|
||||
|
||||
if (toIndex >= 0 && toIndex !== fromIndex) {
|
||||
this.movePane(this.panes[fromIndex], this.panes[toIndex]);
|
||||
}
|
||||
}
|
||||
if (viewsToMove) {
|
||||
this.viewDescriptorService.moveViewsToContainer(viewsToMove, this.viewContainer, undefined, 'dnd');
|
||||
}
|
||||
|
||||
if (viewsToMove.length > 1) {
|
||||
viewsToMove.slice(1).forEach(view => {
|
||||
let toIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
const fromIndex = this.panes.findIndex(p => p.id === view.id);
|
||||
if (anchorView) {
|
||||
if (overlay.currentDropOperation === DropDirection.DOWN ||
|
||||
overlay.currentDropOperation === DropDirection.RIGHT) {
|
||||
|
||||
const fromIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
let toIndex = this.panes.findIndex(p => p.id === pane.id);
|
||||
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (fromIndex > toIndex) {
|
||||
toIndex++;
|
||||
@@ -986,18 +959,50 @@ export class ViewPaneContainer<MementoType extends object = object> extends Comp
|
||||
|
||||
if (toIndex < this.panes.length && toIndex !== fromIndex) {
|
||||
this.movePane(this.panes[fromIndex], this.panes[toIndex]);
|
||||
anchorView = view;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (overlay.currentDropOperation === DropDirection.UP ||
|
||||
overlay.currentDropOperation === DropDirection.LEFT) {
|
||||
const fromIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
let toIndex = this.panes.findIndex(p => p.id === pane.id);
|
||||
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (fromIndex < toIndex) {
|
||||
toIndex--;
|
||||
}
|
||||
|
||||
if (toIndex >= 0 && toIndex !== fromIndex) {
|
||||
this.movePane(this.panes[fromIndex], this.panes[toIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewsToMove.length > 1) {
|
||||
viewsToMove.slice(1).forEach(view => {
|
||||
let toIndex = this.panes.findIndex(p => p.id === anchorView!.id);
|
||||
const fromIndex = this.panes.findIndex(p => p.id === view.id);
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (fromIndex > toIndex) {
|
||||
toIndex++;
|
||||
}
|
||||
|
||||
if (toIndex < this.panes.length && toIndex !== fromIndex) {
|
||||
this.movePane(this.panes[fromIndex], this.panes[toIndex]);
|
||||
anchorView = view;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
removePanes(panes: ViewPane[]): void {
|
||||
|
||||
@@ -609,6 +609,8 @@ export interface IViewDescriptorService {
|
||||
getDefaultContainerById(id: string): ViewContainer | null;
|
||||
getViewLocationById(id: string): ViewContainerLocation | null;
|
||||
|
||||
canMoveViews(): boolean;
|
||||
|
||||
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }>;
|
||||
moveViewsToContainer(views: IViewDescriptor[], viewContainer: ViewContainer, visibilityState?: ViewVisibilityState, reason?: string): void;
|
||||
|
||||
|
||||
@@ -311,7 +311,14 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
return this.viewContainersRegistry.getDefaultViewContainer(location);
|
||||
}
|
||||
|
||||
canMoveViews(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation, requestedIndex?: number, reason?: string): void {
|
||||
if (!this.canMoveViews()) {
|
||||
return;
|
||||
}
|
||||
this.logger.value.trace(`moveViewContainerToLocation: viewContainer:${viewContainer.id} location:${location} reason:${reason}`);
|
||||
this.moveViewContainerToLocationWithoutSaving(viewContainer, location, requestedIndex);
|
||||
this.saveViewCustomizations();
|
||||
@@ -327,6 +334,9 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
}
|
||||
|
||||
moveViewToLocation(view: IViewDescriptor, location: ViewContainerLocation, reason?: string): void {
|
||||
if (!this.canMoveViews()) {
|
||||
return;
|
||||
}
|
||||
this.logger.value.trace(`moveViewToLocation: view:${view.id} location:${location} reason:${reason}`);
|
||||
const container = this.registerGeneratedViewContainer(location);
|
||||
this.moveViewsToContainer([view], container);
|
||||
@@ -337,6 +347,10 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.canMoveViews()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.value.trace(`moveViewsToContainer: views:${views.map(view => view.id).join(',')} viewContainer:${viewContainer.id} reason:${reason}`);
|
||||
|
||||
const from = this.getViewContainerByViewId(views[0].id);
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Event, Emitter } from '../../../../../base/common/event.js';
|
||||
import { IPaneComposite } from '../../../../common/panecomposite.js';
|
||||
import { PaneCompositeDescriptor } from '../../../../browser/panecomposite.js';
|
||||
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
|
||||
import { ViewContainerLocation } from '../../../../common/views.js';
|
||||
|
||||
class StubPaneCompositePart implements IPaneCompositePart {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
@@ -81,6 +82,7 @@ suite('ActivitybarPart', () => {
|
||||
const stubInstantiationService = { createInstance: () => { throw new Error('not expected'); } } as unknown as IInstantiationService;
|
||||
|
||||
const part = disposables.add(new ActivitybarPart(
|
||||
ViewContainerLocation.Sidebar,
|
||||
new StubPaneCompositePart(),
|
||||
stubInstantiationService,
|
||||
layoutService,
|
||||
|
||||
Reference in New Issue
Block a user