diff --git a/CMakeLists.txt b/CMakeLists.txt index 05f815ad6..fe20d42f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QStandardItem/qstandarditem_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QSvgWidget/qsvgwidget_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" @@ -220,6 +221,8 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QTextEdit/ntextedit.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QSvgWidget/nsvgwidget.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QHeaderView/nheaderview.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QSplitter/nsplitter.hpp" + # Test "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/test/CacheTestQObject.h" "${PROJECT_SOURCE_DIR}/src/cpp/lib/test/CacheTestQObject.cpp" diff --git a/package.json b/package.json index 1d7410419..3466bc782 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nodegui/nodegui", - "version": "0.40.1", + "version": "0.41.0", "description": "A cross-platform library to build native desktop apps.", "main": "dist/index.js", "typings": "dist/index.d.ts", 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/QPainter/qpainter_wrap.cpp b/src/cpp/lib/QtWidgets/QPainter/qpainter_wrap.cpp index bad6e2cff..fe06a4d88 100644 --- a/src/cpp/lib/QtWidgets/QPainter/qpainter_wrap.cpp +++ b/src/cpp/lib/QtWidgets/QPainter/qpainter_wrap.cpp @@ -159,7 +159,7 @@ Napi::Value QPainterWrap::end(const Napi::CallbackInfo& info) { Napi::Value QPainterWrap::rotate(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - int angle = info[0].As().Int32Value(); + qreal angle = info[0].As().DoubleValue(); this->instance->rotate(angle); return env.Null(); } @@ -262,16 +262,16 @@ Napi::Value QPainterWrap::drawLine(const Napi::CallbackInfo& info) { Napi::Value QPainterWrap::scale(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - int sx = info[0].As().Int32Value(); - int sy = info[1].As().Int32Value(); + qreal sx = info[0].As().DoubleValue(); + qreal sy = info[1].As().DoubleValue(); this->instance->scale(sx, sy); return env.Null(); } Napi::Value QPainterWrap::translate(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); - int dx = info[0].As().Int32Value(); - int dy = info[1].As().Int32Value(); + qreal dx = info[0].As().DoubleValue(); + qreal dy = info[1].As().DoubleValue(); this->instance->translate(dx, dy); return env.Null(); } 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..6bdcf1ffd --- /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 e56134500..4fedbcdcd 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -93,6 +93,7 @@ #include "QtWidgets/QShortcut/qshortcut_wrap.h" #include "QtWidgets/QSlider/qslider_wrap.h" #include "QtWidgets/QSpinBox/qspinbox_wrap.h" +#include "QtWidgets/QSplitter/qsplitter_wrap.h" #include "QtWidgets/QStackedWidget/qstackedwidget_wrap.h" #include "QtWidgets/QStandardItem/qstandarditem_wrap.h" #include "QtWidgets/QStandardItemModel/qstandarditemmodel_wrap.h" @@ -230,6 +231,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); QPaintEventWrap::init(env, exports); QPaletteWrap::init(env, exports); QAbstractItemModelWrap::init(env, exports); diff --git a/src/index.ts b/src/index.ts index 2d32e0708..0325ad449 100644 --- a/src/index.ts +++ b/src/index.ts @@ -116,6 +116,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..177706c6a --- /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): void { + 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): void { + 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): void { + this.native.setCollapsible(index, collapse); + } + setOrientation(orientation: Orientation): void { + this.native.setOrientation(orientation); + } +} + +export interface QSplitterSignals extends QFrameSignals { + splitterMoved: (pos: number, index: number) => void; +} diff --git a/website/docs/guides/packaging.md b/website/docs/guides/packaging.md index 795a110b6..62cd4be74 100644 --- a/website/docs/guides/packaging.md +++ b/website/docs/guides/packaging.md @@ -11,7 +11,7 @@ In order to distribute your finished app, you can use [@nodegui/packer](https:// npx nodegui-packer --init MyAppName ``` - This will produce the deploy directory containing the template. You can modify this to suite your needs. Like add icons, change the name, description and add other native features or dependencies. Make sure you commit this directory. + This will produce the deploy directory containing the template. You can modify this to suit your needs. Like add icons, change the name, description and add other native features or dependencies. Make sure you commit this directory. - **Step 2: (Run this command every time you want to build a new distributable)**