SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.tabbedPanel {
border-top-color: rgba(128, 128, 128, 0.35);
border-top-width: 1;
border-top-style: solid;
box-sizing: border-box;
}
.tabbedPanel .composite.title {
display: flex;
}
.tabbedPanel .tabList {
display: flex;
margin: 0 auto;
padding: 0;
justify-content: flex-start;
flex-flow: row;
line-height: 35px;
}
.tabbedPanel .tabList > .tab {
cursor: pointer;
}
.tabbedPanel .tabList > .tab > .tabLabel {
text-transform: uppercase;
margin-left: 16px;
margin-right: 16px;
font-size: 11px;
padding-bottom: 4px;
}
.tabbedPanel .composite.title .title-actions .action-label {
display: block;
height: 35px;
line-height: 35px;
min-width: 28px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
}
.composite.title .title-actions {
flex: 1;
}
.tab > .tabLabel.active {
border-bottom: 1px solid;
}
.composite.title ~ tab.fullsize > :first-child {
height: calc(100% - 38px);
}

View File

@@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Component, ContentChildren, QueryList, AfterContentInit, Inject, forwardRef, NgZone, OnInit, Input } from '@angular/core';
import { TabComponent } from './tab.component';
import './panelStyles';
import * as types from 'vs/base/common/types';
import { mixin } from 'vs/base/common/objects';
export interface IPanelOptions {
/**
* Whether or not to show the tabs if there is only one tab present
*/
showTabsWhenOne?: boolean;
}
const defaultOptions: IPanelOptions = {
showTabsWhenOne: true
};
@Component({
selector: 'panel',
template: `
<div class="tabbedPanel fullsize">
<div *ngIf="!options.showTabsWhenOne ? _tabs.length !== 1 : true" class="composite title">
<div class="tabList">
<div *ngFor="let tab of _tabs" class="tab" (click)="selectTab(tab)">
<a class="tabLabel" [class.active]="tab.active">
{{tab.title}}
</a>
</div>
</div>
<div class="title-actions">
</div>
</div>
<ng-content class="fullsize"></ng-content>
</div>
`
})
export class PanelComponent implements AfterContentInit, OnInit {
@Input() public options: IPanelOptions;
@ContentChildren(TabComponent) private _tabs: QueryList<TabComponent>;
private _activeTab: TabComponent;
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) { }
ngOnInit(): void {
this.options = mixin(this.options || {}, defaultOptions, false);
}
ngAfterContentInit(): void {
if (this._tabs && this._tabs.length > 0) {
this._activeTab = this._tabs.first;
this._activeTab.active = true;
}
}
/**
* Select a tab based on index (unrecommended)
* @param index index of tab in the html
*/
selectTab(index: number)
/**
* Select a tab based on the identifier that was passed into the tab
* @param identifier specified identifer of the tab
*/
selectTab(identifier: string);
/**
* Select a tab directly if you have access to the object
* @param tab tab to navigate to
*/
selectTab(tab: TabComponent);
selectTab(input: TabComponent | number | string) {
if (this._tabs && this._tabs.length > 0) {
let tab: TabComponent;
if (input instanceof TabComponent) {
tab = input;
} else if (types.isNumber(input)) {
tab = this._tabs[input];
} else if (types.isString(input)) {
tab = this._tabs.find(i => i.identifier === input);
}
this._zone.run(() => {
if (this._activeTab) {
this._activeTab.active = false;
}
this._activeTab = tab;
this._activeTab.active = true;
});
}
}
}

View File

@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TabComponent } from './tab.component';
import { PanelComponent } from './panel.component';
@NgModule({
imports: [CommonModule],
exports: [TabComponent, PanelComponent],
declarations: [TabComponent, PanelComponent]
})
export class PanelModule { }

View File

