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,104 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-action-bar {
text-align: right;
overflow: hidden;
white-space: nowrap;
}
.monaco-action-bar .actions-container {
display: flex;
margin: 0 auto;
padding: 0;
width: 100%;
justify-content: flex-end;
}
.monaco-action-bar.vertical .actions-container {
display: inline-block;
}
.monaco-action-bar .action-item {
cursor: pointer;
display: inline-block;
-ms-transition: -ms-transform 50ms ease;
-webkit-transition: -webkit-transform 50ms ease;
-moz-transition: -moz-transform 50ms ease;
-o-transition: -o-transform 50ms ease;
transition: transform 50ms ease;
position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */
}
.monaco-action-bar .action-item.disabled {
cursor: default;
}
.monaco-action-bar.animated .action-item.active {
-ms-transform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */
-webkit-transform: scale(1.272019649, 1.272019649);
-moz-transform: scale(1.272019649, 1.272019649);
-o-transform: scale(1.272019649, 1.272019649);
transform: scale(1.272019649, 1.272019649);
}
.monaco-action-bar .action-item .icon {
display: inline-block;
}
.monaco-action-bar .action-label {
font-size: 12px;
margin-right: 0.3em;
}
.monaco-action-bar .action-label.octicon {
font-size: 15px;
line-height: 35px;
text-align: center;
}
.monaco-action-bar .action-item.disabled .action-label,
.monaco-action-bar .action-item.disabled .action-label:hover {
opacity: 0.4;
}
/* Vertical actions */
.monaco-action-bar.vertical {
text-align: left;
}
.monaco-action-bar.vertical .action-item {
display: block;
}
.monaco-action-bar.vertical .action-label.separator {
display: block;
border-bottom: 1px solid #bbb;
padding-top: 1px;
margin-left: .8em;
margin-right: .8em;
}
.monaco-action-bar.animated.vertical .action-item.active {
-ms-transform: translate(5px, 0);
-webkit-transform: translate(5px, 0);
-moz-transform: translate(5px, 0);
-o-transform: translate(5px, 0);
transform: translate(5px, 0);
}
.secondary-actions .monaco-action-bar .action-label {
margin-left: 6px;
}
/* Action Items */
.monaco-action-bar .action-item.select-container {
overflow: hidden; /* somehow the dropdown overflows its container, we prevent it here to not push */
flex: 1;
max-width: 170px;
min-width: 60px;
margin-right: 10px;
}

View File

