mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-26 09:35:38 -05:00
189 lines
6.1 KiB
TypeScript
189 lines
6.1 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* 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/divContainer';
|
|
|
|
import {
|
|
Component, Input, Inject, ChangeDetectorRef, forwardRef,
|
|
ViewChild, ElementRef, OnDestroy, Renderer2, AfterViewInit
|
|
} from '@angular/core';
|
|
|
|
import * as azdata from 'azdata';
|
|
|
|
import { ContainerBase } from 'sql/workbench/browser/modelComponents/componentBase';
|
|
|
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
|
import { KeyCode } from 'vs/base/common/keyCodes';
|
|
import { IComponentDescriptor, IComponent, IModelStore, ComponentEventType } from 'sql/platform/dashboard/browser/interfaces';
|
|
import { convertSize } from 'sql/base/browser/dom';
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
import { registerThemingParticipant, IColorTheme, IThemeService, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
|
import * as colorRegistry from 'vs/platform/theme/common/colorRegistry';
|
|
|
|
class DivItem {
|
|
constructor(public descriptor: IComponentDescriptor, public config: azdata.DivItemLayout) { }
|
|
}
|
|
|
|
@Component({
|
|
template: `
|
|
<div #divContainer *ngIf="items" [ngClass] = "{'divContainer': true, 'clickable-divContainer': clickable}" [ngStyle]="CSSStyles" [style.height]="height" [style.width]="width" [style.display]="display" (keydown)="onKey($event)" [attr.role]="ariaRole" [attr.aria-selected]="ariaSelected" [attr.aria-live]="ariaLive" [attr.aria-label]="ariaLabel">
|
|
<div *ngFor="let item of items" [style.order]="getItemOrder(item)" [ngStyle]="getItemStyles(item)">
|
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
|
</model-component-wrapper>
|
|
</div>
|
|
</div>
|
|
`
|
|
})
|
|
export default class DivContainer extends ContainerBase<azdata.DivItemLayout, azdata.DivContainerProperties> implements IComponent, OnDestroy, AfterViewInit {
|
|
@Input() descriptor: IComponentDescriptor;
|
|
@Input() modelStore: IModelStore;
|
|
@ViewChild('divContainer', { read: ElementRef }) divContainer;
|
|
private _height: string;
|
|
private _width: string;
|
|
private _overflowY: string;
|
|
private viewInitialized: boolean;
|
|
private cancelClick: Function;
|
|
|
|
constructor(
|
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
|
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
|
@Inject(forwardRef(() => Renderer2)) private renderer: Renderer2,
|
|
@Inject(ILogService) logService: ILogService,
|
|
@Inject(IThemeService) themeService: IThemeService,
|
|
) {
|
|
super(changeRef, el, logService);
|
|
this._overflowY = ''; // default
|
|
|
|
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
|
|
const editorHoverBackground = theme.getColor(colorRegistry.editorHoverBackground).toString();
|
|
if (editorHoverBackground) {
|
|
collector.addRule(`
|
|
.clickable-divContainer:hover {
|
|
background-color: ${editorHoverBackground};
|
|
}
|
|
`);
|
|
}
|
|
});
|
|
}
|
|
|
|
ngAfterViewInit(): void {
|
|
this.viewInitialized = true;
|
|
this.updateClickListener();
|
|
this.baseInit();
|
|
}
|
|
|
|
override ngOnDestroy(): void {
|
|
this.baseDestroy();
|
|
}
|
|
|
|
|
|
/// IComponent implementation
|
|
|
|
public setLayout(layout: azdata.DivLayout): void {
|
|
this._height = convertSize(layout.height);
|
|
this._width = convertSize(layout.width);
|
|
this.layout();
|
|
}
|
|
|
|
public override setProperties(properties: { [key: string]: any; }): void {
|
|
super.setProperties(properties);
|
|
if (this.overflowY !== this._overflowY) {
|
|
this.updateOverflowY();
|
|
}
|
|
this.updateScroll();
|
|
this.updateClickable();
|
|
}
|
|
|
|
private updateOverflowY() {
|
|
this._overflowY = this.overflowY;
|
|
if (this._overflowY) {
|
|
let element = <HTMLElement>this.divContainer.nativeElement;
|
|
element.style.overflowY = this._overflowY;
|
|
}
|
|
}
|
|
|
|
private updateScroll() {
|
|
let element = <HTMLElement>this.divContainer.nativeElement;
|
|
element.scrollTop = element.scrollTop - this.yOffsetChange;
|
|
element.dispatchEvent(new Event('scroll'));
|
|
}
|
|
|
|
private updateClickable(): void {
|
|
const element = <HTMLElement>this.divContainer.nativeElement;
|
|
if (this.clickable) {
|
|
element.tabIndex = 0;
|
|
element.style.cursor = 'pointer';
|
|
} else {
|
|
element.removeAttribute('tabIndex');
|
|
element.style.cursor = 'default';
|
|
}
|
|
this.updateClickListener();
|
|
}
|
|
|
|
private onClick() {
|
|
this.fireEvent({
|
|
eventType: ComponentEventType.onDidClick,
|
|
args: undefined
|
|
});
|
|
}
|
|
|
|
// CSS-bound properties
|
|
public override get height(): string {
|
|
return this._height;
|
|
}
|
|
|
|
public override get width(): string {
|
|
return this._width;
|
|
}
|
|
|
|
// CSS-bound properties
|
|
public get overflowY(): string {
|
|
return this.getPropertyOrDefault<any>((props) => props.overflowY, '');
|
|
}
|
|
public set overflowY(newValue: string) {
|
|
this.setPropertyFromUI<any>((properties, newValue) => { properties.overflowY = newValue; }, newValue);
|
|
}
|
|
|
|
public get yOffsetChange(): number {
|
|
return this.getPropertyOrDefault<any>((props) => props.yOffsetChange, 0);
|
|
}
|
|
public set yOffsetChange(newValue: number) {
|
|
this.setPropertyFromUI<any>((properties, newValue) => { properties.yOffsetChange = newValue; }, newValue);
|
|
}
|
|
|
|
public get clickable(): boolean {
|
|
return this.getPropertyOrDefault<boolean>((props) => props.clickable, false);
|
|
}
|
|
|
|
public onKey(e: KeyboardEvent) {
|
|
let event = new StandardKeyboardEvent(e);
|
|
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
|
this.onClick();
|
|
e.stopPropagation();
|
|
}
|
|
}
|
|
|
|
public getItemOrder(item: DivItem): number {
|
|
return item.config ? item.config.order : 0;
|
|
}
|
|
public getItemStyles(item: DivItem): azdata.CssStyles {
|
|
return item.config && item.config.CSSStyles ? item.config.CSSStyles : {};
|
|
}
|
|
|
|
private updateClickListener(): void {
|
|
// We can't hook into the listener until the view is initialized
|
|
if (!this.viewInitialized) {
|
|
return;
|
|
}
|
|
if (this.clickable && !this.cancelClick) {
|
|
this.cancelClick = this.renderer.listen(this.divContainer.nativeElement, 'click', () => this.onClick());
|
|
} else if (!this.clickable && this.cancelClick) {
|
|
this.cancelClick();
|
|
this.cancelClick = undefined;
|
|
}
|
|
}
|
|
}
|
|
|
|
|