128 lines
4.2 KiB
TypeScript
128 lines
4.2 KiB
TypeScript
import {class_to_image} from "./icon-helper";
|
|
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
|
import * as electron from "electron";
|
|
const remote = electron.remote;
|
|
const {Menu, MenuItem} = remote;
|
|
|
|
class ElectronContextMenu implements contextmenu.ContextMenuProvider {
|
|
private _close_listeners: (() => any)[] = [];
|
|
private _current_menu: electron.Menu;
|
|
|
|
private _div: JQuery;
|
|
|
|
despawn_context_menu() {
|
|
if(!this._current_menu)
|
|
return;
|
|
this._current_menu.closePopup();
|
|
this._current_menu = undefined;
|
|
|
|
for(const listener of this._close_listeners) {
|
|
if(listener) {
|
|
try {
|
|
listener();
|
|
} catch (e) {
|
|
console.error("Failed to call context menu close listener: %o", e);
|
|
}
|
|
}
|
|
}
|
|
this._close_listeners = [];
|
|
}
|
|
|
|
finalize() {
|
|
if(this._div) this._div.detach();
|
|
this._div = undefined;
|
|
}
|
|
|
|
initialize() {
|
|
}
|
|
|
|
|
|
private _entry_id = 0;
|
|
private build_menu(entry: contextmenu.MenuEntry) : electron.MenuItem {
|
|
if(entry.type == contextmenu.MenuEntryType.CLOSE) {
|
|
this._close_listeners.push(entry.callback);
|
|
return undefined;
|
|
}
|
|
|
|
const click_callback = () => {
|
|
if(entry.callback)
|
|
entry.callback();
|
|
this.despawn_context_menu();
|
|
};
|
|
const _id = "entry_" + (this._entry_id++);
|
|
if(entry.type == contextmenu.MenuEntryType.ENTRY) {
|
|
return new MenuItem({
|
|
id: _id,
|
|
label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string,
|
|
type: "normal",
|
|
click: click_callback,
|
|
icon: class_to_image(entry.icon_class),
|
|
visible: entry.visible,
|
|
enabled: !entry.disabled
|
|
});
|
|
} else if(entry.type == contextmenu.MenuEntryType.HR) {
|
|
if(typeof(entry.visible) === "boolean" && !entry.visible)
|
|
return undefined;
|
|
|
|
return new MenuItem({
|
|
id: _id,
|
|
type: "separator",
|
|
label: '',
|
|
click: click_callback
|
|
})
|
|
} else if(entry.type == contextmenu.MenuEntryType.CHECKBOX) {
|
|
return new MenuItem({
|
|
id: _id,
|
|
label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string,
|
|
type: "checkbox",
|
|
checked: !!entry.checkbox_checked,
|
|
click: click_callback,
|
|
icon: class_to_image(entry.icon_class),
|
|
visible: entry.visible,
|
|
enabled: !entry.disabled
|
|
});
|
|
} else if (entry.type == contextmenu.MenuEntryType.SUB_MENU) {
|
|
const sub_menu = new Menu();
|
|
for(const e of entry.sub_menu) {
|
|
const build = this.build_menu(e);
|
|
if(!build)
|
|
continue;
|
|
sub_menu.append(build);
|
|
}
|
|
return new MenuItem({
|
|
id: _id,
|
|
label: (typeof entry.name === "function" ? (entry.name as (() => string))() : entry.name) as string,
|
|
type: "submenu",
|
|
submenu: sub_menu,
|
|
click: click_callback,
|
|
icon: class_to_image(entry.icon_class),
|
|
visible: entry.visible,
|
|
enabled: !entry.disabled
|
|
});
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
spawn_context_menu(x: number, y: number, ...entries: contextmenu.MenuEntry[]) {
|
|
this.despawn_context_menu();
|
|
|
|
this._current_menu = new Menu();
|
|
for(const entry of entries) {
|
|
const build = this.build_menu(entry);
|
|
if(!build)
|
|
continue;
|
|
this._current_menu.append(build);
|
|
}
|
|
|
|
this._current_menu.popup({
|
|
window: remote.getCurrentWindow(),
|
|
x: x,
|
|
y: y,
|
|
callback: () => this.despawn_context_menu()
|
|
});
|
|
}
|
|
|
|
html_format_enabled() { return false; }
|
|
}
|
|
|
|
contextmenu.set_provider(new ElectronContextMenu()); |