mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
Merge from vscode 61d5f2b82f17bf9f99f56405204caab88a7e8747
This commit is contained in:
@@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { ITextFileService, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IEditorViewState } from 'vs/editor/common/editorCommon';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { normalizeDriveLetter } from 'vs/base/common/labels';
|
||||
import { MIME_BINARY } from 'vs/base/common/mime';
|
||||
@@ -21,7 +21,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorIdentifier, GroupIdentifier } from 'vs/workbench/common/editor';
|
||||
import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { addDisposableListener, EventType, asDomUri } from 'vs/base/browser/dom';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
|
||||
@@ -29,6 +29,7 @@ import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { isStandalone } from 'vs/base/browser/browser';
|
||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export interface IDraggedResource {
|
||||
resource: URI;
|
||||
@@ -507,3 +508,219 @@ export function containsDragType(event: DragEvent, ...dragTypesToFind: string[])
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export interface ICompositeDragAndDrop {
|
||||
drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: boolean): void;
|
||||
onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||
onDragEnter(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean;
|
||||
}
|
||||
|
||||
export interface ICompositeDragAndDropObserverCallbacks {
|
||||
onDragEnter?: (e: IDraggedCompositeData) => void;
|
||||
onDragLeave?: (e: IDraggedCompositeData) => void;
|
||||
onDrop?: (e: IDraggedCompositeData) => void;
|
||||
onDragOver?: (e: IDraggedCompositeData) => void;
|
||||
onDragStart?: (e: IDraggedCompositeData) => void;
|
||||
onDragEnd?: (e: IDraggedCompositeData) => void;
|
||||
}
|
||||
|
||||
export class CompositeDragAndDropData implements IDragAndDropData {
|
||||
constructor(private type: 'view' | 'composite', private id: string) { }
|
||||
update(dataTransfer: DataTransfer): void {
|
||||
// no-op
|
||||
}
|
||||
getData(): {
|
||||
type: 'view' | 'composite';
|
||||
id: string;
|
||||
} {
|
||||
return { type: this.type, id: this.id };
|
||||
}
|
||||
}
|
||||
|
||||
export interface IDraggedCompositeData {
|
||||
eventData: DragEvent;
|
||||
dragAndDropData: CompositeDragAndDropData;
|
||||
}
|
||||
|
||||
export class DraggedCompositeIdentifier {
|
||||
constructor(private _compositeId: string) { }
|
||||
|
||||
get id(): string {
|
||||
return this._compositeId;
|
||||
}
|
||||
}
|
||||
|
||||
export class DraggedViewIdentifier {
|
||||
constructor(private _viewId: string) { }
|
||||
|
||||
get id(): string {
|
||||
return this._viewId;
|
||||
}
|
||||
}
|
||||
|
||||
export type ViewType = 'composite' | 'view';
|
||||
|
||||
export class CompositeDragAndDropObserver extends Disposable {
|
||||
private transferData: LocalSelectionTransfer<DraggedCompositeIdentifier | DraggedViewIdentifier>;
|
||||
private _onDragStart = this._register(new Emitter<IDraggedCompositeData>());
|
||||
private _onDragEnd = this._register(new Emitter<IDraggedCompositeData>());
|
||||
private static _instance: CompositeDragAndDropObserver | undefined;
|
||||
static get INSTANCE(): CompositeDragAndDropObserver {
|
||||
if (!CompositeDragAndDropObserver._instance) {
|
||||
CompositeDragAndDropObserver._instance = new CompositeDragAndDropObserver();
|
||||
}
|
||||
return CompositeDragAndDropObserver._instance;
|
||||
}
|
||||
private constructor() {
|
||||
super();
|
||||
this.transferData = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier | DraggedViewIdentifier>();
|
||||
}
|
||||
private readDragData(type: ViewType): CompositeDragAndDropData | undefined {
|
||||
if (this.transferData.hasData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype)) {
|
||||
const data = this.transferData.getData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype);
|
||||
if (data && data[0]) {
|
||||
return new CompositeDragAndDropData(type, data[0].id);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
private writeDragData(id: string, type: ViewType): void {
|
||||
this.transferData.setData([type === 'view' ? new DraggedViewIdentifier(id) : new DraggedCompositeIdentifier(id)], type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype);
|
||||
}
|
||||
registerTarget(element: HTMLElement, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable {
|
||||
const disposableStore = new DisposableStore();
|
||||
disposableStore.add(new DragAndDropObserver(element, {
|
||||
onDragEnd: e => {
|
||||
// no-op
|
||||
},
|
||||
onDragEnter: e => {
|
||||
e.preventDefault();
|
||||
if (callbacks.onDragEnter) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (data) {
|
||||
callbacks.onDragEnter({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragLeave: e => {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (callbacks.onDragLeave && data) {
|
||||
callbacks.onDragLeave({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
},
|
||||
onDrop: e => {
|
||||
if (callbacks.onDrop) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
callbacks.onDrop({ eventData: e, dragAndDropData: data! });
|
||||
|
||||
// Fire drag event in case drop handler destroys the dragged element
|
||||
this._onDragEnd.fire({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
},
|
||||
onDragOver: e => {
|
||||
e.preventDefault();
|
||||
if (callbacks.onDragOver) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
callbacks.onDragOver({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
}
|
||||
}));
|
||||
if (callbacks.onDragStart) {
|
||||
this._onDragStart.event(e => {
|
||||
callbacks.onDragStart!(e);
|
||||
}, this, disposableStore);
|
||||
}
|
||||
if (callbacks.onDragEnd) {
|
||||
this._onDragEnd.event(e => {
|
||||
callbacks.onDragEnd!(e);
|
||||
});
|
||||
}
|
||||
return this._register(disposableStore);
|
||||
}
|
||||
registerDraggable(element: HTMLElement, type: ViewType, id: string, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable {
|
||||
element.draggable = true;
|
||||
const disposableStore = new DisposableStore();
|
||||
disposableStore.add(addDisposableListener(element, EventType.DRAG_START, e => {
|
||||
this.writeDragData(id, type);
|
||||
this._onDragStart.fire({ eventData: e, dragAndDropData: this.readDragData(type)! });
|
||||
}));
|
||||
disposableStore.add(new DragAndDropObserver(element, {
|
||||
onDragEnd: e => {
|
||||
const data = this.readDragData(type);
|
||||
if (data && data.getData().id === id) {
|
||||
this.transferData.clearData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._onDragEnd.fire({ eventData: e, dragAndDropData: data! });
|
||||
},
|
||||
onDragEnter: e => {
|
||||
if (callbacks.onDragEnter) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
callbacks.onDragEnter({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
}
|
||||
},
|
||||
onDragLeave: e => {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callbacks.onDragLeave) {
|
||||
callbacks.onDragLeave({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
},
|
||||
onDrop: e => {
|
||||
if (callbacks.onDrop) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
callbacks.onDrop({ eventData: e, dragAndDropData: data! });
|
||||
|
||||
// Fire drag event in case drop handler destroys the dragged element
|
||||
this._onDragEnd.fire({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
},
|
||||
onDragOver: e => {
|
||||
if (callbacks.onDragOver) {
|
||||
const data = this.readDragData('composite') || this.readDragData('view');
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
callbacks.onDragOver({ eventData: e, dragAndDropData: data! });
|
||||
}
|
||||
}
|
||||
}));
|
||||
if (callbacks.onDragStart) {
|
||||
this._onDragStart.event(e => {
|
||||
callbacks.onDragStart!(e);
|
||||
}, this, disposableStore);
|
||||
}
|
||||
if (callbacks.onDragEnd) {
|
||||
this._onDragEnd.event(e => {
|
||||
callbacks.onDragEnd!(e);
|
||||
});
|
||||
}
|
||||
return this._register(disposableStore);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,19 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .drop-block-overlay {
|
||||
visibility: hidden; /* use visibility to ensure transitions */
|
||||
transition-property: opacity;
|
||||
transition-timing-function: linear;
|
||||
transition-duration: 250ms;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .title {
|
||||
display: none; /* Parts have to opt in to show title area */
|
||||
}
|
||||
|
||||
@@ -130,8 +130,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) => this.compositeBar.move(from, to),
|
||||
() => this.getPinnedViewletIds()
|
||||
(from: string, to: string, before?: boolean) => this.compositeBar.move(from, to, before)
|
||||
),
|
||||
compositeSize: 50,
|
||||
colors: (theme: IColorTheme) => this.getActivitybarItemColors(theme),
|
||||
@@ -337,6 +336,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
||||
container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : '';
|
||||
container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : '';
|
||||
container.style.borderLeftColor = !isPositionLeft ? borderColor : '';
|
||||
// container.style.outlineColor = this.getColor(ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND) ?? '';
|
||||
}
|
||||
|
||||
private getActivitybarItemColors(theme: IColorTheme): ICompositeBarColors {
|
||||
|
||||
@@ -9,6 +9,42 @@
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before,
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 48px;
|
||||
height: 2px;
|
||||
display: block;
|
||||
background-color: var(--insert-border-color);
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
transition-duration: 0ms;
|
||||
transition-delay: 100ms;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before {
|
||||
margin-top: -3px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after {
|
||||
margin-top: 1px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before,
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::after,
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::before,
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after {
|
||||
transition-delay: 0s;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before,
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .drop-block-overlay.visible {
|
||||
visibility: visible;
|
||||
backdrop-filter: brightness(97%) blur(2px);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -11,21 +11,19 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors, DraggedCompositeIdentifier } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Widget } from 'vs/base/browser/ui/widget';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { LocalSelectionTransfer, DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { ICompositeDragAndDrop, CompositeDragAndDropData } from 'vs/base/parts/composite/browser/compositeDnd';
|
||||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
import { IComposite } from 'vs/workbench/common/composite';
|
||||
import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd';
|
||||
|
||||
export interface ICompositeBarItem {
|
||||
id: string;
|
||||
@@ -41,30 +39,38 @@ 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) => void,
|
||||
private getVisibleCompositeIds: () => string[]
|
||||
private moveComposite: (from: string, to: string, before?: boolean) => void,
|
||||
) { }
|
||||
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): void {
|
||||
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: boolean): void {
|
||||
const dragData = data.getData();
|
||||
const viewContainerRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
|
||||
|
||||
if (dragData.type === 'composite') {
|
||||
const currentContainer = viewContainerRegistry.get(dragData.id)!;
|
||||
const currentLocation = viewContainerRegistry.getViewContainerLocation(currentContainer);
|
||||
|
||||
// Inserting a composite between composites
|
||||
if (targetCompositeId) {
|
||||
if (currentLocation !== this.targetContainerLocation && this.targetContainerLocation !== ViewContainerLocation.Panel) {
|
||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||
if (destinationContainer && !destinationContainer.rejectAddedViews) {
|
||||
const viewsToMove = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView);
|
||||
this.viewDescriptorService.moveViewsToContainer(viewsToMove, destinationContainer);
|
||||
this.openComposite(targetCompositeId, true).then(composite => {
|
||||
// ... on the same composite bar
|
||||
if (currentLocation === this.targetContainerLocation) {
|
||||
this.moveComposite(dragData.id, targetCompositeId, before);
|
||||
}
|
||||
// ... on a different composite bar
|
||||
else {
|
||||
const viewsToMove = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView);
|
||||
if (viewsToMove.length === 1) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewsToMove[0], this.targetContainerLocation);
|
||||
|
||||
const newContainer = this.viewDescriptorService.getViewContainer(viewsToMove[0].id)!;
|
||||
|
||||
this.moveComposite(newContainer.id, targetCompositeId, before);
|
||||
|
||||
this.openComposite(newContainer.id, true).then(composite => {
|
||||
if (composite && viewsToMove.length === 1) {
|
||||
composite.openView(viewsToMove[0].id, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.moveComposite(dragData.id, targetCompositeId);
|
||||
}
|
||||
} else {
|
||||
const draggedViews = this.viewDescriptorService.getViewDescriptors(currentContainer).allViewDescriptors;
|
||||
@@ -76,38 +82,24 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
}
|
||||
|
||||
if (dragData.type === 'view') {
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dragData.id);
|
||||
if (viewDescriptor && viewDescriptor.canMoveView) {
|
||||
if (targetCompositeId) {
|
||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||
if (destinationContainer && !destinationContainer.rejectAddedViews) {
|
||||
if (this.targetContainerLocation === ViewContainerLocation.Sidebar || this.targetContainerLocation === ViewContainerLocation.Panel) {
|
||||
this.viewDescriptorService.moveViewsToContainer([viewDescriptor], destinationContainer);
|
||||
this.openComposite(targetCompositeId, true).then(composite => {
|
||||
if (composite) {
|
||||
composite.openView(viewDescriptor.id, true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.viewDescriptorService.moveViewToLocation(viewDescriptor, this.targetContainerLocation);
|
||||
this.moveComposite(this.viewDescriptorService.getViewContainer(viewDescriptor.id)!.id, targetCompositeId);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.viewDescriptorService.moveViewToLocation(viewDescriptor, this.targetContainerLocation);
|
||||
const newCompositeId = this.viewDescriptorService.getViewContainer(dragData.id)!.id;
|
||||
const visibleItems = this.getVisibleCompositeIds();
|
||||
const targetId = visibleItems.length ? visibleItems[visibleItems.length - 1] : undefined;
|
||||
if (targetId && targetId !== newCompositeId) {
|
||||
this.moveComposite(newCompositeId, targetId);
|
||||
}
|
||||
if (targetCompositeId) {
|
||||
const viewToMove = this.viewDescriptorService.getViewDescriptor(dragData.id)!;
|
||||
|
||||
this.openComposite(newCompositeId, true).then(composite => {
|
||||
if (viewToMove && viewToMove.canMoveView) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewToMove, this.targetContainerLocation);
|
||||
|
||||
const newContainer = this.viewDescriptorService.getViewContainer(viewToMove.id)!;
|
||||
|
||||
this.moveComposite(newContainer.id, targetCompositeId, before);
|
||||
|
||||
this.openComposite(newContainer.id, true).then(composite => {
|
||||
if (composite) {
|
||||
composite.openView(viewDescriptor.id, true);
|
||||
composite.openView(viewToMove.id, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,41 +121,21 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
const currentContainer = viewContainerRegistry.get(dragData.id)!;
|
||||
const currentLocation = viewContainerRegistry.getViewContainerLocation(currentContainer);
|
||||
|
||||
// ... to the same location
|
||||
// ... to the same composite location
|
||||
if (currentLocation === this.targetContainerLocation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ... across view containers but without a destination composite
|
||||
if (!targetCompositeId) {
|
||||
const draggedViews = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors;
|
||||
if (draggedViews.some(vd => !vd.canMoveView)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (draggedViews.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const defaultLocation = viewContainerRegistry.getViewContainerLocation(this.viewDescriptorService.getDefaultContainer(draggedViews[0].id)!);
|
||||
if (this.targetContainerLocation === ViewContainerLocation.Sidebar && this.targetContainerLocation !== defaultLocation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ... from panel to the sidebar
|
||||
if (this.targetContainerLocation === ViewContainerLocation.Sidebar) {
|
||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||
return !!destinationContainer &&
|
||||
!destinationContainer.rejectAddedViews &&
|
||||
this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.some(vd => vd.canMoveView);
|
||||
}
|
||||
// ... from sidebar to the panel
|
||||
else {
|
||||
// ... to another composite location
|
||||
const draggedViews = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors;
|
||||
if (draggedViews.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ... single view
|
||||
const defaultContainer = this.viewDescriptorService.getDefaultContainer(draggedViews[0].id);
|
||||
const canMoveToDefault = !!defaultContainer && this.viewDescriptorService.getViewContainerLocation(defaultContainer) === this.targetContainerLocation;
|
||||
return !!draggedViews[0].canMoveView && (!!draggedViews[0].containerIcon || canMoveToDefault || this.targetContainerLocation === ViewContainerLocation.Panel);
|
||||
} else {
|
||||
// Dragging an individual view
|
||||
const viewDescriptor = this.viewDescriptorService.getViewDescriptor(dragData.id);
|
||||
@@ -174,13 +146,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
}
|
||||
|
||||
// ... to create a view container
|
||||
if (!targetCompositeId) {
|
||||
return this.targetContainerLocation === ViewContainerLocation.Panel;
|
||||
}
|
||||
|
||||
// ... into a destination
|
||||
const destinationContainer = viewContainerRegistry.get(targetCompositeId);
|
||||
return !!destinationContainer && !destinationContainer.rejectAddedViews;
|
||||
return this.targetContainerLocation === ViewContainerLocation.Panel || !!viewDescriptor.containerIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,8 +181,6 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
private visibleComposites: string[];
|
||||
private compositeSizeInBar: Map<string, number>;
|
||||
|
||||
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier | DraggedViewIdentifier>;
|
||||
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
@@ -232,7 +196,6 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
this.model = new CompositeBarModel(items, options);
|
||||
this.visibleComposites = [];
|
||||
this.compositeSizeInBar = new Map<string, number>();
|
||||
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier>();
|
||||
this.computeSizes(this.model.visibleItems);
|
||||
}
|
||||
|
||||
@@ -278,100 +241,25 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
// Contextmenu for composites
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
||||
|
||||
// Register a drop target on the whole bar to prevent forbidden feedback
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {}));
|
||||
|
||||
// Allow to drop at the end to move composites to the end
|
||||
this._register(new DragAndDropObserver(excessDiv, {
|
||||
onDragOver: (e: DragEvent) => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedCompositeId = data[0].id;
|
||||
|
||||
// Check if drop is allowed
|
||||
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedViewId = data[0].id;
|
||||
|
||||
// Check if drop is allowed
|
||||
if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), undefined, e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(excessDiv, {
|
||||
onDragEnter: (e: IDraggedCompositeData) => {
|
||||
const pinnedItems = this.getPinnedComposites();
|
||||
const validDropTarget = this.options.dndHandler.onDragEnter(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData);
|
||||
this.updateFromDragging(excessDiv, validDropTarget);
|
||||
},
|
||||
|
||||
onDragEnter: (e: DragEvent) => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedCompositeId = data[0].id;
|
||||
|
||||
// Check if drop is allowed
|
||||
const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e);
|
||||
this.updateFromDragging(excessDiv, validDropTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedViewId = data[0].id;
|
||||
|
||||
// Check if drop is allowed
|
||||
const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('view', draggedViewId), undefined, e);
|
||||
this.updateFromDragging(excessDiv, validDropTarget);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onDragLeave: (e: DragEvent) => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) ||
|
||||
this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
this.updateFromDragging(excessDiv, false);
|
||||
}
|
||||
},
|
||||
onDragEnd: (e: DragEvent) => {
|
||||
// no-op, will not be called
|
||||
},
|
||||
onDrop: (e: DragEvent) => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedCompositeId = data[0].id;
|
||||
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
||||
|
||||
this.options.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e);
|
||||
this.updateFromDragging(excessDiv, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedViewId = data[0].id;
|
||||
this.compositeTransfer.clearData(DraggedViewIdentifier.prototype);
|
||||
|
||||
this.options.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), undefined, e);
|
||||
this.updateFromDragging(excessDiv, false);
|
||||
}
|
||||
}
|
||||
onDragLeave: (e: IDraggedCompositeData) => {
|
||||
this.updateFromDragging(excessDiv, false);
|
||||
},
|
||||
onDrop: (e: IDraggedCompositeData) => {
|
||||
const pinnedItems = this.getPinnedComposites();
|
||||
this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, false);
|
||||
this.updateFromDragging(excessDiv, false);
|
||||
}
|
||||
}));
|
||||
|
||||
return actionBarDiv;
|
||||
@@ -519,10 +407,34 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
return item?.pinned;
|
||||
}
|
||||
|
||||
move(compositeId: string, toCompositeId: string): void {
|
||||
if (this.model.move(compositeId, toCompositeId)) {
|
||||
// timeout helps to prevent artifacts from showing up
|
||||
setTimeout(() => this.updateCompositeSwitcher(), 0);
|
||||
move(compositeId: string, toCompositeId: string, before?: boolean): void {
|
||||
|
||||
if (before !== undefined) {
|
||||
const fromIndex = this.model.items.findIndex(c => c.id === compositeId);
|
||||
let toIndex = this.model.items.findIndex(c => c.id === toCompositeId);
|
||||
|
||||
if (fromIndex >= 0 && toIndex >= 0) {
|
||||
if (!before && fromIndex > toIndex) {
|
||||
toIndex++;
|
||||
}
|
||||
|
||||
if (before && fromIndex < toIndex) {
|
||||
toIndex--;
|
||||
}
|
||||
|
||||
if (toIndex < this.model.items.length && toIndex >= 0 && toIndex !== fromIndex) {
|
||||
if (this.model.move(this.model.items[fromIndex].id, this.model.items[toIndex].id)) {
|
||||
// timeout helps to prevent artifacts from showing up
|
||||
setTimeout(() => this.updateCompositeSwitcher(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (this.model.move(compositeId, toCompositeId)) {
|
||||
// timeout helps to prevent artifacts from showing up
|
||||
setTimeout(() => this.updateCompositeSwitcher(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,8 @@ 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 { DragAndDropObserver, LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
||||
import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop } from 'vs/workbench/browser/dnd';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { ICompositeDragAndDrop, CompositeDragAndDropData } from 'vs/base/parts/composite/browser/compositeDnd';
|
||||
|
||||
export interface ICompositeActivity {
|
||||
badge: IBadge;
|
||||
@@ -167,11 +165,15 @@ export class ActivityActionViewItem extends BaseActionViewItem {
|
||||
// Apply foreground color to activity bar items provided with codicons
|
||||
this.label.style.color = foreground ? foreground.toString() : '';
|
||||
}
|
||||
|
||||
const dragColor = colors.activeBackgroundColor || colors.activeForegroundColor;
|
||||
this.container.style.setProperty('--insert-border-color', dragColor ? dragColor.toString() : '');
|
||||
} else {
|
||||
const foreground = this._action.checked ? colors.activeForegroundColor : colors.inactiveForegroundColor;
|
||||
const borderBottomColor = this._action.checked ? colors.activeBorderBottomColor : null;
|
||||
this.label.style.color = foreground ? foreground.toString() : '';
|
||||
this.label.style.borderBottomColor = borderBottomColor ? borderBottomColor.toString() : '';
|
||||
this.container.style.setProperty('--insert-border-color', colors.activeForegroundColor ? colors.activeForegroundColor.toString() : '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,14 +447,6 @@ class ManageExtensionAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class DraggedCompositeIdentifier {
|
||||
constructor(private _compositeId: string) { }
|
||||
|
||||
get id(): string {
|
||||
return this._compositeId;
|
||||
}
|
||||
}
|
||||
|
||||
export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
|
||||
private static manageExtensionAction: ManageExtensionAction;
|
||||
@@ -522,105 +516,38 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
this.showContextMenu(container);
|
||||
}));
|
||||
|
||||
let insertDropBefore: boolean | undefined = undefined;
|
||||
// Allow to drag
|
||||
this._register(dom.addDisposableListener(this.container, dom.EventType.DRAG_START, (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
|
||||
// Registe as dragged to local transfer
|
||||
this.compositeTransfer.setData([new DraggedCompositeIdentifier(this.activity.id)], DraggedCompositeIdentifier.prototype);
|
||||
|
||||
// Trigger the action even on drag start to prevent clicks from failing that started a drag
|
||||
if (!this.getAction().checked) {
|
||||
this.getAction().run();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(new DragAndDropObserver(this.container, {
|
||||
onDragEnter: e => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
||||
const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', data[0].id), this.activity.id, e);
|
||||
this.updateFromDragging(container, validDropTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data) && data[0].id !== this.activity.id) {
|
||||
const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('view', data[0].id), this.activity.id, e);
|
||||
this.updateFromDragging(container, validDropTarget);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, 'composite', this.activity.id, {
|
||||
onDragOver: e => {
|
||||
dom.EventHelper.stop(e, true);
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedCompositeId = data[0].id;
|
||||
if (draggedCompositeId !== this.activity.id) {
|
||||
if (e.dataTransfer && !this.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), this.activity.id, e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedViewId = data[0].id;
|
||||
if (e.dataTransfer && !this.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), this.activity.id, e)) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
const isValidMove = e.dragAndDropData.getData().id !== this.activity.id && this.dndHandler.onDragOver(e.dragAndDropData, this.activity.id, e.eventData);
|
||||
insertDropBefore = this.updateFromDragging(container, isValidMove, e.eventData);
|
||||
},
|
||||
|
||||
onDragLeave: e => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) ||
|
||||
this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
this.updateFromDragging(container, false);
|
||||
}
|
||||
insertDropBefore = this.updateFromDragging(container, false, e.eventData);
|
||||
},
|
||||
|
||||
onDragEnd: e => {
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
this.updateFromDragging(container, false);
|
||||
|
||||
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
||||
}
|
||||
insertDropBefore = this.updateFromDragging(container, false, e.eventData);
|
||||
},
|
||||
|
||||
onDrop: e => {
|
||||
dom.EventHelper.stop(e, true);
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedCompositeId = data[0].id;
|
||||
if (draggedCompositeId !== this.activity.id) {
|
||||
this.updateFromDragging(container, false);
|
||||
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
|
||||
|
||||
this.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), this.activity.id, e);
|
||||
}
|
||||
}
|
||||
this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, !!insertDropBefore);
|
||||
insertDropBefore = this.updateFromDragging(container, false, e.eventData);
|
||||
},
|
||||
onDragStart: e => {
|
||||
if (e.dragAndDropData.getData().id !== this.activity.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const draggedViewId = data[0].id;
|
||||
this.updateFromDragging(container, false);
|
||||
this.compositeTransfer.clearData(DraggedViewIdentifier.prototype);
|
||||
if (e.eventData.dataTransfer) {
|
||||
e.eventData.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
|
||||
this.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), this.activity.id, e);
|
||||
}
|
||||
// Trigger the action even on drag start to prevent clicks from failing that started a drag
|
||||
if (!this.getAction().checked) {
|
||||
this.getAction().run();
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -637,11 +564,42 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
this.updateStyles();
|
||||
}
|
||||
|
||||
private updateFromDragging(element: HTMLElement, isDragging: boolean): void {
|
||||
const theme = this.themeService.getColorTheme();
|
||||
const dragBackground = this.options.colors(theme).dragAndDropBackground;
|
||||
private updateFromDragging(element: HTMLElement, showFeedback: boolean, event: DragEvent): boolean | undefined {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const posX = event.clientX;
|
||||
const posY = event.clientY;
|
||||
const height = rect.bottom - rect.top;
|
||||
const width = rect.right - rect.left;
|
||||
|
||||
element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : '';
|
||||
const forceTop = posY <= rect.top + height * 0.4;
|
||||
const forceBottom = posY > rect.bottom - height * 0.4;
|
||||
const preferTop = posY <= rect.top + height * 0.5;
|
||||
|
||||
const forceLeft = posX <= rect.left + width * 0.4;
|
||||
const forceRight = posX > rect.right - width * 0.4;
|
||||
const preferLeft = posX <= rect.left + width * 0.5;
|
||||
|
||||
const classes = element.classList;
|
||||
const lastClasses = {
|
||||
vertical: classes.contains('top') ? 'top' : (classes.contains('bottom') ? 'bottom' : undefined),
|
||||
horizontal: classes.contains('left') ? 'left' : (classes.contains('right') ? 'right' : undefined)
|
||||
};
|
||||
|
||||
const top = forceTop || (preferTop && !lastClasses.vertical) || (!forceBottom && lastClasses.vertical === 'top');
|
||||
const bottom = forceBottom || (!preferTop && !lastClasses.vertical) || (!forceTop && lastClasses.vertical === 'bottom');
|
||||
const left = forceLeft || (preferLeft && !lastClasses.horizontal) || (!forceRight && lastClasses.horizontal === 'left');
|
||||
const right = forceRight || (!preferLeft && !lastClasses.horizontal) || (!forceLeft && lastClasses.horizontal === 'right');
|
||||
|
||||
dom.toggleClass(element, 'top', showFeedback && top);
|
||||
dom.toggleClass(element, 'bottom', showFeedback && bottom);
|
||||
dom.toggleClass(element, 'left', showFeedback && left);
|
||||
dom.toggleClass(element, 'right', showFeedback && right);
|
||||
|
||||
if (!showFeedback) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return top || left;
|
||||
}
|
||||
|
||||
private showContextMenu(container: HTMLElement): void {
|
||||
|
||||
@@ -32,6 +32,7 @@ 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';
|
||||
import { CompositeDragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
|
||||
interface IEditorPartUIState {
|
||||
serializedGrid: ISerializedGrid;
|
||||
@@ -826,6 +827,20 @@ export class EditorPart extends Part implements IEditorGroupsService, IEditorGro
|
||||
// Drop support
|
||||
this._register(this.createEditorDropTarget(this.container, {}));
|
||||
|
||||
// No drop in the editor
|
||||
const overlay = document.createElement('div');
|
||||
addClass(overlay, 'drop-block-overlay');
|
||||
parent.appendChild(overlay);
|
||||
|
||||
CompositeDragAndDropObserver.INSTANCE.registerTarget(this.element, {
|
||||
onDragStart: e => {
|
||||
toggleClass(overlay, 'visible', true);
|
||||
},
|
||||
onDragEnd: e => {
|
||||
toggleClass(overlay, 'visible', false);
|
||||
}
|
||||
});
|
||||
|
||||
return this.container;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/editorquickaccess';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource } 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';
|
||||
@@ -25,18 +26,14 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService
|
||||
) {
|
||||
super(prefix);
|
||||
}
|
||||
|
||||
protected configure(picker: IQuickPick<IEditorQuickPickItem>): void {
|
||||
|
||||
// Allow to open editors in background without closing picker
|
||||
picker.canAcceptInBackground = true;
|
||||
super(prefix, { canAcceptInBackground: true });
|
||||
}
|
||||
|
||||
protected getPicks(filter: string): Array<IEditorQuickPickItem | IQuickPickSeparator> {
|
||||
const query = prepareQuery(filter);
|
||||
const scorerCache = Object.create(null);
|
||||
|
||||
// Filtering
|
||||
const filteredEditorEntries = this.doGetEditorPickItems().filter(entry => {
|
||||
if (!query.value) {
|
||||
return true;
|
||||
@@ -102,11 +99,11 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro
|
||||
description: editor.getDescription(),
|
||||
iconClasses: getIconClasses(this.modelService, this.modeService, resource),
|
||||
italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor),
|
||||
buttonsAlwaysVisible: isDirty,
|
||||
buttons: [
|
||||
{
|
||||
iconClass: isDirty ? 'codicon-circle-filled' : 'codicon-close',
|
||||
tooltip: localize('closeEditor', "Close Editor")
|
||||
iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close',
|
||||
tooltip: localize('closeEditor', "Close Editor"),
|
||||
alwaysVisible: isDirty
|
||||
}
|
||||
],
|
||||
trigger: async () => {
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
opacity: 0; /* hidden initially */
|
||||
transition: opacity 150ms ease-out;
|
||||
/* color: red; */
|
||||
}
|
||||
|
||||
#monaco-workbench-editor-drop-overlay > .editor-group-overlay-indicator.overlay-move-transition {
|
||||
transition: top 70ms ease-out, left 70ms ease-out, width 70ms ease-out, height 70ms ease-out, opacity 150ms ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.quick-input-list .quick-input-list-entry.has-actions:hover .quick-input-list-entry-action-bar .action-label.dirty-editor::before {
|
||||
content: "\ea76"; /* Close icon flips between black dot and "X" for dirty open editors */
|
||||
}
|
||||
@@ -85,6 +85,40 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item::before,
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item::after {
|
||||
content: '';
|
||||
width: 2px;
|
||||
display: block;
|
||||
background-color: var(--insert-border-color);
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
transition-duration: 0ms;
|
||||
transition-delay: 100ms;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item::before {
|
||||
margin-left: -11px;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item::after {
|
||||
margin-right: -11px;
|
||||
margin-left: 9px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::before,
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::after,
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before,
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after {
|
||||
transition-delay: 0s;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before,
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item .action-label{
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@@ -144,9 +144,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-check
|
||||
(from: string, to: string) => this.compositeBar.move(from, to),
|
||||
() => this.getPinnedPanels().map(p => p.id)
|
||||
(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)
|
||||
),
|
||||
compositeSize: 0,
|
||||
overflowActionSize: 44,
|
||||
|
||||
@@ -23,7 +23,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER } from 'vs/workbench/common/theme';
|
||||
import { SIDE_BAR_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND, SIDE_BAR_BORDER, SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
@@ -33,9 +33,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { LayoutPriority } from 'vs/base/browser/ui/grid/grid';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
||||
import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { DraggedCompositeIdentifier } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
import { LocalSelectionTransfer, DraggedViewIdentifier, DraggedCompositeIdentifier } from 'vs/workbench/browser/dnd';
|
||||
|
||||
export class SidebarPart extends CompositePart<Viewlet> implements IViewletService {
|
||||
|
||||
@@ -209,6 +207,7 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
|
||||
container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : '';
|
||||
container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : '';
|
||||
container.style.borderLeftColor = !isPositionLeft ? borderColor || '' : '';
|
||||
container.style.outlineColor = this.getColor(SIDE_BAR_DRAG_AND_DROP_BACKGROUND) ?? '';
|
||||
}
|
||||
|
||||
layout(width: number, height: number): void {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
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 { 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 } 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 } 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';
|
||||
@@ -20,8 +20,8 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { PaneView, IPaneViewOptions, IPaneOptions, Pane, DefaultPaneDndController } from 'vs/base/browser/ui/splitview/paneview';
|
||||
import { IThemeService, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { PaneView, IPaneViewOptions, IPaneOptions, Pane } from 'vs/base/browser/ui/splitview/paneview';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
@@ -42,11 +42,12 @@ import { parseLinkedText } from 'vs/base/common/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';
|
||||
import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd';
|
||||
import { CompositeDragAndDropObserver, DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
import { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
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';
|
||||
|
||||
export interface IPaneColors extends IColorMapping {
|
||||
dropBackground?: ColorIdentifier;
|
||||
@@ -61,14 +62,6 @@ export interface IViewPaneOptions extends IPaneOptions {
|
||||
titleMenuId?: MenuId;
|
||||
}
|
||||
|
||||
export class DraggedViewIdentifier {
|
||||
constructor(private _viewId: string) { }
|
||||
|
||||
get id(): string {
|
||||
return this._viewId;
|
||||
}
|
||||
}
|
||||
|
||||
type WelcomeActionClassification = {
|
||||
viewId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
uri: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
@@ -508,6 +501,210 @@ interface IViewPaneItem {
|
||||
disposable: IDisposable;
|
||||
}
|
||||
|
||||
const enum DropDirection {
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
class ViewPaneDropOverlay extends Themable {
|
||||
|
||||
private static readonly OVERLAY_ID = 'monaco-workbench-pane-drop-overlay';
|
||||
|
||||
private container!: HTMLElement;
|
||||
private overlay!: HTMLElement;
|
||||
|
||||
private _currentDropOperation: DropDirection | undefined;
|
||||
|
||||
// private currentDropOperation: IDropOperation | undefined;
|
||||
private _disposed: boolean | undefined;
|
||||
|
||||
private cleanupOverlayScheduler: RunOnceScheduler;
|
||||
|
||||
get currentDropOperation(): DropDirection | undefined {
|
||||
return this._currentDropOperation;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private paneElement: HTMLElement,
|
||||
private orientation: Orientation,
|
||||
protected themeService: IThemeService
|
||||
) {
|
||||
super(themeService);
|
||||
this.cleanupOverlayScheduler = this._register(new RunOnceScheduler(() => this.dispose(), 300));
|
||||
|
||||
this.create();
|
||||
}
|
||||
|
||||
get disposed(): boolean {
|
||||
return !!this._disposed;
|
||||
}
|
||||
|
||||
private create(): void {
|
||||
// Container
|
||||
this.container = document.createElement('div');
|
||||
this.container.id = ViewPaneDropOverlay.OVERLAY_ID;
|
||||
|
||||
// Parent
|
||||
this.paneElement.appendChild(this.container);
|
||||
addClass(this.paneElement, 'dragged-over');
|
||||
this._register(toDisposable(() => {
|
||||
this.paneElement.removeChild(this.container);
|
||||
removeClass(this.paneElement, 'dragged-over');
|
||||
}));
|
||||
|
||||
// Overlay
|
||||
this.overlay = document.createElement('div');
|
||||
addClass(this.overlay, 'pane-overlay-indicator');
|
||||
this.container.appendChild(this.overlay);
|
||||
|
||||
// Overlay Event Handling
|
||||
this.registerListeners();
|
||||
|
||||
// Styles
|
||||
this.updateStyles();
|
||||
}
|
||||
|
||||
protected updateStyles(): void {
|
||||
|
||||
// Overlay drop background
|
||||
this.overlay.style.backgroundColor = this.getColor(EDITOR_DRAG_AND_DROP_BACKGROUND) || '';
|
||||
|
||||
// Overlay contrast border (if any)
|
||||
const activeContrastBorderColor = this.getColor(activeContrastBorder);
|
||||
this.overlay.style.outlineColor = activeContrastBorderColor || '';
|
||||
this.overlay.style.outlineOffset = activeContrastBorderColor ? '-2px' : '';
|
||||
this.overlay.style.outlineStyle = activeContrastBorderColor ? 'dashed' : '';
|
||||
this.overlay.style.outlineWidth = activeContrastBorderColor ? '2px' : '';
|
||||
|
||||
this.overlay.style.borderColor = activeContrastBorderColor || '';
|
||||
this.overlay.style.borderStyle = 'solid' || '';
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(new DragAndDropObserver(this.container, {
|
||||
onDragEnter: e => undefined,
|
||||
onDragOver: e => {
|
||||
|
||||
// Position overlay
|
||||
this.positionOverlay(e.offsetX, e.offsetY);
|
||||
|
||||
// Make sure to stop any running cleanup scheduler to remove the overlay
|
||||
if (this.cleanupOverlayScheduler.isScheduled()) {
|
||||
this.cleanupOverlayScheduler.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onDragLeave: e => this.dispose(),
|
||||
onDragEnd: e => this.dispose(),
|
||||
|
||||
onDrop: e => {
|
||||
// Dispose overlay
|
||||
this.dispose();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(addDisposableListener(this.container, EventType.MOUSE_OVER, () => {
|
||||
// Under some circumstances we have seen reports where the drop overlay is not being
|
||||
// cleaned up and as such the editor area remains under the overlay so that you cannot
|
||||
// type into the editor anymore. This seems related to using VMs and DND via host and
|
||||
// guest OS, though some users also saw it without VMs.
|
||||
// To protect against this issue we always destroy the overlay as soon as we detect a
|
||||
// mouse event over it. The delay is used to guarantee we are not interfering with the
|
||||
// actual DROP event that can also trigger a mouse over event.
|
||||
if (!this.cleanupOverlayScheduler.isScheduled()) {
|
||||
this.cleanupOverlayScheduler.schedule();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private positionOverlay(mousePosX: number, mousePosY: number): void {
|
||||
const paneWidth = this.paneElement.clientWidth;
|
||||
const paneHeight = this.paneElement.clientHeight;
|
||||
|
||||
const splitWidthThreshold = paneWidth / 2;
|
||||
const splitHeightThreshold = paneHeight / 2;
|
||||
|
||||
let dropDirection: DropDirection | undefined;
|
||||
|
||||
if (this.orientation === Orientation.VERTICAL) {
|
||||
if (mousePosY < splitHeightThreshold) {
|
||||
dropDirection = DropDirection.UP;
|
||||
} else if (mousePosY >= splitHeightThreshold) {
|
||||
dropDirection = DropDirection.DOWN;
|
||||
}
|
||||
} else {
|
||||
if (mousePosX < splitWidthThreshold) {
|
||||
dropDirection = DropDirection.LEFT;
|
||||
} else if (mousePosX >= splitWidthThreshold) {
|
||||
dropDirection = DropDirection.RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw overlay based on split direction
|
||||
switch (dropDirection) {
|
||||
case DropDirection.UP:
|
||||
this.doPositionOverlay({ top: '0', left: '0', width: '100%', height: '50%' });
|
||||
break;
|
||||
case DropDirection.DOWN:
|
||||
this.doPositionOverlay({ bottom: '0', left: '0', width: '100%', height: '50%' });
|
||||
break;
|
||||
case DropDirection.LEFT:
|
||||
this.doPositionOverlay({ top: '0', left: '0', width: '50%', height: '100%' });
|
||||
break;
|
||||
case DropDirection.RIGHT:
|
||||
this.doPositionOverlay({ top: '0', right: '0', width: '50%', height: '100%' });
|
||||
break;
|
||||
default:
|
||||
this.doPositionOverlay({ top: '0', left: '0', width: '100%', height: '100%' });
|
||||
}
|
||||
|
||||
this.doUpdateOverlayBorder(dropDirection);
|
||||
|
||||
// Make sure the overlay is visible now
|
||||
this.overlay.style.opacity = '1';
|
||||
|
||||
// Enable transition after a timeout to prevent initial animation
|
||||
setTimeout(() => addClass(this.overlay, 'overlay-move-transition'), 0);
|
||||
|
||||
// Remember as current split direction
|
||||
this._currentDropOperation = dropDirection;
|
||||
}
|
||||
|
||||
private doUpdateOverlayBorder(direction: DropDirection | undefined): void {
|
||||
this.overlay.style.borderTopWidth = direction === DropDirection.UP ? '2px' : '0px';
|
||||
this.overlay.style.borderLeftWidth = direction === DropDirection.LEFT ? '2px' : '0px';
|
||||
this.overlay.style.borderBottomWidth = direction === DropDirection.DOWN ? '2px' : '0px';
|
||||
this.overlay.style.borderRightWidth = direction === DropDirection.RIGHT ? '2px' : '0px';
|
||||
}
|
||||
|
||||
private doPositionOverlay(options: { top?: string, bottom?: string, left?: string, right?: string, width: string, height: string }): void {
|
||||
|
||||
// Container
|
||||
this.container.style.height = '100%';
|
||||
|
||||
// Overlay
|
||||
this.overlay.style.top = options.top || '';
|
||||
this.overlay.style.left = options.left || '';
|
||||
this.overlay.style.bottom = options.bottom || '';
|
||||
this.overlay.style.right = options.right || '';
|
||||
this.overlay.style.width = options.width;
|
||||
this.overlay.style.height = options.height;
|
||||
}
|
||||
|
||||
|
||||
contains(element: HTMLElement): boolean {
|
||||
return element === this.container || element === this.overlay;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this._disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
|
||||
readonly viewContainer: ViewContainer;
|
||||
@@ -515,8 +712,6 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
private paneItems: IViewPaneItem[] = [];
|
||||
private paneview?: PaneView;
|
||||
|
||||
private static viewTransfer = LocalSelectionTransfer.getInstance<DraggedViewIdentifier>();
|
||||
|
||||
private visible: boolean = false;
|
||||
|
||||
private areExtensionsReady: boolean = false;
|
||||
@@ -583,10 +778,6 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
throw new Error('Could not find container');
|
||||
}
|
||||
|
||||
// Use default pane dnd controller if not specified
|
||||
if (!this.options.dnd) {
|
||||
this.options.dnd = new DefaultPaneDndController();
|
||||
}
|
||||
|
||||
this.viewContainer = container;
|
||||
this.visibleViewsStorageId = `${id}.numberOfVisibleViews`;
|
||||
@@ -949,19 +1140,104 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
this.paneItems.splice(index, 0, paneItem);
|
||||
assertIsDefined(this.paneview).addPane(pane, size, index);
|
||||
|
||||
this._register(addDisposableListener(pane.draggableElement, EventType.DRAG_START, (e: DragEvent) => {
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
let overlay: ViewPaneDropOverlay | undefined;
|
||||
|
||||
// Register as dragged to local transfer
|
||||
ViewPaneContainer.viewTransfer.setData([new DraggedViewIdentifier(pane.id)], DraggedViewIdentifier.prototype);
|
||||
}));
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, 'view', pane.id, {}));
|
||||
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(pane.dropTargetElement, {
|
||||
onDragEnter: (e) => {
|
||||
if (!overlay) {
|
||||
const dropData = e.dragAndDropData.getData();
|
||||
if (dropData.type === 'view' && dropData.id !== pane.id) {
|
||||
|
||||
this._register(addDisposableListener(pane.draggableElement, EventType.DRAG_END, (e: DragEvent) => {
|
||||
if (ViewPaneContainer.viewTransfer.hasData(DraggedViewIdentifier.prototype)) {
|
||||
ViewPaneContainer.viewTransfer.clearData(DraggedViewIdentifier.prototype);
|
||||
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(pane.dropTargetElement, this.options.orientation ?? Orientation.VERTICAL, 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(pane.dropTargetElement, this.options.orientation ?? Orientation.VERTICAL, 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);
|
||||
}
|
||||
|
||||
if (overlay.currentDropOperation === DropDirection.DOWN ||
|
||||
overlay.currentDropOperation === DropDirection.RIGHT) {
|
||||
|
||||
const fromIndex = this.panes.findIndex(p => p.id === dropData.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 (overlay.currentDropOperation === DropDirection.UP ||
|
||||
overlay.currentDropOperation === DropDirection.LEFT) {
|
||||
const fromIndex = this.panes.findIndex(p => p.id === dropData.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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlay?.dispose();
|
||||
overlay = undefined;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class BrowserMain extends Disposable {
|
||||
}
|
||||
|
||||
private restoreBaseTheme(): void {
|
||||
addClass(this.domElement, window.localStorage.getItem('vscode.baseTheme') || getThemeTypeSelector(DARK));
|
||||
addClass(this.domElement, window.localStorage.getItem('vscode.baseTheme') || getThemeTypeSelector(LIGHT) /* Fallback to a light theme by default on web */);
|
||||
}
|
||||
|
||||
private saveBaseTheme(): void {
|
||||
|
||||
Reference in New Issue
Block a user