mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-06-15 00:26:33 +00:00

- can show badge with updates count, - better hover for libraries and platforms, - save/restore widget state (Closes #1398), - fixed `sentence` and `paragraph` order (Ref #1611) Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
152 lines
4.0 KiB
TypeScript
152 lines
4.0 KiB
TypeScript
import {
|
|
CommandHandler,
|
|
CommandRegistry,
|
|
} from '@theia/core/lib/common/command';
|
|
import {
|
|
Disposable,
|
|
DisposableCollection,
|
|
} from '@theia/core/lib/common/disposable';
|
|
import {
|
|
MenuModelRegistry,
|
|
MenuPath,
|
|
SubMenuOptions,
|
|
} from '@theia/core/lib/common/menu';
|
|
import { unregisterSubmenu } from './arduino-menus';
|
|
|
|
export interface MenuTemplate {
|
|
readonly menuLabel: string;
|
|
}
|
|
|
|
export function isMenuTemplate(arg: unknown): arg is MenuTemplate {
|
|
return (
|
|
typeof arg === 'object' &&
|
|
(arg as MenuTemplate).menuLabel !== undefined &&
|
|
typeof (arg as MenuTemplate).menuLabel === 'string'
|
|
);
|
|
}
|
|
|
|
export interface MenuActionTemplate extends MenuTemplate {
|
|
readonly menuPath: MenuPath;
|
|
readonly handler: CommandHandler;
|
|
/**
|
|
* If not defined the insertion oder will be the order string.
|
|
*/
|
|
readonly order?: string;
|
|
}
|
|
|
|
export function isMenuActionTemplate(
|
|
arg: MenuTemplate
|
|
): arg is MenuActionTemplate {
|
|
return (
|
|
isMenuTemplate(arg) &&
|
|
(arg as MenuActionTemplate).handler !== undefined &&
|
|
typeof (arg as MenuActionTemplate).handler === 'object' &&
|
|
(arg as MenuActionTemplate).menuPath !== undefined &&
|
|
Array.isArray((arg as MenuActionTemplate).menuPath)
|
|
);
|
|
}
|
|
|
|
export function menuActionWithCommandDelegate(
|
|
template: Omit<MenuActionTemplate, 'handler' | 'menuLabel'> & {
|
|
command: string;
|
|
},
|
|
commandRegistry: CommandRegistry
|
|
): MenuActionTemplate {
|
|
const id = template.command;
|
|
const command = commandRegistry.getCommand(id);
|
|
if (!command) {
|
|
throw new Error(`Could not find the registered command with ID: ${id}`);
|
|
}
|
|
return {
|
|
...template,
|
|
menuLabel: command.label ?? id,
|
|
handler: {
|
|
execute: (args) => commandRegistry.executeCommand(id, args),
|
|
isEnabled: (args) => commandRegistry.isEnabled(id, args),
|
|
isVisible: (args) => commandRegistry.isVisible(id, args),
|
|
isToggled: (args) => commandRegistry.isToggled(id, args),
|
|
},
|
|
};
|
|
}
|
|
|
|
export interface SubmenuTemplate extends MenuTemplate {
|
|
readonly menuLabel: string;
|
|
readonly submenuPath: MenuPath;
|
|
readonly options?: SubMenuOptions;
|
|
}
|
|
|
|
interface Services {
|
|
readonly commandRegistry: CommandRegistry;
|
|
readonly menuRegistry: MenuModelRegistry;
|
|
}
|
|
|
|
class MenuIndexCounter {
|
|
private _counter: number;
|
|
constructor(counter = 0) {
|
|
this._counter = counter;
|
|
}
|
|
getAndIncrement(): number {
|
|
const counter = this._counter;
|
|
this._counter++;
|
|
return counter;
|
|
}
|
|
}
|
|
|
|
export function registerMenus(
|
|
options: {
|
|
contextId: string;
|
|
templates: Array<MenuActionTemplate | SubmenuTemplate>;
|
|
} & Services
|
|
): Disposable {
|
|
const { templates } = options;
|
|
const menuIndexCounter = new MenuIndexCounter();
|
|
return new DisposableCollection(
|
|
...templates.map((template) =>
|
|
registerMenu({ template, menuIndexCounter, ...options })
|
|
)
|
|
);
|
|
}
|
|
|
|
function registerMenu(
|
|
options: {
|
|
contextId: string;
|
|
menuIndexCounter: MenuIndexCounter;
|
|
template: MenuActionTemplate | SubmenuTemplate;
|
|
} & Services
|
|
): Disposable {
|
|
const {
|
|
template,
|
|
commandRegistry,
|
|
menuRegistry,
|
|
contextId,
|
|
menuIndexCounter,
|
|
} = options;
|
|
if (isMenuActionTemplate(template)) {
|
|
const { menuLabel, menuPath, handler, order } = template;
|
|
const id = generateCommandId(contextId, menuLabel, menuPath);
|
|
const index = menuIndexCounter.getAndIncrement();
|
|
return new DisposableCollection(
|
|
commandRegistry.registerCommand({ id }, handler),
|
|
menuRegistry.registerMenuAction(menuPath, {
|
|
commandId: id,
|
|
label: menuLabel,
|
|
order: typeof order === 'string' ? order : String(index).padStart(4),
|
|
})
|
|
);
|
|
} else {
|
|
const { menuLabel, submenuPath, options } = template;
|
|
return new DisposableCollection(
|
|
menuRegistry.registerSubmenu(submenuPath, menuLabel, options),
|
|
Disposable.create(() => unregisterSubmenu(submenuPath, menuRegistry))
|
|
);
|
|
}
|
|
|
|
function generateCommandId(
|
|
contextId: string,
|
|
menuLabel: string,
|
|
menuPath: MenuPath
|
|
): string {
|
|
return `arduino-${contextId}-context-${menuPath.join('-')}-${menuLabel}`;
|
|
}
|
|
}
|