diff --git a/src/sql/base/browser/ui/panel/media/panel.css b/src/sql/base/browser/ui/panel/media/panel.css
index 1df983cdf5..e3f4fd9051 100644
--- a/src/sql/base/browser/ui/panel/media/panel.css
+++ b/src/sql/base/browser/ui/panel/media/panel.css
@@ -29,6 +29,8 @@ panel {
padding: 0;
justify-content: flex-start;
line-height: 35px;
+ white-space: nowrap;
+ flex: 1;
}
.tabbedPanel .tabList .tab {
@@ -61,7 +63,7 @@ panel {
}
.composite.title .title-actions {
- flex: 1;
+ flex: 1 1 auto;
}
.tab > .tabLabel.active {
@@ -87,6 +89,10 @@ panel {
height: 100%;
}
+.tabbedPanel.vertical .tabList {
+ flex-direction: column;
+}
+
.tabbedPanel > .tab-content {
flex: 1;
position: relative;
@@ -98,4 +104,9 @@ panel {
.tabbedPanel.horizontal > .title > .tabList {
flex-flow: row;
+}
+
+.tabbedPanel > .title > .monaco-scrollable-element {
+ flex: 0 1 auto;
+ width: inherit;
}
\ No newline at end of file
diff --git a/src/sql/base/browser/ui/panel/panel.component.ts b/src/sql/base/browser/ui/panel/panel.component.ts
index fd8d9bc7ca..52ba175477 100644
--- a/src/sql/base/browser/ui/panel/panel.component.ts
+++ b/src/sql/base/browser/ui/panel/panel.component.ts
@@ -13,6 +13,10 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
import * as types from 'vs/base/common/types';
import { mixin } from 'vs/base/common/objects';
+import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
+import { ScrollbarVisibility } from 'vs/base/common/scrollable';
+import { addDisposableListener, EventType } from 'vs/base/browser/dom';
+import { Disposable } from 'vs/base/common/lifecycle';
export interface IPanelOptions {
/**
@@ -40,9 +44,10 @@ let idPool = 0;
@Component({
selector: 'panel',
template: `
+
-
-
+
+
@@ -60,7 +65,7 @@ let idPool = 0;
`
})
-export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
+export class PanelComponent extends Disposable implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
@Input() public options: IPanelOptions;
@Input() public actions: Array
;
@ContentChildren(TabComponent) private _tabs: QueryList;
@@ -72,10 +77,15 @@ export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDe
private _activeTab: TabComponent;
private _actionbar: ActionBar;
private _mru: TabComponent[];
+ private _scrollableElement: ScrollableElement;
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
@ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
- constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) { }
+ @ViewChild('titleContainer', { read: ElementRef }) private _titleContainer: ElementRef;
+ @ViewChild('tabList', { read: ElementRef }) private _tabList: ElementRef;
+ constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
+ super();
+ }
ngOnInit(): void {
this.options = mixin(this.options || {}, defaultOptions, false);
@@ -90,6 +100,39 @@ export class PanelComponent implements AfterContentInit, OnInit, OnChanges, OnDe
}
ngAfterViewInit(): void {
+ let container = this._titleContainer.nativeElement as HTMLElement;
+ let tabList = this._tabList.nativeElement as HTMLElement;
+ container.removeChild(tabList);
+
+ this._scrollableElement = new ScrollableElement(tabList, {
+ horizontal: ScrollbarVisibility.Auto,
+ vertical: ScrollbarVisibility.Hidden,
+ scrollYToX: true,
+ useShadows: false,
+ horizontalScrollbarSize: 3
+ });
+
+ this._scrollableElement.onScroll(e => {
+ tabList.scrollLeft = e.scrollLeft;
+ });
+
+ container.insertBefore(this._scrollableElement.getDomNode(), container.firstChild);
+
+ this._scrollableElement.setScrollDimensions({
+ width: tabList.offsetWidth,
+ scrollWidth: tabList.scrollWidth
+ });
+
+ this._register(addDisposableListener(window, EventType.RESIZE, () => {
+ // Todo: Need to set timeout because we have to make sure that the grids have already rearraged before the getContentHeight gets called.
+ setTimeout(() => {
+ this._scrollableElement.setScrollDimensions({
+ width: tabList.offsetWidth,
+ scrollWidth: tabList.scrollWidth
+ });
+ }, 100);
+ }));
+
if (this.options.layout === NavigationBarLayout.horizontal) {
(this._tabbedPanelRef.nativeElement).classList.add(horizontalLayout);
} else {
diff --git a/src/sql/parts/dashboard/common/dashboardPage.component.ts b/src/sql/parts/dashboard/common/dashboardPage.component.ts
index bc961bb7ea..957a5b21fb 100644
--- a/src/sql/parts/dashboard/common/dashboardPage.component.ts
+++ b/src/sql/parts/dashboard/common/dashboardPage.component.ts
@@ -174,7 +174,7 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
}));
this._tabsDispose.push(this.dashboardService.onAddNewTabs(e => {
- this.loadNewTabs(e);
+ this.loadNewTabs(e, true);
}));
}
@@ -188,7 +188,7 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
this.dashboardService.writeSettings([this.context, 'tabs'].join('.'), writeableConfig, target);
}
- private loadNewTabs(dashboardTabs: IDashboardTab[]) {
+ private loadNewTabs(dashboardTabs: IDashboardTab[], openLastTab: boolean = false) {
if (dashboardTabs && dashboardTabs.length > 0) {
let selectedTabs = dashboardTabs.map(v => {
let container = dashboardHelper.getDashboardContainer(v.container);
@@ -226,10 +226,12 @@ export abstract class DashboardPage extends Disposable implements OnDestroy {
return config;
});
- // put this immediately on the stack so that is ran *after* the tab is rendered
- setTimeout(() => {
- this._panel.selectTab(selectedTabs.pop().id);
- });
+ if (openLastTab) {
+ // put this immediately on the stack so that is ran *after* the tab is rendered
+ setTimeout(() => {
+ this._panel.selectTab(selectedTabs.pop().id);
+ });
+ }
}
}
diff --git a/src/sql/parts/dashboard/common/dashboardPanel.css b/src/sql/parts/dashboard/common/dashboardPanel.css
index 5b3f82987e..5de4d65f2c 100644
--- a/src/sql/parts/dashboard/common/dashboardPanel.css
+++ b/src/sql/parts/dashboard/common/dashboardPanel.css
@@ -9,12 +9,12 @@ panel.dashboard-panel > .tabbedPanel {
box-sizing: border-box;
}
-panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header .tab > .tabLabel.active {
+panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header .tab > .tabLabel.active {
border-bottom: 0px solid;
}
panel.dashboard-panel > .tabbedPanel > .title > .title-actions,
-panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header {
+panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
box-sizing: border-box;
border: 1px solid transparent;
}
\ No newline at end of file
diff --git a/src/sql/parts/dashboard/common/dashboardPanelStyles.ts b/src/sql/parts/dashboard/common/dashboardPanelStyles.ts
index b77c1265cd..6b9bdcbf76 100644
--- a/src/sql/parts/dashboard/common/dashboardPanelStyles.ts
+++ b/src/sql/parts/dashboard/common/dashboardPanelStyles.ts
@@ -15,21 +15,22 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabActiveForeground = theme.getColor(TAB_ACTIVE_FOREGROUND);
if (tabActiveBackground || tabActiveForeground) {
collector.addRule(`
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab:hover .tabLabel,
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab .tabLabel.active {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab:hover .tabLabel,
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel.active {
color: ${tabActiveForeground};
border-bottom: 0px solid;
}
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header.active {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
background-color: ${tabActiveBackground};
+ outline-color: ${tabActiveBackground};
}
- panel.dashboard-panel > .tabbedPanel.horizontal > .title > .tabList .tab-header.active {
+ panel.dashboard-panel > .tabbedPanel.horizontal > .title > .monaco-scrollable-element > .tabList .tab-header.active {
border-bottom-color: transparent;
}
- panel.dashboard-panel > .tabbedPanel.vertical > .title > .tabList .tab-header.active {
+ panel.dashboard-panel > .tabbedPanel.vertical > .title > .monaco-scrollable-element > .tabList .tab-header.active {
border-right-color: transparent;
}
`);
@@ -38,7 +39,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const activeTabBorderColor = theme.getColor(TAB_ACTIVE_BORDER);
if (activeTabBorderColor) {
collector.addRule(`
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header.active {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
box-shadow: ${activeTabBorderColor} 0 -1px inset;
}
`);
@@ -49,11 +50,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabInactiveForeground = theme.getColor(TAB_INACTIVE_FOREGROUND);
if (tabInactiveBackground || tabInactiveForeground) {
collector.addRule(`
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab .tabLabel {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel {
color: ${tabInactiveForeground};
}
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
background-color: ${tabInactiveBackground};
}
`);
@@ -73,18 +74,10 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabBoarder = theme.getColor(TAB_BORDER);
if (tabBoarder) {
collector.addRule(`
- panel.dashboard-panel > .tabbedPanel > .title > .tabList .tab-header {
+ panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
border-right-color: ${tabBoarder};
border-bottom-color: ${tabBoarder};
}
-
- panel.dashboard-panel > .tabbedPanel.horizontal > .title > .title-actions {
- border-bottom-color: ${tabBoarder};
- }
-
- panel.dashboard-panel > .tabbedPanel.vertical > .title > .title-actions {
- border-right-color: ${tabBoarder};
- }
`);
}