diff --git a/src/sql/base/browser/ui/panel/media/panel.css b/src/sql/base/browser/ui/panel/media/panel.css
index f69b14815e..27942248b7 100644
--- a/src/sql/base/browser/ui/panel/media/panel.css
+++ b/src/sql/base/browser/ui/panel/media/panel.css
@@ -21,6 +21,12 @@ panel {
.tabbedPanel .composite.title {
display: flex;
flex: 0 0 auto;
+ position: relative;
+}
+
+.tabbedPanel .tabContainer {
+ flex: 1 1 auto;
+ overflow: hidden;
}
.tabbedPanel .tabList {
@@ -31,6 +37,7 @@ panel {
line-height: 35px;
white-space: nowrap;
flex: 1;
+ height: 100%;
}
.tabbedPanel .tabList .tab {
@@ -88,17 +95,13 @@ panel {
}
.composite.title .title-actions {
- flex: 1 1 auto;
+ flex: 0 0 auto;
}
.tab > .tabLabel.active {
border-bottom: 1px solid;
}
-.composite.title ~ tab.fullsize > :first-child {
- height: calc(100% - 38px);
-}
-
.tabbedPanel .title-actions .panel-actions .actions-container {
justify-content: flex-start;
}
diff --git a/src/sql/base/browser/ui/panel/panel.component.ts b/src/sql/base/browser/ui/panel/panel.component.ts
index 0821508a16..cca5d7db9b 100644
--- a/src/sql/base/browser/ui/panel/panel.component.ts
+++ b/src/sql/base/browser/ui/panel/panel.component.ts
@@ -7,13 +7,13 @@ import { Component, ContentChildren, QueryList, AfterContentInit, Inject, forwar
import { TabComponent } from './tab.component';
import { TabHeaderComponent } from './tabHeader.component';
+import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import './panelStyles';
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';
@@ -46,12 +46,13 @@ let idPool = 0;
@Component({
selector: 'panel',
template: `
-
-
-
-
-
-
+
+
+
@@ -67,11 +68,12 @@ let idPool = 0;
`
})
-export class PanelComponent extends Disposable implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
+export class PanelComponent extends Disposable {
@Input() public options: IPanelOptions;
@Input() public actions: Array
;
@ContentChildren(TabComponent) private _tabs: QueryList;
@ViewChildren(TabHeaderComponent) private _headerTabs: QueryList;
+ @ViewChild(ScrollableDirective) private scrollable: ScrollableDirective;
@Output() public onTabChange = new EventEmitter();
@Output() public onTabClose = new EventEmitter();
@@ -79,12 +81,11 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
private _activeTab: TabComponent;
private _actionbar: ActionBar;
private _mru: TabComponent[];
- private _scrollableElement: ScrollableElement;
+
+ private ScrollbarVisibility = ScrollbarVisibility;
+ private NavigationBarLayout = NavigationBarLayout;
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
- @ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
- @ViewChild('titleContainer', { read: ElementRef }) private _titleContainer: ElementRef;
- @ViewChild('tabList', { read: ElementRef }) private _tabList: ElementRef;
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
super();
}
@@ -96,51 +97,14 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
ngAfterContentInit(): void {
if (this._tabs && this._tabs.length > 0) {
- this._activeTab = this._tabs.first;
- this._activeTab.active = true;
- }
- }
-
- ngAfterViewInit(): void {
- if (!this.options.showTabsWhenOne ? this._tabs.length !== 1 : true) {
- 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.selectTab(this._tabs.first);
+ } else {
+ const sub = this._tabs.changes.subscribe(() => {
+ if (this._tabs && this._tabs.length > 0) {
+ this.selectTab(this._tabs.first);
+ sub.unsubscribe();
+ }
});
-
- 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 {
- (this._tabbedPanelRef.nativeElement).classList.add(verticalLayout);
- }
}
}
@@ -154,6 +118,17 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
}
}
+ ngAfterViewInit(): void {
+ this._tabs.changes.subscribe(() => {
+ if (this.scrollable) {
+ this.scrollable.layout();
+ }
+ });
+ if (this.scrollable) {
+ this.scrollable.layout();
+ }
+ }
+
ngOnDestroy() {
if (this._actionbar) {
this._actionbar.dispose();
@@ -210,12 +185,6 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
this.setMostRecentlyUsed(tab);
this._activeTab.active = true;
- // Make the tab header focus on the new selected tab
- let activeTabHeader = this._headerTabs.find(i => i.tab === this._activeTab);
- if (activeTabHeader) {
- activeTabHeader.focusOnTabHeader();
- }
-
this.onTabChange.emit(tab);
});
}
diff --git a/src/sql/base/browser/ui/panel/panel.module.ts b/src/sql/base/browser/ui/panel/panel.module.ts
index 164806670b..c1f9d345bf 100644
--- a/src/sql/base/browser/ui/panel/panel.module.ts
+++ b/src/sql/base/browser/ui/panel/panel.module.ts
@@ -9,9 +9,11 @@ import { TabComponent } from './tab.component';
import { TabHeaderComponent } from './tabHeader.component';
import { PanelComponent } from './panel.component';
+import { ScrollableModule } from 'sql/base/browser/ui/scrollable/scrollable.module';
+
@NgModule({
- imports: [CommonModule],
+ imports: [CommonModule, ScrollableModule],
exports: [TabComponent, PanelComponent],
declarations: [TabComponent, TabHeaderComponent, PanelComponent]
})
-export class PanelModule { }
\ No newline at end of file
+export class PanelModule { }
diff --git a/src/sql/base/browser/ui/panel/panelStyles.ts b/src/sql/base/browser/ui/panel/panelStyles.ts
index 532ec0f998..c385fcd843 100644
--- a/src/sql/base/browser/ui/panel/panelStyles.ts
+++ b/src/sql/base/browser/ui/panel/panelStyles.ts
@@ -15,13 +15,13 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
if (titleActive || titleActiveBorder) {
collector.addRule(`
- .tabbedPanel > .title > .tabList .tab:hover .tabLabel,
- .tabbedPanel > .title > .tabList .tab .tabLabel.active {
+ .tabbedPanel > .title .tabList .tab:hover .tabLabel,
+ .tabbedPanel > .title .tabList .tab .tabLabel.active {
color: ${titleActive};
border-bottom-color: ${titleActiveBorder};
}
- .tabbedPanel > .title > .tabList .tab-header.active {
+ .tabbedPanel > .title .tabList .tab-header.active {
outline: none;
}
`);
@@ -31,7 +31,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const titleInactive = theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND);
if (titleInactive) {
collector.addRule(`
- .tabbedPanel > .title > .tabList .tab .tabLabel {
+ .tabbedPanel > .title .tabList .tab .tabLabel {
color: ${titleInactive};
}
`);
@@ -41,7 +41,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const focusBorderColor = theme.getColor(focusBorder);
if (focusBorderColor) {
collector.addRule(`
- .tabbedPanel > .title > .tabList .tab .tabLabel:focus {
+ .tabbedPanel > .title .tabList .tab .tabLabel:focus {
color: ${titleActive};
border-bottom-color: ${focusBorderColor} !important;
border-bottom: 1px solid;
@@ -54,8 +54,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const outline = theme.getColor(activeContrastBorder);
if (outline) {
collector.addRule(`
- .tabbedPanel > .title > .tabList .tab-header.active,
- .tabbedPanel > .title > .tabList .tab-header:hover {
+ .tabbedPanel > .title .tabList .tab-header.active,
+ .tabbedPanel > .title .tabList .tab-header:hover {
outline-color: ${outline};
outline-width: 1px;
outline-style: solid;
@@ -63,7 +63,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
outline-offset: -5px;
}
- .tabbedPanel > .title > .tabList .tab-header:hover:not(.active) {
+ .tabbedPanel > .title .tabList .tab-header:hover:not(.active) {
outline-style: dashed;
}
`);
diff --git a/src/sql/base/browser/ui/panel/tab.component.ts b/src/sql/base/browser/ui/panel/tab.component.ts
index e19ae4b81b..0ab41ee8e5 100644
--- a/src/sql/base/browser/ui/panel/tab.component.ts
+++ b/src/sql/base/browser/ui/panel/tab.component.ts
@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { Component, Input, ContentChild, OnDestroy } from '@angular/core';
+import { Component, Input, ContentChild, OnDestroy, TemplateRef, ChangeDetectorRef, forwardRef, Inject } from '@angular/core';
import { Action } from 'vs/base/common/actions';
@@ -13,13 +13,14 @@ export abstract class TabChild {
@Component({
selector: 'tab',
template: `
-
-
+
+
`
})
export class TabComponent implements OnDestroy {
@ContentChild(TabChild) private _child: TabChild;
+ @ContentChild(TemplateRef) templateRef;
@Input() public title: string;
@Input() public canClose: boolean;
@Input() public actions: Array
;
@@ -27,9 +28,18 @@ export class TabComponent implements OnDestroy {
public _active = false;
@Input() public identifier: string;
@Input() private visibilityType: 'if' | 'visibility' = 'if';
+ private rendered = false;
+
+ constructor(
+ @Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
+ ) { }
public set active(val: boolean) {
this._active = val;
+ if (this.active) {
+ this.rendered = true;
+ }
+ this._cd.detectChanges();
if (this.active && this._child) {
this._child.layout();
}
@@ -45,4 +55,21 @@ export class TabComponent implements OnDestroy {
}
}
+ shouldBeIfed(): boolean {
+ if (this.active) {
+ return true;
+ } else if (this.visibilityType === 'visibility' && this.rendered) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ shouldBeHidden(): boolean {
+ if (this.visibilityType === 'visibility' && !this.active) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/sql/base/browser/ui/panel/tabHeader.component.ts b/src/sql/base/browser/ui/panel/tabHeader.component.ts
index 55599442d2..dd594126b7 100644
--- a/src/sql/base/browser/ui/panel/tabHeader.component.ts
+++ b/src/sql/base/browser/ui/panel/tabHeader.component.ts
@@ -19,7 +19,7 @@ import { CloseTabAction } from './tabActions';
@Component({
selector: 'tab-header',
template: `
-