mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
allow extension to provide custom icons to data explorer tree (#16868)
* expose icon path to extension for OE node * remove node type * pr comments
This commit is contained in:
@@ -23,6 +23,7 @@ import { ServerTreeRenderer } from 'sql/workbench/services/objectExplorer/browse
|
||||
import { ServerTreeElement } from 'sql/workbench/services/objectExplorer/browser/asyncServerTree';
|
||||
import { DefaultServerGroupColor } from 'sql/workbench/services/serverGroup/common/serverGroupViewModel';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { instanceOfSqlThemeIcon } from 'sql/workbench/services/objectExplorer/common/nodeType';
|
||||
|
||||
const DefaultConnectionIconClass = 'server-page';
|
||||
|
||||
@@ -168,6 +169,8 @@ class TreeNodeTemplate extends Disposable {
|
||||
let iconName: string | undefined = undefined;
|
||||
if (element.iconType) {
|
||||
iconName = (typeof element.iconType === 'string') ? element.iconType : element.iconType.id;
|
||||
} else if (instanceOfSqlThemeIcon(element.icon)) {
|
||||
iconName = element.icon.id;
|
||||
} else {
|
||||
iconName = element.nodeTypeId;
|
||||
if (element.nodeStatus) {
|
||||
@@ -185,10 +188,12 @@ class TreeNodeTemplate extends Disposable {
|
||||
this._icon.classList.remove(...tokens);
|
||||
this._icon.classList.add('icon');
|
||||
let iconLowerCaseName = iconName.toLocaleLowerCase();
|
||||
this._icon.classList.add(iconLowerCaseName);
|
||||
if (iconLowerCaseName) {
|
||||
this._icon.classList.add(iconLowerCaseName);
|
||||
}
|
||||
|
||||
if (element.iconPath) {
|
||||
iconRenderer.putIcon(this._icon, element.iconPath);
|
||||
if (element.icon && !instanceOfSqlThemeIcon(element.icon)) {
|
||||
iconRenderer.putIcon(this._icon, element.icon);
|
||||
}
|
||||
|
||||
this._label.textContent = element.label;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IconPath } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { createCSSRule, asCSSUrl } from 'vs/base/browser/dom';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -10,10 +11,10 @@ import { URI } from 'vs/base/common/uri';
|
||||
class IconRenderer {
|
||||
private iconRegistered: Set<string> = new Set<string>();
|
||||
|
||||
public registerIcon(path: URI | IconPath | undefined): string | undefined {
|
||||
public registerIcon(path: IconPath | undefined): string | undefined {
|
||||
if (!path) { return undefined; }
|
||||
let iconPath: IconPath = this.toIconPath(path);
|
||||
let iconUid: string | undefined = this.getIconUid(iconPath);
|
||||
const iconPath: ThemedIconUri = this.toThemedIconUri(path);
|
||||
const iconUid: string | undefined = this.getIconUid(iconPath);
|
||||
if (iconUid && !this.iconRegistered.has(iconUid)) {
|
||||
createCSSRule(`.icon#${iconUid}`, `background: ${asCSSUrl(iconPath.light || iconPath.dark)} center center no-repeat`);
|
||||
createCSSRule(`.vs-dark .icon#${iconUid}, .hc-black .icon#${iconUid}`, `background: ${asCSSUrl(iconPath.dark)} center center no-repeat`);
|
||||
@@ -22,22 +23,32 @@ class IconRenderer {
|
||||
return iconUid;
|
||||
}
|
||||
|
||||
public getIconUid(path: URI | IconPath): string | undefined {
|
||||
public getIconUid(path: IconPath): string | undefined {
|
||||
if (!path) { return undefined; }
|
||||
let iconPath: IconPath = this.toIconPath(path);
|
||||
const iconPath: ThemedIconUri = this.toThemedIconUri(path);
|
||||
return `icon${hash(iconPath.light.toString() + iconPath.dark.toString())}`;
|
||||
}
|
||||
|
||||
private toIconPath(path: URI | IconPath): IconPath {
|
||||
if (URI.isUri(path)) {
|
||||
let singlePath = path;
|
||||
return { light: singlePath, dark: singlePath };
|
||||
private toThemedIconUri(path: IconPath): ThemedIconUri {
|
||||
let light, dark: string | URI;
|
||||
|
||||
if (URI.isUri(path) || (typeof (path) === 'string')) {
|
||||
light = dark = path;
|
||||
} else {
|
||||
return path;
|
||||
light = path.light;
|
||||
dark = path.dark;
|
||||
}
|
||||
return {
|
||||
light: this.toUri(light),
|
||||
dark: this.toUri(dark)
|
||||
};
|
||||
}
|
||||
|
||||
public putIcon(element: HTMLElement, path: URI | IconPath | undefined): void {
|
||||
private toUri(path: string | URI): URI {
|
||||
return URI.isUri(path) ? path : URI.file(path);
|
||||
}
|
||||
|
||||
public putIcon(element: HTMLElement, path: IconPath | undefined): void {
|
||||
let iconUid: string | undefined = this.registerIcon(path);
|
||||
element.id = iconUid ?? '';
|
||||
}
|
||||
@@ -130,7 +141,7 @@ class BadgeRenderer {
|
||||
|
||||
export const badgeRenderer: BadgeRenderer = new BadgeRenderer();
|
||||
|
||||
interface IconPath {
|
||||
interface ThemedIconUri {
|
||||
light: URI;
|
||||
dark: URI;
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ export class ObjectExplorerService implements IObjectExplorerService {
|
||||
}
|
||||
|
||||
let node = new TreeNode(nodeInfo.nodeType, nodeInfo.label, isLeaf, nodeInfo.nodePath,
|
||||
nodeInfo.nodeSubType!, nodeInfo.nodeStatus, parent, nodeInfo.metadata, nodeInfo.iconType, {
|
||||
nodeInfo.nodeSubType!, nodeInfo.nodeStatus, parent, nodeInfo.metadata, nodeInfo.iconType, nodeInfo.icon, {
|
||||
getChildren: (treeNode?: TreeNode) => this.getChildren(treeNode),
|
||||
isExpanded: treeNode => this.isExpanded(treeNode),
|
||||
setNodeExpandedState: async (treeNode, expandedState) => await this.setNodeExpandedState(treeNode, expandedState),
|
||||
|
||||
@@ -17,6 +17,7 @@ import { badgeRenderer, iconRenderer } from 'sql/workbench/services/objectExplor
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { DefaultServerGroupColor } from 'sql/workbench/services/serverGroup/common/serverGroupViewModel';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { instanceOfSqlThemeIcon } from 'sql/workbench/services/objectExplorer/common/nodeType';
|
||||
|
||||
export interface IConnectionTemplateData {
|
||||
root: HTMLElement;
|
||||
@@ -136,6 +137,8 @@ export class ServerTreeRenderer implements IRenderer {
|
||||
let iconName: string | undefined = undefined;
|
||||
if (treeNode.iconType) {
|
||||
iconName = (typeof treeNode.iconType === 'string') ? treeNode.iconType : treeNode.iconType.id;
|
||||
} else if (instanceOfSqlThemeIcon(treeNode.icon)) {
|
||||
iconName = treeNode.icon.id;
|
||||
} else {
|
||||
iconName = treeNode.nodeTypeId;
|
||||
if (treeNode.nodeStatus) {
|
||||
@@ -153,10 +156,12 @@ export class ServerTreeRenderer implements IRenderer {
|
||||
templateData.icon.classList.remove(...tokens);
|
||||
templateData.icon.classList.add('icon');
|
||||
let iconLowerCaseName = iconName.toLocaleLowerCase();
|
||||
templateData.icon.classList.add(iconLowerCaseName);
|
||||
if (iconLowerCaseName) {
|
||||
templateData.icon.classList.add(iconLowerCaseName);
|
||||
}
|
||||
|
||||
if (treeNode.iconPath) {
|
||||
iconRenderer.putIcon(templateData.icon, treeNode.iconPath);
|
||||
if (treeNode.icon && !instanceOfSqlThemeIcon(treeNode.icon)) {
|
||||
iconRenderer.putIcon(templateData.icon, treeNode.icon);
|
||||
}
|
||||
|
||||
templateData.label.textContent = treeNode.label;
|
||||
|
||||
@@ -103,3 +103,8 @@ export class NodeType {
|
||||
export interface SqlThemeIcon {
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export function instanceOfSqlThemeIcon(obj: any): obj is SqlThemeIcon {
|
||||
const icon = obj as SqlThemeIcon;
|
||||
return icon && icon.id !== undefined;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { NodeType, SqlThemeIcon } from 'sql/workbench/services/objectExplorer/co
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
import * as UUID from 'vs/base/common/uuid';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IconPath } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
|
||||
export enum TreeItemCollapsibleState {
|
||||
None = 0,
|
||||
@@ -92,11 +92,12 @@ export class TreeNode {
|
||||
|
||||
public iconType?: string | SqlThemeIcon;
|
||||
|
||||
public iconPath?: URI | { light: URI, dark: URI };
|
||||
public icon?: IconPath | SqlThemeIcon;
|
||||
|
||||
constructor(nodeTypeId: string, label: string, isAlwaysLeaf: boolean, nodePath: string,
|
||||
nodeSubType: string, nodeStatus?: string, parent?: TreeNode, metadata?: azdata.ObjectMetadata,
|
||||
iconType?: string | SqlThemeIcon,
|
||||
icon?: IconPath | SqlThemeIcon,
|
||||
private _objectExplorerCallbacks?: ObjectExplorerCallbacks) {
|
||||
this.nodeTypeId = nodeTypeId;
|
||||
this.label = label;
|
||||
@@ -108,6 +109,7 @@ export class TreeNode {
|
||||
this.id = UUID.generateUuid();
|
||||
this.nodeSubType = nodeSubType;
|
||||
this.nodeStatus = nodeStatus;
|
||||
this.icon = icon;
|
||||
}
|
||||
public getConnectionProfile(): ConnectionProfile | undefined {
|
||||
let currentNode: TreeNode = this;
|
||||
|
||||
Reference in New Issue
Block a user