diff --git a/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h b/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h index 6d4a59fb3..03d686260 100644 --- a/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h +++ b/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h @@ -20,5 +20,7 @@ class DLL_EXPORT QMenuWrap : public Napi::ObjectWrap { static Napi::FunctionReference constructor; // wrapped methods Napi::Value setTitle(const Napi::CallbackInfo& info); - Napi::Value addAction(const Napi::CallbackInfo& info); + Napi::Value addSeparator(const Napi::CallbackInfo& info); + Napi::Value exec(const Napi::CallbackInfo& info); + Napi::Value popup(const Napi::CallbackInfo& info); }; diff --git a/src/cpp/include/nodegui/QtWidgets/QMenuBar/qmenubar_wrap.h b/src/cpp/include/nodegui/QtWidgets/QMenuBar/qmenubar_wrap.h index d175868f4..a980d8a08 100644 --- a/src/cpp/include/nodegui/QtWidgets/QMenuBar/qmenubar_wrap.h +++ b/src/cpp/include/nodegui/QtWidgets/QMenuBar/qmenubar_wrap.h @@ -20,5 +20,6 @@ class DLL_EXPORT QMenuBarWrap : public Napi::ObjectWrap { static Napi::FunctionReference constructor; // wrapped methods Napi::Value addMenu(const Napi::CallbackInfo& info); + Napi::Value addSeparator(const Napi::CallbackInfo& info); Napi::Value setNativeMenuBar(const Napi::CallbackInfo& info); }; diff --git a/src/cpp/include/nodegui/QtWidgets/QWidget/qwidget_macro.h b/src/cpp/include/nodegui/QtWidgets/QWidget/qwidget_macro.h index a4c16097b..abcc6c2df 100644 --- a/src/cpp/include/nodegui/QtWidgets/QWidget/qwidget_macro.h +++ b/src/cpp/include/nodegui/QtWidgets/QWidget/qwidget_macro.h @@ -5,6 +5,7 @@ #include "QtCore/QObject/qobject_macro.h" #include "QtCore/QSize/qsize_wrap.h" #include "QtGui/QIcon/qicon_wrap.h" +#include "QtWidgets/QAction/qaction_wrap.h" #include "QtWidgets/QLayout/qlayout_wrap.h" #include "core/YogaWidget/yogawidget_macro.h" /* @@ -311,6 +312,15 @@ Napi::HandleScope scope(env); \ this->instance->showNormal(); \ return env.Null(); \ + } \ + Napi::Value addAction(const Napi::CallbackInfo& info) { \ + Napi::Env env = info.Env(); \ + Napi::HandleScope scope(env); \ + Napi::Object actionObject = info[0].As(); \ + QActionWrap* actionWrap = \ + Napi::ObjectWrap::Unwrap(actionObject); \ + this->instance->addAction(actionWrap->getInternalInstance()); \ + return env.Null(); \ } #endif // QWIDGET_WRAPPED_METHODS_DECLARATION @@ -360,7 +370,8 @@ InstanceMethod("showFullScreen", &WidgetWrapName::showFullScreen), \ InstanceMethod("showMaximized", &WidgetWrapName::showMaximized), \ InstanceMethod("showMinimized", &WidgetWrapName::showMinimized), \ - InstanceMethod("showNormal", &WidgetWrapName::showNormal), + InstanceMethod("showNormal", &WidgetWrapName::showNormal), \ + InstanceMethod("addAction", &WidgetWrapName::addAction), #endif // QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE diff --git a/src/cpp/lib/QtWidgets/QMenu/qmenu_wrap.cpp b/src/cpp/lib/QtWidgets/QMenu/qmenu_wrap.cpp index b3391c3bb..ecdf9fc5c 100644 --- a/src/cpp/lib/QtWidgets/QMenu/qmenu_wrap.cpp +++ b/src/cpp/lib/QtWidgets/QMenu/qmenu_wrap.cpp @@ -5,6 +5,7 @@ #include +#include "QtCore/QPoint/qpoint_wrap.h" #include "QtWidgets/QAction/qaction_wrap.h" Napi::FunctionReference QMenuWrap::constructor; @@ -15,7 +16,9 @@ Napi::Object QMenuWrap::init(Napi::Env env, Napi::Object exports) { Napi::Function func = DefineClass(env, CLASSNAME, {InstanceMethod("setTitle", &QMenuWrap::setTitle), - InstanceMethod("addAction", &QMenuWrap::addAction), + InstanceMethod("addSeparator", &QMenuWrap::addSeparator), + InstanceMethod("exec", &QMenuWrap::exec), + InstanceMethod("popup", &QMenuWrap::popup), QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QMenuWrap)}); constructor = Napi::Persistent(func); exports.Set(CLASSNAME, func); @@ -57,13 +60,55 @@ Napi::Value QMenuWrap::setTitle(const Napi::CallbackInfo& info) { return env.Null(); } -Napi::Value QMenuWrap::addAction(const Napi::CallbackInfo& info) { +Napi::Value QMenuWrap::addSeparator(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - Napi::Object actionObject = info[0].As(); - QActionWrap* actionWrap = Napi::ObjectWrap::Unwrap(actionObject); - this->instance->addAction(actionWrap->getInternalInstance()); - // TODO: see if we need to return from here an pointer to qaction or not. + auto value = + Napi::External::New(env, this->instance->addSeparator()); + return Napi::Value::From(env, value); +} + +Napi::Value QMenuWrap::exec(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if (info.Length() == 2) { + Napi::Object pointObject = info[0].As(); + QPointWrap* pointWrap = Napi::ObjectWrap::Unwrap(pointObject); + QPoint* qpoint = pointWrap->getInternalInstance(); + + Napi::Object actionObject = info[1].As(); + QActionWrap* actionWrap = + Napi::ObjectWrap::Unwrap(actionObject); + this->instance->exec(*qpoint, actionWrap->getInternalInstance()); + } else if (info.Length() == 0) { + this->instance->exec(); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + + return env.Null(); +} + +Napi::Value QMenuWrap::popup(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object pointObject = info[0].As(); + QPointWrap* pointWrap = Napi::ObjectWrap::Unwrap(pointObject); + QPoint* qpoint = pointWrap->getInternalInstance(); + + Napi::Object actionObject = info[1].As(); + QAction* action = nullptr; + if (!actionObject.IsUndefined() && !actionObject.IsNull()) { + QActionWrap* actionWrap = + Napi::ObjectWrap::Unwrap(actionObject); + action = actionWrap->getInternalInstance(); + } + + this->instance->popup(*qpoint, action); + return env.Null(); } diff --git a/src/cpp/lib/QtWidgets/QMenuBar/qmenubar_wrap.cpp b/src/cpp/lib/QtWidgets/QMenuBar/qmenubar_wrap.cpp index 534deea1e..e2e5f899e 100644 --- a/src/cpp/lib/QtWidgets/QMenuBar/qmenubar_wrap.cpp +++ b/src/cpp/lib/QtWidgets/QMenuBar/qmenubar_wrap.cpp @@ -5,6 +5,7 @@ #include +#include "QtWidgets/QAction/qaction_wrap.h" #include "QtWidgets/QMenu/qmenu_wrap.h" Napi::FunctionReference QMenuBarWrap::constructor; @@ -15,6 +16,7 @@ Napi::Object QMenuBarWrap::init(Napi::Env env, Napi::Object exports) { Napi::Function func = DefineClass( env, CLASSNAME, {InstanceMethod("addMenu", &QMenuBarWrap::addMenu), + InstanceMethod("addSeparator", &QMenuBarWrap::addSeparator), InstanceMethod("setNativeMenuBar", &QMenuBarWrap::setNativeMenuBar), QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QMenuBarWrap)}); constructor = Napi::Persistent(func); @@ -57,11 +59,21 @@ Napi::Value QMenuBarWrap::addMenu(const Napi::CallbackInfo& info) { Napi::Object menuObject = info[0].As(); QMenuWrap* menuWrap = Napi::ObjectWrap::Unwrap(menuObject); + this->instance->addMenu(menuWrap->getInternalInstance()); return env.Null(); } +Napi::Value QMenuBarWrap::addSeparator(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + auto value = + Napi::External::New(env, this->instance->addSeparator()); + return Napi::Value::From(env, value); +} + Napi::Value QMenuBarWrap::setNativeMenuBar(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); diff --git a/src/demo.ts b/src/demo.ts index 07b687d25..6155ea4b5 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -1,8 +1,16 @@ -import { QWidget, QMainWindow, FlexLayout, QTreeWidget, QTreeWidgetItem } from './index'; -import { ItemFlag, CheckState } from './lib/QtEnums'; -import { QSpinBox } from './lib/QtWidgets/QSpinBox'; -import { QLineEdit } from './lib/QtWidgets/QLineEdit'; -import { QStatusBar } from './lib/QtWidgets/QStatusBar'; +import { + QWidget, + QMainWindow, + FlexLayout, + QTreeWidget, + QMenuBar, + QApplication, + QMenu, + QCursor, + QPushButton, +} from './index'; +import { QPoint } from './lib/QtCore/QPoint'; +import { QAction } from './lib/QtWidgets/QAction'; const win = new QMainWindow(); const center = new QWidget(); @@ -10,21 +18,64 @@ const layout = new FlexLayout(); center.setLayout(layout); win.setCentralWidget(center); -const statusBar = new QStatusBar(); -const spinBox = new QSpinBox(); -statusBar.addPermanentWidget(spinBox); -statusBar.addEventListener('messageChanged', message => console.log(`Status bar message changed to: ${message}`)); +const tree = new QTreeWidget(); +tree.hide(); +tree.setColumnCount(2); +tree.setHeaderLabels(['Properties', 'Value']); +center.layout?.addWidget(tree); + +const menubar = new QMenuBar(); +win.setMenuBar(menubar); + +const fm = menubar.addMenu('&File'); +const qaction = fm.addAction('&Quit'); +fm.addSeparator(); +const showTree = fm.addAction('&ShowTree'); +const hideTree = fm.addAction('&HideTree'); + +const menu = new QMenu(); +const sh = menu.addAction('SayHello'); + +// Button row +const buttonRow = new QWidget(); +const buttonRowLayout = new FlexLayout(); +buttonRow.setLayout(buttonRowLayout); +buttonRow.setObjectName('buttonRow'); + +// Buttons +const button = new QPushButton(); +button.setText('click me'); +button.setObjectName('clickme'); +buttonRowLayout.addWidget(button); +layout.addWidget(buttonRow); + +qaction.addEventListener('triggered', () => { + const app = QApplication.instance(); + app.exit(0); +}); + +showTree.addEventListener('triggered', () => { + tree.show(); +}); + +hideTree.addEventListener('triggered', () => { + tree.hide(); +}); + +button.addEventListener('clicked', () => { + const { x, y } = new QCursor().pos(); + menu.exec(new QPoint(x, y), new QAction()); +}); + +sh.addEventListener('triggered', () => { + console.log('Hello!'); +}); + +menubar.addSeparator(); +menubar.addMenu('Hello'); -win.setStatusBar(statusBar); win.show(); -statusBar.showMessage('Hello World', 3000); - -setTimeout(_ => { - statusBar.removeWidget(spinBox); - statusBar.showMessage('Removed spinBox'); -}, 3000); - (global as any).win = win; setInterval(() => null, 1000); diff --git a/src/lib/QtWidgets/QMenu.ts b/src/lib/QtWidgets/QMenu.ts index 6c3ad1f4c..598ba26b8 100644 --- a/src/lib/QtWidgets/QMenu.ts +++ b/src/lib/QtWidgets/QMenu.ts @@ -2,6 +2,7 @@ import { NativeElement } from '../core/Component'; import { NodeWidget, QWidgetSignals } from './QWidget'; import addon from '../utils/addon'; import { QAction } from './QAction'; +import { QPoint } from '../QtCore/QPoint'; /** @@ -19,7 +20,6 @@ const menu = new QMenu(); */ export class QMenu extends NodeWidget { native: NativeElement; - actions: Set; constructor(); constructor(parent: NodeWidget); constructor(parent?: NodeWidget) { @@ -32,15 +32,23 @@ export class QMenu extends NodeWidget { super(native); this.native = native; this.setNodeParent(parent); - this.actions = new Set(); } setTitle(title: string): void { this.native.setTitle(title); } - addAction(action: QAction): QAction { - this.native.addAction(action.native); - this.actions.add(action); - return action; + + addSeparator(): QAction { + return this.native.addSeparator(); + } + exec(point?: QPoint, action?: QAction): void { + if (point && action) { + this.native.exec(point.native, action.native); + return; + } + this.native.exec(); + } + popup(point: QPoint, action?: QAction): void { + this.native.popup(point.native, action?.native); } } diff --git a/src/lib/QtWidgets/QMenuBar.ts b/src/lib/QtWidgets/QMenuBar.ts index 8a5b620de..15f065865 100644 --- a/src/lib/QtWidgets/QMenuBar.ts +++ b/src/lib/QtWidgets/QMenuBar.ts @@ -3,6 +3,7 @@ import { NativeElement } from '../core/Component'; import { NodeWidget, QWidgetSignals } from './QWidget'; import addon from '../utils/addon'; import { checkIfNativeElement } from '../utils/helpers'; +import { QAction } from './QAction'; /** @@ -24,6 +25,7 @@ global.win = win; */ export class QMenuBar extends NodeWidget { native: NativeElement; + _menus: Set; constructor(); constructor(parent: NodeWidget); constructor(native: NativeElement); @@ -40,11 +42,23 @@ export class QMenuBar extends NodeWidget { } super(native); this.native = native; + this._menus = new Set(); this.setNodeParent(parent); } - - addMenu(menu: QMenu): void { + addMenu(menu: QMenu | string): QMenu { + if (typeof menu === 'string') { + const qmenu = new QMenu(); + qmenu.setTitle(menu); + this.native.addMenu(qmenu.native); + this._menus.add(qmenu); + return qmenu; + } this.native.addMenu(menu.native); + this._menus.add(menu); + return menu; + } + addSeparator(): QAction { + return this.native.addSeparator(); } setNativeMenuBar(nativeMenuBar: boolean): void { this.native.setNativeMenuBar(nativeMenuBar); diff --git a/src/lib/QtWidgets/QWidget.ts b/src/lib/QtWidgets/QWidget.ts index def6de667..49a355f43 100644 --- a/src/lib/QtWidgets/QWidget.ts +++ b/src/lib/QtWidgets/QWidget.ts @@ -13,6 +13,7 @@ import { QSize } from '../QtCore/QSize'; import { QRect } from '../QtCore/QRect'; import { QObjectSignals } from '../QtCore/QObject'; import { QFont } from '../QtGui/QFont'; +import { QAction } from './QAction'; /** @@ -49,6 +50,7 @@ Implement all native QWidget methods here so that all widgets get access to thos */ export abstract class NodeWidget extends YogaWidget { layout?: NodeLayout; + actions = new Set(); _rawInlineStyle = ''; type = 'widget'; show(): void { @@ -212,6 +214,18 @@ export abstract class NodeWidget extends YogaWid font(): QFont { return QFont.fromQVariant(this.property('font')); } + addAction(action: QAction | string): QAction { + if (typeof action === 'string') { + const qaction = new QAction(); + qaction.setText(action); + this.native.addAction(qaction.native); + this.actions.add(qaction); + return qaction; + } + this.native.addAction(action.native); + this.actions.add(action); + return action; + } } export interface QWidgetSignals extends QObjectSignals {