@@ -0,0 +1,768 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./actionbar';
import nls = require('vs/nls');
import lifecycle = require('vs/base/common/lifecycle');
import { TPromise } from 'vs/base/common/winjs.base';
import { Builder, $ } from 'vs/base/browser/builder';
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner } from 'vs/base/common/actions';
import DOM = require('vs/base/browser/dom');
import { EventType as CommonEventType } from 'vs/base/common/events';
import types = require('vs/base/common/types');
import { IEventEmitter, EventEmitter } from 'vs/base/common/eventEmitter';
import { Gesture, EventType } from 'vs/base/browser/touch';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
export interface IActionItem extends IEventEmitter {
actionRunner: IActionRunner;
setActionContext(context: any): void;
render(element: HTMLElement): void;
isEnabled(): boolean;
focus(fromRight?: boolean): void;
blur(): void;
dispose(): void;
}
export interface IBaseActionItemOptions {
draggable?: boolean;
isMenu?: boolean;
}
export class BaseActionItem extends EventEmitter implements IActionItem {
public builder: Builder;
public _callOnDispose: lifecycle.IDisposable[];
public _context: any;
public _action: IAction;
private gesture: Gesture;
private _actionRunner: IActionRunner;
constructor(context: any, action: IAction, protected options?: IBaseActionItemOptions) {
super();
this._callOnDispose = [];
this._context = context || this;
this._action = action;
if (action instanceof Action) {
this._callOnDispose.push(action.onDidChange(event => {
if (!this.builder) {
// we have not been rendered yet, so there
// is no point in updating the UI
return;
}
this._handleActionChangeEvent(event);
}));
}
}
protected _handleActionChangeEvent(event: IActionChangeEvent): void {
if (event.enabled !== void 0) {
this._updateEnabled();
}
if (event.checked !== void 0) {
this._updateChecked();
}
if (event.class !== void 0) {
this._updateClass();
}
if (event.label !== void 0) {
this._updateLabel();
this._updateTooltip();
}
if (event.tooltip !== void 0) {
this._updateTooltip();
}
}
public get callOnDispose() {
return this._callOnDispose;
}
public set actionRunner(actionRunner: IActionRunner) {
this._actionRunner = actionRunner;
}
public get actionRunner(): IActionRunner {
return this._actionRunner;
}
public getAction(): IAction {
return this._action;
}
public isEnabled(): boolean {
return this._action.enabled;
}
public setActionContext(newContext: any): void {
this._context = newContext;
}
public render(container: HTMLElement): void {
this.builder = $(container);
this.gesture = new Gesture(container);
const enableDragging = this.options && this.options.draggable;
if (enableDragging) {
container.draggable = true;
}
this.builder.on(EventType.Tap, e => this.onClick(e));
this.builder.on(DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => {
if (!enableDragging) {
DOM.EventHelper.stop(e); // do not run when dragging is on because that would disable it
}
if (this._action.enabled && e.button === 0) {
this.builder.addClass('active');
}
});
this.builder.on(DOM.EventType.CLICK, (e: MouseEvent) => {
DOM.EventHelper.stop(e, true);
// See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard
// > Writing to the clipboard
// > You can use the "cut" and "copy" commands without any special
// permission if you are using them in a short-lived event handler
// for a user action (for example, a click handler).
// => to get the Copy and Paste context menu actions working on Firefox,
// there should be no timeout here
if (this.options && this.options.isMenu) {
this.onClick(e);
} else {
setTimeout(() => this.onClick(e), 50);
}
});
this.builder.on([DOM.EventType.MOUSE_UP, DOM.EventType.MOUSE_OUT], (e: MouseEvent) => {
DOM.EventHelper.stop(e);
this.builder.removeClass('active');
});
}
public onClick(event: Event): void {
DOM.EventHelper.stop(event, true);
let context: any;
if (types.isUndefinedOrNull(this._context)) {
context = event;
} else {
context = this._context;
context.event = event;
}
this._actionRunner.run(this._action, context);
}
public focus(): void {
if (this.builder) {
this.builder.domFocus();
}
}
public blur(): void {
if (this.builder) {
this.builder.domBlur();
}
}
protected _updateEnabled(): void {
// implement in subclass
}
protected _updateLabel(): void {
// implement in subclass
}
protected _updateTooltip(): void {
// implement in subclass
}
protected _updateClass(): void {
// implement in subclass
}
protected _updateChecked(): void {
// implement in subclass
}
public dispose(): void {
super.dispose();
if (this.builder) {
this.builder.destroy();
this.builder = null;
}
if (this.gesture) {
this.gesture.dispose();
this.gesture = null;
}
this._callOnDispose = lifecycle.dispose(this._callOnDispose);
}
}
export class Separator extends Action {
public static ID = 'vs.actions.separator';
constructor(label?: string, order?: number) {
super(Separator.ID, label, label ? 'separator text' : 'separator');
this.checked = false;
this.radio = false;
this.enabled = false;
this.order = order;
}
}
export interface IActionItemOptions extends IBaseActionItemOptions {
icon?: boolean;
label?: boolean;
keybinding?: string;
}
export class ActionItem extends BaseActionItem {
protected $e: Builder;
protected options: IActionItemOptions;
private cssClass: string;
constructor(context: any, action: IAction, options: IActionItemOptions = {}) {
super(context, action, options);
this.options = options;
this.options.icon = options.icon !== undefined ? options.icon : false;
this.options.label = options.label !== undefined ? options.label : true;
this.cssClass = '';
}
public render(container: HTMLElement): void {
super.render(container);
this.$e = $('a.action-label').appendTo(this.builder);
if (this._action.id === Separator.ID) {
// A separator is a presentation item
this.$e.attr({ role: 'presentation' });
} else {
if (this.options.isMenu) {
this.$e.attr({ role: 'menuitem' });
} else {
this.$e.attr({ role: 'button' });
}
}
if (this.options.label && this.options.keybinding) {
$('span.keybinding').text(this.options.keybinding).appendTo(this.builder);
}
this._updateClass();
this._updateLabel();
this._updateTooltip();
this._updateEnabled();
this._updateChecked();
}
public focus(): void {
super.focus();
this.$e.domFocus();
}
public _updateLabel(): void {
if (this.options.label) {
this.$e.text(this.getAction().label);
}
}
public _updateTooltip(): void {
let title: string = null;
if (this.getAction().tooltip) {
title = this.getAction().tooltip;
} else if (!this.options.label && this.getAction().label && this.options.icon) {
title = this.getAction().label;
if (this.options.keybinding) {
title = nls.localize({ key: 'titleLabel', comment: ['action title', 'action keybinding'] }, "{0} ({1})", title, this.options.keybinding);
}
}
if (title) {
this.$e.attr({ title: title });
}
}
public _updateClass(): void {
if (this.cssClass) {
this.$e.removeClass(this.cssClass);
}
if (this.options.icon) {
this.cssClass = this.getAction().class;
this.$e.addClass('icon');
if (this.cssClass) {
this.$e.addClass(this.cssClass);
}
this._updateEnabled();
} else {
this.$e.removeClass('icon');
}
}
public _updateEnabled(): void {
if (this.getAction().enabled) {
this.builder.removeClass('disabled');
this.$e.removeClass('disabled');
this.$e.attr({ tabindex: 0 });
} else {
this.builder.addClass('disabled');
this.$e.addClass('disabled');
DOM.removeTabIndexAndUpdateFocus(this.$e.getHTMLElement());
}
}
public _updateChecked(): void {
if (this.getAction().checked) {
this.$e.addClass('checked');
} else {
this.$e.removeClass('checked');
}
}
public _updateRadio(): void {
if (this.getAction().radio) {
this.$e.addClass('radio');
} else {
this.$e.removeClass('radio');
}
}
}
export enum ActionsOrientation {
HORIZONTAL = 1,
VERTICAL = 2
}
export interface IActionItemProvider {
(action: IAction): IActionItem;
}
export interface IActionBarOptions {
orientation?: ActionsOrientation;
context?: any;
actionItemProvider?: IActionItemProvider;
actionRunner?: IActionRunner;
ariaLabel?: string;
animated?: boolean;
isMenu?: boolean;
}
let defaultOptions: IActionBarOptions = {
orientation: ActionsOrientation.HORIZONTAL,
context: null
};
export interface IActionOptions extends IActionItemOptions {
index?: number;
}
export class ActionBar extends EventEmitter implements IActionRunner {
public options: IActionBarOptions;
private _actionRunner: IActionRunner;
private _context: any;
// Items
public items: IActionItem[];
private focusedItem: number;
private focusTracker: DOM.IFocusTracker;
// Elements
public domNode: HTMLElement;
private actionsList: HTMLElement;
private toDispose: lifecycle.IDisposable[];
constructor(container: HTMLElement | Builder, options: IActionBarOptions = defaultOptions) {
super();
this.options = options;
this._context = options.context;
this.toDispose = [];
this._actionRunner = this.options.actionRunner;
if (!this._actionRunner) {
this._actionRunner = new ActionRunner();
this.toDispose.push(this._actionRunner);
}
this.toDispose.push(this.addEmitter(this._actionRunner));
this.items = [];
this.focusedItem = undefined;
this.domNode = document.createElement('div');
this.domNode.className = 'monaco-action-bar';
if (options.animated !== false) {
DOM.addClass(this.domNode, 'animated');
}
let isVertical = this.options.orientation === ActionsOrientation.VERTICAL;
if (isVertical) {
this.domNode.className += ' vertical';
}
$(this.domNode).on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
let eventHandled = true;
if (event.equals(isVertical ? KeyCode.UpArrow : KeyCode.LeftArrow)) {
this.focusPrevious();
} else if (event.equals(isVertical ? KeyCode.DownArrow : KeyCode.RightArrow)) {
this.focusNext();
} else if (event.equals(KeyCode.Escape)) {
this.cancel();
} else if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
// Nothing, just staying out of the else branch
} else {
eventHandled = false;
}
if (eventHandled) {
event.preventDefault();
event.stopPropagation();
}
});
$(this.domNode).on(DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
// Run action on Enter/Space
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
this.doTrigger(event);
event.preventDefault();
event.stopPropagation();
}
// Recompute focused item
else if (event.equals(KeyCode.Tab) || event.equals(KeyMod.Shift | KeyCode.Tab)) {
this.updateFocusedItem();
}
});
this.focusTracker = DOM.trackFocus(this.domNode);
this.focusTracker.addBlurListener(() => {
if (document.activeElement === this.domNode || !DOM.isAncestor(document.activeElement, this.domNode)) {
this.emit(DOM.EventType.BLUR, {});
this.focusedItem = undefined;
}
});
this.focusTracker.addFocusListener(() => this.updateFocusedItem());
this.actionsList = document.createElement('ul');
this.actionsList.className = 'actions-container';
if (this.options.isMenu) {
this.actionsList.setAttribute('role', 'menubar');
} else {
this.actionsList.setAttribute('role', 'toolbar');
}
if (this.options.ariaLabel) {
this.actionsList.setAttribute('aria-label', this.options.ariaLabel);
}
this.domNode.appendChild(this.actionsList);
((container instanceof Builder) ? container.getHTMLElement() : container).appendChild(this.domNode);
}
public setAriaLabel(label: string): void {
if (label) {
this.actionsList.setAttribute('aria-label', label);
} else {
this.actionsList.removeAttribute('aria-label');
}
}
private updateFocusedItem(): void {
for (let i = 0; i < this.actionsList.children.length; i++) {
let elem = this.actionsList.children[i];
if (DOM.isAncestor(document.activeElement, elem)) {
this.focusedItem = i;
break;
}
}
}
public get context(): any {
return this._context;
}
public set context(context: any) {
this._context = context;
this.items.forEach(i => i.setActionContext(context));
}
public get actionRunner(): IActionRunner {
return this._actionRunner;
}
public set actionRunner(actionRunner: IActionRunner) {
if (actionRunner) {
this._actionRunner = actionRunner;
this.items.forEach(item => item.actionRunner = actionRunner);
}
}
public getContainer(): Builder {
return $(this.domNode);
}
public push(arg: IAction | IAction[], options: IActionOptions = {}): void {
const actions: IAction[] = !Array.isArray(arg) ? [arg] : arg;
let index = types.isNumber(options.index) ? options.index : null;
actions.forEach((action: IAction) => {
const actionItemElement = document.createElement('li');
actionItemElement.className = 'action-item';
actionItemElement.setAttribute('role', 'presentation');
// Prevent native context menu on actions
$(actionItemElement).on(DOM.EventType.CONTEXT_MENU, (e: Event) => {
e.preventDefault();
e.stopPropagation();
});
let item: IActionItem = null;
if (this.options.actionItemProvider) {
item = this.options.actionItemProvider(action);
}
if (!item) {
item = new ActionItem(this.context, action, options);
}
item.actionRunner = this._actionRunner;
item.setActionContext(this.context);
this.addEmitter(item);
item.render(actionItemElement);
if (index === null || index < 0 || index >= this.actionsList.children.length) {
this.actionsList.appendChild(actionItemElement);
} else {
this.actionsList.insertBefore(actionItemElement, this.actionsList.children[index++]);
}
this.items.push(item);
});
}
public pull(index: number): void {
if (index >= 0 && index < this.items.length) {
this.items.splice(index, 1);
this.actionsList.removeChild(this.actionsList.childNodes[index]);
}
}
public clear(): void {
this.items = lifecycle.dispose(this.items);
$(this.actionsList).empty();
}
public length(): number {
return this.items.length;
}
public isEmpty(): boolean {
return this.items.length === 0;
}
public focus(selectFirst?: boolean): void {
if (selectFirst && typeof this.focusedItem === 'undefined') {
this.focusedItem = 0;
}
this.updateFocus();
}
private focusNext(): void {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = this.items.length - 1;
}
let startIndex = this.focusedItem;
let item: IActionItem;
do {
this.focusedItem = (this.focusedItem + 1) % this.items.length;
item = this.items[this.focusedItem];
} while (this.focusedItem !== startIndex && !item.isEnabled());
if (this.focusedItem === startIndex && !item.isEnabled()) {
this.focusedItem = undefined;
}
this.updateFocus();
}
private focusPrevious(): void {
if (typeof this.focusedItem === 'undefined') {
this.focusedItem = 0;
}
let startIndex = this.focusedItem;
let item: IActionItem;
do {
this.focusedItem = this.focusedItem - 1;
if (this.focusedItem < 0) {
this.focusedItem = this.items.length - 1;
}
item = this.items[this.focusedItem];
} while (this.focusedItem !== startIndex && !item.isEnabled());
if (this.focusedItem === startIndex && !item.isEnabled()) {
this.focusedItem = undefined;
}
this.updateFocus(true);
}
private updateFocus(fromRight?: boolean): void {
if (typeof this.focusedItem === 'undefined') {
this.domNode.focus();
return;
}
for (let i = 0; i < this.items.length; i++) {
let item = this.items[i];
let actionItem = <any>item;
if (i === this.focusedItem) {
if (types.isFunction(actionItem.focus)) {
actionItem.focus(fromRight);
}
} else {
if (types.isFunction(actionItem.blur)) {
actionItem.blur();
}
}
}
}
private doTrigger(event: StandardKeyboardEvent): void {
if (typeof this.focusedItem === 'undefined') {
return; //nothing to focus
}
// trigger action
let actionItem = this.items[this.focusedItem];
if (actionItem instanceof BaseActionItem) {
const context = (actionItem._context === null || actionItem._context === undefined) ? event : actionItem._context;
this.run(actionItem._action, context).done();
}
}
private cancel(): void {
if (document.activeElement instanceof HTMLElement) {
(<HTMLElement>document.activeElement).blur(); // remove focus from focused action
}
this.emit(CommonEventType.CANCEL);
}
public run(action: IAction, context?: any): TPromise<void> {
return this._actionRunner.run(action, context);
}
public dispose(): void {
if (this.items !== null) {
lifecycle.dispose(this.items);
}
this.items = null;
if (this.focusTracker) {
this.focusTracker.dispose();
this.focusTracker = null;
}
this.toDispose = lifecycle.dispose(this.toDispose);
this.getContainer().destroy();
super.dispose();
}
}
export class SelectActionItem extends BaseActionItem {
protected selectBox: SelectBox;
protected toDispose: lifecycle.IDisposable[];
constructor(ctx: any, action: IAction, options: string[], selected: number) {
super(ctx, action);
this.selectBox = new SelectBox(options, selected);
this.toDispose = [];
this.toDispose.push(this.selectBox);
this.registerListeners();
}
public setOptions(options: string[], selected?: number): void {
this.selectBox.setOptions(options, selected);
}
public select(index: number): void {
this.selectBox.select(index);
}
private registerListeners(): void {
this.toDispose.push(this.selectBox.onDidSelect(e => {
this.actionRunner.run(this._action, this.getActionContext(e.selected)).done();
}));
}
protected getActionContext(option: string) {
return option;
}
public focus(): void {
if (this.selectBox) {
this.selectBox.focus();
}
}
public blur(): void {
if (this.selectBox) {
this.selectBox.blur();
}
}
public render(container: HTMLElement): void {
this.selectBox.render(container);
}
public dispose(): void {
this.toDispose = lifecycle.dispose(this.toDispose);
super.dispose();
}
}