@@ -0,0 +1,166 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IThemable } from 'vs/platform/theme/common/styler';
import * as objects from 'vs/base/common/objects';
import Event, { Emitter } from 'vs/base/common/event';
import { Dimension, Builder } from 'vs/base/browser/builder';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner } from 'vs/base/common/actions';
import { IActionOptions, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import './panelStyles';
export interface IPanelStyles {
}
export interface IPanelView {
render(container: HTMLElement): void;
layout(dimension: Dimension): void;
}
export interface IPanelTab {
title: string;
identifier: string;
view: IPanelView;
}
interface IInternalPanelTab extends IPanelTab {
header: HTMLElement;
label: HTMLElement;
}
export type PanelTabIdentifier = string;
export class TabbedPanel implements IThemable {
private _tabMap = new Map<PanelTabIdentifier, IInternalPanelTab>();
private _shownTab: PanelTabIdentifier;
public readonly headersize = 35;
private _header: HTMLElement;
private _tabList: HTMLElement;
private _actionbar: ActionBar;
private _body: HTMLElement;
private _currentDimensions: Dimension;
private _collapsed = false;
private _parent: HTMLElement;
private _onTabChange = new Emitter<PanelTabIdentifier>();
public onTabChange: Event<PanelTabIdentifier> = this._onTabChange.event;
constructor(private container: HTMLElement) {
this._parent = document.createElement('div');
this._parent.className = 'tabbedPanel';
container.appendChild(this._parent);
this._header = document.createElement('div');
this._header.className = 'composite title';
this._tabList = document.createElement('div');
this._tabList.className = 'tabList';
this._tabList.style.height = this.headersize + 'px';
this._header.appendChild(this._tabList);
let actionbarcontainer = document.createElement('div');
actionbarcontainer.className = 'title-actions';
this._actionbar = new ActionBar(actionbarcontainer);
this._header.appendChild(actionbarcontainer);
this._parent.appendChild(this._header);
this._body = document.createElement('div');
this._body.className = 'tabBody';
this._parent.appendChild(this._body);
}
public pushTab(tab: IPanelTab): PanelTabIdentifier {
let internalTab = objects.clone(tab) as IInternalPanelTab;
this._tabMap.set(tab.identifier, internalTab);
this._createTab(internalTab);
if (!this._shownTab) {
this.showTab(tab.identifier);
}
return tab.identifier as PanelTabIdentifier;
}
public pushAction(arg: IAction | IAction[], options: IActionOptions = {}): void {
this._actionbar.push(arg, options);
}
public set actionBarContext(context: any) {
this._actionbar.context = context;
}
private _createTab(tab: IInternalPanelTab): void {
let tabElement = document.createElement('div');
tabElement.className = 'tab';
let tabLabel = document.createElement('a');
tabLabel.className = 'tabLabel';
tabLabel.innerText = tab.title;
tabElement.appendChild(tabLabel);
addDisposableListener(tabElement, EventType.CLICK, (e) => this.showTab(tab.identifier));
this._tabList.appendChild(tabElement);
tab.header = tabElement;
tab.label = tabLabel;
}
public showTab(id: PanelTabIdentifier): void {
if (this._shownTab && this._shownTab === id) {
return;
}
if (this._shownTab) {
this._tabMap.get(this._shownTab).label.classList.remove('active');
}
this._shownTab = id;
new Builder(this._body).empty();
let tab = this._tabMap.get(this._shownTab);
tab.label.classList.add('active');
tab.view.render(this._body);
this._onTabChange.fire(id);
if (this._currentDimensions) {
this._layoutCurrentTab(new Dimension(this._currentDimensions.width, this._currentDimensions.height - this.headersize));
}
}
public removeTab(tab: PanelTabIdentifier) {
this._tabMap.get(tab).header.remove();
this._tabMap.delete(tab);
}
public style(styles: IPanelStyles): void {
}
public layout(dimension: Dimension): void {
this._currentDimensions = dimension;
this._header.style.width = dimension.width + 'px';
this._body.style.width = dimension.width + 'px';
this._body.style.height = (dimension.height - this.headersize) + 'px';
this._layoutCurrentTab(new Dimension(dimension.width, dimension.height - this.headersize));
}
private _layoutCurrentTab(dimension: Dimension): void {
if (this._shownTab) {
this._tabMap.get(this._shownTab).view.layout(dimension);
}
}
public focus(): void {
}
public set collapsed(val: boolean) {
if (val === this._collapsed) {
return;
}
this._collapsed = val === false ? false : true;
if (this.collapsed) {
this._body.remove();
} else {
this._parent.appendChild(this._body);
}
}
public get collapsed(): boolean {
return this._collapsed;
}
}

View File

@@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/panel';
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
// Title Active
const titleActive = theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND);
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 {
color: ${titleActive};
border-bottom-color: ${titleActiveBorder};
}
`);
}
// Title Inactive
const titleInactive = theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND);
if (titleInactive) {
collector.addRule(`
.tabbedPanel > .title > .tabList > .tab .tabLabel {
color: ${titleInactive};
}
`);
}
// Title focus
const focusBorderColor = theme.getColor(focusBorder);
if (focusBorderColor) {
collector.addRule(`
.tabbedPanel > .title > .tabList > .tab .tabLabel:focus {
color: ${titleActive};
border-bottom-color: ${focusBorderColor} !important;
border-bottom: 1px solid;
outline: none;
}
`);
}
// Styling with Outline color (e.g. high contrast theme)
const outline = theme.getColor(activeContrastBorder);
if (outline) {
const outline = theme.getColor(activeContrastBorder);
collector.addRule(`
.tabbedPanel > .title > .tabList > .tab .tabLabel.active,
.tabbedPanel > .title > .tabList > .tab .tabLabel:hover {
outline-color: ${outline};
outline-width: 1px;
outline-style: solid;
border-bottom: none;
padding-bottom: 0;
outline-offset: 3px;
}
.tabbedPanel > .title > .tabList > .tab .tabLabel:hover:not(.active) {
outline-style: dashed;
}
`);
}
});

View File

@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* 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 } from '@angular/core';
export abstract class TabChild {
public abstract layout(): void;
}
@Component({
selector: 'tab',
template: `
<div *ngIf="active" class="fullsize">
<ng-content class="body fullsize"></ng-content>
</div>
`
})
export class TabComponent {
@ContentChild(TabChild) private _child: TabChild;
@Input() public title: string;
public _active = false;
@Input() public identifier: string;
public set active(val: boolean) {
this._active = val;
if (this.active && this._child) {
this._child.layout();
}
}
public get active(): boolean {
return this._active;
}
}