diff --git a/samples/sqlservices/src/controllers/mainController.ts b/samples/sqlservices/src/controllers/mainController.ts index 2001bb4567..7b949a762a 100644 --- a/samples/sqlservices/src/controllers/mainController.ts +++ b/samples/sqlservices/src/controllers/mainController.ts @@ -266,10 +266,23 @@ export default class MainController implements vscode.Disposable { values: ['aa', 'bb', 'cc'] }) .component(); - let button = view.modelBuilder.button() + let runIcon = path.join(__dirname, '..', 'media', 'start.svg'); + let runButton = view.modelBuilder.button() .withProperties({ - label: 'Run' + label: 'Run', + iconPath: runIcon }).component(); + + let monitoLightPath = vscode.Uri.file(path.join(__dirname, '..', 'media', 'monitor.svg')); + let monitorIcon = { + light: monitoLightPath, + dark: path.join(__dirname, '..', 'media', 'monitor_inverse.svg') }; + + let monitorButton = view.modelBuilder.button() + .withProperties({ + label: 'Monitor', + iconPath: monitorIcon + }).component(); let toolbarModel = view.modelBuilder.toolbarContainer() .withToolbarItems([{ component: inputBox, @@ -278,7 +291,9 @@ export default class MainController implements vscode.Disposable { component: dropdown, title: 'favorite:' }, { - component: button + component: runButton + }, { + component: monitorButton }]).component(); diff --git a/samples/sqlservices/src/media/monitor.svg b/samples/sqlservices/src/media/monitor.svg new file mode 100644 index 0000000000..642d6a5782 --- /dev/null +++ b/samples/sqlservices/src/media/monitor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/sqlservices/src/media/monitor_inverse.svg b/samples/sqlservices/src/media/monitor_inverse.svg new file mode 100644 index 0000000000..5e56c7cabc --- /dev/null +++ b/samples/sqlservices/src/media/monitor_inverse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/samples/sqlservices/src/media/start.svg b/samples/sqlservices/src/media/start.svg new file mode 100644 index 0000000000..2ceb9e2292 --- /dev/null +++ b/samples/sqlservices/src/media/start.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/sql/parts/modelComponents/button.component.ts b/src/sql/parts/modelComponents/button.component.ts index bf7c4c5468..4ba87046cd 100644 --- a/src/sql/parts/modelComponents/button.component.ts +++ b/src/sql/parts/modelComponents/button.component.ts @@ -2,14 +2,13 @@ * 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!./button'; import { Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver, ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList, AfterViewInit } from '@angular/core'; import * as sqlops from 'sqlops'; -import { Event, Emitter } from 'vs/base/common/event'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; @@ -19,9 +18,13 @@ import { Button } from 'sql/base/browser/ui/button/button'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { attachListStyler } from 'vs/platform/theme/common/styler'; - +import URI from 'vs/base/common/uri'; +import { IdGenerator } from 'vs/base/common/idGenerator'; +import { createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom'; +import { focusBorder, foreground } from 'vs/platform/theme/common/colorRegistry'; +import { Color } from 'vs/base/common/color'; @Component({ - selector: 'button', + selector: 'modelview-button', template: `
` @@ -30,6 +33,8 @@ export default class ButtonComponent extends ComponentBase implements IComponent @Input() descriptor: IComponentDescriptor; @Input() modelStore: IModelStore; private _button: Button; + private _iconClass: string; + private _iconPath: string | URI | { light: string | URI; dark: string | URI }; @ViewChild('input', { read: ElementRef }) private _inputContainer: ElementRef; constructor( @@ -37,6 +42,7 @@ export default class ButtonComponent extends ComponentBase implements IComponent @Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService ) { super(changeRef); + } ngOnInit(): void { @@ -64,6 +70,9 @@ export default class ButtonComponent extends ComponentBase implements IComponent } ngOnDestroy(): void { + if (this._iconClass) { + removeCSSRulesContainingSelector(this._iconClass); + } this.baseDestroy(); } @@ -80,7 +89,58 @@ export default class ButtonComponent extends ComponentBase implements IComponent public setProperties(properties: { [key: string]: any; }): void { super.setProperties(properties); + this._button.enabled = this.enabled; this._button.label = this.label; + this.updateIcon(); + } + + private updateIcon() { + if (this.iconPath && this.iconPath !== this._iconPath) { + this._iconPath = this.iconPath; + if (!this._iconClass) { + const ids = new IdGenerator('button-component-icon-' + Math.round(Math.random() * 1000)); + this._iconClass = ids.nextId(); + this._button.icon = this._iconClass + ' icon'; + + // Styling for icon button + this._register(attachButtonStyler(this._button, this.themeService, { + buttonBackground: Color.transparent.toString(), + buttonHoverBackground: Color.transparent.toString(), + buttonFocusOutline: focusBorder, + buttonForeground: foreground + })); + } + + removeCSSRulesContainingSelector(this._iconClass); + const icon = this.getLightIconPath(this.iconPath); + const iconDark = this.getDarkIconPath(this.iconPath) || icon; + createCSSRule(`.icon.${this._iconClass}`, `background-image: url("${icon}")`); + createCSSRule(`.vs-dark .icon.${this._iconClass}, .hc-black .icon.${this._iconClass}`, `background-image: url("${iconDark}")`); + } + } + + private getLightIconPath(iconPath: string | URI | { light: string | URI; dark: string | URI }): string { + if (iconPath && iconPath['light']) { + return this.getIconPath(iconPath['light']); + } else { + return this.getIconPath(