diff --git a/src/sql/platform/actions/browser/menuEntryActionViewItem.ts b/src/sql/platform/actions/browser/menuEntryActionViewItem.ts new file mode 100644 index 0000000000..b4b0a2b7a8 --- /dev/null +++ b/src/sql/platform/actions/browser/menuEntryActionViewItem.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { asCSSUrl, createCSSRule } from 'vs/base/browser/dom'; +import { IdGenerator } from 'vs/base/common/idGenerator'; +import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; +import { ICommandAction, MenuItemAction } from 'vs/platform/actions/common/actions'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; + +const ids = new IdGenerator('menu-item-action-item-icon-'); + +const ICON_PATH_TO_CSS_RULES = new Map(); + +/** + * Always show label for action items, instead of whether they don't have + * an icon/CSS class. Useful for some toolbar scenarios in particular with + * contributed actions from other extensions + */ +export class LabeledMenuItemActionItem extends MenuEntryActionViewItem { + private _labeledItemClassDispose?: IDisposable; + + constructor( + public _action: MenuItemAction, + @IKeybindingService labeledkeybindingService: IKeybindingService, + @INotificationService protected _notificationService: INotificationService, + private readonly _defaultCSSClassToAdd: string = '' + ) { + super(_action, labeledkeybindingService, _notificationService); + } + + updateLabel(): void { + if (this.label) { + this.label.innerText = this._commandAction.label; + } + } + + // Overwrite item class to ensure that we can pass in a CSS class that other items use + // Leverages the _defaultCSSClassToAdd property that's passed into the constructor + protected _updateItemClass(item: ICommandAction): void { + dispose(this._labeledItemClassDispose); + this._labeledItemClassDispose = undefined; + + if (ThemeIcon.isThemeIcon(item.icon)) { + // TODO + } else if (item.icon) { + let iconClass: string; + + + if (item.icon?.dark?.scheme) { + const iconPathMapKey = item.icon.dark.toString(); + + if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) { + iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; + } else { + iconClass = ids.nextId(); + createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)} !important`); + createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)} !important`); + ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); + } + + if (this.label) { + const iconClasses = iconClass.split(' '); + if (this._defaultCSSClassToAdd) { + iconClasses.push(this._defaultCSSClassToAdd); + } + this.label.classList.add('codicon', ...iconClasses); + this._labeledItemClassDispose = toDisposable(() => { + if (this.label) { + this.label.classList.remove('codicon', ...iconClasses); + } + }); + } + } + } + } + + dispose(): void { + if (this._labeledItemClassDispose) { + dispose(this._labeledItemClassDispose); + this._labeledItemClassDispose = undefined; + } + + super.dispose(); + } +} + +/** + * This is a duplicate of LabeledMenuItemActionItem with the following exceptions: + * - Adds CSS class: `masked-icon` to contributed actions label element. + * - Adds style rule for masked-icon. + */ +export class MaskedLabeledMenuItemActionItem extends MenuEntryActionViewItem { + private _labeledItemClassDispose?: IDisposable; + + constructor( + public _action: MenuItemAction, + @IKeybindingService labeledkeybindingService: IKeybindingService, + @INotificationService protected _notificationService: INotificationService, + private readonly _defaultCSSClassToAdd: string = '' + ) { + super(_action, labeledkeybindingService, _notificationService); + } + + updateLabel(): void { + if (this.label) { + this.label.innerText = this._commandAction.label; + } + } + + // Overwrite item class to ensure that we can pass in a CSS class that other items use + // Leverages the _defaultCSSClassToAdd property that's passed into the constructor + protected _updateItemClass(item: ICommandAction): void { + dispose(this._labeledItemClassDispose); + this._labeledItemClassDispose = undefined; + + if (ThemeIcon.isThemeIcon(item.icon)) { + // TODO + } else if (item.icon) { + let iconClass: string; + + + if (item.icon?.dark?.scheme) { + const iconPathMapKey = item.icon.dark.toString(); + + if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) { + iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; + } else { + iconClass = ids.nextId(); + createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `-webkit-mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`); + createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`); + ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); + } + + if (this.label) { + const iconClasses = iconClass.split(' '); + if (this._defaultCSSClassToAdd) { + iconClasses.push(this._defaultCSSClassToAdd); + } + this.label.classList.add('codicon', ...iconClasses); + this.label.classList.add('masked-icon', ...iconClasses); + this._labeledItemClassDispose = toDisposable(() => { + if (this.label) { + this.label.classList.remove('codicon', ...iconClasses); + } + }); + } + } + } + } + + dispose(): void { + if (this._labeledItemClassDispose) { + dispose(this._labeledItemClassDispose); + this._labeledItemClassDispose = undefined; + } + + super.dispose(); + } +} diff --git a/src/sql/workbench/contrib/dashboard/browser/core/dashboardPage.component.ts b/src/sql/workbench/contrib/dashboard/browser/core/dashboardPage.component.ts index 2f55fd3581..a183f50736 100644 --- a/src/sql/workbench/contrib/dashboard/browser/core/dashboardPage.component.ts +++ b/src/sql/workbench/contrib/dashboard/browser/core/dashboardPage.component.ts @@ -43,7 +43,7 @@ import * as DOM from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { TaskRegistry } from 'sql/workbench/services/tasks/browser/tasksRegistry'; import { MenuRegistry, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; -import { fillInActions, LabeledMenuItemActionItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { NAV_SECTION } from 'sql/workbench/contrib/dashboard/browser/containers/dashboardNavSection.contribution'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; @@ -51,6 +51,7 @@ import { DASHBOARD_BORDER, EDITOR_PANE_BACKGROUND, TOOLBAR_OVERFLOW_SHADOW } fro import { IColorTheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { attachTabbedPanelStyler } from 'sql/workbench/common/styler'; import { focusBorder } from 'vs/platform/theme/common/colorRegistry'; +import { LabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem'; const dashboardRegistry = Registry.as(DashboardExtensions.DashboardContributions); const homeTabGroupId = 'home'; diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts index 177a72db1b..d79768da8a 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts @@ -41,7 +41,7 @@ import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { ILogService } from 'vs/platform/log/common/log'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { MaskedLabeledMenuItemActionItem, fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { Button } from 'sql/base/browser/ui/button/button'; import { isUndefinedOrNull } from 'vs/base/common/types'; import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams'; @@ -52,6 +52,7 @@ import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/not import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component'; +import { MaskedLabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem'; export const NOTEBOOK_SELECTOR: string = 'notebook-component'; diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index 92eaac1cf8..1b5e0c644a 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -4,11 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./menuEntryActionViewItem'; -import { asCSSUrl, createCSSRule, ModifierKeyEmitter } from 'vs/base/browser/dom'; +import { asCSSUrl, ModifierKeyEmitter } from 'vs/base/browser/dom'; import { domEvent } from 'vs/base/browser/event'; import { IAction, Separator } from 'vs/base/common/actions'; -import { IdGenerator } from 'vs/base/common/idGenerator'; // {{SQL CARBON EDIT}} -import { IDisposable, toDisposable, MutableDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; // {{SQL CARBON EDIT}} +import { IDisposable, toDisposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { ICommandAction, IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction, Icon } from 'vs/platform/actions/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -45,8 +44,7 @@ function asDisposable(groups: ReadonlyArray<[string, ReadonlyArray]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation', primaryMaxCount: number = Number.MAX_SAFE_INTEGER): void { +export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation', primaryMaxCount: number = Number.MAX_SAFE_INTEGER): void { // {{SQL CARBON EDIT}} add export modifier let primaryBucket: IAction[]; let secondaryBucket: IAction[]; @@ -80,10 +78,6 @@ export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray(); // {{SQL CARBON EDIT}} - add back since custom toolbar menu is using below - export class MenuEntryActionViewItem extends ActionViewItem { private _wantsAltCommand: boolean = false; @@ -262,150 +256,3 @@ export function createActionViewItem(instaService: IInstantiationService, action return undefined; } } - -// {{SQL CARBON EDIT}} - This is here to use the 'ids' generator above -// Always show label for action items, instead of whether they don't have -// an icon/CSS class. Useful for some toolbar scenarios in particular with -// contributed actions from other extensions -export class LabeledMenuItemActionItem extends MenuEntryActionViewItem { - private _labeledItemClassDispose?: IDisposable; - - constructor( - public _action: MenuItemAction, - @IKeybindingService labeledkeybindingService: IKeybindingService, - @INotificationService protected _notificationService: INotificationService, - private readonly _defaultCSSClassToAdd: string = '' - ) { - super(_action, labeledkeybindingService, _notificationService); - } - - updateLabel(): void { - if (this.label) { - this.label.innerText = this._commandAction.label; - } - } - - // Overwrite item class to ensure that we can pass in a CSS class that other items use - // Leverages the _defaultCSSClassToAdd property that's passed into the constructor - protected _updateItemClass(item: ICommandAction): void { - dispose(this._labeledItemClassDispose); - this._labeledItemClassDispose = undefined; - - if (ThemeIcon.isThemeIcon(item.icon)) { - // TODO - } else if (item.icon) { - let iconClass: string; - - - if (item.icon?.dark?.scheme) { - const iconPathMapKey = item.icon.dark.toString(); - - if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) { - iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; - } else { - iconClass = ids.nextId(); - createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`); - createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)}`); - ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); - } - - if (this.label) { - const iconClasses = iconClass.split(' '); - if (this._defaultCSSClassToAdd) { - iconClasses.push(this._defaultCSSClassToAdd); - } - this.label.classList.add('codicon', ...iconClasses); - this._labeledItemClassDispose = toDisposable(() => { - if (this.label) { - this.label.classList.remove('codicon', ...iconClasses); - } - }); - } - } - } - } - - dispose(): void { - if (this._labeledItemClassDispose) { - dispose(this._labeledItemClassDispose); - this._labeledItemClassDispose = undefined; - } - - super.dispose(); - } -} - -/** - * This is a duplicate of LabeledMenuItemActionItem with the following exceptions: - * - Adds CSS class: `masked-icon` to contributed actions label element. - * - Adds style rule for masked-icon. - */ -export class MaskedLabeledMenuItemActionItem extends MenuEntryActionViewItem { - private _labeledItemClassDispose?: IDisposable; - - constructor( - public _action: MenuItemAction, - @IKeybindingService labeledkeybindingService: IKeybindingService, - @INotificationService protected _notificationService: INotificationService, - private readonly _defaultCSSClassToAdd: string = '' - ) { - super(_action, labeledkeybindingService, _notificationService); - } - - updateLabel(): void { - if (this.label) { - this.label.innerText = this._commandAction.label; - } - } - - // Overwrite item class to ensure that we can pass in a CSS class that other items use - // Leverages the _defaultCSSClassToAdd property that's passed into the constructor - protected _updateItemClass(item: ICommandAction): void { - dispose(this._labeledItemClassDispose); - this._labeledItemClassDispose = undefined; - - if (ThemeIcon.isThemeIcon(item.icon)) { - // TODO - } else if (item.icon) { - let iconClass: string; - - - if (item.icon?.dark?.scheme) { - const iconPathMapKey = item.icon.dark.toString(); - - if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) { - iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; - } else { - iconClass = ids.nextId(); - createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `-webkit-mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`); - createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`); - ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass); - } - - if (this.label) { - const iconClasses = iconClass.split(' '); - if (this._defaultCSSClassToAdd) { - iconClasses.push(this._defaultCSSClassToAdd); - } - this.label.classList.add('codicon', ...iconClasses); - this.label.classList.add('masked-icon', ...iconClasses); - this._labeledItemClassDispose = toDisposable(() => { - if (this.label) { - this.label.classList.remove('codicon', ...iconClasses); - } - }); - } - } - } - } - - dispose(): void { - if (this._labeledItemClassDispose) { - dispose(this._labeledItemClassDispose); - this._labeledItemClassDispose = undefined; - } - - super.dispose(); - } -} -// {{SQL CARBON EDIT}} - End