diff --git a/packages/widgets/src/dockpanel.ts b/packages/widgets/src/dockpanel.ts index 593000d81..6c6db69f9 100644 --- a/packages/widgets/src/dockpanel.ts +++ b/packages/widgets/src/dockpanel.ts @@ -74,6 +74,9 @@ class DockPanel extends Widget { if (options.tabsMovable !== undefined) { this._tabsMovable = options.tabsMovable; } + if(options.tabsConstrained !== undefined){ + this._tabsConstrained = options.tabsConstrained; + } // Toggle the CSS mode attribute. this.dataset['mode'] = this._mode; @@ -204,6 +207,7 @@ class DockPanel extends Widget { get tabsMovable(): boolean { return this._tabsMovable; } + /** * Enable / Disable draggable / movable tabs. @@ -213,6 +217,20 @@ class DockPanel extends Widget { each(this.tabBars(), (tabbar) => { tabbar.tabsMovable = value }); } + /** + * Whether the tabs are constrained to their source dock panel + */ + get tabsConstrained(): boolean{ + return this._tabsConstrained; + } + + /** + * Constrain/Allow tabs to be dragged outside of this dock panel + */ + set tabsConstrained(value:boolean) { + this._tabsConstrained = value; + } + /** * Whether the dock panel is empty. */ @@ -516,7 +534,7 @@ class DockPanel extends Widget { // Show the drop indicator overlay and update the drop // action based on the drop target zone under the mouse. - if (this._showOverlay(event.clientX, event.clientY) === 'invalid') { + if ((this._tabsConstrained && event.source !== this) || this._showOverlay(event.clientX, event.clientY) === 'invalid') { event.dropAction = 'none'; } else { event.dropAction = event.proposedAction; @@ -970,6 +988,7 @@ class DockPanel extends Widget { mimeData, dragImage, proposedAction: 'move', supportedActions: 'move', + source: this }); // Hide the tab node in the original tab. @@ -996,6 +1015,7 @@ class DockPanel extends Widget { private _drag: Drag | null = null; private _renderer: DockPanel.IRenderer; private _tabsMovable: boolean = true; + private _tabsConstrained: boolean = false; private _pressData: Private.IPressData | null = null; private _layoutModified = new Signal(this); } @@ -1035,7 +1055,7 @@ namespace DockPanel { /** * The mode for the dock panel. * - * The deafult is `'multiple-document'`. + * The default is `'multiple-document'`. */ mode?: DockPanel.Mode; @@ -1051,6 +1071,13 @@ namespace DockPanel { * The default is `'true'`. */ tabsMovable?: boolean; + + /** + * Constrain tabs to this dock panel + * + * The default is `'false'`. + */ + tabsConstrained?: boolean; } /** diff --git a/packages/widgets/tests/src/dockpanel.spec.ts b/packages/widgets/tests/src/dockpanel.spec.ts index c95cecc6b..c45ea5b5d 100644 --- a/packages/widgets/tests/src/dockpanel.spec.ts +++ b/packages/widgets/tests/src/dockpanel.spec.ts @@ -40,12 +40,18 @@ describe('@lumino/widgets', () => { let renderer = Object.create(TabBar.defaultRenderer); let panel = new DockPanel({ tabsMovable: true, - renderer + renderer, + tabsConstrained:true }); each(panel.tabBars(), (tabBar) => { expect(tabBar.tabsMovable).to.equal(true); }); each(panel.tabBars(), (tabBar) => { expect(tabBar.renderer).to.equal(renderer); }); }); + it('should not have tabs constrained by default', ()=>{ + let panel = new DockPanel(); + expect(panel.tabsConstrained).to.equal(false); + }) + it('should add a `lm-DockPanel` class', () => { let panel = new DockPanel(); expect(panel.hasClass('lm-DockPanel')).to.equal(true); @@ -89,4 +95,4 @@ describe('@lumino/widgets', () => { }); -}); \ No newline at end of file +});