diff --git a/CMakeLists.txt b/CMakeLists.txt index 752fde426..b37aefe99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,6 +149,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QSvgWidget/qsvgwidget_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QDesktopWidget/qdesktopwidget_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QStyleFactory/qstylefactory_wrap.cpp" + "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QSplitter/qsplitter_wrap.cpp" # Custom widgets (include them for automoc since they contain Q_OBJECT) "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtCore/QAbstractItemModel/nabstractitemmodel.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtCore/QItemSelectionModel/nitemselectionmodel.hpp" @@ -215,6 +216,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QSvgWidget/nsvgwidget.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QDesktopWidget/nqdesktopwidget.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QHeaderView/nheaderview.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QSplitter/nsplitter.hpp" ) AddCommonConfig(${CORE_WIDGETS_ADDON}) diff --git a/src/cpp/include/nodegui/QtWidgets/QSplitter/nsplitter.hpp b/src/cpp/include/nodegui/QtWidgets/QSplitter/nsplitter.hpp new file mode 100644 index 000000000..6f2b7de0e --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QSplitter/nsplitter.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include "Extras/Export/export.h" +#include "QtWidgets/QFrame/qframe_macro.h" +#include "core/NodeWidget/nodewidget.h" + +class DLL_EXPORT NSplitter : public QSplitter, public NodeWidget { + Q_OBJECT + NODEWIDGET_IMPLEMENTATIONS(QSplitter) + public: + using QSplitter::QSplitter; + + virtual void connectSignalsToEventEmitter() { + QFRAME_SIGNALS + QObject::connect(this, &QSplitter::splitterMoved, [=](int pos, int index) { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({Napi::String::New(env, "splitterMoved"), + Napi::Number::New(env, pos), + Napi::Number::New(env, index)}); + }); + } +}; diff --git a/src/cpp/include/nodegui/QtWidgets/QSplitter/qsplitter_wrap.h b/src/cpp/include/nodegui/QtWidgets/QSplitter/qsplitter_wrap.h new file mode 100644 index 000000000..bae681e0a --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QSplitter/qsplitter_wrap.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include + +#include "Extras/Export/export.h" +#include "QtWidgets/QFrame/qframe_macro.h" +#include "QtWidgets/QSplitter/nsplitter.hpp" + +class DLL_EXPORT QSplitterWrap : public Napi::ObjectWrap { + QFRAME_WRAPPED_METHODS_DECLARATION + private: + QPointer instance; + + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + QSplitterWrap(const Napi::CallbackInfo& info); + ~QSplitterWrap(); + NSplitter* getInternalInstance(); + // class constructor + static Napi::FunctionReference constructor; + // wrapped methods + Napi::Value addWidget(const Napi::CallbackInfo& info); + Napi::Value childrenCollapsible(const Napi::CallbackInfo& info); + Napi::Value count(const Napi::CallbackInfo& info); + Napi::Value indexOf(const Napi::CallbackInfo& info); + Napi::Value insertWidget(const Napi::CallbackInfo& info); + Napi::Value isCollapsible(const Napi::CallbackInfo& info); + Napi::Value orientation(const Napi::CallbackInfo& info); + Napi::Value setCollapsible(const Napi::CallbackInfo& info); + Napi::Value setOrientation(const Napi::CallbackInfo& info); +}; diff --git a/src/cpp/lib/QtWidgets/QSplitter/qsplitter_wrap.cpp b/src/cpp/lib/QtWidgets/QSplitter/qsplitter_wrap.cpp new file mode 100644 index 000000000..e9e6d5002 --- /dev/null +++ b/src/cpp/lib/QtWidgets/QSplitter/qsplitter_wrap.cpp @@ -0,0 +1,136 @@ +#include "QtWidgets/QSplitter/qsplitter_wrap.h" + +#include "Extras/Utils/nutils.h" + +Napi::FunctionReference QSplitterWrap::constructor; + +Napi::Object QSplitterWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QSplitter"; + Napi::Function func = DefineClass( + env, CLASSNAME, + {InstanceMethod("addWidget", &QSplitterWrap::addWidget), + InstanceMethod("childrenCollapsible", &QSplitterWrap::childrenCollapsible), + InstanceMethod("count", &QSplitterWrap::count), + InstanceMethod("indexOf", &QSplitterWrap::indexOf), + InstanceMethod("insertWidget", &QSplitterWrap::insertWidget), + InstanceMethod("isCollapsible", &QSplitterWrap::isCollapsible), + InstanceMethod("orientation", &QSplitterWrap::orientation), + InstanceMethod("setCollapsible", &QSplitterWrap::setCollapsible), + InstanceMethod("setOrientation", &QSplitterWrap::setOrientation), + QFRAME_WRAPPED_METHODS_EXPORT_DEFINE(QSplitterWrap)}); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NSplitter* QSplitterWrap::getInternalInstance() { return this->instance; } + +QSplitterWrap::~QSplitterWrap() { + extrautils::safeDelete(this->instance); +} + +QSplitterWrap::QSplitterWrap(const Napi::CallbackInfo& info) + : Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if (info.Length() == 1) { + Napi::Object parentObject = info[0].As(); + NodeWidgetWrap* parentWidgetWrap = + Napi::ObjectWrap::Unwrap(parentObject); + this->instance = new NSplitter(parentWidgetWrap->getInternalInstance()); + } else if (info.Length() == 0) { + this->instance = new NSplitter(); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + this->rawData = extrautils::configureQWidget( + this->getInternalInstance(), this->getInternalInstance()->getFlexNode(), + false); +} + +Napi::Value QSplitterWrap::addWidget(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object widgetObject = info[0].As(); + NodeWidgetWrap* widgetWrap = + Napi::ObjectWrap::Unwrap(widgetObject); + + this->instance->addWidget(widgetWrap->getInternalInstance()); + return env.Null(); +} + +Napi::Value QSplitterWrap::childrenCollapsible(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + return Napi::Boolean::New(env, this->instance->childrenCollapsible()); +} + +Napi::Value QSplitterWrap::count(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + return Napi::Number::New(env, this->instance->count()); +} + +Napi::Value QSplitterWrap::indexOf(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object widgetObject = info[0].As(); + NodeWidgetWrap* widgetWrap = + Napi::ObjectWrap::Unwrap(widgetObject); + + return Napi::Number::New( + env, this->instance->indexOf(widgetWrap->getInternalInstance())); +} + +Napi::Value QSplitterWrap::insertWidget(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int index = info[0].As().Int32Value(); + Napi::Object widgetObject = info[1].As(); + NodeWidgetWrap* widgetWrap = + Napi::ObjectWrap::Unwrap(widgetObject); + + this->instance->insertWidget(index, widgetWrap->getInternalInstance()); + return env.Null(); +} + +Napi::Value QSplitterWrap::isCollapsible(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int index = info[0].As().Int32Value(); + return Napi::Boolean::New(env, this->instance->isCollapsible(index)); +} + +Napi::Value QSplitterWrap::orientation(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + return Napi::Number::New(env, static_cast(this->instance->orientation())); +} + +Napi::Value QSplitterWrap::setCollapsible(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int index = info[0].As().Int32Value(); + bool collapse = info[1].As().Value(); + this->instance->setCollapsible(index, collapse); + return env.Null(); +} + +Napi::Value QSplitterWrap::setOrientation(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int orientation = info[0].As().Int32Value(); + this->instance->setOrientation(static_cast(orientation)); + + return env.Null(); +} \ No newline at end of file diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 14963003c..bfb748bdb 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -98,6 +98,7 @@ #include "QtWidgets/QStatusBar/qstatusbar_wrap.h" #include "QtWidgets/QStyleFactory/qstylefactory_wrap.h" #include "QtWidgets/QSvgWidget/qsvgwidget_wrap.h" +#include "QtWidgets/QSplitter/qsplitter_wrap.h" #include "QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h" #include "QtWidgets/QTabBar/qtabbar_wrap.h" #include "QtWidgets/QTabWidget/qtabwidget_wrap.h" @@ -225,6 +226,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QStandardItemModelWrap::init(env, exports); QStandardItemWrap::init(env, exports); QSvgWidgetWrap::init(env, exports); + QSplitterWrap::init(env, exports); QDesktopWidgetWrap::init(env, exports); QPaintEventWrap::init(env, exports); QPaletteWrap::init(env, exports); diff --git a/src/index.ts b/src/index.ts index a63d50611..c73d4fd75 100644 --- a/src/index.ts +++ b/src/index.ts @@ -115,6 +115,7 @@ export { QDialog, QDialogSignals } from './lib/QtWidgets/QDialog'; export { QMessageBox, QMessageBoxSignals, QMessageBoxIcon, ButtonRole } from './lib/QtWidgets/QMessageBox'; export { QInputDialog, QInputDialogSignals, InputDialogOptions, InputMode } from './lib/QtWidgets/QInputDialog'; export { QSvgWidget } from './lib/QtWidgets/QSvgWidget'; +export { QSplitter, QSplitterSignals } from './lib/QtWidgets/QSplitter'; export { QButtonGroup, QButtonGroupSignals } from './lib/QtWidgets/QButtonGroup'; diff --git a/src/lib/QtWidgets/QSplitter.ts b/src/lib/QtWidgets/QSplitter.ts new file mode 100644 index 000000000..370c8ce10 --- /dev/null +++ b/src/lib/QtWidgets/QSplitter.ts @@ -0,0 +1,83 @@ +import addon from '../utils/addon'; +import { NodeWidget } from './QWidget'; +import { NodeFrame, QFrameSignals } from './QFrame'; +import { NativeElement } from '../core/Component'; +import { Orientation } from '../QtEnums'; + +/** + +> A QSplitter provides ability to let the user control the size between child widgets + +* **This class is a JS wrapper around Qt's [QSplitter class](https://doc.qt.io/qt-5/qsplitter.html)** + +### Example + +```javascript +const { QSplitter, QWidget, QBoxLayout, Direction, Orientation } = require("@nodegui/nodegui"); + +const rootView = new QWidget(); +const rootLayout = new QBoxLayout(Direction.LeftToRight); +rootLayout.setSpacing(0); +rootView.setLayout(rootLayout); +rootView.setObjectName('myroot'); + +const splitterHorizontal = new QSplitter(); +splitterHorizontal.setObjectName("splitterleft"); +splitterHorizontal.setOrientation(Orientation.Horizontal); +const left = new QWidget(); +left.setInlineStyle('background-color: red;'); +const right = new QWidget(); +right.setInlineStyle('background-color: yellow;'); +rootView.layout!.addWidget(splitterHorizontal); +splitterHorizontal.addWidget(left); +splitterHorizontal.addWidget(right); +``` + + */ +export class QSplitter extends NodeFrame { + native: NativeElement; + constructor(); + constructor(parent: NodeWidget); + constructor(parent?: NodeWidget) { + let native; + if (parent) { + native = new addon.QSplitter(parent.native); + } else { + native = new addon.QSplitter(); + } + super(native); + this.native = native; + this.setNodeParent(parent); + } + addWidget(widget: NodeWidget) { + this.native.addWidget(widget.native); + } + childrenCollapsible(): boolean { + return this.native.childrenCollapsible(); + } + count(): number { + return this.native.count(); + } + indexOf(widget: NodeWidget): number { + return this.native.indexOf(widget.native); + } + insertWidget(index: number, widget: NodeWidget) { + this.native.insertWidget(index, widget.native); + } + isCollapsible(index: number): boolean { + return this.native.isCollapsible(index); + } + orientation(): Orientation { + return this.native.orientation(); + } + setCollapsible(index: number, collapse: boolean) { + this.native.setCollapsible(index, collapse); + } + setOrientation(orientation: Orientation) { + this.native.setOrientation(orientation); + } +} + +export interface QSplitterSignals extends QFrameSignals { + splitterMoved: (pos: number, index: number) => void; +}