|
| 1 | +import { WidgetEventListeners } from "../View/RNView"; |
| 2 | +import { |
| 3 | + QSystemTrayIconSignals, |
| 4 | + QSystemTrayIcon, |
| 5 | + NodeWidget, |
| 6 | + QIcon, |
| 7 | + QMenu, |
| 8 | +} from "@nodegui/nodegui"; |
| 9 | +import { RNComponent, RNProps } from "../config"; |
| 10 | +import { throwUnsupported } from "../../utils/helpers"; |
| 11 | + |
| 12 | +/** |
| 13 | + * The SystemTrayIcon component provides the ability to add and manipulate a native system tray icon. |
| 14 | + * [NodeGui's QSystemTrayIcon](https://docs.nodegui.org/docs/api/generated/classes/qsystemtrayicon). |
| 15 | + * ## Example |
| 16 | + * ```javascript |
| 17 | + * import React from "react"; |
| 18 | + * import { QIcon, QAction } from "@nodegui/nodegui"; |
| 19 | + * import { Menu, Renderer, SystemTrayIcon, Window } from "@nodegui/react-nodegui"; |
| 20 | + * import path from "path"; |
| 21 | + * |
| 22 | + * const icon = new QIcon(path.join(__dirname, "../extras/assets/nodegui.png")); |
| 23 | + * const action = new QAction(); |
| 24 | + * action.setText("Hello"); |
| 25 | + * action.addEventListener("triggered", () => { |
| 26 | + * console.log("hello"); |
| 27 | + * }); |
| 28 | + * |
| 29 | + * const App = () => { |
| 30 | + * return ( |
| 31 | + * <Window> |
| 32 | + * <SystemTrayIcon icon={icon} tooltip="Hello World" visible> |
| 33 | + * <Menu actions={[action]} /> |
| 34 | + * </SystemTrayIcon> |
| 35 | + * </Window> |
| 36 | + * ); |
| 37 | + * }; |
| 38 | + * |
| 39 | + * Renderer.render(<App />); |
| 40 | + * |
| 41 | + * ``` |
| 42 | + */ |
| 43 | +export interface SystemTrayIconProps extends RNProps { |
| 44 | + /** |
| 45 | + * Sets an icon for the system tray. [QSystemTrayIcon: setIcon](https://docs.nodegui.org/docs/api/generated/classes/qsystemtrayicon#seticon) |
| 46 | + */ |
| 47 | + icon?: QIcon; |
| 48 | + |
| 49 | + /** |
| 50 | + * Sets the object name (id) of the widget in Qt. Object name can be analogous to id of an element in the web world. Using the objectName of the widget one can reference it in the Qt's stylesheet much like what we do with id in the web world. [QWidget: setObjectName](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetobjectnameobjectname) |
| 51 | + */ |
| 52 | + id?: string; |
| 53 | + |
| 54 | + /** |
| 55 | + * Prop to set the event listener map. See [Handlong Events](/docs/guides/handle-events) |
| 56 | + */ |
| 57 | + on?: Partial<WidgetEventListeners | QSystemTrayIconSignals>; |
| 58 | + |
| 59 | + /** |
| 60 | + * Sets a tooltip for the system tray. [QSystemTrayIcon: setTooltip](https://docs.nodegui.org/docs/api/generated/classes/qsystemtrayicon#settooltip) |
| 61 | + */ |
| 62 | + tooltip?: string; |
| 63 | + |
| 64 | + /** |
| 65 | + * Shows or hides the widget and its children. [QWidget: show](https://docs.nodegui.org/docs/api/NodeWidget#widgetshow) |
| 66 | + */ |
| 67 | + visible?: boolean; |
| 68 | +} |
| 69 | + |
| 70 | +const setSystemTrayIconProps = ( |
| 71 | + widget: RNSystemTrayIcon, |
| 72 | + newProps: SystemTrayIconProps, |
| 73 | + oldProps: SystemTrayIconProps |
| 74 | +) => { |
| 75 | + const setter: SystemTrayIconProps = { |
| 76 | + set icon(icon: QIcon) { |
| 77 | + widget.setIcon(icon); |
| 78 | + }, |
| 79 | + set id(id: string) { |
| 80 | + widget.setObjectName(id); |
| 81 | + }, |
| 82 | + set on( |
| 83 | + listenerMap: Partial<WidgetEventListeners | QSystemTrayIconSignals> |
| 84 | + ) { |
| 85 | + const listenerMapLatest: any = Object.assign({}, listenerMap); |
| 86 | + const oldListenerMap = Object.assign({}, oldProps.on); |
| 87 | + Object.entries(oldListenerMap).forEach(([eventType, oldEvtListener]) => { |
| 88 | + const newEvtListener = listenerMapLatest[eventType]; |
| 89 | + if (oldEvtListener !== newEvtListener) { |
| 90 | + widget.removeEventListener(eventType as any, oldEvtListener); |
| 91 | + } else { |
| 92 | + delete listenerMapLatest[eventType]; |
| 93 | + } |
| 94 | + }); |
| 95 | + |
| 96 | + Object.entries(listenerMapLatest).forEach( |
| 97 | + ([eventType, newEvtListener]) => { |
| 98 | + widget.addEventListener(eventType as any, newEvtListener); |
| 99 | + } |
| 100 | + ); |
| 101 | + }, |
| 102 | + set tooltip(tooltip: string) { |
| 103 | + widget.setToolTip(tooltip); |
| 104 | + }, |
| 105 | + set visible(shouldShow: boolean) { |
| 106 | + shouldShow ? widget.show() : widget.hide(); |
| 107 | + }, |
| 108 | + }; |
| 109 | + Object.assign(setter, newProps); |
| 110 | +}; |
| 111 | + |
| 112 | +/** |
| 113 | + * @ignore |
| 114 | + */ |
| 115 | +export class RNSystemTrayIcon extends QSystemTrayIcon implements RNComponent { |
| 116 | + static tagName = "systemtrayicon"; |
| 117 | + |
| 118 | + setProps(newProps: SystemTrayIconProps, oldProps: SystemTrayIconProps): void { |
| 119 | + setSystemTrayIconProps(this, newProps, oldProps); |
| 120 | + } |
| 121 | + appendInitialChild(child: NodeWidget<any>): void { |
| 122 | + if (child instanceof QMenu) { |
| 123 | + if (!this.contextMenu) { |
| 124 | + this.setContextMenu(child); |
| 125 | + } else { |
| 126 | + console.warn("SystemTrayIcon can't have more than one Menu."); |
| 127 | + } |
| 128 | + } else { |
| 129 | + console.warn("SystemTrayIcon only supports Menu as its children"); |
| 130 | + } |
| 131 | + } |
| 132 | + appendChild(child: NodeWidget<any>): void { |
| 133 | + this.appendInitialChild(child); |
| 134 | + } |
| 135 | + insertBefore(child: NodeWidget<any>, beforeChild: NodeWidget<any>): void { |
| 136 | + throwUnsupported(this); |
| 137 | + } |
| 138 | + removeChild(child: NodeWidget<any>): void { |
| 139 | + throwUnsupported(this); |
| 140 | + } |
| 141 | +} |
0 commit comments